Tue Aug 20 16:35:07 2013

Asterisk developer's documentation


pbx.c File Reference

Core PBX routines. More...

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

Go to the source code of this file.

Data Structures

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

Defines

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

Functions

void __ast_context_destroy (struct ast_context *list, struct ast_hashtab *contexttab, struct ast_context *con, const char *registrar)
int __ast_custom_function_register (struct ast_custom_function *acf, struct ast_module *mod)
 Register a custom function.
static int __ast_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority, int async)
static void __ast_internal_context_destroy (struct ast_context *con)
static enum ast_pbx_result __ast_pbx_run (struct ast_channel *c, struct ast_pbx_args *args)
static void __init_extensionstate_buf (void)
static void __init_switch_data (void)
static int _extension_match_core (const char *pattern, const char *data, enum ext_match_t mode)
static int acf_exception_read (struct ast_channel *chan, const char *name, char *data, char *buf, size_t buflen)
static int acf_retrieve_docs (struct ast_custom_function *acf)
static struct match_charadd_exten_to_pattern_tree (struct ast_context *con, struct ast_exten *e1, int findonly)
static struct match_charadd_pattern_node (struct ast_context *con, struct match_char *current, const struct pattern_node *pattern, int is_pattern, int already, struct match_char **nextcharptr)
static int add_priority (struct ast_context *con, struct ast_exten *tmp, struct ast_exten *el, struct ast_exten *e, int replace)
 add the extension in the priority chain.
static struct match_charalready_in_tree (struct match_char *current, char *pat, int is_pattern)
int ast_active_calls (void)
 Retrieve the number of active calls.
int ast_add_extension (const char *context, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar)
 Add and extension to an extension context.
int ast_add_extension2 (struct ast_context *con, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar)
 Main interface to add extensions to the list for out context.
static int ast_add_extension2_lockopt (struct ast_context *con, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar, int lock_context)
 Same as ast_add_extension2() but controls the context locking.
static int ast_add_extension_nolock (const char *context, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar)
static int ast_add_hint (struct ast_exten *e)
 Add hint to hint list, check initial extension state.
int ast_async_goto (struct ast_channel *chan, const char *context, const char *exten, int priority)
 Set the channel to next execute the specified dialplan location.
int ast_async_goto_by_name (const char *channame, const char *context, const char *exten, int priority)
 Set the channel to next execute the specified dialplan location.
int ast_async_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority)
int ast_async_parseable_goto (struct ast_channel *chan, const char *goto_string)
int ast_build_timing (struct ast_timing *i, const char *info_in)
 Construct a timing bitmap, for use in time-based conditionals.
int ast_canmatch_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
 Looks for a valid matching extension.
static int ast_change_hint (struct ast_exten *oe, struct ast_exten *ne)
 Change hint for an extension.
int ast_check_timing (const struct ast_timing *i)
 Evaluate a pre-constructed bitmap as to whether the current time falls within the range specified.
int ast_check_timing2 (const struct ast_timing *i, const struct timeval tv)
 Evaluate a pre-constructed bitmap as to whether a particular time falls within the range specified.
char * ast_complete_applications (const char *line, const char *word, int state)
 Command completion for the list of installed applications.
int ast_context_add_ignorepat (const char *context, const char *value, const char *registrar)
 Add an ignorepat.
int ast_context_add_ignorepat2 (struct ast_context *con, const char *value, const char *registrar)
int ast_context_add_include (const char *context, const char *include, const char *registrar)
 Add a context include.
int ast_context_add_include2 (struct ast_context *con, const char *value, const char *registrar)
 Add a context include.
int ast_context_add_switch (const char *context, const char *sw, const char *data, int eval, const char *registrar)
 Add a switch.
int ast_context_add_switch2 (struct ast_context *con, const char *value, const char *data, int eval, const char *registrar)
 Adds a switch (first param is a ast_context).
void ast_context_destroy (struct ast_context *con, const char *registrar)
 Destroy a context (matches the specified context (or ANY context if NULL).
struct ast_contextast_context_find (const char *name)
 Find a context.
struct ast_contextast_context_find_or_create (struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *name, const char *registrar)
 Register a new context or find an existing one.
int ast_context_lockmacro (const char *context)
 locks the macrolock in the given given context
int ast_context_remove_extension (const char *context, const char *extension, int priority, const char *registrar)
 Simply remove extension from context.
int ast_context_remove_extension2 (struct ast_context *con, const char *extension, int priority, const char *registrar, int already_locked)
 This functionc locks given context, search for the right extension and fires out all peer in this extensions with given priority. If priority is set to 0, all peers are removed. After that, unlock context and return.
int ast_context_remove_extension_callerid (const char *context, const char *extension, int priority, const char *callerid, int matchcallerid, const char *registrar)
int ast_context_remove_extension_callerid2 (struct ast_context *con, const char *extension, int priority, const char *callerid, int matchcallerid, const char *registrar, int already_locked)
int ast_context_remove_ignorepat (const char *context, const char *ignorepat, const char *registrar)
int ast_context_remove_ignorepat2 (struct ast_context *con, const char *ignorepat, const char *registrar)
int ast_context_remove_include (const char *context, const char *include, const char *registrar)
 Remove included contexts. This function locks contexts list by &conlist, search for the right context structure, leave context list locked and call ast_context_remove_include2 which removes include, unlock contexts list and return ...
int ast_context_remove_include2 (struct ast_context *con, const char *include, const char *registrar)
 Locks context, remove included contexts, unlocks context. When we call this function, &conlock lock must be locked, because when we giving *con argument, some process can remove/change this context and after that there can be segfault.
int ast_context_remove_switch (const char *context, const char *sw, const char *data, const char *registrar)
 Remove a switch.
int ast_context_remove_switch2 (struct ast_context *con, const char *sw, const char *data, const char *registrar)
 This function locks given context, removes switch, unlock context and return.
int ast_context_unlockmacro (const char *context)
 Unlocks the macrolock in the given context.
int ast_context_verify_includes (struct ast_context *con)
 Verifies includes in an ast_contect structure.
struct ast_custom_functionast_custom_function_find (const char *name)
int ast_custom_function_unregister (struct ast_custom_function *acf)
 Unregister a custom function.
int ast_destroy_timing (struct ast_timing *i)
 Deallocates memory structures associated with a timing bitmap.
enum ast_extension_states ast_devstate_to_extenstate (enum ast_device_state devstate)
 Map devstate to an extension state.
int ast_exists_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
 Determine whether an extension exists.
int ast_explicit_goto (struct ast_channel *chan, const char *context, const char *exten, int priority)
int ast_extension_close (const char *pattern, const char *data, int needmore)
int ast_extension_cmp (const char *a, const char *b)
 Determine if one extension should match before another.
int ast_extension_match (const char *pattern, const char *data)
 Determine if a given extension matches a given pattern (in NXX format).
int ast_extension_state (struct ast_channel *c, const char *context, const char *exten)
 Check extension state for an extension by using hint.
static int ast_extension_state2 (struct ast_exten *e)
 Check state of extension by using hints.
const char * ast_extension_state2str (int extension_state)
 Return extension_state as string.
static int ast_extension_state3 (struct ast_str *hint_app)
int ast_extension_state_add (const char *context, const char *exten, ast_state_cb_type change_cb, void *data)
 Add watcher for extension states.
int ast_extension_state_add_destroy (const char *context, const char *exten, ast_state_cb_type change_cb, ast_state_cb_destroy_type destroy_cb, void *data)
 Add watcher for extension states with destructor.
int ast_extension_state_del (int id, ast_state_cb_type change_cb)
 ast_extension_state_del: Remove a watcher from the callback list
int ast_findlabel_extension (struct ast_channel *c, const char *context, const char *exten, const char *label, const char *callerid)
 Find the priority of an extension that has the specified label.
int ast_findlabel_extension2 (struct ast_channel *c, struct ast_context *con, const char *exten, const char *label, const char *callerid)
 Find the priority of an extension that has the specified label.
int ast_func_read (struct ast_channel *chan, const char *function, char *workspace, size_t len)
 executes a read operation on a function
int ast_func_read2 (struct ast_channel *chan, const char *function, struct ast_str **str, ssize_t maxlen)
 executes a read operation on a function
int ast_func_write (struct ast_channel *chan, const char *function, const char *value)
 executes a write operation on a function
const char * ast_get_context_name (struct ast_context *con)
const char * ast_get_context_registrar (struct ast_context *c)
const char * ast_get_extension_app (struct ast_exten *e)
void * ast_get_extension_app_data (struct ast_exten *e)
const char * ast_get_extension_cidmatch (struct ast_exten *e)
struct ast_contextast_get_extension_context (struct ast_exten *exten)
const char * ast_get_extension_label (struct ast_exten *exten)
int ast_get_extension_matchcid (struct ast_exten *e)
const char * ast_get_extension_name (struct ast_exten *exten)
int ast_get_extension_priority (struct ast_exten *exten)
const char * ast_get_extension_registrar (struct ast_exten *e)
int ast_get_hint (char *hint, int hintsize, char *name, int namesize, struct ast_channel *c, const char *context, const char *exten)
 Get hint for channel.
const char * ast_get_ignorepat_name (struct ast_ignorepat *ip)
const char * ast_get_ignorepat_registrar (struct ast_ignorepat *ip)
const char * ast_get_include_name (struct ast_include *inc)
const char * ast_get_include_registrar (struct ast_include *i)
const char * ast_get_switch_data (struct ast_sw *sw)
int ast_get_switch_eval (struct ast_sw *sw)
const char * ast_get_switch_name (struct ast_sw *sw)
const char * ast_get_switch_registrar (struct ast_sw *sw)
int ast_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority)
int ast_hashtab_compare_contexts (const void *ah_a, const void *ah_b)
 hashtable functions for contexts
unsigned int ast_hashtab_hash_contexts (const void *obj)
static struct ast_extenast_hint_extension (struct ast_channel *c, const char *context, const char *exten)
static struct ast_extenast_hint_extension_nolock (struct ast_channel *c, const char *context, const char *exten)
 Find hint for given extension in context.
int ast_ignore_pattern (const char *context, const char *pattern)
 Checks to see if a number should be ignored.
int ast_matchmore_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
 Looks to see if adding anything to this extension might match something. (exists ^ canmatch).
void ast_merge_contexts_and_delete (struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *registrar)
 Merge the temporary contexts into a global contexts list and delete from the global list the ones that are being added.
int ast_parseable_goto (struct ast_channel *chan, const char *goto_string)
int ast_pbx_init (void)
int ast_pbx_outgoing_app (const char *type, format_t format, void *data, int timeout, const char *app, const char *appdata, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel)
static int ast_pbx_outgoing_cdr_failed (void)
 Function to post an empty cdr after a spool call fails.
int ast_pbx_outgoing_exten (const char *type, format_t format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **channel)
enum ast_pbx_result ast_pbx_run (struct ast_channel *c)
 Execute the PBX in the current thread.
static void * ast_pbx_run_app (void *data)
 run the application and free the descriptor once done
enum ast_pbx_result ast_pbx_run_args (struct ast_channel *c, struct ast_pbx_args *args)
 Execute the PBX in the current thread.
enum ast_pbx_result ast_pbx_start (struct ast_channel *c)
 Create a new thread and start the PBX.
int ast_processed_calls (void)
 Retrieve the total number of calls processed through the PBX since last restart.
int ast_rdlock_context (struct ast_context *con)
 Read locks a given context.
int ast_rdlock_contexts (void)
 Read locks the context list.
int ast_register_application2 (const char *app, int(*execute)(struct ast_channel *, const char *), const char *synopsis, const char *description, void *mod)
 Dynamically register a new dial plan application.
int ast_register_switch (struct ast_switch *sw)
 Register an alternative dialplan switch.
static int ast_remove_hint (struct ast_exten *e)
 Remove hint from extension.
int ast_spawn_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid, int *found, int combined_find_spawn)
 Launch a new extension (i.e. new stack).
int ast_str_get_hint (struct ast_str **hint, ssize_t hintsize, struct ast_str **name, ssize_t namesize, struct ast_channel *c, const char *context, const char *exten)
 Get hint for channel.
const char * ast_str_retrieve_variable (struct ast_str **str, ssize_t maxlen, struct ast_channel *c, struct varshead *headp, const char *var)
void ast_str_substitute_variables (struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, const char *templ)
void ast_str_substitute_variables_full (struct ast_str **buf, ssize_t maxlen, struct ast_channel *c, struct varshead *headp, const char *templ, size_t *used)
void ast_str_substitute_variables_varshead (struct ast_str **buf, ssize_t maxlen, struct varshead *headp, const char *templ)
static const char * ast_str_substring (struct ast_str *value, int offset, int length)
int ast_unlock_context (struct ast_context *con)
int ast_unlock_contexts (void)
 Unlocks contexts.
int ast_unregister_application (const char *app)
 Unregister an application.
void ast_unregister_switch (struct ast_switch *sw)
 Unregister an alternative switch.
struct ast_extenast_walk_context_extensions (struct ast_context *con, struct ast_exten *exten)
struct ast_ignorepatast_walk_context_ignorepats (struct ast_context *con, struct ast_ignorepat *ip)
struct ast_includeast_walk_context_includes (struct ast_context *con, struct ast_include *inc)
struct ast_swast_walk_context_switches (struct ast_context *con, struct ast_sw *sw)
struct ast_contextast_walk_contexts (struct ast_context *con)
struct ast_extenast_walk_extension_priorities (struct ast_exten *exten, struct ast_exten *priority)
int ast_wrlock_context (struct ast_context *con)
 Write locks a given context.
int ast_wrlock_contexts (void)
 Write locks the context list.
static void * async_wait (void *data)
static void cli_match_char_tree (struct match_char *node, char *prefix, int fd)
static int collect_digits (struct ast_channel *c, int waittime, char *buf, int buflen, int pos)
 collect digits from the channel into the buffer.
static int compare_char (const void *a, const void *b)
static char * complete_core_show_hint (const char *line, const char *word, int pos, int state)
 autocomplete for CLI command 'core show hint'
static char * complete_show_dialplan_context (const char *line, const char *word, int pos, int state)
static void context_merge (struct ast_context **extcontexts, struct ast_hashtab *exttable, struct ast_context *context, const char *registrar)
static void context_merge_incls_swits_igps_other_registrars (struct ast_context *new, struct ast_context *old, const char *registrar)
static void create_match_char_tree (struct ast_context *con)
static void decrease_call_count (void)
static void destroy_exten (struct ast_exten *e)
static void destroy_hint (void *obj)
static void destroy_pattern_tree (struct match_char *pattern_tree)
static void destroy_state_cb (void *doomed)
static void device_state_cb (const struct ast_event *event, void *unused)
static void exception_store_free (void *data)
static int ext_cmp (const char *left, const char *right)
static int ext_cmp_exten (const char *left, const char *right)
static int ext_cmp_exten_partial (const char *left, const char *right)
static int ext_cmp_exten_strlen (const char *str)
static int ext_cmp_pattern (const char *left, const char *right)
static int ext_cmp_pattern_pos (const char **p, unsigned char *bitwise)
 helper functions to sort extension patterns in the desired way, so that more specific patterns appear first.
static int ext_strncpy (char *dst, const char *src, int len)
 copy a string skipping whitespace
static int extension_match_core (const char *pattern, const char *data, enum ext_match_t mode)
static struct ast_contextfind_context (const char *context)
 lookup for a context with a given name,
static struct ast_contextfind_context_locked (const char *context)
 lookup for a context with a given name,
static int find_hint_by_cb_id (void *obj, void *arg, int flags)
 Remove a watcher from the callback list.
static char * func_args (char *function)
 return a pointer to the arguments of the function, and terminates the function name with '\0'
static struct ast_extenget_canmatch_exten (struct match_char *node)
static const char * get_pattern_node (struct pattern_node *node, const char *src, int pattern, const char *extenbuf)
static unsigned get_range (char *src, int max, const char *const names[], const char *msg)
 helper function to return a range up to max (7, 12, 31 respectively). names, if supplied, is an array of names that should be mapped to numbers.
static void get_timerange (struct ast_timing *i, char *times)
 store a bitmask of valid times, one bit each 1 minute
static char * handle_debug_dialplan (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 Send ack once.
static char * handle_set_chanvar (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_set_extenpatternmatchnew (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_set_global (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_show_application (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_show_applications (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_show_chanvar (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI support for listing chanvar's variables in a parseable way.
static char * handle_show_dialplan (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_show_function (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_show_functions (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_show_globals (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI support for listing global variables in a parseable way.
static char * handle_show_hint (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 handle_show_hint: CLI support for listing registered dial plan hint
static char * handle_show_hints (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 handle_show_hints: CLI support for listing registered dial plan hints
static char * handle_show_switches (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 handle_show_switches: CLI support for listing registered dial plan switches
static int handle_statechange (void *datap)
static char * handle_unset_extenpatternmatchnew (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int hashtab_compare_exten_labels (const void *ah_a, const void *ah_b)
static int hashtab_compare_exten_numbers (const void *ah_a, const void *ah_b)
static int hashtab_compare_extens (const void *ha_a, const void *ah_b)
static unsigned int hashtab_hash_extens (const void *obj)
static unsigned int hashtab_hash_labels (const void *obj)
static unsigned int hashtab_hash_priority (const void *obj)
static int hint_cmp (void *obj, void *arg, int flags)
static int hint_hash (const void *obj, const int flags)
static int hint_id_cmp (void *obj, void *arg, int flags)
static int hints_data_provider_get (const struct ast_data_search *search, struct ast_data *data_root)
static int include_valid (struct ast_include *i)
static int increase_call_count (const struct ast_channel *c)
 Increase call count for channel.
static void insert_in_next_chars_alt_char_list (struct match_char **parent_ptr, struct match_char *node)
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_shutdown (void)
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 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 unload_pbx (void)
static void unreference_cached_app (struct ast_app *app)
static void update_scoreboard (struct scoreboard *board, int length, int spec, struct ast_exten *exten, char last, const char *callerid, int deleted, struct match_char *node)
static void wait_for_hangup (struct ast_channel *chan, const void *data)

Variables

static int autofallthrough = 1
static struct ast_app_option background_opts [128] = { [ 's' ] = { .flag = (1 << 0) }, [ 'n' ] = { .flag = (1 << 1) }, [ 'm' ] = { .flag = (1 << 2) }, [ 'p' ] = { .flag = (1 << 3) },}
static struct pbx_builtin builtins []
 Declaration of builtin applications.
static ast_mutex_t conlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 }
 Lock for the ast_context list.
static ast_mutex_t context_merge_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 }
 Lock to hold off restructuring of hints by ast_merge_contexts_and_delete.
static struct ast_contextcontexts
static struct ast_hashtabcontexts_table = NULL
static int countcalls
static const char *const days []
static struct ast_event_subdevice_state_sub
 Subscription for device state change events.
static struct ast_taskprocessordevice_state_tps
static struct ast_custom_function exception_function
static struct ast_datastore_info exception_store_info
static int extenpatternmatchnew = 0
static struct cfextension_states extension_states []
static struct ast_threadstorage extensionstate_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_extensionstate_buf , .custom_init = NULL , }
static struct varshead globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE
static ast_rwlock_t globalslock = { PTHREAD_RWLOCK_INITIALIZER , NULL, 1 }
static struct ao2_containerhints
static struct ast_data_handler hints_data_provider
static ast_mutex_t maxcalllock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 }
static const char *const months []
static char * overrideswitch = NULL
static struct ast_cli_entry pbx_cli []
static struct ast_data_entry pbx_data_providers []
static struct ast_app_option resetcdr_opts [128] = { [ 'w' ] = { .flag = AST_CDR_FLAG_POSTED }, [ 'a' ] = { .flag = AST_CDR_FLAG_LOCKED }, [ 'v' ] = { .flag = AST_CDR_FLAG_KEEP_VARS }, [ 'e' ] = { .flag = AST_CDR_FLAG_POST_ENABLE },}
static struct ao2_containerstatecbs
static int stateid = 1
static struct ast_threadstorage switch_data = { .once = PTHREAD_ONCE_INIT , .key_init = __init_switch_data , .custom_init = NULL , }
static struct ast_custom_function testtime_function
static 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 1458 of file pbx.c.

#define BACKGROUND_MATCHEXTEN   (1 << 2)

Definition at line 799 of file pbx.c.

Referenced by pbx_builtin_background().

#define BACKGROUND_NOANSWER   (1 << 1)

Definition at line 798 of file pbx.c.

Referenced by pbx_builtin_background().

#define BACKGROUND_PLAYBACK   (1 << 3)

Definition at line 800 of file pbx.c.

Referenced by pbx_builtin_background().

#define BACKGROUND_SKIP   (1 << 0)

Definition at line 797 of file pbx.c.

Referenced by pbx_builtin_background().

#define BITS_PER   8

Referenced by ext_cmp_pattern_pos().

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

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

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

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

Definition at line 786 of file pbx.c.

Referenced by pbx_extension_helper(), and realtime_exec().

#define HASH_EXTENHINT_SIZE   563

Definition at line 975 of file pbx.c.

Referenced by ast_pbx_init().

#define INC_DST_OVERFLOW_CHECK

Referenced by get_pattern_node().

#define NEW_MATCHER_CHK_MATCH

Referenced by new_find_extension().

#define NEW_MATCHER_RECURSE

Referenced by new_find_extension().

#define SAY_STUBS

Definition at line 60 of file pbx.c.

#define STATUS_NO_CONTEXT   1

Definition at line 2920 of file pbx.c.

#define STATUS_NO_EXTENSION   2

Definition at line 2921 of file pbx.c.

#define STATUS_NO_LABEL   4

Definition at line 2923 of file pbx.c.

#define STATUS_NO_PRIORITY   3

Definition at line 2922 of file pbx.c.

#define STATUS_SUCCESS   5

Definition at line 2924 of file pbx.c.

#define SWITCH_DATA_LENGTH   256

Definition at line 789 of file pbx.c.

#define VAR_BUF_SIZE   4096
#define VAR_HARDTRAN   3

Definition at line 795 of file pbx.c.

#define VAR_NORMAL   1

Definition at line 793 of file pbx.c.

#define VAR_SOFTTRAN   2

Definition at line 794 of file pbx.c.

#define WAITEXTEN_DIALTONE   (1 << 1)

Definition at line 810 of file pbx.c.

Referenced by pbx_builtin_waitexten().

#define WAITEXTEN_MOH   (1 << 0)

Definition at line 809 of file pbx.c.

Referenced by pbx_builtin_waitexten().


Function Documentation

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

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

09391 {
09392    struct ast_context *tmp, *tmpl=NULL;
09393    struct ast_exten *exten_item, *prio_item;
09394 
09395    for (tmp = list; tmp; ) {
09396       struct ast_context *next = NULL; /* next starting point */
09397          /* The following code used to skip forward to the next
09398             context with matching registrar, but this didn't
09399             make sense; individual priorities registrar'd to
09400             the matching registrar could occur in any context! */
09401       ast_debug(1, "Investigate ctx %s %s\n", tmp->name, tmp->registrar);
09402       if (con) {
09403          for (; tmp; tmpl = tmp, tmp = tmp->next) { /* skip to the matching context */
09404             ast_debug(1, "check ctx %s %s\n", tmp->name, tmp->registrar);
09405             if ( !strcasecmp(tmp->name, con->name) ) {
09406                break;   /* found it */
09407             }
09408          }
09409       }
09410 
09411       if (!tmp)   /* not found, we are done */
09412          break;
09413       ast_wrlock_context(tmp);
09414 
09415       if (registrar) {
09416          /* then search thru and remove any extens that match registrar. */
09417          struct ast_hashtab_iter *exten_iter;
09418          struct ast_hashtab_iter *prio_iter;
09419          struct ast_ignorepat *ip, *ipl = NULL, *ipn = NULL;
09420          struct ast_include *i, *pi = NULL, *ni = NULL;
09421          struct ast_sw *sw = NULL;
09422 
09423          /* remove any ignorepats whose registrar matches */
09424          for (ip = tmp->ignorepats; ip; ip = ipn) {
09425             ipn = ip->next;
09426             if (!strcmp(ip->registrar, registrar)) {
09427                if (ipl) {
09428                   ipl->next = ip->next;
09429                   ast_free(ip);
09430                   continue; /* don't change ipl */
09431                } else {
09432                   tmp->ignorepats = ip->next;
09433                   ast_free(ip);
09434                   continue; /* don't change ipl */
09435                }
09436             }
09437             ipl = ip;
09438          }
09439          /* remove any includes whose registrar matches */
09440          for (i = tmp->includes; i; i = ni) {
09441             ni = i->next;
09442             if (strcmp(i->registrar, registrar) == 0) {
09443                /* remove from list */
09444                if (pi) {
09445                   pi->next = i->next;
09446                   /* free include */
09447                   ast_free(i);
09448                   continue; /* don't change pi */
09449                } else {
09450                   tmp->includes = i->next;
09451                   /* free include */
09452                   ast_free(i);
09453                   continue; /* don't change pi */
09454                }
09455             }
09456             pi = i;
09457          }
09458          /* remove any switches whose registrar matches */
09459          AST_LIST_TRAVERSE_SAFE_BEGIN(&tmp->alts, sw, list) {
09460             if (strcmp(sw->registrar,registrar) == 0) {
09461                AST_LIST_REMOVE_CURRENT(list);
09462                ast_free(sw);
09463             }
09464          }
09465          AST_LIST_TRAVERSE_SAFE_END;
09466 
09467          if (tmp->root_table) { /* it is entirely possible that the context is EMPTY */
09468             exten_iter = ast_hashtab_start_traversal(tmp->root_table);
09469             while ((exten_item=ast_hashtab_next(exten_iter))) {
09470                int end_traversal = 1;
09471                prio_iter = ast_hashtab_start_traversal(exten_item->peer_table);
09472                while ((prio_item=ast_hashtab_next(prio_iter))) {
09473                   char extension[AST_MAX_EXTENSION];
09474                   char cidmatch[AST_MAX_EXTENSION];
09475                   if (!prio_item->registrar || strcmp(prio_item->registrar, registrar) != 0) {
09476                      continue;
09477                   }
09478                   ast_verb(3, "Remove %s/%s/%d, registrar=%s; con=%s(%p); con->root=%p\n",
09479                          tmp->name, prio_item->exten, prio_item->priority, registrar, con? con->name : "<nil>", con, con? con->root_table: NULL);
09480                   /* set matchcid to 1 to insure we get a direct match, and NULL registrar to make sure no wildcarding is done */
09481                   ast_copy_string(extension, prio_item->exten, sizeof(extension));
09482                   if (prio_item->cidmatch) {
09483                      ast_copy_string(cidmatch, prio_item->cidmatch, sizeof(cidmatch));
09484                   }
09485                   end_traversal &= ast_context_remove_extension_callerid2(tmp, extension, prio_item->priority, prio_item->cidmatch ? cidmatch : NULL, 1, NULL, 1);
09486                }
09487                /* Explanation:
09488                 * ast_context_remove_extension_callerid2 will destroy the extension that it comes across. This
09489                 * destruction includes destroying the exten's peer_table, which we are currently traversing. If
09490                 * ast_context_remove_extension_callerid2 ever should return '0' then this means we have destroyed
09491                 * the hashtable which we are traversing, and thus calling ast_hashtab_end_traversal will result
09492                 * in reading invalid memory. Thus, if we detect that we destroyed the hashtable, then we will simply
09493                 * free the iterator
09494                 */
09495                if (end_traversal) {
09496                   ast_hashtab_end_traversal(prio_iter);
09497                } else {
09498                   ast_free(prio_iter);
09499                }
09500             }
09501             ast_hashtab_end_traversal(exten_iter);
09502          }
09503 
09504          /* delete the context if it's registrar matches, is empty, has refcount of 1, */
09505          /* it's not empty, if it has includes, ignorepats, or switches that are registered from
09506             another registrar. It's not empty if there are any extensions */
09507          if (strcmp(tmp->registrar, registrar) == 0 && tmp->refcount < 2 && !tmp->root && !tmp->ignorepats && !tmp->includes && AST_LIST_EMPTY(&tmp->alts)) {
09508             ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar);
09509             ast_hashtab_remove_this_object(contexttab, tmp);
09510 
09511             next = tmp->next;
09512             if (tmpl)
09513                tmpl->next = next;
09514             else
09515                contexts = next;
09516             /* Okay, now we're safe to let it go -- in a sense, we were
09517                ready to let it go as soon as we locked it. */
09518             ast_unlock_context(tmp);
09519             __ast_internal_context_destroy(tmp);
09520          } else {
09521             ast_debug(1,"Couldn't delete ctx %s/%s; refc=%d; tmp.root=%p\n", tmp->name, tmp->registrar,
09522                     tmp->refcount, tmp->root);
09523             ast_unlock_context(tmp);
09524             next = tmp->next;
09525             tmpl = tmp;
09526          }
09527       } else if (con) {
09528          ast_verb(3, "Deleting context %s registrar=%s\n", tmp->name, tmp->registrar);
09529          ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar);
09530          ast_hashtab_remove_this_object(contexttab, tmp);
09531 
09532          next = tmp->next;
09533          if (tmpl)
09534             tmpl->next = next;
09535          else
09536             contexts = next;
09537          /* Okay, now we're safe to let it go -- in a sense, we were
09538             ready to let it go as soon as we locked it. */
09539          ast_unlock_context(tmp);
09540          __ast_internal_context_destroy(tmp);
09541       }
09542 
09543       /* if we have a specific match, we are done, otherwise continue */
09544       tmp = con ? NULL : next;
09545    }
09546 }

int __ast_custom_function_register ( struct ast_custom_function acf,
struct ast_module mod 
)

Register a custom function.

Definition at line 3814 of file pbx.c.

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

Referenced by load_pbx().

03815 {
03816    struct ast_custom_function *cur;
03817    char tmps[80];
03818 
03819    if (!acf) {
03820       return -1;
03821    }
03822 
03823    acf->mod = mod;
03824 #ifdef AST_XML_DOCS
03825    acf->docsrc = AST_STATIC_DOC;
03826 #endif
03827 
03828    if (acf_retrieve_docs(acf)) {
03829       return -1;
03830    }
03831 
03832    AST_RWLIST_WRLOCK(&acf_root);
03833 
03834    AST_RWLIST_TRAVERSE(&acf_root, cur, acflist) {
03835       if (!strcmp(acf->name, cur->name)) {
03836          ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name);
03837          AST_RWLIST_UNLOCK(&acf_root);
03838          return -1;
03839       }
03840    }
03841 
03842    /* Store in alphabetical order */
03843    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) {
03844       if (strcasecmp(acf->name, cur->name) < 0) {
03845          AST_RWLIST_INSERT_BEFORE_CURRENT(acf, acflist);
03846          break;
03847       }
03848    }
03849    AST_RWLIST_TRAVERSE_SAFE_END;
03850 
03851    if (!cur) {
03852       AST_RWLIST_INSERT_TAIL(&acf_root, acf, acflist);
03853    }
03854 
03855    AST_RWLIST_UNLOCK(&acf_root);
03856 
03857    ast_verb(2, "Registered custom function '%s'\n", term_color(tmps, acf->name, COLOR_BRCYAN, 0, sizeof(tmps)));
03858 
03859    return 0;
03860 }

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

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

10821 {
10822    int (*goto_func)(struct ast_channel *chan, const char *context, const char *exten, int priority);
10823 
10824    if (!chan)
10825       return -2;
10826 
10827    if (context == NULL)
10828       context = chan->context;
10829    if (exten == NULL)
10830       exten = chan->exten;
10831 
10832    goto_func = (async) ? ast_async_goto : ast_explicit_goto;
10833    if (ast_exists_extension(chan, context, exten, priority,
10834       S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL)))
10835       return goto_func(chan, context, exten, priority);
10836    else {
10837       return AST_PBX_GOTO_FAILED;
10838    }
10839 }

static void __ast_internal_context_destroy ( struct ast_context con  )  [static]

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

09344 {
09345    struct ast_include *tmpi;
09346    struct ast_sw *sw;
09347    struct ast_exten *e, *el, *en;
09348    struct ast_ignorepat *ipi;
09349    struct ast_context *tmp = con;
09350 
09351    for (tmpi = tmp->includes; tmpi; ) { /* Free includes */
09352       struct ast_include *tmpil = tmpi;
09353       tmpi = tmpi->next;
09354       ast_free(tmpil);
09355    }
09356    for (ipi = tmp->ignorepats; ipi; ) { /* Free ignorepats */
09357       struct ast_ignorepat *ipl = ipi;
09358       ipi = ipi->next;
09359       ast_free(ipl);
09360    }
09361    if (tmp->registrar)
09362       ast_free(tmp->registrar);
09363 
09364    /* destroy the hash tabs */
09365    if (tmp->root_table) {
09366       ast_hashtab_destroy(tmp->root_table, 0);
09367    }
09368    /* and destroy the pattern tree */
09369    if (tmp->pattern_tree)
09370       destroy_pattern_tree(tmp->pattern_tree);
09371 
09372    while ((sw = AST_LIST_REMOVE_HEAD(&tmp->alts, list)))
09373       ast_free(sw);
09374    for (e = tmp->root; e;) {
09375       for (en = e->peer; en;) {
09376          el = en;
09377          en = en->peer;
09378          destroy_exten(el);
09379       }
09380       el = e;
09381       e = e->next;
09382       destroy_exten(el);
09383    }
09384    tmp->root = NULL;
09385    ast_rwlock_destroy(&tmp->lock);
09386    ast_free(tmp);
09387 }

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

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

Referenced by ast_pbx_run_args(), and pbx_thread().

05175 {
05176    int found = 0; /* set if we find at least one match */
05177    int res = 0;
05178    int autoloopflag;
05179    int error = 0;    /* set an error conditions */
05180 
05181    /* A little initial setup here */
05182    if (c->pbx) {
05183       ast_log(LOG_WARNING, "%s already has PBX structure??\n", c->name);
05184       /* XXX and now what ? */
05185       ast_free(c->pbx);
05186    }
05187    if (!(c->pbx = ast_calloc(1, sizeof(*c->pbx))))
05188       return -1;
05189    /* Set reasonable defaults */
05190    c->pbx->rtimeoutms = 10000;
05191    c->pbx->dtimeoutms = 5000;
05192 
05193    autoloopflag = ast_test_flag(c, AST_FLAG_IN_AUTOLOOP);   /* save value to restore at the end */
05194    ast_set_flag(c, AST_FLAG_IN_AUTOLOOP);
05195 
05196    /* Start by trying whatever the channel is set to */
05197    if (!ast_exists_extension(c, c->context, c->exten, c->priority,
05198       S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05199       /* If not successful fall back to 's' */
05200       ast_verb(2, "Starting %s at %s,%s,%d failed so falling back to exten 's'\n", c->name, c->context, c->exten, c->priority);
05201       /* XXX the original code used the existing priority in the call to
05202        * ast_exists_extension(), and reset it to 1 afterwards.
05203        * I believe the correct thing is to set it to 1 immediately.
05204        */
05205       set_ext_pri(c, "s", 1);
05206       if (!ast_exists_extension(c, c->context, c->exten, c->priority,
05207          S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05208          /* JK02: And finally back to default if everything else failed */
05209          ast_verb(2, "Starting %s at %s,%s,%d still failed so falling back to context 'default'\n", c->name, c->context, c->exten, c->priority);
05210          ast_copy_string(c->context, "default", sizeof(c->context));
05211       }
05212    }
05213    ast_channel_lock(c);
05214    if (c->cdr) {
05215       /* allow CDR variables that have been collected after channel was created to be visible during call */
05216       ast_cdr_update(c);
05217    }
05218    ast_channel_unlock(c);
05219    for (;;) {
05220       char dst_exten[256]; /* buffer to accumulate digits */
05221       int pos = 0;      /* XXX should check bounds */
05222       int digit = 0;
05223       int invalid = 0;
05224       int timeout = 0;
05225 
05226       /* No digits pressed yet */
05227       dst_exten[pos] = '\0';
05228 
05229       /* loop on priorities in this context/exten */
05230       while (!(res = ast_spawn_extension(c, c->context, c->exten, c->priority,
05231          S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL),
05232          &found, 1))) {
05233          if (!ast_check_hangup(c)) {
05234             ++c->priority;
05235             continue;
05236          }
05237 
05238          /* Check softhangup flags. */
05239          if (c->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) {
05240             ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO);
05241             continue;
05242          }
05243          if (c->_softhangup & AST_SOFTHANGUP_TIMEOUT) {
05244             if (ast_exists_extension(c, c->context, "T", 1,
05245                S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05246                set_ext_pri(c, "T", 1);
05247                /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
05248                memset(&c->whentohangup, 0, sizeof(c->whentohangup));
05249                ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
05250                continue;
05251             } else if (ast_exists_extension(c, c->context, "e", 1,
05252                S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05253                raise_exception(c, "ABSOLUTETIMEOUT", 1);
05254                /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
05255                memset(&c->whentohangup, 0, sizeof(c->whentohangup));
05256                ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
05257                continue;
05258             }
05259 
05260             /* Call timed out with no special extension to jump to. */
05261             error = 1;
05262             break;
05263          }
05264          ast_debug(1, "Extension %s, priority %d returned normally even though call was hung up\n",
05265             c->exten, c->priority);
05266          error = 1;
05267          break;
05268       } /* end while  - from here on we can use 'break' to go out */
05269       if (found && res) {
05270          /* Something bad happened, or a hangup has been requested. */
05271          if (strchr("0123456789ABCDEF*#", res)) {
05272             ast_debug(1, "Oooh, got something to jump out with ('%c')!\n", res);
05273             pos = 0;
05274             dst_exten[pos++] = digit = res;
05275             dst_exten[pos] = '\0';
05276          } else if (res == AST_PBX_INCOMPLETE) {
05277             ast_debug(1, "Spawn extension (%s,%s,%d) exited INCOMPLETE on '%s'\n", c->context, c->exten, c->priority, c->name);
05278             ast_verb(2, "Spawn extension (%s, %s, %d) exited INCOMPLETE on '%s'\n", c->context, c->exten, c->priority, c->name);
05279 
05280             /* Don't cycle on incomplete - this will happen if the only extension that matches is our "incomplete" extension */
05281             if (!ast_matchmore_extension(c, c->context, c->exten, 1,
05282                S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05283                invalid = 1;
05284             } else {
05285                ast_copy_string(dst_exten, c->exten, sizeof(dst_exten));
05286                digit = 1;
05287                pos = strlen(dst_exten);
05288             }
05289          } else {
05290             ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
05291             ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
05292 
05293             if ((res == AST_PBX_ERROR)
05294                && ast_exists_extension(c, c->context, "e", 1,
05295                   S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05296                /* if we are already on the 'e' exten, don't jump to it again */
05297                if (!strcmp(c->exten, "e")) {
05298                   ast_verb(2, "Spawn extension (%s, %s, %d) exited ERROR while already on 'e' exten on '%s'\n", c->context, c->exten, c->priority, c->name);
05299                   error = 1;
05300                } else {
05301                   raise_exception(c, "ERROR", 1);
05302                   continue;
05303                }
05304             }
05305 
05306             if (c->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) {
05307                ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO);
05308                continue;
05309             }
05310             if (c->_softhangup & AST_SOFTHANGUP_TIMEOUT) {
05311                if (ast_exists_extension(c, c->context, "T", 1,
05312                   S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05313                   set_ext_pri(c, "T", 1);
05314                   /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
05315                   memset(&c->whentohangup, 0, sizeof(c->whentohangup));
05316                   ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
05317                   continue;
05318                } else if (ast_exists_extension(c, c->context, "e", 1,
05319                   S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05320                   raise_exception(c, "ABSOLUTETIMEOUT", 1);
05321                   /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
05322                   memset(&c->whentohangup, 0, sizeof(c->whentohangup));
05323                   ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
05324                   continue;
05325                }
05326                /* Call timed out with no special extension to jump to. */
05327             }
05328             ast_channel_lock(c);
05329             if (c->cdr) {
05330                ast_cdr_update(c);
05331             }
05332             ast_channel_unlock(c);
05333             error = 1;
05334             break;
05335          }
05336       }
05337       if (error)
05338          break;
05339 
05340       /*!\note
05341        * We get here on a failure of some kind:  non-existing extension or
05342        * hangup.  We have options, here.  We can either catch the failure
05343        * and continue, or we can drop out entirely. */
05344 
05345       if (invalid
05346          || (ast_strlen_zero(dst_exten) &&
05347             !ast_exists_extension(c, c->context, c->exten, 1,
05348             S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL)))) {
05349          /*!\note
05350           * If there is no match at priority 1, it is not a valid extension anymore.
05351           * Try to continue at "i" (for invalid) or "e" (for exception) or exit if
05352           * neither exist.
05353           */
05354          if (ast_exists_extension(c, c->context, "i", 1,
05355             S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05356             ast_verb(3, "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, c->name);
05357             pbx_builtin_setvar_helper(c, "INVALID_EXTEN", c->exten);
05358             set_ext_pri(c, "i", 1);
05359          } else if (ast_exists_extension(c, c->context, "e", 1,
05360             S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05361             raise_exception(c, "INVALID", 1);
05362          } else {
05363             ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n",
05364                c->name, c->exten, c->context);
05365             error = 1; /* we know what to do with it */
05366             break;
05367          }
05368       } else if (c->_softhangup & AST_SOFTHANGUP_TIMEOUT) {
05369          /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */
05370          ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
05371       } else { /* keypress received, get more digits for a full extension */
05372          int waittime = 0;
05373          if (digit)
05374             waittime = c->pbx->dtimeoutms;
05375          else if (!autofallthrough)
05376             waittime = c->pbx->rtimeoutms;
05377          if (!waittime) {
05378             const char *status = pbx_builtin_getvar_helper(c, "DIALSTATUS");
05379             if (!status)
05380                status = "UNKNOWN";
05381             ast_verb(3, "Auto fallthrough, channel '%s' status is '%s'\n", c->name, status);
05382             if (!strcasecmp(status, "CONGESTION"))
05383                res = pbx_builtin_congestion(c, "10");
05384             else if (!strcasecmp(status, "CHANUNAVAIL"))
05385                res = pbx_builtin_congestion(c, "10");
05386             else if (!strcasecmp(status, "BUSY"))
05387                res = pbx_builtin_busy(c, "10");
05388             error = 1; /* XXX disable message */
05389             break;   /* exit from the 'for' loop */
05390          }
05391 
05392          if (collect_digits(c, waittime, dst_exten, sizeof(dst_exten), pos))
05393             break;
05394          if (res == AST_PBX_INCOMPLETE && ast_strlen_zero(&dst_exten[pos]))
05395             timeout = 1;
05396          if (!timeout
05397             && ast_exists_extension(c, c->context, dst_exten, 1,
05398                S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { /* Prepare the next cycle */
05399             set_ext_pri(c, dst_exten, 1);
05400          } else {
05401             /* No such extension */
05402             if (!timeout && !ast_strlen_zero(dst_exten)) {
05403                /* An invalid extension */
05404                if (ast_exists_extension(c, c->context, "i", 1,
05405                   S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05406                   ast_verb(3, "Invalid extension '%s' in context '%s' on %s\n", dst_exten, c->context, c->name);
05407                   pbx_builtin_setvar_helper(c, "INVALID_EXTEN", dst_exten);
05408                   set_ext_pri(c, "i", 1);
05409                } else if (ast_exists_extension(c, c->context, "e", 1,
05410                   S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05411                   raise_exception(c, "INVALID", 1);
05412                } else {
05413                   ast_log(LOG_WARNING,
05414                      "Invalid extension '%s', but no rule 'i' or 'e' in context '%s'\n",
05415                      dst_exten, c->context);
05416                   found = 1; /* XXX disable message */
05417                   break;
05418                }
05419             } else {
05420                /* A simple timeout */
05421                if (ast_exists_extension(c, c->context, "t", 1,
05422                   S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05423                   ast_verb(3, "Timeout on %s\n", c->name);
05424                   set_ext_pri(c, "t", 1);
05425                } else if (ast_exists_extension(c, c->context, "e", 1,
05426                   S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05427                   raise_exception(c, "RESPONSETIMEOUT", 1);
05428                } else {
05429                   ast_log(LOG_WARNING,
05430                      "Timeout, but no rule 't' or 'e' in context '%s'\n",
05431                      c->context);
05432                   found = 1; /* XXX disable message */
05433                   break;
05434                }
05435             }
05436          }
05437          ast_channel_lock(c);
05438          if (c->cdr) {
05439             ast_verb(2, "CDR updated on %s\n",c->name);
05440             ast_cdr_update(c);
05441          }
05442          ast_channel_unlock(c);
05443       }
05444    }
05445 
05446    if (!found && !error) {
05447       ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name);
05448    }
05449 
05450    if (!args || !args->no_hangup_chan) {
05451       ast_softhangup(c, AST_SOFTHANGUP_APPUNLOAD);
05452    }
05453 
05454    if ((!args || !args->no_hangup_chan)
05455       && !ast_test_flag(c, AST_FLAG_BRIDGE_HANGUP_RUN)
05456       && ast_exists_extension(c, c->context, "h", 1,
05457          S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05458       set_ext_pri(c, "h", 1);
05459       if (c->cdr && ast_opt_end_cdr_before_h_exten) {
05460          ast_cdr_end(c->cdr);
05461       }
05462       while ((res = ast_spawn_extension(c, c->context, c->exten, c->priority,
05463          S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL),
05464          &found, 1)) == 0) {
05465          c->priority++;
05466       }
05467       if (found && res) {
05468          /* Something bad happened, or a hangup has been requested. */
05469          ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
05470          ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
05471       }
05472    }
05473    ast_set2_flag(c, autoloopflag, AST_FLAG_IN_AUTOLOOP);
05474    ast_clear_flag(c, AST_FLAG_BRIDGE_HANGUP_RUN); /* from one round to the next, make sure this gets cleared */
05475    pbx_destroy(c->pbx);
05476    c->pbx = NULL;
05477 
05478    if (!args || !args->no_hangup_chan) {
05479       ast_hangup(c);
05480    }
05481 
05482    return 0;
05483 }

static void __init_extensionstate_buf ( void   )  [static]

Definition at line 823 of file pbx.c.

00826 : An extension

static void __init_switch_data ( void   )  [static]

Definition at line 822 of file pbx.c.

00826 : An extension

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

Definition at line 2664 of file pbx.c.

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

Referenced by extension_match_core().

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

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

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

03552 {
03553    struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL);
03554    struct pbx_exception *exception = NULL;
03555    if (!ds || !ds->data)
03556       return -1;
03557    exception = ds->data;
03558    if (!strcasecmp(data, "REASON"))
03559       ast_copy_string(buf, exception->reason, buflen);
03560    else if (!strcasecmp(data, "CONTEXT"))
03561       ast_copy_string(buf, exception->context, buflen);
03562    else if (!strncasecmp(data, "EXTEN", 5))
03563       ast_copy_string(buf, exception->exten, buflen);
03564    else if (!strcasecmp(data, "PRIORITY"))
03565       snprintf(buf, buflen, "%d", exception->priority);
03566    else
03567       return -1;
03568    return 0;
03569 }

static int acf_retrieve_docs ( struct ast_custom_function acf  )  [static]

Definition at line 3769 of file pbx.c.

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

Referenced by __ast_custom_function_register().

03770 {
03771 #ifdef AST_XML_DOCS
03772    char *tmpxml;
03773 
03774    /* Let's try to find it in the Documentation XML */
03775    if (!ast_strlen_zero(acf->desc) || !ast_strlen_zero(acf->synopsis)) {
03776       return 0;
03777    }
03778 
03779    if (ast_string_field_init(acf, 128)) {
03780       return -1;
03781    }
03782 
03783    /* load synopsis */
03784    tmpxml = ast_xmldoc_build_synopsis("function", acf->name, ast_module_name(acf->mod));
03785    ast_string_field_set(acf, synopsis, tmpxml);
03786    ast_free(tmpxml);
03787 
03788    /* load description */
03789    tmpxml = ast_xmldoc_build_description("function", acf->name, ast_module_name(acf->mod));
03790    ast_string_field_set(acf, desc, tmpxml);
03791    ast_free(tmpxml);
03792 
03793    /* load syntax */
03794    tmpxml = ast_xmldoc_build_syntax("function", acf->name, ast_module_name(acf->mod));
03795    ast_string_field_set(acf, syntax, tmpxml);
03796    ast_free(tmpxml);
03797 
03798    /* load arguments */
03799    tmpxml = ast_xmldoc_build_arguments("function", acf->name, ast_module_name(acf->mod));
03800    ast_string_field_set(acf, arguments, tmpxml);
03801    ast_free(tmpxml);
03802 
03803    /* load seealso */
03804    tmpxml = ast_xmldoc_build_seealso("function", acf->name, ast_module_name(acf->mod));
03805    ast_string_field_set(acf, seealso, tmpxml);
03806    ast_free(tmpxml);
03807 
03808    acf->docsrc = AST_XML_DOC;
03809 #endif
03810 
03811    return 0;
03812 }

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

Definition at line 2147 of file pbx.c.

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

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

02148 {
02149    struct match_char *m1 = NULL;
02150    struct match_char *m2 = NULL;
02151    struct match_char **m0;
02152    const char *pos;
02153    int already;
02154    int pattern = 0;
02155    int idx_cur;
02156    int idx_next;
02157    char extenbuf[512];
02158    struct pattern_node pat_node[2];
02159 
02160    if (e1->matchcid) {
02161       if (sizeof(extenbuf) < strlen(e1->exten) + strlen(e1->cidmatch) + 2) {
02162          ast_log(LOG_ERROR,
02163             "The pattern %s/%s is too big to deal with: it will be ignored! Disaster!\n",
02164             e1->exten, e1->cidmatch);
02165          return NULL;
02166       }
02167       sprintf(extenbuf, "%s/%s", e1->exten, e1->cidmatch);/* Safe.  We just checked. */
02168    } else {
02169       ast_copy_string(extenbuf, e1->exten, sizeof(extenbuf));
02170    }
02171 
02172 #ifdef NEED_DEBUG
02173    ast_log(LOG_DEBUG, "Adding exten %s to tree\n", extenbuf);
02174 #endif
02175    m1 = con->pattern_tree; /* each pattern starts over at the root of the pattern tree */
02176    m0 = &con->pattern_tree;
02177    already = 1;
02178 
02179    pos = extenbuf;
02180    if (*pos == '_') {
02181       pattern = 1;
02182       ++pos;
02183    }
02184    idx_cur = 0;
02185    pos = get_pattern_node(&pat_node[idx_cur], pos, pattern, extenbuf);
02186    for (; pat_node[idx_cur].buf[0]; idx_cur = idx_next) {
02187       idx_next = (idx_cur + 1) % ARRAY_LEN(pat_node);
02188       pos = get_pattern_node(&pat_node[idx_next], pos, pattern, extenbuf);
02189 
02190       /* See about adding node to tree. */
02191       m2 = NULL;
02192       if (already && (m2 = already_in_tree(m1, pat_node[idx_cur].buf, pattern))
02193          && m2->next_char) {
02194          if (!pat_node[idx_next].buf[0]) {
02195             /*
02196              * This is the end of the pattern, but not the end of the tree.
02197              * Mark this node with the exten... a shorter pattern might win
02198              * if the longer one doesn't match.
02199              */
02200             if (findonly) {
02201                return m2;
02202             }
02203             if (m2->exten) {
02204                ast_log(LOG_WARNING, "Found duplicate exten. Had %s found %s\n",
02205                   m2->deleted ? "(deleted/invalid)" : m2->exten->exten, e1->exten);
02206             }
02207             m2->exten = e1;
02208             m2->deleted = 0;
02209          }
02210          m1 = m2->next_char; /* m1 points to the node to compare against */
02211          m0 = &m2->next_char; /* m0 points to the ptr that points to m1 */
02212       } else { /* not already OR not m2 OR nor m2->next_char */
02213          if (m2) {
02214             if (findonly) {
02215                return m2;
02216             }
02217             m1 = m2; /* while m0 stays the same */
02218          } else {
02219             if (findonly) {
02220                return m1;
02221             }
02222             m1 = add_pattern_node(con, m1, &pat_node[idx_cur], pattern, already, m0);
02223             if (!m1) { /* m1 is the node just added */
02224                return NULL;
02225             }
02226             m0 = &m1->next_char;
02227          }
02228          if (!pat_node[idx_next].buf[0]) {
02229             if (m2 && m2->exten) {
02230                ast_log(LOG_WARNING, "Found duplicate exten. Had %s found %s\n",
02231                   m2->deleted ? "(deleted/invalid)" : m2->exten->exten, e1->exten);
02232             }
02233             m1->deleted = 0;
02234             m1->exten = e1;
02235          }
02236 
02237          /* The 'already' variable is a mini-optimization designed to make it so that we
02238           * don't have to call already_in_tree when we know it will return false.
02239           */
02240          already = 0;
02241       }
02242    }
02243    return m1;
02244 }

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

01950 {
01951    struct match_char *m;
01952 
01953    if (!(m = ast_calloc(1, sizeof(*m) + strlen(pattern->buf)))) {
01954       return NULL;
01955    }
01956 
01957    /* strcpy is safe here since we know its size and have allocated
01958     * just enough space for when we allocated m
01959     */
01960    strcpy(m->x, pattern->buf);
01961 
01962    /* the specificity scores are the same as used in the old
01963       pattern matcher. */
01964    m->is_pattern = is_pattern;
01965    if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'N') {
01966       m->specificity = 0x0832;
01967    } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'Z') {
01968       m->specificity = 0x0931;
01969    } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'X') {
01970       m->specificity = 0x0a30;
01971    } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == '.') {
01972       m->specificity = 0x18000;
01973    } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == '!') {
01974       m->specificity = 0x28000;
01975    } else {
01976       m->specificity = pattern->specif;
01977    }
01978 
01979    if (!con->pattern_tree) {
01980       insert_in_next_chars_alt_char_list(&con->pattern_tree, m);
01981    } else {
01982       if (already) { /* switch to the new regime (traversing vs appending)*/
01983          insert_in_next_chars_alt_char_list(nextcharptr, m);
01984       } else {
01985          insert_in_next_chars_alt_char_list(&current->next_char, m);
01986       }
01987    }
01988 
01989    return m;
01990 }

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

08531 {
08532    struct ast_exten *ep;
08533    struct ast_exten *eh=e;
08534    int repeated_label = 0; /* Track if this label is a repeat, assume no. */
08535 
08536    for (ep = NULL; e ; ep = e, e = e->peer) {
08537       if (e->label && tmp->label && e->priority != tmp->priority && !strcmp(e->label, tmp->label)) {
08538          if (strcmp(e->exten, tmp->exten)) {
08539             ast_log(LOG_WARNING,
08540                "Extension '%s' priority %d in '%s', label '%s' already in use at aliased extension '%s' priority %d\n",
08541                tmp->exten, tmp->priority, con->name, tmp->label, e->exten, e->priority);
08542          } else {
08543             ast_log(LOG_WARNING,
08544                "Extension '%s' priority %d in '%s', label '%s' already in use at priority %d\n",
08545                tmp->exten, tmp->priority, con->name, tmp->label, e->priority);
08546          }
08547          repeated_label = 1;
08548       }
08549       if (e->priority >= tmp->priority) {
08550          break;
08551       }
08552    }
08553 
08554    if (repeated_label) {   /* Discard the label since it's a repeat. */
08555       tmp->label = NULL;
08556    }
08557 
08558    if (!e) {   /* go at the end, and ep is surely set because the list is not empty */
08559       ast_hashtab_insert_safe(eh->peer_table, tmp);
08560 
08561       if (tmp->label) {
08562          ast_hashtab_insert_safe(eh->peer_label_table, tmp);
08563       }
08564       ep->peer = tmp;
08565       return 0;   /* success */
08566    }
08567    if (e->priority == tmp->priority) {
08568       /* Can't have something exactly the same.  Is this a
08569          replacement?  If so, replace, otherwise, bonk. */
08570       if (!replace) {
08571          if (strcmp(e->exten, tmp->exten)) {
08572             ast_log(LOG_WARNING,
08573                "Unable to register extension '%s' priority %d in '%s', already in use by aliased extension '%s'\n",
08574                tmp->exten, tmp->priority, con->name, e->exten);
08575          } else {
08576             ast_log(LOG_WARNING,
08577                "Unable to register extension '%s' priority %d in '%s', already in use\n",
08578                tmp->exten, tmp->priority, con->name);
08579          }
08580          if (tmp->datad) {
08581             tmp->datad(tmp->data);
08582             /* if you free this, null it out */
08583             tmp->data = NULL;
08584          }
08585 
08586          ast_free(tmp);
08587          return -1;
08588       }
08589       /* we are replacing e, so copy the link fields and then update
08590        * whoever pointed to e to point to us
08591        */
08592       tmp->next = e->next; /* not meaningful if we are not first in the peer list */
08593       tmp->peer = e->peer; /* always meaningful */
08594       if (ep)  {     /* We're in the peer list, just insert ourselves */
08595          ast_hashtab_remove_object_via_lookup(eh->peer_table,e);
08596 
08597          if (e->label) {
08598             ast_hashtab_remove_object_via_lookup(eh->peer_label_table,e);
08599          }
08600 
08601          ast_hashtab_insert_safe(eh->peer_table,tmp);
08602          if (tmp->label) {
08603             ast_hashtab_insert_safe(eh->peer_label_table,tmp);
08604          }
08605 
08606          ep->peer = tmp;
08607       } else if (el) {     /* We're the first extension. Take over e's functions */
08608          struct match_char *x = add_exten_to_pattern_tree(con, e, 1);
08609          tmp->peer_table = e->peer_table;
08610          tmp->peer_label_table = e->peer_label_table;
08611          ast_hashtab_remove_object_via_lookup(tmp->peer_table,e);
08612          ast_hashtab_insert_safe(tmp->peer_table,tmp);
08613          if (e->label) {
08614             ast_hashtab_remove_object_via_lookup(tmp->peer_label_table, e);
08615          }
08616          if (tmp->label) {
08617             ast_hashtab_insert_safe(tmp->peer_label_table, tmp);
08618          }
08619 
08620          ast_hashtab_remove_object_via_lookup(con->root_table, e);
08621          ast_hashtab_insert_safe(con->root_table, tmp);
08622          el->next = tmp;
08623          /* The pattern trie points to this exten; replace the pointer,
08624             and all will be well */
08625          if (x) { /* if the trie isn't formed yet, don't sweat this */
08626             if (x->exten) { /* this test for safety purposes */
08627                x->exten = tmp; /* replace what would become a bad pointer */
08628             } else {
08629                ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n");
08630             }
08631          }
08632       } else {       /* We're the very first extension.  */
08633          struct match_char *x = add_exten_to_pattern_tree(con, e, 1);
08634          ast_hashtab_remove_object_via_lookup(con->root_table, e);
08635          ast_hashtab_insert_safe(con->root_table, tmp);
08636          tmp->peer_table = e->peer_table;
08637          tmp->peer_label_table = e->peer_label_table;
08638          ast_hashtab_remove_object_via_lookup(tmp->peer_table, e);
08639          ast_hashtab_insert_safe(tmp->peer_table, tmp);
08640          if (e->label) {
08641             ast_hashtab_remove_object_via_lookup(tmp->peer_label_table, e);
08642          }
08643          if (tmp->label) {
08644             ast_hashtab_insert_safe(tmp->peer_label_table, tmp);
08645          }
08646 
08647          ast_hashtab_remove_object_via_lookup(con->root_table, e);
08648          ast_hashtab_insert_safe(con->root_table, tmp);
08649          con->root = tmp;
08650          /* The pattern trie points to this exten; replace the pointer,
08651             and all will be well */
08652          if (x) { /* if the trie isn't formed yet; no problem */
08653             if (x->exten) { /* this test for safety purposes */
08654                x->exten = tmp; /* replace what would become a bad pointer */
08655             } else {
08656                ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n");
08657             }
08658          }
08659       }
08660       if (tmp->priority == PRIORITY_HINT)
08661          ast_change_hint(e,tmp);
08662       /* Destroy the old one */
08663       if (e->datad)
08664          e->datad(e->data);
08665       ast_free(e);
08666    } else { /* Slip ourselves in just before e */
08667       tmp->peer = e;
08668       tmp->next = e->next; /* extension chain, or NULL if e is not the first extension */
08669       if (ep) {         /* Easy enough, we're just in the peer list */
08670          if (tmp->label) {
08671             ast_hashtab_insert_safe(eh->peer_label_table, tmp);
08672          }
08673          ast_hashtab_insert_safe(eh->peer_table, tmp);
08674          ep->peer = tmp;
08675       } else {       /* we are the first in some peer list, so link in the ext list */
08676          tmp->peer_table = e->peer_table;
08677          tmp->peer_label_table = e->peer_label_table;
08678          e->peer_table = 0;
08679          e->peer_label_table = 0;
08680          ast_hashtab_insert_safe(tmp->peer_table, tmp);
08681          if (tmp->label) {
08682             ast_hashtab_insert_safe(tmp->peer_label_table, tmp);
08683          }
08684          ast_hashtab_remove_object_via_lookup(con->root_table, e);
08685          ast_hashtab_insert_safe(con->root_table, tmp);
08686          if (el)
08687             el->next = tmp;   /* in the middle... */
08688          else
08689             con->root = tmp; /* ... or at the head */
08690          e->next = NULL;   /* e is no more at the head, so e->next must be reset */
08691       }
08692       /* And immediately return success. */
08693       if (tmp->priority == PRIORITY_HINT) {
08694          ast_add_hint(tmp);
08695       }
08696    }
08697    return 0;
08698 }

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

Definition at line 1887 of file pbx.c.

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

Referenced by add_exten_to_pattern_tree().

01888 {
01889    struct match_char *t;
01890 
01891    if (!current) {
01892       return 0;
01893    }
01894 
01895    for (t = current; t; t = t->alt_char) {
01896       if (is_pattern == t->is_pattern && !strcmp(pat, t->x)) {/* uh, we may want to sort exploded [] contents to make matching easy */
01897          return t;
01898       }
01899    }
01900 
01901    return 0;
01902 }

int ast_active_calls ( void   ) 

Retrieve the number of active calls.

Definition at line 5631 of file pbx.c.

References countcalls.

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

05632 {
05633    return countcalls;
05634 }

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

08367 {
08368    int ret = -1;
08369    struct ast_context *c;
08370 
08371    c = find_context_locked(context);
08372    if (c) {
08373       ret = ast_add_extension2(c, replace, extension, priority, label, callerid,
08374          application, data, datad, registrar);
08375       ast_unlock_contexts();
08376    }
08377 
08378    return ret;
08379 }

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

References ast_add_extension2_lockopt().

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

08729 {
08730    return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid,
08731       application, data, datad, registrar, 1);
08732 }

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

08745 {
08746    /*
08747     * Sort extensions (or patterns) according to the rules indicated above.
08748     * These are implemented by the function ext_cmp()).
08749     * All priorities for the same ext/pattern/cid are kept in a list,
08750     * using the 'peer' field  as a link field..
08751     */
08752    struct ast_exten *tmp, *tmp2, *e, *el = NULL;
08753    int res;
08754    int length;
08755    char *p;
08756    char expand_buf[VAR_BUF_SIZE];
08757    struct ast_exten dummy_exten = {0};
08758    char dummy_name[1024];
08759 
08760    if (ast_strlen_zero(extension)) {
08761       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",
08762             con->name);
08763       return -1;
08764    }
08765 
08766    /* If we are adding a hint evalulate in variables and global variables */
08767    if (priority == PRIORITY_HINT && strstr(application, "${") && extension[0] != '_') {
08768       struct ast_channel *c = ast_dummy_channel_alloc();
08769 
08770       if (c) {
08771          ast_copy_string(c->exten, extension, sizeof(c->exten));
08772          ast_copy_string(c->context, con->name, sizeof(c->context));
08773       }
08774       pbx_substitute_variables_helper(c, application, expand_buf, sizeof(expand_buf));
08775       application = expand_buf;
08776       if (c) {
08777          ast_channel_unref(c);
08778       }
08779    }
08780 
08781    length = sizeof(struct ast_exten);
08782    length += strlen(extension) + 1;
08783    length += strlen(application) + 1;
08784    if (label)
08785       length += strlen(label) + 1;
08786    if (callerid)
08787       length += strlen(callerid) + 1;
08788    else
08789       length ++;  /* just the '\0' */
08790 
08791    /* Be optimistic:  Build the extension structure first */
08792    if (!(tmp = ast_calloc(1, length)))
08793       return -1;
08794 
08795    if (ast_strlen_zero(label)) /* let's turn empty labels to a null ptr */
08796       label = 0;
08797 
08798    /* use p as dst in assignments, as the fields are const char * */
08799    p = tmp->stuff;
08800    if (label) {
08801       tmp->label = p;
08802       strcpy(p, label);
08803       p += strlen(label) + 1;
08804    }
08805    tmp->exten = p;
08806    p += ext_strncpy(p, extension, strlen(extension) + 1) + 1;
08807    tmp->priority = priority;
08808    tmp->cidmatch = p;   /* but use p for assignments below */
08809 
08810    /* Blank callerid and NULL callerid are two SEPARATE things.  Do NOT confuse the two!!! */
08811    if (callerid) {
08812       p += ext_strncpy(p, callerid, strlen(callerid) + 1) + 1;
08813       tmp->matchcid = 1;
08814    } else {
08815       *p++ = '\0';
08816       tmp->matchcid = 0;
08817    }
08818    tmp->app = p;
08819    strcpy(p, application);
08820    tmp->parent = con;
08821    tmp->data = data;
08822    tmp->datad = datad;
08823    tmp->registrar = registrar;
08824 
08825    if (lock_context) {
08826       ast_wrlock_context(con);
08827    }
08828 
08829    if (con->pattern_tree) { /* usually, on initial load, the pattern_tree isn't formed until the first find_exten; so if we are adding
08830                         an extension, and the trie exists, then we need to incrementally add this pattern to it. */
08831       ast_copy_string(dummy_name, extension, sizeof(dummy_name));
08832       dummy_exten.exten = dummy_name;
08833       dummy_exten.matchcid = 0;
08834       dummy_exten.cidmatch = 0;
08835       tmp2 = ast_hashtab_lookup(con->root_table, &dummy_exten);
08836       if (!tmp2) {
08837          /* hmmm, not in the trie; */
08838          add_exten_to_pattern_tree(con, tmp, 0);
08839          ast_hashtab_insert_safe(con->root_table, tmp); /* for the sake of completeness */
08840       }
08841    }
08842    res = 0; /* some compilers will think it is uninitialized otherwise */
08843    for (e = con->root; e; el = e, e = e->next) {   /* scan the extension list */
08844       res = ext_cmp(e->exten, tmp->exten);
08845       if (res == 0) { /* extension match, now look at cidmatch */
08846          if (!e->matchcid && !tmp->matchcid)
08847             res = 0;
08848          else if (tmp->matchcid && !e->matchcid)
08849             res = 1;
08850          else if (e->matchcid && !tmp->matchcid)
08851             res = -1;
08852          else
08853             res = ext_cmp(e->cidmatch, tmp->cidmatch);
08854       }
08855       if (res >= 0)
08856          break;
08857    }
08858    if (e && res == 0) { /* exact match, insert in the priority chain */
08859       res = add_priority(con, tmp, el, e, replace);
08860       if (lock_context) {
08861          ast_unlock_context(con);
08862       }
08863       if (res < 0) {
08864          errno = EEXIST;   /* XXX do we care ? */
08865          return 0; /* XXX should we return -1 maybe ? */
08866       }
08867    } else {
08868       /*
08869        * not an exact match, this is the first entry with this pattern,
08870        * so insert in the main list right before 'e' (if any)
08871        */
08872       tmp->next = e;
08873       if (el) {  /* there is another exten already in this context */
08874          el->next = tmp;
08875          tmp->peer_table = ast_hashtab_create(13,
08876                      hashtab_compare_exten_numbers,
08877                      ast_hashtab_resize_java,
08878                      ast_hashtab_newsize_java,
08879                      hashtab_hash_priority,
08880                      0);
08881          tmp->peer_label_table = ast_hashtab_create(7,
08882                         hashtab_compare_exten_labels,
08883                         ast_hashtab_resize_java,
08884                         ast_hashtab_newsize_java,
08885                         hashtab_hash_labels,
08886                         0);
08887          if (label) {
08888             ast_hashtab_insert_safe(tmp->peer_label_table, tmp);
08889          }
08890          ast_hashtab_insert_safe(tmp->peer_table, tmp);
08891       } else {  /* this is the first exten in this context */
08892          if (!con->root_table)
08893             con->root_table = ast_hashtab_create(27,
08894                                        hashtab_compare_extens,
08895                                        ast_hashtab_resize_java,
08896                                        ast_hashtab_newsize_java,
08897                                        hashtab_hash_extens,
08898                                        0);
08899          con->root = tmp;
08900          con->root->peer_table = ast_hashtab_create(13,
08901                         hashtab_compare_exten_numbers,
08902                         ast_hashtab_resize_java,
08903                         ast_hashtab_newsize_java,
08904                         hashtab_hash_priority,
08905                         0);
08906          con->root->peer_label_table = ast_hashtab_create(7,
08907                            hashtab_compare_exten_labels,
08908                            ast_hashtab_resize_java,
08909                            ast_hashtab_newsize_java,
08910                            hashtab_hash_labels,
08911                            0);
08912          if (label) {
08913             ast_hashtab_insert_safe(con->root->peer_label_table, tmp);
08914          }
08915          ast_hashtab_insert_safe(con->root->peer_table, tmp);
08916 
08917       }
08918       ast_hashtab_insert_safe(con->root_table, tmp);
08919       if (lock_context) {
08920          ast_unlock_context(con);
08921       }
08922       if (tmp->priority == PRIORITY_HINT) {
08923          ast_add_hint(tmp);
08924       }
08925    }
08926    if (option_debug) {
08927       if (tmp->matchcid) {
08928          ast_debug(1, "Added extension '%s' priority %d (CID match '%s') to %s (%p)\n",
08929                  tmp->exten, tmp->priority, tmp->cidmatch, con->name, con);
08930       } else {
08931          ast_debug(1, "Added extension '%s' priority %d to %s (%p)\n",
08932                  tmp->exten, tmp->priority, con->name, con);
08933       }
08934    }
08935 
08936    if (tmp->matchcid) {
08937       ast_verb(3, "Added extension '%s' priority %d (CID match '%s') to %s\n",
08938              tmp->exten, tmp->priority, tmp->cidmatch, con->name);
08939    } else {
08940       ast_verb(3, "Added extension '%s' priority %d to %s\n",
08941              tmp->exten, tmp->priority, con->name);
08942    }
08943 
08944    return 0;
08945 }

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

References ast_add_extension2_lockopt(), and find_context().

Referenced by ast_merge_contexts_and_delete().

08347 {
08348    int ret = -1;
08349    struct ast_context *c;
08350 
08351    c = find_context(context);
08352    if (c) {
08353       ret = ast_add_extension2_lockopt(c, replace, extension, priority, label, callerid,
08354          application, data, datad, registrar, 1);
08355    }
08356 
08357    return ret;
08358 }

static int ast_add_hint ( struct ast_exten e  )  [static]

Add hint to hint list, check initial extension state.

Definition at line 4974 of file pbx.c.

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

Referenced by add_priority(), and ast_add_extension2_lockopt().

04975 {
04976    struct ast_hint *hint_new;
04977    struct ast_hint *hint_found;
04978 
04979    if (!e) {
04980       return -1;
04981    }
04982 
04983    /*
04984     * We must create the hint we wish to add before determining if
04985     * it is already in the hints container to avoid possible
04986     * deadlock when getting the current extension state.
04987     */
04988    hint_new = ao2_alloc(sizeof(*hint_new), destroy_hint);
04989    if (!hint_new) {
04990       return -1;
04991    }
04992 
04993    /* Initialize new hint. */
04994    hint_new->callbacks = ao2_container_alloc(1, NULL, hint_id_cmp);
04995    if (!hint_new->callbacks) {
04996       ao2_ref(hint_new, -1);
04997       return -1;
04998    }
04999    hint_new->exten = e;
05000    hint_new->laststate = ast_extension_state2(e);
05001 
05002    /* Prevent multiple add hints from adding the same hint at the same time. */
05003    ao2_lock(hints);
05004 
05005    /* Search if hint exists, do nothing */
05006    hint_found = ao2_find(hints, e, 0);
05007    if (hint_found) {
05008       ao2_ref(hint_found, -1);
05009       ao2_unlock(hints);
05010       ao2_ref(hint_new, -1);
05011       ast_debug(2, "HINTS: Not re-adding existing hint %s: %s\n",
05012          ast_get_extension_name(e), ast_get_extension_app(e));
05013       return -1;
05014    }
05015 
05016    /* Add new hint to the hints container */
05017    ast_debug(2, "HINTS: Adding hint %s: %s\n",
05018       ast_get_extension_name(e), ast_get_extension_app(e));
05019    ao2_link(hints, hint_new);
05020 
05021    ao2_unlock(hints);
05022    ao2_ref(hint_new, -1);
05023 
05024    return 0;
05025 }

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

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

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

08405 {
08406    int res = 0;
08407    struct ast_channel *tmpchan;
08408    struct {
08409       char *accountcode;
08410       char *exten;
08411       char *context;
08412       char *linkedid;
08413       char *name;
08414       struct ast_cdr *cdr;
08415       int amaflags;
08416       int state;
08417       format_t readformat;
08418       format_t writeformat;
08419    } tmpvars = { 0, };
08420 
08421    ast_channel_lock(chan);
08422    if (chan->pbx) { /* This channel is currently in the PBX */
08423       ast_explicit_goto(chan, context, exten, priority + 1);
08424       ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO);
08425       ast_channel_unlock(chan);
08426       return res;
08427    }
08428 
08429    /* In order to do it when the channel doesn't really exist within
08430     * the PBX, we have to make a new channel, masquerade, and start the PBX
08431     * at the new location */
08432    tmpvars.accountcode = ast_strdupa(chan->accountcode);
08433    tmpvars.exten = ast_strdupa(chan->exten);
08434    tmpvars.context = ast_strdupa(chan->context);
08435    tmpvars.linkedid = ast_strdupa(chan->linkedid);
08436    tmpvars.name = ast_strdupa(chan->name);
08437    tmpvars.amaflags = chan->amaflags;
08438    tmpvars.state = chan->_state;
08439    tmpvars.writeformat = chan->writeformat;
08440    tmpvars.readformat = chan->readformat;
08441    tmpvars.cdr = chan->cdr ? ast_cdr_dup(chan->cdr) : NULL;
08442 
08443    ast_channel_unlock(chan);
08444 
08445    /* Do not hold any channel locks while calling channel_alloc() since the function
08446     * locks the channel container when linking the new channel in. */
08447    if (!(tmpchan = ast_channel_alloc(0, tmpvars.state, 0, 0, tmpvars.accountcode, tmpvars.exten, tmpvars.context, tmpvars.linkedid, tmpvars.amaflags, "AsyncGoto/%s", tmpvars.name))) {
08448       ast_cdr_discard(tmpvars.cdr);
08449       return -1;
08450    }
08451 
08452    /* copy the cdr info over */
08453    if (tmpvars.cdr) {
08454       ast_cdr_discard(tmpchan->cdr);
08455       tmpchan->cdr = tmpvars.cdr;
08456       tmpvars.cdr = NULL;
08457    }
08458 
08459    /* Make formats okay */
08460    tmpchan->readformat = tmpvars.readformat;
08461    tmpchan->writeformat = tmpvars.writeformat;
08462 
08463    /* Setup proper location. Never hold another channel lock while calling this function. */
08464    ast_explicit_goto(tmpchan, S_OR(context, tmpvars.context), S_OR(exten, tmpvars.exten), priority);
08465 
08466    /* Masquerade into tmp channel */
08467    if (ast_channel_masquerade(tmpchan, chan)) {
08468       /* Failed to set up the masquerade.  It's probably chan_local
08469        * in the middle of optimizing itself out.  Sad. :( */
08470       ast_hangup(tmpchan);
08471       tmpchan = NULL;
08472       res = -1;
08473    } else {
08474       ast_do_masquerade(tmpchan);
08475       /* Start the PBX going on our stolen channel */
08476       if (ast_pbx_start(tmpchan)) {
08477          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name);
08478          ast_hangup(tmpchan);
08479          res = -1;
08480       }
08481    }
08482 
08483    return res;
08484 }

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

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

08487 {
08488    struct ast_channel *chan;
08489    int res = -1;
08490 
08491    if ((chan = ast_channel_get_by_name(channame))) {
08492       res = ast_async_goto(chan, context, exten, priority);
08493       chan = ast_channel_unref(chan);
08494    }
08495 
08496    return res;
08497 }

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

References __ast_goto_if_exists().

10847 {
10848    return __ast_goto_if_exists(chan, context, exten, priority, 1);
10849 }

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

References pbx_parseable_goto().

Referenced by asyncgoto_exec(), and handle_redirect().

10912 {
10913    return pbx_parseable_goto(chan, goto_string, 1);
10914 }

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

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

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

07988 {
07989    char *info;
07990    int j, num_fields, last_sep = -1;
07991 
07992    /* Check for empty just in case */
07993    if (ast_strlen_zero(info_in)) {
07994       return 0;
07995    }
07996 
07997    /* make a copy just in case we were passed a static string */
07998    info = ast_strdupa(info_in);
07999 
08000    /* count the number of fields in the timespec */
08001    for (j = 0, num_fields = 1; info[j] != '\0'; j++) {
08002       if (info[j] == ',') {
08003          last_sep = j;
08004          num_fields++;
08005       }
08006    }
08007 
08008    /* save the timezone, if it is specified */
08009    if (num_fields == 5) {
08010       i->timezone = ast_strdup(info + last_sep + 1);
08011    } else {
08012       i->timezone = NULL;
08013    }
08014 
08015    /* Assume everything except time */
08016    i->monthmask = 0xfff;   /* 12 bits */
08017    i->daymask = 0x7fffffffU; /* 31 bits */
08018    i->dowmask = 0x7f; /* 7 bits */
08019    /* on each call, use strsep() to move info to the next argument */
08020    get_timerange(i, strsep(&info, "|,"));
08021    if (info)
08022       i->dowmask = get_range(strsep(&info, "|,"), 7, days, "day of week");
08023    if (info)
08024       i->daymask = get_range(strsep(&info, "|,"), 31, NULL, "day");
08025    if (info)
08026       i->monthmask = get_range(strsep(&info, "|,"), 12, months, "month");
08027    return 1;
08028 }

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

References E_CANMATCH, and pbx_extension_helper().

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

05116 {
05117    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0);
05118 }

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

Change hint for an extension.

Definition at line 5028 of file pbx.c.

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

Referenced by add_priority().

05029 {
05030    struct ast_hint *hint;
05031 
05032    if (!oe || !ne) {
05033       return -1;
05034    }
05035 
05036    ao2_lock(hints);/* Locked to hold off others while we move the hint around. */
05037 
05038    /*
05039     * Unlink the hint from the hints container as the extension
05040     * name (which is the hash value) could change.
05041     */
05042    hint = ao2_find(hints, oe, OBJ_UNLINK);
05043    if (!hint) {
05044       ao2_unlock(hints);
05045       return -1;
05046    }
05047 
05048    /* Update the hint and put it back in the hints container. */
05049    ao2_lock(hint);
05050    hint->exten = ne;
05051    ao2_unlock(hint);
05052    ao2_link(hints, hint);
05053 
05054    ao2_unlock(hints);
05055    ao2_ref(hint, -1);
05056 
05057    return 0;
05058 }

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

References ast_check_timing2(), and ast_tvnow().

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

08031 {
08032    return ast_check_timing2(i, ast_tvnow());
08033 }

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

08036 {
08037    struct ast_tm tm;
08038 
08039    ast_localtime(&tv, &tm, i->timezone);
08040 
08041    /* If it's not the right month, return */
08042    if (!(i->monthmask & (1 << tm.tm_mon)))
08043       return 0;
08044 
08045    /* If it's not that time of the month.... */
08046    /* Warning, tm_mday has range 1..31! */
08047    if (!(i->daymask & (1 << (tm.tm_mday-1))))
08048       return 0;
08049 
08050    /* If it's not the right day of the week */
08051    if (!(i->dowmask & (1 << tm.tm_wday)))
08052       return 0;
08053 
08054    /* Sanity check the hour just to be safe */
08055    if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) {
08056       ast_log(LOG_WARNING, "Insane time...\n");
08057       return 0;
08058    }
08059 
08060    /* Now the tough part, we calculate if it fits
08061       in the right time based on min/hour */
08062    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))))
08063       return 0;
08064 
08065    /* If we got this far, then we're good */
08066    return 1;
08067 }

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

10917 {
10918    struct ast_app *app = NULL;
10919    int which = 0;
10920    char *ret = NULL;
10921    size_t wordlen = strlen(word);
10922 
10923    AST_RWLIST_RDLOCK(&apps);
10924    AST_RWLIST_TRAVERSE(&apps, app, list) {
10925       if (!strncasecmp(word, app->name, wordlen) && ++which > state) {
10926          ret = ast_strdup(app->name);
10927          break;
10928       }
10929    }
10930    AST_RWLIST_UNLOCK(&apps);
10931 
10932    return ret;
10933 }

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

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

Referenced by handle_cli_dialplan_add_ignorepat().

08272 {
08273    int ret = -1;
08274    struct ast_context *c;
08275 
08276    c = find_context_locked(context);
08277    if (c) {
08278       ret = ast_context_add_ignorepat2(c, value, registrar);
08279       ast_unlock_contexts();
08280    }
08281    return ret;
08282 }

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

Definition at line 8284 of file pbx.c.

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

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

08285 {
08286    struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL;
08287    int length;
08288    char *pattern;
08289    length = sizeof(struct ast_ignorepat);
08290    length += strlen(value) + 1;
08291    if (!(ignorepat = ast_calloc(1, length)))
08292       return -1;
08293    /* The cast to char * is because we need to write the initial value.
08294     * The field is not supposed to be modified otherwise.  Also, gcc 4.2
08295     * sees the cast as dereferencing a type-punned pointer and warns about
08296     * it.  This is the workaround (we're telling gcc, yes, that's really
08297     * what we wanted to do).
08298     */
08299    pattern = (char *) ignorepat->pattern;
08300    strcpy(pattern, value);
08301    ignorepat->next = NULL;
08302    ignorepat->registrar = registrar;
08303    ast_wrlock_context(con);
08304    for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) {
08305       ignorepatl = ignorepatc;
08306       if (!strcasecmp(ignorepatc->pattern, value)) {
08307          /* Already there */
08308          ast_unlock_context(con);
08309          ast_free(ignorepat);
08310          errno = EEXIST;
08311          return -1;
08312       }
08313    }
08314    if (ignorepatl)
08315       ignorepatl->next = ignorepat;
08316    else
08317       con->ignorepats = ignorepat;
08318    ast_unlock_context(con);
08319    return 0;
08320 
08321 }

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

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

Referenced by handle_cli_dialplan_add_include().

07816 {
07817    int ret = -1;
07818    struct ast_context *c;
07819 
07820    c = find_context_locked(context);
07821    if (c) {
07822       ret = ast_context_add_include2(c, include, registrar);
07823       ast_unlock_contexts();
07824    }
07825    return ret;
07826 }

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

08086 {
08087    struct ast_include *new_include;
08088    char *c;
08089    struct ast_include *i, *il = NULL; /* include, include_last */
08090    int length;
08091    char *p;
08092 
08093    length = sizeof(struct ast_include);
08094    length += 2 * (strlen(value) + 1);
08095 
08096    /* allocate new include structure ... */
08097    if (!(new_include = ast_calloc(1, length)))
08098       return -1;
08099    /* Fill in this structure. Use 'p' for assignments, as the fields
08100     * in the structure are 'const char *'
08101     */
08102    p = new_include->stuff;
08103    new_include->name = p;
08104    strcpy(p, value);
08105    p += strlen(value) + 1;
08106    new_include->rname = p;
08107    strcpy(p, value);
08108    /* Strip off timing info, and process if it is there */
08109    if ( (c = strchr(p, ',')) ) {
08110       *c++ = '\0';
08111       new_include->hastime = ast_build_timing(&(new_include->timing), c);
08112    }
08113    new_include->next      = NULL;
08114    new_include->registrar = registrar;
08115 
08116    ast_wrlock_context(con);
08117 
08118    /* ... go to last include and check if context is already included too... */
08119    for (i = con->includes; i; i = i->next) {
08120       if (!strcasecmp(i->name, new_include->name)) {
08121          ast_destroy_timing(&(new_include->timing));
08122          ast_free(new_include);
08123          ast_unlock_context(con);
08124          errno = EEXIST;
08125          return -1;
08126       }
08127       il = i;
08128    }
08129 
08130    /* ... include new context into context list, unlock, return */
08131    if (il)
08132       il->next = new_include;
08133    else
08134       con->includes = new_include;
08135    ast_verb(3, "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con));
08136 
08137    ast_unlock_context(con);
08138 
08139    return 0;
08140 }

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

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

08148 {
08149    int ret = -1;
08150    struct ast_context *c;
08151 
08152    c = find_context_locked(context);
08153    if (c) { /* found, add switch to this context */
08154       ret = ast_context_add_switch2(c, sw, data, eval, registrar);
08155       ast_unlock_contexts();
08156    }
08157    return ret;
08158 }

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

08169 {
08170    struct ast_sw *new_sw;
08171    struct ast_sw *i;
08172    int length;
08173    char *p;
08174 
08175    length = sizeof(struct ast_sw);
08176    length += strlen(value) + 1;
08177    if (data)
08178       length += strlen(data);
08179    length++;
08180 
08181    /* allocate new sw structure ... */
08182    if (!(new_sw = ast_calloc(1, length)))
08183       return -1;
08184    /* ... fill in this structure ... */
08185    p = new_sw->stuff;
08186    new_sw->name = p;
08187    strcpy(new_sw->name, value);
08188    p += strlen(value) + 1;
08189    new_sw->data = p;
08190    if (data) {
08191       strcpy(new_sw->data, data);
08192       p += strlen(data) + 1;
08193    } else {
08194       strcpy(new_sw->data, "");
08195       p++;
08196    }
08197    new_sw->eval     = eval;
08198    new_sw->registrar = registrar;
08199 
08200    /* ... try to lock this context ... */
08201    ast_wrlock_context(con);
08202 
08203    /* ... go to last sw and check if context is already swd too... */
08204    AST_LIST_TRAVERSE(&con->alts, i, list) {
08205       if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) {
08206          ast_free(new_sw);
08207          ast_unlock_context(con);
08208          errno = EEXIST;
08209          return -1;
08210       }
08211    }
08212 
08213    /* ... sw new context into context list, unlock, return */
08214    AST_LIST_INSERT_TAIL(&con->alts, new_sw, list);
08215 
08216    ast_verb(3, "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con));
08217 
08218    ast_unlock_context(con);
08219 
08220    return 0;
08221 }

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

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

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

02897 {
02898    struct ast_context *tmp;
02899    struct fake_context item;
02900 
02901    if (!name) {
02902       return NULL;
02903    }
02904    ast_rdlock_contexts();
02905    if (contexts_table) {
02906       ast_copy_string(item.name, name, sizeof(item.name));
02907       tmp = ast_hashtab_lookup(contexts_table, &item);
02908    } else {
02909       tmp = NULL;
02910       while ((tmp = ast_walk_contexts(tmp))) {
02911          if (!strcasecmp(name, tmp->name)) {
02912             break;
02913          }
02914       }
02915    }
02916    ast_unlock_contexts();
02917    return tmp;
02918 }

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

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

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

07415 {
07416    struct ast_context *tmp, **local_contexts;
07417    struct fake_context search;
07418    int length = sizeof(struct ast_context) + strlen(name) + 1;
07419 
07420    if (!contexts_table) {
07421       /* Protect creation of contexts_table from reentrancy. */
07422       ast_wrlock_contexts();
07423       if (!contexts_table) {
07424          contexts_table = ast_hashtab_create(17,
07425             ast_hashtab_compare_contexts,
07426             ast_hashtab_resize_java,
07427             ast_hashtab_newsize_java,
07428             ast_hashtab_hash_contexts,
07429             0);
07430       }
07431       ast_unlock_contexts();
07432    }
07433 
07434    ast_copy_string(search.name, name, sizeof(search.name));
07435    if (!extcontexts) {
07436       ast_rdlock_contexts();
07437       local_contexts = &contexts;
07438       tmp = ast_hashtab_lookup(contexts_table, &search);
07439       ast_unlock_contexts();
07440       if (tmp) {
07441          tmp->refcount++;
07442          return tmp;
07443       }
07444    } else { /* local contexts just in a linked list; search there for the new context; slow, linear search, but not frequent */
07445       local_contexts = extcontexts;
07446       tmp = ast_hashtab_lookup(exttable, &search);
07447       if (tmp) {
07448          tmp->refcount++;
07449          return tmp;
07450       }
07451    }
07452 
07453    if ((tmp = ast_calloc(1, length))) {
07454       ast_rwlock_init(&tmp->lock);
07455       ast_mutex_init(&tmp->macrolock);
07456       strcpy(tmp->name, name);
07457       tmp->root = NULL;
07458       tmp->root_table = NULL;
07459       tmp->registrar = ast_strdup(registrar);
07460       tmp->includes = NULL;
07461       tmp->ignorepats = NULL;
07462       tmp->refcount = 1;
07463    } else {
07464       ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name);
07465       return NULL;
07466    }
07467 
07468    if (!extcontexts) {
07469       ast_wrlock_contexts();
07470       tmp->next = *local_contexts;
07471       *local_contexts = tmp;
07472       ast_hashtab_insert_safe(contexts_table, tmp); /*put this context into the tree */
07473       ast_unlock_contexts();
07474       ast_debug(1, "Registered context '%s'(%p) in table %p registrar: %s\n", tmp->name, tmp, contexts_table, registrar);
07475       ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar);
07476    } else {
07477       tmp->next = *local_contexts;
07478       if (exttable)
07479          ast_hashtab_insert_immediate(exttable, tmp); /*put this context into the tree */
07480 
07481       *local_contexts = tmp;
07482       ast_debug(1, "Registered context '%s'(%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar);
07483       ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar);
07484    }
07485    return tmp;
07486 }

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

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

Referenced by _macro_exec().

06010 {
06011    struct ast_context *c;
06012    int ret = -1;
06013 
06014    c = find_context_locked(context);
06015    if (c) {
06016       ast_unlock_contexts();
06017 
06018       /* if we found context, lock macrolock */
06019       ret = ast_mutex_lock(&c->macrolock);
06020    }
06021 
06022    return ret;
06023 }

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

05815 {
05816    return ast_context_remove_extension_callerid(context, extension, priority, NULL, 0, registrar);
05817 }

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

References ast_context_remove_extension_callerid2().

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

05845 {
05846    return ast_context_remove_extension_callerid2(con, extension, priority, NULL, 0, registrar, already_locked);
05847 }

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

05820 {
05821    int ret = -1; /* default error return */
05822    struct ast_context *c;
05823 
05824    c = find_context_locked(context);
05825    if (c) { /* ... remove extension ... */
05826       ret = ast_context_remove_extension_callerid2(c, extension, priority, callerid,
05827          matchcallerid, registrar, 0);
05828       ast_unlock_contexts();
05829    }
05830 
05831    return ret;
05832 }

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

05850 {
05851    struct ast_exten *exten, *prev_exten = NULL;
05852    struct ast_exten *peer;
05853    struct ast_exten ex, *exten2, *exten3;
05854    char dummy_name[1024];
05855    struct ast_exten *previous_peer = NULL;
05856    struct ast_exten *next_peer = NULL;
05857    int found = 0;
05858 
05859    if (!already_locked)
05860       ast_wrlock_context(con);
05861 
05862    /* Handle this is in the new world */
05863 
05864    /* FIXME For backwards compatibility, if callerid==NULL, then remove ALL
05865     * peers, not just those matching the callerid. */
05866 #ifdef NEED_DEBUG
05867    ast_verb(3,"Removing %s/%s/%d%s%s from trees, registrar=%s\n", con->name, extension, priority, matchcallerid ? "/" : "", matchcallerid ? callerid : "", registrar);
05868 #endif
05869 #ifdef CONTEXT_DEBUG
05870    check_contexts(__FILE__, __LINE__);
05871 #endif
05872    /* find this particular extension */
05873    ex.exten = dummy_name;
05874    ex.matchcid = matchcallerid && !ast_strlen_zero(callerid); /* don't say match if there's no callerid */
05875    ex.cidmatch = callerid;
05876    ast_copy_string(dummy_name, extension, sizeof(dummy_name));
05877    exten = ast_hashtab_lookup(con->root_table, &ex);
05878    if (exten) {
05879       if (priority == 0) {
05880          exten2 = ast_hashtab_remove_this_object(con->root_table, exten);
05881          if (!exten2)
05882             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);
05883          if (con->pattern_tree) {
05884             struct match_char *x = add_exten_to_pattern_tree(con, exten, 1);
05885 
05886             if (x->exten) { /* this test for safety purposes */
05887                x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */
05888                x->exten = 0; /* get rid of what will become a bad pointer */
05889             } else {
05890                ast_log(LOG_WARNING,"Trying to delete an exten from a context, but the pattern tree node returned isn't a full extension\n");
05891             }
05892          }
05893       } else {
05894          ex.priority = priority;
05895          exten2 = ast_hashtab_lookup(exten->peer_table, &ex);
05896          if (exten2) {
05897 
05898             if (exten2->label) { /* if this exten has a label, remove that, too */
05899                exten3 = ast_hashtab_remove_this_object(exten->peer_label_table,exten2);
05900                if (!exten3)
05901                   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);
05902             }
05903 
05904             exten3 = ast_hashtab_remove_this_object(exten->peer_table, exten2);
05905             if (!exten3)
05906                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);
05907             if (exten2 == exten && exten2->peer) {
05908                exten2 = ast_hashtab_remove_this_object(con->root_table, exten);
05909                ast_hashtab_insert_immediate(con->root_table, exten2->peer);
05910             }
05911             if (ast_hashtab_size(exten->peer_table) == 0) {
05912                /* well, if the last priority of an exten is to be removed,
05913                   then, the extension is removed, too! */
05914                exten3 = ast_hashtab_remove_this_object(con->root_table, exten);
05915                if (!exten3)
05916                   ast_log(LOG_ERROR,"Did not remove this exten (%s) from the context root_table (%s) (priority %d)\n", exten->exten, con->name, priority);
05917                if (con->pattern_tree) {
05918                   struct match_char *x = add_exten_to_pattern_tree(con, exten, 1);
05919                   if (x->exten) { /* this test for safety purposes */
05920                      x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */
05921                      x->exten = 0; /* get rid of what will become a bad pointer */
05922                   }
05923                }
05924             }
05925          } else {
05926             ast_log(LOG_ERROR,"Could not find priority %d of exten %s in context %s!\n",
05927                   priority, exten->exten, con->name);
05928          }
05929       }
05930    } else {
05931       /* hmmm? this exten is not in this pattern tree? */
05932       ast_log(LOG_WARNING,"Cannot find extension %s in root_table in context %s\n",
05933             extension, con->name);
05934    }
05935 #ifdef NEED_DEBUG
05936    if (con->pattern_tree) {
05937       ast_log(LOG_NOTICE,"match char tree after exten removal:\n");
05938       log_match_char_tree(con->pattern_tree, " ");
05939    }
05940 #endif
05941 
05942    /* scan the extension list to find first matching extension-registrar */
05943    for (exten = con->root; exten; prev_exten = exten, exten = exten->next) {
05944       if (!strcmp(exten->exten, extension) &&
05945          (!registrar || !strcmp(exten->registrar, registrar)) &&
05946          (!matchcallerid || (!ast_strlen_zero(callerid) && !ast_strlen_zero(exten->cidmatch) && !strcmp(exten->cidmatch, callerid)) || (ast_strlen_zero(callerid) && ast_strlen_zero(exten->cidmatch))))
05947          break;
05948    }
05949    if (!exten) {
05950       /* we can't find right extension */
05951       if (!already_locked)
05952          ast_unlock_context(con);
05953       return -1;
05954    }
05955 
05956    /* scan the priority list to remove extension with exten->priority == priority */
05957    for (peer = exten, next_peer = exten->peer ? exten->peer : exten->next;
05958        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)));
05959          peer = next_peer, next_peer = next_peer ? (next_peer->peer ? next_peer->peer : next_peer->next) : NULL) {
05960       if ((priority == 0 || peer->priority == priority) &&
05961             (!callerid || !matchcallerid || (matchcallerid && !strcmp(peer->cidmatch, callerid))) &&
05962             (!registrar || !strcmp(peer->registrar, registrar) )) {
05963          found = 1;
05964 
05965          /* we are first priority extension? */
05966          if (!previous_peer) {
05967             /*
05968              * We are first in the priority chain, so must update the extension chain.
05969              * The next node is either the next priority or the next extension
05970              */
05971             struct ast_exten *next_node = peer->peer ? peer->peer : peer->next;
05972             if (peer->peer) {
05973                /* move the peer_table and peer_label_table down to the next peer, if
05974                   it is there */
05975                peer->peer->peer_table = peer->peer_table;
05976                peer->peer->peer_label_table = peer->peer_label_table;
05977                peer->peer_table = NULL;
05978                peer->peer_label_table = NULL;
05979             }
05980             if (!prev_exten) {   /* change the root... */
05981                con->root = next_node;
05982             } else {
05983                prev_exten->next = next_node; /* unlink */
05984             }
05985             if (peer->peer)   { /* update the new head of the pri list */
05986                peer->peer->next = peer->next;
05987             }
05988          } else { /* easy, we are not first priority in extension */
05989             previous_peer->peer = peer->peer;
05990          }
05991 
05992          /* now, free whole priority extension */
05993          destroy_exten(peer);
05994       } else {
05995          previous_peer = peer;
05996       }
05997    }
05998    if (!already_locked)
05999       ast_unlock_context(con);
06000    return found ? 0 : -1;
06001 }

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

Definition at line 8227 of file pbx.c.

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

Referenced by handle_cli_dialplan_remove_ignorepat().

08228 {
08229    int ret = -1;
08230    struct ast_context *c;
08231 
08232    c = find_context_locked(context);
08233    if (c) {
08234       ret = ast_context_remove_ignorepat2(c, ignorepat, registrar);
08235       ast_unlock_contexts();
08236    }
08237    return ret;
08238 }

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

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

08241 {
08242    struct ast_ignorepat *ip, *ipl = NULL;
08243 
08244    ast_wrlock_context(con);
08245 
08246    for (ip = con->ignorepats; ip; ip = ip->next) {
08247       if (!strcmp(ip->pattern, ignorepat) &&
08248          (!registrar || (registrar == ip->registrar))) {
08249          if (ipl) {
08250             ipl->next = ip->next;
08251             ast_free(ip);
08252          } else {
08253             con->ignorepats = ip->next;
08254             ast_free(ip);
08255          }
08256          ast_unlock_context(con);
08257          return 0;
08258       }
08259       ipl = ip;
08260    }
08261 
08262    ast_unlock_context(con);
08263    errno = EINVAL;
08264    return -1;
08265 }

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

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

Referenced by handle_cli_dialplan_remove_include().

05708 {
05709    int ret = -1;
05710    struct ast_context *c;
05711 
05712    c = find_context_locked(context);
05713    if (c) {
05714       /* found, remove include from this context ... */
05715       ret = ast_context_remove_include2(c, include, registrar);
05716       ast_unlock_contexts();
05717    }
05718    return ret;
05719 }

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

05731 {
05732    struct ast_include *i, *pi = NULL;
05733    int ret = -1;
05734 
05735    ast_wrlock_context(con);
05736 
05737    /* find our include */
05738    for (i = con->includes; i; pi = i, i = i->next) {
05739       if (!strcmp(i->name, include) &&
05740             (!registrar || !strcmp(i->registrar, registrar))) {
05741          /* remove from list */
05742          ast_verb(3, "Removing inclusion of context '%s' in context '%s; registrar=%s'\n", include, ast_get_context_name(con), registrar);
05743          if (pi)
05744             pi->next = i->next;
05745          else
05746             con->includes = i->next;
05747          /* free include and return */
05748          ast_destroy_timing(&(i->timing));
05749          ast_free(i);
05750          ret = 0;
05751          break;
05752       }
05753    }
05754 
05755    ast_unlock_context(con);
05756 
05757    return ret;
05758 }

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

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

05766 {
05767    int ret = -1; /* default error return */
05768    struct ast_context *c;
05769 
05770    c = find_context_locked(context);
05771    if (c) {
05772       /* remove switch from this context ... */
05773       ret = ast_context_remove_switch2(c, sw, data, registrar);
05774       ast_unlock_contexts();
05775    }
05776    return ret;
05777 }

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

05788 {
05789    struct ast_sw *i;
05790    int ret = -1;
05791 
05792    ast_wrlock_context(con);
05793 
05794    /* walk switches */
05795    AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) {
05796       if (!strcmp(i->name, sw) && !strcmp(i->data, data) &&
05797          (!registrar || !strcmp(i->registrar, registrar))) {
05798          /* found, remove from list */
05799          ast_verb(3, "Removing switch '%s' from context '%s; registrar=%s'\n", sw, ast_get_context_name(con), registrar);
05800          AST_LIST_REMOVE_CURRENT(list);
05801          ast_free(i); /* free switch and return */
05802          ret = 0;
05803          break;
05804       }
05805    }
05806    AST_LIST_TRAVERSE_SAFE_END;
05807 
05808    ast_unlock_context(con);
05809 
05810    return ret;
05811 }

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

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

Referenced by _macro_exec().

06031 {
06032    struct ast_context *c;
06033    int ret = -1;
06034 
06035    c = find_context_locked(context);
06036    if (c) {
06037       ast_unlock_contexts();
06038 
06039       /* if we found context, unlock macrolock */
06040       ret = ast_mutex_unlock(&c->macrolock);
06041    }
06042 
06043    return ret;
06044 }

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

10802 {
10803    struct ast_include *inc = NULL;
10804    int res = 0;
10805 
10806    while ( (inc = ast_walk_context_includes(con, inc)) ) {
10807       if (ast_context_find(inc->rname))
10808          continue;
10809 
10810       res = -1;
10811       ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n",
10812          ast_get_context_name(con), inc->rname);
10813       break;
10814    }
10815 
10816    return res;
10817 }

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 3739 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(), unload_module(), and unload_pbx().

03740 {
03741    struct ast_custom_function *cur;
03742 
03743    if (!acf) {
03744       return -1;
03745    }
03746 
03747    AST_RWLIST_WRLOCK(&acf_root);
03748    if ((cur = AST_RWLIST_REMOVE(&acf_root, acf, acflist))) {
03749 #ifdef AST_XML_DOCS
03750       if (cur->docsrc == AST_XML_DOC) {
03751          ast_string_field_free_memory(acf);
03752       }
03753 #endif
03754       ast_verb(2, "Unregistered custom function %s\n", cur->name);
03755    }
03756    AST_RWLIST_UNLOCK(&acf_root);
03757 
03758    return cur ? 0 : -1;
03759 }

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

08070 {
08071    if (i->timezone) {
08072       ast_free(i->timezone);
08073       i->timezone = NULL;
08074    }
08075    return 0;
08076 }

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

04549 {
04550    switch (devstate) {
04551    case AST_DEVICE_ONHOLD:
04552       return AST_EXTENSION_ONHOLD;
04553    case AST_DEVICE_BUSY:
04554       return AST_EXTENSION_BUSY;
04555    case AST_DEVICE_UNKNOWN:
04556       return AST_EXTENSION_NOT_INUSE;
04557    case AST_DEVICE_UNAVAILABLE:
04558    case AST_DEVICE_INVALID:
04559       return AST_EXTENSION_UNAVAILABLE;
04560    case AST_DEVICE_RINGINUSE:
04561       return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING);
04562    case AST_DEVICE_RINGING:
04563       return AST_EXTENSION_RINGING;
04564    case AST_DEVICE_INUSE:
04565       return AST_EXTENSION_INUSE;
04566    case AST_DEVICE_NOT_INUSE:
04567       return AST_EXTENSION_NOT_INUSE;
04568    case AST_DEVICE_TOTAL: /* not a device state, included for completeness */
04569       break;
04570    }
04571 
04572    return AST_EXTENSION_NOT_INUSE;
04573 }

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

References E_MATCH, and pbx_extension_helper().

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

05101 {
05102    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0);
05103 }

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

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

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

08382 {
08383    if (!chan)
08384       return -1;
08385 
08386    ast_channel_lock(chan);
08387 
08388    if (!ast_strlen_zero(context))
08389       ast_copy_string(chan->context, context, sizeof(chan->context));
08390    if (!ast_strlen_zero(exten))
08391       ast_copy_string(chan->exten, exten, sizeof(chan->exten));
08392    if (priority > -1) {
08393       chan->priority = priority;
08394       /* see flag description in channel.h for explanation */
08395       if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP))
08396          chan->priority--;
08397    }
08398 
08399    ast_channel_unlock(chan);
08400 
08401    return 0;
08402 }

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

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

02874 {
02875    if (needmore != E_MATCHMORE && needmore != E_CANMATCH)
02876       ast_log(LOG_WARNING, "invalid argument %d\n", needmore);
02877    return extension_match_core(pattern, data, needmore);
02878 }

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

References ext_cmp().

Referenced by lua_extension_cmp().

02639 {
02640    int cmp;
02641 
02642    cmp = ext_cmp(a, b);
02643    if (cmp < 0) {
02644       return -1;
02645    }
02646    if (cmp > 0) {
02647       return 1;
02648    }
02649    return 0;
02650 }

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

02869 {
02870    return extension_match_core(pattern, data, E_MATCH);
02871 }

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

04619 {
04620    struct ast_exten *e;
04621 
04622    if (!(e = ast_hint_extension(c, context, exten))) {  /* Do we have a hint for this extension ? */
04623       return -1;                   /* No hint, return -1 */
04624    }
04625 
04626    if (e->exten[0] == '_') {
04627       /* Create this hint on-the-fly */
04628       ast_add_extension(e->parent->name, 0, exten, e->priority, e->label,
04629          e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr,
04630          e->registrar);
04631       if (!(e = ast_hint_extension(c, context, exten))) {
04632          /* Improbable, but not impossible */
04633          return -1;
04634       }
04635    }
04636 
04637    return ast_extension_state2(e);  /* Check all devices in the hint */
04638 }

static int ast_extension_state2 ( struct ast_exten e  )  [static]

Check state of extension by using hints.

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

04594 {
04595    struct ast_str *hint_app = ast_str_thread_get(&extensionstate_buf, 32);
04596 
04597    if (!e || !hint_app) {
04598       return -1;
04599    }
04600 
04601    ast_str_set(&hint_app, 0, "%s", ast_get_extension_app(e));
04602    return ast_extension_state3(hint_app);
04603 }

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

References ARRAY_LEN, extension_states, and cfextension_states::text.

Referenced by cb_extensionstate(), handle_request_subscribe(), handle_show_hint(), handle_show_hints(), hints_data_provider_get(), and show_channels_cb().

04607 {
04608    int i;
04609 
04610    for (i = 0; (i < ARRAY_LEN(extension_states)); i++) {
04611       if (extension_states[i].extension_state == extension_state)
04612          return extension_states[i].text;
04613    }
04614    return "Unknown";
04615 }

static int ast_extension_state3 ( struct ast_str hint_app  )  [static]

Definition at line 4575 of file pbx.c.

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

Referenced by ast_extension_state2(), and handle_statechange().

04576 {
04577    char *cur;
04578    char *rest;
04579    struct ast_devstate_aggregate agg;
04580 
04581    /* One or more devices separated with a & character */
04582    rest = ast_str_buffer(hint_app);
04583 
04584    ast_devstate_aggregate_init(&agg);
04585    while ((cur = strsep(&rest, "&"))) {
04586       ast_devstate_aggregate_add(&agg, ast_device_state(cur));
04587    }
04588 
04589    return ast_devstate_to_extenstate(ast_devstate_aggregate_result(&agg));
04590 }

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

References ast_extension_state_add_destroy().

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

04841 {
04842    return ast_extension_state_add_destroy(context, exten, change_cb, NULL, data);
04843 }

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

04754 {
04755    struct ast_hint *hint;
04756    struct ast_state_cb *state_cb;
04757    struct ast_exten *e;
04758    int id;
04759 
04760    /* If there's no context and extension:  add callback to statecbs list */
04761    if (!context && !exten) {
04762       /* Prevent multiple adds from adding the same change_cb at the same time. */
04763       ao2_lock(statecbs);
04764 
04765       /* Remove any existing change_cb. */
04766       ao2_find(statecbs, change_cb, OBJ_UNLINK | OBJ_NODATA);
04767 
04768       /* Now insert the change_cb */
04769       if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) {
04770          ao2_unlock(statecbs);
04771          return -1;
04772       }
04773       state_cb->id = 0;
04774       state_cb->change_cb = change_cb;
04775       state_cb->destroy_cb = destroy_cb;
04776       state_cb->data = data;
04777       ao2_link(statecbs, state_cb);
04778 
04779       ao2_ref(state_cb, -1);
04780       ao2_unlock(statecbs);
04781       return 0;
04782    }
04783 
04784    if (!context || !exten)
04785       return -1;
04786 
04787    /* This callback type is for only one hint, so get the hint */
04788    e = ast_hint_extension(NULL, context, exten);
04789    if (!e) {
04790       return -1;
04791    }
04792 
04793    /* If this is a pattern, dynamically create a new extension for this
04794     * particular match.  Note that this will only happen once for each
04795     * individual extension, because the pattern will no longer match first.
04796     */
04797    if (e->exten[0] == '_') {
04798       ast_add_extension(e->parent->name, 0, exten, e->priority, e->label,
04799          e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr,
04800          e->registrar);
04801       e = ast_hint_extension(NULL, context, exten);
04802       if (!e || e->exten[0] == '_') {
04803          return -1;
04804       }
04805    }
04806 
04807    /* Find the hint in the hints container */
04808    ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */
04809    hint = ao2_find(hints, e, 0);
04810    if (!hint) {
04811       ao2_unlock(hints);
04812       return -1;
04813    }
04814 
04815    /* Now insert the callback in the callback list  */
04816    if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) {
04817       ao2_ref(hint, -1);
04818       ao2_unlock(hints);
04819       return -1;
04820    }
04821    do {
04822       id = stateid++;      /* Unique ID for this callback */
04823       /* Do not allow id to ever be -1 or 0. */
04824    } while (id == -1 || id == 0);
04825    state_cb->id = id;
04826    state_cb->change_cb = change_cb; /* Pointer to callback routine */
04827    state_cb->destroy_cb = destroy_cb;
04828    state_cb->data = data;     /* Data for the callback */
04829    ao2_link(hint->callbacks, state_cb);
04830 
04831    ao2_ref(state_cb, -1);
04832    ao2_ref(hint, -1);
04833    ao2_unlock(hints);
04834 
04835    return id;
04836 }

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

04862 {
04863    struct ast_state_cb *p_cur;
04864    int ret = -1;
04865 
04866    if (!id) {  /* id == 0 is a callback without extension */
04867       if (!change_cb) {
04868          return ret;
04869       }
04870       p_cur = ao2_find(statecbs, change_cb, OBJ_UNLINK);
04871       if (p_cur) {
04872          ret = 0;
04873          ao2_ref(p_cur, -1);
04874       }
04875    } else { /* callback with extension, find the callback based on ID */
04876       struct ast_hint *hint;
04877 
04878       ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */
04879       hint = ao2_callback(hints, 0, find_hint_by_cb_id, &id);
04880       if (hint) {
04881          p_cur = ao2_find(hint->callbacks, &id, OBJ_UNLINK);
04882          if (p_cur) {
04883             ret = 0;
04884             ao2_ref(p_cur, -1);
04885          }
04886          ao2_ref(hint, -1);
04887       }
04888       ao2_unlock(hints);
04889    }
04890 
04891    return ret;
04892 }

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

05106 {
05107    return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
05108 }

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

References E_FINDLABEL, and pbx_extension_helper().

Referenced by pbx_load_config().

05111 {
05112    return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
05113 }

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

03884 {
03885    char *copy = ast_strdupa(function);
03886    char *args = func_args(copy);
03887    struct ast_custom_function *acfptr = ast_custom_function_find(copy);
03888    int res;
03889    struct ast_module_user *u = NULL;
03890 
03891    if (acfptr == NULL) {
03892       ast_log(LOG_ERROR, "Function %s not registered\n", copy);
03893    } else if (!acfptr->read && !acfptr->read2) {
03894       ast_log(LOG_ERROR, "Function %s cannot be read\n", copy);
03895    } else if (acfptr->read) {
03896       if (acfptr->mod) {
03897          u = __ast_module_user_add(acfptr->mod, chan);
03898       }
03899       res = acfptr->read(chan, copy, args, workspace, len);
03900       if (acfptr->mod && u) {
03901          __ast_module_user_remove(acfptr->mod, u);
03902       }
03903       return res;
03904    } else {
03905       struct ast_str *str = ast_str_create(16);
03906       if (acfptr->mod) {
03907          u = __ast_module_user_add(acfptr->mod, chan);
03908       }
03909       res = acfptr->read2(chan, copy, args, &str, 0);
03910       if (acfptr->mod && u) {
03911          __ast_module_user_remove(acfptr->mod, u);
03912       }
03913       ast_copy_string(workspace, ast_str_buffer(str), len > ast_str_size(str) ? ast_str_size(str) : len);
03914       ast_free(str);
03915       return res;
03916    }
03917    return -1;
03918 }

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

03921 {
03922    char *copy = ast_strdupa(function);
03923    char *args = func_args(copy);
03924    struct ast_custom_function *acfptr = ast_custom_function_find(copy);
03925    int res;
03926    struct ast_module_user *u = NULL;
03927 
03928    if (acfptr == NULL) {
03929       ast_log(LOG_ERROR, "Function %s not registered\n", copy);
03930    } else if (!acfptr->read && !acfptr->read2) {
03931       ast_log(LOG_ERROR, "Function %s cannot be read\n", copy);
03932    } else {
03933       if (acfptr->mod) {
03934          u = __ast_module_user_add(acfptr->mod, chan);
03935       }
03936       ast_str_reset(*str);
03937       if (acfptr->read2) {
03938          /* ast_str enabled */
03939          res = acfptr->read2(chan, copy, args, str, maxlen);
03940       } else {
03941          /* Legacy function pointer, allocate buffer for result */
03942          int maxsize = ast_str_size(*str);
03943          if (maxlen > -1) {
03944             if (maxlen == 0) {
03945                if (acfptr->read_max) {
03946                   maxsize = acfptr->read_max;
03947                } else {
03948                   maxsize = VAR_BUF_SIZE;
03949                }
03950             } else {
03951                maxsize = maxlen;
03952             }
03953             ast_str_make_space(str, maxsize);
03954          }
03955          res = acfptr->read(chan, copy, args, ast_str_buffer(*str), maxsize);
03956       }
03957       if (acfptr->mod && u) {
03958          __ast_module_user_remove(acfptr->mod, u);
03959       }
03960       return res;
03961    }
03962    return -1;
03963 }

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 3965 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(), pbx_builtin_pushvar_helper(), and pbx_builtin_setvar_helper().

03966 {
03967    char *copy = ast_strdupa(function);
03968    char *args = func_args(copy);
03969    struct ast_custom_function *acfptr = ast_custom_function_find(copy);
03970 
03971    if (acfptr == NULL)
03972       ast_log(LOG_ERROR, "Function %s not registered\n", copy);
03973    else if (!acfptr->write)
03974       ast_log(LOG_ERROR, "Function %s cannot be written to\n", copy);
03975    else {
03976       int res;
03977       struct ast_module_user *u = NULL;
03978       if (acfptr->mod)
03979          u = __ast_module_user_add(acfptr->mod, chan);
03980       res = acfptr->write(chan, copy, args, value);
03981       if (acfptr->mod && u)
03982          __ast_module_user_remove(acfptr->mod, u);
03983       return res;
03984    }
03985 
03986    return -1;
03987 }

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

Definition at line 10691 of file pbx.c.

References ast_context::registrar.

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

10692 {
10693    return c ? c->registrar : NULL;
10694 }

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

References ast_exten::cidmatch.

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

10717 {
10718    return e ? e->cidmatch : NULL;
10719 }

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

Definition at line 10658 of file pbx.c.

References ast_exten::parent.

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

10659 {
10660    return exten ? exten->parent : NULL;
10661 }

const char* ast_get_extension_label ( struct ast_exten exten  ) 

Definition at line 10668 of file pbx.c.

References ast_exten::label.

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

10669 {
10670    return exten ? exten->label : NULL;
10671 }

int ast_get_extension_matchcid ( struct ast_exten e  ) 

Definition at line 10711 of file pbx.c.

References ast_exten::matchcid.

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

10712 {
10713    return e ? e->matchcid : 0;
10714 }

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

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

10684 {
10685    return exten ? exten->priority : -1;
10686 }

const char* ast_get_extension_registrar ( struct ast_exten e  ) 

Definition at line 10696 of file pbx.c.

References ast_exten::registrar.

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

10697 {
10698    return e ? e->registrar : NULL;
10699 }

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

05063 {
05064    struct ast_exten *e = ast_hint_extension(c, context, exten);
05065 
05066    if (e) {
05067       if (hint)
05068          ast_copy_string(hint, ast_get_extension_app(e), hintsize);
05069       if (name) {
05070          const char *tmp = ast_get_extension_app_data(e);
05071          if (tmp)
05072             ast_copy_string(name, tmp, namesize);
05073       }
05074       return -1;
05075    }
05076    return 0;
05077 }

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

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

10707 {
10708    return ip ? ip->registrar : NULL;
10709 }

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

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

10702 {
10703    return i ? i->registrar : NULL;
10704 }

const char* ast_get_switch_data ( struct ast_sw sw  ) 

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

10737 {
10738    return sw ? sw->data : NULL;
10739 }

int ast_get_switch_eval ( struct ast_sw sw  ) 

Definition at line 10741 of file pbx.c.

References ast_sw::eval.

Referenced by context_merge_incls_swits_igps_other_registrars().

10742 {
10743    return sw->eval;
10744 }

const char* ast_get_switch_name ( struct ast_sw sw  ) 

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

10732 {
10733    return sw ? sw->name : NULL;
10734 }

const char* ast_get_switch_registrar ( struct ast_sw sw  ) 

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

10747 {
10748    return sw ? sw->registrar : NULL;
10749 }

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

References __ast_goto_if_exists().

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

10842 {
10843    return __ast_goto_if_exists(chan, context, exten, priority, 0);
10844 }

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

hashtable functions for contexts

Definition at line 1081 of file pbx.c.

References ast_context::name.

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

01082 {
01083    const struct ast_context *ac = ah_a;
01084    const struct ast_context *bc = ah_b;
01085    if (!ac || !bc) /* safety valve, but it might prevent a crash you'd rather have happen */
01086       return 1;
01087    /* assume context names are registered in a string table! */
01088    return strcmp(ac->name, bc->name);
01089 }

unsigned int ast_hashtab_hash_contexts ( const void *  obj  ) 

Definition at line 1124 of file pbx.c.

References ast_hashtab_hash_string(), and ast_context::name.

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

01125 {
01126    const struct ast_context *ac = obj;
01127    return ast_hashtab_hash_string(ac->name);
01128 }

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

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

04540 {
04541    struct ast_exten *e;
04542    ast_rdlock_contexts();
04543    e = ast_hint_extension_nolock(c, context, exten);
04544    ast_unlock_contexts();
04545    return e;
04546 }

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

04534 {
04535    struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */
04536    return pbx_find_extension(c, NULL, &q, context, exten, PRIORITY_HINT, NULL, "", E_MATCH);
04537 }

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

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

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

08324 {
08325    struct ast_context *con = ast_context_find(context);
08326 
08327    if (con) {
08328       struct ast_ignorepat *pat;
08329 
08330       for (pat = con->ignorepats; pat; pat = pat->next) {
08331          if (ast_extension_match(pat->pattern, pattern))
08332             return 1;
08333       }
08334    }
08335 
08336    return 0;
08337 }

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

References E_MATCHMORE, and pbx_extension_helper().

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

05121 {
05122    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0);
05123 }

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

07621 {
07622    double ft;
07623    struct ast_context *tmp;
07624    struct ast_context *oldcontextslist;
07625    struct ast_hashtab *oldtable;
07626    struct store_hints hints_stored = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
07627    struct store_hints hints_removed = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
07628    struct store_hint *saved_hint;
07629    struct ast_hint *hint;
07630    struct ast_exten *exten;
07631    int length;
07632    struct ast_state_cb *thiscb;
07633    struct ast_hashtab_iter *iter;
07634    struct ao2_iterator i;
07635    struct timeval begintime;
07636    struct timeval writelocktime;
07637    struct timeval endlocktime;
07638    struct timeval enddeltime;
07639 
07640    /*
07641     * It is very important that this function hold the hints
07642     * container lock _and_ the conlock during its operation; not
07643     * only do we need to ensure that the list of contexts and
07644     * extensions does not change, but also that no hint callbacks
07645     * (watchers) are added or removed during the merge/delete
07646     * process
07647     *
07648     * In addition, the locks _must_ be taken in this order, because
07649     * there are already other code paths that use this order
07650     */
07651 
07652    begintime = ast_tvnow();
07653    ast_mutex_lock(&context_merge_lock);/* Serialize ast_merge_contexts_and_delete */
07654    ast_wrlock_contexts();
07655    iter = ast_hashtab_start_traversal(contexts_table);
07656    while ((tmp = ast_hashtab_next(iter))) {
07657       context_merge(extcontexts, exttable, tmp, registrar);
07658    }
07659    ast_hashtab_end_traversal(iter);
07660 
07661    ao2_lock(hints);
07662    writelocktime = ast_tvnow();
07663 
07664    /* preserve all watchers for hints */
07665    i = ao2_iterator_init(hints, AO2_ITERATOR_DONTLOCK);
07666    for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
07667       if (ao2_container_count(hint->callbacks)) {
07668          ao2_lock(hint);
07669          if (!hint->exten) {
07670             /* The extension has already been destroyed. (Should never happen here) */
07671             ao2_unlock(hint);
07672             continue;
07673          }
07674 
07675          length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2
07676             + sizeof(*saved_hint);
07677          if (!(saved_hint = ast_calloc(1, length))) {
07678             ao2_unlock(hint);
07679             continue;
07680          }
07681 
07682          /* This removes all the callbacks from the hint into saved_hint. */
07683          while ((thiscb = ao2_callback(hint->callbacks, OBJ_UNLINK, NULL, NULL))) {
07684             AST_LIST_INSERT_TAIL(&saved_hint->callbacks, thiscb, entry);
07685             /*
07686              * We intentionally do not unref thiscb to account for the
07687              * non-ao2 reference in saved_hint->callbacks
07688              */
07689          }
07690 
07691          saved_hint->laststate = hint->laststate;
07692          saved_hint->context = saved_hint->data;
07693          strcpy(saved_hint->data, hint->exten->parent->name);
07694          saved_hint->exten = saved_hint->data + strlen(saved_hint->context) + 1;
07695          strcpy(saved_hint->exten, hint->exten->exten);
07696          ao2_unlock(hint);
07697          AST_LIST_INSERT_HEAD(&hints_stored, saved_hint, list);
07698       }
07699    }
07700    ao2_iterator_destroy(&i);
07701 
07702    /* save the old table and list */
07703    oldtable = contexts_table;
07704    oldcontextslist = contexts;
07705 
07706    /* move in the new table and list */
07707    contexts_table = exttable;
07708    contexts = *extcontexts;
07709 
07710    /*
07711     * Restore the watchers for hints that can be found; notify
07712     * those that cannot be restored.
07713     */
07714    while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_stored, list))) {
07715       struct pbx_find_info q = { .stacklen = 0 };
07716 
07717       exten = pbx_find_extension(NULL, NULL, &q, saved_hint->context, saved_hint->exten,
07718          PRIORITY_HINT, NULL, "", E_MATCH);
07719       /*
07720        * If this is a pattern, dynamically create a new extension for this
07721        * particular match.  Note that this will only happen once for each
07722        * individual extension, because the pattern will no longer match first.
07723        */
07724       if (exten && exten->exten[0] == '_') {
07725          ast_add_extension_nolock(exten->parent->name, 0, saved_hint->exten,
07726             PRIORITY_HINT, NULL, 0, exten->app, ast_strdup(exten->data), ast_free_ptr,
07727             exten->registrar);
07728          /* rwlocks are not recursive locks */
07729          exten = ast_hint_extension_nolock(NULL, saved_hint->context,
07730             saved_hint->exten);
07731       }
07732 
07733       /* Find the hint in the hints container */
07734       hint = exten ? ao2_find(hints, exten, 0) : NULL;
07735       if (!hint) {
07736          /*
07737           * Notify watchers of this removed hint later when we aren't
07738           * encumberd by so many locks.
07739           */
07740          AST_LIST_INSERT_HEAD(&hints_removed, saved_hint, list);
07741       } else {
07742          ao2_lock(hint);
07743          while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) {
07744             ao2_link(hint->callbacks, thiscb);
07745             /* Ref that we added when putting into saved_hint->callbacks */
07746             ao2_ref(thiscb, -1);
07747          }
07748          hint->laststate = saved_hint->laststate;
07749          ao2_unlock(hint);
07750          ao2_ref(hint, -1);
07751          ast_free(saved_hint);
07752       }
07753    }
07754 
07755    ao2_unlock(hints);
07756    ast_unlock_contexts();
07757 
07758    /*
07759     * Notify watchers of all removed hints with the same lock
07760     * environment as handle_statechange().
07761     */
07762    while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_removed, list))) {
07763       /* this hint has been removed, notify the watchers */
07764       while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) {
07765          thiscb->change_cb(saved_hint->context, saved_hint->exten,
07766             AST_EXTENSION_REMOVED, thiscb->data);
07767          /* Ref that we added when putting into saved_hint->callbacks */
07768          ao2_ref(thiscb, -1);
07769       }
07770       ast_free(saved_hint);
07771    }
07772 
07773    ast_mutex_unlock(&context_merge_lock);
07774    endlocktime = ast_tvnow();
07775 
07776    /*
07777     * The old list and hashtab no longer are relevant, delete them
07778     * while the rest of asterisk is now freely using the new stuff
07779     * instead.
07780     */
07781 
07782    ast_hashtab_destroy(oldtable, NULL);
07783 
07784    for (tmp = oldcontextslist; tmp; ) {
07785       struct ast_context *next;  /* next starting point */
07786 
07787       next = tmp->next;
07788       __ast_internal_context_destroy(tmp);
07789       tmp = next;
07790    }
07791    enddeltime = ast_tvnow();
07792 
07793    ft = ast_tvdiff_us(writelocktime, begintime);
07794    ft /= 1000000.0;
07795    ast_verb(3,"Time to scan old dialplan and merge leftovers back into the new: %8.6f sec\n", ft);
07796 
07797    ft = ast_tvdiff_us(endlocktime, writelocktime);
07798    ft /= 1000000.0;
07799    ast_verb(3,"Time to restore hints and swap in new dialplan: %8.6f sec\n", ft);
07800 
07801    ft = ast_tvdiff_us(enddeltime, endlocktime);
07802    ft /= 1000000.0;
07803    ast_verb(3,"Time to delete the old dialplan: %8.6f sec\n", ft);
07804 
07805    ft = ast_tvdiff_us(enddeltime, begintime);
07806    ft /= 1000000.0;
07807    ast_verb(3,"Total time merge_contexts_delete: %8.6f sec\n", ft);
07808 }

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

10907 {
10908    return pbx_parseable_goto(chan, goto_string, 0);
10909 }

int ast_pbx_init ( void   ) 

Provided by pbx.c

Definition at line 10983 of file pbx.c.

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

Referenced by main().

10984 {
10985    hints = ao2_container_alloc(HASH_EXTENHINT_SIZE, hint_hash, hint_cmp);
10986    statecbs = ao2_container_alloc(1, NULL, statecbs_cmp);
10987 
10988    ast_register_atexit(pbx_shutdown);
10989 
10990    return (hints && statecbs) ? 0 : -1;
10991 }

int ast_pbx_outgoing_app ( const char *  type,
format_t  format,
void *  data,
int  timeout,
const char *  app,
const char *  appdata,
int *  reason,
int  sync,
const char *  cid_num,
const char *  cid_name,
struct ast_variable vars,
const char *  account,
struct ast_channel **  locked_channel 
)

Synchronously or asynchronously make an outbound call and send it to a particular application with given extension

Definition at line 9217 of file pbx.c.

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

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

09218 {
09219    struct ast_channel *chan;
09220    struct app_tmp *tmp;
09221    int res = -1, cdr_res = -1;
09222    struct outgoing_helper oh;
09223 
09224    memset(&oh, 0, sizeof(oh));
09225    oh.vars = vars;
09226    oh.account = account;
09227 
09228    if (locked_channel)
09229       *locked_channel = NULL;
09230    if (ast_strlen_zero(app)) {
09231       res = -1;
09232       goto outgoing_app_cleanup;
09233    }
09234    if (synchronous) {
09235       chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh);
09236       if (chan) {
09237          ast_set_variables(chan, vars);
09238          if (account)
09239             ast_cdr_setaccount(chan, account);
09240          if (chan->_state == AST_STATE_UP) {
09241             res = 0;
09242             ast_verb(4, "Channel %s was answered.\n", chan->name);
09243             tmp = ast_calloc(1, sizeof(*tmp));
09244             if (!tmp || ast_string_field_init(tmp, 252)) {
09245                if (tmp) {
09246                   ast_free(tmp);
09247                }
09248                res = -1;
09249             } else {
09250                ast_string_field_set(tmp, app, app);
09251                ast_string_field_set(tmp, data, appdata);
09252                tmp->chan = chan;
09253                if (synchronous > 1) {
09254                   if (locked_channel)
09255                      ast_channel_unlock(chan);
09256                   ast_pbx_run_app(tmp);
09257                } else {
09258                   if (locked_channel)
09259                      ast_channel_lock(chan);
09260                   if (ast_pthread_create_detached(&tmp->t, NULL, ast_pbx_run_app, tmp)) {
09261                      ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno));
09262                      ast_string_field_free_memory(tmp);
09263                      ast_free(tmp);
09264                      if (locked_channel)
09265                         ast_channel_unlock(chan);
09266                      ast_hangup(chan);
09267                      res = -1;
09268                   } else {
09269                      if (locked_channel)
09270                         *locked_channel = chan;
09271                   }
09272                }
09273             }
09274          } else {
09275             ast_verb(4, "Channel %s was never answered.\n", chan->name);
09276             if (chan->cdr) { /* update the cdr */
09277                /* here we update the status of the call, which sould be busy.
09278                 * if that fails then we set the status to failed */
09279                if (ast_cdr_disposition(chan->cdr, chan->hangupcause))
09280                   ast_cdr_failed(chan->cdr);
09281             }
09282             ast_hangup(chan);
09283          }
09284       }
09285 
09286       if (res < 0) { /* the call failed for some reason */
09287          if (*reason == 0) { /* if the call failed (not busy or no answer)
09288                         * update the cdr with the failed message */
09289             cdr_res = ast_pbx_outgoing_cdr_failed();
09290             if (cdr_res != 0) {
09291                res = cdr_res;
09292                goto outgoing_app_cleanup;
09293             }
09294          }
09295       }
09296 
09297    } else {
09298       struct async_stat *as;
09299       if (!(as = ast_calloc(1, sizeof(*as)))) {
09300          res = -1;
09301          goto outgoing_app_cleanup;
09302       }
09303       chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh);
09304       if (!chan) {
09305          ast_free(as);
09306          res = -1;
09307          goto outgoing_app_cleanup;
09308       }
09309       as->chan = chan;
09310       ast_copy_string(as->app, app, sizeof(as->app));
09311       if (appdata)
09312          ast_copy_string(as->appdata,  appdata, sizeof(as->appdata));
09313       as->timeout = timeout;
09314       ast_set_variables(chan, vars);
09315       if (account)
09316          ast_cdr_setaccount(chan, account);
09317       /* Start a new thread, and get something handling this channel. */
09318       if (locked_channel)
09319          ast_channel_lock(chan);
09320       if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) {
09321          ast_log(LOG_WARNING, "Failed to start async wait\n");
09322          ast_free(as);
09323          if (locked_channel)
09324             ast_channel_unlock(chan);
09325          ast_hangup(chan);
09326          res = -1;
09327          goto outgoing_app_cleanup;
09328       } else {
09329          if (locked_channel)
09330             *locked_channel = chan;
09331       }
09332       res = 0;
09333    }
09334 outgoing_app_cleanup:
09335    ast_variables_destroy(vars);
09336    return res;
09337 }

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

09022 {
09023    /* allocate a channel */
09024    struct ast_channel *chan = ast_dummy_channel_alloc();
09025 
09026    if (!chan)
09027       return -1;  /* failure */
09028 
09029    chan->cdr = ast_cdr_alloc();
09030    if (!chan->cdr) {
09031       /* allocation of the cdr failed */
09032       chan = ast_channel_unref(chan);   /* free the channel */
09033       return -1;                /* return failure */
09034    }
09035 
09036    /* allocation of the cdr was successful */
09037    ast_cdr_init(chan->cdr, chan);  /* initialize our channel's cdr */
09038    ast_cdr_start(chan->cdr);       /* record the start and stop time */
09039    ast_cdr_end(chan->cdr);
09040    ast_cdr_failed(chan->cdr);      /* set the status to failed */
09041    ast_cdr_detach(chan->cdr);      /* post and free the record */
09042    chan->cdr = NULL;
09043    chan = ast_channel_unref(chan);         /* free the channel */
09044 
09045    return 0;  /* success */
09046 }

int ast_pbx_outgoing_exten ( const char *  type,
format_t  format,
void *  data,
int  timeout,
const char *  context,
const char *  exten,
int  priority,
int *  reason,
int  sync,
const char *  cid_num,
const char *  cid_name,
struct ast_variable vars,
const char *  account,
struct ast_channel **  locked_channel 
)

Synchronously or asynchronously make an outbound call and send it to a particular extension

Definition at line 9048 of file pbx.c.

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

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

09049 {
09050    struct ast_channel *chan;
09051    struct async_stat *as;
09052    int res = -1, cdr_res = -1;
09053    struct outgoing_helper oh;
09054 
09055    if (synchronous) {
09056       oh.context = context;
09057       oh.exten = exten;
09058       oh.priority = priority;
09059       oh.cid_num = cid_num;
09060       oh.cid_name = cid_name;
09061       oh.account = account;
09062       oh.vars = vars;
09063       oh.parent_channel = NULL;
09064 
09065       chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh);
09066       if (channel) {
09067          *channel = chan;
09068          if (chan)
09069             ast_channel_lock(chan);
09070       }
09071       if (chan) {
09072          if (chan->_state == AST_STATE_UP) {
09073                res = 0;
09074             ast_verb(4, "Channel %s was answered.\n", chan->name);
09075 
09076             if (synchronous > 1) {
09077                if (channel)
09078                   ast_channel_unlock(chan);
09079                if (ast_pbx_run(chan)) {
09080                   ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name);
09081                   if (channel)
09082                      *channel = NULL;
09083                   ast_hangup(chan);
09084                   chan = NULL;
09085                   res = -1;
09086                }
09087             } else {
09088                if (ast_pbx_start(chan)) {
09089                   ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name);
09090                   if (channel) {
09091                      *channel = NULL;
09092                      ast_channel_unlock(chan);
09093                   }
09094                   ast_hangup(chan);
09095                   res = -1;
09096                }
09097                chan = NULL;
09098             }
09099          } else {
09100             ast_verb(4, "Channel %s was never answered.\n", chan->name);
09101 
09102             if (chan->cdr) { /* update the cdr */
09103                /* here we update the status of the call, which sould be busy.
09104                 * if that fails then we set the status to failed */
09105                if (ast_cdr_disposition(chan->cdr, chan->hangupcause))
09106                   ast_cdr_failed(chan->cdr);
09107             }
09108 
09109             if (channel) {
09110                *channel = NULL;
09111                ast_channel_unlock(chan);
09112             }
09113             ast_hangup(chan);
09114             chan = NULL;
09115          }
09116       }
09117 
09118       if (res < 0) { /* the call failed for some reason */
09119          if (*reason == 0) { /* if the call failed (not busy or no answer)
09120                         * update the cdr with the failed message */
09121             cdr_res = ast_pbx_outgoing_cdr_failed();
09122             if (cdr_res != 0) {
09123                res = cdr_res;
09124                goto outgoing_exten_cleanup;
09125             }
09126          }
09127 
09128          /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */
09129          /* check if "failed" exists */
09130          if (ast_exists_extension(chan, context, "failed", 1, NULL)) {
09131             chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", NULL, 0, "OutgoingSpoolFailed");
09132             if (chan) {
09133                char failed_reason[4] = "";
09134                if (!ast_strlen_zero(context))
09135                   ast_copy_string(chan->context, context, sizeof(chan->context));
09136                set_ext_pri(chan, "failed", 1);
09137                ast_set_variables(chan, vars);
09138                snprintf(failed_reason, sizeof(failed_reason), "%d", *reason);
09139                pbx_builtin_setvar_helper(chan, "REASON", failed_reason);
09140                if (account)
09141                   ast_cdr_setaccount(chan, account);
09142                if (ast_pbx_run(chan)) {
09143                   ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name);
09144                   ast_hangup(chan);
09145                }
09146                chan = NULL;
09147             }
09148          }
09149       }
09150    } else {
09151       if (!(as = ast_calloc(1, sizeof(*as)))) {
09152          res = -1;
09153          goto outgoing_exten_cleanup;
09154       }
09155       chan = ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name);
09156       if (channel) {
09157          *channel = chan;
09158          if (chan)
09159             ast_channel_lock(chan);
09160       }
09161       if (!chan) {
09162          ast_free(as);
09163          res = -1;
09164          goto outgoing_exten_cleanup;
09165       }
09166       as->chan = chan;
09167       ast_copy_string(as->context, context, sizeof(as->context));
09168       set_ext_pri(as->chan,  exten, priority);
09169       as->timeout = timeout;
09170       ast_set_variables(chan, vars);
09171       if (account)
09172          ast_cdr_setaccount(chan, account);
09173       if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) {
09174          ast_log(LOG_WARNING, "Failed to start async wait\n");
09175          ast_free(as);
09176          if (channel) {
09177             *channel = NULL;
09178             ast_channel_unlock(chan);
09179          }
09180          ast_hangup(chan);
09181          res = -1;
09182          goto outgoing_exten_cleanup;
09183       }
09184       res = 0;
09185    }
09186 outgoing_exten_cleanup:
09187    ast_variables_destroy(vars);
09188    return res;
09189 }

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

05627 {
05628    return ast_pbx_run_args(c, NULL);
05629 }

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

run the application and free the descriptor once done

Definition at line 9201 of file pbx.c.

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

Referenced by ast_pbx_outgoing_app().

09202 {
09203    struct app_tmp *tmp = data;
09204    struct ast_app *app;
09205    app = pbx_findapp(tmp->app);
09206    if (app) {
09207       ast_verb(4, "Launching %s(%s) on %s\n", tmp->app, tmp->data, tmp->chan->name);
09208       pbx_exec(tmp->chan, app, tmp->data);
09209    } else
09210       ast_log(LOG_WARNING, "No such application '%s'\n", tmp->app);
09211    ast_hangup(tmp->chan);
09212    ast_string_field_free_memory(tmp);
09213    ast_free(tmp);
09214    return NULL;
09215 }

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

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

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

05607 {
05608    enum ast_pbx_result res = AST_PBX_SUCCESS;
05609 
05610    if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) {
05611       ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n");
05612       return AST_PBX_FAILED;
05613    }
05614 
05615    if (increase_call_count(c)) {
05616       return AST_PBX_CALL_LIMIT;
05617    }
05618 
05619    res = __ast_pbx_run(c, args);
05620 
05621    decrease_call_count();
05622 
05623    return res;
05624 }

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

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

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

05580 {
05581    pthread_t t;
05582 
05583    if (!c) {
05584       ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
05585       return AST_PBX_FAILED;
05586    }
05587 
05588    if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) {
05589       ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n");
05590       return AST_PBX_FAILED;
05591    }
05592 
05593    if (increase_call_count(c))
05594       return AST_PBX_CALL_LIMIT;
05595 
05596    /* Start a new thread, and get something handling this channel. */
05597    if (ast_pthread_create_detached(&t, NULL, pbx_thread, c)) {
05598       ast_log(LOG_WARNING, "Failed to create new channel thread\n");
05599       decrease_call_count();
05600       return AST_PBX_FAILED;
05601    }
05602 
05603    return AST_PBX_SUCCESS;
05604 }

int ast_processed_calls ( void   ) 

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

Definition at line 5636 of file pbx.c.

References totalcalls.

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

05637 {
05638    return totalcalls;
05639 }

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

10641 {
10642    return ast_rwlock_rdlock(&con->lock);
10643 }

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

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

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

06048 {
06049    struct ast_app *tmp, *cur = NULL;
06050    char tmps[80];
06051    int length, res;
06052 #ifdef AST_XML_DOCS
06053    char *tmpxml;
06054 #endif
06055 
06056    AST_RWLIST_WRLOCK(&apps);
06057    AST_RWLIST_TRAVERSE(&apps, tmp, list) {
06058       if (!(res = strcasecmp(app, tmp->name))) {
06059          ast_log(LOG_WARNING, "Already have an application '%s'\n", app);
06060          AST_RWLIST_UNLOCK(&apps);
06061          return -1;
06062       } else if (res < 0)
06063          break;
06064    }
06065 
06066    length = sizeof(*tmp) + strlen(app) + 1;
06067 
06068    if (!(tmp = ast_calloc(1, length))) {
06069       AST_RWLIST_UNLOCK(&apps);
06070       return -1;
06071    }
06072 
06073    if (ast_string_field_init(tmp, 128)) {
06074       AST_RWLIST_UNLOCK(&apps);
06075       ast_free(tmp);
06076       return -1;
06077    }
06078 
06079    strcpy(tmp->name, app);
06080    tmp->execute = execute;
06081    tmp->module = mod;
06082 
06083 #ifdef AST_XML_DOCS
06084    /* Try to lookup the docs in our XML documentation database */
06085    if (ast_strlen_zero(synopsis) && ast_strlen_zero(description)) {
06086       /* load synopsis */
06087       tmpxml = ast_xmldoc_build_synopsis("application", app, ast_module_name(tmp->module));
06088       ast_string_field_set(tmp, synopsis, tmpxml);
06089       ast_free(tmpxml);
06090 
06091       /* load description */
06092       tmpxml = ast_xmldoc_build_description("application", app, ast_module_name(tmp->module));
06093       ast_string_field_set(tmp, description, tmpxml);
06094       ast_free(tmpxml);
06095 
06096       /* load syntax */
06097       tmpxml = ast_xmldoc_build_syntax("application", app, ast_module_name(tmp->module));
06098       ast_string_field_set(tmp, syntax, tmpxml);
06099       ast_free(tmpxml);
06100 
06101       /* load arguments */
06102       tmpxml = ast_xmldoc_build_arguments("application", app, ast_module_name(tmp->module));
06103       ast_string_field_set(tmp, arguments, tmpxml);
06104       ast_free(tmpxml);
06105 
06106       /* load seealso */
06107       tmpxml = ast_xmldoc_build_seealso("application", app, ast_module_name(tmp->module));
06108       ast_string_field_set(tmp, seealso, tmpxml);
06109       ast_free(tmpxml);
06110       tmp->docsrc = AST_XML_DOC;
06111    } else {
06112 #endif
06113       ast_string_field_set(tmp, synopsis, synopsis);
06114       ast_string_field_set(tmp, description, description);
06115 #ifdef AST_XML_DOCS
06116       tmp->docsrc = AST_STATIC_DOC;
06117    }
06118 #endif
06119 
06120    /* Store in alphabetical order */
06121    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, cur, list) {
06122       if (strcasecmp(tmp->name, cur->name) < 0) {
06123          AST_RWLIST_INSERT_BEFORE_CURRENT(tmp, list);
06124          break;
06125       }
06126    }
06127    AST_RWLIST_TRAVERSE_SAFE_END;
06128    if (!cur)
06129       AST_RWLIST_INSERT_TAIL(&apps, tmp, list);
06130 
06131    ast_verb(2, "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps)));
06132 
06133    AST_RWLIST_UNLOCK(&apps);
06134 
06135    return 0;
06136 }

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

06143 {
06144    struct ast_switch *tmp;
06145 
06146    AST_RWLIST_WRLOCK(&switches);
06147    AST_RWLIST_TRAVERSE(&switches, tmp, list) {
06148       if (!strcasecmp(tmp->name, sw->name)) {
06149          AST_RWLIST_UNLOCK(&switches);
06150          ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name);
06151          return -1;
06152       }
06153    }
06154    AST_RWLIST_INSERT_TAIL(&switches, sw, list);
06155    AST_RWLIST_UNLOCK(&switches);
06156 
06157    return 0;
06158 }

static int ast_remove_hint ( struct ast_exten e  )  [static]

Remove hint from extension.

Definition at line 4941 of file pbx.c.

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

Referenced by destroy_exten().

04942 {
04943    /* Cleanup the Notifys if hint is removed */
04944    struct ast_hint *hint;
04945 
04946    if (!e) {
04947       return -1;
04948    }
04949 
04950    hint = ao2_find(hints, e, OBJ_UNLINK);
04951    if (!hint) {
04952       return -1;
04953    }
04954 
04955    /*
04956     * The extension is being destroyed so we must save some
04957     * information to notify that the extension is deactivated.
04958     */
04959    ao2_lock(hint);
04960    ast_copy_string(hint->context_name,
04961       ast_get_context_name(ast_get_extension_context(hint->exten)),
04962       sizeof(hint->context_name));
04963    ast_copy_string(hint->exten_name, ast_get_extension_name(hint->exten),
04964       sizeof(hint->exten_name));
04965    hint->exten = NULL;
04966    ao2_unlock(hint);
04967 
04968    ao2_ref(hint, -1);
04969 
04970    return 0;
04971 }

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

05126 {
05127    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN, found, combined_find_spawn);
05128 }

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

05081 {
05082    struct ast_exten *e = ast_hint_extension(c, context, exten);
05083 
05084    if (!e) {
05085       return 0;
05086    }
05087 
05088    if (hint) {
05089       ast_str_set(hint, hintsize, "%s", ast_get_extension_app(e));
05090    }
05091    if (name) {
05092       const char *tmp = ast_get_extension_app_data(e);
05093       if (tmp) {
05094          ast_str_set(name, namesize, "%s", tmp);
05095       }
05096    }
05097    return -1;
05098 }

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

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

Referenced by ast_str_substitute_variables_full(), and pbx_retrieve_variable().

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

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

References ast_str_substitute_variables_full().

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

04169 {
04170    size_t used;
04171    ast_str_substitute_variables_full(buf, maxlen, chan, NULL, templ, &used);
04172 }

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

03990 {
03991    /* Substitutes variables into buf, based on string templ */
03992    char *cp4 = NULL;
03993    const char *tmp, *whereweare;
03994    int orig_size = 0;
03995    int offset, offset2, isfunction;
03996    const char *nextvar, *nextexp, *nextthing;
03997    const char *vars, *vare;
03998    char *finalvars;
03999    int pos, brackets, needsub, len;
04000    struct ast_str *substr1 = ast_str_create(16), *substr2 = NULL, *substr3 = ast_str_create(16);
04001 
04002    ast_str_reset(*buf);
04003    whereweare = tmp = templ;
04004    while (!ast_strlen_zero(whereweare)) {
04005       /* reset our buffer */
04006       ast_str_reset(substr3);
04007 
04008       /* Assume we're copying the whole remaining string */
04009       pos = strlen(whereweare);
04010       nextvar = NULL;
04011       nextexp = NULL;
04012       nextthing = strchr(whereweare, '$');
04013       if (nextthing) {
04014          switch (nextthing[1]) {
04015          case '{':
04016             nextvar = nextthing;
04017             pos = nextvar - whereweare;
04018             break;
04019          case '[':
04020             nextexp = nextthing;
04021             pos = nextexp - whereweare;
04022             break;
04023          default:
04024             pos = 1;
04025          }
04026       }
04027 
04028       if (pos) {
04029          /* Copy that many bytes */
04030          ast_str_append_substr(buf, maxlen, whereweare, pos);
04031 
04032          templ += pos;
04033          whereweare += pos;
04034       }
04035 
04036       if (nextvar) {
04037          /* We have a variable.  Find the start and end, and determine
04038             if we are going to have to recursively call ourselves on the
04039             contents */
04040          vars = vare = nextvar + 2;
04041          brackets = 1;
04042          needsub = 0;
04043 
04044          /* Find the end of it */
04045          while (brackets && *vare) {
04046             if ((vare[0] == '$') && (vare[1] == '{')) {
04047                needsub++;
04048             } else if (vare[0] == '{') {
04049                brackets++;
04050             } else if (vare[0] == '}') {
04051                brackets--;
04052             } else if ((vare[0] == '$') && (vare[1] == '['))
04053                needsub++;
04054             vare++;
04055          }
04056          if (brackets)
04057             ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n");
04058          len = vare - vars - 1;
04059 
04060          /* Skip totally over variable string */
04061          whereweare += (len + 3);
04062 
04063          /* Store variable name (and truncate) */
04064          ast_str_set_substr(&substr1, 0, vars, len);
04065          ast_debug(5, "Evaluating '%s' (from '%s' len %d)\n", ast_str_buffer(substr1), vars, len);
04066 
04067          /* Substitute if necessary */
04068          if (needsub) {
04069             size_t used;
04070             if (!substr2) {
04071                substr2 = ast_str_create(16);
04072             }
04073 
04074             ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used);
04075             finalvars = ast_str_buffer(substr2);
04076          } else {
04077             finalvars = ast_str_buffer(substr1);
04078          }
04079 
04080          parse_variable_name(finalvars, &offset, &offset2, &isfunction);
04081          if (isfunction) {
04082             /* Evaluate function */
04083             if (c || !headp) {
04084                cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3);
04085             } else {
04086                struct varshead old;
04087                struct ast_channel *bogus = ast_dummy_channel_alloc();
04088                if (bogus) {
04089                   memcpy(&old, &bogus->varshead, sizeof(old));
04090                   memcpy(&bogus->varshead, headp, sizeof(bogus->varshead));
04091                   cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3);
04092                   /* Don't deallocate the varshead that was passed in */
04093                   memcpy(&bogus->varshead, &old, sizeof(bogus->varshead));
04094                   ast_channel_unref(bogus);
04095                } else {
04096                   ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution.  Function results may be blank.\n");
04097                }
04098             }
04099             ast_debug(2, "Function result is '%s'\n", cp4 ? cp4 : "(null)");
04100          } else {
04101             /* Retrieve variable value */
04102             ast_str_retrieve_variable(&substr3, 0, c, headp, finalvars);
04103             cp4 = ast_str_buffer(substr3);
04104          }
04105          if (cp4) {
04106             ast_str_substring(substr3, offset, offset2);
04107             ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3));
04108          }
04109       } else if (nextexp) {
04110          /* We have an expression.  Find the start and end, and determine
04111             if we are going to have to recursively call ourselves on the
04112             contents */
04113          vars = vare = nextexp + 2;
04114          brackets = 1;
04115          needsub = 0;
04116 
04117          /* Find the end of it */
04118          while (brackets && *vare) {
04119             if ((vare[0] == '$') && (vare[1] == '[')) {
04120                needsub++;
04121                brackets++;
04122                vare++;
04123             } else if (vare[0] == '[') {
04124                brackets++;
04125             } else if (vare[0] == ']') {
04126                brackets--;
04127             } else if ((vare[0] == '$') && (vare[1] == '{')) {
04128                needsub++;
04129                vare++;
04130             }
04131             vare++;
04132          }
04133          if (brackets)
04134             ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n");
04135          len = vare - vars - 1;
04136 
04137          /* Skip totally over expression */
04138          whereweare += (len + 3);
04139 
04140          /* Store variable name (and truncate) */
04141          ast_str_set_substr(&substr1, 0, vars, len);
04142 
04143          /* Substitute if necessary */
04144          if (needsub) {
04145             size_t used;
04146             if (!substr2) {
04147                substr2 = ast_str_create(16);
04148             }
04149 
04150             ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used);
04151             finalvars = ast_str_buffer(substr2);
04152          } else {
04153             finalvars = ast_str_buffer(substr1);
04154          }
04155 
04156          if (ast_str_expr(&substr3, 0, c, finalvars)) {
04157             ast_debug(2, "Expression result is '%s'\n", ast_str_buffer(substr3));
04158          }
04159          ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3));
04160       }
04161    }
04162    *used = ast_str_strlen(*buf) - orig_size;
04163    ast_free(substr1);
04164    ast_free(substr2);
04165    ast_free(substr3);
04166 }

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

04175 {
04176    size_t used;
04177    ast_str_substitute_variables_full(buf, maxlen, NULL, headp, templ, &used);
04178 }

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

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

03306 {
03307    int lr;  /* length of the input string after the copy */
03308 
03309    lr = ast_str_strlen(value); /* compute length after copy, so we never go out of the workspace */
03310 
03311    /* Quick check if no need to do anything */
03312    if (offset == 0 && length >= lr) /* take the whole string */
03313       return ast_str_buffer(value);
03314 
03315    if (offset < 0)   {  /* translate negative offset into positive ones */
03316       offset = lr + offset;
03317       if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */
03318          offset = 0;
03319    }
03320 
03321    /* too large offset result in empty string so we know what to return */
03322    if (offset >= lr) {
03323       ast_str_reset(value);
03324       return ast_str_buffer(value);
03325    }
03326 
03327    if (offset > 0) {
03328       /* Go ahead and chop off the beginning */
03329       memmove(ast_str_buffer(value), ast_str_buffer(value) + offset, ast_str_strlen(value) - offset + 1);
03330       lr -= offset;
03331    }
03332 
03333    if (length >= 0 && length < lr) {   /* truncate if necessary */
03334       char *tmp = ast_str_buffer(value);
03335       tmp[length] = '\0';
03336       ast_str_update(value);
03337    } else if (length < 0) {
03338       if (lr > -length) { /* After we remove from the front and from the rear, is there anything left? */
03339          char *tmp = ast_str_buffer(value);
03340          tmp[lr + length] = '\0';
03341          ast_str_update(value);
03342       } else {
03343          ast_str_reset(value);
03344       }
03345    } else {
03346       /* Nothing to do, but update the buffer length */
03347       ast_str_update(value);
03348    }
03349 
03350    return ast_str_buffer(value);
03351 }

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

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

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

07394 {
07395    struct ast_app *tmp;
07396 
07397    AST_RWLIST_WRLOCK(&apps);
07398    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, tmp, list) {
07399       if (!strcasecmp(app, tmp->name)) {
07400          unreference_cached_app(tmp);
07401          AST_RWLIST_REMOVE_CURRENT(list);
07402          ast_verb(2, "Unregistered application '%s'\n", tmp->name);
07403          ast_string_field_free_memory(tmp);
07404          ast_free(tmp);
07405          break;
07406       }
07407    }
07408    AST_RWLIST_TRAVERSE_SAFE_END;
07409    AST_RWLIST_UNLOCK(&apps);
07410 
07411    return tmp ? 0 : -1;
07412 }

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

References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

Referenced by __unload_module(), and unload_module().

06161 {
06162    AST_RWLIST_WRLOCK(&switches);
06163    AST_RWLIST_REMOVE(&switches, sw, list);
06164    AST_RWLIST_UNLOCK(&switches);
06165 }

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

Definition at line 10759 of file pbx.c.

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

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

10761 {
10762    if (!exten)
10763       return con ? con->root : NULL;
10764    else
10765       return exten->next;
10766 }

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

Definition at line 10792 of file pbx.c.

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

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

10794 {
10795    if (!ip)
10796       return con ? con->ignorepats : NULL;
10797    else
10798       return ip->next;
10799 }

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

References ast_context::alts, AST_LIST_FIRST, and AST_LIST_NEXT.

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

10770 {
10771    if (!sw)
10772       return con ? AST_LIST_FIRST(&con->alts) : NULL;
10773    else
10774       return AST_LIST_NEXT(sw, list);
10775 }

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

10779 {
10780    return priority ? priority->peer : exten;
10781 }

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

10636 {
10637    return ast_rwlock_wrlock(&con->lock);
10638 }

int ast_wrlock_contexts ( void   ) 

Write locks the context list.

Return values:
0 on success
-1 on error

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

10618 {
10619    return ast_mutex_lock(&conlock);
10620 }

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

Definition at line 8958 of file pbx.c.

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

Referenced by ast_pbx_outgoing_app(), and ast_pbx_outgoing_exten().

08959 {
08960    struct async_stat *as = data;
08961    struct ast_channel *chan = as->chan;
08962    int timeout = as->timeout;
08963    int res;
08964    struct ast_frame *f;
08965    struct ast_app *app;
08966    struct timeval start = ast_tvnow();
08967    int ms;
08968 
08969    while ((ms = ast_remaining_ms(start, timeout)) &&
08970          chan->_state != AST_STATE_UP) {
08971       res = ast_waitfor(chan, ms);
08972       if (res < 1)
08973          break;
08974 
08975       f = ast_read(chan);
08976       if (!f)
08977          break;
08978       if (f->frametype == AST_FRAME_CONTROL) {
08979          if ((f->subclass.integer == AST_CONTROL_BUSY)  ||
08980              (f->subclass.integer == AST_CONTROL_CONGESTION) ) {
08981             ast_frfree(f);
08982             break;
08983          }
08984       }
08985       ast_frfree(f);
08986    }
08987    if (chan->_state == AST_STATE_UP) {
08988       if (!ast_strlen_zero(as->app)) {
08989          app = pbx_findapp(as->app);
08990          if (app) {
08991             ast_verb(3, "Launching %s(%s) on %s\n", as->app, as->appdata, chan->name);
08992             pbx_exec(chan, app, as->appdata);
08993          } else
08994             ast_log(LOG_WARNING, "No such application '%s'\n", as->app);
08995       } else {
08996          if (!ast_strlen_zero(as->context))
08997             ast_copy_string(chan->context, as->context, sizeof(chan->context));
08998          if (!ast_strlen_zero(as->exten))
08999             ast_copy_string(chan->exten, as->exten, sizeof(chan->exten));
09000          if (as->priority > 0)
09001             chan->priority = as->priority;
09002          /* Run the PBX */
09003          if (ast_pbx_run(chan)) {
09004             ast_log(LOG_ERROR, "Failed to start PBX on %s\n", chan->name);
09005          } else {
09006             /* PBX will have taken care of this */
09007             chan = NULL;
09008          }
09009       }
09010    }
09011    ast_free(as);
09012    if (chan)
09013       ast_hangup(chan);
09014    return NULL;
09015 }

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

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

01625 {
01626    char extenstr[40];
01627    struct ast_str *my_prefix = ast_str_alloca(1024);
01628 
01629    extenstr[0] = '\0';
01630 
01631    if (node->exten) {
01632       snprintf(extenstr, sizeof(extenstr), "(%p)", node->exten);
01633    }
01634 
01635    if (strlen(node->x) > 1) {
01636       ast_cli(fd, "%s[%s]:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N',
01637          node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "",
01638          node->exten ? node->exten->exten : "", extenstr);
01639    } else {
01640       ast_cli(fd, "%s%s:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N',
01641          node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "",
01642          node->exten ? node->exten->exten : "", extenstr);
01643    }
01644 
01645    ast_str_set(&my_prefix, 0, "%s+       ", prefix);
01646 
01647    if (node->next_char)
01648       cli_match_char_tree(node->next_char, ast_str_buffer(my_prefix), fd);
01649 
01650    if (node->alt_char)
01651       cli_match_char_tree(node->alt_char, prefix, fd);
01652 }

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

05147 {
05148    int digit;
05149 
05150    buf[pos] = '\0';  /* make sure it is properly terminated */
05151    while (ast_matchmore_extension(c, c->context, buf, 1,
05152       S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05153       /* As long as we're willing to wait, and as long as it's not defined,
05154          keep reading digits until we can't possibly get a right answer anymore.  */
05155       digit = ast_waitfordigit(c, waittime);
05156       if (c->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) {
05157          ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO);
05158       } else {
05159          if (!digit) /* No entry */
05160             break;
05161          if (digit < 0) /* Error, maybe a  hangup */
05162             return -1;
05163          if (pos < buflen - 1) { /* XXX maybe error otherwise ? */
05164             buf[pos++] = digit;
05165             buf[pos] = '\0';
05166          }
05167          waittime = c->pbx->dtimeoutms;
05168       }
05169    }
05170    return 0;
05171 }

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

Definition at line 1072 of file pbx.c.

Referenced by get_pattern_node().

01073 {
01074    const unsigned char *ac = a;
01075    const unsigned char *bc = b;
01076 
01077    return *ac - *bc;
01078 }

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

06348 {
06349    struct ast_hint *hint;
06350    char *ret = NULL;
06351    int which = 0;
06352    int wordlen;
06353    struct ao2_iterator i;
06354 
06355    if (pos != 3)
06356       return NULL;
06357 
06358    wordlen = strlen(word);
06359 
06360    /* walk through all hints */
06361    i = ao2_iterator_init(hints, 0);
06362    for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
06363       ao2_lock(hint);
06364       if (!hint->exten) {
06365          /* The extension has already been destroyed */
06366          ao2_unlock(hint);
06367          continue;
06368       }
06369       if (!strncasecmp(word, ast_get_extension_name(hint->exten), wordlen) && ++which > state) {
06370          ret = ast_strdup(ast_get_extension_name(hint->exten));
06371          ao2_unlock(hint);
06372          ao2_ref(hint, -1);
06373          break;
06374       }
06375       ao2_unlock(hint);
06376    }
06377    ao2_iterator_destroy(&i);
06378 
06379    return ret;
06380 }

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

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

06559 {
06560    struct ast_context *c = NULL;
06561    char *ret = NULL;
06562    int which = 0;
06563    int wordlen;
06564 
06565    /* we are do completion of [exten@]context on second position only */
06566    if (pos != 2)
06567       return NULL;
06568 
06569    ast_rdlock_contexts();
06570 
06571    wordlen = strlen(word);
06572 
06573    /* walk through all contexts and return the n-th match */
06574    while ( (c = ast_walk_contexts(c)) ) {
06575       if (!strncasecmp(word, ast_get_context_name(c), wordlen) && ++which > state) {
06576          ret = ast_strdup(ast_get_context_name(c));
06577          break;
06578       }
06579    }
06580 
06581    ast_unlock_contexts();
06582 
06583    return ret;
06584 }

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

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

07535 {
07536    struct ast_context *new = ast_hashtab_lookup(exttable, context); /* is there a match in the new set? */
07537    struct ast_exten *exten_item, *prio_item, *new_exten_item, *new_prio_item;
07538    struct ast_hashtab_iter *exten_iter;
07539    struct ast_hashtab_iter *prio_iter;
07540    int insert_count = 0;
07541    int first = 1;
07542 
07543    /* We'll traverse all the extensions/prios, and see which are not registrar'd with
07544       the current registrar, and copy them to the new context. If the new context does not
07545       exist, we'll create it "on demand". If no items are in this context to copy, then we'll
07546       only create the empty matching context if the old one meets the criteria */
07547 
07548    if (context->root_table) {
07549       exten_iter = ast_hashtab_start_traversal(context->root_table);
07550       while ((exten_item=ast_hashtab_next(exten_iter))) {
07551          if (new) {
07552             new_exten_item = ast_hashtab_lookup(new->root_table, exten_item);
07553          } else {
07554             new_exten_item = NULL;
07555          }
07556          prio_iter = ast_hashtab_start_traversal(exten_item->peer_table);
07557          while ((prio_item=ast_hashtab_next(prio_iter))) {
07558             int res1;
07559             char *dupdstr;
07560 
07561             if (new_exten_item) {
07562                new_prio_item = ast_hashtab_lookup(new_exten_item->peer_table, prio_item);
07563             } else {
07564                new_prio_item = NULL;
07565             }
07566             if (strcmp(prio_item->registrar,registrar) == 0) {
07567                continue;
07568             }
07569             /* make sure the new context exists, so we have somewhere to stick this exten/prio */
07570             if (!new) {
07571                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 */
07572             }
07573 
07574             /* copy in the includes, switches, and ignorepats */
07575             if (first) { /* but, only need to do this once */
07576                context_merge_incls_swits_igps_other_registrars(new, context, registrar);
07577                first = 0;
07578             }
07579 
07580             if (!new) {
07581                ast_log(LOG_ERROR,"Could not allocate a new context for %s in merge_and_delete! Danger!\n", context->name);
07582                ast_hashtab_end_traversal(prio_iter);
07583                ast_hashtab_end_traversal(exten_iter);
07584                return; /* no sense continuing. */
07585             }
07586             /* we will not replace existing entries in the new context with stuff from the old context.
07587                but, if this is because of some sort of registrar conflict, we ought to say something... */
07588 
07589             dupdstr = ast_strdup(prio_item->data);
07590 
07591             res1 = ast_add_extension2(new, 0, prio_item->exten, prio_item->priority, prio_item->label, 
07592                                 prio_item->matchcid ? prio_item->cidmatch : NULL, prio_item->app, dupdstr, prio_item->datad, prio_item->registrar);
07593             if (!res1 && new_exten_item && new_prio_item){
07594                ast_verb(3,"Dropping old dialplan item %s/%s/%d [%s(%s)] (registrar=%s) due to conflict with new dialplan\n",
07595                      context->name, prio_item->exten, prio_item->priority, prio_item->app, (char*)prio_item->data, prio_item->registrar);
07596             } else {
07597                /* 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,
07598                 and no double frees take place, either! */
07599                insert_count++;
07600             }
07601          }
07602          ast_hashtab_end_traversal(prio_iter);
07603       }
07604       ast_hashtab_end_traversal(exten_iter);
07605    }
07606 
07607    if (!insert_count && !new && (strcmp(context->registrar, registrar) != 0 ||
07608         (strcmp(context->registrar, registrar) == 0 && context->refcount > 1))) {
07609       /* we could have given it the registrar of the other module who incremented the refcount,
07610          but that's not available, so we give it the registrar we know about */
07611       new = ast_context_find_or_create(extcontexts, exttable, context->name, context->registrar);
07612 
07613       /* copy in the includes, switches, and ignorepats */
07614       context_merge_incls_swits_igps_other_registrars(new, context, registrar);
07615    }
07616 }

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

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

07502 {
07503    struct ast_include *i;
07504    struct ast_ignorepat *ip;
07505    struct ast_sw *sw;
07506 
07507    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);
07508    /* copy in the includes, switches, and ignorepats */
07509    /* walk through includes */
07510    for (i = NULL; (i = ast_walk_context_includes(old, i)) ; ) {
07511       if (strcmp(ast_get_include_registrar(i), registrar) == 0)
07512          continue; /* not mine */
07513       ast_context_add_include2(new, ast_get_include_name(i), ast_get_include_registrar(i));
07514    }
07515 
07516    /* walk through switches */
07517    for (sw = NULL; (sw = ast_walk_context_switches(old, sw)) ; ) {
07518       if (strcmp(ast_get_switch_registrar(sw), registrar) == 0)
07519          continue; /* not mine */
07520       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));
07521    }
07522 
07523    /* walk thru ignorepats ... */
07524    for (ip = NULL; (ip = ast_walk_context_ignorepats(old, ip)); ) {
07525       if (strcmp(ast_get_ignorepat_registrar(ip), registrar) == 0)
07526          continue; /* not mine */
07527       ast_context_add_ignorepat2(new, ast_get_ignorepat_name(ip), ast_get_ignorepat_registrar(ip));
07528    }
07529 }

static void create_match_char_tree ( struct ast_context con  )  [static]

Definition at line 2246 of file pbx.c.

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

Referenced by pbx_find_extension().

02247 {
02248    struct ast_hashtab_iter *t1;
02249    struct ast_exten *e1;
02250 #ifdef NEED_DEBUG
02251    int biggest_bucket, resizes, numobjs, numbucks;
02252 
02253    ast_log(LOG_DEBUG,"Creating Extension Trie for context %s(%p)\n", con->name, con);
02254    ast_hashtab_get_stats(con->root_table, &biggest_bucket, &resizes, &numobjs, &numbucks);
02255    ast_log(LOG_DEBUG,"This tree has %d objects in %d bucket lists, longest list=%d objects, and has resized %d times\n",
02256          numobjs, numbucks, biggest_bucket, resizes);
02257 #endif
02258    t1 = ast_hashtab_start_traversal(con->root_table);
02259    while ((e1 = ast_hashtab_next(t1))) {
02260       if (e1->exten) {
02261          add_exten_to_pattern_tree(con, e1, 0);
02262       } else {
02263          ast_log(LOG_ERROR, "Attempt to create extension with no extension name.\n");
02264       }
02265    }
02266    ast_hashtab_end_traversal(t1);
02267 }

static void decrease_call_count ( void   )  [static]

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

05538 {
05539    ast_mutex_lock(&maxcalllock);
05540    if (countcalls > 0)
05541       countcalls--;
05542    ast_mutex_unlock(&maxcalllock);
05543 }

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

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

04912 {
04913    struct ast_hint *hint = obj;
04914 
04915    if (hint->callbacks) {
04916       struct ast_state_cb *state_cb;
04917       const char *context_name;
04918       const char *exten_name;
04919 
04920       if (hint->exten) {
04921          context_name = ast_get_context_name(ast_get_extension_context(hint->exten));
04922          exten_name = ast_get_extension_name(hint->exten);
04923          hint->exten = NULL;
04924       } else {
04925          /* The extension has already been destroyed */
04926          context_name = hint->context_name;
04927          exten_name = hint->exten_name;
04928       }
04929       while ((state_cb = ao2_callback(hint->callbacks, OBJ_UNLINK, NULL, NULL))) {
04930          /* Notify with -1 and remove all callbacks */
04931          /* NOTE: The casts will not be needed for v1.10 and later */
04932          state_cb->change_cb((char *) context_name, (char *) exten_name,
04933             AST_EXTENSION_DEACTIVATED, state_cb->data);
04934          ao2_ref(state_cb, -1);
04935       }
04936       ao2_ref(hint->callbacks, -1);
04937    }
04938 }

static void destroy_pattern_tree ( struct match_char pattern_tree  )  [static]

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

02270 {
02271    /* destroy all the alternates */
02272    if (pattern_tree->alt_char) {
02273       destroy_pattern_tree(pattern_tree->alt_char);
02274       pattern_tree->alt_char = 0;
02275    }
02276    /* destroy all the nexts */
02277    if (pattern_tree->next_char) {
02278       destroy_pattern_tree(pattern_tree->next_char);
02279       pattern_tree->next_char = 0;
02280    }
02281    pattern_tree->exten = 0; /* never hurts to make sure there's no pointers laying around */
02282    ast_free(pattern_tree);
02283 }

static void destroy_state_cb ( void *  doomed  )  [static]

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

04743 {
04744    struct ast_state_cb *state_cb = doomed;
04745 
04746    if (state_cb->destroy_cb) {
04747       state_cb->destroy_cb(state_cb->id, state_cb->data);
04748    }
04749 }

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

Definition at line 10485 of file pbx.c.

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

Referenced by load_pbx().

10486 {
10487    const char *device;
10488    struct statechange *sc;
10489 
10490    device = ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE);
10491    if (ast_strlen_zero(device)) {
10492       ast_log(LOG_ERROR, "Received invalid event that had no device IE\n");
10493       return;
10494    }
10495 
10496    if (!(sc = ast_calloc(1, sizeof(*sc) + strlen(device) + 1)))
10497       return;
10498    strcpy(sc->dev, device);
10499    if (ast_taskprocessor_push(device_state_tps, handle_statechange, sc) < 0) {
10500       ast_free(sc);
10501    }
10502 }

static void exception_store_free ( void *  data  )  [static]

Definition at line 3496 of file pbx.c.

References ast_free, and ast_string_field_free_memory.

03497 {
03498    struct pbx_exception *exception = data;
03499    ast_string_field_free_memory(exception);
03500    ast_free(exception);
03501 }

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

Definition at line 2616 of file pbx.c.

References ext_cmp_exten(), and ext_cmp_pattern().

Referenced by ast_add_extension2_lockopt(), and ast_extension_cmp().

02617 {
02618    /* Make sure non-pattern extens come first. */
02619    if (left[0] != '_') {
02620       if (right[0] == '_') {
02621          return -1;
02622       }
02623       /* Compare two non-pattern extens. */
02624       return ext_cmp_exten(left, right);
02625    }
02626    if (right[0] != '_') {
02627       return 1;
02628    }
02629 
02630    /*
02631     * OK, we need full pattern sorting routine.
02632     *
02633     * Skip past the underscores
02634     */
02635    return ext_cmp_pattern(left + 1, right + 1);
02636 }

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

Definition at line 2366 of file pbx.c.

Referenced by _extension_match_core(), and ext_cmp().

02367 {
02368    int cmp;
02369 
02370    for (;;) {
02371       /* Ignore '-' chars as eye candy fluff. */
02372       while (*left == '-') {
02373          ++left;
02374       }
02375       while (*right == '-') {
02376          ++right;
02377       }
02378 
02379       cmp = *left - *right;
02380       if (cmp) {
02381          break;
02382       }
02383       if (!*left) {
02384          /*
02385           * Get here only if both strings ended at the same time.  cmp
02386           * would be non-zero if only one string ended.
02387           */
02388          break;
02389       }
02390       ++left;
02391       ++right;
02392    }
02393    return cmp;
02394 }

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

Definition at line 2323 of file pbx.c.

Referenced by _extension_match_core().

02324 {
02325    int cmp;
02326 
02327    for (;;) {
02328       /* Ignore '-' chars as eye candy fluff. */
02329       while (*left == '-') {
02330          ++left;
02331       }
02332       while (*right == '-') {
02333          ++right;
02334       }
02335 
02336       if (!*right) {
02337          /*
02338           * Right ended first for partial match or both ended at the same
02339           * time for a match.
02340           */
02341          cmp = 0;
02342          break;
02343       }
02344 
02345       cmp = *left - *right;
02346       if (cmp) {
02347          break;
02348       }
02349       ++left;
02350       ++right;
02351    }
02352    return cmp;
02353 }

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

Definition at line 2293 of file pbx.c.

References len().

Referenced by _extension_match_core().

02294 {
02295    int len;
02296 
02297    len = 0;
02298    for (;;) {
02299       /* Ignore '-' chars as eye candy fluff. */
02300       while (*str == '-') {
02301          ++str;
02302       }
02303       if (!*str) {
02304          break;
02305       }
02306       ++str;
02307       ++len;
02308    }
02309    return len;
02310 }

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

Definition at line 2568 of file pbx.c.

References ARRAY_LEN, and ext_cmp_pattern_pos().

Referenced by _extension_match_core(), and ext_cmp().

02569 {
02570    int cmp;
02571    int left_pos;
02572    int right_pos;
02573 
02574    for (;;) {
02575       unsigned char left_bitwise[32] = { 0, };
02576       unsigned char right_bitwise[32] = { 0, };
02577 
02578       left_pos = ext_cmp_pattern_pos(&left, left_bitwise);
02579       right_pos = ext_cmp_pattern_pos(&right, right_bitwise);
02580       cmp = left_pos - right_pos;
02581       if (!cmp) {
02582          /*
02583           * Are the character sets different, even though they score the same?
02584           *
02585           * Note: Must swap left and right to get the sense of the
02586           * comparison correct.  Otherwise, we would need to multiply by
02587           * -1 instead.
02588           */
02589          cmp = memcmp(right_bitwise, left_bitwise, ARRAY_LEN(left_bitwise));
02590       }
02591       if (cmp) {
02592          break;
02593       }
02594       if (!left) {
02595          /*
02596           * Get here only if both patterns ended at the same time.  cmp
02597           * would be non-zero if only one pattern ended.
02598           */
02599          break;
02600       }
02601    }
02602    return cmp;
02603 }

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

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

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

Definition at line 2453 of file pbx.c.

References ast_log(), BITS_PER, and LOG_WARNING.

Referenced by ext_cmp_pattern().

02454 {
02455 #define BITS_PER  8  /* Number of bits per unit (byte). */
02456    unsigned char c;
02457    unsigned char cmin;
02458    int count;
02459    const char *end;
02460 
02461    do {
02462       /* Get character and advance. (Ignore '-' chars as eye candy fluff.) */
02463       do {
02464          c = *(*p)++;
02465       } while (c == '-');
02466 
02467       /* always return unless we have a set of chars */
02468       switch (c) {
02469       default:
02470          /* ordinary character */
02471          bitwise[c / BITS_PER] = 1 << ((BITS_PER - 1) - (c % BITS_PER));
02472          return 0x0100 | c;
02473 
02474       case 'n':
02475       case 'N':
02476          /* 2..9 */
02477          bitwise[6] = 0x3f;
02478          bitwise[7] = 0xc0;
02479          return 0x0800 | '2';
02480 
02481       case 'x':
02482       case 'X':
02483          /* 0..9 */
02484          bitwise[6] = 0xff;
02485          bitwise[7] = 0xc0;
02486          return 0x0A00 | '0';
02487 
02488       case 'z':
02489       case 'Z':
02490          /* 1..9 */
02491          bitwise[6] = 0x7f;
02492          bitwise[7] = 0xc0;
02493          return 0x0900 | '1';
02494 
02495       case '.':
02496          /* wildcard */
02497          return 0x18000;
02498 
02499       case '!':
02500          /* earlymatch */
02501          return 0x28000;   /* less specific than '.' */
02502 
02503       case '\0':
02504          /* empty string */
02505          *p = NULL;
02506          return 0x30000;
02507 
02508       case '[':
02509          /* char set */
02510          break;
02511       }
02512       /* locate end of set */
02513       end = strchr(*p, ']');
02514 
02515       if (!end) {
02516          ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n");
02517          return 0x40000;   /* XXX make this entry go last... */
02518       }
02519 
02520       count = 0;
02521       cmin = 0xFF;
02522       for (; *p < end; ++*p) {
02523          unsigned char c1; /* first char in range */
02524          unsigned char c2; /* last char in range */
02525 
02526          c1 = (*p)[0];
02527          if (*p + 2 < end && (*p)[1] == '-') { /* this is a range */
02528             c2 = (*p)[2];
02529             *p += 2;    /* skip a total of 3 chars */
02530          } else {        /* individual character */
02531             c2 = c1;
02532          }
02533          if (c1 < cmin) {
02534             cmin = c1;
02535          }
02536          for (; c1 <= c2; ++c1) {
02537             unsigned char mask = 1 << ((BITS_PER - 1) - (c1 % BITS_PER));
02538 
02539             /*
02540              * Note: If two character sets score the same, the one with the
02541              * lowest ASCII values will compare as coming first.  Must fill
02542              * in most significant bits for lower ASCII values to accomplish
02543              * the desired sort order.
02544              */
02545             if (!(bitwise[c1 / BITS_PER] & mask)) {
02546                /* Add the character to the set. */
02547                bitwise[c1 / BITS_PER] |= mask;
02548                count += 0x100;
02549             }
02550          }
02551       }
02552       ++*p;
02553    } while (!count);/* While the char set was empty. */
02554    return count | cmin;
02555 }

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

copy a string skipping whitespace

Definition at line 8500 of file pbx.c.

Referenced by ast_add_extension2_lockopt().

08501 {
08502    int count = 0;
08503    int insquares = 0;
08504 
08505    while (*src && (count < len - 1)) {
08506       if (*src == '[') {
08507          insquares = 1;
08508       } else if (*src == ']') {
08509          insquares = 0;
08510       } else if (*src == ' ' && !insquares) {
08511          src++;
08512          continue;
08513       }
08514       *dst = *src;
08515       dst++;
08516       src++;
08517       count++;
08518    }
08519    *dst = '\0';
08520 
08521    return count;
08522 }

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

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

02856 {
02857    int i;
02858    static int prof_id = -2;   /* marker for 'unallocated' id */
02859    if (prof_id == -2) {
02860       prof_id = ast_add_profile("ext_match", 0);
02861    }
02862    ast_mark(prof_id, 1);
02863    i = _extension_match_core(ast_strlen_zero(pattern) ? "" : pattern, ast_strlen_zero(data) ? "" : data, mode);
02864    ast_mark(prof_id, 0);
02865    return i;
02866 }

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

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

05672 {
05673    struct fake_context item;
05674 
05675    ast_copy_string(item.name, context, sizeof(item.name));
05676 
05677    return ast_hashtab_lookup(contexts_table, &item);
05678 }

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

05686 {
05687    struct ast_context *c;
05688    struct fake_context item;
05689 
05690    ast_copy_string(item.name, context, sizeof(item.name));
05691 
05692    ast_rdlock_contexts();
05693    c = ast_hashtab_lookup(contexts_table, &item);
05694    if (!c) {
05695       ast_unlock_contexts();
05696    }
05697 
05698    return c;
05699 }

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

Remove a watcher from the callback list.

Definition at line 4846 of file pbx.c.

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

Referenced by ast_extension_state_del().

04847 {
04848    struct ast_state_cb *state_cb;
04849    const struct ast_hint *hint = obj;
04850    int *id = arg;
04851 
04852    if ((state_cb = ao2_find(hint->callbacks, id, 0))) {
04853       ao2_ref(state_cb, -1);
04854       return CMP_MATCH | CMP_STOP;
04855    }
04856 
04857    return 0;
04858 }

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

References args, ast_log(), and LOG_WARNING.

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

03866 {
03867    char *args = strchr(function, '(');
03868 
03869    if (!args) {
03870       ast_log(LOG_WARNING, "Function '%s' doesn't contain parentheses.  Assuming null argument.\n", function);
03871    } else {
03872       char *p;
03873       *args++ = '\0';
03874       if ((p = strrchr(args, ')'))) {
03875          *p = '\0';
03876       } else {
03877          ast_log(LOG_WARNING, "Can't find trailing parenthesis for function '%s(%s'?\n", function, args);
03878       }
03879    }
03880    return args;
03881 }

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

Definition at line 1654 of file pbx.c.

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

01655 {
01656    /* find the exten at the end of the rope */
01657    struct match_char *node2 = node;
01658 
01659    for (node2 = node; node2; node2 = node2->next_char) {
01660       if (node2->exten) {
01661 #ifdef NEED_DEBUG_HERE
01662          ast_log(LOG_NOTICE,"CanMatch_exten returns exten %s(%p)\n", node2->exten->exten, node2->exten);
01663 #endif
01664          return node2->exten;
01665       }
01666    }
01667 #ifdef NEED_DEBUG_HERE
01668    ast_log(LOG_NOTICE,"CanMatch_exten returns NULL, match_char=%s\n", node->x);
01669 #endif
01670    return 0;
01671 }

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

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

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

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

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

Referenced by ast_build_timing().

07856 {
07857    int start, end; /* start and ending position */
07858    unsigned int mask = 0;
07859    char *part;
07860 
07861    /* Check for whole range */
07862    if (ast_strlen_zero(src) || !strcmp(src, "*")) {
07863       return (1 << max) - 1;
07864    }
07865 
07866    while ((part = strsep(&src, "&"))) {
07867       /* Get start and ending position */
07868       char *endpart = strchr(part, '-');
07869       if (endpart) {
07870          *endpart++ = '\0';
07871       }
07872       /* Find the start */
07873       if ((start = lookup_name(part, names, max)) < 0) {
07874          ast_log(LOG_WARNING, "Invalid %s '%s', skipping element\n", msg, part);
07875          continue;
07876       }
07877       if (endpart) { /* find end of range */
07878          if ((end = lookup_name(endpart, names, max)) < 0) {
07879             ast_log(LOG_WARNING, "Invalid end %s '%s', skipping element\n", msg, endpart);
07880             continue;
07881          }
07882       } else {
07883          end = start;
07884       }
07885       /* Fill the mask. Remember that ranges are cyclic */
07886       mask |= (1 << end);   /* initialize with last element */
07887       while (start != end) {
07888          mask |= (1 << start);
07889          if (++start >= max) {
07890             start = 0;
07891          }
07892       }
07893    }
07894    return mask;
07895 }

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

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

Referenced by ast_build_timing().

07899 {
07900    char *endpart, *part;
07901    int x;
07902    int st_h, st_m;
07903    int endh, endm;
07904    int minute_start, minute_end;
07905 
07906    /* start disabling all times, fill the fields with 0's, as they may contain garbage */
07907    memset(i->minmask, 0, sizeof(i->minmask));
07908 
07909    /* 1-minute per bit */
07910    /* Star is all times */
07911    if (ast_strlen_zero(times) || !strcmp(times, "*")) {
07912       /* 48, because each hour takes 2 integers; 30 bits each */
07913       for (x = 0; x < 48; x++) {
07914          i->minmask[x] = 0x3fffffff; /* 30 bits */
07915       }
07916       return;
07917    }
07918    /* Otherwise expect a range */
07919    while ((part = strsep(&times, "&"))) {
07920       if (!(endpart = strchr(part, '-'))) {
07921          if (sscanf(part, "%2d:%2d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) {
07922             ast_log(LOG_WARNING, "%s isn't a valid time.\n", part);
07923             continue;
07924          }
07925          i->minmask[st_h * 2 + (st_m >= 30 ? 1 : 0)] |= (1 << (st_m % 30));
07926          continue;
07927       }
07928       *endpart++ = '\0';
07929       /* why skip non digits? Mostly to skip spaces */
07930       while (*endpart && !isdigit(*endpart)) {
07931          endpart++;
07932       }
07933       if (!*endpart) {
07934          ast_log(LOG_WARNING, "Invalid time range starting with '%s-'.\n", part);
07935          continue;
07936       }
07937       if (sscanf(part, "%2d:%2d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) {
07938          ast_log(LOG_WARNING, "'%s' isn't a valid start time.\n", part);
07939          continue;
07940       }
07941       if (sscanf(endpart, "%2d:%2d", &endh, &endm) != 2 || endh < 0 || endh > 23 || endm < 0 || endm > 59) {
07942          ast_log(LOG_WARNING, "'%s' isn't a valid end time.\n", endpart);
07943          continue;
07944       }
07945       minute_start = st_h * 60 + st_m;
07946       minute_end = endh * 60 + endm;
07947       /* Go through the time and enable each appropriate bit */
07948       for (x = minute_start; x != minute_end; x = (x + 1) % (24 * 60)) {
07949          i->minmask[x / 30] |= (1 << (x % 30));
07950       }
07951       /* Do the last one */
07952       i->minmask[x / 30] |= (1 << (x % 30));
07953    }
07954    /* All done */
07955    return;
07956 }

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

Send ack once.

Definition at line 6884 of file pbx.c.

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

06885 {
06886    char *exten = NULL, *context = NULL;
06887    /* Variables used for different counters */
06888    struct dialplan_counters counters;
06889    const char *incstack[AST_PBX_MAX_STACK];
06890 
06891    switch (cmd) {
06892    case CLI_INIT:
06893       e->command = "dialplan debug";
06894       e->usage =
06895          "Usage: dialplan debug [context]\n"
06896          "       Show dialplan context Trie(s). Usually only useful to folks debugging the deep internals of the fast pattern matcher\n";
06897       return NULL;
06898    case CLI_GENERATE:
06899       return complete_show_dialplan_context(a->line, a->word, a->pos, a->n);
06900    }
06901 
06902    memset(&counters, 0, sizeof(counters));
06903 
06904    if (a->argc != 2 && a->argc != 3)
06905       return CLI_SHOWUSAGE;
06906 
06907    /* we obtain [exten@]context? if yes, split them ... */
06908    /* note: we ignore the exten totally here .... */
06909    if (a->argc == 3) {
06910       if (strchr(a->argv[2], '@')) {   /* split into exten & context */
06911          context = ast_strdupa(a->argv[2]);
06912          exten = strsep(&context, "@");
06913          /* change empty strings to NULL */
06914          if (ast_strlen_zero(exten))
06915             exten = NULL;
06916       } else { /* no '@' char, only context given */
06917          context = ast_strdupa(a->argv[2]);
06918       }
06919       if (ast_strlen_zero(context))
06920          context = NULL;
06921    }
06922    /* else Show complete dial plan, context and exten are NULL */
06923    show_debug_helper(a->fd, context, exten, &counters, NULL, 0, incstack);
06924 
06925    /* check for input failure and throw some error messages */
06926    if (context && !counters.context_existence) {
06927       ast_cli(a->fd, "There is no existence of '%s' context\n", context);
06928       return CLI_FAILURE;
06929    }
06930 
06931 
06932    ast_cli(a->fd,"-= %d %s. =-\n",
06933          counters.total_context, counters.total_context == 1 ? "context" : "contexts");
06934 
06935    /* everything ok */
06936    return CLI_SUCCESS;
06937 }

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

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

07258 {
07259    struct ast_channel *chan;
07260    const char *chan_name, *var_name, *var_value;
07261 
07262    switch (cmd) {
07263    case CLI_INIT:
07264       e->command = "dialplan set chanvar";
07265       e->usage =
07266          "Usage: dialplan set chanvar <channel> <varname> <value>\n"
07267          "       Set channel variable <varname> to <value>\n";
07268       return NULL;
07269    case CLI_GENERATE:
07270       return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
07271    }
07272 
07273    if (a->argc != e->args + 3)
07274       return CLI_SHOWUSAGE;
07275 
07276    chan_name = a->argv[e->args];
07277    var_name = a->argv[e->args + 1];
07278    var_value = a->argv[e->args + 2];
07279 
07280    if (!(chan = ast_channel_get_by_name(chan_name))) {
07281       ast_cli(a->fd, "Channel '%s' not found\n", chan_name);
07282       return CLI_FAILURE;
07283    }
07284 
07285    pbx_builtin_setvar_helper(chan, var_name, var_value);
07286 
07287    chan = ast_channel_unref(chan);
07288 
07289    ast_cli(a->fd, "\n    -- Channel variable '%s' set to '%s' for '%s'\n",  var_name, var_value, chan_name);
07290 
07291    return CLI_SUCCESS;
07292 }

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

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

07295 {
07296    int oldval = 0;
07297 
07298    switch (cmd) {
07299    case CLI_INIT:
07300       e->command = "dialplan set extenpatternmatchnew true";
07301       e->usage =
07302          "Usage: dialplan set extenpatternmatchnew true|false\n"
07303          "       Use the NEW extension pattern matching algorithm, true or false.\n";
07304       return NULL;
07305    case CLI_GENERATE:
07306       return NULL;
07307    }
07308 
07309    if (a->argc != 4)
07310       return CLI_SHOWUSAGE;
07311 
07312    oldval =  pbx_set_extenpatternmatchnew(1);
07313 
07314    if (oldval)
07315       ast_cli(a->fd, "\n    -- Still using the NEW pattern match algorithm for extension names in the dialplan.\n");
07316    else
07317       ast_cli(a->fd, "\n    -- Switched to using the NEW pattern match algorithm for extension names in the dialplan.\n");
07318 
07319    return CLI_SUCCESS;
07320 }

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

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

07236 {
07237    switch (cmd) {
07238    case CLI_INIT:
07239       e->command = "dialplan set global";
07240       e->usage =
07241          "Usage: dialplan set global <name> <value>\n"
07242          "       Set global dialplan variable <name> to <value>\n";
07243       return NULL;
07244    case CLI_GENERATE:
07245       return NULL;
07246    }
07247 
07248    if (a->argc != e->args + 2)
07249       return CLI_SHOWUSAGE;
07250 
07251    pbx_builtin_setvar_helper(NULL, a->argv[3], a->argv[4]);
07252    ast_cli(a->fd, "\n    -- Global variable '%s' set to '%s'\n", a->argv[3], a->argv[4]);
07253 
07254    return CLI_SUCCESS;
07255 }

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

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

06247 {
06248    struct ast_app *aa;
06249    int app, no_registered_app = 1;
06250 
06251    switch (cmd) {
06252    case CLI_INIT:
06253       e->command = "core show application";
06254       e->usage =
06255          "Usage: core show application <application> [<application> [<application> [...]]]\n"
06256          "       Describes a particular application.\n";
06257       return NULL;
06258    case CLI_GENERATE:
06259       /*
06260        * There is a possibility to show informations about more than one
06261        * application at one time. You can type 'show application Dial Echo' and
06262        * you will see informations about these two applications ...
06263        */
06264       return ast_complete_applications(a->line, a->word, a->n);
06265    }
06266 
06267    if (a->argc < 4) {
06268       return CLI_SHOWUSAGE;
06269    }
06270 
06271    AST_RWLIST_RDLOCK(&apps);
06272    AST_RWLIST_TRAVERSE(&apps, aa, list) {
06273       /* Check for each app that was supplied as an argument */
06274       for (app = 3; app < a->argc; app++) {
06275          if (strcasecmp(aa->name, a->argv[app])) {
06276             continue;
06277          }
06278 
06279          /* We found it! */
06280          no_registered_app = 0;
06281 
06282          print_app_docs(aa, a->fd);
06283       }
06284    }
06285    AST_RWLIST_UNLOCK(&apps);
06286 
06287    /* we found at least one app? no? */
06288    if (no_registered_app) {
06289       ast_cli(a->fd, "Your application(s) is (are) not registered\n");
06290       return CLI_FAILURE;
06291    }
06292 
06293    return CLI_SUCCESS;
06294 }

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

Definition at line 6471 of file pbx.c.

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

06472 {
06473    struct ast_app *aa;
06474    int like = 0, describing = 0;
06475    int total_match = 0;    /* Number of matches in like clause */
06476    int total_apps = 0;     /* Number of apps registered */
06477    static const char * const choices[] = { "like", "describing", NULL };
06478 
06479    switch (cmd) {
06480    case CLI_INIT:
06481       e->command = "core show applications [like|describing]";
06482       e->usage =
06483          "Usage: core show applications [{like|describing} <text>]\n"
06484          "       List applications which are currently available.\n"
06485          "       If 'like', <text> will be a substring of the app name\n"
06486          "       If 'describing', <text> will be a substring of the description\n";
06487       return NULL;
06488    case CLI_GENERATE:
06489       return (a->pos != 3) ? NULL : ast_cli_complete(a->word, choices, a->n);
06490    }
06491 
06492    AST_RWLIST_RDLOCK(&apps);
06493 
06494    if (AST_RWLIST_EMPTY(&apps)) {
06495       ast_cli(a->fd, "There are no registered applications\n");
06496       AST_RWLIST_UNLOCK(&apps);
06497       return CLI_SUCCESS;
06498    }
06499 
06500    /* core list applications like <keyword> */
06501    if ((a->argc == 5) && (!strcmp(a->argv[3], "like"))) {
06502       like = 1;
06503    } else if ((a->argc > 4) && (!strcmp(a->argv[3], "describing"))) {
06504       describing = 1;
06505    }
06506 
06507    /* core list applications describing <keyword1> [<keyword2>] [...] */
06508    if ((!like) && (!describing)) {
06509       ast_cli(a->fd, "    -= Registered Asterisk Applications =-\n");
06510    } else {
06511       ast_cli(a->fd, "    -= Matching Asterisk Applications =-\n");
06512    }
06513 
06514    AST_RWLIST_TRAVERSE(&apps, aa, list) {
06515       int printapp = 0;
06516       total_apps++;
06517       if (like) {
06518          if (strcasestr(aa->name, a->argv[4])) {
06519             printapp = 1;
06520             total_match++;
06521          }
06522       } else if (describing) {
06523          if (aa->description) {
06524             /* Match all words on command line */
06525             int i;
06526             printapp = 1;
06527             for (i = 4; i < a->argc; i++) {
06528                if (!strcasestr(aa->description, a->argv[i])) {
06529                   printapp = 0;
06530                } else {
06531                   total_match++;
06532                }
06533             }
06534          }
06535       } else {
06536          printapp = 1;
06537       }
06538 
06539       if (printapp) {
06540          ast_cli(a->fd,"  %20s: %s\n", aa->name, aa->synopsis ? aa->synopsis : "<Synopsis not available>");
06541       }
06542    }
06543    if ((!like) && (!describing)) {
06544       ast_cli(a->fd, "    -= %d Applications Registered =-\n",total_apps);
06545    } else {
06546       ast_cli(a->fd, "    -= %d Applications Matching =-\n",total_match);
06547    }
06548 
06549    AST_RWLIST_UNLOCK(&apps);
06550 
06551    return CLI_SUCCESS;
06552 }

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

07201 {
07202    struct ast_channel *chan = NULL;
07203    struct ast_str *vars = ast_str_alloca(BUFSIZ * 4); /* XXX large because we might have lots of channel vars */
07204 
07205    switch (cmd) {
07206    case CLI_INIT:
07207       e->command = "dialplan show chanvar";
07208       e->usage =
07209          "Usage: dialplan show chanvar <channel>\n"
07210          "       List current channel variables and their values\n";
07211       return NULL;
07212    case CLI_GENERATE:
07213       return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
07214    }
07215 
07216    if (a->argc != e->args + 1)
07217       return CLI_SHOWUSAGE;
07218 
07219    if (!(chan = ast_channel_get_by_name(a->argv[e->args]))) {
07220       ast_cli(a->fd, "Channel '%s' not found\n", a->argv[e->args]);
07221       return CLI_FAILURE;
07222    }
07223 
07224    pbx_builtin_serialize_variables(chan, &vars);
07225 
07226    if (ast_str_strlen(vars)) {
07227       ast_cli(a->fd, "\nVariables for channel %s:\n%s\n", a->argv[e->args], ast_str_buffer(vars));
07228    }
07229 
07230    chan = ast_channel_unref(chan);
07231 
07232    return CLI_SUCCESS;
07233 }

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

Definition at line 6817 of file pbx.c.

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

06818 {
06819    char *exten = NULL, *context = NULL;
06820    /* Variables used for different counters */
06821    struct dialplan_counters counters;
06822    const char *incstack[AST_PBX_MAX_STACK];
06823 
06824    switch (cmd) {
06825    case CLI_INIT:
06826       e->command = "dialplan show";
06827       e->usage =
06828          "Usage: dialplan show [[exten@]context]\n"
06829          "       Show dialplan\n";
06830       return NULL;
06831    case CLI_GENERATE:
06832       return complete_show_dialplan_context(a->line, a->word, a->pos, a->n);
06833    }
06834 
06835    memset(&counters, 0, sizeof(counters));
06836 
06837    if (a->argc != 2 && a->argc != 3)
06838       return CLI_SHOWUSAGE;
06839 
06840    /* we obtain [exten@]context? if yes, split them ... */
06841    if (a->argc == 3) {
06842       if (strchr(a->argv[2], '@')) {   /* split into exten & context */
06843          context = ast_strdupa(a->argv[2]);
06844          exten = strsep(&context, "@");
06845          /* change empty strings to NULL */
06846          if (ast_strlen_zero(exten))
06847             exten = NULL;
06848       } else { /* no '@' char, only context given */
06849          context = ast_strdupa(a->argv[2]);
06850       }
06851       if (ast_strlen_zero(context))
06852          context = NULL;
06853    }
06854    /* else Show complete dial plan, context and exten are NULL */
06855    show_dialplan_helper(a->fd, context, exten, &counters, NULL, 0, incstack);
06856 
06857    /* check for input failure and throw some error messages */
06858    if (context && !counters.context_existence) {
06859       ast_cli(a->fd, "There is no existence of '%s' context\n", context);
06860       return CLI_FAILURE;
06861    }
06862 
06863    if (exten && !counters.extension_existence) {
06864       if (context)
06865          ast_cli(a->fd, "There is no existence of %s@%s extension\n",
06866             exten, context);
06867       else
06868          ast_cli(a->fd,
06869             "There is no existence of '%s' extension in all contexts\n",
06870             exten);
06871       return CLI_FAILURE;
06872    }
06873 
06874    ast_cli(a->fd,"-= %d %s (%d %s) in %d %s. =-\n",
06875             counters.total_exten, counters.total_exten == 1 ? "extension" : "extensions",
06876             counters.total_prio, counters.total_prio == 1 ? "priority" : "priorities",
06877             counters.total_context, counters.total_context == 1 ? "context" : "contexts");
06878 
06879    /* everything ok */
06880    return CLI_SUCCESS;
06881 }

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

Definition at line 3618 of file pbx.c.

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

03619 {
03620    struct ast_custom_function *acf;
03621    /* Maximum number of characters added by terminal coloring is 22 */
03622    char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40], argtitle[40], seealsotitle[40];
03623    char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL, *seealso = NULL;
03624    char stxtitle[40], *syntax = NULL, *arguments = NULL;
03625    int syntax_size, description_size, synopsis_size, arguments_size, seealso_size;
03626    char *ret = NULL;
03627    int which = 0;
03628    int wordlen;
03629 
03630    switch (cmd) {
03631    case CLI_INIT:
03632       e->command = "core show function";
03633       e->usage =
03634          "Usage: core show function <function>\n"
03635          "       Describe a particular dialplan function.\n";
03636       return NULL;
03637    case CLI_GENERATE:
03638       wordlen = strlen(a->word);
03639       /* case-insensitive for convenience in this 'complete' function */
03640       AST_RWLIST_RDLOCK(&acf_root);
03641       AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) {
03642          if (!strncasecmp(a->word, acf->name, wordlen) && ++which > a->n) {
03643             ret = ast_strdup(acf->name);
03644             break;
03645          }
03646       }
03647       AST_RWLIST_UNLOCK(&acf_root);
03648 
03649       return ret;
03650    }
03651 
03652    if (a->argc < 4) {
03653       return CLI_SHOWUSAGE;
03654    }
03655 
03656    if (!(acf = ast_custom_function_find(a->argv[3]))) {
03657       ast_cli(a->fd, "No function by that name registered.\n");
03658       return CLI_FAILURE;
03659    }
03660 
03661    syntax_size = strlen(S_OR(acf->syntax, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
03662    if (!(syntax = ast_malloc(syntax_size))) {
03663       ast_cli(a->fd, "Memory allocation failure!\n");
03664       return CLI_FAILURE;
03665    }
03666 
03667    snprintf(info, sizeof(info), "\n  -= Info about function '%s' =- \n\n", acf->name);
03668    term_color(infotitle, info, COLOR_MAGENTA, 0, sizeof(infotitle));
03669    term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
03670    term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
03671    term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40);
03672    term_color(argtitle, "[Arguments]\n", COLOR_MAGENTA, 0, 40);
03673    term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, 40);
03674    term_color(syntax, S_OR(acf->syntax, "Not available"), COLOR_CYAN, 0, syntax_size);
03675 #ifdef AST_XML_DOCS
03676    if (acf->docsrc == AST_XML_DOC) {
03677       arguments = ast_xmldoc_printable(S_OR(acf->arguments, "Not available"), 1);
03678       synopsis = ast_xmldoc_printable(S_OR(acf->synopsis, "Not available"), 1);
03679       description = ast_xmldoc_printable(S_OR(acf->desc, "Not available"), 1);
03680       seealso = ast_xmldoc_printable(S_OR(acf->seealso, "Not available"), 1);
03681    } else
03682 #endif
03683    {
03684       synopsis_size = strlen(S_OR(acf->synopsis, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
03685       synopsis = ast_malloc(synopsis_size);
03686 
03687       description_size = strlen(S_OR(acf->desc, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
03688       description = ast_malloc(description_size);
03689 
03690       arguments_size = strlen(S_OR(acf->arguments, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
03691       arguments = ast_malloc(arguments_size);
03692 
03693       seealso_size = strlen(S_OR(acf->seealso, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
03694       seealso = ast_malloc(seealso_size);
03695 
03696       /* check allocated memory. */
03697       if (!synopsis || !description || !arguments || !seealso) {
03698          ast_free(synopsis);
03699          ast_free(description);
03700          ast_free(arguments);
03701          ast_free(seealso);
03702          ast_free(syntax);
03703          return CLI_FAILURE;
03704       }
03705 
03706       term_color(arguments, S_OR(acf->arguments, "Not available"), COLOR_CYAN, 0, arguments_size);
03707       term_color(synopsis, S_OR(acf->synopsis, "Not available"), COLOR_CYAN, 0, synopsis_size);
03708       term_color(description, S_OR(acf->desc, "Not available"), COLOR_CYAN, 0, description_size);
03709       term_color(seealso, S_OR(acf->seealso, "Not available"), COLOR_CYAN, 0, seealso_size);
03710    }
03711 
03712    ast_cli(a->fd, "%s%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n",
03713          infotitle, syntitle, synopsis, destitle, description,
03714          stxtitle, syntax, argtitle, arguments, seealsotitle, seealso);
03715 
03716    ast_free(arguments);
03717    ast_free(synopsis);
03718    ast_free(description);
03719    ast_free(seealso);
03720    ast_free(syntax);
03721 
03722    return CLI_SUCCESS;
03723 }

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

Definition at line 3576 of file pbx.c.

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

03577 {
03578    struct ast_custom_function *acf;
03579    int count_acf = 0;
03580    int like = 0;
03581 
03582    switch (cmd) {
03583    case CLI_INIT:
03584       e->command = "core show functions [like]";
03585       e->usage =
03586          "Usage: core show functions [like <text>]\n"
03587          "       List builtin functions, optionally only those matching a given string\n";
03588       return NULL;
03589    case CLI_GENERATE:
03590       return NULL;
03591    }
03592 
03593    if (a->argc == 5 && (!strcmp(a->argv[3], "like")) ) {
03594       like = 1;
03595    } else if (a->argc != 3) {
03596       return CLI_SHOWUSAGE;
03597    }
03598 
03599    ast_cli(a->fd, "%s Custom Functions:\n--------------------------------------------------------------------------------\n", like ? "Matching" : "Installed");
03600 
03601    AST_RWLIST_RDLOCK(&acf_root);
03602    AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) {
03603       if (!like || strstr(acf->name, a->argv[4])) {
03604          count_acf++;
03605          ast_cli(a->fd, "%-20.20s  %-35.35s  %s\n",
03606             S_OR(acf->name, ""),
03607             S_OR(acf->syntax, ""),
03608             S_OR(acf->synopsis, ""));
03609       }
03610    }
03611    AST_RWLIST_UNLOCK(&acf_root);
03612 
03613    ast_cli(a->fd, "%d %scustom functions installed.\n", count_acf, like ? "matching " : "");
03614 
03615    return CLI_SUCCESS;
03616 }

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

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

07143 {
07144    int i = 0;
07145    struct ast_var_t *newvariable;
07146 
07147    switch (cmd) {
07148    case CLI_INIT:
07149       e->command = "dialplan show globals";
07150       e->usage =
07151          "Usage: dialplan show globals\n"
07152          "       List current global dialplan variables and their values\n";
07153       return NULL;
07154    case CLI_GENERATE:
07155       return NULL;
07156    }
07157 
07158    ast_rwlock_rdlock(&globalslock);
07159    AST_LIST_TRAVERSE (&globals, newvariable, entries) {
07160       i++;
07161       ast_cli(a->fd, "   %s=%s\n", ast_var_name(newvariable), ast_var_value(newvariable));
07162    }
07163    ast_rwlock_unlock(&globalslock);
07164    ast_cli(a->fd, "\n    -- %d variable(s)\n", i);
07165 
07166    return CLI_SUCCESS;
07167 }

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

06384 {
06385    struct ast_hint *hint;
06386    int watchers;
06387    int num = 0, extenlen;
06388    struct ao2_iterator i;
06389 
06390    switch (cmd) {
06391    case CLI_INIT:
06392       e->command = "core show hint";
06393       e->usage =
06394          "Usage: core show hint <exten>\n"
06395          "       List registered hint\n";
06396       return NULL;
06397    case CLI_GENERATE:
06398       return complete_core_show_hint(a->line, a->word, a->pos, a->n);
06399    }
06400 
06401    if (a->argc < 4)
06402       return CLI_SHOWUSAGE;
06403 
06404    if (ao2_container_count(hints) == 0) {
06405       ast_cli(a->fd, "There are no registered dialplan hints\n");
06406       return CLI_SUCCESS;
06407    }
06408    
06409    extenlen = strlen(a->argv[3]);
06410    i = ao2_iterator_init(hints, 0);
06411    for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
06412       ao2_lock(hint);
06413       if (!hint->exten) {
06414          /* The extension has already been destroyed */
06415          ao2_unlock(hint);
06416          continue;
06417       }
06418       if (!strncasecmp(ast_get_extension_name(hint->exten), a->argv[3], extenlen)) {
06419          watchers = ao2_container_count(hint->callbacks);
06420          ast_cli(a->fd, "   %20s@%-20.20s: %-20.20s  State:%-15.15s Watchers %2d\n",
06421             ast_get_extension_name(hint->exten),
06422             ast_get_context_name(ast_get_extension_context(hint->exten)),
06423             ast_get_extension_app(hint->exten),
06424             ast_extension_state2str(hint->laststate), watchers);
06425          num++;
06426       }
06427       ao2_unlock(hint);
06428    }
06429    ao2_iterator_destroy(&i);
06430    if (!num)
06431       ast_cli(a->fd, "No hints matching extension %s\n", a->argv[3]);
06432    else
06433       ast_cli(a->fd, "%d hint%s matching extension %s\n", num, (num!=1 ? "s":""), a->argv[3]);
06434    return CLI_SUCCESS;
06435 }

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

06298 {
06299    struct ast_hint *hint;
06300    int num = 0;
06301    int watchers;
06302    struct ao2_iterator i;
06303 
06304    switch (cmd) {
06305    case CLI_INIT:
06306       e->command = "core show hints";
06307       e->usage =
06308          "Usage: core show hints\n"
06309          "       List registered hints\n";
06310       return NULL;
06311    case CLI_GENERATE:
06312       return NULL;
06313    }
06314 
06315    if (ao2_container_count(hints) == 0) {
06316       ast_cli(a->fd, "There are no registered dialplan hints\n");
06317       return CLI_SUCCESS;
06318    }
06319    /* ... we have hints ... */
06320    ast_cli(a->fd, "\n    -= Registered Asterisk Dial Plan Hints =-\n");
06321 
06322    i = ao2_iterator_init(hints, 0);
06323    for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
06324       ao2_lock(hint);
06325       if (!hint->exten) {
06326          /* The extension has already been destroyed */
06327          ao2_unlock(hint);
06328          continue;
06329       }
06330       watchers = ao2_container_count(hint->callbacks);
06331       ast_cli(a->fd, "   %20s@%-20.20s: %-20.20s  State:%-15.15s Watchers %2d\n",
06332          ast_get_extension_name(hint->exten),
06333          ast_get_context_name(ast_get_extension_context(hint->exten)),
06334          ast_get_extension_app(hint->exten),
06335          ast_extension_state2str(hint->laststate), watchers);
06336       ao2_unlock(hint);
06337       num++;
06338    }
06339    ao2_iterator_destroy(&i);
06340 
06341    ast_cli(a->fd, "----------------\n");
06342    ast_cli(a->fd, "- %d hints registered\n", num);
06343    return CLI_SUCCESS;
06344 }

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

06440 {
06441    struct ast_switch *sw;
06442 
06443    switch (cmd) {
06444    case CLI_INIT:
06445       e->command = "core show switches";
06446       e->usage =
06447          "Usage: core show switches\n"
06448          "       List registered switches\n";
06449       return NULL;
06450    case CLI_GENERATE:
06451       return NULL;
06452    }
06453 
06454    AST_RWLIST_RDLOCK(&switches);
06455 
06456    if (AST_RWLIST_EMPTY(&switches)) {
06457       AST_RWLIST_UNLOCK(&switches);
06458       ast_cli(a->fd, "There are no registered alternative switches\n");
06459       return CLI_SUCCESS;
06460    }
06461 
06462    ast_cli(a->fd, "\n    -= Registered Asterisk Alternative Switches =-\n");
06463    AST_RWLIST_TRAVERSE(&switches, sw, list)
06464       ast_cli(a->fd, "%s: %s\n", sw->name, sw->description);
06465 
06466    AST_RWLIST_UNLOCK(&switches);
06467 
06468    return CLI_SUCCESS;
06469 }

static int handle_statechange ( void *  datap  )  [static]

Definition at line 4640 of file pbx.c.

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

Referenced by device_state_cb().

04641 {
04642    struct ast_hint *hint;
04643    struct ast_str *hint_app;
04644    struct statechange *sc = datap;
04645    struct ao2_iterator i;
04646    struct ao2_iterator cb_iter;
04647    char context_name[AST_MAX_CONTEXT];
04648    char exten_name[AST_MAX_EXTENSION];
04649 
04650    hint_app = ast_str_create(1024);
04651    if (!hint_app) {
04652       ast_free(sc);
04653       return -1;
04654    }
04655 
04656    ast_mutex_lock(&context_merge_lock);/* Hold off ast_merge_contexts_and_delete */
04657    i = ao2_iterator_init(hints, 0);
04658    for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
04659       struct ast_state_cb *state_cb;
04660       char *cur, *parse;
04661       int state;
04662 
04663       ao2_lock(hint);
04664       if (!hint->exten) {
04665          /* The extension has already been destroyed */
04666          ao2_unlock(hint);
04667          continue;
04668       }
04669 
04670       /* Does this hint monitor the device that changed state? */
04671       ast_str_set(&hint_app, 0, "%s", ast_get_extension_app(hint->exten));
04672       parse = ast_str_buffer(hint_app);
04673       while ((cur = strsep(&parse, "&"))) {
04674          if (!strcasecmp(cur, sc->dev)) {
04675             /* The hint monitors the device. */
04676             break;
04677          }
04678       }
04679       if (!cur) {
04680          /* The hint does not monitor the device. */
04681          ao2_unlock(hint);
04682          continue;
04683       }
04684 
04685       /*
04686        * Save off strings in case the hint extension gets destroyed
04687        * while we are notifying the watchers.
04688        */
04689       ast_copy_string(context_name,
04690          ast_get_context_name(ast_get_extension_context(hint->exten)),
04691          sizeof(context_name));
04692       ast_copy_string(exten_name, ast_get_extension_name(hint->exten),
04693          sizeof(exten_name));
04694       ast_str_set(&hint_app, 0, "%s", ast_get_extension_app(hint->exten));
04695       ao2_unlock(hint);
04696 
04697       /*
04698        * Get device state for this hint.
04699        *
04700        * NOTE: We cannot hold any locks while determining the hint
04701        * device state or notifying the watchers without causing a
04702        * deadlock.  (conlock, hints, and hint)
04703        */
04704       state = ast_extension_state3(hint_app);
04705       if (state == hint->laststate) {
04706          continue;
04707       }
04708 
04709       /* Device state changed since last check - notify the watchers. */
04710       hint->laststate = state;   /* record we saw the change */
04711 
04712       /* For general callbacks */
04713       cb_iter = ao2_iterator_init(statecbs, 0);
04714       for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) {
04715          state_cb->change_cb(context_name, exten_name, state, state_cb->data);
04716       }
04717       ao2_iterator_destroy(&cb_iter);
04718 
04719       /* For extension callbacks */
04720       cb_iter = ao2_iterator_init(hint->callbacks, 0);
04721       for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) {
04722          state_cb->change_cb(context_name, exten_name, state, state_cb->data);
04723       }
04724       ao2_iterator_destroy(&cb_iter);
04725    }
04726    ao2_iterator_destroy(&i);
04727    ast_mutex_unlock(&context_merge_lock);
04728 
04729    ast_free(hint_app);
04730    ast_free(sc);
04731    return 0;
04732 }

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

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

07323 {
07324    int oldval = 0;
07325 
07326    switch (cmd) {
07327    case CLI_INIT:
07328       e->command = "dialplan set extenpatternmatchnew false";
07329       e->usage =
07330          "Usage: dialplan set extenpatternmatchnew true|false\n"
07331          "       Use the NEW extension pattern matching algorithm, true or false.\n";
07332       return NULL;
07333    case CLI_GENERATE:
07334       return NULL;
07335    }
07336 
07337    if (a->argc != 4)
07338       return CLI_SHOWUSAGE;
07339 
07340    oldval =  pbx_set_extenpatternmatchnew(0);
07341 
07342    if (!oldval)
07343       ast_cli(a->fd, "\n    -- Still using the OLD pattern match algorithm for extension names in the dialplan.\n");
07344    else
07345       ast_cli(a->fd, "\n    -- Switched to using the OLD pattern match algorithm for extension names in the dialplan.\n");
07346 
07347    return CLI_SUCCESS;
07348 }

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

Definition at line 1117 of file pbx.c.

References ast_exten::label, and S_OR.

Referenced by ast_add_extension2_lockopt().

01118 {
01119    const struct ast_exten *ac = ah_a;
01120    const struct ast_exten *bc = ah_b;
01121    return strcmp(S_OR(ac->label, ""), S_OR(bc->label, ""));
01122 }

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

Definition at line 1110 of file pbx.c.

References ast_exten::priority.

Referenced by ast_add_extension2_lockopt().

01111 {
01112    const struct ast_exten *ac = ah_a;
01113    const struct ast_exten *bc = ah_b;
01114    return ac->priority != bc->priority;
01115 }

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

Definition at line 1091 of file pbx.c.

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

Referenced by ast_add_extension2_lockopt().

01092 {
01093    const struct ast_exten *ac = ah_a;
01094    const struct ast_exten *bc = ah_b;
01095    int x = strcmp(ac->exten, bc->exten);
01096    if (x) { /* if exten names are diff, then return */
01097       return x;
01098    }
01099 
01100    /* but if they are the same, do the cidmatch values match? */
01101    if (ac->matchcid && bc->matchcid) {
01102       return strcmp(ac->cidmatch,bc->cidmatch);
01103    } else if (!ac->matchcid && !bc->matchcid) {
01104       return 0; /* if there's no matchcid on either side, then this is a match */
01105    } else {
01106       return 1; /* if there's matchcid on one but not the other, they are different */
01107    }
01108 }

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

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

01131 {
01132    const struct ast_exten *ac = obj;
01133    unsigned int x = ast_hashtab_hash_string(ac->exten);
01134    unsigned int y = 0;
01135    if (ac->matchcid)
01136       y = ast_hashtab_hash_string(ac->cidmatch);
01137    return x+y;
01138 }

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

Definition at line 1146 of file pbx.c.

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

Referenced by ast_add_extension2_lockopt().

01147 {
01148    const struct ast_exten *ac = obj;
01149    return ast_hashtab_hash_string(S_OR(ac->label, ""));
01150 }

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

Definition at line 1140 of file pbx.c.

References ast_hashtab_hash_int(), and ast_exten::priority.

Referenced by ast_add_extension2_lockopt().

01141 {
01142    const struct ast_exten *ac = obj;
01143    return ast_hashtab_hash_int(ac->priority);
01144 }

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

Definition at line 10955 of file pbx.c.

References CMP_MATCH, CMP_STOP, and ast_hint::exten.

Referenced by ast_pbx_init().

10956 {
10957    const struct ast_hint *hint = obj;
10958    const struct ast_exten *exten = arg;
10959 
10960    return (hint->exten == exten) ? CMP_MATCH | CMP_STOP : 0;
10961 }

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

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

10936 {
10937    const struct ast_hint *hint = obj;
10938    const char *exten_name;
10939    int res;
10940 
10941    exten_name = ast_get_extension_name(hint->exten);
10942    if (ast_strlen_zero(exten_name)) {
10943       /*
10944        * If the exten or extension name isn't set, return 0 so that
10945        * the ao2_find() search will start in the first bucket.
10946        */
10947       res = 0;
10948    } else {
10949       res = ast_str_case_hash(exten_name);
10950    }
10951 
10952    return res;
10953 }

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

Definition at line 4895 of file pbx.c.

References CMP_MATCH, CMP_STOP, and ast_state_cb::id.

Referenced by ast_add_hint().

04896 {
04897    const struct ast_state_cb *cb = obj;
04898    int *id = arg;
04899 
04900    return (cb->id == *id) ? CMP_MATCH | CMP_STOP : 0;
04901 }

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

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

10510 {
10511    struct ast_data *data_hint;
10512    struct ast_hint *hint;
10513    int watchers;
10514    struct ao2_iterator i;
10515 
10516    if (ao2_container_count(hints) == 0) {
10517       return 0;
10518    }
10519 
10520    i = ao2_iterator_init(hints, 0);
10521    for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
10522       watchers = ao2_container_count(hint->callbacks);
10523       data_hint = ast_data_add_node(data_root, "hint");
10524       if (!data_hint) {
10525          continue;
10526       }
10527       ast_data_add_str(data_hint, "extension", ast_get_extension_name(hint->exten));
10528       ast_data_add_str(data_hint, "context", ast_get_context_name(ast_get_extension_context(hint->exten)));
10529       ast_data_add_str(data_hint, "application", ast_get_extension_app(hint->exten));
10530       ast_data_add_str(data_hint, "state", ast_extension_state2str(hint->laststate));
10531       ast_data_add_int(data_hint, "watchers", watchers);
10532 
10533       if (!ast_data_search_match(search, data_hint)) {
10534          ast_data_remove_node(data_root, data_hint);
10535       }
10536    }
10537    ao2_iterator_destroy(&i);
10538 
10539    return 0;
10540 }

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

Definition at line 1490 of file pbx.c.

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

Referenced by pbx_find_extension().

01491 {
01492    if (!i->hastime)
01493       return 1;
01494 
01495    return ast_check_timing(&(i->timing));
01496 }

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

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

Referenced by ast_pbx_run_args(), and ast_pbx_start().

05491 {
05492    int failed = 0;
05493    double curloadavg;
05494 #if defined(HAVE_SYSINFO)
05495    long curfreemem;
05496    struct sysinfo sys_info;
05497 #endif
05498 
05499    ast_mutex_lock(&maxcalllock);
05500    if (option_maxcalls) {
05501       if (countcalls >= option_maxcalls) {
05502          ast_log(LOG_WARNING, "Maximum call limit of %d calls exceeded by '%s'!\n", option_maxcalls, c->name);
05503          failed = -1;
05504       }
05505    }
05506    if (option_maxload) {
05507       getloadavg(&curloadavg, 1);
05508       if (curloadavg >= option_maxload) {
05509          ast_log(LOG_WARNING, "Maximum loadavg limit of %f load exceeded by '%s' (currently %f)!\n", option_maxload, c->name, curloadavg);
05510          failed = -1;
05511       }
05512    }
05513 #if defined(HAVE_SYSINFO)
05514    if (option_minmemfree) {
05515       if (!sysinfo(&sys_info)) {
05516          /* make sure that the free system memory is above the configured low watermark
05517           * convert the amount of freeram from mem_units to MB */
05518          curfreemem = sys_info.freeram * sys_info.mem_unit;
05519          curfreemem /= 1024 * 1024;
05520          if (curfreemem < option_minmemfree) {
05521             ast_log(LOG_WARNING, "Available system memory (~%ldMB) is below the configured low watermark (%ldMB)\n", curfreemem, option_minmemfree);
05522             failed = -1;
05523          }
05524       }
05525    }
05526 #endif
05527 
05528    if (!failed) {
05529       countcalls++;
05530       totalcalls++;
05531    }
05532    ast_mutex_unlock(&maxcalllock);
05533 
05534    return failed;
05535 }

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

Definition at line 1908 of file pbx.c.

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

Referenced by add_pattern_node().

01909 {
01910    struct match_char *curr, *lcurr;
01911 
01912    /* insert node into the tree at "current", so the alt_char list from current is
01913       sorted in increasing value as you go to the leaves */
01914    if (!(*parent_ptr)) {
01915       *parent_ptr = node;
01916       return;
01917    }
01918 
01919    if ((*parent_ptr)->specificity > node->specificity) {
01920       /* insert at head */
01921       node->alt_char = (*parent_ptr);
01922       *parent_ptr = node;
01923       return;
01924    } 
01925 
01926    lcurr = *parent_ptr;
01927    for (curr = (*parent_ptr)->alt_char; curr; curr = curr->alt_char) {
01928       if (curr->specificity > node->specificity) {
01929          node->alt_char = curr;
01930          lcurr->alt_char = node;
01931          break;
01932       }
01933       lcurr = curr;
01934    }
01935 
01936    if (!curr) {
01937       lcurr->alt_char = node;
01938    }
01939 
01940 }

int load_pbx ( void   ) 

Provided by pbx.c

Definition at line 10576 of file pbx.c.

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

Referenced by main().

10577 {
10578    int x;
10579 
10580    ast_register_atexit(unload_pbx);
10581 
10582    /* Initialize the PBX */
10583    ast_verb(1, "Asterisk PBX Core Initializing\n");
10584    if (!(device_state_tps = ast_taskprocessor_get("pbx-core", 0))) {
10585       ast_log(LOG_WARNING, "failed to create pbx-core taskprocessor\n");
10586    }
10587 
10588    ast_verb(1, "Registering builtin applications:\n");
10589    ast_cli_register_multiple(pbx_cli, ARRAY_LEN(pbx_cli));
10590    ast_data_register_multiple_core(pbx_data_providers, ARRAY_LEN(pbx_data_providers));
10591    __ast_custom_function_register(&exception_function, NULL);
10592    __ast_custom_function_register(&testtime_function, NULL);
10593 
10594    /* Register builtin applications */
10595    for (x = 0; x < ARRAY_LEN(builtins); x++) {
10596       ast_verb(1, "[%s]\n", builtins[x].name);
10597       if (ast_register_application2(builtins[x].name, builtins[x].execute, NULL, NULL, NULL)) {
10598          ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name);
10599          return -1;
10600       }
10601    }
10602 
10603    /* Register manager application */
10604    ast_manager_register_xml("ShowDialPlan", EVENT_FLAG_CONFIG | EVENT_FLAG_REPORTING, manager_show_dialplan);
10605 
10606    if (!(device_state_sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE, device_state_cb, "pbx Device State Change", NULL,
10607          AST_EVENT_IE_END))) {
10608       return -1;
10609    }
10610 
10611    return 0;
10612 }

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

Referenced by get_range().

07833 {
07834    int i;
07835 
07836    if (names && *s > '9') {
07837       for (i = 0; names[i]; i++) {
07838          if (!strcasecmp(s, names[i])) {
07839             return i;
07840          }
07841       }
07842    }
07843 
07844    /* Allow months and weekdays to be specified as numbers, as well */
07845    if (sscanf(s, "%2d", &i) == 1 && i >= 1 && i <= max) {
07846       /* What the array offset would have been: "1" would be at offset 0 */
07847       return i - 1;
07848    }
07849    return -1; /* error return */
07850 }

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

Send ack once.

Definition at line 6940 of file pbx.c.

References astman_send_listack().

Referenced by manager_show_dialplan(), and manager_show_dialplan_helper().

06941 {
06942    astman_send_listack(s, m, "DialPlan list will follow", "start");
06943 }

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

Manager listing of dial plan.

Definition at line 7085 of file pbx.c.

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

Referenced by load_pbx().

07086 {
07087    const char *exten, *context;
07088    const char *id = astman_get_header(m, "ActionID");
07089    char idtext[256];
07090 
07091    /* Variables used for different counters */
07092    struct dialplan_counters counters;
07093 
07094    if (!ast_strlen_zero(id))
07095       snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id);
07096    else
07097       idtext[0] = '\0';
07098 
07099    memset(&counters, 0, sizeof(counters));
07100 
07101    exten = astman_get_header(m, "Extension");
07102    context = astman_get_header(m, "Context");
07103 
07104    manager_show_dialplan_helper(s, m, idtext, context, exten, &counters, NULL);
07105 
07106    if (!ast_strlen_zero(context) && !counters.context_existence) {
07107       char errorbuf[BUFSIZ];
07108 
07109       snprintf(errorbuf, sizeof(errorbuf), "Did not find context %s", context);
07110       astman_send_error(s, m, errorbuf);
07111       return 0;
07112    }
07113    if (!ast_strlen_zero(exten) && !counters.extension_existence) {
07114       char errorbuf[BUFSIZ];
07115 
07116       if (!ast_strlen_zero(context))
07117          snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s@%s", exten, context);
07118       else
07119          snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s in any context", exten);
07120       astman_send_error(s, m, errorbuf);
07121       return 0;
07122    }
07123 
07124    if (!counters.total_items) {
07125       manager_dpsendack(s, m);
07126    }
07127 
07128    astman_append(s, "Event: ShowDialPlanComplete\r\n"
07129       "EventList: Complete\r\n"
07130       "ListItems: %d\r\n"
07131       "ListExtensions: %d\r\n"
07132       "ListPriorities: %d\r\n"
07133       "ListContexts: %d\r\n"
07134       "%s"
07135       "\r\n", counters.total_items, counters.total_exten, counters.total_prio, counters.total_context, idtext);
07136 
07137    /* everything ok */
07138    return 0;
07139 }

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

06953 {
06954    struct ast_context *c;
06955    int res = 0, old_total_exten = dpc->total_exten;
06956 
06957    if (ast_strlen_zero(exten))
06958       exten = NULL;
06959    if (ast_strlen_zero(context))
06960       context = NULL;
06961 
06962    ast_debug(3, "manager_show_dialplan: Context: -%s- Extension: -%s-\n", context, exten);
06963 
06964    /* try to lock contexts */
06965    if (ast_rdlock_contexts()) {
06966       astman_send_error(s, m, "Failed to lock contexts");
06967       ast_log(LOG_WARNING, "Failed to lock contexts list for manager: listdialplan\n");
06968       return -1;
06969    }
06970 
06971    c = NULL;      /* walk all contexts ... */
06972    while ( (c = ast_walk_contexts(c)) ) {
06973       struct ast_exten *e;
06974       struct ast_include *i;
06975       struct ast_ignorepat *ip;
06976 
06977       if (context && strcmp(ast_get_context_name(c), context) != 0)
06978          continue;   /* not the name we want */
06979 
06980       dpc->context_existence = 1;
06981       dpc->total_context++;
06982 
06983       ast_debug(3, "manager_show_dialplan: Found Context: %s \n", ast_get_context_name(c));
06984 
06985       if (ast_rdlock_context(c)) {  /* failed to lock */
06986          ast_debug(3, "manager_show_dialplan: Failed to lock context\n");
06987          continue;
06988       }
06989 
06990       /* XXX note- an empty context is not printed */
06991       e = NULL;      /* walk extensions in context  */
06992       while ( (e = ast_walk_context_extensions(c, e)) ) {
06993          struct ast_exten *p;
06994 
06995          /* looking for extension? is this our extension? */
06996          if (exten && !ast_extension_match(ast_get_extension_name(e), exten)) {
06997             /* not the one we are looking for, continue */
06998             ast_debug(3, "manager_show_dialplan: Skipping extension %s\n", ast_get_extension_name(e));
06999             continue;
07000          }
07001          ast_debug(3, "manager_show_dialplan: Found Extension: %s \n", ast_get_extension_name(e));
07002 
07003          dpc->extension_existence = 1;
07004 
07005          dpc->total_exten++;
07006 
07007          p = NULL;      /* walk next extension peers */
07008          while ( (p = ast_walk_extension_priorities(e, p)) ) {
07009             int prio = ast_get_extension_priority(p);
07010 
07011             dpc->total_prio++;
07012             if (!dpc->total_items++)
07013                manager_dpsendack(s, m);
07014             astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
07015             astman_append(s, "Context: %s\r\nExtension: %s\r\n", ast_get_context_name(c), ast_get_extension_name(e) );
07016 
07017             /* XXX maybe make this conditional, if p != e ? */
07018             if (ast_get_extension_label(p))
07019                astman_append(s, "ExtensionLabel: %s\r\n", ast_get_extension_label(p));
07020 
07021             if (prio == PRIORITY_HINT) {
07022                astman_append(s, "Priority: hint\r\nApplication: %s\r\n", ast_get_extension_app(p));
07023             } else {
07024                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));
07025             }
07026             astman_append(s, "Registrar: %s\r\n\r\n", ast_get_extension_registrar(e));
07027          }
07028       }
07029 
07030       i = NULL;      /* walk included and write info ... */
07031       while ( (i = ast_walk_context_includes(c, i)) ) {
07032          if (exten) {
07033             /* Check all includes for the requested extension */
07034             manager_show_dialplan_helper(s, m, actionidtext, ast_get_include_name(i), exten, dpc, i);
07035          } else {
07036             if (!dpc->total_items++)
07037                manager_dpsendack(s, m);
07038             astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
07039             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));
07040             astman_append(s, "\r\n");
07041             ast_debug(3, "manager_show_dialplan: Found Included context: %s \n", ast_get_include_name(i));
07042          }
07043       }
07044 
07045       ip = NULL;  /* walk ignore patterns and write info ... */
07046       while ( (ip = ast_walk_context_ignorepats(c, ip)) ) {
07047          const char *ipname = ast_get_ignorepat_name(ip);
07048          char ignorepat[AST_MAX_EXTENSION];
07049 
07050          snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname);
07051          if (!exten || ast_extension_match(ignorepat, exten)) {
07052             if (!dpc->total_items++)
07053                manager_dpsendack(s, m);
07054             astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
07055             astman_append(s, "Context: %s\r\nIgnorePattern: %s\r\nRegistrar: %s\r\n", ast_get_context_name(c), ipname, ast_get_ignorepat_registrar(ip));
07056             astman_append(s, "\r\n");
07057          }
07058       }
07059       if (!rinclude) {
07060          struct ast_sw *sw = NULL;
07061          while ( (sw = ast_walk_context_switches(c, sw)) ) {
07062             if (!dpc->total_items++)
07063                manager_dpsendack(s, m);
07064             astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
07065             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));  
07066             astman_append(s, "\r\n");
07067             ast_debug(3, "manager_show_dialplan: Found Switch : %s \n", ast_get_switch_name(sw));
07068          }
07069       }
07070 
07071       ast_unlock_context(c);
07072    }
07073    ast_unlock_contexts();
07074 
07075    if (dpc->total_exten == old_total_exten) {
07076       ast_debug(3, "manager_show_dialplan: Found nothing new\n");
07077       /* Nothing new under the sun */
07078       return -1;
07079    } else {
07080       return res;
07081    }
07082 }

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

Definition at line 2926 of file pbx.c.

References ast_extension_match(), and ast_strlen_zero().

Referenced by pbx_find_extension().

02927 {
02928    /* If the Caller*ID pattern is empty, then we're matching NO Caller*ID, so
02929       failing to get a number should count as a match, otherwise not */
02930 
02931    if (ast_strlen_zero(callerid)) {
02932       return ast_strlen_zero(cidpattern) ? 1 : 0;
02933    }
02934 
02935    return ast_extension_match(cidpattern, callerid);
02936 }

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

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

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

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

03237 {
03238    int parens = 0;
03239 
03240    *offset = 0;
03241    *length = INT_MAX;
03242    *isfunc = 0;
03243    for (; *var; var++) {
03244       if (*var == '(') {
03245          (*isfunc)++;
03246          parens++;
03247       } else if (*var == ')') {
03248          parens--;
03249       } else if (*var == ':' && parens == 0) {
03250          *var++ = '\0';
03251          sscanf(var, "%30d:%30d", offset, length);
03252          return 1; /* offset:length valid */
03253       }
03254    }
03255    return 0;
03256 }

void pbx_builtin_clear_globals ( void   ) 

Definition at line 10384 of file pbx.c.

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

Referenced by handle_cli_dialplan_reload(), and reload().

10385 {
10386    struct ast_var_t *vardata;
10387 
10388    ast_rwlock_wrlock(&globalslock);
10389    while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries)))
10390       ast_var_delete(vardata);
10391    ast_rwlock_unlock(&globalslock);
10392 }

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

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

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

10149 {
10150    struct ast_var_t *variables;
10151    const char *ret = NULL;
10152    int i;
10153    struct varshead *places[2] = { NULL, &globals };
10154 
10155    if (!name)
10156       return NULL;
10157 
10158    if (chan) {
10159       ast_channel_lock(chan);
10160       places[0] = &chan->varshead;
10161    }
10162 
10163    for (i = 0; i < 2; i++) {
10164       if (!places[i])
10165          continue;
10166       if (places[i] == &globals)
10167          ast_rwlock_rdlock(&globalslock);
10168       AST_LIST_TRAVERSE(places[i], variables, entries) {
10169          if (!strcmp(name, ast_var_name(variables))) {
10170             ret = ast_var_value(variables);
10171             break;
10172          }
10173       }
10174       if (places[i] == &globals)
10175          ast_rwlock_unlock(&globalslock);
10176       if (ret)
10177          break;
10178    }
10179 
10180    if (chan)
10181       ast_channel_unlock(chan);
10182 
10183    return ret;
10184 }

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

Definition at line 10406 of file pbx.c.

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

10407 {
10408    char *condition, *branch1, *branch2, *branch;
10409    char *stringp;
10410 
10411    if (ast_strlen_zero(data)) {
10412       ast_log(LOG_WARNING, "Ignoring, since there is no variable to check\n");
10413       return 0;
10414    }
10415 
10416    stringp = ast_strdupa(data);
10417    condition = strsep(&stringp,"?");
10418    branch1 = strsep(&stringp,":");
10419    branch2 = strsep(&stringp,"");
10420    branch = pbx_checkcondition(condition) ? branch1 : branch2;
10421 
10422    if (ast_strlen_zero(branch)) {
10423       ast_debug(1, "Not taking any branch\n");
10424       return 0;
10425    }
10426 
10427    return pbx_builtin_goto(chan, branch);
10428 }

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

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

10345 {
10346    char *name;
10347    char *value;
10348    char *channel;
10349    char tmp[VAR_BUF_SIZE];
10350    static int deprecation_warning = 0;
10351 
10352    if (ast_strlen_zero(data)) {
10353       ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n");
10354       return 0;
10355    }
10356    tmp[0] = 0;
10357    if (!deprecation_warning) {
10358       ast_log(LOG_WARNING, "ImportVar is deprecated.  Please use Set(varname=${IMPORT(channel,variable)}) instead.\n");
10359       deprecation_warning = 1;
10360    }
10361 
10362    value = ast_strdupa(data);
10363    name = strsep(&value,"=");
10364    channel = strsep(&value,",");
10365    if (channel && value && name) { /*! \todo XXX should do !ast_strlen_zero(..) of the args ? */
10366       struct ast_channel *chan2 = ast_channel_get_by_name(channel);
10367       if (chan2) {
10368          char *s = ast_alloca(strlen(value) + 4);
10369          sprintf(s, "${%s}", value);
10370          pbx_substitute_variables_helper(chan2, s, tmp, sizeof(tmp) - 1);
10371          chan2 = ast_channel_unref(chan2);
10372       }
10373       pbx_builtin_setvar_helper(chan, name, tmp);
10374    }
10375 
10376    return(0);
10377 }

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

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

09670 {
09671    const char *options = data;
09672    int answer = 1;
09673 
09674    /* Some channels can receive DTMF in unanswered state; some cannot */
09675    if (!ast_strlen_zero(options) && strchr(options, 'n')) {
09676       answer = 0;
09677    }
09678 
09679    /* If the channel is hungup, stop waiting */
09680    if (ast_check_hangup(chan)) {
09681       return -1;
09682    } else if (chan->_state != AST_STATE_UP && answer) {
09683       __ast_answer(chan, 0, 1);
09684    }
09685 
09686    ast_indicate(chan, AST_CONTROL_INCOMPLETE);
09687 
09688    return AST_PBX_INCOMPLETE;
09689 }

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

Definition at line 10379 of file pbx.c.

10380 {
10381    return 0;
10382 }

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

10187 {
10188    struct ast_var_t *newvariable;
10189    struct varshead *headp;
10190 
10191    if (name[strlen(name)-1] == ')') {
10192       char *function = ast_strdupa(name);
10193 
10194       ast_log(LOG_WARNING, "Cannot push a value onto a function\n");
10195       ast_func_write(chan, function, value);
10196       return;
10197    }
10198 
10199    if (chan) {
10200       ast_channel_lock(chan);
10201       headp = &chan->varshead;
10202    } else {
10203       ast_rwlock_wrlock(&globalslock);
10204       headp = &globals;
10205    }
10206 
10207    if (value) {
10208       if (headp == &globals)
10209          ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value);
10210       newvariable = ast_var_assign(name, value);
10211       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
10212    }
10213 
10214    if (chan)
10215       ast_channel_unlock(chan);
10216    else
10217       ast_rwlock_unlock(&globalslock);
10218 }

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

Definition at line 3545 of file pbx.c.

References raise_exception().

03546 {
03547    /* Priority will become 1, next time through the AUTOLOOP */
03548    return raise_exception(chan, reason, 0);
03549 }

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

Definition at line 10467 of file pbx.c.

References ast_say_character_str().

10468 {
10469    int res = 0;
10470 
10471    if (data)
10472       res = ast_say_character_str(chan, data, "", chan->language);
10473    return res;
10474 }

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

Definition at line 10458 of file pbx.c.

References ast_say_digit_str().

10459 {
10460    int res = 0;
10461 
10462    if (data)
10463       res = ast_say_digit_str(chan, data, "", chan->language);
10464    return res;
10465 }

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

Definition at line 10430 of file pbx.c.

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

10431 {
10432    char tmp[256];
10433    char *number = tmp;
10434    char *options;
10435 
10436    if (ast_strlen_zero(data)) {
10437       ast_log(LOG_WARNING, "SayNumber requires an argument (number)\n");
10438       return -1;
10439    }
10440    ast_copy_string(tmp, data, sizeof(tmp));
10441    strsep(&number, ",");
10442    options = strsep(&number, ",");
10443    if (options) {
10444       if ( strcasecmp(options, "f") && strcasecmp(options, "m") &&
10445          strcasecmp(options, "c") && strcasecmp(options, "n") ) {
10446          ast_log(LOG_WARNING, "SayNumber gender option is either 'f', 'm', 'c' or 'n'\n");
10447          return -1;
10448       }
10449    }
10450 
10451    if (ast_say_number(chan, atoi(tmp), "", chan->language, options)) {
10452       ast_log(LOG_WARNING, "We were unable to say the number %s, is it too large?\n", tmp);
10453    }
10454 
10455    return 0;
10456 }

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

Definition at line 10476 of file pbx.c.

References ast_say_phonetic_str().

10477 {
10478    int res = 0;
10479 
10480    if (data)
10481       res = ast_say_phonetic_str(chan, data, "", chan->language);
10482    return res;
10483 }

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

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

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

10118 {
10119    struct ast_var_t *variables;
10120    const char *var, *val;
10121    int total = 0;
10122 
10123    if (!chan)
10124       return 0;
10125 
10126    ast_str_reset(*buf);
10127 
10128    ast_channel_lock(chan);
10129 
10130    AST_LIST_TRAVERSE(&chan->varshead, variables, entries) {
10131       if ((var = ast_var_name(variables)) && (val = ast_var_value(variables))
10132          /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */
10133          ) {
10134          if (ast_str_append(buf, 0, "%s=%s\n", var, val) < 0) {
10135             ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
10136             break;
10137          } else
10138             total++;
10139       } else
10140          break;
10141    }
10142 
10143    ast_channel_unlock(chan);
10144 
10145    return total;
10146 }

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

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

Referenced by ast_compile_ael2().

10279 {
10280    char *name, *value, *mydata;
10281 
10282    if (ast_compat_app_set) {
10283       return pbx_builtin_setvar_multiple(chan, data);
10284    }
10285 
10286    if (ast_strlen_zero(data)) {
10287       ast_log(LOG_WARNING, "Set requires one variable name/value pair.\n");
10288       return 0;
10289    }
10290 
10291    mydata = ast_strdupa(data);
10292    name = strsep(&mydata, "=");
10293    value = mydata;
10294    if (!value) {
10295       ast_log(LOG_WARNING, "Set requires an '=' to be a valid assignment.\n");
10296       return 0;
10297    }
10298 
10299    if (strchr(name, ' ')) {
10300       ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, mydata);
10301    }
10302 
10303    pbx_builtin_setvar_helper(chan, name, value);
10304 
10305    return 0;
10306 }

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

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

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

10221 {
10222    struct ast_var_t *newvariable;
10223    struct varshead *headp;
10224    const char *nametail = name;
10225 
10226    if (name[strlen(name) - 1] == ')') {
10227       char *function = ast_strdupa(name);
10228 
10229       return ast_func_write(chan, function, value);
10230    }
10231 
10232    if (chan) {
10233       ast_channel_lock(chan);
10234       headp = &chan->varshead;
10235    } else {
10236       ast_rwlock_wrlock(&globalslock);
10237       headp = &globals;
10238    }
10239 
10240    /* For comparison purposes, we have to strip leading underscores */
10241    if (*nametail == '_') {
10242       nametail++;
10243       if (*nametail == '_')
10244          nametail++;
10245    }
10246 
10247    AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) {
10248       if (strcmp(ast_var_name(newvariable), nametail) == 0) {
10249          /* there is already such a variable, delete it */
10250          AST_LIST_REMOVE_CURRENT(entries);
10251          ast_var_delete(newvariable);
10252          break;
10253       }
10254    }
10255    AST_LIST_TRAVERSE_SAFE_END;
10256 
10257    if (value) {
10258       if (headp == &globals)
10259          ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value);
10260       newvariable = ast_var_assign(name, value);
10261       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
10262       manager_event(EVENT_FLAG_DIALPLAN, "VarSet",
10263          "Channel: %s\r\n"
10264          "Variable: %s\r\n"
10265          "Value: %s\r\n"
10266          "Uniqueid: %s\r\n",
10267          chan ? chan->name : "none", name, value,
10268          chan ? chan->uniqueid : "none");
10269    }
10270 
10271    if (chan)
10272       ast_channel_unlock(chan);
10273    else
10274       ast_rwlock_unlock(&globalslock);
10275    return 0;
10276 }

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

10309 {
10310    char *data;
10311    int x;
10312    AST_DECLARE_APP_ARGS(args,
10313       AST_APP_ARG(pair)[24];
10314    );
10315    AST_DECLARE_APP_ARGS(pair,
10316       AST_APP_ARG(name);
10317       AST_APP_ARG(value);
10318    );
10319 
10320    if (ast_strlen_zero(vdata)) {
10321       ast_log(LOG_WARNING, "MSet requires at least one variable name/value pair.\n");
10322       return 0;
10323    }
10324 
10325    data = ast_strdupa(vdata);
10326    AST_STANDARD_APP_ARGS(args, data);
10327 
10328    for (x = 0; x < args.argc; x++) {
10329       AST_NONSTANDARD_APP_ARGS(pair, args.pair[x], '=');
10330       if (pair.argc == 2) {
10331          pbx_builtin_setvar_helper(chan, pair.name, pair.value);
10332          if (strchr(pair.name, ' '))
10333             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);
10334       } else if (!chan) {
10335          ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '='\n", pair.name);
10336       } else {
10337          ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '=' (in %s@%s:%d\n", pair.name, chan->exten, chan->context, chan->priority);
10338       }
10339    }
10340 
10341    return 0;
10342 }

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

10395 {
10396    int res;
10397    if (ast_strlen_zero(condition)) {                /* NULL or empty strings are false */
10398       return 0;
10399    } else if (sscanf(condition, "%30d", &res) == 1) { /* Numbers are evaluated for truth */
10400       return res;
10401    } else {                                         /* Strings are true */
10402       return 1;
10403    }
10404 }

static void pbx_destroy ( struct ast_pbx p  )  [static]

Definition at line 1498 of file pbx.c.

References ast_free.

Referenced by __ast_pbx_run().

01499 {
01500    ast_free(p);
01501 }

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

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

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

01421 {
01422    int res;
01423    struct ast_module_user *u = NULL;
01424    const char *saved_c_appl;
01425    const char *saved_c_data;
01426 
01427    if (c->cdr && !ast_check_hangup(c))
01428       ast_cdr_setapp(c->cdr, app->name, data);
01429 
01430    /* save channel values */
01431    saved_c_appl= c->appl;
01432    saved_c_data= c->data;
01433 
01434    c->appl = app->name;
01435    c->data = data;
01436    ast_cel_report_event(c, AST_CEL_APP_START, NULL, NULL, NULL);
01437 
01438    if (app->module)
01439       u = __ast_module_user_add(app->module, c);
01440    if (strcasecmp(app->name, "system") && !ast_strlen_zero(data) &&
01441          strchr(data, '|') && !strchr(data, ',') && !ast_opt_dont_warn) {
01442       ast_log(LOG_WARNING, "The application delimiter is now the comma, not "
01443          "the pipe.  Did you forget to convert your dialplan?  (%s(%s))\n",
01444          app->name, (char *) data);
01445    }
01446    res = app->execute(c, S_OR(data, ""));
01447    if (app->module && u)
01448       __ast_module_user_remove(app->module, u);
01449    ast_cel_report_event(c, AST_CEL_APP_END, NULL, NULL, NULL);
01450    /* restore channel values */
01451    c->appl = saved_c_appl;
01452    c->data = saved_c_data;
01453    return res;
01454 }

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

References ast_exten::app, app, ast_copy_string(), ast_debug, ast_log(), ast_rdlock_contexts(), ast_unlock_contexts(), ast_verb, ast_exten::cached_app, COLOR_BRCYAN, COLOR_BRMAGENTA, ast_channel::context, pbx_find_info::data, E_CANMATCH, E_FINDLABEL, E_MATCH, E_MATCHMORE, EVENT_FLAG_DIALPLAN, ast_switch::exec, EXT_DATA_SIZE, ast_channel::exten, pbx_find_info::foundcontext, LOG_NOTICE, LOG_WARNING, manager_event, ast_switch::name, ast_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().

04428 {
04429    struct ast_exten *e;
04430    struct ast_app *app;
04431    int res;
04432    struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */
04433    char passdata[EXT_DATA_SIZE];
04434 
04435    int matching_action = (action == E_MATCH || action == E_CANMATCH || action == E_MATCHMORE);
04436 
04437    ast_rdlock_contexts();
04438    if (found)
04439       *found = 0;
04440 
04441    e = pbx_find_extension(c, con, &q, context, exten, priority, label, callerid, action);
04442    if (e) {
04443       if (found)
04444          *found = 1;
04445       if (matching_action) {
04446          ast_unlock_contexts();
04447          return -1;  /* success, we found it */
04448       } else if (action == E_FINDLABEL) { /* map the label to a priority */
04449          res = e->priority;
04450          ast_unlock_contexts();
04451          return res; /* the priority we were looking for */
04452       } else { /* spawn */
04453          if (!e->cached_app)
04454             e->cached_app = pbx_findapp(e->app);
04455          app = e->cached_app;
04456          ast_unlock_contexts();
04457          if (!app) {
04458             ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority);
04459             return -1;
04460          }
04461          if (c->context != context)
04462             ast_copy_string(c->context, context, sizeof(c->context));
04463          if (c->exten != exten)
04464             ast_copy_string(c->exten, exten, sizeof(c->exten));
04465          c->priority = priority;
04466          pbx_substitute_variables(passdata, sizeof(passdata), c, e);
04467 #ifdef CHANNEL_TRACE
04468          ast_channel_trace_update(c);
04469 #endif
04470          ast_debug(1, "Launching '%s'\n", app->name);
04471          if (VERBOSITY_ATLEAST(3)) {
04472             char tmp[80], tmp2[80], tmp3[EXT_DATA_SIZE];
04473             ast_verb(3, "Executing [%s@%s:%d] %s(\"%s\", \"%s\") %s\n",
04474                exten, context, priority,
04475                term_color(tmp, app->name, COLOR_BRCYAN, 0, sizeof(tmp)),
04476                term_color(tmp2, c->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)),
04477                term_color(tmp3, passdata, COLOR_BRMAGENTA, 0, sizeof(tmp3)),
04478                "in new stack");
04479          }
04480          manager_event(EVENT_FLAG_DIALPLAN, "Newexten",
04481                "Channel: %s\r\n"
04482                "Context: %s\r\n"
04483                "Extension: %s\r\n"
04484                "Priority: %d\r\n"
04485                "Application: %s\r\n"
04486                "AppData: %s\r\n"
04487                "Uniqueid: %s\r\n",
04488                c->name, c->context, c->exten, c->priority, app->name, passdata, c->uniqueid);
04489          return pbx_exec(c, app, passdata);  /* 0 on success, -1 on failure */
04490       }
04491    } else if (q.swo) {  /* not found here, but in another switch */
04492       if (found)
04493          *found = 1;
04494       ast_unlock_contexts();
04495       if (matching_action) {
04496          return -1;
04497       } else {
04498          if (!q.swo->exec) {
04499             ast_log(LOG_WARNING, "No execution engine for switch %s\n", q.swo->name);
04500             res = -1;
04501          }
04502          return q.swo->exec(c, q.foundcontext ? q.foundcontext : context, exten, priority, callerid, q.data);
04503       }
04504    } else { /* not found anywhere, see what happened */
04505       ast_unlock_contexts();
04506       /* Using S_OR here because Solaris doesn't like NULL being passed to ast_log */
04507       switch (q.status) {
04508       case STATUS_NO_CONTEXT:
04509          if (!matching_action && !combined_find_spawn)
04510             ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", S_OR(context, ""));
04511          break;
04512       case STATUS_NO_EXTENSION:
04513          if (!matching_action && !combined_find_spawn)
04514             ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, S_OR(context, ""));
04515          break;
04516       case STATUS_NO_PRIORITY:
04517          if (!matching_action && !combined_find_spawn)
04518             ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, S_OR(context, ""));
04519          break;
04520       case STATUS_NO_LABEL:
04521          if (context && !combined_find_spawn)
04522             ast_log(LOG_NOTICE, "No such label '%s' in extension '%s' in context '%s'\n", label, exten, S_OR(context, ""));
04523          break;
04524       default:
04525          ast_debug(1, "Shouldn't happen!\n");
04526       }
04527 
04528       return (matching_action) ? 0 : -1;
04529    }
04530 }

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

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

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

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

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

Definition at line 1476 of file pbx.c.

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

Referenced by pbx_find_extension().

01477 {
01478    struct ast_switch *asw;
01479 
01480    AST_RWLIST_RDLOCK(&switches);
01481    AST_RWLIST_TRAVERSE(&switches, asw, list) {
01482       if (!strcasecmp(asw->name, sw))
01483          break;
01484    }
01485    AST_RWLIST_UNLOCK(&switches);
01486 
01487    return asw;
01488 }

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

Definition at line 10851 of file pbx.c.

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

Referenced by ast_async_parseable_goto(), and ast_parseable_goto().

10852 {
10853    char *exten, *pri, *context;
10854    char *stringp;
10855    int ipri;
10856    int mode = 0;
10857 
10858    if (ast_strlen_zero(goto_string)) {
10859       ast_log(LOG_WARNING, "Goto requires an argument ([[context,]extension,]priority)\n");
10860       return -1;
10861    }
10862    stringp = ast_strdupa(goto_string);
10863    context = strsep(&stringp, ","); /* guaranteed non-null */
10864    exten = strsep(&stringp, ",");
10865    pri = strsep(&stringp, ",");
10866    if (!exten) {  /* Only a priority in this one */
10867       pri = context;
10868       exten = NULL;
10869       context = NULL;
10870    } else if (!pri) {   /* Only an extension and priority in this one */
10871       pri = exten;
10872       exten = context;
10873       context = NULL;
10874    }
10875    if (*pri == '+') {
10876       mode = 1;
10877       pri++;
10878    } else if (*pri == '-') {
10879       mode = -1;
10880       pri++;
10881    }
10882    if (sscanf(pri, "%30d", &ipri) != 1) {
10883       ipri = ast_findlabel_extension(chan, context ? context : chan->context,
10884          exten ? exten : chan->exten, pri,
10885          S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL));
10886       if (ipri < 1) {
10887          ast_log(LOG_WARNING, "Priority '%s' must be a number > 0, or valid label\n", pri);
10888          return -1;
10889       } else
10890          mode = 0;
10891    }
10892    /* At this point we have a priority and maybe an extension and a context */
10893 
10894    if (mode)
10895       ipri = chan->priority + (ipri * mode);
10896 
10897    if (async)
10898       ast_async_goto(chan, context, exten, ipri);
10899    else
10900       ast_explicit_goto(chan, context, exten, ipri);
10901 
10902    return 0;
10903 
10904 }

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

03360 {
03361    struct ast_str *str = ast_str_create(16);
03362    const char *cret;
03363 
03364    cret = ast_str_retrieve_variable(&str, 0, c, headp, var);
03365    ast_copy_string(workspace, ast_str_buffer(str), workspacelen);
03366    *ret = cret ? workspace : NULL;
03367    ast_free(str);
03368 }

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

References autofallthrough.

Referenced by pbx_load_module().

05642 {
05643    int oldval = autofallthrough;
05644    autofallthrough = newval;
05645    return oldval;
05646 }

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

References extenpatternmatchnew.

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

05649 {
05650    int oldval = extenpatternmatchnew;
05651    extenpatternmatchnew = newval;
05652    return oldval;
05653 }

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

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

Referenced by pbx_load_module().

05656 {
05657    if (overrideswitch) {
05658       ast_free(overrideswitch);
05659    }
05660    if (!ast_strlen_zero(newval)) {
05661       overrideswitch = ast_strdup(newval);
05662    } else {
05663       overrideswitch = NULL;
05664    }
05665 }

static void pbx_shutdown ( void   )  [static]

Definition at line 10971 of file pbx.c.

References ao2_ref, hints, and statecbs.

Referenced by ast_pbx_init().

10972 {
10973    if (hints) {
10974       ao2_ref(hints, -1);
10975       hints = NULL;
10976    }
10977    if (statecbs) {
10978       ao2_ref(statecbs, -1);
10979       statecbs = NULL;
10980    }
10981 }

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

Definition at line 4388 of file pbx.c.

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

Referenced by pbx_extension_helper().

04389 {
04390    const char *tmp;
04391 
04392    /* Nothing more to do */
04393    if (!e->data) {
04394       *passdata = '\0';
04395       return;
04396    }
04397 
04398    /* No variables or expressions in e->data, so why scan it? */
04399    if ((!(tmp = strchr(e->data, '$'))) || (!strstr(tmp, "${") && !strstr(tmp, "$["))) {
04400       ast_copy_string(passdata, e->data, datalen);
04401       return;
04402    }
04403 
04404    pbx_substitute_variables_helper(c, e->data, passdata, datalen - 1);
04405 }

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

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

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

04181 {
04182    /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!!  */
04183    char *cp4 = NULL;
04184    const char *tmp, *whereweare, *orig_cp2 = cp2;
04185    int length, offset, offset2, isfunction;
04186    char *workspace = NULL;
04187    char *ltmp = NULL, *var = NULL;
04188    char *nextvar, *nextexp, *nextthing;
04189    char *vars, *vare;
04190    int pos, brackets, needsub, len;
04191 
04192    *cp2 = 0; /* just in case nothing ends up there */
04193    whereweare=tmp=cp1;
04194    while (!ast_strlen_zero(whereweare) && count) {
04195       /* Assume we're copying the whole remaining string */
04196       pos = strlen(whereweare);
04197       nextvar = NULL;
04198       nextexp = NULL;
04199       nextthing = strchr(whereweare, '$');
04200       if (nextthing) {
04201          switch (nextthing[1]) {
04202          case '{':
04203             nextvar = nextthing;
04204             pos = nextvar - whereweare;
04205             break;
04206          case '[':
04207             nextexp = nextthing;
04208             pos = nextexp - whereweare;
04209             break;
04210          default:
04211             pos = 1;
04212          }
04213       }
04214 
04215       if (pos) {
04216          /* Can't copy more than 'count' bytes */
04217          if (pos > count)
04218             pos = count;
04219 
04220          /* Copy that many bytes */
04221          memcpy(cp2, whereweare, pos);
04222 
04223          count -= pos;
04224          cp2 += pos;
04225          whereweare += pos;
04226          *cp2 = 0;
04227       }
04228 
04229       if (nextvar) {
04230          /* We have a variable.  Find the start and end, and determine
04231             if we are going to have to recursively call ourselves on the
04232             contents */
04233          vars = vare = nextvar + 2;
04234          brackets = 1;
04235          needsub = 0;
04236 
04237          /* Find the end of it */
04238          while (brackets && *vare) {
04239             if ((vare[0] == '$') && (vare[1] == '{')) {
04240                needsub++;
04241             } else if (vare[0] == '{') {
04242                brackets++;
04243             } else if (vare[0] == '}') {
04244                brackets--;
04245             } else if ((vare[0] == '$') && (vare[1] == '['))
04246                needsub++;
04247             vare++;
04248          }
04249          if (brackets)
04250             ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n");
04251          len = vare - vars - 1;
04252 
04253          /* Skip totally over variable string */
04254          whereweare += (len + 3);
04255 
04256          if (!var)
04257             var = ast_alloca(VAR_BUF_SIZE);
04258 
04259          /* Store variable name (and truncate) */
04260          ast_copy_string(var, vars, len + 1);
04261 
04262          /* Substitute if necessary */
04263          if (needsub) {
04264             size_t used;
04265             if (!ltmp)
04266                ltmp = ast_alloca(VAR_BUF_SIZE);
04267 
04268             pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used);
04269             vars = ltmp;
04270          } else {
04271             vars = var;
04272          }
04273 
04274          if (!workspace)
04275             workspace = ast_alloca(VAR_BUF_SIZE);
04276 
04277          workspace[0] = '\0';
04278 
04279          parse_variable_name(vars, &offset, &offset2, &isfunction);
04280          if (isfunction) {
04281             /* Evaluate function */
04282             if (c || !headp)
04283                cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
04284             else {
04285                struct varshead old;
04286                struct ast_channel *c = ast_dummy_channel_alloc();
04287                if (c) {
04288                   memcpy(&old, &c->varshead, sizeof(old));
04289                   memcpy(&c->varshead, headp, sizeof(c->varshead));
04290                   cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
04291                   /* Don't deallocate the varshead that was passed in */
04292                   memcpy(&c->varshead, &old, sizeof(c->varshead));
04293                   c = ast_channel_unref(c);
04294                } else {
04295                   ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution.  Function results may be blank.\n");
04296                }
04297             }
04298             ast_debug(2, "Function result is '%s'\n", cp4 ? cp4 : "(null)");
04299          } else {
04300             /* Retrieve variable value */
04301             pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp);
04302          }
04303          if (cp4) {
04304             cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE);
04305 
04306             length = strlen(cp4);
04307             if (length > count)
04308                length = count;
04309             memcpy(cp2, cp4, length);
04310             count -= length;
04311             cp2 += length;
04312             *cp2 = 0;
04313          }
04314       } else if (nextexp) {
04315          /* We have an expression.  Find the start and end, and determine
04316             if we are going to have to recursively call ourselves on the
04317             contents */
04318          vars = vare = nextexp + 2;
04319          brackets = 1;
04320          needsub = 0;
04321 
04322          /* Find the end of it */
04323          while (brackets && *vare) {
04324             if ((vare[0] == '$') && (vare[1] == '[')) {
04325                needsub++;
04326                brackets++;
04327                vare++;
04328             } else if (vare[0] == '[') {
04329                brackets++;
04330             } else if (vare[0] == ']') {
04331                brackets--;
04332             } else if ((vare[0] == '$') && (vare[1] == '{')) {
04333                needsub++;
04334                vare++;
04335             }
04336             vare++;
04337          }
04338          if (brackets)
04339             ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n");
04340          len = vare - vars - 1;
04341 
04342          /* Skip totally over expression */
04343          whereweare += (len + 3);
04344 
04345          if (!var)
04346             var = ast_alloca(VAR_BUF_SIZE);
04347 
04348          /* Store variable name (and truncate) */
04349          ast_copy_string(var, vars, len + 1);
04350 
04351          /* Substitute if necessary */
04352          if (needsub) {
04353             size_t used;
04354             if (!ltmp)
04355                ltmp = ast_alloca(VAR_BUF_SIZE);
04356 
04357             pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used);
04358             vars = ltmp;
04359          } else {
04360             vars = var;
04361          }
04362 
04363          length = ast_expr(vars, cp2, count, c);
04364 
04365          if (length) {
04366             ast_debug(1, "Expression result is '%s'\n", cp2);
04367             count -= length;
04368             cp2 += length;
04369             *cp2 = 0;
04370          }
04371       }
04372    }
04373    *used = cp2 - orig_cp2;
04374 }

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

Definition at line 4382 of file pbx.c.

References pbx_substitute_variables_helper_full().

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

04383 {
04384    size_t used;
04385    pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count, &used);
04386 }

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

Definition at line 5559 of file pbx.c.

References __ast_pbx_run(), and decrease_call_count().

Referenced by ast_pbx_start().

05560 {
05561    /* Oh joyeous kernel, we're a new thread, with nothing to do but
05562       answer this channel and get it going.
05563    */
05564    /* NOTE:
05565       The launcher of this function _MUST_ increment 'countcalls'
05566       before invoking the function; it will be decremented when the
05567       PBX has finished running on the channel
05568     */
05569    struct ast_channel *c = data;
05570 
05571    __ast_pbx_run(c, NULL);
05572    decrease_call_count();
05573 
05574    pthread_exit(NULL);
05575 
05576    return NULL;
05577 }

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

Definition at line 6171 of file pbx.c.

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

Referenced by handle_show_application().

06172 {
06173    /* Maximum number of characters added by terminal coloring is 22 */
06174    char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40], stxtitle[40], argtitle[40];
06175    char seealsotitle[40];
06176    char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL, *syntax = NULL, *arguments = NULL;
06177    char *seealso = NULL;
06178    int syntax_size, synopsis_size, description_size, arguments_size, seealso_size;
06179 
06180    snprintf(info, sizeof(info), "\n  -= Info about application '%s' =- \n\n", aa->name);
06181    term_color(infotitle, info, COLOR_MAGENTA, 0, sizeof(infotitle));
06182 
06183    term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
06184    term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
06185    term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40);
06186    term_color(argtitle, "[Arguments]\n", COLOR_MAGENTA, 0, 40);
06187    term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, 40);
06188 
06189 #ifdef AST_XML_DOCS
06190    if (aa->docsrc == AST_XML_DOC) {
06191       description = ast_xmldoc_printable(S_OR(aa->description, "Not available"), 1);
06192       arguments = ast_xmldoc_printable(S_OR(aa->arguments, "Not available"), 1);
06193       synopsis = ast_xmldoc_printable(S_OR(aa->synopsis, "Not available"), 1);
06194       seealso = ast_xmldoc_printable(S_OR(aa->seealso, "Not available"), 1);
06195 
06196       if (!synopsis || !description || !arguments || !seealso) {
06197          goto return_cleanup;
06198       }
06199    } else
06200 #endif
06201    {
06202       synopsis_size = strlen(S_OR(aa->synopsis, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
06203       synopsis = ast_malloc(synopsis_size);
06204 
06205       description_size = strlen(S_OR(aa->description, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
06206       description = ast_malloc(description_size);
06207 
06208       arguments_size = strlen(S_OR(aa->arguments, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
06209       arguments = ast_malloc(arguments_size);
06210 
06211       seealso_size = strlen(S_OR(aa->seealso, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
06212       seealso = ast_malloc(seealso_size);
06213 
06214       if (!synopsis || !description || !arguments || !seealso) {
06215          goto return_cleanup;
06216       }
06217 
06218       term_color(synopsis, S_OR(aa->synopsis, "Not available"), COLOR_CYAN, 0, synopsis_size);
06219       term_color(description, S_OR(aa->description, "Not available"),   COLOR_CYAN, 0, description_size);
06220       term_color(arguments, S_OR(aa->arguments, "Not available"), COLOR_CYAN, 0, arguments_size);
06221       term_color(seealso, S_OR(aa->seealso, "Not available"), COLOR_CYAN, 0, seealso_size);
06222    }
06223 
06224    /* Handle the syntax the same for both XML and raw docs */
06225    syntax_size = strlen(S_OR(aa->syntax, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
06226    if (!(syntax = ast_malloc(syntax_size))) {
06227       goto return_cleanup;
06228    }
06229    term_color(syntax, S_OR(aa->syntax, "Not available"), COLOR_CYAN, 0, syntax_size);
06230 
06231    ast_cli(fd, "%s%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n",
06232          infotitle, syntitle, synopsis, destitle, description,
06233          stxtitle, syntax, argtitle, arguments, seealsotitle, seealso);
06234 
06235 return_cleanup:
06236    ast_free(description);
06237    ast_free(arguments);
06238    ast_free(synopsis);
06239    ast_free(seealso);
06240    ast_free(syntax);
06241 }

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

helper function to print an extension

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

06598 {
06599    int prio = ast_get_extension_priority(e);
06600    if (prio == PRIORITY_HINT) {
06601       snprintf(buf, buflen, "hint: %s",
06602          ast_get_extension_app(e));
06603    } else {
06604       snprintf(buf, buflen, "%d. %s(%s)",
06605          prio, ast_get_extension_app(e),
06606          (!ast_strlen_zero(ast_get_extension_app_data(e)) ? (char *)ast_get_extension_app_data(e) : ""));
06607    }
06608 }

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

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

03520 {
03521    struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL);
03522    struct pbx_exception *exception = NULL;
03523 
03524    if (!ds) {
03525       ds = ast_datastore_alloc(&exception_store_info, NULL);
03526       if (!ds)
03527          return -1;
03528       if (!(exception = ast_calloc_with_stringfields(1, struct pbx_exception, 128))) {
03529          ast_datastore_free(ds);
03530          return -1;
03531       }
03532       ds->data = exception;
03533       ast_channel_datastore_add(chan, ds);
03534    } else
03535       exception = ds->data;
03536 
03537    ast_string_field_set(exception, reason, reason);
03538    ast_string_field_set(exception, context, chan->context);
03539    ast_string_field_set(exception, exten, chan->exten);
03540    exception->priority = chan->priority;
03541    set_ext_pri(chan, "e", priority);
03542    return 0;
03543 }

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

05132 {
05133    ast_channel_lock(c);
05134    ast_copy_string(c->exten, exten, sizeof(c->exten));
05135    c->priority = pri;
05136    ast_channel_unlock(c);
05137 }

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

06763 {
06764    struct ast_context *c = NULL;
06765    int res = 0, old_total_exten = dpc->total_exten;
06766 
06767    ast_cli(fd,"\n     In-mem exten Trie for Fast Extension Pattern Matching:\n\n");
06768 
06769    ast_cli(fd,"\n           Explanation: Node Contents Format = <char(s) to match>:<pattern?>:<specif>:[matched extension]\n");
06770    ast_cli(fd,    "                        Where <char(s) to match> is a set of chars, any one of which should match the current character\n");
06771    ast_cli(fd,    "                              <pattern?>: Y if this a pattern match (eg. _XZN[5-7]), N otherwise\n");
06772    ast_cli(fd,    "                              <specif>: an assigned 'exactness' number for this matching char. The lower the number, the more exact the match\n");
06773    ast_cli(fd,    "                              [matched exten]: If all chars matched to this point, which extension this matches. In form: EXTEN:<exten string>\n");
06774    ast_cli(fd,    "                        In general, you match a trie node to a string character, from left to right. All possible matching chars\n");
06775    ast_cli(fd,    "                        are in a string vertically, separated by an unbroken string of '+' characters.\n\n");
06776    ast_rdlock_contexts();
06777 
06778    /* walk all contexts ... */
06779    while ( (c = ast_walk_contexts(c)) ) {
06780       int context_info_printed = 0;
06781 
06782       if (context && strcmp(ast_get_context_name(c), context))
06783          continue;   /* skip this one, name doesn't match */
06784 
06785       dpc->context_existence = 1;
06786 
06787       if (!c->pattern_tree) {
06788          /* Ignore check_return warning from Coverity for ast_exists_extension below */
06789          ast_exists_extension(NULL, c->name, "s", 1, ""); /* do this to force the trie to built, if it is not already */
06790       }
06791 
06792       ast_rdlock_context(c);
06793 
06794       dpc->total_context++;
06795       ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
06796          ast_get_context_name(c), ast_get_context_registrar(c));
06797       context_info_printed = 1;
06798 
06799       if (c->pattern_tree)
06800       {
06801          cli_match_char_tree(c->pattern_tree, " ", fd);
06802       } else {
06803          ast_cli(fd,"\n     No Pattern Trie present. Perhaps the context is empty...or there is trouble...\n\n");
06804       }
06805 
06806       ast_unlock_context(c);
06807 
06808       /* if we print something in context, make an empty line */
06809       if (context_info_printed)
06810          ast_cli(fd, "\n");
06811    }
06812    ast_unlock_contexts();
06813 
06814    return (dpc->total_exten == old_total_exten) ? -1 : res;
06815 }

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

06612 {
06613    struct ast_context *c = NULL;
06614    int res = 0, old_total_exten = dpc->total_exten;
06615 
06616    ast_rdlock_contexts();
06617 
06618    /* walk all contexts ... */
06619    while ( (c = ast_walk_contexts(c)) ) {
06620       struct ast_exten *e;
06621       struct ast_include *i;
06622       struct ast_ignorepat *ip;
06623       char buf[256], buf2[256];
06624       int context_info_printed = 0;
06625 
06626       if (context && strcmp(ast_get_context_name(c), context))
06627          continue;   /* skip this one, name doesn't match */
06628 
06629       dpc->context_existence = 1;
06630 
06631       ast_rdlock_context(c);
06632 
06633       /* are we looking for exten too? if yes, we print context
06634        * only if we find our extension.
06635        * Otherwise print context even if empty ?
06636        * XXX i am not sure how the rinclude is handled.
06637        * I think it ought to go inside.
06638        */
06639       if (!exten) {
06640          dpc->total_context++;
06641          ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
06642             ast_get_context_name(c), ast_get_context_registrar(c));
06643          context_info_printed = 1;
06644       }
06645 
06646       /* walk extensions ... */
06647       e = NULL;
06648       while ( (e = ast_walk_context_extensions(c, e)) ) {
06649          struct ast_exten *p;
06650 
06651          if (exten && !ast_extension_match(ast_get_extension_name(e), exten))
06652             continue;   /* skip, extension match failed */
06653 
06654          dpc->extension_existence = 1;
06655 
06656          /* may we print context info? */
06657          if (!context_info_printed) {
06658             dpc->total_context++;
06659             if (rinclude) { /* TODO Print more info about rinclude */
06660                ast_cli(fd, "[ Included context '%s' created by '%s' ]\n",
06661                   ast_get_context_name(c), ast_get_context_registrar(c));
06662             } else {
06663                ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
06664                   ast_get_context_name(c), ast_get_context_registrar(c));
06665             }
06666             context_info_printed = 1;
06667          }
06668          dpc->total_prio++;
06669 
06670          /* write extension name and first peer */
06671          if (e->matchcid)
06672             snprintf(buf, sizeof(buf), "'%s' (CID match '%s') => ", ast_get_extension_name(e), e->cidmatch);
06673          else
06674             snprintf(buf, sizeof(buf), "'%s' =>", ast_get_extension_name(e));
06675 
06676          print_ext(e, buf2, sizeof(buf2));
06677 
06678          ast_cli(fd, "  %-17s %-45s [%s]\n", buf, buf2,
06679             ast_get_extension_registrar(e));
06680 
06681          dpc->total_exten++;
06682          /* walk next extension peers */
06683          p = e;   /* skip the first one, we already got it */
06684          while ( (p = ast_walk_extension_priorities(e, p)) ) {
06685             const char *el = ast_get_extension_label(p);
06686             dpc->total_prio++;
06687             if (el)
06688                snprintf(buf, sizeof(buf), "   [%s]", el);
06689             else
06690                buf[0] = '\0';
06691             print_ext(p, buf2, sizeof(buf2));
06692 
06693             ast_cli(fd,"  %-17s %-45s [%s]\n", buf, buf2,
06694                ast_get_extension_registrar(p));
06695          }
06696       }
06697 
06698       /* walk included and write info ... */
06699       i = NULL;
06700       while ( (i = ast_walk_context_includes(c, i)) ) {
06701          snprintf(buf, sizeof(buf), "'%s'", ast_get_include_name(i));
06702          if (exten) {
06703             /* Check all includes for the requested extension */
06704             if (includecount >= AST_PBX_MAX_STACK) {
06705                ast_log(LOG_WARNING, "Maximum include depth exceeded!\n");
06706             } else {
06707                int dupe = 0;
06708                int x;
06709                for (x = 0; x < includecount; x++) {
06710                   if (!strcasecmp(includes[x], ast_get_include_name(i))) {
06711                      dupe++;
06712                      break;
06713                   }
06714                }
06715                if (!dupe) {
06716                   includes[includecount] = ast_get_include_name(i);
06717                   show_dialplan_helper(fd, ast_get_include_name(i), exten, dpc, i, includecount + 1, includes);
06718                } else {
06719                   ast_log(LOG_WARNING, "Avoiding circular include of %s within %s\n", ast_get_include_name(i), context);
06720                }
06721             }
06722          } else {
06723             ast_cli(fd, "  Include =>        %-45s [%s]\n",
06724                buf, ast_get_include_registrar(i));
06725          }
06726       }
06727 
06728       /* walk ignore patterns and write info ... */
06729       ip = NULL;
06730       while ( (ip = ast_walk_context_ignorepats(c, ip)) ) {
06731          const char *ipname = ast_get_ignorepat_name(ip);
06732          char ignorepat[AST_MAX_EXTENSION];
06733          snprintf(buf, sizeof(buf), "'%s'", ipname);
06734          snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname);
06735          if (!exten || ast_extension_match(ignorepat, exten)) {
06736             ast_cli(fd, "  Ignore pattern => %-45s [%s]\n",
06737                buf, ast_get_ignorepat_registrar(ip));
06738          }
06739       }
06740       if (!rinclude) {
06741          struct ast_sw *sw = NULL;
06742          while ( (sw = ast_walk_context_switches(c, sw)) ) {
06743             snprintf(buf, sizeof(buf), "'%s/%s'",
06744                ast_get_switch_name(sw),
06745                ast_get_switch_data(sw));
06746             ast_cli(fd, "  Alt. Switch =>    %-45s [%s]\n",
06747                buf, ast_get_switch_registrar(sw));
06748          }
06749       }
06750 
06751       ast_unlock_context(c);
06752 
06753       /* if we print something in context, make an empty line */
06754       if (context_info_printed)
06755          ast_cli(fd, "\n");
06756    }
06757    ast_unlock_contexts();
06758 
06759    return (dpc->total_exten == old_total_exten) ? -1 : res;
06760 }

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

Definition at line 10963 of file pbx.c.

References ast_state_cb::change_cb, CMP_MATCH, and CMP_STOP.

Referenced by ast_pbx_init().

10964 {
10965    const struct ast_state_cb *state_cb = obj;
10966    ast_state_cb_type change_cb = arg;
10967 
10968    return (state_cb->change_cb == change_cb) ? CMP_MATCH | CMP_STOP : 0;
10969 }

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

References ast_copy_string().

Referenced by pbx_substitute_variables_helper_full().

03270 {
03271    char *ret = workspace;
03272    int lr;  /* length of the input string after the copy */
03273 
03274    ast_copy_string(workspace, value, workspace_len); /* always make a copy */
03275 
03276    lr = strlen(ret); /* compute length after copy, so we never go out of the workspace */
03277 
03278    /* Quick check if no need to do anything */
03279    if (offset == 0 && length >= lr) /* take the whole string */
03280       return ret;
03281 
03282    if (offset < 0)   {  /* translate negative offset into positive ones */
03283       offset = lr + offset;
03284       if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */
03285          offset = 0;
03286    }
03287 
03288    /* too large offset result in empty string so we know what to return */
03289    if (offset >= lr)
03290       return ret + lr;  /* the final '\0' */
03291 
03292    ret += offset;    /* move to the start position */
03293    if (length >= 0 && length < lr - offset)  /* truncate if necessary */
03294       ret[length] = '\0';
03295    else if (length < 0) {
03296       if (lr > offset - length) /* After we remove from the front and from the rear, is there anything left? */
03297          ret[lr + length - offset] = '\0';
03298       else
03299          ret[0] = '\0';
03300    }
03301 
03302    return ret;
03303 }

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

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

01674 {
01675    struct match_char *m3;
01676    struct match_char *m4;
01677    struct ast_exten *e3;
01678 
01679    if (node && node->x[0] == '.' && !node->x[1]) { /* dot and ! will ALWAYS be next match in a matchmore */
01680       return node->exten;
01681    }
01682 
01683    if (node && node->x[0] == '!' && !node->x[1]) {
01684       return node->exten;
01685    }
01686 
01687    if (!node || !node->next_char) {
01688       return NULL;
01689    }
01690 
01691    m3 = node->next_char;
01692 
01693    if (m3->exten) {
01694       return m3->exten;
01695    }
01696    for (m4 = m3->alt_char; m4; m4 = m4->alt_char) {
01697       if (m4->exten) {
01698          return m4->exten;
01699       }
01700    }
01701    for (m4 = m3; m4; m4 = m4->alt_char) {
01702       e3 = trie_find_next_match(m3);
01703       if (e3) {
01704          return e3;
01705       }
01706    }
01707 
01708    return NULL;
01709 }

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

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

07375 {
07376    struct ast_context *context = NULL;
07377    struct ast_exten *eroot = NULL, *e = NULL;
07378 
07379    ast_rdlock_contexts();
07380    while ((context = ast_walk_contexts(context))) {
07381       while ((eroot = ast_walk_context_extensions(context, eroot))) {
07382          while ((e = ast_walk_extension_priorities(eroot, e))) {
07383             if (e->cached_app == app)
07384                e->cached_app = NULL;
07385          }
07386       }
07387    }
07388    ast_unlock_contexts();
07389 
07390    return;
07391 }

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

01578 {
01579    /* if this extension is marked as deleted, then skip this -- if it never shows
01580       on the scoreboard, it will never be found, nor will halt the traversal. */
01581    if (deleted)
01582       return;
01583    board->total_specificity = spec;
01584    board->total_length = length;
01585    board->exten = exten;
01586    board->last_char = last;
01587    board->node = node;
01588 #ifdef NEED_DEBUG_HERE
01589    ast_log(LOG_NOTICE,"Scoreboarding (LONGER) %s, len=%d, score=%d\n", exten->exten, length, spec);
01590 #endif
01591 }

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

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

09556 {
09557    int res;
09558    struct ast_frame *f;
09559    double waitsec;
09560    int waittime;
09561 
09562    if (ast_strlen_zero(data) || (sscanf(data, "%30lg", &waitsec) != 1) || (waitsec < 0))
09563       waitsec = -1;
09564    if (waitsec > -1) {
09565       waittime = waitsec * 1000.0;
09566       ast_safe_sleep(chan, waittime);
09567    } else do {
09568       res = ast_waitfor(chan, -1);
09569       if (res < 0)
09570          return;
09571       f = ast_read(chan);
09572       if (f)
09573          ast_frfree(f);
09574    } while(f);
09575 }


Variable Documentation

int autofallthrough = 1 [static]

Definition at line 1156 of file pbx.c.

Referenced by __ast_pbx_run(), and pbx_set_autofallthrough().

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

Definition at line 807 of file pbx.c.

Referenced by pbx_builtin_background().

struct pbx_builtin builtins[] [static]

Declaration of builtin applications.

Referenced by load_pbx(), and unload_pbx().

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

Lock for the ast_context list.

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

Definition at line 1215 of file pbx.c.

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

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

Lock to hold off restructuring of hints by ast_merge_contexts_and_delete.

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

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

const char* const days[] [static]

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

Referenced by load_pbx(), and unload_pbx().

Definition at line 820 of file pbx.c.

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

Definition at line 3571 of file pbx.c.

Referenced by load_pbx(), and unload_pbx().

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

Definition at line 3503 of file pbx.c.

Referenced by acf_exception_read(), and raise_exception().

int extenpatternmatchnew = 0 [static]

Definition at line 1157 of file pbx.c.

Referenced by pbx_find_extension(), and pbx_set_extenpatternmatchnew().

Referenced by ast_extension_state2str().

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

Definition at line 823 of file pbx.c.

Referenced by ast_extension_state2().

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

Definition at line 1235 of file pbx.c.

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

Initial value:

Definition at line 10542 of file pbx.c.

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

Definition at line 1163 of file pbx.c.

Referenced by decrease_call_count(), and increase_call_count().

const char* const months[] [static]

Definition at line 7970 of file pbx.c.

Referenced by ast_build_timing().

char* overrideswitch = NULL [static]

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

Referenced by load_pbx(), and unload_pbx().

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

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

Referenced by pbx_builtin_resetcdr().

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

Definition at line 1226 of file pbx.c.

Referenced by ast_extension_state_add_destroy().

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

Definition at line 822 of file pbx.c.

Referenced by pbx_find_extension().

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

Definition at line 9787 of file pbx.c.

Referenced by load_pbx(), and unload_pbx().

int totalcalls [static]

Definition at line 1165 of file pbx.c.

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

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

Definition at line 815 of file pbx.c.

Referenced by pbx_builtin_waitexten().


Generated on 20 Aug 2013 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1