Mon Oct 8 12:39:24 2012

Asterisk developer's documentation


pbx.c File Reference

Core PBX routines. More...

#include "asterisk.h"
#include "asterisk/_private.h"
#include "asterisk/paths.h"
#include <ctype.h>
#include <time.h>
#include <sys/time.h>
#include <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 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)
 Add an extension to an extension context, this time with an ast_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).
ast_contextast_context_find (const char *name)
 Find a context.
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 a context include.
int ast_context_remove_include2 (struct ast_context *con, const char *include, const char *registrar)
 Removes an include by an ast_context structure.
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.
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)
 Uses hint and devicestate callback to get the state of an extension.
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 string representation of the state of an extension.
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)
 Registers a state change callback.
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)
 Registers a state change callback with destructor.
int ast_extension_state_del (int id, ast_state_cb_type change_cb)
 Deletes a registered state change callback by ID.
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)
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)
 If an extension hint exists, return non-zero.
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)
 Register an 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)
 If an extension hint exists, return non-zero.
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.
ast_extenast_walk_context_extensions (struct ast_context *con, struct ast_exten *exten)
ast_ignorepatast_walk_context_ignorepats (struct ast_context *con, struct ast_ignorepat *ip)
ast_includeast_walk_context_includes (struct ast_context *con, struct ast_include *inc)
ast_swast_walk_context_switches (struct ast_context *con, struct ast_sw *sw)
ast_contextast_walk_contexts (struct ast_context *con)
ast_extenast_walk_extension_priorities (struct ast_exten *exten, struct ast_exten *priority)
int ast_wrlock_context (struct ast_context *con)
 Write locks a given context.
int ast_wrlock_contexts (void)
 Write locks the context list.
static void * async_wait (void *data)
static void cli_match_char_tree (struct match_char *node, char *prefix, int fd)
static int collect_digits (struct ast_channel *c, int waittime, char *buf, int buflen, int pos)
 collect digits from the channel into the buffer.
static int compare_char (const void *a, const void *b)
static char * complete_core_show_hint (const char *line, const char *word, int pos, int state)
 autocomplete for CLI command 'core show hint'
static char * complete_show_dialplan_context (const char *line, const char *word, int pos, int state)
static void context_merge (struct ast_context **extcontexts, struct ast_hashtab *exttable, struct ast_context *context, const char *registrar)
static void context_merge_incls_swits_igps_other_registrars (struct ast_context *new, struct ast_context *old, const char *registrar)
static void create_match_char_tree (struct ast_context *con)
static void decrease_call_count (void)
static void destroy_exten (struct ast_exten *e)
static void destroy_hint (void *obj)
static void destroy_pattern_tree (struct match_char *pattern_tree)
static void destroy_state_cb (void *doomed)
static void device_state_cb (const struct ast_event *event, void *unused)
static void exception_store_free (void *data)
static int ext_cmp (const char *a, const char *b)
 the full routine to compare extensions in rules.
static int ext_cmp1 (const char **p, unsigned char *bitwise)
 helper functions to sort extensions and patterns in the desired way, so that more specific patterns appear first.
static int ext_strncpy (char *dst, const char *src, int len)
 copy a string skipping whitespace
static int extension_match_core (const char *pattern, const char *data, enum ext_match_t mode)
static struct ast_contextfind_context (const char *context)
 lookup for a context with a given name,
static struct ast_contextfind_context_locked (const char *context)
 lookup for a context with a given name,
static int find_hint_by_cb_id (void *obj, void *arg, int flags)
 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:.
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)
ast_apppbx_findapp (const char *app)
 Look up an application.
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)
 Retrieve the value of a builtin variable or variable from the channel variable stack.
int pbx_set_autofallthrough (int newval)
int pbx_set_extenpatternmatchnew (int newval)
void pbx_set_overrideswitch (const char *newval)
static void pbx_substitute_variables (char *passdata, int datalen, struct ast_channel *c, struct ast_exten *e)
void pbx_substitute_variables_helper (struct ast_channel *c, const char *cp1, char *cp2, int count)
void pbx_substitute_variables_helper_full (struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count, size_t *used)
void pbx_substitute_variables_varshead (struct varshead *headp, const char *cp1, char *cp2, int count)
static void * pbx_thread (void *data)
static void print_app_docs (struct ast_app *aa, int fd)
static void print_ext (struct ast_exten *e, char *buf, int buflen)
 helper function to print an extension
static int raise_exception (struct ast_channel *chan, const char *reason, int priority)
static void set_ext_pri (struct ast_channel *c, const char *exten, int pri)
static int show_debug_helper (int fd, const char *context, const char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude, int includecount, const char *includes[])
static int show_dialplan_helper (int fd, const char *context, const char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude, int includecount, const char *includes[])
static int statecbs_cmp (void *obj, void *arg, int flags)
static char * substring (const char *value, int offset, int length, char *workspace, size_t workspace_len)
 takes a substring. It is ok to call with value == workspace.
static int testtime_write (struct ast_channel *chan, const char *cmd, char *var, const char *value)
static struct ast_extentrie_find_next_match (struct match_char *node)
static void unreference_cached_app (struct ast_app *app)
static void update_scoreboard (struct scoreboard *board, int length, int spec, struct ast_exten *exten, char last, const char *callerid, int deleted, struct match_char *node)
static void wait_for_hangup (struct ast_channel *chan, const void *data)

Variables

static int autofallthrough = 1
static struct ast_app_option background_opts [128] = { [ 's' ] = { .flag = (1 << 0) }, [ 'n' ] = { .flag = (1 << 1) }, [ 'm' ] = { .flag = (1 << 2) }, [ 'p' ] = { .flag = (1 << 3) },}
static struct pbx_builtin builtins []
 Declaration of builtin applications.
static ast_mutex_t conlock = { PTHREAD_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 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().

#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

#define SAY_STUBS

Definition at line 60 of file pbx.c.

#define STATUS_NO_CONTEXT   1

Definition at line 2697 of file pbx.c.

#define STATUS_NO_EXTENSION   2

Definition at line 2698 of file pbx.c.

#define STATUS_NO_LABEL   4

Definition at line 2700 of file pbx.c.

#define STATUS_NO_PRIORITY   3

Definition at line 2699 of file pbx.c.

#define STATUS_SUCCESS   5

Definition at line 2701 of file pbx.c.

#define SWITCH_DATA_LENGTH   256

Definition at line 789 of file pbx.c.

#define VAR_BUF_SIZE   4096

Definition at line 791 of file pbx.c.

Referenced by ast_add_extension2_lockopt(), ast_func_read2(), pbx_builtin_importvar(), and pbx_substitute_variables_helper_full().

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

References __ast_internal_context_destroy(), 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_sw::list, ast_context::name, ast_sw::next, ast_include::next, ast_ignorepat::next, ast_context::next, ast_exten::next, ast_exten::peer_table, ast_exten::priority, ast_exten::registrar, ast_sw::registrar, ast_include::registrar, ast_ignorepat::registrar, ast_context::registrar, and ast_context::root_table.

Referenced by ast_context_destroy().

09145 {
09146    struct ast_context *tmp, *tmpl=NULL;
09147    struct ast_exten *exten_item, *prio_item;
09148 
09149    for (tmp = list; tmp; ) {
09150       struct ast_context *next = NULL; /* next starting point */
09151          /* The following code used to skip forward to the next
09152             context with matching registrar, but this didn't
09153             make sense; individual priorities registrar'd to
09154             the matching registrar could occur in any context! */
09155       ast_debug(1, "Investigate ctx %s %s\n", tmp->name, tmp->registrar);
09156       if (con) {
09157          for (; tmp; tmpl = tmp, tmp = tmp->next) { /* skip to the matching context */
09158             ast_debug(1, "check ctx %s %s\n", tmp->name, tmp->registrar);
09159             if ( !strcasecmp(tmp->name, con->name) ) {
09160                break;   /* found it */
09161             }
09162          }
09163       }
09164 
09165       if (!tmp)   /* not found, we are done */
09166          break;
09167       ast_wrlock_context(tmp);
09168 
09169       if (registrar) {
09170          /* then search thru and remove any extens that match registrar. */
09171          struct ast_hashtab_iter *exten_iter;
09172          struct ast_hashtab_iter *prio_iter;
09173          struct ast_ignorepat *ip, *ipl = NULL, *ipn = NULL;
09174          struct ast_include *i, *pi = NULL, *ni = NULL;
09175          struct ast_sw *sw = NULL;
09176 
09177          /* remove any ignorepats whose registrar matches */
09178          for (ip = tmp->ignorepats; ip; ip = ipn) {
09179             ipn = ip->next;
09180             if (!strcmp(ip->registrar, registrar)) {
09181                if (ipl) {
09182                   ipl->next = ip->next;
09183                   ast_free(ip);
09184                   continue; /* don't change ipl */
09185                } else {
09186                   tmp->ignorepats = ip->next;
09187                   ast_free(ip);
09188                   continue; /* don't change ipl */
09189                }
09190             }
09191             ipl = ip;
09192          }
09193          /* remove any includes whose registrar matches */
09194          for (i = tmp->includes; i; i = ni) {
09195             ni = i->next;
09196             if (strcmp(i->registrar, registrar) == 0) {
09197                /* remove from list */
09198                if (pi) {
09199                   pi->next = i->next;
09200                   /* free include */
09201                   ast_free(i);
09202                   continue; /* don't change pi */
09203                } else {
09204                   tmp->includes = i->next;
09205                   /* free include */
09206                   ast_free(i);
09207                   continue; /* don't change pi */
09208                }
09209             }
09210             pi = i;
09211          }
09212          /* remove any switches whose registrar matches */
09213          AST_LIST_TRAVERSE_SAFE_BEGIN(&tmp->alts, sw, list) {
09214             if (strcmp(sw->registrar,registrar) == 0) {
09215                AST_LIST_REMOVE_CURRENT(list);
09216                ast_free(sw);
09217             }
09218          }
09219          AST_LIST_TRAVERSE_SAFE_END;
09220 
09221          if (tmp->root_table) { /* it is entirely possible that the context is EMPTY */
09222             exten_iter = ast_hashtab_start_traversal(tmp->root_table);
09223             while ((exten_item=ast_hashtab_next(exten_iter))) {
09224                int end_traversal = 1;
09225                prio_iter = ast_hashtab_start_traversal(exten_item->peer_table);
09226                while ((prio_item=ast_hashtab_next(prio_iter))) {
09227                   char extension[AST_MAX_EXTENSION];
09228                   char cidmatch[AST_MAX_EXTENSION];
09229                   if (!prio_item->registrar || strcmp(prio_item->registrar, registrar) != 0) {
09230                      continue;
09231                   }
09232                   ast_verb(3, "Remove %s/%s/%d, registrar=%s; con=%s(%p); con->root=%p\n",
09233                          tmp->name, prio_item->exten, prio_item->priority, registrar, con? con->name : "<nil>", con, con? con->root_table: NULL);
09234                   /* set matchcid to 1 to insure we get a direct match, and NULL registrar to make sure no wildcarding is done */
09235                   ast_copy_string(extension, prio_item->exten, sizeof(extension));
09236                   if (prio_item->cidmatch) {
09237                      ast_copy_string(cidmatch, prio_item->cidmatch, sizeof(cidmatch));
09238                   }
09239                   end_traversal &= ast_context_remove_extension_callerid2(tmp, extension, prio_item->priority, prio_item->cidmatch ? cidmatch : NULL, 1, NULL, 1);
09240                }
09241                /* Explanation:
09242                 * ast_context_remove_extension_callerid2 will destroy the extension that it comes across. This
09243                 * destruction includes destroying the exten's peer_table, which we are currently traversing. If
09244                 * ast_context_remove_extension_callerid2 ever should return '0' then this means we have destroyed
09245                 * the hashtable which we are traversing, and thus calling ast_hashtab_end_traversal will result
09246                 * in reading invalid memory. Thus, if we detect that we destroyed the hashtable, then we will simply
09247                 * free the iterator
09248                 */
09249                if (end_traversal) {
09250                   ast_hashtab_end_traversal(prio_iter);
09251                } else {
09252                   ast_free(prio_iter);
09253                }
09254             }
09255             ast_hashtab_end_traversal(exten_iter);
09256          }
09257 
09258          /* delete the context if it's registrar matches, is empty, has refcount of 1, */
09259          /* it's not empty, if it has includes, ignorepats, or switches that are registered from
09260             another registrar. It's not empty if there are any extensions */
09261          if (strcmp(tmp->registrar, registrar) == 0 && tmp->refcount < 2 && !tmp->root && !tmp->ignorepats && !tmp->includes && AST_LIST_EMPTY(&tmp->alts)) {
09262             ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar);
09263             ast_hashtab_remove_this_object(contexttab, tmp);
09264 
09265             next = tmp->next;
09266             if (tmpl)
09267                tmpl->next = next;
09268             else
09269                contexts = next;
09270             /* Okay, now we're safe to let it go -- in a sense, we were
09271                ready to let it go as soon as we locked it. */
09272             ast_unlock_context(tmp);
09273             __ast_internal_context_destroy(tmp);
09274          } else {
09275             ast_debug(1,"Couldn't delete ctx %s/%s; refc=%d; tmp.root=%p\n", tmp->name, tmp->registrar,
09276                     tmp->refcount, tmp->root);
09277             ast_unlock_context(tmp);
09278             next = tmp->next;
09279             tmpl = tmp;
09280          }
09281       } else if (con) {
09282          ast_verb(3, "Deleting context %s registrar=%s\n", tmp->name, tmp->registrar);
09283          ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar);
09284          ast_hashtab_remove_this_object(contexttab, tmp);
09285 
09286          next = tmp->next;
09287          if (tmpl)
09288             tmpl->next = next;
09289          else
09290             contexts = next;
09291          /* Okay, now we're safe to let it go -- in a sense, we were
09292             ready to let it go as soon as we locked it. */
09293          ast_unlock_context(tmp);
09294          __ast_internal_context_destroy(tmp);
09295       }
09296 
09297       /* if we have a specific match, we are done, otherwise continue */
09298       tmp = con ? NULL : next;
09299    }
09300 }

int __ast_custom_function_register ( struct ast_custom_function acf,
struct ast_module mod 
)

Register a custom function.

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

03592 {
03593    struct ast_custom_function *cur;
03594    char tmps[80];
03595 
03596    if (!acf) {
03597       return -1;
03598    }
03599 
03600    acf->mod = mod;
03601 #ifdef AST_XML_DOCS
03602    acf->docsrc = AST_STATIC_DOC;
03603 #endif
03604 
03605    if (acf_retrieve_docs(acf)) {
03606       return -1;
03607    }
03608 
03609    AST_RWLIST_WRLOCK(&acf_root);
03610 
03611    AST_RWLIST_TRAVERSE(&acf_root, cur, acflist) {
03612       if (!strcmp(acf->name, cur->name)) {
03613          ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name);
03614          AST_RWLIST_UNLOCK(&acf_root);
03615          return -1;
03616       }
03617    }
03618 
03619    /* Store in alphabetical order */
03620    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) {
03621       if (strcasecmp(acf->name, cur->name) < 0) {
03622          AST_RWLIST_INSERT_BEFORE_CURRENT(acf, acflist);
03623          break;
03624       }
03625    }
03626    AST_RWLIST_TRAVERSE_SAFE_END;
03627 
03628    if (!cur) {
03629       AST_RWLIST_INSERT_TAIL(&acf_root, acf, acflist);
03630    }
03631 
03632    AST_RWLIST_UNLOCK(&acf_root);
03633 
03634    ast_verb(2, "Registered custom function '%s'\n", term_color(tmps, acf->name, COLOR_BRCYAN, 0, sizeof(tmps)));
03635 
03636    return 0;
03637 }

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

Definition at line 10549 of file pbx.c.

References ast_async_goto(), ast_exists_extension(), ast_explicit_goto(), AST_PBX_GOTO_FAILED, ast_channel::context, ast_channel::exten, and S_COR.

Referenced by ast_async_goto_if_exists(), and ast_goto_if_exists().

10550 {
10551    int (*goto_func)(struct ast_channel *chan, const char *context, const char *exten, int priority);
10552 
10553    if (!chan)
10554       return -2;
10555 
10556    if (context == NULL)
10557       context = chan->context;
10558    if (exten == NULL)
10559       exten = chan->exten;
10560 
10561    goto_func = (async) ? ast_async_goto : ast_explicit_goto;
10562    if (ast_exists_extension(chan, context, exten, priority,
10563       S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL)))
10564       return goto_func(chan, context, exten, priority);
10565    else {
10566       return AST_PBX_GOTO_FAILED;
10567    }
10568 }

static void __ast_internal_context_destroy ( struct ast_context con  )  [static]

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

09098 {
09099    struct ast_include *tmpi;
09100    struct ast_sw *sw;
09101    struct ast_exten *e, *el, *en;
09102    struct ast_ignorepat *ipi;
09103    struct ast_context *tmp = con;
09104 
09105    for (tmpi = tmp->includes; tmpi; ) { /* Free includes */
09106       struct ast_include *tmpil = tmpi;
09107       tmpi = tmpi->next;
09108       ast_free(tmpil);
09109    }
09110    for (ipi = tmp->ignorepats; ipi; ) { /* Free ignorepats */
09111       struct ast_ignorepat *ipl = ipi;
09112       ipi = ipi->next;
09113       ast_free(ipl);
09114    }
09115    if (tmp->registrar)
09116       ast_free(tmp->registrar);
09117 
09118    /* destroy the hash tabs */
09119    if (tmp->root_table) {
09120       ast_hashtab_destroy(tmp->root_table, 0);
09121    }
09122    /* and destroy the pattern tree */
09123    if (tmp->pattern_tree)
09124       destroy_pattern_tree(tmp->pattern_tree);
09125 
09126    while ((sw = AST_LIST_REMOVE_HEAD(&tmp->alts, list)))
09127       ast_free(sw);
09128    for (e = tmp->root; e;) {
09129       for (en = e->peer; en;) {
09130          el = en;
09131          en = en->peer;
09132          destroy_exten(el);
09133       }
09134       el = e;
09135       e = e->next;
09136       destroy_exten(el);
09137    }
09138    tmp->root = NULL;
09139    ast_rwlock_destroy(&tmp->lock);
09140    ast_free(tmp);
09141 }

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

Definition at line 4950 of file pbx.c.

References ast_channel::_softhangup, ast_calloc, ast_cdr_update(), ast_channel_clear_softhangup(), ast_channel_lock, ast_channel_unlock, ast_check_hangup(), ast_copy_string(), ast_exists_extension(), AST_FLAG_IN_AUTOLOOP, ast_free, ast_log(), ast_set_flag, AST_SOFTHANGUP_ASYNCGOTO, AST_SOFTHANGUP_TIMEOUT, ast_spawn_extension(), ast_test_flag, ast_verb, ast_channel::caller, ast_channel::cdr, ast_channel::context, ast_pbx::dtimeoutms, ast_channel::exten, ast_party_caller::id, LOG_WARNING, ast_channel::name, ast_party_id::number, ast_channel::pbx, ast_channel::priority, ast_pbx::rtimeoutms, S_COR, set_ext_pri(), ast_party_number::str, and ast_party_number::valid.

Referenced by ast_pbx_run_args(), and pbx_thread().

04952 {
04953    int found = 0; /* set if we find at least one match */
04954    int res = 0;
04955    int autoloopflag;
04956    int error = 0;    /* set an error conditions */
04957 
04958    /* A little initial setup here */
04959    if (c->pbx) {
04960       ast_log(LOG_WARNING, "%s already has PBX structure??\n", c->name);
04961       /* XXX and now what ? */
04962       ast_free(c->pbx);
04963    }
04964    if (!(c->pbx = ast_calloc(1, sizeof(*c->pbx))))
04965       return -1;
04966    /* Set reasonable defaults */
04967    c->pbx->rtimeoutms = 10000;
04968    c->pbx->dtimeoutms = 5000;
04969 
04970    autoloopflag = ast_test_flag(c, AST_FLAG_IN_AUTOLOOP);   /* save value to restore at the end */
04971    ast_set_flag(c, AST_FLAG_IN_AUTOLOOP);
04972 
04973    /* Start by trying whatever the channel is set to */
04974    if (!ast_exists_extension(c, c->context, c->exten, c->priority,
04975       S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
04976       /* If not successful fall back to 's' */
04977       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);
04978       /* XXX the original code used the existing priority in the call to
04979        * ast_exists_extension(), and reset it to 1 afterwards.
04980        * I believe the correct thing is to set it to 1 immediately.
04981        */
04982       set_ext_pri(c, "s", 1);
04983       if (!ast_exists_extension(c, c->context, c->exten, c->priority,
04984          S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
04985          /* JK02: And finally back to default if everything else failed */
04986          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);
04987          ast_copy_string(c->context, "default", sizeof(c->context));
04988       }
04989    }
04990    ast_channel_lock(c);
04991    if (c->cdr) {
04992       /* allow CDR variables that have been collected after channel was created to be visible during call */
04993       ast_cdr_update(c);
04994    }
04995    ast_channel_unlock(c);
04996    for (;;) {
04997       char dst_exten[256]; /* buffer to accumulate digits */
04998       int pos = 0;      /* XXX should check bounds */
04999       int digit = 0;
05000       int invalid = 0;
05001       int timeout = 0;
05002 
05003       /* loop on priorities in this context/exten */
05004       while (!(res = ast_spawn_extension(c, c->context, c->exten, c->priority,
05005          S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL),
05006          &found, 1))) {
05007          if (!ast_check_hangup(c)) {
05008             ++c->priority;
05009             continue;
05010          }
05011 
05012          /* Check softhangup flags. */
05013          if (c->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) {
05014             ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO);
05015             continue;
05016          }
05017          if (c->_softhangup & AST_SOFTHANGUP_TIMEOUT) {
05018             if (ast_exists_extension(c, c->context, "T", 1,
05019                S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05020                set_ext_pri(c, "T", 1);
05021                /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
05022                memset(&c->whentohangup, 0, sizeof(c->whentohangup));
05023                ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
05024                continue;
05025             } else if (ast_exists_extension(c, c->context, "e", 1,
05026                S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05027                raise_exception(c, "ABSOLUTETIMEOUT", 1);
05028                /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
05029                memset(&c->whentohangup, 0, sizeof(c->whentohangup));
05030                ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
05031                continue;
05032             }
05033 
05034             /* Call timed out with no special extension to jump to. */
05035             error = 1;
05036             break;
05037          }
05038          ast_debug(1, "Extension %s, priority %d returned normally even though call was hung up\n",
05039             c->exten, c->priority);
05040          error = 1;
05041          break;
05042       } /* end while  - from here on we can use 'break' to go out */
05043       if (found && res) {
05044          /* Something bad happened, or a hangup has been requested. */
05045          if (strchr("0123456789ABCDEF*#", res)) {
05046             ast_debug(1, "Oooh, got something to jump out with ('%c')!\n", res);
05047             pos = 0;
05048             dst_exten[pos++] = digit = res;
05049             dst_exten[pos] = '\0';
05050          } else if (res == AST_PBX_INCOMPLETE) {
05051             ast_debug(1, "Spawn extension (%s,%s,%d) exited INCOMPLETE on '%s'\n", c->context, c->exten, c->priority, c->name);
05052             ast_verb(2, "Spawn extension (%s, %s, %d) exited INCOMPLETE on '%s'\n", c->context, c->exten, c->priority, c->name);
05053 
05054             /* Don't cycle on incomplete - this will happen if the only extension that matches is our "incomplete" extension */
05055             if (!ast_matchmore_extension(c, c->context, c->exten, 1,
05056                S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05057                invalid = 1;
05058             } else {
05059                ast_copy_string(dst_exten, c->exten, sizeof(dst_exten));
05060                digit = 1;
05061                pos = strlen(dst_exten);
05062             }
05063          } else {
05064             ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
05065             ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
05066 
05067             if ((res == AST_PBX_ERROR)
05068                && ast_exists_extension(c, c->context, "e", 1,
05069                   S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05070                /* if we are already on the 'e' exten, don't jump to it again */
05071                if (!strcmp(c->exten, "e")) {
05072                   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);
05073                   error = 1;
05074                } else {
05075                   raise_exception(c, "ERROR", 1);
05076                   continue;
05077                }
05078             }
05079 
05080             if (c->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) {
05081                ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO);
05082                continue;
05083             }
05084             if (c->_softhangup & AST_SOFTHANGUP_TIMEOUT) {
05085                if (ast_exists_extension(c, c->context, "T", 1,
05086                   S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05087                   set_ext_pri(c, "T", 1);
05088                   /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
05089                   memset(&c->whentohangup, 0, sizeof(c->whentohangup));
05090                   ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
05091                   continue;
05092                } else if (ast_exists_extension(c, c->context, "e", 1,
05093                   S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05094                   raise_exception(c, "ABSOLUTETIMEOUT", 1);
05095                   /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
05096                   memset(&c->whentohangup, 0, sizeof(c->whentohangup));
05097                   ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
05098                   continue;
05099                }
05100                /* Call timed out with no special extension to jump to. */
05101             }
05102             ast_channel_lock(c);
05103             if (c->cdr) {
05104                ast_cdr_update(c);
05105             }
05106             ast_channel_unlock(c);
05107             error = 1;
05108             break;
05109          }
05110       }
05111       if (error)
05112          break;
05113 
05114       /*!\note
05115        * We get here on a failure of some kind:  non-existing extension or
05116        * hangup.  We have options, here.  We can either catch the failure
05117        * and continue, or we can drop out entirely. */
05118 
05119       if (invalid
05120          || (ast_strlen_zero(dst_exten) &&
05121             !ast_exists_extension(c, c->context, c->exten, 1,
05122             S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL)))) {
05123          /*!\note
05124           * If there is no match at priority 1, it is not a valid extension anymore.
05125           * Try to continue at "i" (for invalid) or "e" (for exception) or exit if
05126           * neither exist.
05127           */
05128          if (ast_exists_extension(c, c->context, "i", 1,
05129             S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05130             ast_verb(3, "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, c->name);
05131             pbx_builtin_setvar_helper(c, "INVALID_EXTEN", c->exten);
05132             set_ext_pri(c, "i", 1);
05133          } else if (ast_exists_extension(c, c->context, "e", 1,
05134             S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05135             raise_exception(c, "INVALID", 1);
05136          } else {
05137             ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n",
05138                c->name, c->exten, c->context);
05139             error = 1; /* we know what to do with it */
05140             break;
05141          }
05142       } else if (c->_softhangup & AST_SOFTHANGUP_TIMEOUT) {
05143          /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */
05144          ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
05145       } else { /* keypress received, get more digits for a full extension */
05146          int waittime = 0;
05147          if (digit)
05148             waittime = c->pbx->dtimeoutms;
05149          else if (!autofallthrough)
05150             waittime = c->pbx->rtimeoutms;
05151          if (!waittime) {
05152             const char *status = pbx_builtin_getvar_helper(c, "DIALSTATUS");
05153             if (!status)
05154                status = "UNKNOWN";
05155             ast_verb(3, "Auto fallthrough, channel '%s' status is '%s'\n", c->name, status);
05156             if (!strcasecmp(status, "CONGESTION"))
05157                res = pbx_builtin_congestion(c, "10");
05158             else if (!strcasecmp(status, "CHANUNAVAIL"))
05159                res = pbx_builtin_congestion(c, "10");
05160             else if (!strcasecmp(status, "BUSY"))
05161                res = pbx_builtin_busy(c, "10");
05162             error = 1; /* XXX disable message */
05163             break;   /* exit from the 'for' loop */
05164          }
05165 
05166          if (collect_digits(c, waittime, dst_exten, sizeof(dst_exten), pos))
05167             break;
05168          if (res == AST_PBX_INCOMPLETE && ast_strlen_zero(&dst_exten[pos]))
05169             timeout = 1;
05170          if (!timeout
05171             && ast_exists_extension(c, c->context, dst_exten, 1,
05172                S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { /* Prepare the next cycle */
05173             set_ext_pri(c, dst_exten, 1);
05174          } else {
05175             /* No such extension */
05176             if (!timeout && !ast_strlen_zero(dst_exten)) {
05177                /* An invalid extension */
05178                if (ast_exists_extension(c, c->context, "i", 1,
05179                   S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05180                   ast_verb(3, "Invalid extension '%s' in context '%s' on %s\n", dst_exten, c->context, c->name);
05181                   pbx_builtin_setvar_helper(c, "INVALID_EXTEN", dst_exten);
05182                   set_ext_pri(c, "i", 1);
05183                } else if (ast_exists_extension(c, c->context, "e", 1,
05184                   S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05185                   raise_exception(c, "INVALID", 1);
05186                } else {
05187                   ast_log(LOG_WARNING,
05188                      "Invalid extension '%s', but no rule 'i' or 'e' in context '%s'\n",
05189                      dst_exten, c->context);
05190                   found = 1; /* XXX disable message */
05191                   break;
05192                }
05193             } else {
05194                /* A simple timeout */
05195                if (ast_exists_extension(c, c->context, "t", 1,
05196                   S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05197                   ast_verb(3, "Timeout on %s\n", c->name);
05198                   set_ext_pri(c, "t", 1);
05199                } else if (ast_exists_extension(c, c->context, "e", 1,
05200                   S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05201                   raise_exception(c, "RESPONSETIMEOUT", 1);
05202                } else {
05203                   ast_log(LOG_WARNING,
05204                      "Timeout, but no rule 't' or 'e' in context '%s'\n",
05205                      c->context);
05206                   found = 1; /* XXX disable message */
05207                   break;
05208                }
05209             }
05210          }
05211          ast_channel_lock(c);
05212          if (c->cdr) {
05213             ast_verb(2, "CDR updated on %s\n",c->name);
05214             ast_cdr_update(c);
05215          }
05216          ast_channel_unlock(c);
05217       }
05218    }
05219 
05220    if (!found && !error) {
05221       ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name);
05222    }
05223 
05224    if (!args || !args->no_hangup_chan) {
05225       ast_softhangup(c, AST_SOFTHANGUP_APPUNLOAD);
05226    }
05227 
05228    if ((!args || !args->no_hangup_chan)
05229       && !ast_test_flag(c, AST_FLAG_BRIDGE_HANGUP_RUN)
05230       && ast_exists_extension(c, c->context, "h", 1,
05231          S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05232       set_ext_pri(c, "h", 1);
05233       if (c->cdr && ast_opt_end_cdr_before_h_exten) {
05234          ast_cdr_end(c->cdr);
05235       }
05236       while ((res = ast_spawn_extension(c, c->context, c->exten, c->priority,
05237          S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL),
05238          &found, 1)) == 0) {
05239          c->priority++;
05240       }
05241       if (found && res) {
05242          /* Something bad happened, or a hangup has been requested. */
05243          ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
05244          ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
05245       }
05246    }
05247    ast_set2_flag(c, autoloopflag, AST_FLAG_IN_AUTOLOOP);
05248    ast_clear_flag(c, AST_FLAG_BRIDGE_HANGUP_RUN); /* from one round to the next, make sure this gets cleared */
05249    pbx_destroy(c->pbx);
05250    c->pbx = NULL;
05251 
05252    if (!args || !args->no_hangup_chan) {
05253       ast_hangup(c);
05254    }
05255 
05256    return 0;
05257 }

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

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

Referenced by extension_match_core().

02470 {
02471    mode &= E_MATCH_MASK;   /* only consider the relevant bits */
02472 
02473 #ifdef NEED_DEBUG_HERE
02474    ast_log(LOG_NOTICE,"match core: pat: '%s', dat: '%s', mode=%d\n", pattern, data, (int)mode);
02475 #endif
02476 
02477    if ( (mode == E_MATCH) && (pattern[0] == '_') && (!strcasecmp(pattern,data)) ) { /* note: if this test is left out, then _x. will not match _x. !!! */
02478 #ifdef NEED_DEBUG_HERE
02479       ast_log(LOG_NOTICE,"return (1) - pattern matches pattern\n");
02480 #endif
02481       return 1;
02482    }
02483 
02484    if (pattern[0] != '_') { /* not a pattern, try exact or partial match */
02485       int ld = strlen(data), lp = strlen(pattern);
02486 
02487       if (lp < ld) {    /* pattern too short, cannot match */
02488 #ifdef NEED_DEBUG_HERE
02489          ast_log(LOG_NOTICE,"return (0) - pattern too short, cannot match\n");
02490 #endif
02491          return 0;
02492       }
02493       /* depending on the mode, accept full or partial match or both */
02494       if (mode == E_MATCH) {
02495 #ifdef NEED_DEBUG_HERE
02496          ast_log(LOG_NOTICE,"return (!strcmp(%s,%s) when mode== E_MATCH)\n", pattern, data);
02497 #endif
02498          return !strcmp(pattern, data); /* 1 on match, 0 on fail */
02499       }
02500       if (ld == 0 || !strncasecmp(pattern, data, ld)) { /* partial or full match */
02501 #ifdef NEED_DEBUG_HERE
02502          ast_log(LOG_NOTICE,"return (mode(%d) == E_MATCHMORE ? lp(%d) > ld(%d) : 1)\n", mode, lp, ld);
02503 #endif
02504          return (mode == E_MATCHMORE) ? lp > ld : 1; /* XXX should consider '!' and '/' ? */
02505       } else {
02506 #ifdef NEED_DEBUG_HERE
02507          ast_log(LOG_NOTICE,"return (0) when ld(%d) > 0 && pattern(%s) != data(%s)\n", ld, pattern, data);
02508 #endif
02509          return 0;
02510       }
02511    }
02512    pattern++; /* skip leading _ */
02513    /*
02514     * XXX below we stop at '/' which is a separator for the CID info. However we should
02515     * not store '/' in the pattern at all. When we insure it, we can remove the checks.
02516     */
02517    while (*data && *pattern && *pattern != '/') {
02518       const char *end;
02519 
02520       if (*data == '-') { /* skip '-' in data (just a separator) */
02521          data++;
02522          continue;
02523       }
02524       switch (toupper(*pattern)) {
02525       case '[':   /* a range */
02526          end = strchr(pattern+1, ']'); /* XXX should deal with escapes ? */
02527          if (end == NULL) {
02528             ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n");
02529             return 0;   /* unconditional failure */
02530          }
02531          for (pattern++; pattern != end; pattern++) {
02532             if (pattern+2 < end && pattern[1] == '-') { /* this is a range */
02533                if (*data >= pattern[0] && *data <= pattern[2])
02534                   break;   /* match found */
02535                else {
02536                   pattern += 2; /* skip a total of 3 chars */
02537                   continue;
02538                }
02539             } else if (*data == pattern[0])
02540                break;   /* match found */
02541          }
02542          if (pattern == end) {
02543 #ifdef NEED_DEBUG_HERE
02544             ast_log(LOG_NOTICE,"return (0) when pattern==end\n");
02545 #endif
02546             return 0;
02547          }
02548          pattern = end; /* skip and continue */
02549          break;
02550       case 'N':
02551          if (*data < '2' || *data > '9') {
02552 #ifdef NEED_DEBUG_HERE
02553             ast_log(LOG_NOTICE,"return (0) N is matched\n");
02554 #endif
02555             return 0;
02556          }
02557          break;
02558       case 'X':
02559          if (*data < '0' || *data > '9') {
02560 #ifdef NEED_DEBUG_HERE
02561             ast_log(LOG_NOTICE,"return (0) X is matched\n");
02562 #endif
02563             return 0;
02564          }
02565          break;
02566       case 'Z':
02567          if (*data < '1' || *data > '9') {
02568 #ifdef NEED_DEBUG_HERE
02569             ast_log(LOG_NOTICE,"return (0) Z is matched\n");
02570 #endif
02571             return 0;
02572          }
02573          break;
02574       case '.':   /* Must match, even with more digits */
02575 #ifdef NEED_DEBUG_HERE
02576          ast_log(LOG_NOTICE, "return (1) when '.' is matched\n");
02577 #endif
02578          return 1;
02579       case '!':   /* Early match */
02580 #ifdef NEED_DEBUG_HERE
02581          ast_log(LOG_NOTICE, "return (2) when '!' is matched\n");
02582 #endif
02583          return 2;
02584       case ' ':
02585       case '-':   /* Ignore these in patterns */
02586          data--; /* compensate the final data++ */
02587          break;
02588       default:
02589          if (*data != *pattern) {
02590 #ifdef NEED_DEBUG_HERE
02591             ast_log(LOG_NOTICE, "return (0) when *data(%c) != *pattern(%c)\n", *data, *pattern);
02592 #endif
02593             return 0;
02594          }
02595       }
02596       data++;
02597       pattern++;
02598    }
02599    if (*data)        /* data longer than pattern, no match */ {
02600 #ifdef NEED_DEBUG_HERE
02601       ast_log(LOG_NOTICE, "return (0) when data longer than pattern\n");
02602 #endif
02603       return 0;
02604    }
02605 
02606    /*
02607     * match so far, but ran off the end of the data.
02608     * Depending on what is next, determine match or not.
02609     */
02610    if (*pattern == '\0' || *pattern == '/') {   /* exact match */
02611 #ifdef NEED_DEBUG_HERE
02612       ast_log(LOG_NOTICE, "at end, return (%d) in 'exact match'\n", (mode==E_MATCHMORE) ? 0 : 1);
02613 #endif
02614       return (mode == E_MATCHMORE) ? 0 : 1;  /* this is a failure for E_MATCHMORE */
02615    } else if (*pattern == '!')   {     /* early match */
02616 #ifdef NEED_DEBUG_HERE
02617       ast_log(LOG_NOTICE, "at end, return (2) when '!' is matched\n");
02618 #endif
02619       return 2;
02620    } else {                /* partial match */
02621 #ifdef NEED_DEBUG_HERE
02622       ast_log(LOG_NOTICE, "at end, return (%d) which deps on E_MATCH\n", (mode == E_MATCH) ? 0 : 1);
02623 #endif
02624       return (mode == E_MATCH) ? 0 : 1;   /* this is a failure for E_MATCH */
02625    }
02626 }

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

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

03329 {
03330    struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL);
03331    struct pbx_exception *exception = NULL;
03332    if (!ds || !ds->data)
03333       return -1;
03334    exception = ds->data;
03335    if (!strcasecmp(data, "REASON"))
03336       ast_copy_string(buf, exception->reason, buflen);
03337    else if (!strcasecmp(data, "CONTEXT"))
03338       ast_copy_string(buf, exception->context, buflen);
03339    else if (!strncasecmp(data, "EXTEN", 5))
03340       ast_copy_string(buf, exception->exten, buflen);
03341    else if (!strcasecmp(data, "PRIORITY"))
03342       snprintf(buf, buflen, "%d", exception->priority);
03343    else
03344       return -1;
03345    return 0;
03346 }

static int acf_retrieve_docs ( struct ast_custom_function acf  )  [static]

Definition at line 3546 of file pbx.c.

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

Referenced by __ast_custom_function_register().

03547 {
03548 #ifdef AST_XML_DOCS
03549    char *tmpxml;
03550 
03551    /* Let's try to find it in the Documentation XML */
03552    if (!ast_strlen_zero(acf->desc) || !ast_strlen_zero(acf->synopsis)) {
03553       return 0;
03554    }
03555 
03556    if (ast_string_field_init(acf, 128)) {
03557       return -1;
03558    }
03559 
03560    /* load synopsis */
03561    tmpxml = ast_xmldoc_build_synopsis("function", acf->name, ast_module_name(acf->mod));
03562    ast_string_field_set(acf, synopsis, tmpxml);
03563    ast_free(tmpxml);
03564 
03565    /* load description */
03566    tmpxml = ast_xmldoc_build_description("function", acf->name, ast_module_name(acf->mod));
03567    ast_string_field_set(acf, desc, tmpxml);
03568    ast_free(tmpxml);
03569 
03570    /* load syntax */
03571    tmpxml = ast_xmldoc_build_syntax("function", acf->name, ast_module_name(acf->mod));
03572    ast_string_field_set(acf, syntax, tmpxml);
03573    ast_free(tmpxml);
03574 
03575    /* load arguments */
03576    tmpxml = ast_xmldoc_build_arguments("function", acf->name, ast_module_name(acf->mod));
03577    ast_string_field_set(acf, arguments, tmpxml);
03578    ast_free(tmpxml);
03579 
03580    /* load seealso */
03581    tmpxml = ast_xmldoc_build_seealso("function", acf->name, ast_module_name(acf->mod));
03582    ast_string_field_set(acf, seealso, tmpxml);
03583    ast_free(tmpxml);
03584 
03585    acf->docsrc = AST_XML_DOC;
03586 #endif
03587 
03588    return 0;
03589 }

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

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 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]

Definition at line 1949 of file pbx.c.

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

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

References ast_log(), ast_exten::exten, ast_exten::label, LOG_WARNING, ast_context::name, ast_exten::peer, and ast_exten::priority.

Referenced by ast_add_extension2_lockopt().

08302 {
08303    struct ast_exten *ep;
08304    struct ast_exten *eh=e;
08305    int repeated_label = 0; /* Track if this label is a repeat, assume no. */
08306 
08307    for (ep = NULL; e ; ep = e, e = e->peer) {
08308       if (e->label && tmp->label && e->priority != tmp->priority && !strcmp(e->label, tmp->label)) {
08309          ast_log(LOG_WARNING, "Extension '%s', priority %d in '%s', label '%s' already in use at "
08310                "priority %d\n", tmp->exten, tmp->priority, con->name, tmp->label, e->priority);
08311          repeated_label = 1;
08312       }
08313       if (e->priority >= tmp->priority) {
08314          break;
08315       }
08316    }
08317 
08318    if (repeated_label) {   /* Discard the label since it's a repeat. */
08319       tmp->label = NULL;
08320    }
08321 
08322    if (!e) {   /* go at the end, and ep is surely set because the list is not empty */
08323       ast_hashtab_insert_safe(eh->peer_table, tmp);
08324 
08325       if (tmp->label) {
08326          ast_hashtab_insert_safe(eh->peer_label_table, tmp);
08327       }
08328       ep->peer = tmp;
08329       return 0;   /* success */
08330    }
08331    if (e->priority == tmp->priority) {
08332       /* Can't have something exactly the same.  Is this a
08333          replacement?  If so, replace, otherwise, bonk. */
08334       if (!replace) {
08335          ast_log(LOG_WARNING, "Unable to register extension '%s', priority %d in '%s', already in use\n", tmp->exten, tmp->priority, con->name);
08336          if (tmp->datad) {
08337             tmp->datad(tmp->data);
08338             /* if you free this, null it out */
08339             tmp->data = NULL;
08340          }
08341 
08342          ast_free(tmp);
08343          return -1;
08344       }
08345       /* we are replacing e, so copy the link fields and then update
08346        * whoever pointed to e to point to us
08347        */
08348       tmp->next = e->next; /* not meaningful if we are not first in the peer list */
08349       tmp->peer = e->peer; /* always meaningful */
08350       if (ep)  {     /* We're in the peer list, just insert ourselves */
08351          ast_hashtab_remove_object_via_lookup(eh->peer_table,e);
08352 
08353          if (e->label) {
08354             ast_hashtab_remove_object_via_lookup(eh->peer_label_table,e);
08355          }
08356 
08357          ast_hashtab_insert_safe(eh->peer_table,tmp);
08358          if (tmp->label) {
08359             ast_hashtab_insert_safe(eh->peer_label_table,tmp);
08360          }
08361 
08362          ep->peer = tmp;
08363       } else if (el) {     /* We're the first extension. Take over e's functions */
08364          struct match_char *x = add_exten_to_pattern_tree(con, e, 1);
08365          tmp->peer_table = e->peer_table;
08366          tmp->peer_label_table = e->peer_label_table;
08367          ast_hashtab_remove_object_via_lookup(tmp->peer_table,e);
08368          ast_hashtab_insert_safe(tmp->peer_table,tmp);
08369          if (e->label) {
08370             ast_hashtab_remove_object_via_lookup(tmp->peer_label_table, e);
08371          }
08372          if (tmp->label) {
08373             ast_hashtab_insert_safe(tmp->peer_label_table, tmp);
08374          }
08375 
08376          ast_hashtab_remove_object_via_lookup(con->root_table, e);
08377          ast_hashtab_insert_safe(con->root_table, tmp);
08378          el->next = tmp;
08379          /* The pattern trie points to this exten; replace the pointer,
08380             and all will be well */
08381          if (x) { /* if the trie isn't formed yet, don't sweat this */
08382             if (x->exten) { /* this test for safety purposes */
08383                x->exten = tmp; /* replace what would become a bad pointer */
08384             } else {
08385                ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n");
08386             }
08387          }
08388       } else {       /* We're the very first extension.  */
08389          struct match_char *x = add_exten_to_pattern_tree(con, e, 1);
08390          ast_hashtab_remove_object_via_lookup(con->root_table, e);
08391          ast_hashtab_insert_safe(con->root_table, tmp);
08392          tmp->peer_table = e->peer_table;
08393          tmp->peer_label_table = e->peer_label_table;
08394          ast_hashtab_remove_object_via_lookup(tmp->peer_table, e);
08395          ast_hashtab_insert_safe(tmp->peer_table, tmp);
08396          if (e->label) {
08397             ast_hashtab_remove_object_via_lookup(tmp->peer_label_table, e);
08398          }
08399          if (tmp->label) {
08400             ast_hashtab_insert_safe(tmp->peer_label_table, tmp);
08401          }
08402 
08403          ast_hashtab_remove_object_via_lookup(con->root_table, e);
08404          ast_hashtab_insert_safe(con->root_table, tmp);
08405          con->root = tmp;
08406          /* The pattern trie points to this exten; replace the pointer,
08407             and all will be well */
08408          if (x) { /* if the trie isn't formed yet; no problem */
08409             if (x->exten) { /* this test for safety purposes */
08410                x->exten = tmp; /* replace what would become a bad pointer */
08411             } else {
08412                ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n");
08413             }
08414          }
08415       }
08416       if (tmp->priority == PRIORITY_HINT)
08417          ast_change_hint(e,tmp);
08418       /* Destroy the old one */
08419       if (e->datad)
08420          e->datad(e->data);
08421       ast_free(e);
08422    } else { /* Slip ourselves in just before e */
08423       tmp->peer = e;
08424       tmp->next = e->next; /* extension chain, or NULL if e is not the first extension */
08425       if (ep) {         /* Easy enough, we're just in the peer list */
08426          if (tmp->label) {
08427             ast_hashtab_insert_safe(eh->peer_label_table, tmp);
08428          }
08429          ast_hashtab_insert_safe(eh->peer_table, tmp);
08430          ep->peer = tmp;
08431       } else {       /* we are the first in some peer list, so link in the ext list */
08432          tmp->peer_table = e->peer_table;
08433          tmp->peer_label_table = e->peer_label_table;
08434          e->peer_table = 0;
08435          e->peer_label_table = 0;
08436          ast_hashtab_insert_safe(tmp->peer_table, tmp);
08437          if (tmp->label) {
08438             ast_hashtab_insert_safe(tmp->peer_label_table, tmp);
08439          }
08440          ast_hashtab_remove_object_via_lookup(con->root_table, e);
08441          ast_hashtab_insert_safe(con->root_table, tmp);
08442          if (el)
08443             el->next = tmp;   /* in the middle... */
08444          else
08445             con->root = tmp; /* ... or at the head */
08446          e->next = NULL;   /* e is no more at the head, so e->next must be reset */
08447       }
08448       /* And immediately return success. */
08449       if (tmp->priority == PRIORITY_HINT) {
08450          ast_add_hint(tmp);
08451       }
08452    }
08453    return 0;
08454 }

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

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

References countcalls.

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

05406 {
05407    return countcalls;
05408 }

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

08138 {
08139    int ret = -1;
08140    struct ast_context *c;
08141 
08142    c = find_context_locked(context);
08143    if (c) {
08144       ret = ast_add_extension2(c, replace, extension, priority, label, callerid,
08145          application, data, datad, registrar);
08146       ast_unlock_contexts();
08147    }
08148 
08149    return ret;
08150 }

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 
)

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

References ast_add_extension2_lockopt().

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

08485 {
08486    return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid,
08487       application, data, datad, registrar, 1);
08488 }

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

08501 {
08502    /*
08503     * Sort extensions (or patterns) according to the rules indicated above.
08504     * These are implemented by the function ext_cmp()).
08505     * All priorities for the same ext/pattern/cid are kept in a list,
08506     * using the 'peer' field  as a link field..
08507     */
08508    struct ast_exten *tmp, *tmp2, *e, *el = NULL;
08509    int res;
08510    int length;
08511    char *p;
08512    char expand_buf[VAR_BUF_SIZE];
08513    struct ast_exten dummy_exten = {0};
08514    char dummy_name[1024];
08515 
08516    if (ast_strlen_zero(extension)) {
08517       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",
08518             con->name);
08519       return -1;
08520    }
08521 
08522    /* If we are adding a hint evalulate in variables and global variables */
08523    if (priority == PRIORITY_HINT && strstr(application, "${") && !strstr(extension, "_")) {
08524       struct ast_channel *c = ast_dummy_channel_alloc();
08525 
08526       if (c) {
08527          ast_copy_string(c->exten, extension, sizeof(c->exten));
08528          ast_copy_string(c->context, con->name, sizeof(c->context));
08529       }
08530       pbx_substitute_variables_helper(c, application, expand_buf, sizeof(expand_buf));
08531       application = expand_buf;
08532       if (c) {
08533          ast_channel_unref(c);
08534       }
08535    }
08536 
08537    length = sizeof(struct ast_exten);
08538    length += strlen(extension) + 1;
08539    length += strlen(application) + 1;
08540    if (label)
08541       length += strlen(label) + 1;
08542    if (callerid)
08543       length += strlen(callerid) + 1;
08544    else
08545       length ++;  /* just the '\0' */
08546 
08547    /* Be optimistic:  Build the extension structure first */
08548    if (!(tmp = ast_calloc(1, length)))
08549       return -1;
08550 
08551    if (ast_strlen_zero(label)) /* let's turn empty labels to a null ptr */
08552       label = 0;
08553 
08554    /* use p as dst in assignments, as the fields are const char * */
08555    p = tmp->stuff;
08556    if (label) {
08557       tmp->label = p;
08558       strcpy(p, label);
08559       p += strlen(label) + 1;
08560    }
08561    tmp->exten = p;
08562    p += ext_strncpy(p, extension, strlen(extension) + 1) + 1;
08563    tmp->priority = priority;
08564    tmp->cidmatch = p;   /* but use p for assignments below */
08565 
08566    /* Blank callerid and NULL callerid are two SEPARATE things.  Do NOT confuse the two!!! */
08567    if (callerid) {
08568       p += ext_strncpy(p, callerid, strlen(callerid) + 1) + 1;
08569       tmp->matchcid = 1;
08570    } else {
08571       *p++ = '\0';
08572       tmp->matchcid = 0;
08573    }
08574    tmp->app = p;
08575    strcpy(p, application);
08576    tmp->parent = con;
08577    tmp->data = data;
08578    tmp->datad = datad;
08579    tmp->registrar = registrar;
08580 
08581    if (lock_context) {
08582       ast_wrlock_context(con);
08583    }
08584 
08585    if (con->pattern_tree) { /* usually, on initial load, the pattern_tree isn't formed until the first find_exten; so if we are adding
08586                         an extension, and the trie exists, then we need to incrementally add this pattern to it. */
08587       ast_copy_string(dummy_name, extension, sizeof(dummy_name));
08588       dummy_exten.exten = dummy_name;
08589       dummy_exten.matchcid = 0;
08590       dummy_exten.cidmatch = 0;
08591       tmp2 = ast_hashtab_lookup(con->root_table, &dummy_exten);
08592       if (!tmp2) {
08593          /* hmmm, not in the trie; */
08594          add_exten_to_pattern_tree(con, tmp, 0);
08595          ast_hashtab_insert_safe(con->root_table, tmp); /* for the sake of completeness */
08596       }
08597    }
08598    res = 0; /* some compilers will think it is uninitialized otherwise */
08599    for (e = con->root; e; el = e, e = e->next) {   /* scan the extension list */
08600       res = ext_cmp(e->exten, tmp->exten);
08601       if (res == 0) { /* extension match, now look at cidmatch */
08602          if (!e->matchcid && !tmp->matchcid)
08603             res = 0;
08604          else if (tmp->matchcid && !e->matchcid)
08605             res = 1;
08606          else if (e->matchcid && !tmp->matchcid)
08607             res = -1;
08608          else
08609             res = ext_cmp(e->cidmatch, tmp->cidmatch);
08610       }
08611       if (res >= 0)
08612          break;
08613    }
08614    if (e && res == 0) { /* exact match, insert in the priority chain */
08615       res = add_priority(con, tmp, el, e, replace);
08616       if (lock_context) {
08617          ast_unlock_context(con);
08618       }
08619       if (res < 0) {
08620          errno = EEXIST;   /* XXX do we care ? */
08621          return 0; /* XXX should we return -1 maybe ? */
08622       }
08623    } else {
08624       /*
08625        * not an exact match, this is the first entry with this pattern,
08626        * so insert in the main list right before 'e' (if any)
08627        */
08628       tmp->next = e;
08629       if (el) {  /* there is another exten already in this context */
08630          el->next = tmp;
08631          tmp->peer_table = ast_hashtab_create(13,
08632                      hashtab_compare_exten_numbers,
08633                      ast_hashtab_resize_java,
08634                      ast_hashtab_newsize_java,
08635                      hashtab_hash_priority,
08636                      0);
08637          tmp->peer_label_table = ast_hashtab_create(7,
08638                         hashtab_compare_exten_labels,
08639                         ast_hashtab_resize_java,
08640                         ast_hashtab_newsize_java,
08641                         hashtab_hash_labels,
08642                         0);
08643          if (label) {
08644             ast_hashtab_insert_safe(tmp->peer_label_table, tmp);
08645          }
08646          ast_hashtab_insert_safe(tmp->peer_table, tmp);
08647       } else {  /* this is the first exten in this context */
08648          if (!con->root_table)
08649             con->root_table = ast_hashtab_create(27,
08650                                        hashtab_compare_extens,
08651                                        ast_hashtab_resize_java,
08652                                        ast_hashtab_newsize_java,
08653                                        hashtab_hash_extens,
08654                                        0);
08655          con->root = tmp;
08656          con->root->peer_table = ast_hashtab_create(13,
08657                         hashtab_compare_exten_numbers,
08658                         ast_hashtab_resize_java,
08659                         ast_hashtab_newsize_java,
08660                         hashtab_hash_priority,
08661                         0);
08662          con->root->peer_label_table = ast_hashtab_create(7,
08663                            hashtab_compare_exten_labels,
08664                            ast_hashtab_resize_java,
08665                            ast_hashtab_newsize_java,
08666                            hashtab_hash_labels,
08667                            0);
08668          if (label) {
08669             ast_hashtab_insert_safe(con->root->peer_label_table, tmp);
08670          }
08671          ast_hashtab_insert_safe(con->root->peer_table, tmp);
08672 
08673       }
08674       ast_hashtab_insert_safe(con->root_table, tmp);
08675       if (lock_context) {
08676          ast_unlock_context(con);
08677       }
08678       if (tmp->priority == PRIORITY_HINT) {
08679          ast_add_hint(tmp);
08680       }
08681    }
08682    if (option_debug) {
08683       if (tmp->matchcid) {
08684          ast_debug(1, "Added extension '%s' priority %d (CID match '%s') to %s (%p)\n",
08685                  tmp->exten, tmp->priority, tmp->cidmatch, con->name, con);
08686       } else {
08687          ast_debug(1, "Added extension '%s' priority %d to %s (%p)\n",
08688                  tmp->exten, tmp->priority, con->name, con);
08689       }
08690    }
08691 
08692    if (tmp->matchcid) {
08693       ast_verb(3, "Added extension '%s' priority %d (CID match '%s') to %s\n",
08694              tmp->exten, tmp->priority, tmp->cidmatch, con->name);
08695    } else {
08696       ast_verb(3, "Added extension '%s' priority %d to %s\n",
08697              tmp->exten, tmp->priority, con->name);
08698    }
08699 
08700    return 0;
08701 }

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

References ast_add_extension2_lockopt(), and find_context().

Referenced by ast_merge_contexts_and_delete().

08118 {
08119    int ret = -1;
08120    struct ast_context *c;
08121 
08122    c = find_context(context);
08123    if (c) {
08124       ret = ast_add_extension2_lockopt(c, replace, extension, priority, label, callerid,
08125          application, data, datad, registrar, 1);
08126    }
08127 
08128    return ret;
08129 }

static int ast_add_hint ( struct ast_exten e  )  [static]

Add hint to hint list, check initial extension state.

Definition at line 4751 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(), destroy_hint(), hint_id_cmp(), and hints.

Referenced by ast_add_extension2_lockopt().

04752 {
04753    struct ast_hint *hint_new;
04754    struct ast_hint *hint_found;
04755 
04756    if (!e) {
04757       return -1;
04758    }
04759 
04760    /*
04761     * We must create the hint we wish to add before determining if
04762     * it is already in the hints container to avoid possible
04763     * deadlock when getting the current extension state.
04764     */
04765    hint_new = ao2_alloc(sizeof(*hint_new), destroy_hint);
04766    if (!hint_new) {
04767       return -1;
04768    }
04769 
04770    /* Initialize new hint. */
04771    hint_new->callbacks = ao2_container_alloc(1, NULL, hint_id_cmp);
04772    if (!hint_new->callbacks) {
04773       ao2_ref(hint_new, -1);
04774       return -1;
04775    }
04776    hint_new->exten = e;
04777    hint_new->laststate = ast_extension_state2(e);
04778 
04779    /* Prevent multiple add hints from adding the same hint at the same time. */
04780    ao2_lock(hints);
04781 
04782    /* Search if hint exists, do nothing */
04783    hint_found = ao2_find(hints, e, 0);
04784    if (hint_found) {
04785       ao2_ref(hint_found, -1);
04786       ao2_unlock(hints);
04787       ao2_ref(hint_new, -1);
04788       ast_debug(2, "HINTS: Not re-adding existing hint %s: %s\n",
04789          ast_get_extension_name(e), ast_get_extension_app(e));
04790       return -1;
04791    }
04792 
04793    /* Add new hint to the hints container */
04794    ast_debug(2, "HINTS: Adding hint %s: %s\n",
04795       ast_get_extension_name(e), ast_get_extension_app(e));
04796    ao2_link(hints, hint_new);
04797 
04798    ao2_unlock(hints);
04799    ao2_ref(hint_new, -1);
04800 
04801    return 0;
04802 }

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

References ast_channel::_state, ast_channel::accountcode, 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, ast_channel::linkedid, LOG_WARNING, ast_channel::name, 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().

08176 {
08177    int res = 0;
08178    struct ast_channel *tmpchan;
08179    struct {
08180       char *accountcode;
08181       char *exten;
08182       char *context;
08183       char *linkedid;
08184       char *name;
08185       struct ast_cdr *cdr;
08186       int amaflags;
08187       int state;
08188       format_t readformat;
08189       format_t writeformat;
08190    } tmpvars = { 0, };
08191 
08192    ast_channel_lock(chan);
08193    if (chan->pbx) { /* This channel is currently in the PBX */
08194       ast_explicit_goto(chan, context, exten, priority + 1);
08195       ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO);
08196       ast_channel_unlock(chan);
08197       return res;
08198    }
08199 
08200    /* In order to do it when the channel doesn't really exist within
08201     * the PBX, we have to make a new channel, masquerade, and start the PBX
08202     * at the new location */
08203    tmpvars.accountcode = ast_strdupa(chan->accountcode);
08204    tmpvars.exten = ast_strdupa(chan->exten);
08205    tmpvars.context = ast_strdupa(chan->context);
08206    tmpvars.linkedid = ast_strdupa(chan->linkedid);
08207    tmpvars.name = ast_strdupa(chan->name);
08208    tmpvars.amaflags = chan->amaflags;
08209    tmpvars.state = chan->_state;
08210    tmpvars.writeformat = chan->writeformat;
08211    tmpvars.readformat = chan->readformat;
08212    tmpvars.cdr = chan->cdr ? ast_cdr_dup(chan->cdr) : NULL;
08213 
08214    ast_channel_unlock(chan);
08215 
08216    /* Do not hold any channel locks while calling channel_alloc() since the function
08217     * locks the channel container when linking the new channel in. */
08218    if (!(tmpchan = ast_channel_alloc(0, tmpvars.state, 0, 0, tmpvars.accountcode, tmpvars.exten, tmpvars.context, tmpvars.linkedid, tmpvars.amaflags, "AsyncGoto/%s", tmpvars.name))) {
08219       ast_cdr_discard(tmpvars.cdr);
08220       return -1;
08221    }
08222 
08223    /* copy the cdr info over */
08224    if (tmpvars.cdr) {
08225       ast_cdr_discard(tmpchan->cdr);
08226       tmpchan->cdr = tmpvars.cdr;
08227       tmpvars.cdr = NULL;
08228    }
08229 
08230    /* Make formats okay */
08231    tmpchan->readformat = tmpvars.readformat;
08232    tmpchan->writeformat = tmpvars.writeformat;
08233 
08234    /* Setup proper location. Never hold another channel lock while calling this function. */
08235    ast_explicit_goto(tmpchan, S_OR(context, tmpvars.context), S_OR(exten, tmpvars.exten), priority);
08236 
08237    /* Masquerade into tmp channel */
08238    if (ast_channel_masquerade(tmpchan, chan)) {
08239       /* Failed to set up the masquerade.  It's probably chan_local
08240        * in the middle of optimizing itself out.  Sad. :( */
08241       ast_hangup(tmpchan);
08242       tmpchan = NULL;
08243       res = -1;
08244    } else {
08245       ast_do_masquerade(tmpchan);
08246       /* Start the PBX going on our stolen channel */
08247       if (ast_pbx_start(tmpchan)) {
08248          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name);
08249          ast_hangup(tmpchan);
08250          res = -1;
08251       }
08252    }
08253 
08254    return res;
08255 }

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

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

08258 {
08259    struct ast_channel *chan;
08260    int res = -1;
08261 
08262    if ((chan = ast_channel_get_by_name(channame))) {
08263       res = ast_async_goto(chan, context, exten, priority);
08264       chan = ast_channel_unref(chan);
08265    }
08266 
08267    return res;
08268 }

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

References __ast_goto_if_exists().

10576 {
10577    return __ast_goto_if_exists(chan, context, exten, priority, 1);
10578 }

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

References pbx_parseable_goto().

Referenced by asyncgoto_exec(), and handle_redirect().

10641 {
10642    return pbx_parseable_goto(chan, goto_string, 1);
10643 }

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

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

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

07759 {
07760    char *info;
07761    int j, num_fields, last_sep = -1;
07762 
07763    /* Check for empty just in case */
07764    if (ast_strlen_zero(info_in)) {
07765       return 0;
07766    }
07767 
07768    /* make a copy just in case we were passed a static string */
07769    info = ast_strdupa(info_in);
07770 
07771    /* count the number of fields in the timespec */
07772    for (j = 0, num_fields = 1; info[j] != '\0'; j++) {
07773       if (info[j] == ',') {
07774          last_sep = j;
07775          num_fields++;
07776       }
07777    }
07778 
07779    /* save the timezone, if it is specified */
07780    if (num_fields == 5) {
07781       i->timezone = ast_strdup(info + last_sep + 1);
07782    } else {
07783       i->timezone = NULL;
07784    }
07785 
07786    /* Assume everything except time */
07787    i->monthmask = 0xfff;   /* 12 bits */
07788    i->daymask = 0x7fffffffU; /* 31 bits */
07789    i->dowmask = 0x7f; /* 7 bits */
07790    /* on each call, use strsep() to move info to the next argument */
07791    get_timerange(i, strsep(&info, "|,"));
07792    if (info)
07793       i->dowmask = get_range(strsep(&info, "|,"), 7, days, "day of week");
07794    if (info)
07795       i->daymask = get_range(strsep(&info, "|,"), 31, NULL, "day");
07796    if (info)
07797       i->monthmask = get_range(strsep(&info, "|,"), 12, months, "month");
07798    return 1;
07799 }

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

04893 {
04894    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0);
04895 }

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

Change hint for an extension.

Definition at line 4805 of file pbx.c.

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

04806 {
04807    struct ast_hint *hint;
04808 
04809    if (!oe || !ne) {
04810       return -1;
04811    }
04812 
04813    ao2_lock(hints);/* Locked to hold off others while we move the hint around. */
04814 
04815    /*
04816     * Unlink the hint from the hints container as the extension
04817     * name (which is the hash value) could change.
04818     */
04819    hint = ao2_find(hints, oe, OBJ_UNLINK);
04820    if (!hint) {
04821       ao2_unlock(hints);
04822       return -1;
04823    }
04824 
04825    /* Update the hint and put it back in the hints container. */
04826    ao2_lock(hint);
04827    hint->exten = ne;
04828    ao2_unlock(hint);
04829    ao2_link(hints, hint);
04830 
04831    ao2_unlock(hints);
04832    ao2_ref(hint, -1);
04833 
04834    return 0;
04835 }

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

References ast_check_timing2(), and ast_tvnow().

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

07802 {
07803    return ast_check_timing2(i, ast_tvnow());
07804 }

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

07807 {
07808    struct ast_tm tm;
07809 
07810    ast_localtime(&tv, &tm, i->timezone);
07811 
07812    /* If it's not the right month, return */
07813    if (!(i->monthmask & (1 << tm.tm_mon)))
07814       return 0;
07815 
07816    /* If it's not that time of the month.... */
07817    /* Warning, tm_mday has range 1..31! */
07818    if (!(i->daymask & (1 << (tm.tm_mday-1))))
07819       return 0;
07820 
07821    /* If it's not the right day of the week */
07822    if (!(i->dowmask & (1 << tm.tm_wday)))
07823       return 0;
07824 
07825    /* Sanity check the hour just to be safe */
07826    if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) {
07827       ast_log(LOG_WARNING, "Insane time...\n");
07828       return 0;
07829    }
07830 
07831    /* Now the tough part, we calculate if it fits
07832       in the right time based on min/hour */
07833    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))))
07834       return 0;
07835 
07836    /* If we got this far, then we're good */
07837    return 1;
07838 }

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

References app, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strdup, and ast_app::list.

Referenced by handle_orig(), and handle_show_application().

10646 {
10647    struct ast_app *app = NULL;
10648    int which = 0;
10649    char *ret = NULL;
10650    size_t wordlen = strlen(word);
10651 
10652    AST_RWLIST_RDLOCK(&apps);
10653    AST_RWLIST_TRAVERSE(&apps, app, list) {
10654       if (!strncasecmp(word, app->name, wordlen) && ++which > state) {
10655          ret = ast_strdup(app->name);
10656          break;
10657       }
10658    }
10659    AST_RWLIST_UNLOCK(&apps);
10660 
10661    return ret;
10662 }

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

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

Referenced by handle_cli_dialplan_add_ignorepat().

08043 {
08044    int ret = -1;
08045    struct ast_context *c;
08046 
08047    c = find_context_locked(context);
08048    if (c) {
08049       ret = ast_context_add_ignorepat2(c, value, registrar);
08050       ast_unlock_contexts();
08051    }
08052    return ret;
08053 }

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

Definition at line 8055 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_context_add_ignorepat(), and context_merge_incls_swits_igps_other_registrars().

08056 {
08057    struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL;
08058    int length;
08059    char *pattern;
08060    length = sizeof(struct ast_ignorepat);
08061    length += strlen(value) + 1;
08062    if (!(ignorepat = ast_calloc(1, length)))
08063       return -1;
08064    /* The cast to char * is because we need to write the initial value.
08065     * The field is not supposed to be modified otherwise.  Also, gcc 4.2
08066     * sees the cast as dereferencing a type-punned pointer and warns about
08067     * it.  This is the workaround (we're telling gcc, yes, that's really
08068     * what we wanted to do).
08069     */
08070    pattern = (char *) ignorepat->pattern;
08071    strcpy(pattern, value);
08072    ignorepat->next = NULL;
08073    ignorepat->registrar = registrar;
08074    ast_wrlock_context(con);
08075    for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) {
08076       ignorepatl = ignorepatc;
08077       if (!strcasecmp(ignorepatc->pattern, value)) {
08078          /* Already there */
08079          ast_unlock_context(con);
08080          ast_free(ignorepat);
08081          errno = EEXIST;
08082          return -1;
08083       }
08084    }
08085    if (ignorepatl)
08086       ignorepatl->next = ignorepat;
08087    else
08088       con->ignorepats = ignorepat;
08089    ast_unlock_context(con);
08090    return 0;
08091 
08092 }

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

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

Referenced by handle_cli_dialplan_add_include().

07587 {
07588    int ret = -1;
07589    struct ast_context *c;
07590 
07591    c = find_context_locked(context);
07592    if (c) {
07593       ret = ast_context_add_include2(c, include, registrar);
07594       ast_unlock_contexts();
07595    }
07596    return ret;
07597 }

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 7855 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_context_add_include(), and context_merge_incls_swits_igps_other_registrars().

07857 {
07858    struct ast_include *new_include;
07859    char *c;
07860    struct ast_include *i, *il = NULL; /* include, include_last */
07861    int length;
07862    char *p;
07863 
07864    length = sizeof(struct ast_include);
07865    length += 2 * (strlen(value) + 1);
07866 
07867    /* allocate new include structure ... */
07868    if (!(new_include = ast_calloc(1, length)))
07869       return -1;
07870    /* Fill in this structure. Use 'p' for assignments, as the fields
07871     * in the structure are 'const char *'
07872     */
07873    p = new_include->stuff;
07874    new_include->name = p;
07875    strcpy(p, value);
07876    p += strlen(value) + 1;
07877    new_include->rname = p;
07878    strcpy(p, value);
07879    /* Strip off timing info, and process if it is there */
07880    if ( (c = strchr(p, ',')) ) {
07881       *c++ = '\0';
07882       new_include->hastime = ast_build_timing(&(new_include->timing), c);
07883    }
07884    new_include->next      = NULL;
07885    new_include->registrar = registrar;
07886 
07887    ast_wrlock_context(con);
07888 
07889    /* ... go to last include and check if context is already included too... */
07890    for (i = con->includes; i; i = i->next) {
07891       if (!strcasecmp(i->name, new_include->name)) {
07892          ast_destroy_timing(&(new_include->timing));
07893          ast_free(new_include);
07894          ast_unlock_context(con);
07895          errno = EEXIST;
07896          return -1;
07897       }
07898       il = i;
07899    }
07900 
07901    /* ... include new context into context list, unlock, return */
07902    if (il)
07903       il->next = new_include;
07904    else
07905       con->includes = new_include;
07906    ast_verb(3, "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con));
07907 
07908    ast_unlock_context(con);
07909 
07910    return 0;
07911 }

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

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

07919 {
07920    int ret = -1;
07921    struct ast_context *c;
07922 
07923    c = find_context_locked(context);
07924    if (c) { /* found, add switch to this context */
07925       ret = ast_context_add_switch2(c, sw, data, eval, registrar);
07926       ast_unlock_contexts();
07927    }
07928    return ret;
07929 }

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 7938 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, store_hint::list, ast_sw::name, ast_sw::registrar, and ast_sw::stuff.

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

07940 {
07941    struct ast_sw *new_sw;
07942    struct ast_sw *i;
07943    int length;
07944    char *p;
07945 
07946    length = sizeof(struct ast_sw);
07947    length += strlen(value) + 1;
07948    if (data)
07949       length += strlen(data);
07950    length++;
07951 
07952    /* allocate new sw structure ... */
07953    if (!(new_sw = ast_calloc(1, length)))
07954       return -1;
07955    /* ... fill in this structure ... */
07956    p = new_sw->stuff;
07957    new_sw->name = p;
07958    strcpy(new_sw->name, value);
07959    p += strlen(value) + 1;
07960    new_sw->data = p;
07961    if (data) {
07962       strcpy(new_sw->data, data);
07963       p += strlen(data) + 1;
07964    } else {
07965       strcpy(new_sw->data, "");
07966       p++;
07967    }
07968    new_sw->eval     = eval;
07969    new_sw->registrar = registrar;
07970 
07971    /* ... try to lock this context ... */
07972    ast_wrlock_context(con);
07973 
07974    /* ... go to last sw and check if context is already swd too... */
07975    AST_LIST_TRAVERSE(&con->alts, i, list) {
07976       if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) {
07977          ast_free(new_sw);
07978          ast_unlock_context(con);
07979          errno = EEXIST;
07980          return -1;
07981       }
07982    }
07983 
07984    /* ... sw new context into context list, unlock, return */
07985    AST_LIST_INSERT_TAIL(&con->alts, new_sw, list);
07986 
07987    ast_verb(3, "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con));
07988 
07989    ast_unlock_context(con);
07990 
07991    return 0;
07992 }

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

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

02674 {
02675    struct ast_context *tmp;
02676    struct fake_context item;
02677 
02678    if (!name) {
02679       return NULL;
02680    }
02681    ast_rdlock_contexts();
02682    if (contexts_table) {
02683       ast_copy_string(item.name, name, sizeof(item.name));
02684       tmp = ast_hashtab_lookup(contexts_table, &item);
02685    } else {
02686       tmp = NULL;
02687       while ((tmp = ast_walk_contexts(tmp))) {
02688          if (!strcasecmp(name, tmp->name)) {
02689             break;
02690          }
02691       }
02692    }
02693    ast_unlock_contexts();
02694    return tmp;
02695 }

struct ast_context* ast_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.

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 7185 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, name, ast_context::next, ast_context::refcount, ast_context::registrar, ast_context::root, and ast_context::root_table.

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

07186 {
07187    struct ast_context *tmp, **local_contexts;
07188    struct fake_context search;
07189    int length = sizeof(struct ast_context) + strlen(name) + 1;
07190 
07191    if (!contexts_table) {
07192       /* Protect creation of contexts_table from reentrancy. */
07193       ast_wrlock_contexts();
07194       if (!contexts_table) {
07195          contexts_table = ast_hashtab_create(17,
07196             ast_hashtab_compare_contexts,
07197             ast_hashtab_resize_java,
07198             ast_hashtab_newsize_java,
07199             ast_hashtab_hash_contexts,
07200             0);
07201       }
07202       ast_unlock_contexts();
07203    }
07204 
07205    ast_copy_string(search.name, name, sizeof(search.name));
07206    if (!extcontexts) {
07207       ast_rdlock_contexts();
07208       local_contexts = &contexts;
07209       tmp = ast_hashtab_lookup(contexts_table, &search);
07210       ast_unlock_contexts();
07211       if (tmp) {
07212          tmp->refcount++;
07213          return tmp;
07214       }
07215    } else { /* local contexts just in a linked list; search there for the new context; slow, linear search, but not frequent */
07216       local_contexts = extcontexts;
07217       tmp = ast_hashtab_lookup(exttable, &search);
07218       if (tmp) {
07219          tmp->refcount++;
07220          return tmp;
07221       }
07222    }
07223 
07224    if ((tmp = ast_calloc(1, length))) {
07225       ast_rwlock_init(&tmp->lock);
07226       ast_mutex_init(&tmp->macrolock);
07227       strcpy(tmp->name, name);
07228       tmp->root = NULL;
07229       tmp->root_table = NULL;
07230       tmp->registrar = ast_strdup(registrar);
07231       tmp->includes = NULL;
07232       tmp->ignorepats = NULL;
07233       tmp->refcount = 1;
07234    } else {
07235       ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name);
07236       return NULL;
07237    }
07238 
07239    if (!extcontexts) {
07240       ast_wrlock_contexts();
07241       tmp->next = *local_contexts;
07242       *local_contexts = tmp;
07243       ast_hashtab_insert_safe(contexts_table, tmp); /*put this context into the tree */
07244       ast_unlock_contexts();
07245       ast_debug(1, "Registered context '%s'(%p) in table %p registrar: %s\n", tmp->name, tmp, contexts_table, registrar);
07246       ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar);
07247    } else {
07248       tmp->next = *local_contexts;
07249       if (exttable)
07250          ast_hashtab_insert_immediate(exttable, tmp); /*put this context into the tree */
07251 
07252       *local_contexts = tmp;
07253       ast_debug(1, "Registered context '%s'(%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar);
07254       ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar);
07255    }
07256    return tmp;
07257 }

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

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

Referenced by _macro_exec().

05784 {
05785    struct ast_context *c;
05786    int ret = -1;
05787 
05788    c = find_context_locked(context);
05789    if (c) {
05790       ast_unlock_contexts();
05791 
05792       /* if we found context, lock macrolock */
05793       ret = ast_mutex_lock(&c->macrolock);
05794    }
05795 
05796    return ret;
05797 }

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

05589 {
05590    return ast_context_remove_extension_callerid(context, extension, priority, NULL, 0, registrar);
05591 }

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

References ast_context_remove_extension_callerid2().

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

05619 {
05620    return ast_context_remove_extension_callerid2(con, extension, priority, NULL, 0, registrar, already_locked);
05621 }

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

05594 {
05595    int ret = -1; /* default error return */
05596    struct ast_context *c;
05597 
05598    c = find_context_locked(context);
05599    if (c) { /* ... remove extension ... */
05600       ret = ast_context_remove_extension_callerid2(c, extension, priority, callerid,
05601          matchcallerid, registrar, 0);
05602       ast_unlock_contexts();
05603    }
05604 
05605    return ret;
05606 }

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 5623 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, destroy_exten(), ast_exten::exten, exten, ast_exten::label, LOG_ERROR, LOG_NOTICE, LOG_WARNING, ast_exten::matchcid, ast_exten::next, ast_exten::peer, ast_exten::peer_label_table, ast_exten::peer_table, ast_exten::priority, ast_exten::registrar, and match_char::x.

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

05624 {
05625    struct ast_exten *exten, *prev_exten = NULL;
05626    struct ast_exten *peer;
05627    struct ast_exten ex, *exten2, *exten3;
05628    char dummy_name[1024];
05629    struct ast_exten *previous_peer = NULL;
05630    struct ast_exten *next_peer = NULL;
05631    int found = 0;
05632 
05633    if (!already_locked)
05634       ast_wrlock_context(con);
05635 
05636    /* Handle this is in the new world */
05637 
05638    /* FIXME For backwards compatibility, if callerid==NULL, then remove ALL
05639     * peers, not just those matching the callerid. */
05640 #ifdef NEED_DEBUG
05641    ast_verb(3,"Removing %s/%s/%d%s%s from trees, registrar=%s\n", con->name, extension, priority, matchcallerid ? "/" : "", matchcallerid ? callerid : "", registrar);
05642 #endif
05643 #ifdef CONTEXT_DEBUG
05644    check_contexts(__FILE__, __LINE__);
05645 #endif
05646    /* find this particular extension */
05647    ex.exten = dummy_name;
05648    ex.matchcid = matchcallerid && !ast_strlen_zero(callerid); /* don't say match if there's no callerid */
05649    ex.cidmatch = callerid;
05650    ast_copy_string(dummy_name, extension, sizeof(dummy_name));
05651    exten = ast_hashtab_lookup(con->root_table, &ex);
05652    if (exten) {
05653       if (priority == 0) {
05654          exten2 = ast_hashtab_remove_this_object(con->root_table, exten);
05655          if (!exten2)
05656             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);
05657          if (con->pattern_tree) {
05658             struct match_char *x = add_exten_to_pattern_tree(con, exten, 1);
05659 
05660             if (x->exten) { /* this test for safety purposes */
05661                x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */
05662                x->exten = 0; /* get rid of what will become a bad pointer */
05663             } else {
05664                ast_log(LOG_WARNING,"Trying to delete an exten from a context, but the pattern tree node returned isn't a full extension\n");
05665             }
05666          }
05667       } else {
05668          ex.priority = priority;
05669          exten2 = ast_hashtab_lookup(exten->peer_table, &ex);
05670          if (exten2) {
05671 
05672             if (exten2->label) { /* if this exten has a label, remove that, too */
05673                exten3 = ast_hashtab_remove_this_object(exten->peer_label_table,exten2);
05674                if (!exten3)
05675                   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);
05676             }
05677 
05678             exten3 = ast_hashtab_remove_this_object(exten->peer_table, exten2);
05679             if (!exten3)
05680                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);
05681             if (exten2 == exten && exten2->peer) {
05682                exten2 = ast_hashtab_remove_this_object(con->root_table, exten);
05683                ast_hashtab_insert_immediate(con->root_table, exten2->peer);
05684             }
05685             if (ast_hashtab_size(exten->peer_table) == 0) {
05686                /* well, if the last priority of an exten is to be removed,
05687                   then, the extension is removed, too! */
05688                exten3 = ast_hashtab_remove_this_object(con->root_table, exten);
05689                if (!exten3)
05690                   ast_log(LOG_ERROR,"Did not remove this exten (%s) from the context root_table (%s) (priority %d)\n", exten->exten, con->name, priority);
05691                if (con->pattern_tree) {
05692                   struct match_char *x = add_exten_to_pattern_tree(con, exten, 1);
05693                   if (x->exten) { /* this test for safety purposes */
05694                      x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */
05695                      x->exten = 0; /* get rid of what will become a bad pointer */
05696                   }
05697                }
05698             }
05699          } else {
05700             ast_log(LOG_ERROR,"Could not find priority %d of exten %s in context %s!\n",
05701                   priority, exten->exten, con->name);
05702          }
05703       }
05704    } else {
05705       /* hmmm? this exten is not in this pattern tree? */
05706       ast_log(LOG_WARNING,"Cannot find extension %s in root_table in context %s\n",
05707             extension, con->name);
05708    }
05709 #ifdef NEED_DEBUG
05710    if (con->pattern_tree) {
05711       ast_log(LOG_NOTICE,"match char tree after exten removal:\n");
05712       log_match_char_tree(con->pattern_tree, " ");
05713    }
05714 #endif
05715 
05716    /* scan the extension list to find first matching extension-registrar */
05717    for (exten = con->root; exten; prev_exten = exten, exten = exten->next) {
05718       if (!strcmp(exten->exten, extension) &&
05719          (!registrar || !strcmp(exten->registrar, registrar)) &&
05720          (!matchcallerid || (!ast_strlen_zero(callerid) && !ast_strlen_zero(exten->cidmatch) && !strcmp(exten->cidmatch, callerid)) || (ast_strlen_zero(callerid) && ast_strlen_zero(exten->cidmatch))))
05721          break;
05722    }
05723    if (!exten) {
05724       /* we can't find right extension */
05725       if (!already_locked)
05726          ast_unlock_context(con);
05727       return -1;
05728    }
05729 
05730    /* scan the priority list to remove extension with exten->priority == priority */
05731    for (peer = exten, next_peer = exten->peer ? exten->peer : exten->next;
05732        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)));
05733          peer = next_peer, next_peer = next_peer ? (next_peer->peer ? next_peer->peer : next_peer->next) : NULL) {
05734       if ((priority == 0 || peer->priority == priority) &&
05735             (!callerid || !matchcallerid || (matchcallerid && !strcmp(peer->cidmatch, callerid))) &&
05736             (!registrar || !strcmp(peer->registrar, registrar) )) {
05737          found = 1;
05738 
05739          /* we are first priority extension? */
05740          if (!previous_peer) {
05741             /*
05742              * We are first in the priority chain, so must update the extension chain.
05743              * The next node is either the next priority or the next extension
05744              */
05745             struct ast_exten *next_node = peer->peer ? peer->peer : peer->next;
05746             if (peer->peer) {
05747                /* move the peer_table and peer_label_table down to the next peer, if
05748                   it is there */
05749                peer->peer->peer_table = peer->peer_table;
05750                peer->peer->peer_label_table = peer->peer_label_table;
05751                peer->peer_table = NULL;
05752                peer->peer_label_table = NULL;
05753             }
05754             if (!prev_exten) {   /* change the root... */
05755                con->root = next_node;
05756             } else {
05757                prev_exten->next = next_node; /* unlink */
05758             }
05759             if (peer->peer)   { /* update the new head of the pri list */
05760                peer->peer->next = peer->next;
05761             }
05762          } else { /* easy, we are not first priority in extension */
05763             previous_peer->peer = peer->peer;
05764          }
05765 
05766          /* now, free whole priority extension */
05767          destroy_exten(peer);
05768       } else {
05769          previous_peer = peer;
05770       }
05771    }
05772    if (!already_locked)
05773       ast_unlock_context(con);
05774    return found ? 0 : -1;
05775 }

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

Definition at line 7998 of file pbx.c.

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

Referenced by handle_cli_dialplan_remove_ignorepat().

07999 {
08000    int ret = -1;
08001    struct ast_context *c;
08002 
08003    c = find_context_locked(context);
08004    if (c) {
08005       ret = ast_context_remove_ignorepat2(c, ignorepat, registrar);
08006       ast_unlock_contexts();
08007    }
08008    return ret;
08009 }

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

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

08012 {
08013    struct ast_ignorepat *ip, *ipl = NULL;
08014 
08015    ast_wrlock_context(con);
08016 
08017    for (ip = con->ignorepats; ip; ip = ip->next) {
08018       if (!strcmp(ip->pattern, ignorepat) &&
08019          (!registrar || (registrar == ip->registrar))) {
08020          if (ipl) {
08021             ipl->next = ip->next;
08022             ast_free(ip);
08023          } else {
08024             con->ignorepats = ip->next;
08025             ast_free(ip);
08026          }
08027          ast_unlock_context(con);
08028          return 0;
08029       }
08030       ipl = ip;
08031    }
08032 
08033    ast_unlock_context(con);
08034    errno = EINVAL;
08035    return -1;
08036 }

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

Remove a context include.

Note:
See ast_context_add_include for information on arguments
Return values:
0 on success
-1 on failure

Definition at line 5481 of file pbx.c.

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

Referenced by handle_cli_dialplan_remove_include().

05482 {
05483    int ret = -1;
05484    struct ast_context *c;
05485 
05486    c = find_context_locked(context);
05487    if (c) {
05488       /* found, remove include from this context ... */
05489       ret = ast_context_remove_include2(c, include, registrar);
05490       ast_unlock_contexts();
05491    }
05492    return ret;
05493 }

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

Removes an include by an ast_context structure.

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

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

05505 {
05506    struct ast_include *i, *pi = NULL;
05507    int ret = -1;
05508 
05509    ast_wrlock_context(con);
05510 
05511    /* find our include */
05512    for (i = con->includes; i; pi = i, i = i->next) {
05513       if (!strcmp(i->name, include) &&
05514             (!registrar || !strcmp(i->registrar, registrar))) {
05515          /* remove from list */
05516          ast_verb(3, "Removing inclusion of context '%s' in context '%s; registrar=%s'\n", include, ast_get_context_name(con), registrar);
05517          if (pi)
05518             pi->next = i->next;
05519          else
05520             con->includes = i->next;
05521          /* free include and return */
05522          ast_destroy_timing(&(i->timing));
05523          ast_free(i);
05524          ret = 0;
05525          break;
05526       }
05527    }
05528 
05529    ast_unlock_context(con);
05530 
05531    return ret;
05532 }

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

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

05540 {
05541    int ret = -1; /* default error return */
05542    struct ast_context *c;
05543 
05544    c = find_context_locked(context);
05545    if (c) {
05546       /* remove switch from this context ... */
05547       ret = ast_context_remove_switch2(c, sw, data, registrar);
05548       ast_unlock_contexts();
05549    }
05550    return ret;
05551 }

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 5561 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::list, ast_sw::name, and ast_sw::registrar.

Referenced by ast_context_remove_switch().

05562 {
05563    struct ast_sw *i;
05564    int ret = -1;
05565 
05566    ast_wrlock_context(con);
05567 
05568    /* walk switches */
05569    AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) {
05570       if (!strcmp(i->name, sw) && !strcmp(i->data, data) &&
05571          (!registrar || !strcmp(i->registrar, registrar))) {
05572          /* found, remove from list */
05573          ast_verb(3, "Removing switch '%s' from context '%s; registrar=%s'\n", sw, ast_get_context_name(con), registrar);
05574          AST_LIST_REMOVE_CURRENT(list);
05575          ast_free(i); /* free switch and return */
05576          ret = 0;
05577          break;
05578       }
05579    }
05580    AST_LIST_TRAVERSE_SAFE_END;
05581 
05582    ast_unlock_context(con);
05583 
05584    return ret;
05585 }

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

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

Referenced by _macro_exec().

05805 {
05806    struct ast_context *c;
05807    int ret = -1;
05808 
05809    c = find_context_locked(context);
05810    if (c) {
05811       ast_unlock_contexts();
05812 
05813       /* if we found context, unlock macrolock */
05814       ret = ast_mutex_unlock(&c->macrolock);
05815    }
05816 
05817    return ret;
05818 }

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

10531 {
10532    struct ast_include *inc = NULL;
10533    int res = 0;
10534 
10535    while ( (inc = ast_walk_context_includes(con, inc)) ) {
10536       if (ast_context_find(inc->rname))
10537          continue;
10538 
10539       res = -1;
10540       ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n",
10541          ast_get_context_name(con), inc->rname);
10542       break;
10543    }
10544 
10545    return res;
10546 }

struct ast_custom_function* ast_custom_function_find ( const char *  name  ) 

Definition at line 3502 of file pbx.c.

References ast_custom_function::acflist, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, and ast_custom_function::name.

Referenced by ast_func_read(), ast_func_read2(), ast_func_write(), config_curl(), destroy_curl(), handle_show_function(), op_func(), realtime_curl(), realtime_multi_curl(), require_curl(), store_curl(), update2_curl(), and update_curl().

03503 {
03504    struct ast_custom_function *acf = NULL;
03505 
03506    AST_RWLIST_RDLOCK(&acf_root);
03507    AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) {
03508       if (!strcmp(name, acf->name))
03509          break;
03510    }
03511    AST_RWLIST_UNLOCK(&acf_root);
03512 
03513    return acf;
03514 }

int ast_custom_function_unregister ( struct ast_custom_function acf  ) 

Unregister a custom function.

Definition at line 3516 of file pbx.c.

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

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

03517 {
03518    struct ast_custom_function *cur;
03519 
03520    if (!acf) {
03521       return -1;
03522    }
03523 
03524    AST_RWLIST_WRLOCK(&acf_root);
03525    if ((cur = AST_RWLIST_REMOVE(&acf_root, acf, acflist))) {
03526 #ifdef AST_XML_DOCS
03527       if (cur->docsrc == AST_XML_DOC) {
03528          ast_string_field_free_memory(acf);
03529       }
03530 #endif
03531       ast_verb(2, "Unregistered custom function %s\n", cur->name);
03532    }
03533    AST_RWLIST_UNLOCK(&acf_root);
03534 
03535    return cur ? 0 : -1;
03536 }

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

07841 {
07842    if (i->timezone) {
07843       ast_free(i->timezone);
07844       i->timezone = NULL;
07845    }
07846    return 0;
07847 }

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

04326 {
04327    switch (devstate) {
04328    case AST_DEVICE_ONHOLD:
04329       return AST_EXTENSION_ONHOLD;
04330    case AST_DEVICE_BUSY:
04331       return AST_EXTENSION_BUSY;
04332    case AST_DEVICE_UNKNOWN:
04333       return AST_EXTENSION_NOT_INUSE;
04334    case AST_DEVICE_UNAVAILABLE:
04335    case AST_DEVICE_INVALID:
04336       return AST_EXTENSION_UNAVAILABLE;
04337    case AST_DEVICE_RINGINUSE:
04338       return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING);
04339    case AST_DEVICE_RINGING:
04340       return AST_EXTENSION_RINGING;
04341    case AST_DEVICE_INUSE:
04342       return AST_EXTENSION_INUSE;
04343    case AST_DEVICE_NOT_INUSE:
04344       return AST_EXTENSION_NOT_INUSE;
04345    case AST_DEVICE_TOTAL: /* not a device state, included for completeness */
04346       break;
04347    }
04348 
04349    return AST_EXTENSION_NOT_INUSE;
04350 }

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 4877 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_bridge_call(), ast_pbx_outgoing_exten(), cb_events(), cli_console_dial(), conf_run(), console_dial(), console_transfer(), dahdi_handle_dtmf(), dahdi_r2_on_call_offered(), dahdi_r2_on_dnis_digit_received(), 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(), pri_dchannel(), pri_ss_thread(), privacy_exec(), process_ast_dsp(), process_sdp(), readexten_exec(), register_peer_exten(), show_debug_helper(), sip_new(), sip_read(), skinny_ss(), socket_process(), vm_authenticate(), and waitstream_core().

04878 {
04879    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0);
04880 }

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 8152 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(), do_bridge_masquerade(), handle_setpriority(), pbx_parseable_goto(), and return_exec().

08153 {
08154    if (!chan)
08155       return -1;
08156 
08157    ast_channel_lock(chan);
08158 
08159    if (!ast_strlen_zero(context))
08160       ast_copy_string(chan->context, context, sizeof(chan->context));
08161    if (!ast_strlen_zero(exten))
08162       ast_copy_string(chan->exten, exten, sizeof(chan->exten));
08163    if (priority > -1) {
08164       chan->priority = priority;
08165       /* see flag description in channel.h for explanation */
08166       if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP))
08167          chan->priority--;
08168    }
08169 
08170    ast_channel_unlock(chan);
08171 
08172    return 0;
08173 }

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

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

02651 {
02652    if (needmore != E_MATCHMORE && needmore != E_CANMATCH)
02653       ast_log(LOG_WARNING, "invalid argument %d\n", needmore);
02654    return extension_match_core(pattern, data, needmore);
02655 }

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

References ext_cmp().

Referenced by lua_extension_cmp().

02453 {
02454    return ext_cmp(a, b);
02455 }

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 2645 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(), show_dialplan_helper(), and sig_pri_msn_match().

02646 {
02647    return extension_match_core(pattern, data, E_MATCH);
02648 }

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

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

Parameters:
c this is not important
context which context to look in
exten which extension to get state
Returns:
extension state as defined in the ast_extension_states enum

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

04396 {
04397    struct ast_exten *e;
04398 
04399    if (!(e = ast_hint_extension(c, context, exten))) {  /* Do we have a hint for this extension ? */
04400       return -1;                   /* No hint, return -1 */
04401    }
04402 
04403    if (e->exten[0] == '_') {
04404       /* Create this hint on-the-fly */
04405       ast_add_extension(e->parent->name, 0, exten, e->priority, e->label,
04406          e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr,
04407          e->registrar);
04408       if (!(e = ast_hint_extension(c, context, exten))) {
04409          /* Improbable, but not impossible */
04410          return -1;
04411       }
04412    }
04413 
04414    return ast_extension_state2(e);  /* Check all devices in the hint */
04415 }

static int ast_extension_state2 ( struct ast_exten e  )  [static]

Check state of extension by using hints.

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

04371 {
04372    struct ast_str *hint_app = ast_str_thread_get(&extensionstate_buf, 32);
04373 
04374    if (!e || !hint_app) {
04375       return -1;
04376    }
04377 
04378    ast_str_set(&hint_app, 0, "%s", ast_get_extension_app(e));
04379    return ast_extension_state3(hint_app);
04380 }

const char* ast_extension_state2str ( int  extension_state  ) 

Return string representation of the state of an extension.

Parameters:
extension_state is the numerical state delivered by ast_extension_state
Returns:
the state of an extension as string

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

04384 {
04385    int i;
04386 
04387    for (i = 0; (i < ARRAY_LEN(extension_states)); i++) {
04388       if (extension_states[i].extension_state == extension_state)
04389          return extension_states[i].text;
04390    }
04391    return "Unknown";
04392 }

static int ast_extension_state3 ( struct ast_str hint_app  )  [static]

Definition at line 4352 of file pbx.c.

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

Referenced by ast_extension_state2(), and handle_statechange().

04353 {
04354    char *cur;
04355    char *rest;
04356    struct ast_devstate_aggregate agg;
04357 
04358    /* One or more devices separated with a & character */
04359    rest = ast_str_buffer(hint_app);
04360 
04361    ast_devstate_aggregate_init(&agg);
04362    while ((cur = strsep(&rest, "&"))) {
04363       ast_devstate_aggregate_add(&agg, ast_device_state(cur));
04364    }
04365 
04366    return ast_devstate_to_extenstate(ast_devstate_aggregate_result(&agg));
04367 }

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

Registers a state change callback.

Parameters:
context which context to look in
exten which extension to get state
change_cb callback to call if state changed
data to pass to callback
Note:
The change_cb is called if the state of an extension is changed.
Return values:
-1 on failure
ID on success

Definition at line 4616 of file pbx.c.

References ast_extension_state_add_destroy().

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

04618 {
04619    return ast_extension_state_add_destroy(context, exten, change_cb, NULL, data);
04620 }

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 
)

Registers a state change callback with destructor.

Since:
1.8.9

10.1.0

Parameters:
context which context to look in
exten which extension to get state
change_cb callback to call if state changed
destroy_cb callback to call when registration destroyed.
data to pass to callback
Note:
The change_cb is called if the state of an extension is changed.

The destroy_cb is called when the registration is deleted so the registerer can release any associated resources.

Return values:
-1 on failure
ID on success

Definition at line 4529 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_exten::cidmatch, ast_exten::data, destroy_state_cb(), ast_exten::exten, hints, 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().

04531 {
04532    struct ast_hint *hint;
04533    struct ast_state_cb *state_cb;
04534    struct ast_exten *e;
04535    int id;
04536 
04537    /* If there's no context and extension:  add callback to statecbs list */
04538    if (!context && !exten) {
04539       /* Prevent multiple adds from adding the same change_cb at the same time. */
04540       ao2_lock(statecbs);
04541 
04542       /* Remove any existing change_cb. */
04543       ao2_find(statecbs, change_cb, OBJ_UNLINK | OBJ_NODATA);
04544 
04545       /* Now insert the change_cb */
04546       if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) {
04547          ao2_unlock(statecbs);
04548          return -1;
04549       }
04550       state_cb->id = 0;
04551       state_cb->change_cb = change_cb;
04552       state_cb->destroy_cb = destroy_cb;
04553       state_cb->data = data;
04554       ao2_link(statecbs, state_cb);
04555 
04556       ao2_ref(state_cb, -1);
04557       ao2_unlock(statecbs);
04558       return 0;
04559    }
04560 
04561    if (!context || !exten)
04562       return -1;
04563 
04564    /* This callback type is for only one hint, so get the hint */
04565    e = ast_hint_extension(NULL, context, exten);
04566    if (!e) {
04567       return -1;
04568    }
04569 
04570    /* If this is a pattern, dynamically create a new extension for this
04571     * particular match.  Note that this will only happen once for each
04572     * individual extension, because the pattern will no longer match first.
04573     */
04574    if (e->exten[0] == '_') {
04575       ast_add_extension(e->parent->name, 0, exten, e->priority, e->label,
04576          e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr,
04577          e->registrar);
04578       e = ast_hint_extension(NULL, context, exten);
04579       if (!e || e->exten[0] == '_') {
04580          return -1;
04581       }
04582    }
04583 
04584    /* Find the hint in the hints container */
04585    ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */
04586    hint = ao2_find(hints, e, 0);
04587    if (!hint) {
04588       ao2_unlock(hints);
04589       return -1;
04590    }
04591 
04592    /* Now insert the callback in the callback list  */
04593    if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) {
04594       ao2_ref(hint, -1);
04595       ao2_unlock(hints);
04596       return -1;
04597    }
04598    do {
04599       id = stateid++;      /* Unique ID for this callback */
04600       /* Do not allow id to ever be -1 or 0. */
04601    } while (id == -1 || id == 0);
04602    state_cb->id = id;
04603    state_cb->change_cb = change_cb; /* Pointer to callback routine */
04604    state_cb->destroy_cb = destroy_cb;
04605    state_cb->data = data;     /* Data for the callback */
04606    ao2_link(hint->callbacks, state_cb);
04607 
04608    ao2_ref(state_cb, -1);
04609    ao2_ref(hint, -1);
04610    ao2_unlock(hints);
04611 
04612    return id;
04613 }

int ast_extension_state_del ( int  id,
ast_state_cb_type  change_cb 
)

Deletes a registered state change callback by ID.

Parameters:
id of the registered state callback to delete
change_cb callback to call if state changed (Used if id == 0 (global))
Return values:
0 success
-1 failure

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

04639 {
04640    struct ast_state_cb *p_cur;
04641    int ret = -1;
04642 
04643    if (!id) {  /* id == 0 is a callback without extension */
04644       if (!change_cb) {
04645          return ret;
04646       }
04647       p_cur = ao2_find(statecbs, change_cb, OBJ_UNLINK);
04648       if (p_cur) {
04649          ret = 0;
04650          ao2_ref(p_cur, -1);
04651       }
04652    } else { /* callback with extension, find the callback based on ID */
04653       struct ast_hint *hint;
04654 
04655       ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */
04656       hint = ao2_callback(hints, 0, find_hint_by_cb_id, &id);
04657       if (hint) {
04658          p_cur = ao2_find(hint->callbacks, &id, OBJ_UNLINK);
04659          if (p_cur) {
04660             ret = 0;
04661             ao2_ref(p_cur, -1);
04662          }
04663          ao2_ref(hint, -1);
04664       }
04665       ao2_unlock(hints);
04666    }
04667 
04668    return ret;
04669 }

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

04883 {
04884    return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
04885 }

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

References E_FINDLABEL, and pbx_extension_helper().

04888 {
04889    return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
04890 }

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 3660 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, ast_module_user::chan, 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().

03661 {
03662    char *copy = ast_strdupa(function);
03663    char *args = func_args(copy);
03664    struct ast_custom_function *acfptr = ast_custom_function_find(copy);
03665    int res;
03666    struct ast_module_user *u = NULL;
03667 
03668    if (acfptr == NULL) {
03669       ast_log(LOG_ERROR, "Function %s not registered\n", copy);
03670    } else if (!acfptr->read && !acfptr->read2) {
03671       ast_log(LOG_ERROR, "Function %s cannot be read\n", copy);
03672    } else if (acfptr->read) {
03673       if (acfptr->mod) {
03674          u = __ast_module_user_add(acfptr->mod, chan);
03675       }
03676       res = acfptr->read(chan, copy, args, workspace, len);
03677       if (acfptr->mod && u) {
03678          __ast_module_user_remove(acfptr->mod, u);
03679       }
03680       return res;
03681    } else {
03682       struct ast_str *str = ast_str_create(16);
03683       if (acfptr->mod) {
03684          u = __ast_module_user_add(acfptr->mod, chan);
03685       }
03686       res = acfptr->read2(chan, copy, args, &str, 0);
03687       if (acfptr->mod && u) {
03688          __ast_module_user_remove(acfptr->mod, u);
03689       }
03690       ast_copy_string(workspace, ast_str_buffer(str), len > ast_str_size(str) ? ast_str_size(str) : len);
03691       ast_free(str);
03692       return res;
03693    }
03694    return -1;
03695 }

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 3697 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, ast_module_user::chan, copy(), func_args(), LOG_ERROR, maxsize, ast_custom_function::mod, ast_custom_function::read, ast_custom_function::read2, ast_custom_function::read_max, str, and VAR_BUF_SIZE.

Referenced by append_channel_vars(), and ast_str_substitute_variables_full().

03698 {
03699    char *copy = ast_strdupa(function);
03700    char *args = func_args(copy);
03701    struct ast_custom_function *acfptr = ast_custom_function_find(copy);
03702    int res;
03703    struct ast_module_user *u = NULL;
03704 
03705    if (acfptr == NULL) {
03706       ast_log(LOG_ERROR, "Function %s not registered\n", copy);
03707    } else if (!acfptr->read && !acfptr->read2) {
03708       ast_log(LOG_ERROR, "Function %s cannot be read\n", copy);
03709    } else {
03710       if (acfptr->mod) {
03711          u = __ast_module_user_add(acfptr->mod, chan);
03712       }
03713       ast_str_reset(*str);
03714       if (acfptr->read2) {
03715          /* ast_str enabled */
03716          res = acfptr->read2(chan, copy, args, str, maxlen);
03717       } else {
03718          /* Legacy function pointer, allocate buffer for result */
03719          int maxsize = ast_str_size(*str);
03720          if (maxlen > -1) {
03721             if (maxlen == 0) {
03722                if (acfptr->read_max) {
03723                   maxsize = acfptr->read_max;
03724                } else {
03725                   maxsize = VAR_BUF_SIZE;
03726                }
03727             } else {
03728                maxsize = maxlen;
03729             }
03730             ast_str_make_space(str, maxsize);
03731          }
03732          res = acfptr->read(chan, copy, args, ast_str_buffer(*str), maxsize);
03733       }
03734       if (acfptr->mod && u) {
03735          __ast_module_user_remove(acfptr->mod, u);
03736       }
03737       return res;
03738    }
03739    return -1;
03740 }

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

References __ast_module_user_add(), __ast_module_user_remove(), args, ast_custom_function_find(), ast_log(), ast_strdupa, ast_module_user::chan, 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().

03743 {
03744    char *copy = ast_strdupa(function);
03745    char *args = func_args(copy);
03746    struct ast_custom_function *acfptr = ast_custom_function_find(copy);
03747 
03748    if (acfptr == NULL)
03749       ast_log(LOG_ERROR, "Function %s not registered\n", copy);
03750    else if (!acfptr->write)
03751       ast_log(LOG_ERROR, "Function %s cannot be written to\n", copy);
03752    else {
03753       int res;
03754       struct ast_module_user *u = NULL;
03755       if (acfptr->mod)
03756          u = __ast_module_user_add(acfptr->mod, chan);
03757       res = acfptr->write(chan, copy, args, value);
03758       if (acfptr->mod && u)
03759          __ast_module_user_remove(acfptr->mod, u);
03760       return res;
03761    }
03762 
03763    return -1;
03764 }

const char* ast_get_context_name ( struct ast_context con  ) 

Definition at line 10382 of file pbx.c.

References ast_context::name.

Referenced by _macro_exec(), ast_context_add_include2(), ast_context_add_switch2(), ast_context_remove_include2(), ast_context_remove_switch2(), ast_context_verify_includes(), ast_remove_hint(), complete_dialplan_add_extension(), complete_dialplan_add_ignorepat(), complete_dialplan_add_include(), complete_dialplan_remove_extension(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), complete_show_dialplan_context(), context_merge_incls_swits_igps_other_registrars(), destroy_hint(), dundi_precache_full(), find_matching_endwhile(), find_matching_priority(), handle_cli_dialplan_save(), handle_show_hint(), handle_show_hints(), handle_statechange(), hints_data_provider_get(), manager_show_dialplan_helper(), show_debug_helper(), and show_dialplan_helper().

10383 {
10384    return con ? con->name : NULL;
10385 }

const char* ast_get_context_registrar ( struct ast_context c  ) 

Definition at line 10420 of file pbx.c.

References ast_context::registrar.

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

10421 {
10422    return c ? c->registrar : NULL;
10423 }

const char* ast_get_extension_app ( struct ast_exten e  ) 

Definition at line 10450 of file pbx.c.

References ast_exten::app.

Referenced by _macro_exec(), ast_add_hint(), ast_extension_state2(), ast_get_hint(), ast_str_get_hint(), find_matching_endwhile(), get_parking_exten(), handle_cli_dialplan_save(), handle_show_hint(), handle_show_hints(), handle_statechange(), hints_data_provider_get(), manager_show_dialplan_helper(), and print_ext().

10451 {
10452    return e ? e->app : NULL;
10453 }

void* ast_get_extension_app_data ( struct ast_exten e  ) 

Definition at line 10455 of file pbx.c.

References ast_exten::data.

Referenced by _macro_exec(), ast_get_hint(), ast_masq_park_call_exten(), ast_park_call_exten(), ast_str_get_hint(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), print_ext(), and xfer_park_call_helper().

10456 {
10457    return e ? e->data : NULL;
10458 }

const char* ast_get_extension_cidmatch ( struct ast_exten e  ) 

Definition at line 10445 of file pbx.c.

References ast_exten::cidmatch.

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

10446 {
10447    return e ? e->cidmatch : NULL;
10448 }

struct ast_context* ast_get_extension_context ( struct ast_exten exten  ) 

Definition at line 10387 of file pbx.c.

References exten.

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

10388 {
10389    return exten ? exten->parent : NULL;
10390 }

const char* ast_get_extension_label ( struct ast_exten exten  ) 

Definition at line 10397 of file pbx.c.

References exten.

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

10398 {
10399    return exten ? exten->label : NULL;
10400 }

int ast_get_extension_matchcid ( struct ast_exten e  ) 

Definition at line 10440 of file pbx.c.

References ast_exten::matchcid.

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

10441 {
10442    return e ? e->matchcid : 0;
10443 }

const char* ast_get_extension_name ( struct ast_exten exten  ) 

Definition at line 10392 of file pbx.c.

References exten.

Referenced by ast_add_hint(), ast_remove_hint(), complete_core_show_hint(), complete_dialplan_remove_extension(), destroy_hint(), dundi_precache_full(), find_matching_priority(), handle_cli_dialplan_save(), handle_show_hint(), handle_show_hints(), handle_statechange(), hint_hash(), hints_data_provider_get(), manager_show_dialplan_helper(), and show_dialplan_helper().

10393 {
10394    return exten ? exten->exten : NULL;
10395 }

int ast_get_extension_priority ( struct ast_exten exten  ) 

Definition at line 10412 of file pbx.c.

References exten.

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

10413 {
10414    return exten ? exten->priority : -1;
10415 }

const char* ast_get_extension_registrar ( struct ast_exten e  ) 

Definition at line 10425 of file pbx.c.

References ast_exten::registrar.

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

10426 {
10427    return e ? e->registrar : NULL;
10428 }

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

If an extension hint exists, return non-zero.

Parameters:
hint buffer for hint
hintsize size of hint buffer, in bytes
name buffer for name portion of hint
namesize size of name buffer
c Channel from which to return the hint. This is only important when the hint or name contains an expression to be expanded.
context which context to look in
exten which extension to search for
Returns:
If an extension within the given context with the priority PRIORITY_HINT is found, a non zero value will be returned. Otherwise, 0 is returned.

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

04840 {
04841    struct ast_exten *e = ast_hint_extension(c, context, exten);
04842 
04843    if (e) {
04844       if (hint)
04845          ast_copy_string(hint, ast_get_extension_app(e), hintsize);
04846       if (name) {
04847          const char *tmp = ast_get_extension_app_data(e);
04848          if (tmp)
04849             ast_copy_string(name, tmp, namesize);
04850       }
04851       return -1;
04852    }
04853    return 0;
04854 }

const char* ast_get_ignorepat_name ( struct ast_ignorepat ip  ) 

Definition at line 10407 of file pbx.c.

References ast_ignorepat::pattern.

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

10408 {
10409    return ip ? ip->pattern : NULL;
10410 }

const char* ast_get_ignorepat_registrar ( struct ast_ignorepat ip  ) 

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

10436 {
10437    return ip ? ip->registrar : NULL;
10438 }

const char* ast_get_include_name ( struct ast_include inc  ) 

Definition at line 10402 of file pbx.c.

References ast_include::name.

Referenced by complete_dialplan_remove_include(), context_merge_incls_swits_igps_other_registrars(), find_matching_priority(), handle_cli_dialplan_save(), lookup_ci(), manager_show_dialplan_helper(), and show_dialplan_helper().

10403 {
10404    return inc ? inc->name : NULL;
10405 }

const char* ast_get_include_registrar ( struct ast_include i  ) 

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

10431 {
10432    return i ? i->registrar : NULL;
10433 }

const char* ast_get_switch_data ( struct ast_sw sw  ) 

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

10466 {
10467    return sw ? sw->data : NULL;
10468 }

int ast_get_switch_eval ( struct ast_sw sw  ) 

Definition at line 10470 of file pbx.c.

References ast_sw::eval.

Referenced by context_merge_incls_swits_igps_other_registrars().

10471 {
10472    return sw->eval;
10473 }

const char* ast_get_switch_name ( struct ast_sw sw  ) 

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

10461 {
10462    return sw ? sw->name : NULL;
10463 }

const char* ast_get_switch_registrar ( struct ast_sw sw  ) 

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

10476 {
10477    return sw ? sw->registrar : NULL;
10478 }

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

10571 {
10572    return __ast_goto_if_exists(chan, context, exten, priority, 0);
10573 }

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]

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

04317 {
04318    struct ast_exten *e;
04319    ast_rdlock_contexts();
04320    e = ast_hint_extension_nolock(c, context, exten);
04321    ast_unlock_contexts();
04322    return e;
04323 }

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

Find hint for given extension in context.

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

04311 {
04312    struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */
04313    return pbx_find_extension(c, NULL, &q, context, exten, PRIORITY_HINT, NULL, "", E_MATCH);
04314 }

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 8094 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(), pri_ss_thread(), and skinny_ss().

08095 {
08096    struct ast_context *con = ast_context_find(context);
08097 
08098    if (con) {
08099       struct ast_ignorepat *pat;
08100 
08101       for (pat = con->ignorepats; pat; pat = pat->next) {
08102          if (ast_extension_match(pat->pattern, pattern))
08103             return 1;
08104       }
08105    }
08106 
08107    return 0;
08108 }

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

References E_MATCHMORE, and pbx_extension_helper().

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

04898 {
04899    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0);
04900 }

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 7391 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_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, store_hint::data, E_MATCH, store_hint::exten, hints, ast_hint::laststate, store_hint::laststate, store_hint::list, ast_context::next, store_hint::next, OBJ_UNLINK, pbx_find_extension(), PRIORITY_HINT, and pbx_find_info::stacklen.

Referenced by lua_reload_extensions(), and pbx_load_module().

07392 {
07393    double ft;
07394    struct ast_context *tmp;
07395    struct ast_context *oldcontextslist;
07396    struct ast_hashtab *oldtable;
07397    struct store_hints hints_stored = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
07398    struct store_hints hints_removed = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
07399    struct store_hint *saved_hint;
07400    struct ast_hint *hint;
07401    struct ast_exten *exten;
07402    int length;
07403    struct ast_state_cb *thiscb;
07404    struct ast_hashtab_iter *iter;
07405    struct ao2_iterator i;
07406    struct timeval begintime;
07407    struct timeval writelocktime;
07408    struct timeval endlocktime;
07409    struct timeval enddeltime;
07410 
07411    /*
07412     * It is very important that this function hold the hints
07413     * container lock _and_ the conlock during its operation; not
07414     * only do we need to ensure that the list of contexts and
07415     * extensions does not change, but also that no hint callbacks
07416     * (watchers) are added or removed during the merge/delete
07417     * process
07418     *
07419     * In addition, the locks _must_ be taken in this order, because
07420     * there are already other code paths that use this order
07421     */
07422 
07423    begintime = ast_tvnow();
07424    ast_mutex_lock(&context_merge_lock);/* Serialize ast_merge_contexts_and_delete */
07425    ast_wrlock_contexts();
07426    iter = ast_hashtab_start_traversal(contexts_table);
07427    while ((tmp = ast_hashtab_next(iter))) {
07428       context_merge(extcontexts, exttable, tmp, registrar);
07429    }
07430    ast_hashtab_end_traversal(iter);
07431 
07432    ao2_lock(hints);
07433    writelocktime = ast_tvnow();
07434 
07435    /* preserve all watchers for hints */
07436    i = ao2_iterator_init(hints, AO2_ITERATOR_DONTLOCK);
07437    for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
07438       if (ao2_container_count(hint->callbacks)) {
07439          ao2_lock(hint);
07440          if (!hint->exten) {
07441             /* The extension has already been destroyed. (Should never happen here) */
07442             ao2_unlock(hint);
07443             continue;
07444          }
07445 
07446          length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2
07447             + sizeof(*saved_hint);
07448          if (!(saved_hint = ast_calloc(1, length))) {
07449             ao2_unlock(hint);
07450             continue;
07451          }
07452 
07453          /* This removes all the callbacks from the hint into saved_hint. */
07454          while ((thiscb = ao2_callback(hint->callbacks, OBJ_UNLINK, NULL, NULL))) {
07455             AST_LIST_INSERT_TAIL(&saved_hint->callbacks, thiscb, entry);
07456             /*
07457              * We intentionally do not unref thiscb to account for the
07458              * non-ao2 reference in saved_hint->callbacks
07459              */
07460          }
07461 
07462          saved_hint->laststate = hint->laststate;
07463          saved_hint->context = saved_hint->data;
07464          strcpy(saved_hint->data, hint->exten->parent->name);
07465          saved_hint->exten = saved_hint->data + strlen(saved_hint->context) + 1;
07466          strcpy(saved_hint->exten, hint->exten->exten);
07467          ao2_unlock(hint);
07468          AST_LIST_INSERT_HEAD(&hints_stored, saved_hint, list);
07469       }
07470    }
07471    ao2_iterator_destroy(&i);
07472 
07473    /* save the old table and list */
07474    oldtable = contexts_table;
07475    oldcontextslist = contexts;
07476 
07477    /* move in the new table and list */
07478    contexts_table = exttable;
07479    contexts = *extcontexts;
07480 
07481    /*
07482     * Restore the watchers for hints that can be found; notify
07483     * those that cannot be restored.
07484     */
07485    while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_stored, list))) {
07486       struct pbx_find_info q = { .stacklen = 0 };
07487 
07488       exten = pbx_find_extension(NULL, NULL, &q, saved_hint->context, saved_hint->exten,
07489          PRIORITY_HINT, NULL, "", E_MATCH);
07490       /*
07491        * If this is a pattern, dynamically create a new extension for this
07492        * particular match.  Note that this will only happen once for each
07493        * individual extension, because the pattern will no longer match first.
07494        */
07495       if (exten && exten->exten[0] == '_') {
07496          ast_add_extension_nolock(exten->parent->name, 0, saved_hint->exten,
07497             PRIORITY_HINT, NULL, 0, exten->app, ast_strdup(exten->data), ast_free_ptr,
07498             exten->registrar);
07499          /* rwlocks are not recursive locks */
07500          exten = ast_hint_extension_nolock(NULL, saved_hint->context,
07501             saved_hint->exten);
07502       }
07503 
07504       /* Find the hint in the hints container */
07505       hint = exten ? ao2_find(hints, exten, 0) : NULL;
07506       if (!hint) {
07507          /*
07508           * Notify watchers of this removed hint later when we aren't
07509           * encumberd by so many locks.
07510           */
07511          AST_LIST_INSERT_HEAD(&hints_removed, saved_hint, list);
07512       } else {
07513          ao2_lock(hint);
07514          while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) {
07515             ao2_link(hint->callbacks, thiscb);
07516             /* Ref that we added when putting into saved_hint->callbacks */
07517             ao2_ref(thiscb, -1);
07518          }
07519          hint->laststate = saved_hint->laststate;
07520          ao2_unlock(hint);
07521          ao2_ref(hint, -1);
07522          ast_free(saved_hint);
07523       }
07524    }
07525 
07526    ao2_unlock(hints);
07527    ast_unlock_contexts();
07528 
07529    /*
07530     * Notify watchers of all removed hints with the same lock
07531     * environment as handle_statechange().
07532     */
07533    while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_removed, list))) {
07534       /* this hint has been removed, notify the watchers */
07535       while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) {
07536          thiscb->change_cb(saved_hint->context, saved_hint->exten,
07537             AST_EXTENSION_REMOVED, thiscb->data);
07538          /* Ref that we added when putting into saved_hint->callbacks */
07539          ao2_ref(thiscb, -1);
07540       }
07541       ast_free(saved_hint);
07542    }
07543 
07544    ast_mutex_unlock(&context_merge_lock);
07545    endlocktime = ast_tvnow();
07546 
07547    /*
07548     * The old list and hashtab no longer are relevant, delete them
07549     * while the rest of asterisk is now freely using the new stuff
07550     * instead.
07551     */
07552 
07553    ast_hashtab_destroy(oldtable, NULL);
07554 
07555    for (tmp = oldcontextslist; tmp; ) {
07556       struct ast_context *next;  /* next starting point */
07557 
07558       next = tmp->next;
07559       __ast_internal_context_destroy(tmp);
07560       tmp = next;
07561    }
07562    enddeltime = ast_tvnow();
07563 
07564    ft = ast_tvdiff_us(writelocktime, begintime);
07565    ft /= 1000000.0;
07566    ast_verb(3,"Time to scan old dialplan and merge leftovers back into the new: %8.6f sec\n", ft);
07567 
07568    ft = ast_tvdiff_us(endlocktime, writelocktime);
07569    ft /= 1000000.0;
07570    ast_verb(3,"Time to restore hints and swap in new dialplan: %8.6f sec\n", ft);
07571 
07572    ft = ast_tvdiff_us(enddeltime, endlocktime);
07573    ft /= 1000000.0;
07574    ast_verb(3,"Time to delete the old dialplan: %8.6f sec\n", ft);
07575 
07576    ft = ast_tvdiff_us(enddeltime, begintime);
07577    ft /= 1000000.0;
07578    ast_verb(3,"Total time merge_contexts_delete: %8.6f sec\n", ft);
07579 }

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

10636 {
10637    return pbx_parseable_goto(chan, goto_string, 0);
10638 }

int ast_pbx_init ( void   ) 

Provided by pbx.c

Definition at line 10700 of file pbx.c.

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

Referenced by main().

10701 {
10702    hints = ao2_container_alloc(HASH_EXTENHINT_SIZE, hint_hash, hint_cmp);
10703    statecbs = ao2_container_alloc(1, NULL, statecbs_cmp);
10704 
10705    return (hints && statecbs) ? 0 : -1;
10706 }

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

References __ast_request_and_dial(), 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(), async_stat::chan, errno, LOG_WARNING, and outgoing_helper::vars.

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

08972 {
08973    struct ast_channel *chan;
08974    struct app_tmp *tmp;
08975    int res = -1, cdr_res = -1;
08976    struct outgoing_helper oh;
08977 
08978    memset(&oh, 0, sizeof(oh));
08979    oh.vars = vars;
08980    oh.account = account;
08981 
08982    if (locked_channel)
08983       *locked_channel = NULL;
08984    if (ast_strlen_zero(app)) {
08985       res = -1;
08986       goto outgoing_app_cleanup;
08987    }
08988    if (synchronous) {
08989       chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh);
08990       if (chan) {
08991          ast_set_variables(chan, vars);
08992          if (account)
08993             ast_cdr_setaccount(chan, account);
08994          if (chan->_state == AST_STATE_UP) {
08995             res = 0;
08996             ast_verb(4, "Channel %s was answered.\n", chan->name);
08997             tmp = ast_calloc(1, sizeof(*tmp));
08998             if (!tmp || ast_string_field_init(tmp, 252)) {
08999                if (tmp) {
09000                   ast_free(tmp);
09001                }
09002                res = -1;
09003             } else {
09004                ast_string_field_set(tmp, app, app);
09005                ast_string_field_set(tmp, data, appdata);
09006                tmp->chan = chan;
09007                if (synchronous > 1) {
09008                   if (locked_channel)
09009                      ast_channel_unlock(chan);
09010                   ast_pbx_run_app(tmp);
09011                } else {
09012                   if (locked_channel)
09013                      ast_channel_lock(chan);
09014                   if (ast_pthread_create_detached(&tmp->t, NULL, ast_pbx_run_app, tmp)) {
09015                      ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno));
09016                      ast_string_field_free_memory(tmp);
09017                      ast_free(tmp);
09018                      if (locked_channel)
09019                         ast_channel_unlock(chan);
09020                      ast_hangup(chan);
09021                      res = -1;
09022                   } else {
09023                      if (locked_channel)
09024                         *locked_channel = chan;
09025                   }
09026                }
09027             }
09028          } else {
09029             ast_verb(4, "Channel %s was never answered.\n", chan->name);
09030             if (chan->cdr) { /* update the cdr */
09031                /* here we update the status of the call, which sould be busy.
09032                 * if that fails then we set the status to failed */
09033                if (ast_cdr_disposition(chan->cdr, chan->hangupcause))
09034                   ast_cdr_failed(chan->cdr);
09035             }
09036             ast_hangup(chan);
09037          }
09038       }
09039 
09040       if (res < 0) { /* the call failed for some reason */
09041          if (*reason == 0) { /* if the call failed (not busy or no answer)
09042                         * update the cdr with the failed message */
09043             cdr_res = ast_pbx_outgoing_cdr_failed();
09044             if (cdr_res != 0) {
09045                res = cdr_res;
09046                goto outgoing_app_cleanup;
09047             }
09048          }
09049       }
09050 
09051    } else {
09052       struct async_stat *as;
09053       if (!(as = ast_calloc(1, sizeof(*as)))) {
09054          res = -1;
09055          goto outgoing_app_cleanup;
09056       }
09057       chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh);
09058       if (!chan) {
09059          ast_free(as);
09060          res = -1;
09061          goto outgoing_app_cleanup;
09062       }
09063       as->chan = chan;
09064       ast_copy_string(as->app, app, sizeof(as->app));
09065       if (appdata)
09066          ast_copy_string(as->appdata,  appdata, sizeof(as->appdata));
09067       as->timeout = timeout;
09068       ast_set_variables(chan, vars);
09069       if (account)
09070          ast_cdr_setaccount(chan, account);
09071       /* Start a new thread, and get something handling this channel. */
09072       if (locked_channel)
09073          ast_channel_lock(chan);
09074       if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) {
09075          ast_log(LOG_WARNING, "Failed to start async wait\n");
09076          ast_free(as);
09077          if (locked_channel)
09078             ast_channel_unlock(chan);
09079          ast_hangup(chan);
09080          res = -1;
09081          goto outgoing_app_cleanup;
09082       } else {
09083          if (locked_channel)
09084             *locked_channel = chan;
09085       }
09086       res = 0;
09087    }
09088 outgoing_app_cleanup:
09089    ast_variables_destroy(vars);
09090    return res;
09091 }

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

08776 {
08777    /* allocate a channel */
08778    struct ast_channel *chan = ast_dummy_channel_alloc();
08779 
08780    if (!chan)
08781       return -1;  /* failure */
08782 
08783    chan->cdr = ast_cdr_alloc();
08784    if (!chan->cdr) {
08785       /* allocation of the cdr failed */
08786       chan = ast_channel_unref(chan);   /* free the channel */
08787       return -1;                /* return failure */
08788    }
08789 
08790    /* allocation of the cdr was successful */
08791    ast_cdr_init(chan->cdr, chan);  /* initialize our channel's cdr */
08792    ast_cdr_start(chan->cdr);       /* record the start and stop time */
08793    ast_cdr_end(chan->cdr);
08794    ast_cdr_failed(chan->cdr);      /* set the status to failed */
08795    ast_cdr_detach(chan->cdr);      /* post and free the record */
08796    chan->cdr = NULL;
08797    chan = ast_channel_unref(chan);         /* free the channel */
08798 
08799    return 0;  /* success */
08800 }

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 8802 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, outgoing_helper::cid_name, outgoing_helper::cid_num, ast_channel::context, outgoing_helper::context, outgoing_helper::exten, ast_channel::hangupcause, LOG_ERROR, LOG_WARNING, ast_channel::name, outgoing_helper::parent_channel, pbx_builtin_setvar_helper(), outgoing_helper::priority, set_ext_pri(), and outgoing_helper::vars.

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

08803 {
08804    struct ast_channel *chan;
08805    struct async_stat *as;
08806    int res = -1, cdr_res = -1;
08807    struct outgoing_helper oh;
08808 
08809    if (synchronous) {
08810       oh.context = context;
08811       oh.exten = exten;
08812       oh.priority = priority;
08813       oh.cid_num = cid_num;
08814       oh.cid_name = cid_name;
08815       oh.account = account;
08816       oh.vars = vars;
08817       oh.parent_channel = NULL;
08818 
08819       chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh);
08820       if (channel) {
08821          *channel = chan;
08822          if (chan)
08823             ast_channel_lock(chan);
08824       }
08825       if (chan) {
08826          if (chan->_state == AST_STATE_UP) {
08827                res = 0;
08828             ast_verb(4, "Channel %s was answered.\n", chan->name);
08829 
08830             if (synchronous > 1) {
08831                if (channel)
08832                   ast_channel_unlock(chan);
08833                if (ast_pbx_run(chan)) {
08834                   ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name);
08835                   if (channel)
08836                      *channel = NULL;
08837                   ast_hangup(chan);
08838                   chan = NULL;
08839                   res = -1;
08840                }
08841             } else {
08842                if (ast_pbx_start(chan)) {
08843                   ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name);
08844                   if (channel) {
08845                      *channel = NULL;
08846                      ast_channel_unlock(chan);
08847                   }
08848                   ast_hangup(chan);
08849                   res = -1;
08850                }
08851                chan = NULL;
08852             }
08853          } else {
08854             ast_verb(4, "Channel %s was never answered.\n", chan->name);
08855 
08856             if (chan->cdr) { /* update the cdr */
08857                /* here we update the status of the call, which sould be busy.
08858                 * if that fails then we set the status to failed */
08859                if (ast_cdr_disposition(chan->cdr, chan->hangupcause))
08860                   ast_cdr_failed(chan->cdr);
08861             }
08862 
08863             if (channel) {
08864                *channel = NULL;
08865                ast_channel_unlock(chan);
08866             }
08867             ast_hangup(chan);
08868             chan = NULL;
08869          }
08870       }
08871 
08872       if (res < 0) { /* the call failed for some reason */
08873          if (*reason == 0) { /* if the call failed (not busy or no answer)
08874                         * update the cdr with the failed message */
08875             cdr_res = ast_pbx_outgoing_cdr_failed();
08876             if (cdr_res != 0) {
08877                res = cdr_res;
08878                goto outgoing_exten_cleanup;
08879             }
08880          }
08881 
08882          /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */
08883          /* check if "failed" exists */
08884          if (ast_exists_extension(chan, context, "failed", 1, NULL)) {
08885             chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", NULL, 0, "OutgoingSpoolFailed");
08886             if (chan) {
08887                char failed_reason[4] = "";
08888                if (!ast_strlen_zero(context))
08889                   ast_copy_string(chan->context, context, sizeof(chan->context));
08890                set_ext_pri(chan, "failed", 1);
08891                ast_set_variables(chan, vars);
08892                snprintf(failed_reason, sizeof(failed_reason), "%d", *reason);
08893                pbx_builtin_setvar_helper(chan, "REASON", failed_reason);
08894                if (account)
08895                   ast_cdr_setaccount(chan, account);
08896                if (ast_pbx_run(chan)) {
08897                   ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name);
08898                   ast_hangup(chan);
08899                }
08900                chan = NULL;
08901             }
08902          }
08903       }
08904    } else {
08905       if (!(as = ast_calloc(1, sizeof(*as)))) {
08906          res = -1;
08907          goto outgoing_exten_cleanup;
08908       }
08909       chan = ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name);
08910       if (channel) {
08911          *channel = chan;
08912          if (chan)
08913             ast_channel_lock(chan);
08914       }
08915       if (!chan) {
08916          ast_free(as);
08917          res = -1;
08918          goto outgoing_exten_cleanup;
08919       }
08920       as->chan = chan;
08921       ast_copy_string(as->context, context, sizeof(as->context));
08922       set_ext_pri(as->chan,  exten, priority);
08923       as->timeout = timeout;
08924       ast_set_variables(chan, vars);
08925       if (account)
08926          ast_cdr_setaccount(chan, account);
08927       if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) {
08928          ast_log(LOG_WARNING, "Failed to start async wait\n");
08929          ast_free(as);
08930          if (channel) {
08931             *channel = NULL;
08932             ast_channel_unlock(chan);
08933          }
08934          ast_hangup(chan);
08935          res = -1;
08936          goto outgoing_exten_cleanup;
08937       }
08938       res = 0;
08939    }
08940 outgoing_exten_cleanup:
08941    ast_variables_destroy(vars);
08942    return res;
08943 }

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

References ast_pbx_run_args().

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

05401 {
05402    return ast_pbx_run_args(c, NULL);
05403 }

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

run the application and free the descriptor once done

Definition at line 8955 of file pbx.c.

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

Referenced by ast_pbx_outgoing_app().

08956 {
08957    struct app_tmp *tmp = data;
08958    struct ast_app *app;
08959    app = pbx_findapp(tmp->app);
08960    if (app) {
08961       ast_verb(4, "Launching %s(%s) on %s\n", tmp->app, tmp->data, tmp->chan->name);
08962       pbx_exec(tmp->chan, app, tmp->data);
08963    } else
08964       ast_log(LOG_WARNING, "No such application '%s'\n", tmp->app);
08965    ast_hangup(tmp->chan);
08966    ast_string_field_free_memory(tmp);
08967    ast_free(tmp);
08968    return NULL;
08969 }

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

References __ast_pbx_run(), args, 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(), and handle_gosub().

05381 {
05382    enum ast_pbx_result res = AST_PBX_SUCCESS;
05383 
05384    if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) {
05385       ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n");
05386       return AST_PBX_FAILED;
05387    }
05388 
05389    if (increase_call_count(c)) {
05390       return AST_PBX_CALL_LIMIT;
05391    }
05392 
05393    res = __ast_pbx_run(c, args);
05394 
05395    decrease_call_count();
05396 
05397    return res;
05398 }

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

05354 {
05355    pthread_t t;
05356 
05357    if (!c) {
05358       ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
05359       return AST_PBX_FAILED;
05360    }
05361 
05362    if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) {
05363       ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n");
05364       return AST_PBX_FAILED;
05365    }
05366 
05367    if (increase_call_count(c))
05368       return AST_PBX_CALL_LIMIT;
05369 
05370    /* Start a new thread, and get something handling this channel. */
05371    if (ast_pthread_create_detached(&t, NULL, pbx_thread, c)) {
05372       ast_log(LOG_WARNING, "Failed to create new channel thread\n");
05373       decrease_call_count();
05374       return AST_PBX_FAILED;
05375    }
05376 
05377    return AST_PBX_SUCCESS;
05378 }

int ast_processed_calls ( void   ) 

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

Definition at line 5410 of file pbx.c.

References totalcalls.

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

05411 {
05412    return totalcalls;
05413 }

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

10370 {
10371    return ast_rwlock_rdlock(&con->lock);
10372 }

int ast_rdlock_contexts ( void   ) 

Read locks the context list.

Return values:
0 on success
-1 on error

Definition at line 10351 of file pbx.c.

References ast_mutex_lock, and conlock.

Referenced by _macro_exec(), ast_context_find(), ast_context_find_or_create(), ast_hint_extension(), complete_dialplan_add_extension(), complete_dialplan_add_ignorepat(), complete_dialplan_add_include(), complete_dialplan_remove_extension(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), complete_show_dialplan_context(), dundi_precache_full(), find_context_locked(), find_matching_endwhile(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), pbx_extension_helper(), show_debug_helper(), show_dialplan_helper(), and unreference_cached_app().

10352 {
10353    return ast_mutex_lock(&conlock);
10354 }

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

Register an application.

Parameters:
app Short name of the application
execute a function callback to execute the application. It should return non-zero if the channel needs to be hung up.
synopsis a short description (one line synopsis) of the application
description long description with all of the details about the use of the application
mod module this application belongs to
This registers an application with Asterisk's internal application list.
Note:
The individual applications themselves are responsible for registering and unregistering and unregistering their own CLI commands.
Return values:
0 success
-1 failure.

Definition at line 5821 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, ast_app::list, 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().

05822 {
05823    struct ast_app *tmp, *cur = NULL;
05824    char tmps[80];
05825    int length, res;
05826 #ifdef AST_XML_DOCS
05827    char *tmpxml;
05828 #endif
05829 
05830    AST_RWLIST_WRLOCK(&apps);
05831    AST_RWLIST_TRAVERSE(&apps, tmp, list) {
05832       if (!(res = strcasecmp(app, tmp->name))) {
05833          ast_log(LOG_WARNING, "Already have an application '%s'\n", app);
05834          AST_RWLIST_UNLOCK(&apps);
05835          return -1;
05836       } else if (res < 0)
05837          break;
05838    }
05839 
05840    length = sizeof(*tmp) + strlen(app) + 1;
05841 
05842    if (!(tmp = ast_calloc(1, length))) {
05843       AST_RWLIST_UNLOCK(&apps);
05844       return -1;
05845    }
05846 
05847    if (ast_string_field_init(tmp, 128)) {
05848       AST_RWLIST_UNLOCK(&apps);
05849       ast_free(tmp);
05850       return -1;
05851    }
05852 
05853    strcpy(tmp->name, app);
05854    tmp->execute = execute;
05855    tmp->module = mod;
05856 
05857 #ifdef AST_XML_DOCS
05858    /* Try to lookup the docs in our XML documentation database */
05859    if (ast_strlen_zero(synopsis) && ast_strlen_zero(description)) {
05860       /* load synopsis */
05861       tmpxml = ast_xmldoc_build_synopsis("application", app, ast_module_name(tmp->module));
05862       ast_string_field_set(tmp, synopsis, tmpxml);
05863       ast_free(tmpxml);
05864 
05865       /* load description */
05866       tmpxml = ast_xmldoc_build_description("application", app, ast_module_name(tmp->module));
05867       ast_string_field_set(tmp, description, tmpxml);
05868       ast_free(tmpxml);
05869 
05870       /* load syntax */
05871       tmpxml = ast_xmldoc_build_syntax("application", app, ast_module_name(tmp->module));
05872       ast_string_field_set(tmp, syntax, tmpxml);
05873       ast_free(tmpxml);
05874 
05875       /* load arguments */
05876       tmpxml = ast_xmldoc_build_arguments("application", app, ast_module_name(tmp->module));
05877       ast_string_field_set(tmp, arguments, tmpxml);
05878       ast_free(tmpxml);
05879 
05880       /* load seealso */
05881       tmpxml = ast_xmldoc_build_seealso("application", app, ast_module_name(tmp->module));
05882       ast_string_field_set(tmp, seealso, tmpxml);
05883       ast_free(tmpxml);
05884       tmp->docsrc = AST_XML_DOC;
05885    } else {
05886 #endif
05887       ast_string_field_set(tmp, synopsis, synopsis);
05888       ast_string_field_set(tmp, description, description);
05889 #ifdef AST_XML_DOCS
05890       tmp->docsrc = AST_STATIC_DOC;
05891    }
05892 #endif
05893 
05894    /* Store in alphabetical order */
05895    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, cur, list) {
05896       if (strcasecmp(tmp->name, cur->name) < 0) {
05897          AST_RWLIST_INSERT_BEFORE_CURRENT(tmp, list);
05898          break;
05899       }
05900    }
05901    AST_RWLIST_TRAVERSE_SAFE_END;
05902    if (!cur)
05903       AST_RWLIST_INSERT_TAIL(&apps, tmp, list);
05904 
05905    ast_verb(2, "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps)));
05906 
05907    AST_RWLIST_UNLOCK(&apps);
05908 
05909    return 0;
05910 }

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

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

Referenced by load_module().

05917 {
05918    struct ast_switch *tmp;
05919 
05920    AST_RWLIST_WRLOCK(&switches);
05921    AST_RWLIST_TRAVERSE(&switches, tmp, list) {
05922       if (!strcasecmp(tmp->name, sw->name)) {
05923          AST_RWLIST_UNLOCK(&switches);
05924          ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name);
05925          return -1;
05926       }
05927    }
05928    AST_RWLIST_INSERT_TAIL(&switches, sw, list);
05929    AST_RWLIST_UNLOCK(&switches);
05930 
05931    return 0;
05932 }

static int ast_remove_hint ( struct ast_exten e  )  [static]

Remove hint from extension.

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

04719 {
04720    /* Cleanup the Notifys if hint is removed */
04721    struct ast_hint *hint;
04722 
04723    if (!e) {
04724       return -1;
04725    }
04726 
04727    hint = ao2_find(hints, e, OBJ_UNLINK);
04728    if (!hint) {
04729       return -1;
04730    }
04731 
04732    /*
04733     * The extension is being destroyed so we must save some
04734     * information to notify that the extension is deactivated.
04735     */
04736    ao2_lock(hint);
04737    ast_copy_string(hint->context_name,
04738       ast_get_context_name(ast_get_extension_context(hint->exten)),
04739       sizeof(hint->context_name));
04740    ast_copy_string(hint->exten_name, ast_get_extension_name(hint->exten),
04741       sizeof(hint->exten_name));
04742    hint->exten = NULL;
04743    ao2_unlock(hint);
04744 
04745    ao2_ref(hint, -1);
04746 
04747    return 0;
04748 }

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

04903 {
04904    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN, found, combined_find_spawn);
04905 }

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 
)

If an extension hint exists, return non-zero.

Parameters:
hint buffer for hint
hintsize Maximum size of hint buffer (<0 to prevent growth, >0 to limit growth to that number of bytes, or 0 for unlimited growth)
name buffer for name portion of hint
namesize Maximum size of name buffer (<0 to prevent growth, >0 to limit growth to that number of bytes, or 0 for unlimited growth)
c Channel from which to return the hint. This is only important when the hint or name contains an expression to be expanded.
context which context to look in
exten which extension to search for
Returns:
If an extension within the given context with the priority PRIORITY_HINT is found, a non zero value will be returned. Otherwise, 0 is returned.

Definition at line 4857 of file pbx.c.

References ast_get_extension_app(), ast_get_extension_app_data(), ast_hint_extension(), ast_str_set(), and fake_context::name.

Referenced by ast_str_retrieve_variable().

04858 {
04859    struct ast_exten *e = ast_hint_extension(c, context, exten);
04860 
04861    if (!e) {
04862       return 0;
04863    }
04864 
04865    if (hint) {
04866       ast_str_set(hint, hintsize, "%s", ast_get_extension_app(e));
04867    }
04868    if (name) {
04869       const char *tmp = ast_get_extension_app_data(e);
04870       if (tmp) {
04871          ast_str_set(name, namesize, "%s", tmp);
04872       }
04873    }
04874    return -1;
04875 }

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 3147 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_channel::name, ast_party_id::number, parse_variable_name(), ast_party_number::plan, ast_channel::priority, str, ast_party_dialed::transit_network_select, and ast_channel::uniqueid.

Referenced by ast_str_substitute_variables_full(), and pbx_retrieve_variable().

03148 {
03149    const char not_found = '\0';
03150    char *tmpvar;
03151    const char *ret;
03152    const char *s; /* the result */
03153    int offset, length;
03154    int i, need_substring;
03155    struct varshead *places[2] = { headp, &globals };  /* list of places where we may look */
03156    char workspace[20];
03157 
03158    if (c) {
03159       ast_channel_lock(c);
03160       places[0] = &c->varshead;
03161    }
03162    /*
03163     * Make a copy of var because parse_variable_name() modifies the string.
03164     * Then if called directly, we might need to run substring() on the result;
03165     * remember this for later in 'need_substring', 'offset' and 'length'
03166     */
03167    tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */
03168    need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */);
03169 
03170    /*
03171     * Look first into predefined variables, then into variable lists.
03172     * Variable 's' points to the result, according to the following rules:
03173     * s == &not_found (set at the beginning) means that we did not find a
03174     * matching variable and need to look into more places.
03175     * If s != &not_found, s is a valid result string as follows:
03176     * s = NULL if the variable does not have a value;
03177     * you typically do this when looking for an unset predefined variable.
03178     * s = workspace if the result has been assembled there;
03179     * typically done when the result is built e.g. with an snprintf(),
03180     * so we don't need to do an additional copy.
03181     * s != workspace in case we have a string, that needs to be copied
03182     * (the ast_copy_string is done once for all at the end).
03183     * Typically done when the result is already available in some string.
03184     */
03185    s = &not_found;   /* default value */
03186    if (c) { /* This group requires a valid channel */
03187       /* Names with common parts are looked up a piece at a time using strncmp. */
03188       if (!strncmp(var, "CALL", 4)) {
03189          if (!strncmp(var + 4, "ING", 3)) {
03190             if (!strcmp(var + 7, "PRES")) {        /* CALLINGPRES */
03191                ast_str_set(str, maxlen, "%d",
03192                   ast_party_id_presentation(&c->caller.id));
03193                s = ast_str_buffer(*str);
03194             } else if (!strcmp(var + 7, "ANI2")) {    /* CALLINGANI2 */
03195                ast_str_set(str, maxlen, "%d", c->caller.ani2);
03196                s = ast_str_buffer(*str);
03197             } else if (!strcmp(var + 7, "TON")) {     /* CALLINGTON */
03198                ast_str_set(str, maxlen, "%d", c->caller.id.number.plan);
03199                s = ast_str_buffer(*str);
03200             } else if (!strcmp(var + 7, "TNS")) {     /* CALLINGTNS */
03201                ast_str_set(str, maxlen, "%d", c->dialed.transit_network_select);
03202                s = ast_str_buffer(*str);
03203             }
03204          }
03205       } else if (!strcmp(var, "HINT")) {
03206          s = ast_str_get_hint(str, maxlen, NULL, 0, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL;
03207       } else if (!strcmp(var, "HINTNAME")) {
03208          s = ast_str_get_hint(NULL, 0, str, maxlen, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL;
03209       } else if (!strcmp(var, "EXTEN")) {
03210          s = c->exten;
03211       } else if (!strcmp(var, "CONTEXT")) {
03212          s = c->context;
03213       } else if (!strcmp(var, "PRIORITY")) {
03214          ast_str_set(str, maxlen, "%d", c->priority);
03215          s = ast_str_buffer(*str);
03216       } else if (!strcmp(var, "CHANNEL")) {
03217          s = c->name;
03218       } else if (!strcmp(var, "UNIQUEID")) {
03219          s = c->uniqueid;
03220       } else if (!strcmp(var, "HANGUPCAUSE")) {
03221          ast_str_set(str, maxlen, "%d", c->hangupcause);
03222          s = ast_str_buffer(*str);
03223       }
03224    }
03225    if (s == &not_found) { /* look for more */
03226       if (!strcmp(var, "EPOCH")) {
03227          ast_str_set(str, maxlen, "%u", (int) time(NULL));
03228          s = ast_str_buffer(*str);
03229       } else if (!strcmp(var, "SYSTEMNAME")) {
03230          s = ast_config_AST_SYSTEM_NAME;
03231       } else if (!strcmp(var, "ENTITYID")) {
03232          ast_eid_to_str(workspace, sizeof(workspace), &ast_eid_default);
03233          s = workspace;
03234       }
03235    }
03236    /* if not found, look into chanvars or global vars */
03237    for (i = 0; s == &not_found && i < ARRAY_LEN(places); i++) {
03238       struct ast_var_t *variables;
03239       if (!places[i])
03240          continue;
03241       if (places[i] == &globals)
03242          ast_rwlock_rdlock(&globalslock);
03243       AST_LIST_TRAVERSE(places[i], variables, entries) {
03244          if (!strcasecmp(ast_var_name(variables), var)) {
03245             s = ast_var_value(variables);
03246             break;
03247          }
03248       }
03249       if (places[i] == &globals)
03250          ast_rwlock_unlock(&globalslock);
03251    }
03252    if (s == &not_found || s == NULL) {
03253       ast_debug(5, "Result of '%s' is NULL\n", var);
03254       ret = NULL;
03255    } else {
03256       ast_debug(5, "Result of '%s' is '%s'\n", var, s);
03257       if (s != ast_str_buffer(*str)) {
03258          ast_str_set(str, maxlen, "%s", s);
03259       }
03260       ret = ast_str_buffer(*str);
03261       if (need_substring) {
03262          ret = ast_str_substring(*str, offset, length);
03263          ast_debug(2, "Final result of '%s' is '%s'\n", var, ret);
03264       }
03265    }
03266 
03267    if (c) {
03268       ast_channel_unlock(c);
03269    }
03270    return ret;
03271 }

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

References ast_str_substitute_variables_full().

Referenced by _macro_exec(), acf_odbc_read(), acf_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().

03946 {
03947    size_t used;
03948    ast_str_substitute_variables_full(buf, maxlen, chan, NULL, templ, &used);
03949 }

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

03767 {
03768    /* Substitutes variables into buf, based on string templ */
03769    char *cp4 = NULL;
03770    const char *tmp, *whereweare;
03771    int orig_size = 0;
03772    int offset, offset2, isfunction;
03773    const char *nextvar, *nextexp, *nextthing;
03774    const char *vars, *vare;
03775    char *finalvars;
03776    int pos, brackets, needsub, len;
03777    struct ast_str *substr1 = ast_str_create(16), *substr2 = NULL, *substr3 = ast_str_create(16);
03778 
03779    ast_str_reset(*buf);
03780    whereweare = tmp = templ;
03781    while (!ast_strlen_zero(whereweare)) {
03782       /* reset our buffer */
03783       ast_str_reset(substr3);
03784 
03785       /* Assume we're copying the whole remaining string */
03786       pos = strlen(whereweare);
03787       nextvar = NULL;
03788       nextexp = NULL;
03789       nextthing = strchr(whereweare, '$');
03790       if (nextthing) {
03791          switch (nextthing[1]) {
03792          case '{':
03793             nextvar = nextthing;
03794             pos = nextvar - whereweare;
03795             break;
03796          case '[':
03797             nextexp = nextthing;
03798             pos = nextexp - whereweare;
03799             break;
03800          default:
03801             pos = 1;
03802          }
03803       }
03804 
03805       if (pos) {
03806          /* Copy that many bytes */
03807          ast_str_append_substr(buf, maxlen, whereweare, pos);
03808 
03809          templ += pos;
03810          whereweare += pos;
03811       }
03812 
03813       if (nextvar) {
03814          /* We have a variable.  Find the start and end, and determine
03815             if we are going to have to recursively call ourselves on the
03816             contents */
03817          vars = vare = nextvar + 2;
03818          brackets = 1;
03819          needsub = 0;
03820 
03821          /* Find the end of it */
03822          while (brackets && *vare) {
03823             if ((vare[0] == '$') && (vare[1] == '{')) {
03824                needsub++;
03825             } else if (vare[0] == '{') {
03826                brackets++;
03827             } else if (vare[0] == '}') {
03828                brackets--;
03829             } else if ((vare[0] == '$') && (vare[1] == '['))
03830                needsub++;
03831             vare++;
03832          }
03833          if (brackets)
03834             ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n");
03835          len = vare - vars - 1;
03836 
03837          /* Skip totally over variable string */
03838          whereweare += (len + 3);
03839 
03840          /* Store variable name (and truncate) */
03841          ast_str_set_substr(&substr1, 0, vars, len);
03842          ast_debug(5, "Evaluating '%s' (from '%s' len %d)\n", ast_str_buffer(substr1), vars, len);
03843 
03844          /* Substitute if necessary */
03845          if (needsub) {
03846             size_t used;
03847             if (!substr2) {
03848                substr2 = ast_str_create(16);
03849             }
03850 
03851             ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used);
03852             finalvars = ast_str_buffer(substr2);
03853          } else {
03854             finalvars = ast_str_buffer(substr1);
03855          }
03856 
03857          parse_variable_name(finalvars, &offset, &offset2, &isfunction);
03858          if (isfunction) {
03859             /* Evaluate function */
03860             if (c || !headp) {
03861                cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3);
03862             } else {
03863                struct varshead old;
03864                struct ast_channel *bogus = ast_dummy_channel_alloc();
03865                if (bogus) {
03866                   memcpy(&old, &bogus->varshead, sizeof(old));
03867                   memcpy(&bogus->varshead, headp, sizeof(bogus->varshead));
03868                   cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3);
03869                   /* Don't deallocate the varshead that was passed in */
03870                   memcpy(&bogus->varshead, &old, sizeof(bogus->varshead));
03871                   ast_channel_unref(bogus);
03872                } else {
03873                   ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution.  Function results may be blank.\n");
03874                }
03875             }
03876             ast_debug(2, "Function result is '%s'\n", cp4 ? cp4 : "(null)");
03877          } else {
03878             /* Retrieve variable value */
03879             ast_str_retrieve_variable(&substr3, 0, c, headp, finalvars);
03880             cp4 = ast_str_buffer(substr3);
03881          }
03882          if (cp4) {
03883             ast_str_substring(substr3, offset, offset2);
03884             ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3));
03885          }
03886       } else if (nextexp) {
03887          /* We have an expression.  Find the start and end, and determine
03888             if we are going to have to recursively call ourselves on the
03889             contents */
03890          vars = vare = nextexp + 2;
03891          brackets = 1;
03892          needsub = 0;
03893 
03894          /* Find the end of it */
03895          while (brackets && *vare) {
03896             if ((vare[0] == '$') && (vare[1] == '[')) {
03897                needsub++;
03898                brackets++;
03899                vare++;
03900             } else if (vare[0] == '[') {
03901                brackets++;
03902             } else if (vare[0] == ']') {
03903                brackets--;
03904             } else if ((vare[0] == '$') && (vare[1] == '{')) {
03905                needsub++;
03906                vare++;
03907             }
03908             vare++;
03909          }
03910          if (brackets)
03911             ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n");
03912          len = vare - vars - 1;
03913 
03914          /* Skip totally over expression */
03915          whereweare += (len + 3);
03916 
03917          /* Store variable name (and truncate) */
03918          ast_str_set_substr(&substr1, 0, vars, len);
03919 
03920          /* Substitute if necessary */
03921          if (needsub) {
03922             size_t used;
03923             if (!substr2) {
03924                substr2 = ast_str_create(16);
03925             }
03926 
03927             ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used);
03928             finalvars = ast_str_buffer(substr2);
03929          } else {
03930             finalvars = ast_str_buffer(substr1);
03931          }
03932 
03933          if (ast_str_expr(&substr3, 0, c, finalvars)) {
03934             ast_debug(2, "Expression result is '%s'\n", ast_str_buffer(substr3));
03935          }
03936          ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3));
03937       }
03938    }
03939    *used = ast_str_strlen(*buf) - orig_size;
03940    ast_free(substr1);
03941    ast_free(substr2);
03942    ast_free(substr3);
03943 }

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

03952 {
03953    size_t used;
03954    ast_str_substitute_variables_full(buf, maxlen, NULL, headp, templ, &used);
03955 }

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

Definition at line 3082 of file pbx.c.

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

Referenced by ast_str_retrieve_variable(), and ast_str_substitute_variables_full().

03083 {
03084    int lr;  /* length of the input string after the copy */
03085 
03086    lr = ast_str_strlen(value); /* compute length after copy, so we never go out of the workspace */
03087 
03088    /* Quick check if no need to do anything */
03089    if (offset == 0 && length >= lr) /* take the whole string */
03090       return ast_str_buffer(value);
03091 
03092    if (offset < 0)   {  /* translate negative offset into positive ones */
03093       offset = lr + offset;
03094       if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */
03095          offset = 0;
03096    }
03097 
03098    /* too large offset result in empty string so we know what to return */
03099    if (offset >= lr) {
03100       ast_str_reset(value);
03101       return ast_str_buffer(value);
03102    }
03103 
03104    if (offset > 0) {
03105       /* Go ahead and chop off the beginning */
03106       memmove(ast_str_buffer(value), ast_str_buffer(value) + offset, ast_str_strlen(value) - offset + 1);
03107       lr -= offset;
03108    }
03109 
03110    if (length >= 0 && length < lr) {   /* truncate if necessary */
03111       char *tmp = ast_str_buffer(value);
03112       tmp[length] = '\0';
03113       ast_str_update(value);
03114    } else if (length < 0) {
03115       if (lr > -length) { /* After we remove from the front and from the rear, is there anything left? */
03116          char *tmp = ast_str_buffer(value);
03117          tmp[lr + length] = '\0';
03118          ast_str_update(value);
03119       } else {
03120          ast_str_reset(value);
03121       }
03122    } else {
03123       /* Nothing to do, but update the buffer length */
03124       ast_str_update(value);
03125    }
03126 
03127    return ast_str_buffer(value);
03128 }

int ast_unlock_context ( struct ast_context con  ) 

Return values:
Unlocks the given context
Parameters:
con context to unlock
Return values:
0 on success
-1 on failure

Definition at line 10374 of file pbx.c.

References ast_rwlock_unlock, and ast_context::lock.

Referenced by __ast_context_destroy(), _macro_exec(), 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(), ast_context_remove_switch2(), 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().

10375 {
10376    return ast_rwlock_unlock(&con->lock);
10377 }

int ast_unlock_contexts ( void   ) 

Unlocks contexts.

Return values:
0 on success
-1 on failure

Definition at line 10356 of file pbx.c.

References ast_mutex_unlock, and conlock.

Referenced by _macro_exec(), ast_add_extension(), ast_context_add_ignorepat(), ast_context_add_include(), ast_context_add_switch(), ast_context_destroy(), ast_context_find(), ast_context_find_or_create(), ast_context_lockmacro(), ast_context_remove_extension_callerid(), ast_context_remove_ignorepat(), ast_context_remove_include(), ast_context_remove_switch(), ast_context_unlockmacro(), ast_hint_extension(), ast_merge_contexts_and_delete(), complete_dialplan_add_extension(), complete_dialplan_add_ignorepat(), complete_dialplan_add_include(), complete_dialplan_remove_extension(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), complete_show_dialplan_context(), dundi_precache_full(), find_context_locked(), find_matching_endwhile(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), pbx_extension_helper(), show_debug_helper(), show_dialplan_helper(), and unreference_cached_app().

10357 {
10358    return ast_mutex_unlock(&conlock);
10359 }

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 7164 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::list, ast_app::name, and unreference_cached_app().

Referenced by __unload_module(), load_module(), and unload_module().

07165 {
07166    struct ast_app *tmp;
07167 
07168    AST_RWLIST_WRLOCK(&apps);
07169    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, tmp, list) {
07170       if (!strcasecmp(app, tmp->name)) {
07171          unreference_cached_app(tmp);
07172          AST_RWLIST_REMOVE_CURRENT(list);
07173          ast_verb(2, "Unregistered application '%s'\n", tmp->name);
07174          ast_string_field_free_memory(tmp);
07175          ast_free(tmp);
07176          break;
07177       }
07178    }
07179    AST_RWLIST_TRAVERSE_SAFE_END;
07180    AST_RWLIST_UNLOCK(&apps);
07181 
07182    return tmp ? 0 : -1;
07183 }

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

References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and ast_switch::list.

Referenced by __unload_module(), and unload_module().

05935 {
05936    AST_RWLIST_WRLOCK(&switches);
05937    AST_RWLIST_REMOVE(&switches, sw, list);
05938    AST_RWLIST_UNLOCK(&switches);
05939 }

struct ast_exten* ast_walk_context_extensions ( struct ast_context con,
struct ast_exten exten 
)

Definition at line 10488 of file pbx.c.

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

10490 {
10491    if (!exten)
10492       return con ? con->root : NULL;
10493    else
10494       return exten->next;
10495 }

struct ast_ignorepat* ast_walk_context_ignorepats ( struct ast_context con,
struct ast_ignorepat ip 
)

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

10523 {
10524    if (!ip)
10525       return con ? con->ignorepats : NULL;
10526    else
10527       return ip->next;
10528 }

struct ast_include* ast_walk_context_includes ( struct ast_context con,
struct ast_include inc 
)

Definition at line 10512 of file pbx.c.

References ast_context::includes, and ast_include::next.

Referenced by ast_context_verify_includes(), complete_dialplan_remove_include(), context_merge_incls_swits_igps_other_registrars(), context_used(), find_matching_priority(), handle_cli_dialplan_save(), lookup_ci(), manager_show_dialplan_helper(), and show_dialplan_helper().

10514 {
10515    if (!inc)
10516       return con ? con->includes : NULL;
10517    else
10518       return inc->next;
10519 }

struct ast_sw* ast_walk_context_switches ( struct ast_context con,
struct ast_sw sw 
)

Definition at line 10497 of file pbx.c.

References ast_context::alts, AST_LIST_FIRST, AST_LIST_NEXT, and ast_sw::list.

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

10499 {
10500    if (!sw)
10501       return con ? AST_LIST_FIRST(&con->alts) : NULL;
10502    else
10503       return AST_LIST_NEXT(sw, list);
10504 }

struct ast_context* ast_walk_contexts ( struct ast_context con  ) 

Definition at line 10483 of file pbx.c.

References contexts, and ast_context::next.

Referenced by _macro_exec(), ast_context_find(), complete_dialplan_add_extension(), complete_dialplan_add_ignorepat(), complete_dialplan_add_include(), complete_dialplan_remove_extension(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), complete_show_dialplan_context(), dundi_precache_full(), find_matching_endwhile(), find_matching_priority(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), pbx_load_module(), show_debug_helper(), show_dialplan_helper(), and unreference_cached_app().

10484 {
10485    return con ? con->next : contexts;
10486 }

struct ast_exten* ast_walk_extension_priorities ( struct ast_exten exten,
struct ast_exten priority 
)

Definition at line 10506 of file pbx.c.

References exten, and ast_exten::priority.

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

10508 {
10509    return priority ? priority->peer : exten;
10510 }

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

10365 {
10366    return ast_rwlock_wrlock(&con->lock);
10367 }

int ast_wrlock_contexts ( void   ) 

Write locks the context list.

Return values:
0 on success
-1 on error

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

10347 {
10348    return ast_mutex_lock(&conlock);
10349 }

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

Definition at line 8714 of file pbx.c.

References ast_channel::_state, app, 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_STATE_UP, ast_strlen_zero(), ast_verb, ast_waitfor(), async_stat::chan, ast_channel::context, async_stat::context, ast_channel::exten, async_stat::exten, f, LOG_ERROR, LOG_WARNING, ast_channel::name, pbx_exec(), pbx_findapp(), ast_channel::priority, async_stat::priority, and async_stat::timeout.

Referenced by ast_pbx_outgoing_app(), and ast_pbx_outgoing_exten().

08715 {
08716    struct async_stat *as = data;
08717    struct ast_channel *chan = as->chan;
08718    int timeout = as->timeout;
08719    int res;
08720    struct ast_frame *f;
08721    struct ast_app *app;
08722 
08723    while (timeout && (chan->_state != AST_STATE_UP)) {
08724       res = ast_waitfor(chan, timeout);
08725       if (res < 1)
08726          break;
08727       if (timeout > -1)
08728          timeout = res;
08729       f = ast_read(chan);
08730       if (!f)
08731          break;
08732       if (f->frametype == AST_FRAME_CONTROL) {
08733          if ((f->subclass.integer == AST_CONTROL_BUSY)  ||
08734              (f->subclass.integer == AST_CONTROL_CONGESTION) ) {
08735             ast_frfree(f);
08736             break;
08737          }
08738       }
08739       ast_frfree(f);
08740    }
08741    if (chan->_state == AST_STATE_UP) {
08742       if (!ast_strlen_zero(as->app)) {
08743          app = pbx_findapp(as->app);
08744          if (app) {
08745             ast_verb(3, "Launching %s(%s) on %s\n", as->app, as->appdata, chan->name);
08746             pbx_exec(chan, app, as->appdata);
08747          } else
08748             ast_log(LOG_WARNING, "No such application '%s'\n", as->app);
08749       } else {
08750          if (!ast_strlen_zero(as->context))
08751             ast_copy_string(chan->context, as->context, sizeof(chan->context));
08752          if (!ast_strlen_zero(as->exten))
08753             ast_copy_string(chan->exten, as->exten, sizeof(chan->exten));
08754          if (as->priority > 0)
08755             chan->priority = as->priority;
08756          /* Run the PBX */
08757          if (ast_pbx_run(chan)) {
08758             ast_log(LOG_ERROR, "Failed to start PBX on %s\n", chan->name);
08759          } else {
08760             /* PBX will have taken care of this */
08761             chan = NULL;
08762          }
08763       }
08764    }
08765    ast_free(as);
08766    if (chan)
08767       ast_hangup(chan);
08768    return NULL;
08769 }

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

04924 {
04925    int digit;
04926 
04927    buf[pos] = '\0';  /* make sure it is properly terminated */
04928    while (ast_matchmore_extension(c, c->context, buf, 1,
04929       S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
04930       /* As long as we're willing to wait, and as long as it's not defined,
04931          keep reading digits until we can't possibly get a right answer anymore.  */
04932       digit = ast_waitfordigit(c, waittime);
04933       if (c->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) {
04934          ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO);
04935       } else {
04936          if (!digit) /* No entry */
04937             break;
04938          if (digit < 0) /* Error, maybe a  hangup */
04939             return -1;
04940          if (pos < buflen - 1) { /* XXX maybe error otherwise ? */
04941             buf[pos++] = digit;
04942             buf[pos] = '\0';
04943          }
04944          waittime = c->pbx->dtimeoutms;
04945       }
04946    }
04947    return 0;
04948 }

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

06122 {
06123    struct ast_hint *hint;
06124    char *ret = NULL;
06125    int which = 0;
06126    int wordlen;
06127    struct ao2_iterator i;
06128 
06129    if (pos != 3)
06130       return NULL;
06131 
06132    wordlen = strlen(word);
06133 
06134    /* walk through all hints */
06135    i = ao2_iterator_init(hints, 0);
06136    for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
06137       ao2_lock(hint);
06138       if (!hint->exten) {
06139          /* The extension has already been destroyed */
06140          ao2_unlock(hint);
06141          continue;
06142       }
06143       if (!strncasecmp(word, ast_get_extension_name(hint->exten), wordlen) && ++which > state) {
06144          ret = ast_strdup(ast_get_extension_name(hint->exten));
06145          ao2_unlock(hint);
06146          ao2_ref(hint, -1);
06147          break;
06148       }
06149       ao2_unlock(hint);
06150    }
06151    ao2_iterator_destroy(&i);
06152 
06153    return ret;
06154 }

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

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

06333 {
06334    struct ast_context *c = NULL;
06335    char *ret = NULL;
06336    int which = 0;
06337    int wordlen;
06338 
06339    /* we are do completion of [exten@]context on second position only */
06340    if (pos != 2)
06341       return NULL;
06342 
06343    ast_rdlock_contexts();
06344 
06345    wordlen = strlen(word);
06346 
06347    /* walk through all contexts and return the n-th match */
06348    while ( (c = ast_walk_contexts(c)) ) {
06349       if (!strncasecmp(word, ast_get_context_name(c), wordlen) && ++which > state) {
06350          ret = ast_strdup(ast_get_context_name(c));
06351          break;
06352       }
06353    }
06354 
06355    ast_unlock_contexts();
06356 
06357    return ret;
06358 }

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

Definition at line 7305 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, store_hint::context, context_merge_incls_swits_igps_other_registrars(), ast_exten::data, ast_exten::datad, ast_exten::exten, store_hint::first, ast_exten::label, LOG_ERROR, ast_exten::matchcid, ast_exten::peer_table, ast_exten::priority, and ast_exten::registrar.

Referenced by ast_merge_contexts_and_delete().

07306 {
07307    struct ast_context *new = ast_hashtab_lookup(exttable, context); /* is there a match in the new set? */
07308    struct ast_exten *exten_item, *prio_item, *new_exten_item, *new_prio_item;
07309    struct ast_hashtab_iter *exten_iter;
07310    struct ast_hashtab_iter *prio_iter;
07311    int insert_count = 0;
07312    int first = 1;
07313 
07314    /* We'll traverse all the extensions/prios, and see which are not registrar'd with
07315       the current registrar, and copy them to the new context. If the new context does not
07316       exist, we'll create it "on demand". If no items are in this context to copy, then we'll
07317       only create the empty matching context if the old one meets the criteria */
07318 
07319    if (context->root_table) {
07320       exten_iter = ast_hashtab_start_traversal(context->root_table);
07321       while ((exten_item=ast_hashtab_next(exten_iter))) {
07322          if (new) {
07323             new_exten_item = ast_hashtab_lookup(new->root_table, exten_item);
07324          } else {
07325             new_exten_item = NULL;
07326          }
07327          prio_iter = ast_hashtab_start_traversal(exten_item->peer_table);
07328          while ((prio_item=ast_hashtab_next(prio_iter))) {
07329             int res1;
07330             char *dupdstr;
07331 
07332             if (new_exten_item) {
07333                new_prio_item = ast_hashtab_lookup(new_exten_item->peer_table, prio_item);
07334             } else {
07335                new_prio_item = NULL;
07336             }
07337             if (strcmp(prio_item->registrar,registrar) == 0) {
07338                continue;
07339             }
07340             /* make sure the new context exists, so we have somewhere to stick this exten/prio */
07341             if (!new) {
07342                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 */
07343             }
07344 
07345             /* copy in the includes, switches, and ignorepats */
07346             if (first) { /* but, only need to do this once */
07347                context_merge_incls_swits_igps_other_registrars(new, context, registrar);
07348                first = 0;
07349             }
07350 
07351             if (!new) {
07352                ast_log(LOG_ERROR,"Could not allocate a new context for %s in merge_and_delete! Danger!\n", context->name);
07353                ast_hashtab_end_traversal(prio_iter);
07354                ast_hashtab_end_traversal(exten_iter);
07355                return; /* no sense continuing. */
07356             }
07357             /* we will not replace existing entries in the new context with stuff from the old context.
07358                but, if this is because of some sort of registrar conflict, we ought to say something... */
07359 
07360             dupdstr = ast_strdup(prio_item->data);
07361 
07362             res1 = ast_add_extension2(new, 0, prio_item->exten, prio_item->priority, prio_item->label, 
07363                                 prio_item->matchcid ? prio_item->cidmatch : NULL, prio_item->app, dupdstr, prio_item->datad, prio_item->registrar);
07364             if (!res1 && new_exten_item && new_prio_item){
07365                ast_verb(3,"Dropping old dialplan item %s/%s/%d [%s(%s)] (registrar=%s) due to conflict with new dialplan\n",
07366                      context->name, prio_item->exten, prio_item->priority, prio_item->app, (char*)prio_item->data, prio_item->registrar);
07367             } else {
07368                /* 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,
07369                 and no double frees take place, either! */
07370                insert_count++;
07371             }
07372          }
07373          ast_hashtab_end_traversal(prio_iter);
07374       }
07375       ast_hashtab_end_traversal(exten_iter);
07376    }
07377 
07378    if (!insert_count && !new && (strcmp(context->registrar, registrar) != 0 ||
07379         (strcmp(context->registrar, registrar) == 0 && context->refcount > 1))) {
07380       /* we could have given it the registrar of the other module who incremented the refcount,
07381          but that's not available, so we give it the registrar we know about */
07382       new = ast_context_find_or_create(extcontexts, exttable, context->name, context->registrar);
07383 
07384       /* copy in the includes, switches, and ignorepats */
07385       context_merge_incls_swits_igps_other_registrars(new, context, registrar);
07386    }
07387 }

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

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

07273 {
07274    struct ast_include *i;
07275    struct ast_ignorepat *ip;
07276    struct ast_sw *sw;
07277 
07278    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);
07279    /* copy in the includes, switches, and ignorepats */
07280    /* walk through includes */
07281    for (i = NULL; (i = ast_walk_context_includes(old, i)) ; ) {
07282       if (strcmp(ast_get_include_registrar(i), registrar) == 0)
07283          continue; /* not mine */
07284       ast_context_add_include2(new, ast_get_include_name(i), ast_get_include_registrar(i));
07285    }
07286 
07287    /* walk through switches */
07288    for (sw = NULL; (sw = ast_walk_context_switches(old, sw)) ; ) {
07289       if (strcmp(ast_get_switch_registrar(sw), registrar) == 0)
07290          continue; /* not mine */
07291       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));
07292    }
07293 
07294    /* walk thru ignorepats ... */
07295    for (ip = NULL; (ip = ast_walk_context_ignorepats(old, ip)); ) {
07296       if (strcmp(ast_get_ignorepat_registrar(ip), registrar) == 0)
07297          continue; /* not mine */
07298       ast_context_add_ignorepat2(new, ast_get_ignorepat_name(ip), ast_get_ignorepat_registrar(ip));
07299    }
07300 }

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, ast_context::root_table, and t1.

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

05312 {
05313    ast_mutex_lock(&maxcalllock);
05314    if (countcalls > 0)
05315       countcalls--;
05316    ast_mutex_unlock(&maxcalllock);
05317 }

static void destroy_exten ( struct ast_exten e  )  [static]

Definition at line 5319 of file pbx.c.

References ast_free, ast_hashtab_destroy(), ast_remove_hint(), ast_exten::priority, and PRIORITY_HINT.

Referenced by __ast_internal_context_destroy(), and ast_context_remove_extension_callerid2().

05320 {
05321    if (e->priority == PRIORITY_HINT)
05322       ast_remove_hint(e);
05323 
05324    if (e->peer_table)
05325       ast_hashtab_destroy(e->peer_table,0);
05326    if (e->peer_label_table)
05327       ast_hashtab_destroy(e->peer_label_table, 0);
05328    if (e->datad)
05329       e->datad(e->data);
05330    ast_free(e);
05331 }

static void destroy_hint ( void *  obj  )  [static]

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

04689 {
04690    struct ast_hint *hint = obj;
04691 
04692    if (hint->callbacks) {
04693       struct ast_state_cb *state_cb;
04694       const char *context_name;
04695       const char *exten_name;
04696 
04697       if (hint->exten) {
04698          context_name = ast_get_context_name(ast_get_extension_context(hint->exten));
04699          exten_name = ast_get_extension_name(hint->exten);
04700          hint->exten = NULL;
04701       } else {
04702          /* The extension has already been destroyed */
04703          context_name = hint->context_name;
04704          exten_name = hint->exten_name;
04705       }
04706       while ((state_cb = ao2_callback(hint->callbacks, OBJ_UNLINK, NULL, NULL))) {
04707          /* Notify with -1 and remove all callbacks */
04708          /* NOTE: The casts will not be needed for v1.10 and later */
04709          state_cb->change_cb((char *) context_name, (char *) exten_name,
04710             AST_EXTENSION_DEACTIVATED, state_cb->data);
04711          ao2_ref(state_cb, -1);
04712       }
04713       ao2_ref(hint->callbacks, -1);
04714    }
04715 }

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

04520 {
04521    struct ast_state_cb *state_cb = doomed;
04522 
04523    if (state_cb->destroy_cb) {
04524       state_cb->destroy_cb(state_cb->id, state_cb->data);
04525    }
04526 }

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

Definition at line 10241 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(), device_state_tps, handle_statechange(), and LOG_ERROR.

10242 {
10243    const char *device;
10244    struct statechange *sc;
10245 
10246    device = ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE);
10247    if (ast_strlen_zero(device)) {
10248       ast_log(LOG_ERROR, "Received invalid event that had no device IE\n");
10249       return;
10250    }
10251 
10252    if (!(sc = ast_calloc(1, sizeof(*sc) + strlen(device) + 1)))
10253       return;
10254    strcpy(sc->dev, device);
10255    if (ast_taskprocessor_push(device_state_tps, handle_statechange, sc) < 0) {
10256       ast_free(sc);
10257    }
10258 }

static void exception_store_free ( void *  data  )  [static]

Definition at line 3273 of file pbx.c.

References ast_free, and ast_string_field_free_memory.

03274 {
03275    struct pbx_exception *exception = data;
03276    ast_string_field_free_memory(exception);
03277    ast_free(exception);
03278 }

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

the full routine to compare extensions in rules.

Definition at line 2419 of file pbx.c.

References ext_cmp1().

Referenced by ast_add_extension2_lockopt(), and ast_extension_cmp().

02420 {
02421    /* make sure non-patterns come first.
02422     * If a is not a pattern, it either comes first or
02423     * we do a more complex pattern comparison.
02424     */
02425    int ret = 0;
02426 
02427    if (a[0] != '_')
02428       return (b[0] == '_') ? -1 : strcmp(a, b);
02429 
02430    /* Now we know a is a pattern; if b is not, a comes first */
02431    if (b[0] != '_')
02432       return 1;
02433 
02434    /* ok we need full pattern sorting routine.
02435     * skip past the underscores */
02436    ++a; ++b;
02437    do {
02438       unsigned char bitwise[2][32] = { { 0, } };
02439       ret = ext_cmp1(&a, bitwise[0]) - ext_cmp1(&b, bitwise[1]);
02440       if (ret == 0) {
02441          /* Are the classes different, even though they score the same? */
02442          ret = memcmp(bitwise[0], bitwise[1], 32);
02443       }
02444    } while (!ret && a && b);
02445    if (ret == 0) {
02446       return 0;
02447    } else {
02448       return (ret > 0) ? 1 : -1;
02449    }
02450 }

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

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

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

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

Definition at line 2339 of file pbx.c.

References ast_log(), and LOG_WARNING.

Referenced by ext_cmp().

02340 {
02341    int c, cmin = 0xff, count = 0;
02342    const char *end;
02343 
02344    /* load value and advance pointer */
02345    c = *(*p)++;
02346 
02347    /* always return unless we have a set of chars */
02348    switch (toupper(c)) {
02349    default: /* ordinary character */
02350       bitwise[c / 8] = 1 << (c % 8);
02351       return 0x0100 | (c & 0xff);
02352 
02353    case 'N':   /* 2..9 */
02354       bitwise[6] = 0xfc;
02355       bitwise[7] = 0x03;
02356       return 0x0800 | '2';
02357 
02358    case 'X':   /* 0..9 */
02359       bitwise[6] = 0xff;
02360       bitwise[7] = 0x03;
02361       return 0x0A00 | '0';
02362 
02363    case 'Z':   /* 1..9 */
02364       bitwise[6] = 0xfe;
02365       bitwise[7] = 0x03;
02366       return 0x0900 | '1';
02367 
02368    case '.':   /* wildcard */
02369       return 0x18000;
02370 
02371    case '!':   /* earlymatch */
02372       return 0x28000;   /* less specific than NULL */
02373 
02374    case '\0':  /* empty string */
02375       *p = NULL;
02376       return 0x30000;
02377 
02378    case '[':   /* pattern */
02379       break;
02380    }
02381    /* locate end of set */
02382    end = strchr(*p, ']');
02383 
02384    if (end == NULL) {
02385       ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n");
02386       return 0x40000;   /* XXX make this entry go last... */
02387    }
02388 
02389    for (; *p < end  ; (*p)++) {
02390       unsigned char c1, c2;   /* first-last char in range */
02391       c1 = (unsigned char)((*p)[0]);
02392       if (*p + 2 < end && (*p)[1] == '-') { /* this is a range */
02393          c2 = (unsigned char)((*p)[2]);
02394          *p += 2;    /* skip a total of 3 chars */
02395       } else {        /* individual character */
02396          c2 = c1;
02397       }
02398       if (c1 < cmin) {
02399          cmin = c1;
02400       }
02401       for (; c1 <= c2; c1++) {
02402          unsigned char mask = 1 << (c1 % 8);
02403          /*!\note If two patterns score the same, the one with the lowest
02404           * ascii values will compare as coming first. */
02405          /* Flag the character as included (used) and count it. */
02406          if (!(bitwise[ c1 / 8 ] & mask)) {
02407             bitwise[ c1 / 8 ] |= mask;
02408             count += 0x100;
02409          }
02410       }
02411    }
02412    (*p)++;
02413    return count == 0 ? 0x30000 : (count | cmin);
02414 }

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

copy a string skipping whitespace

Definition at line 8271 of file pbx.c.

Referenced by ast_add_extension2_lockopt().

08272 {
08273    int count = 0;
08274    int insquares = 0;
08275 
08276    while (*src && (count < len - 1)) {
08277       if (*src == '[') {
08278          insquares = 1;
08279       } else if (*src == ']') {
08280          insquares = 0;
08281       } else if (*src == ' ' && !insquares) {
08282          src++;
08283          continue;
08284       }
08285       *dst = *src;
08286       dst++;
08287       src++;
08288       count++;
08289    }
08290    *dst = '\0';
08291 
08292    return count;
08293 }

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

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

02633 {
02634    int i;
02635    static int prof_id = -2;   /* marker for 'unallocated' id */
02636    if (prof_id == -2) {
02637       prof_id = ast_add_profile("ext_match", 0);
02638    }
02639    ast_mark(prof_id, 1);
02640    i = _extension_match_core(ast_strlen_zero(pattern) ? "" : pattern, ast_strlen_zero(data) ? "" : data, mode);
02641    ast_mark(prof_id, 0);
02642    return i;
02643 }

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

lookup for a context with a given name,

Return values:
found context or NULL if not found.

Definition at line 5445 of file pbx.c.

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

05446 {
05447    struct fake_context item;
05448 
05449    ast_copy_string(item.name, context, sizeof(item.name));
05450 
05451    return ast_hashtab_lookup(contexts_table, &item);
05452 }

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

lookup for a context with a given name,

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

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

05460 {
05461    struct ast_context *c;
05462    struct fake_context item;
05463 
05464    ast_copy_string(item.name, context, sizeof(item.name));
05465 
05466    ast_rdlock_contexts();
05467    c = ast_hashtab_lookup(contexts_table, &item);
05468    if (!c) {
05469       ast_unlock_contexts();
05470    }
05471 
05472    return c;
05473 }

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

Remove a watcher from the callback list.

Definition at line 4623 of file pbx.c.

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

Referenced by ast_extension_state_del().

04624 {
04625    struct ast_state_cb *state_cb;
04626    const struct ast_hint *hint = obj;
04627    int *id = arg;
04628 
04629    if ((state_cb = ao2_find(hint->callbacks, id, 0))) {
04630       ao2_ref(state_cb, -1);
04631       return CMP_MATCH | CMP_STOP;
04632    }
04633 
04634    return 0;
04635 }

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

References args, ast_log(), and LOG_WARNING.

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

03643 {
03644    char *args = strchr(function, '(');
03645 
03646    if (!args) {
03647       ast_log(LOG_WARNING, "Function '%s' doesn't contain parentheses.  Assuming null argument.\n", function);
03648    } else {
03649       char *p;
03650       *args++ = '\0';
03651       if ((p = strrchr(args, ')'))) {
03652          *p = '\0';
03653       } else {
03654          ast_log(LOG_WARNING, "Can't find trailing parenthesis for function '%s(%s'?\n", function, args);
03655       }
03656    }
03657    return args;
03658 }

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

Definition at line 1654 of file pbx.c.

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

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

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

Referenced by ast_build_timing().

07627 {
07628    int start, end; /* start and ending position */
07629    unsigned int mask = 0;
07630    char *part;
07631 
07632    /* Check for whole range */
07633    if (ast_strlen_zero(src) || !strcmp(src, "*")) {
07634       return (1 << max) - 1;
07635    }
07636 
07637    while ((part = strsep(&src, "&"))) {
07638       /* Get start and ending position */
07639       char *endpart = strchr(part, '-');
07640       if (endpart) {
07641          *endpart++ = '\0';
07642       }
07643       /* Find the start */
07644       if ((start = lookup_name(part, names, max)) < 0) {
07645          ast_log(LOG_WARNING, "Invalid %s '%s', skipping element\n", msg, part);
07646          continue;
07647       }
07648       if (endpart) { /* find end of range */
07649          if ((end = lookup_name(endpart, names, max)) < 0) {
07650             ast_log(LOG_WARNING, "Invalid end %s '%s', skipping element\n", msg, endpart);
07651             continue;
07652          }
07653       } else {
07654          end = start;
07655       }
07656       /* Fill the mask. Remember that ranges are cyclic */
07657       mask |= (1 << end);   /* initialize with last element */
07658       while (start != end) {
07659          mask |= (1 << start);
07660          if (++start >= max) {
07661             start = 0;
07662          }
07663       }
07664    }
07665    return mask;
07666 }

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

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

Referenced by ast_build_timing().

07670 {
07671    char *endpart, *part;
07672    int x;
07673    int st_h, st_m;
07674    int endh, endm;
07675    int minute_start, minute_end;
07676 
07677    /* start disabling all times, fill the fields with 0's, as they may contain garbage */
07678    memset(i->minmask, 0, sizeof(i->minmask));
07679 
07680    /* 1-minute per bit */
07681    /* Star is all times */
07682    if (ast_strlen_zero(times) || !strcmp(times, "*")) {
07683       /* 48, because each hour takes 2 integers; 30 bits each */
07684       for (x = 0; x < 48; x++) {
07685          i->minmask[x] = 0x3fffffff; /* 30 bits */
07686       }
07687       return;
07688    }
07689    /* Otherwise expect a range */
07690    while ((part = strsep(&times, "&"))) {
07691       if (!(endpart = strchr(part, '-'))) {
07692          if (sscanf(part, "%2d:%2d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) {
07693             ast_log(LOG_WARNING, "%s isn't a valid time.\n", part);
07694             continue;
07695          }
07696          i->minmask[st_h * 2 + (st_m >= 30 ? 1 : 0)] |= (1 << (st_m % 30));
07697          continue;
07698       }
07699       *endpart++ = '\0';
07700       /* why skip non digits? Mostly to skip spaces */
07701       while (*endpart && !isdigit(*endpart)) {
07702          endpart++;
07703       }
07704       if (!*endpart) {
07705          ast_log(LOG_WARNING, "Invalid time range starting with '%s-'.\n", part);
07706          continue;
07707       }
07708       if (sscanf(part, "%2d:%2d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) {
07709          ast_log(LOG_WARNING, "'%s' isn't a valid start time.\n", part);
07710          continue;
07711       }
07712       if (sscanf(endpart, "%2d:%2d", &endh, &endm) != 2 || endh < 0 || endh > 23 || endm < 0 || endm > 59) {
07713          ast_log(LOG_WARNING, "'%s' isn't a valid end time.\n", endpart);
07714          continue;
07715       }
07716       minute_start = st_h * 60 + st_m;
07717       minute_end = endh * 60 + endm;
07718       /* Go through the time and enable each appropriate bit */
07719       for (x = minute_start; x != minute_end; x = (x + 1) % (24 * 60)) {
07720          i->minmask[x / 30] |= (1 << (x % 30));
07721       }
07722       /* Do the last one */
07723       i->minmask[x / 30] |= (1 << (x % 30));
07724    }
07725    /* All done */
07726    return;
07727 }

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

Send ack once.

Definition at line 6658 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(), exten, ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, ast_cli_args::pos, show_debug_helper(), strsep(), ast_cli_entry::usage, and ast_cli_args::word.

06659 {
06660    char *exten = NULL, *context = NULL;
06661    /* Variables used for different counters */
06662    struct dialplan_counters counters;
06663    const char *incstack[AST_PBX_MAX_STACK];
06664 
06665    switch (cmd) {
06666    case CLI_INIT:
06667       e->command = "dialplan debug";
06668       e->usage =
06669          "Usage: dialplan debug [context]\n"
06670          "       Show dialplan context Trie(s). Usually only useful to folks debugging the deep internals of the fast pattern matcher\n";
06671       return NULL;
06672    case CLI_GENERATE:
06673       return complete_show_dialplan_context(a->line, a->word, a->pos, a->n);
06674    }
06675 
06676    memset(&counters, 0, sizeof(counters));
06677 
06678    if (a->argc != 2 && a->argc != 3)
06679       return CLI_SHOWUSAGE;
06680 
06681    /* we obtain [exten@]context? if yes, split them ... */
06682    /* note: we ignore the exten totally here .... */
06683    if (a->argc == 3) {
06684       if (strchr(a->argv[2], '@')) {   /* split into exten & context */
06685          context = ast_strdupa(a->argv[2]);
06686          exten = strsep(&context, "@");
06687          /* change empty strings to NULL */
06688          if (ast_strlen_zero(exten))
06689             exten = NULL;
06690       } else { /* no '@' char, only context given */
06691          context = ast_strdupa(a->argv[2]);
06692       }
06693       if (ast_strlen_zero(context))
06694          context = NULL;
06695    }
06696    /* else Show complete dial plan, context and exten are NULL */
06697    show_debug_helper(a->fd, context, exten, &counters, NULL, 0, incstack);
06698 
06699    /* check for input failure and throw some error messages */
06700    if (context && !counters.context_existence) {
06701       ast_cli(a->fd, "There is no existence of '%s' context\n", context);
06702       return CLI_FAILURE;
06703    }
06704 
06705 
06706    ast_cli(a->fd,"-= %d %s. =-\n",
06707          counters.total_context, counters.total_context == 1 ? "context" : "contexts");
06708 
06709    /* everything ok */
06710    return CLI_SUCCESS;
06711 }

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

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

07029 {
07030    struct ast_channel *chan;
07031    const char *chan_name, *var_name, *var_value;
07032 
07033    switch (cmd) {
07034    case CLI_INIT:
07035       e->command = "dialplan set chanvar";
07036       e->usage =
07037          "Usage: dialplan set chanvar <channel> <varname> <value>\n"
07038          "       Set channel variable <varname> to <value>\n";
07039       return NULL;
07040    case CLI_GENERATE:
07041       return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
07042    }
07043 
07044    if (a->argc != e->args + 3)
07045       return CLI_SHOWUSAGE;
07046 
07047    chan_name = a->argv[e->args];
07048    var_name = a->argv[e->args + 1];
07049    var_value = a->argv[e->args + 2];
07050 
07051    if (!(chan = ast_channel_get_by_name(chan_name))) {
07052       ast_cli(a->fd, "Channel '%s' not found\n", chan_name);
07053       return CLI_FAILURE;
07054    }
07055 
07056    pbx_builtin_setvar_helper(chan, var_name, var_value);
07057 
07058    chan = ast_channel_unref(chan);
07059 
07060    ast_cli(a->fd, "\n    -- Channel variable '%s' set to '%s' for '%s'\n",  var_name, var_value, chan_name);
07061 
07062    return CLI_SUCCESS;
07063 }

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

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

07066 {
07067    int oldval = 0;
07068 
07069    switch (cmd) {
07070    case CLI_INIT:
07071       e->command = "dialplan set extenpatternmatchnew true";
07072       e->usage =
07073          "Usage: dialplan set extenpatternmatchnew true|false\n"
07074          "       Use the NEW extension pattern matching algorithm, true or false.\n";
07075       return NULL;
07076    case CLI_GENERATE:
07077       return NULL;
07078    }
07079 
07080    if (a->argc != 4)
07081       return CLI_SHOWUSAGE;
07082 
07083    oldval =  pbx_set_extenpatternmatchnew(1);
07084 
07085    if (oldval)
07086       ast_cli(a->fd, "\n    -- Still using the NEW pattern match algorithm for extension names in the dialplan.\n");
07087    else
07088       ast_cli(a->fd, "\n    -- Switched to using the NEW pattern match algorithm for extension names in the dialplan.\n");
07089 
07090    return CLI_SUCCESS;
07091 }

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

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

07007 {
07008    switch (cmd) {
07009    case CLI_INIT:
07010       e->command = "dialplan set global";
07011       e->usage =
07012          "Usage: dialplan set global <name> <value>\n"
07013          "       Set global dialplan variable <name> to <value>\n";
07014       return NULL;
07015    case CLI_GENERATE:
07016       return NULL;
07017    }
07018 
07019    if (a->argc != e->args + 2)
07020       return CLI_SHOWUSAGE;
07021 
07022    pbx_builtin_setvar_helper(NULL, a->argv[3], a->argv[4]);
07023    ast_cli(a->fd, "\n    -- Global variable '%s' set to '%s'\n", a->argv[3], a->argv[4]);
07024 
07025    return CLI_SUCCESS;
07026 }

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

Definition at line 6020 of file pbx.c.

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

06021 {
06022    struct ast_app *aa;
06023    int app, no_registered_app = 1;
06024 
06025    switch (cmd) {
06026    case CLI_INIT:
06027       e->command = "core show application";
06028       e->usage =
06029          "Usage: core show application <application> [<application> [<application> [...]]]\n"
06030          "       Describes a particular application.\n";
06031       return NULL;
06032    case CLI_GENERATE:
06033       /*
06034        * There is a possibility to show informations about more than one
06035        * application at one time. You can type 'show application Dial Echo' and
06036        * you will see informations about these two applications ...
06037        */
06038       return ast_complete_applications(a->line, a->word, a->n);
06039    }
06040 
06041    if (a->argc < 4) {
06042       return CLI_SHOWUSAGE;
06043    }
06044 
06045    AST_RWLIST_RDLOCK(&apps);
06046    AST_RWLIST_TRAVERSE(&apps, aa, list) {
06047       /* Check for each app that was supplied as an argument */
06048       for (app = 3; app < a->argc; app++) {
06049          if (strcasecmp(aa->name, a->argv[app])) {
06050             continue;
06051          }
06052 
06053          /* We found it! */
06054          no_registered_app = 0;
06055 
06056          print_app_docs(aa, a->fd);
06057       }
06058    }
06059    AST_RWLIST_UNLOCK(&apps);
06060 
06061    /* we found at least one app? no? */
06062    if (no_registered_app) {
06063       ast_cli(a->fd, "Your application(s) is (are) not registered\n");
06064       return CLI_FAILURE;
06065    }
06066 
06067    return CLI_SUCCESS;
06068 }

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

Definition at line 6245 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_app::list, ast_cli_args::n, ast_app::name, ast_cli_args::pos, strcasestr(), ast_app::synopsis, ast_cli_entry::usage, and ast_cli_args::word.

06246 {
06247    struct ast_app *aa;
06248    int like = 0, describing = 0;
06249    int total_match = 0;    /* Number of matches in like clause */
06250    int total_apps = 0;     /* Number of apps registered */
06251    static const char * const choices[] = { "like", "describing", NULL };
06252 
06253    switch (cmd) {
06254    case CLI_INIT:
06255       e->command = "core show applications [like|describing]";
06256       e->usage =
06257          "Usage: core show applications [{like|describing} <text>]\n"
06258          "       List applications which are currently available.\n"
06259          "       If 'like', <text> will be a substring of the app name\n"
06260          "       If 'describing', <text> will be a substring of the description\n";
06261       return NULL;
06262    case CLI_GENERATE:
06263       return (a->pos != 3) ? NULL : ast_cli_complete(a->word, choices, a->n);
06264    }
06265 
06266    AST_RWLIST_RDLOCK(&apps);
06267 
06268    if (AST_RWLIST_EMPTY(&apps)) {
06269       ast_cli(a->fd, "There are no registered applications\n");
06270       AST_RWLIST_UNLOCK(&apps);
06271       return CLI_SUCCESS;
06272    }
06273 
06274    /* core list applications like <keyword> */
06275    if ((a->argc == 5) && (!strcmp(a->argv[3], "like"))) {
06276       like = 1;
06277    } else if ((a->argc > 4) && (!strcmp(a->argv[3], "describing"))) {
06278       describing = 1;
06279    }
06280 
06281    /* core list applications describing <keyword1> [<keyword2>] [...] */
06282    if ((!like) && (!describing)) {
06283       ast_cli(a->fd, "    -= Registered Asterisk Applications =-\n");
06284    } else {
06285       ast_cli(a->fd, "    -= Matching Asterisk Applications =-\n");
06286    }
06287 
06288    AST_RWLIST_TRAVERSE(&apps, aa, list) {
06289       int printapp = 0;
06290       total_apps++;
06291       if (like) {
06292          if (strcasestr(aa->name, a->argv[4])) {
06293             printapp = 1;
06294             total_match++;
06295          }
06296       } else if (describing) {
06297          if (aa->description) {
06298             /* Match all words on command line */
06299             int i;
06300             printapp = 1;
06301             for (i = 4; i < a->argc; i++) {
06302                if (!strcasestr(aa->description, a->argv[i])) {
06303                   printapp = 0;
06304                } else {
06305                   total_match++;
06306                }
06307             }
06308          }
06309       } else {
06310          printapp = 1;
06311       }
06312 
06313       if (printapp) {
06314          ast_cli(a->fd,"  %20s: %s\n", aa->name, aa->synopsis ? aa->synopsis : "<Synopsis not available>");
06315       }
06316    }
06317    if ((!like) && (!describing)) {
06318       ast_cli(a->fd, "    -= %d Applications Registered =-\n",total_apps);
06319    } else {
06320       ast_cli(a->fd, "    -= %d Applications Matching =-\n",total_match);
06321    }
06322 
06323    AST_RWLIST_UNLOCK(&apps);
06324 
06325    return CLI_SUCCESS;
06326 }

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

06972 {
06973    struct ast_channel *chan = NULL;
06974    struct ast_str *vars = ast_str_alloca(BUFSIZ * 4); /* XXX large because we might have lots of channel vars */
06975 
06976    switch (cmd) {
06977    case CLI_INIT:
06978       e->command = "dialplan show chanvar";
06979       e->usage =
06980          "Usage: dialplan show chanvar <channel>\n"
06981          "       List current channel variables and their values\n";
06982       return NULL;
06983    case CLI_GENERATE:
06984       return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
06985    }
06986 
06987    if (a->argc != e->args + 1)
06988       return CLI_SHOWUSAGE;
06989 
06990    if (!(chan = ast_channel_get_by_name(a->argv[e->args]))) {
06991       ast_cli(a->fd, "Channel '%s' not found\n", a->argv[e->args]);
06992       return CLI_FAILURE;
06993    }
06994 
06995    pbx_builtin_serialize_variables(chan, &vars);
06996 
06997    if (ast_str_strlen(vars)) {
06998       ast_cli(a->fd, "\nVariables for channel %s:\n%s\n", a->argv[e->args], ast_str_buffer(vars));
06999    }
07000 
07001    chan = ast_channel_unref(chan);
07002 
07003    return CLI_SUCCESS;
07004 }

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

Definition at line 6591 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(), exten, ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, ast_cli_args::pos, show_dialplan_helper(), strsep(), ast_cli_entry::usage, and ast_cli_args::word.

06592 {
06593    char *exten = NULL, *context = NULL;
06594    /* Variables used for different counters */
06595    struct dialplan_counters counters;
06596    const char *incstack[AST_PBX_MAX_STACK];
06597 
06598    switch (cmd) {
06599    case CLI_INIT:
06600       e->command = "dialplan show";
06601       e->usage =
06602          "Usage: dialplan show [[exten@]context]\n"
06603          "       Show dialplan\n";
06604       return NULL;
06605    case CLI_GENERATE:
06606       return complete_show_dialplan_context(a->line, a->word, a->pos, a->n);
06607    }
06608 
06609    memset(&counters, 0, sizeof(counters));
06610 
06611    if (a->argc != 2 && a->argc != 3)
06612       return CLI_SHOWUSAGE;
06613 
06614    /* we obtain [exten@]context? if yes, split them ... */
06615    if (a->argc == 3) {
06616       if (strchr(a->argv[2], '@')) {   /* split into exten & context */
06617          context = ast_strdupa(a->argv[2]);
06618          exten = strsep(&context, "@");
06619          /* change empty strings to NULL */
06620          if (ast_strlen_zero(exten))
06621             exten = NULL;
06622       } else { /* no '@' char, only context given */
06623          context = ast_strdupa(a->argv[2]);
06624       }
06625       if (ast_strlen_zero(context))
06626          context = NULL;
06627    }
06628    /* else Show complete dial plan, context and exten are NULL */
06629    show_dialplan_helper(a->fd, context, exten, &counters, NULL, 0, incstack);
06630 
06631    /* check for input failure and throw some error messages */
06632    if (context && !counters.context_existence) {
06633       ast_cli(a->fd, "There is no existence of '%s' context\n", context);
06634       return CLI_FAILURE;
06635    }
06636 
06637    if (exten && !counters.extension_existence) {
06638       if (context)
06639          ast_cli(a->fd, "There is no existence of %s@%s extension\n",
06640             exten, context);
06641       else
06642          ast_cli(a->fd,
06643             "There is no existence of '%s' extension in all contexts\n",
06644             exten);
06645       return CLI_FAILURE;
06646    }
06647 
06648    ast_cli(a->fd,"-= %d %s (%d %s) in %d %s. =-\n",
06649             counters.total_exten, counters.total_exten == 1 ? "extension" : "extensions",
06650             counters.total_prio, counters.total_prio == 1 ? "priority" : "priorities",
06651             counters.total_context, counters.total_context == 1 ? "context" : "contexts");
06652 
06653    /* everything ok */
06654    return CLI_SUCCESS;
06655 }

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

Definition at line 3395 of file pbx.c.

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

03396 {
03397    struct ast_custom_function *acf;
03398    /* Maximum number of characters added by terminal coloring is 22 */
03399    char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40], argtitle[40], seealsotitle[40];
03400    char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL, *seealso = NULL;
03401    char stxtitle[40], *syntax = NULL, *arguments = NULL;
03402    int syntax_size, description_size, synopsis_size, arguments_size, seealso_size;
03403    char *ret = NULL;
03404    int which = 0;
03405    int wordlen;
03406 
03407    switch (cmd) {
03408    case CLI_INIT:
03409       e->command = "core show function";
03410       e->usage =
03411          "Usage: core show function <function>\n"
03412          "       Describe a particular dialplan function.\n";
03413       return NULL;
03414    case CLI_GENERATE:
03415       wordlen = strlen(a->word);
03416       /* case-insensitive for convenience in this 'complete' function */
03417       AST_RWLIST_RDLOCK(&acf_root);
03418       AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) {
03419          if (!strncasecmp(a->word, acf->name, wordlen) && ++which > a->n) {
03420             ret = ast_strdup(acf->name);
03421             break;
03422          }
03423       }
03424       AST_RWLIST_UNLOCK(&acf_root);
03425 
03426       return ret;
03427    }
03428 
03429    if (a->argc < 4) {
03430       return CLI_SHOWUSAGE;
03431    }
03432 
03433    if (!(acf = ast_custom_function_find(a->argv[3]))) {
03434       ast_cli(a->fd, "No function by that name registered.\n");
03435       return CLI_FAILURE;
03436    }
03437 
03438    syntax_size = strlen(S_OR(acf->syntax, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
03439    if (!(syntax = ast_malloc(syntax_size))) {
03440       ast_cli(a->fd, "Memory allocation failure!\n");
03441       return CLI_FAILURE;
03442    }
03443 
03444    snprintf(info, sizeof(info), "\n  -= Info about function '%s' =- \n\n", acf->name);
03445    term_color(infotitle, info, COLOR_MAGENTA, 0, sizeof(infotitle));
03446    term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
03447    term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
03448    term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40);
03449    term_color(argtitle, "[Arguments]\n", COLOR_MAGENTA, 0, 40);
03450    term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, 40);
03451    term_color(syntax, S_OR(acf->syntax, "Not available"), COLOR_CYAN, 0, syntax_size);
03452 #ifdef AST_XML_DOCS
03453    if (acf->docsrc == AST_XML_DOC) {
03454       arguments = ast_xmldoc_printable(S_OR(acf->arguments, "Not available"), 1);
03455       synopsis = ast_xmldoc_printable(S_OR(acf->synopsis, "Not available"), 1);
03456       description = ast_xmldoc_printable(S_OR(acf->desc, "Not available"), 1);
03457       seealso = ast_xmldoc_printable(S_OR(acf->seealso, "Not available"), 1);
03458    } else
03459 #endif
03460    {
03461       synopsis_size = strlen(S_OR(acf->synopsis, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
03462       synopsis = ast_malloc(synopsis_size);
03463 
03464       description_size = strlen(S_OR(acf->desc, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
03465       description = ast_malloc(description_size);
03466 
03467       arguments_size = strlen(S_OR(acf->arguments, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
03468       arguments = ast_malloc(arguments_size);
03469 
03470       seealso_size = strlen(S_OR(acf->seealso, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
03471       seealso = ast_malloc(seealso_size);
03472 
03473       /* check allocated memory. */
03474       if (!synopsis || !description || !arguments || !seealso) {
03475          ast_free(synopsis);
03476          ast_free(description);
03477          ast_free(arguments);
03478          ast_free(seealso);
03479          ast_free(syntax);
03480          return CLI_FAILURE;
03481       }
03482 
03483       term_color(arguments, S_OR(acf->arguments, "Not available"), COLOR_CYAN, 0, arguments_size);
03484       term_color(synopsis, S_OR(acf->synopsis, "Not available"), COLOR_CYAN, 0, synopsis_size);
03485       term_color(description, S_OR(acf->desc, "Not available"), COLOR_CYAN, 0, description_size);
03486       term_color(seealso, S_OR(acf->seealso, "Not available"), COLOR_CYAN, 0, seealso_size);
03487    }
03488 
03489    ast_cli(a->fd, "%s%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n",
03490          infotitle, syntitle, synopsis, destitle, description,
03491          stxtitle, syntax, argtitle, arguments, seealsotitle, seealso);
03492 
03493    ast_free(arguments);
03494    ast_free(synopsis);
03495    ast_free(description);
03496    ast_free(seealso);
03497    ast_free(syntax);
03498 
03499    return CLI_SUCCESS;
03500 }

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

Definition at line 3353 of file pbx.c.

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

03354 {
03355    struct ast_custom_function *acf;
03356    int count_acf = 0;
03357    int like = 0;
03358 
03359    switch (cmd) {
03360    case CLI_INIT:
03361       e->command = "core show functions [like]";
03362       e->usage =
03363          "Usage: core show functions [like <text>]\n"
03364          "       List builtin functions, optionally only those matching a given string\n";
03365       return NULL;
03366    case CLI_GENERATE:
03367       return NULL;
03368    }
03369 
03370    if (a->argc == 5 && (!strcmp(a->argv[3], "like")) ) {
03371       like = 1;
03372    } else if (a->argc != 3) {
03373       return CLI_SHOWUSAGE;
03374    }
03375 
03376    ast_cli(a->fd, "%s Custom Functions:\n--------------------------------------------------------------------------------\n", like ? "Matching" : "Installed");
03377 
03378    AST_RWLIST_RDLOCK(&acf_root);
03379    AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) {
03380       if (!like || strstr(acf->name, a->argv[4])) {
03381          count_acf++;
03382          ast_cli(a->fd, "%-20.20s  %-35.35s  %s\n",
03383             S_OR(acf->name, ""),
03384             S_OR(acf->syntax, ""),
03385             S_OR(acf->synopsis, ""));
03386       }
03387    }
03388    AST_RWLIST_UNLOCK(&acf_root);
03389 
03390    ast_cli(a->fd, "%d %scustom functions installed.\n", count_acf, like ? "matching " : "");
03391 
03392    return CLI_SUCCESS;
03393 }

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

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

06914 {
06915    int i = 0;
06916    struct ast_var_t *newvariable;
06917 
06918    switch (cmd) {
06919    case CLI_INIT:
06920       e->command = "dialplan show globals";
06921       e->usage =
06922          "Usage: dialplan show globals\n"
06923          "       List current global dialplan variables and their values\n";
06924       return NULL;
06925    case CLI_GENERATE:
06926       return NULL;
06927    }
06928 
06929    ast_rwlock_rdlock(&globalslock);
06930    AST_LIST_TRAVERSE (&globals, newvariable, entries) {
06931       i++;
06932       ast_cli(a->fd, "   %s=%s\n", ast_var_name(newvariable), ast_var_value(newvariable));
06933    }
06934    ast_rwlock_unlock(&globalslock);
06935    ast_cli(a->fd, "\n    -- %d variable(s)\n", i);
06936 
06937    return CLI_SUCCESS;
06938 }

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

06158 {
06159    struct ast_hint *hint;
06160    int watchers;
06161    int num = 0, extenlen;
06162    struct ao2_iterator i;
06163 
06164    switch (cmd) {
06165    case CLI_INIT:
06166       e->command = "core show hint";
06167       e->usage =
06168          "Usage: core show hint <exten>\n"
06169          "       List registered hint\n";
06170       return NULL;
06171    case CLI_GENERATE:
06172       return complete_core_show_hint(a->line, a->word, a->pos, a->n);
06173    }
06174 
06175    if (a->argc < 4)
06176       return CLI_SHOWUSAGE;
06177 
06178    if (ao2_container_count(hints) == 0) {
06179       ast_cli(a->fd, "There are no registered dialplan hints\n");
06180       return CLI_SUCCESS;
06181    }
06182    
06183    extenlen = strlen(a->argv[3]);
06184    i = ao2_iterator_init(hints, 0);
06185    for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
06186       ao2_lock(hint);
06187       if (!hint->exten) {
06188          /* The extension has already been destroyed */
06189          ao2_unlock(hint);
06190          continue;
06191       }
06192       if (!strncasecmp(ast_get_extension_name(hint->exten), a->argv[3], extenlen)) {
06193          watchers = ao2_container_count(hint->callbacks);
06194          ast_cli(a->fd, "   %20s@%-20.20s: %-20.20s  State:%-15.15s Watchers %2d\n",
06195             ast_get_extension_name(hint->exten),
06196             ast_get_context_name(ast_get_extension_context(hint->exten)),
06197             ast_get_extension_app(hint->exten),
06198             ast_extension_state2str(hint->laststate), watchers);
06199          num++;
06200       }
06201       ao2_unlock(hint);
06202    }
06203    ao2_iterator_destroy(&i);
06204    if (!num)
06205       ast_cli(a->fd, "No hints matching extension %s\n", a->argv[3]);
06206    else
06207       ast_cli(a->fd, "%d hint%s matching extension %s\n", num, (num!=1 ? "s":""), a->argv[3]);
06208    return CLI_SUCCESS;
06209 }

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

06072 {
06073    struct ast_hint *hint;
06074    int num = 0;
06075    int watchers;
06076    struct ao2_iterator i;
06077 
06078    switch (cmd) {
06079    case CLI_INIT:
06080       e->command = "core show hints";
06081       e->usage =
06082          "Usage: core show hints\n"
06083          "       List registered hints\n";
06084       return NULL;
06085    case CLI_GENERATE:
06086       return NULL;
06087    }
06088 
06089    if (ao2_container_count(hints) == 0) {
06090       ast_cli(a->fd, "There are no registered dialplan hints\n");
06091       return CLI_SUCCESS;
06092    }
06093    /* ... we have hints ... */
06094    ast_cli(a->fd, "\n    -= Registered Asterisk Dial Plan Hints =-\n");
06095 
06096    i = ao2_iterator_init(hints, 0);
06097    for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
06098       ao2_lock(hint);
06099       if (!hint->exten) {
06100          /* The extension has already been destroyed */
06101          ao2_unlock(hint);
06102          continue;
06103       }
06104       watchers = ao2_container_count(hint->callbacks);
06105       ast_cli(a->fd, "   %20s@%-20.20s: %-20.20s  State:%-15.15s Watchers %2d\n",
06106          ast_get_extension_name(hint->exten),
06107          ast_get_context_name(ast_get_extension_context(hint->exten)),
06108          ast_get_extension_app(hint->exten),
06109          ast_extension_state2str(hint->laststate), watchers);
06110       ao2_unlock(hint);
06111       num++;
06112    }
06113    ao2_iterator_destroy(&i);
06114 
06115    ast_cli(a->fd, "----------------\n");
06116    ast_cli(a->fd, "- %d hints registered\n", num);
06117    return CLI_SUCCESS;
06118 }

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 6213 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::list, ast_switch::name, and ast_cli_entry::usage.

06214 {
06215    struct ast_switch *sw;
06216 
06217    switch (cmd) {
06218    case CLI_INIT:
06219       e->command = "core show switches";
06220       e->usage =
06221          "Usage: core show switches\n"
06222          "       List registered switches\n";
06223       return NULL;
06224    case CLI_GENERATE:
06225       return NULL;
06226    }
06227 
06228    AST_RWLIST_RDLOCK(&switches);
06229 
06230    if (AST_RWLIST_EMPTY(&switches)) {
06231       AST_RWLIST_UNLOCK(&switches);
06232       ast_cli(a->fd, "There are no registered alternative switches\n");
06233       return CLI_SUCCESS;
06234    }
06235 
06236    ast_cli(a->fd, "\n    -= Registered Asterisk Alternative Switches =-\n");
06237    AST_RWLIST_TRAVERSE(&switches, sw, list)
06238       ast_cli(a->fd, "%s: %s\n", sw->name, sw->description);
06239 
06240    AST_RWLIST_UNLOCK(&switches);
06241 
06242    return CLI_SUCCESS;
06243 }

static int handle_statechange ( void *  datap  )  [static]

Definition at line 4417 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, context_merge_lock, statechange::dev, ast_hint::exten, hints, ast_hint::laststate, parse(), statecbs, and strsep().

04418 {
04419    struct ast_hint *hint;
04420    struct ast_str *hint_app;
04421    struct statechange *sc = datap;
04422    struct ao2_iterator i;
04423    struct ao2_iterator cb_iter;
04424    char context_name[AST_MAX_CONTEXT];
04425    char exten_name[AST_MAX_EXTENSION];
04426 
04427    hint_app = ast_str_create(1024);
04428    if (!hint_app) {
04429       ast_free(sc);
04430       return -1;
04431    }
04432 
04433    ast_mutex_lock(&context_merge_lock);/* Hold off ast_merge_contexts_and_delete */
04434    i = ao2_iterator_init(hints, 0);
04435    for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
04436       struct ast_state_cb *state_cb;
04437       char *cur, *parse;
04438       int state;
04439 
04440       ao2_lock(hint);
04441       if (!hint->exten) {
04442          /* The extension has already been destroyed */
04443          ao2_unlock(hint);
04444          continue;
04445       }
04446 
04447       /* Does this hint monitor the device that changed state? */
04448       ast_str_set(&hint_app, 0, "%s", ast_get_extension_app(hint->exten));
04449       parse = ast_str_buffer(hint_app);
04450       while ((cur = strsep(&parse, "&"))) {
04451          if (!strcasecmp(cur, sc->dev)) {
04452             /* The hint monitors the device. */
04453             break;
04454          }
04455       }
04456       if (!cur) {
04457          /* The hint does not monitor the device. */
04458          ao2_unlock(hint);
04459          continue;
04460       }
04461 
04462       /*
04463        * Save off strings in case the hint extension gets destroyed
04464        * while we are notifying the watchers.
04465        */
04466       ast_copy_string(context_name,
04467          ast_get_context_name(ast_get_extension_context(hint->exten)),
04468          sizeof(context_name));
04469       ast_copy_string(exten_name, ast_get_extension_name(hint->exten),
04470          sizeof(exten_name));
04471       ast_str_set(&hint_app, 0, "%s", ast_get_extension_app(hint->exten));
04472       ao2_unlock(hint);
04473 
04474       /*
04475        * Get device state for this hint.
04476        *
04477        * NOTE: We cannot hold any locks while determining the hint
04478        * device state or notifying the watchers without causing a
04479        * deadlock.  (conlock, hints, and hint)
04480        */
04481       state = ast_extension_state3(hint_app);
04482       if (state == hint->laststate) {
04483          continue;
04484       }
04485 
04486       /* Device state changed since last check - notify the watchers. */
04487       hint->laststate = state;   /* record we saw the change */
04488 
04489       /* For general callbacks */
04490       cb_iter = ao2_iterator_init(statecbs, 0);
04491       for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) {
04492          state_cb->change_cb(context_name, exten_name, state, state_cb->data);
04493       }
04494       ao2_iterator_destroy(&cb_iter);
04495 
04496       /* For extension callbacks */
04497       cb_iter = ao2_iterator_init(hint->callbacks, 0);
04498       for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) {
04499          state_cb->change_cb(context_name, exten_name, state, state_cb->data);
04500       }
04501       ao2_iterator_destroy(&cb_iter);
04502    }
04503    ao2_iterator_destroy(&i);
04504    ast_mutex_unlock(&context_merge_lock);
04505 
04506    ast_free(hint_app);
04507    ast_free(sc);
04508    return 0;
04509 }

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

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

07094 {
07095    int oldval = 0;
07096 
07097    switch (cmd) {
07098    case CLI_INIT:
07099       e->command = "dialplan set extenpatternmatchnew false";
07100       e->usage =
07101          "Usage: dialplan set extenpatternmatchnew true|false\n"
07102          "       Use the NEW extension pattern matching algorithm, true or false.\n";
07103       return NULL;
07104    case CLI_GENERATE:
07105       return NULL;
07106    }
07107 
07108    if (a->argc != 4)
07109       return CLI_SHOWUSAGE;
07110 
07111    oldval =  pbx_set_extenpatternmatchnew(0);
07112 
07113    if (!oldval)
07114       ast_cli(a->fd, "\n    -- Still using the OLD pattern match algorithm for extension names in the dialplan.\n");
07115    else
07116       ast_cli(a->fd, "\n    -- Switched to using the OLD pattern match algorithm for extension names in the dialplan.\n");
07117 
07118    return CLI_SUCCESS;
07119 }

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

References CMP_MATCH, CMP_STOP, exten, and ast_hint::exten.

Referenced by ast_pbx_init().

10685 {
10686    const struct ast_hint *hint = obj;
10687    const struct ast_exten *exten = arg;
10688 
10689    return (hint->exten == exten) ? CMP_MATCH | CMP_STOP : 0;
10690 }

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

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

10665 {
10666    const struct ast_hint *hint = obj;
10667    const char *exten_name;
10668    int res;
10669 
10670    exten_name = ast_get_extension_name(hint->exten);
10671    if (ast_strlen_zero(exten_name)) {
10672       /*
10673        * If the exten or extension name isn't set, return 0 so that
10674        * the ao2_find() search will start in the first bucket.
10675        */
10676       res = 0;
10677    } else {
10678       res = ast_str_case_hash(exten_name);
10679    }
10680 
10681    return res;
10682 }

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

Definition at line 4672 of file pbx.c.

References CMP_MATCH, CMP_STOP, and ast_state_cb::id.

Referenced by ast_add_hint().

04673 {
04674    const struct ast_state_cb *cb = obj;
04675    int *id = arg;
04676 
04677    return (cb->id == *id) ? CMP_MATCH | CMP_STOP : 0;
04678 }

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

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

10266 {
10267    struct ast_data *data_hint;
10268    struct ast_hint *hint;
10269    int watchers;
10270    struct ao2_iterator i;
10271 
10272    if (ao2_container_count(hints) == 0) {
10273       return 0;
10274    }
10275 
10276    i = ao2_iterator_init(hints, 0);
10277    for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
10278       watchers = ao2_container_count(hint->callbacks);
10279       data_hint = ast_data_add_node(data_root, "hint");
10280       if (!data_hint) {
10281          continue;
10282       }
10283       ast_data_add_str(data_hint, "extension", ast_get_extension_name(hint->exten));
10284       ast_data_add_str(data_hint, "context", ast_get_context_name(ast_get_extension_context(hint->exten)));
10285       ast_data_add_str(data_hint, "application", ast_get_extension_app(hint->exten));
10286       ast_data_add_str(data_hint, "state", ast_extension_state2str(hint->laststate));
10287       ast_data_add_int(data_hint, "watchers", watchers);
10288 
10289       if (!ast_data_search_match(search, data_hint)) {
10290          ast_data_remove_node(data_root, data_hint);
10291       }
10292    }
10293    ao2_iterator_destroy(&i);
10294 
10295    return 0;
10296 }

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

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

Referenced by ast_pbx_run_args(), and ast_pbx_start().

05265 {
05266    int failed = 0;
05267    double curloadavg;
05268 #if defined(HAVE_SYSINFO)
05269    long curfreemem;
05270    struct sysinfo sys_info;
05271 #endif
05272 
05273    ast_mutex_lock(&maxcalllock);
05274    if (option_maxcalls) {
05275       if (countcalls >= option_maxcalls) {
05276          ast_log(LOG_WARNING, "Maximum call limit of %d calls exceeded by '%s'!\n", option_maxcalls, c->name);
05277          failed = -1;
05278       }
05279    }
05280    if (option_maxload) {
05281       getloadavg(&curloadavg, 1);
05282       if (curloadavg >= option_maxload) {
05283          ast_log(LOG_WARNING, "Maximum loadavg limit of %f load exceeded by '%s' (currently %f)!\n", option_maxload, c->name, curloadavg);
05284          failed = -1;
05285       }
05286    }
05287 #if defined(HAVE_SYSINFO)
05288    if (option_minmemfree) {
05289       if (!sysinfo(&sys_info)) {
05290          /* make sure that the free system memory is above the configured low watermark
05291           * convert the amount of freeram from mem_units to MB */
05292          curfreemem = sys_info.freeram * sys_info.mem_unit;
05293          curfreemem /= 1024 * 1024;
05294          if (curfreemem < option_minmemfree) {
05295             ast_log(LOG_WARNING, "Available system memory (~%ldMB) is below the configured low watermark (%ldMB)\n", curfreemem, option_minmemfree);
05296             failed = -1;
05297          }
05298       }
05299    }
05300 #endif
05301 
05302    if (!failed) {
05303       countcalls++;
05304       totalcalls++;
05305    }
05306    ast_mutex_unlock(&maxcalllock);
05307 
05308    return failed;
05309 }

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

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

Referenced by main().

10308 {
10309    int x;
10310 
10311    /* Initialize the PBX */
10312    ast_verb(1, "Asterisk PBX Core Initializing\n");
10313    if (!(device_state_tps = ast_taskprocessor_get("pbx-core", 0))) {
10314       ast_log(LOG_WARNING, "failed to create pbx-core taskprocessor\n");
10315    }
10316 
10317    ast_verb(1, "Registering builtin applications:\n");
10318    ast_cli_register_multiple(pbx_cli, ARRAY_LEN(pbx_cli));
10319    ast_data_register_multiple_core(pbx_data_providers, ARRAY_LEN(pbx_data_providers));
10320    __ast_custom_function_register(&exception_function, NULL);
10321    __ast_custom_function_register(&testtime_function, NULL);
10322 
10323    /* Register builtin applications */
10324    for (x = 0; x < ARRAY_LEN(builtins); x++) {
10325       ast_verb(1, "[%s]\n", builtins[x].name);
10326       if (ast_register_application2(builtins[x].name, builtins[x].execute, NULL, NULL, NULL)) {
10327          ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name);
10328          return -1;
10329       }
10330    }
10331 
10332    /* Register manager application */
10333    ast_manager_register_xml("ShowDialPlan", EVENT_FLAG_CONFIG | EVENT_FLAG_REPORTING, manager_show_dialplan);
10334 
10335    if (!(device_state_sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE, device_state_cb, "pbx Device State Change", NULL,
10336          AST_EVENT_IE_END))) {
10337       return -1;
10338    }
10339 
10340    return 0;
10341 }

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

Referenced by get_range().

07604 {
07605    int i;
07606 
07607    if (names && *s > '9') {
07608       for (i = 0; names[i]; i++) {
07609          if (!strcasecmp(s, names[i])) {
07610             return i;
07611          }
07612       }
07613    }
07614 
07615    /* Allow months and weekdays to be specified as numbers, as well */
07616    if (sscanf(s, "%2d", &i) == 1 && i >= 1 && i <= max) {
07617       /* What the array offset would have been: "1" would be at offset 0 */
07618       return i - 1;
07619    }
07620    return -1; /* error return */
07621 }

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

Send ack once.

Definition at line 6714 of file pbx.c.

References astman_send_listack().

Referenced by manager_show_dialplan_helper().

06715 {
06716    astman_send_listack(s, m, "DialPlan list will follow", "start");
06717 }

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

Manager listing of dial plan.

Definition at line 6860 of file pbx.c.

References ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), exten, and manager_show_dialplan_helper().

Referenced by load_pbx().

06861 {
06862    const char *exten, *context;
06863    const char *id = astman_get_header(m, "ActionID");
06864    char idtext[256];
06865 
06866    /* Variables used for different counters */
06867    struct dialplan_counters counters;
06868 
06869    if (!ast_strlen_zero(id))
06870       snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id);
06871    else
06872       idtext[0] = '\0';
06873 
06874    memset(&counters, 0, sizeof(counters));
06875 
06876    exten = astman_get_header(m, "Extension");
06877    context = astman_get_header(m, "Context");
06878 
06879    manager_show_dialplan_helper(s, m, idtext, context, exten, &counters, NULL);
06880 
06881    if (context && !counters.context_existence) {
06882       char errorbuf[BUFSIZ];
06883 
06884       snprintf(errorbuf, sizeof(errorbuf), "Did not find context %s", context);
06885       astman_send_error(s, m, errorbuf);
06886       return 0;
06887    }
06888    if (exten && !counters.extension_existence) {
06889       char errorbuf[BUFSIZ];
06890 
06891       if (context)
06892          snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s@%s", exten, context);
06893       else
06894          snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s in any context", exten);
06895       astman_send_error(s, m, errorbuf);
06896       return 0;
06897    }
06898 
06899    astman_append(s, "Event: ShowDialPlanComplete\r\n"
06900       "EventList: Complete\r\n"
06901       "ListItems: %d\r\n"
06902       "ListExtensions: %d\r\n"
06903       "ListPriorities: %d\r\n"
06904       "ListContexts: %d\r\n"
06905       "%s"
06906       "\r\n", counters.total_items, counters.total_exten, counters.total_prio, counters.total_context, idtext);
06907 
06908    /* everything ok */
06909    return 0;
06910 }

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

06727 {
06728    struct ast_context *c;
06729    int res = 0, old_total_exten = dpc->total_exten;
06730 
06731    if (ast_strlen_zero(exten))
06732       exten = NULL;
06733    if (ast_strlen_zero(context))
06734       context = NULL;
06735 
06736    ast_debug(3, "manager_show_dialplan: Context: -%s- Extension: -%s-\n", context, exten);
06737 
06738    /* try to lock contexts */
06739    if (ast_rdlock_contexts()) {
06740       astman_send_error(s, m, "Failed to lock contexts");
06741       ast_log(LOG_WARNING, "Failed to lock contexts list for manager: listdialplan\n");
06742       return -1;
06743    }
06744 
06745    c = NULL;      /* walk all contexts ... */
06746    while ( (c = ast_walk_contexts(c)) ) {
06747       struct ast_exten *e;
06748       struct ast_include *i;
06749       struct ast_ignorepat *ip;
06750 
06751       if (context && strcmp(ast_get_context_name(c), context) != 0)
06752          continue;   /* not the name we want */
06753 
06754       dpc->context_existence = 1;
06755 
06756       ast_debug(3, "manager_show_dialplan: Found Context: %s \n", ast_get_context_name(c));
06757 
06758       if (ast_rdlock_context(c)) {  /* failed to lock */
06759          ast_debug(3, "manager_show_dialplan: Failed to lock context\n");
06760          continue;
06761       }
06762 
06763       /* XXX note- an empty context is not printed */
06764       e = NULL;      /* walk extensions in context  */
06765       while ( (e = ast_walk_context_extensions(c, e)) ) {
06766          struct ast_exten *p;
06767 
06768          /* looking for extension? is this our extension? */
06769          if (exten && !ast_extension_match(ast_get_extension_name(e), exten)) {
06770             /* not the one we are looking for, continue */
06771             ast_debug(3, "manager_show_dialplan: Skipping extension %s\n", ast_get_extension_name(e));
06772             continue;
06773          }
06774          ast_debug(3, "manager_show_dialplan: Found Extension: %s \n", ast_get_extension_name(e));
06775 
06776          dpc->extension_existence = 1;
06777 
06778          /* may we print context info? */
06779          dpc->total_context++;
06780          dpc->total_exten++;
06781 
06782          p = NULL;      /* walk next extension peers */
06783          while ( (p = ast_walk_extension_priorities(e, p)) ) {
06784             int prio = ast_get_extension_priority(p);
06785 
06786             dpc->total_prio++;
06787             if (!dpc->total_items++)
06788                manager_dpsendack(s, m);
06789             astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
06790             astman_append(s, "Context: %s\r\nExtension: %s\r\n", ast_get_context_name(c), ast_get_extension_name(e) );
06791 
06792             /* XXX maybe make this conditional, if p != e ? */
06793             if (ast_get_extension_label(p))
06794                astman_append(s, "ExtensionLabel: %s\r\n", ast_get_extension_label(p));
06795 
06796             if (prio == PRIORITY_HINT) {
06797                astman_append(s, "Priority: hint\r\nApplication: %s\r\n", ast_get_extension_app(p));
06798             } else {
06799                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));
06800             }
06801             astman_append(s, "Registrar: %s\r\n\r\n", ast_get_extension_registrar(e));
06802          }
06803       }
06804 
06805       i = NULL;      /* walk included and write info ... */
06806       while ( (i = ast_walk_context_includes(c, i)) ) {
06807          if (exten) {
06808             /* Check all includes for the requested extension */
06809             manager_show_dialplan_helper(s, m, actionidtext, ast_get_include_name(i), exten, dpc, i);
06810          } else {
06811             if (!dpc->total_items++)
06812                manager_dpsendack(s, m);
06813             astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
06814             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));
06815             astman_append(s, "\r\n");
06816             ast_debug(3, "manager_show_dialplan: Found Included context: %s \n", ast_get_include_name(i));
06817          }
06818       }
06819 
06820       ip = NULL;  /* walk ignore patterns and write info ... */
06821       while ( (ip = ast_walk_context_ignorepats(c, ip)) ) {
06822          const char *ipname = ast_get_ignorepat_name(ip);
06823          char ignorepat[AST_MAX_EXTENSION];
06824 
06825          snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname);
06826          if (!exten || ast_extension_match(ignorepat, exten)) {
06827             if (!dpc->total_items++)
06828                manager_dpsendack(s, m);
06829             astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
06830             astman_append(s, "Context: %s\r\nIgnorePattern: %s\r\nRegistrar: %s\r\n", ast_get_context_name(c), ipname, ast_get_ignorepat_registrar(ip));
06831             astman_append(s, "\r\n");
06832          }
06833       }
06834       if (!rinclude) {
06835          struct ast_sw *sw = NULL;
06836          while ( (sw = ast_walk_context_switches(c, sw)) ) {
06837             if (!dpc->total_items++)
06838                manager_dpsendack(s, m);
06839             astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
06840             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));  
06841             astman_append(s, "\r\n");
06842             ast_debug(3, "manager_show_dialplan: Found Switch : %s \n", ast_get_switch_name(sw));
06843          }
06844       }
06845 
06846       ast_unlock_context(c);
06847    }
06848    ast_unlock_contexts();
06849 
06850    if (dpc->total_exten == old_total_exten) {
06851       ast_debug(3, "manager_show_dialplan: Found nothing new\n");
06852       /* Nothing new under the sun */
06853       return -1;
06854    } else {
06855       return res;
06856    }
06857 }

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

Definition at line 2703 of file pbx.c.

References ast_extension_match(), and ast_strlen_zero().

Referenced by pbx_find_extension().

02704 {
02705    /* If the Caller*ID pattern is empty, then we're matching NO Caller*ID, so
02706       failing to get a number should count as a match, otherwise not */
02707 
02708    if (ast_strlen_zero(callerid)) {
02709       return ast_strlen_zero(cidpattern) ? 1 : 0;
02710    }
02711 
02712    return ast_extension_match(cidpattern, callerid);
02713 }

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_hashtab_lookup(), ast_log(), match_char::deleted, E_FINDLABEL, E_MATCH, E_SPAWN, ast_exten::exten, match_char::exten, match_char::is_pattern, ast_exten::label, LOG_NOTICE, NEW_MATCHER_CHK_MATCH, 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 3013 of file pbx.c.

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

03014 {
03015    int parens = 0;
03016 
03017    *offset = 0;
03018    *length = INT_MAX;
03019    *isfunc = 0;
03020    for (; *var; var++) {
03021       if (*var == '(') {
03022          (*isfunc)++;
03023          parens++;
03024       } else if (*var == ')') {
03025          parens--;
03026       } else if (*var == ':' && parens == 0) {
03027          *var++ = '\0';
03028          sscanf(var, "%30d:%30d", offset, length);
03029          return 1; /* offset:length valid */
03030       }
03031    }
03032    return 0;
03033 }

void pbx_builtin_clear_globals ( void   ) 

Definition at line 10140 of file pbx.c.

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

Referenced by handle_cli_dialplan_reload(), and reload().

10141 {
10142    struct ast_var_t *vardata;
10143 
10144    ast_rwlock_wrlock(&globalslock);
10145    while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries)))
10146       ast_var_delete(vardata);
10147    ast_rwlock_unlock(&globalslock);
10148 }

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 9902 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, and globalslock.

Referenced by _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(), dahdi_r2_answer(), dahdi_r2_get_channel_category(), dial_exec_full(), do_forward(), dundi_exec(), dundi_helper(), feature_check(), feature_interpret(), find_by_mark(), 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(), 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(), sig_pri_call(), sig_pri_hangup(), sip_addheader(), sla_trunk_exec(), speech_background(), try_suggested_sip_codec(), and update_bridge_vars().

09903 {
09904    struct ast_var_t *variables;
09905    const char *ret = NULL;
09906    int i;
09907    struct varshead *places[2] = { NULL, &globals };
09908 
09909    if (!name)
09910       return NULL;
09911 
09912    if (chan) {
09913       ast_channel_lock(chan);
09914       places[0] = &chan->varshead;
09915    }
09916 
09917    for (i = 0; i < 2; i++) {
09918       if (!places[i])
09919          continue;
09920       if (places[i] == &globals)
09921          ast_rwlock_rdlock(&globalslock);
09922       AST_LIST_TRAVERSE(places[i], variables, entries) {
09923          if (!strcmp(name, ast_var_name(variables))) {
09924             ret = ast_var_value(variables);
09925             break;
09926          }
09927       }
09928       if (places[i] == &globals)
09929          ast_rwlock_unlock(&globalslock);
09930       if (ret)
09931          break;
09932    }
09933 
09934    if (chan)
09935       ast_channel_unlock(chan);
09936 
09937    return ret;
09938 }

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

Definition at line 10162 of file pbx.c.

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

10163 {
10164    char *condition, *branch1, *branch2, *branch;
10165    char *stringp;
10166 
10167    if (ast_strlen_zero(data)) {
10168       ast_log(LOG_WARNING, "Ignoring, since there is no variable to check\n");
10169       return 0;
10170    }
10171 
10172    stringp = ast_strdupa(data);
10173    condition = strsep(&stringp,"?");
10174    branch1 = strsep(&stringp,":");
10175    branch2 = strsep(&stringp,"");
10176    branch = pbx_checkcondition(condition) ? branch1 : branch2;
10177 
10178    if (ast_strlen_zero(branch)) {
10179       ast_debug(1, "Not taking any branch\n");
10180       return 0;
10181    }
10182 
10183    return pbx_builtin_goto(chan, branch);
10184 }

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

Definition at line 10098 of file pbx.c.

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

10099 {
10100    char *name;
10101    char *value;
10102    char *channel;
10103    char tmp[VAR_BUF_SIZE];
10104    static int deprecation_warning = 0;
10105 
10106    if (ast_strlen_zero(data)) {
10107       ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n");
10108       return 0;
10109    }
10110    tmp[0] = 0;
10111    if (!deprecation_warning) {
10112       ast_log(LOG_WARNING, "ImportVar is deprecated.  Please use Set(varname=${IMPORT(channel,variable)}) instead.\n");
10113       deprecation_warning = 1;
10114    }
10115 
10116    value = ast_strdupa(data);
10117    name = strsep(&value,"=");
10118    channel = strsep(&value,",");
10119    if (channel && value && name) { /*! \todo XXX should do !ast_strlen_zero(..) of the args ? */
10120       struct ast_channel *chan2 = ast_channel_get_by_name(channel);
10121       if (chan2) {
10122          char *s = alloca(strlen(value) + 4);
10123          if (s) {
10124             sprintf(s, "${%s}", value);
10125             pbx_substitute_variables_helper(chan2, s, tmp, sizeof(tmp) - 1);
10126          }
10127          chan2 = ast_channel_unref(chan2);
10128       }
10129       pbx_builtin_setvar_helper(chan, name, tmp);
10130    }
10131 
10132    return(0);
10133 }

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

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

09424 {
09425    const char *options = data;
09426    int answer = 1;
09427 
09428    /* Some channels can receive DTMF in unanswered state; some cannot */
09429    if (!ast_strlen_zero(options) && strchr(options, 'n')) {
09430       answer = 0;
09431    }
09432 
09433    /* If the channel is hungup, stop waiting */
09434    if (ast_check_hangup(chan)) {
09435       return -1;
09436    } else if (chan->_state != AST_STATE_UP && answer) {
09437       __ast_answer(chan, 0, 1);
09438    }
09439 
09440    ast_indicate(chan, AST_CONTROL_INCOMPLETE);
09441 
09442    return AST_PBX_INCOMPLETE;
09443 }

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

Definition at line 10135 of file pbx.c.

10136 {
10137    return 0;
10138 }

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 9940 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, and LOG_WARNING.

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

09941 {
09942    struct ast_var_t *newvariable;
09943    struct varshead *headp;
09944 
09945    if (name[strlen(name)-1] == ')') {
09946       char *function = ast_strdupa(name);
09947 
09948       ast_log(LOG_WARNING, "Cannot push a value onto a function\n");
09949       ast_func_write(chan, function, value);
09950       return;
09951    }
09952 
09953    if (chan) {
09954       ast_channel_lock(chan);
09955       headp = &chan->varshead;
09956    } else {
09957       ast_rwlock_wrlock(&globalslock);
09958       headp = &globals;
09959    }
09960 
09961    if (value) {
09962       if (headp == &globals)
09963          ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value);
09964       newvariable = ast_var_assign(name, value);
09965       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
09966    }
09967 
09968    if (chan)
09969       ast_channel_unlock(chan);
09970    else
09971       ast_rwlock_unlock(&globalslock);
09972 }

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

Definition at line 3322 of file pbx.c.

References raise_exception().

03323 {
03324    /* Priority will become 1, next time through the AUTOLOOP */
03325    return raise_exception(chan, reason, 0);
03326 }

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

Definition at line 10223 of file pbx.c.

References ast_say_character_str(), and ast_channel::language.

10224 {
10225    int res = 0;
10226 
10227    if (data)
10228       res = ast_say_character_str(chan, data, "", chan->language);
10229    return res;
10230 }

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

Definition at line 10214 of file pbx.c.

References ast_say_digit_str(), and ast_channel::language.

10215 {
10216    int res = 0;
10217 
10218    if (data)
10219       res = ast_say_digit_str(chan, data, "", chan->language);
10220    return res;
10221 }

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

Definition at line 10186 of file pbx.c.

References ast_copy_string(), ast_log(), ast_say_number(), ast_strlen_zero(), ast_channel::language, LOG_WARNING, and strsep().

10187 {
10188    char tmp[256];
10189    char *number = tmp;
10190    char *options;
10191 
10192    if (ast_strlen_zero(data)) {
10193       ast_log(LOG_WARNING, "SayNumber requires an argument (number)\n");
10194       return -1;
10195    }
10196    ast_copy_string(tmp, data, sizeof(tmp));
10197    strsep(&number, ",");
10198    options = strsep(&number, ",");
10199    if (options) {
10200       if ( strcasecmp(options, "f") && strcasecmp(options, "m") &&
10201          strcasecmp(options, "c") && strcasecmp(options, "n") ) {
10202          ast_log(LOG_WARNING, "SayNumber gender option is either 'f', 'm', 'c' or 'n'\n");
10203          return -1;
10204       }
10205    }
10206 
10207    if (ast_say_number(chan, atoi(tmp), "", chan->language, options)) {
10208       ast_log(LOG_WARNING, "We were unable to say the number %s, is it too large?\n", tmp);
10209    }
10210 
10211    return 0;
10212 }

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

Definition at line 10232 of file pbx.c.

References ast_say_phonetic_str(), and ast_channel::language.

10233 {
10234    int res = 0;
10235 
10236    if (data)
10237       res = ast_say_phonetic_str(chan, data, "", chan->language);
10238    return res;
10239 }

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

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

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

09872 {
09873    struct ast_var_t *variables;
09874    const char *var, *val;
09875    int total = 0;
09876 
09877    if (!chan)
09878       return 0;
09879 
09880    ast_str_reset(*buf);
09881 
09882    ast_channel_lock(chan);
09883 
09884    AST_LIST_TRAVERSE(&chan->varshead, variables, entries) {
09885       if ((var = ast_var_name(variables)) && (val = ast_var_value(variables))
09886          /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */
09887          ) {
09888          if (ast_str_append(buf, 0, "%s=%s\n", var, val) < 0) {
09889             ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
09890             break;
09891          } else
09892             total++;
09893       } else
09894          break;
09895    }
09896 
09897    ast_channel_unlock(chan);
09898 
09899    return total;
09900 }

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

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

Referenced by ast_compile_ael2().

10033 {
10034    char *name, *value, *mydata;
10035 
10036    if (ast_compat_app_set) {
10037       return pbx_builtin_setvar_multiple(chan, data);
10038    }
10039 
10040    if (ast_strlen_zero(data)) {
10041       ast_log(LOG_WARNING, "Set requires one variable name/value pair.\n");
10042       return 0;
10043    }
10044 
10045    mydata = ast_strdupa(data);
10046    name = strsep(&mydata, "=");
10047    value = mydata;
10048    if (!value) {
10049       ast_log(LOG_WARNING, "Set requires an '=' to be a valid assignment.\n");
10050       return 0;
10051    }
10052 
10053    if (strchr(name, ' ')) {
10054       ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, mydata);
10055    }
10056 
10057    pbx_builtin_setvar_helper(chan, name, value);
10058 
10059    return 0;
10060 }

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 9974 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, ast_channel::name, and ast_channel::uniqueid.

Referenced by __analog_ss_thread(), __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(), 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(), process_ast_dsp(), process_sdp(), read_exec(), readexten_exec(), readfile_exec(), 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(), sig_pri_new_ast_channel(), 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().

09975 {
09976    struct ast_var_t *newvariable;
09977    struct varshead *headp;
09978    const char *nametail = name;
09979 
09980    if (name[strlen(name) - 1] == ')') {
09981       char *function = ast_strdupa(name);
09982 
09983       return ast_func_write(chan, function, value);
09984    }
09985 
09986    if (chan) {
09987       ast_channel_lock(chan);
09988       headp = &chan->varshead;
09989    } else {
09990       ast_rwlock_wrlock(&globalslock);
09991       headp = &globals;
09992    }
09993 
09994    /* For comparison purposes, we have to strip leading underscores */
09995    if (*nametail == '_') {
09996       nametail++;
09997       if (*nametail == '_')
09998          nametail++;
09999    }
10000 
10001    AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) {
10002       if (strcmp(ast_var_name(newvariable), nametail) == 0) {
10003          /* there is already such a variable, delete it */
10004          AST_LIST_REMOVE_CURRENT(entries);
10005          ast_var_delete(newvariable);
10006          break;
10007       }
10008    }
10009    AST_LIST_TRAVERSE_SAFE_END;
10010 
10011    if (value) {
10012       if (headp == &globals)
10013          ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value);
10014       newvariable = ast_var_assign(name, value);
10015       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
10016       manager_event(EVENT_FLAG_DIALPLAN, "VarSet",
10017          "Channel: %s\r\n"
10018          "Variable: %s\r\n"
10019          "Value: %s\r\n"
10020          "Uniqueid: %s\r\n",
10021          chan ? chan->name : "none", name, value,
10022          chan ? chan->uniqueid : "none");
10023    }
10024 
10025    if (chan)
10026       ast_channel_unlock(chan);
10027    else
10028       ast_rwlock_unlock(&globalslock);
10029    return 0;
10030 }

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 10062 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, ast_channel::name, pbx_builtin_setvar_helper(), ast_channel::priority, and value.

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

10063 {
10064    char *data;
10065    int x;
10066    AST_DECLARE_APP_ARGS(args,
10067       AST_APP_ARG(pair)[24];
10068    );
10069    AST_DECLARE_APP_ARGS(pair,
10070       AST_APP_ARG(name);
10071       AST_APP_ARG(value);
10072    );
10073 
10074    if (ast_strlen_zero(vdata)) {
10075       ast_log(LOG_WARNING, "MSet requires at least one variable name/value pair.\n");
10076       return 0;
10077    }
10078 
10079    data = ast_strdupa(vdata);
10080    AST_STANDARD_APP_ARGS(args, data);
10081 
10082    for (x = 0; x < args.argc; x++) {
10083       AST_NONSTANDARD_APP_ARGS(pair, args.pair[x], '=');
10084       if (pair.argc == 2) {
10085          pbx_builtin_setvar_helper(chan, pair.name, pair.value);
10086          if (strchr(pair.name, ' '))
10087             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);
10088       } else if (!chan) {
10089          ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '='\n", pair.name);
10090       } else {
10091          ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '=' (in %s@%s:%d\n", pair.name, chan->exten, chan->context, chan->priority);
10092       }
10093    }
10094 
10095    return 0;
10096 }

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

10151 {
10152    int res;
10153    if (ast_strlen_zero(condition)) {                /* NULL or empty strings are false */
10154       return 0;
10155    } else if (sscanf(condition, "%30d", &res) == 1) { /* Numbers are evaluated for truth */
10156       return res;
10157    } else {                                         /* Strings are true */
10158       return 1;
10159    }
10160 }

static void pbx_destroy ( struct ast_pbx p  )  [static]

Definition at line 1498 of file pbx.c.

References ast_free.

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(), app, 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, LOG_WARNING, 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(), pbx_builtin_execiftime(), pbx_extension_helper(), 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 4202 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_channel::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(), ast_channel::uniqueid, and VERBOSITY_ATLEAST.

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

04205 {
04206    struct ast_exten *e;
04207    struct ast_app *app;
04208    int res;
04209    struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */
04210    char passdata[EXT_DATA_SIZE];
04211 
04212    int matching_action = (action == E_MATCH || action == E_CANMATCH || action == E_MATCHMORE);
04213 
04214    ast_rdlock_contexts();
04215    if (found)
04216       *found = 0;
04217 
04218    e = pbx_find_extension(c, con, &q, context, exten, priority, label, callerid, action);
04219    if (e) {
04220       if (found)
04221          *found = 1;
04222       if (matching_action) {
04223          ast_unlock_contexts();
04224          return -1;  /* success, we found it */
04225       } else if (action == E_FINDLABEL) { /* map the label to a priority */
04226          res = e->priority;
04227          ast_unlock_contexts();
04228          return res; /* the priority we were looking for */
04229       } else { /* spawn */
04230          if (!e->cached_app)
04231             e->cached_app = pbx_findapp(e->app);
04232          app = e->cached_app;
04233          ast_unlock_contexts();
04234          if (!app) {
04235             ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority);
04236             return -1;
04237          }
04238          if (c->context != context)
04239             ast_copy_string(c->context, context, sizeof(c->context));
04240          if (c->exten != exten)
04241             ast_copy_string(c->exten, exten, sizeof(c->exten));
04242          c->priority = priority;
04243          pbx_substitute_variables(passdata, sizeof(passdata), c, e);
04244 #ifdef CHANNEL_TRACE
04245          ast_channel_trace_update(c);
04246 #endif
04247          ast_debug(1, "Launching '%s'\n", app->name);
04248          if (VERBOSITY_ATLEAST(3)) {
04249             char tmp[80], tmp2[80], tmp3[EXT_DATA_SIZE];
04250             ast_verb(3, "Executing [%s@%s:%d] %s(\"%s\", \"%s\") %s\n",
04251                exten, context, priority,
04252                term_color(tmp, app->name, COLOR_BRCYAN, 0, sizeof(tmp)),
04253                term_color(tmp2, c->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)),
04254                term_color(tmp3, passdata, COLOR_BRMAGENTA, 0, sizeof(tmp3)),
04255                "in new stack");
04256          }
04257          manager_event(EVENT_FLAG_DIALPLAN, "Newexten",
04258                "Channel: %s\r\n"
04259                "Context: %s\r\n"
04260                "Extension: %s\r\n"
04261                "Priority: %d\r\n"
04262                "Application: %s\r\n"
04263                "AppData: %s\r\n"
04264                "Uniqueid: %s\r\n",
04265                c->name, c->context, c->exten, c->priority, app->name, passdata, c->uniqueid);
04266          return pbx_exec(c, app, passdata);  /* 0 on success, -1 on failure */
04267       }
04268    } else if (q.swo) {  /* not found here, but in another switch */
04269       if (found)
04270          *found = 1;
04271       ast_unlock_contexts();
04272       if (matching_action) {
04273          return -1;
04274       } else {
04275          if (!q.swo->exec) {
04276             ast_log(LOG_WARNING, "No execution engine for switch %s\n", q.swo->name);
04277             res = -1;
04278          }
04279          return q.swo->exec(c, q.foundcontext ? q.foundcontext : context, exten, priority, callerid, q.data);
04280       }
04281    } else { /* not found anywhere, see what happened */
04282       ast_unlock_contexts();
04283       /* Using S_OR here because Solaris doesn't like NULL being passed to ast_log */
04284       switch (q.status) {
04285       case STATUS_NO_CONTEXT:
04286          if (!matching_action && !combined_find_spawn)
04287             ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", S_OR(context, ""));
04288          break;
04289       case STATUS_NO_EXTENSION:
04290          if (!matching_action && !combined_find_spawn)
04291             ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, S_OR(context, ""));
04292          break;
04293       case STATUS_NO_PRIORITY:
04294          if (!matching_action && !combined_find_spawn)
04295             ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, S_OR(context, ""));
04296          break;
04297       case STATUS_NO_LABEL:
04298          if (context && !combined_find_spawn)
04299             ast_log(LOG_NOTICE, "No such label '%s' in extension '%s' in context '%s'\n", label, exten, S_OR(context, ""));
04300          break;
04301       default:
04302          ast_debug(1, "Shouldn't happen!\n");
04303       }
04304 
04305       return (matching_action) ? 0 : -1;
04306    }
04307 }

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 
)

Definition at line 2715 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, strsep(), switch_data, pbx_find_info::swo, scoreboard::total_length, scoreboard::total_specificity, and trie_find_next_match().

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

02719 {
02720    int x, res;
02721    struct ast_context *tmp = NULL;
02722    struct ast_exten *e = NULL, *eroot = NULL;
02723    struct ast_include *i = NULL;
02724    struct ast_sw *sw = NULL;
02725    struct ast_exten pattern = {NULL, };
02726    struct scoreboard score = {0, };
02727    struct ast_str *tmpdata = NULL;
02728 
02729    pattern.label = label;
02730    pattern.priority = priority;
02731 #ifdef NEED_DEBUG_HERE
02732    ast_log(LOG_NOTICE, "Looking for cont/ext/prio/label/action = %s/%s/%d/%s/%d\n", context, exten, priority, label, (int) action);
02733 #endif
02734 
02735    /* Initialize status if appropriate */
02736    if (q->stacklen == 0) {
02737       q->status = STATUS_NO_CONTEXT;
02738       q->swo = NULL;
02739       q->data = NULL;
02740       q->foundcontext = NULL;
02741    } else if (q->stacklen >= AST_PBX_MAX_STACK) {
02742       ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n");
02743       return NULL;
02744    }
02745 
02746    /* Check first to see if we've already been checked */
02747    for (x = 0; x < q->stacklen; x++) {
02748       if (!strcasecmp(q->incstack[x], context))
02749          return NULL;
02750    }
02751 
02752    if (bypass) { /* bypass means we only look there */
02753       tmp = bypass;
02754    } else {      /* look in contexts */
02755       tmp = find_context(context);
02756       if (!tmp) {
02757          return NULL;
02758       }
02759    }
02760 
02761    if (q->status < STATUS_NO_EXTENSION)
02762       q->status = STATUS_NO_EXTENSION;
02763 
02764    /* Do a search for matching extension */
02765 
02766    eroot = NULL;
02767    score.total_specificity = 0;
02768    score.exten = 0;
02769    score.total_length = 0;
02770    if (!tmp->pattern_tree && tmp->root_table) {
02771       create_match_char_tree(tmp);
02772 #ifdef NEED_DEBUG
02773       ast_log(LOG_DEBUG, "Tree Created in context %s:\n", context);
02774       log_match_char_tree(tmp->pattern_tree," ");
02775 #endif
02776    }
02777 #ifdef NEED_DEBUG
02778    ast_log(LOG_NOTICE, "The Trie we are searching in:\n");
02779    log_match_char_tree(tmp->pattern_tree, "::  ");
02780 #endif
02781 
02782    do {
02783       if (!ast_strlen_zero(overrideswitch)) {
02784          char *osw = ast_strdupa(overrideswitch), *name;
02785          struct ast_switch *asw;
02786          ast_switch_f *aswf = NULL;
02787          char *datap;
02788          int eval = 0;
02789 
02790          name = strsep(&osw, "/");
02791          asw = pbx_findswitch(name);
02792 
02793          if (!asw) {
02794             ast_log(LOG_WARNING, "No such switch '%s'\n", name);
02795             break;
02796          }
02797 
02798          if (osw && strchr(osw, '$')) {
02799             eval = 1;
02800          }
02801 
02802          if (eval && !(tmpdata = ast_str_thread_get(&switch_data, 512))) {
02803             ast_log(LOG_WARNING, "Can't evaluate overrideswitch?!\n");
02804             break;
02805          } else if (eval) {
02806             /* Substitute variables now */
02807             pbx_substitute_variables_helper(chan, osw, ast_str_buffer(tmpdata), ast_str_size(tmpdata));
02808             datap = ast_str_buffer(tmpdata);
02809          } else {
02810             datap = osw;
02811          }
02812 
02813          /* equivalent of extension_match_core() at the switch level */
02814          if (action == E_CANMATCH)
02815             aswf = asw->canmatch;
02816          else if (action == E_MATCHMORE)
02817             aswf = asw->matchmore;
02818          else /* action == E_MATCH */
02819             aswf = asw->exists;
02820          if (!aswf) {
02821             res = 0;
02822          } else {
02823             if (chan) {
02824                ast_autoservice_start(chan);
02825             }
02826             res = aswf(chan, context, exten, priority, callerid, datap);
02827             if (chan) {
02828                ast_autoservice_stop(chan);
02829             }
02830          }
02831          if (res) {  /* Got a match */
02832             q->swo = asw;
02833             q->data = datap;
02834             q->foundcontext = context;
02835             /* XXX keep status = STATUS_NO_CONTEXT ? */
02836             return NULL;
02837          }
02838       }
02839    } while (0);
02840 
02841    if (extenpatternmatchnew) {
02842       new_find_extension(exten, &score, tmp->pattern_tree, 0, 0, callerid, label, action);
02843       eroot = score.exten;
02844 
02845       if (score.last_char == '!' && action == E_MATCHMORE) {
02846          /* We match an extension ending in '!'.
02847           * The decision in this case is final and is NULL (no match).
02848           */
02849 #ifdef NEED_DEBUG_HERE
02850          ast_log(LOG_NOTICE,"Returning MATCHMORE NULL with exclamation point.\n");
02851 #endif
02852          return NULL;
02853       }
02854 
02855       if (!eroot && (action == E_CANMATCH || action == E_MATCHMORE) && score.canmatch_exten) {
02856          q->status = STATUS_SUCCESS;
02857 #ifdef NEED_DEBUG_HERE
02858          ast_log(LOG_NOTICE,"Returning CANMATCH exten %s\n", score.canmatch_exten->exten);
02859 #endif
02860          return score.canmatch_exten;
02861       }
02862 
02863       if ((action == E_MATCHMORE || action == E_CANMATCH)  && eroot) {
02864          if (score.node) {
02865             struct ast_exten *z = trie_find_next_match(score.node);
02866             if (z) {
02867 #ifdef NEED_DEBUG_HERE
02868                ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten %s\n", z->exten);
02869 #endif
02870             } else {
02871                if (score.canmatch_exten) {
02872 #ifdef NEED_DEBUG_HERE
02873                   ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE canmatchmatch exten %s(%p)\n", score.canmatch_exten->exten, score.canmatch_exten);
02874 #endif
02875                   return score.canmatch_exten;
02876                } else {
02877 #ifdef NEED_DEBUG_HERE
02878                   ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten NULL\n");
02879 #endif
02880                }
02881             }
02882             return z;
02883          }
02884 #ifdef NEED_DEBUG_HERE
02885          ast_log(LOG_NOTICE, "Returning CANMATCH/MATCHMORE NULL (no next_match)\n");
02886 #endif
02887          return NULL;  /* according to the code, complete matches are null matches in MATCHMORE mode */
02888       }
02889 
02890       if (eroot) {
02891          /* found entry, now look for the right priority */
02892          if (q->status < STATUS_NO_PRIORITY)
02893             q->status = STATUS_NO_PRIORITY;
02894          e = NULL;
02895          if (action == E_FINDLABEL && label ) {
02896             if (q->status < STATUS_NO_LABEL)
02897                q->status = STATUS_NO_LABEL;
02898             e = ast_hashtab_lookup(eroot->peer_label_table, &pattern);
02899          } else {
02900             e = ast_hashtab_lookup(eroot->peer_table, &pattern);
02901          }
02902          if (e) { /* found a valid match */
02903             q->status = STATUS_SUCCESS;
02904             q->foundcontext = context;
02905 #ifdef NEED_DEBUG_HERE
02906             ast_log(LOG_NOTICE,"Returning complete match of exten %s\n", e->exten);
02907 #endif
02908             return e;
02909          }
02910       }
02911    } else {   /* the old/current default exten pattern match algorithm */
02912 
02913       /* scan the list trying to match extension and CID */
02914       eroot = NULL;
02915       while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) {
02916          int match = extension_match_core(eroot->exten, exten, action);
02917          /* 0 on fail, 1 on match, 2 on earlymatch */
02918 
02919          if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid)))
02920             continue;   /* keep trying */
02921          if (match == 2 && action == E_MATCHMORE) {
02922             /* We match an extension ending in '!'.
02923              * The decision in this case is final and is NULL (no match).
02924              */
02925             return NULL;
02926          }
02927          /* found entry, now look for the right priority */
02928          if (q->status < STATUS_NO_PRIORITY)
02929             q->status = STATUS_NO_PRIORITY;
02930          e = NULL;
02931          if (action == E_FINDLABEL && label ) {
02932             if (q->status < STATUS_NO_LABEL)
02933                q->status = STATUS_NO_LABEL;
02934             e = ast_hashtab_lookup(eroot->peer_label_table, &pattern);
02935          } else {
02936             e = ast_hashtab_lookup(eroot->peer_table, &pattern);
02937          }
02938          if (e) { /* found a valid match */
02939             q->status = STATUS_SUCCESS;
02940             q->foundcontext = context;
02941             return e;
02942          }
02943       }
02944    }
02945 
02946    /* Check alternative switches */
02947    AST_LIST_TRAVERSE(&tmp->alts, sw, list) {
02948       struct ast_switch *asw = pbx_findswitch(sw->name);
02949       ast_switch_f *aswf = NULL;
02950       char *datap;
02951 
02952       if (!asw) {
02953          ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name);
02954          continue;
02955       }
02956 
02957       /* Substitute variables now */
02958       if (sw->eval) {
02959          if (!(tmpdata = ast_str_thread_get(&switch_data, 512))) {
02960             ast_log(LOG_WARNING, "Can't evaluate switch?!\n");
02961             continue;
02962          }
02963          pbx_substitute_variables_helper(chan, sw->data, ast_str_buffer(tmpdata), ast_str_size(tmpdata));
02964       }
02965 
02966       /* equivalent of extension_match_core() at the switch level */
02967       if (action == E_CANMATCH)
02968          aswf = asw->canmatch;
02969       else if (action == E_MATCHMORE)
02970          aswf = asw->matchmore;
02971       else /* action == E_MATCH */
02972          aswf = asw->exists;
02973       datap = sw->eval ? ast_str_buffer(tmpdata) : sw->data;
02974       if (!aswf)
02975          res = 0;
02976       else {
02977          if (chan)
02978             ast_autoservice_start(chan);
02979          res = aswf(chan, context, exten, priority, callerid, datap);
02980          if (chan)
02981             ast_autoservice_stop(chan);
02982       }
02983       if (res) {  /* Got a match */
02984          q->swo = asw;
02985          q->data = datap;
02986          q->foundcontext = context;
02987          /* XXX keep status = STATUS_NO_CONTEXT ? */
02988          return NULL;
02989       }
02990    }
02991    q->incstack[q->stacklen++] = tmp->name;   /* Setup the stack */
02992    /* Now try any includes we have in this context */
02993    for (i = tmp->includes; i; i = i->next) {
02994       if (include_valid(i)) {
02995          if ((e = pbx_find_extension(chan, bypass, q, i->rname, exten, priority, label, callerid, action))) {
02996 #ifdef NEED_DEBUG_HERE
02997             ast_log(LOG_NOTICE,"Returning recursive match of %s\n", e->exten);
02998 #endif
02999             return e;
03000          }
03001          if (q->swo)
03002             return NULL;
03003       }
03004    }
03005    return NULL;
03006 }

struct ast_app* pbx_findapp ( const char *  app  ) 

Look up an application.

Parameters:
app name of the app
This function searches for the ast_app structure within the apps that are registered for the one with the name you passed in.

Returns:
the ast_app structure that matches on success, or NULL on failure

Definition at line 1462 of file pbx.c.

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

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

01463 {
01464    struct ast_app *tmp;
01465 
01466    AST_RWLIST_RDLOCK(&apps);
01467    AST_RWLIST_TRAVERSE(&apps, tmp, list) {
01468       if (!strcasecmp(tmp->name, app))
01469          break;
01470    }
01471    AST_RWLIST_UNLOCK(&apps);
01472 
01473    return tmp;
01474 }

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

Definition at line 1476 of file pbx.c.

References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_switch::list, 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 10580 of file pbx.c.

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

Referenced by ast_async_parseable_goto(), and ast_parseable_goto().

10581 {
10582    char *exten, *pri, *context;
10583    char *stringp;
10584    int ipri;
10585    int mode = 0;
10586 
10587    if (ast_strlen_zero(goto_string)) {
10588       ast_log(LOG_WARNING, "Goto requires an argument ([[context,]extension,]priority)\n");
10589       return -1;
10590    }
10591    stringp = ast_strdupa(goto_string);
10592    context = strsep(&stringp, ","); /* guaranteed non-null */
10593    exten = strsep(&stringp, ",");
10594    pri = strsep(&stringp, ",");
10595    if (!exten) {  /* Only a priority in this one */
10596       pri = context;
10597       exten = NULL;
10598       context = NULL;
10599    } else if (!pri) {   /* Only an extension and priority in this one */
10600       pri = exten;
10601       exten = context;
10602       context = NULL;
10603    }
10604    if (*pri == '+') {
10605       mode = 1;
10606       pri++;
10607    } else if (*pri == '-') {
10608       mode = -1;
10609       pri++;
10610    }
10611    if (sscanf(pri, "%30d", &ipri) != 1) {
10612       ipri = ast_findlabel_extension(chan, context ? context : chan->context,
10613          exten ? exten : chan->exten, pri,
10614          S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL));
10615       if (ipri < 1) {
10616          ast_log(LOG_WARNING, "Priority '%s' must be a number > 0, or valid label\n", pri);
10617          return -1;
10618       } else
10619          mode = 0;
10620    }
10621    /* At this point we have a priority and maybe an extension and a context */
10622 
10623    if (mode)
10624       ipri = chan->priority + (ipri * mode);
10625 
10626    if (async)
10627       ast_async_goto(chan, context, exten, ipri);
10628    else
10629       ast_explicit_goto(chan, context, exten, ipri);
10630 
10631    return 0;
10632 
10633 }

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

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

Note:
See also

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

03137 {
03138    struct ast_str *str = ast_str_create(16);
03139    const char *cret;
03140 
03141    cret = ast_str_retrieve_variable(&str, 0, c, headp, var);
03142    ast_copy_string(workspace, ast_str_buffer(str), workspacelen);
03143    *ret = cret ? workspace : NULL;
03144    ast_free(str);
03145 }

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

References autofallthrough.

Referenced by pbx_load_module().

05416 {
05417    int oldval = autofallthrough;
05418    autofallthrough = newval;
05419    return oldval;
05420 }

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

References extenpatternmatchnew.

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

05423 {
05424    int oldval = extenpatternmatchnew;
05425    extenpatternmatchnew = newval;
05426    return oldval;
05427 }

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

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

Referenced by pbx_load_module().

05430 {
05431    if (overrideswitch) {
05432       ast_free(overrideswitch);
05433    }
05434    if (!ast_strlen_zero(newval)) {
05435       overrideswitch = ast_strdup(newval);
05436    } else {
05437       overrideswitch = NULL;
05438    }
05439 }

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

Definition at line 4165 of file pbx.c.

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

Referenced by pbx_extension_helper().

04166 {
04167    const char *tmp;
04168 
04169    /* Nothing more to do */
04170    if (!e->data) {
04171       *passdata = '\0';
04172       return;
04173    }
04174 
04175    /* No variables or expressions in e->data, so why scan it? */
04176    if ((!(tmp = strchr(e->data, '$'))) || (!strstr(tmp, "${") && !strstr(tmp, "$["))) {
04177       ast_copy_string(passdata, e->data, datalen);
04178       return;
04179    }
04180 
04181    pbx_substitute_variables_helper(c, e->data, passdata, datalen - 1);
04182 }

void pbx_substitute_variables_helper ( struct ast_channel c,
const char *  cp1,
char *  cp2,
int  count 
)

Definition at line 4153 of file pbx.c.

References pbx_substitute_variables_helper_full(), and ast_channel::varshead.

Referenced by add_extensions(), ast_add_extension2_lockopt(), function_eval(), get_manager_event_info(), get_mapping_weight(), import_helper(), launch_monitor_thread(), manager_log(), pbx_builtin_importvar(), pbx_find_extension(), pbx_load_config(), pbx_substitute_variables(), rotate_file(), substituted(), and write_cdr().

04154 {
04155    size_t used;
04156    pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count, &used);
04157 }

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

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

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

03958 {
03959    /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!!  */
03960    char *cp4 = NULL;
03961    const char *tmp, *whereweare, *orig_cp2 = cp2;
03962    int length, offset, offset2, isfunction;
03963    char *workspace = NULL;
03964    char *ltmp = NULL, *var = NULL;
03965    char *nextvar, *nextexp, *nextthing;
03966    char *vars, *vare;
03967    int pos, brackets, needsub, len;
03968 
03969    *cp2 = 0; /* just in case nothing ends up there */
03970    whereweare=tmp=cp1;
03971    while (!ast_strlen_zero(whereweare) && count) {
03972       /* Assume we're copying the whole remaining string */
03973       pos = strlen(whereweare);
03974       nextvar = NULL;
03975       nextexp = NULL;
03976       nextthing = strchr(whereweare, '$');
03977       if (nextthing) {
03978          switch (nextthing[1]) {
03979          case '{':
03980             nextvar = nextthing;
03981             pos = nextvar - whereweare;
03982             break;
03983          case '[':
03984             nextexp = nextthing;
03985             pos = nextexp - whereweare;
03986             break;
03987          default:
03988             pos = 1;
03989          }
03990       }
03991 
03992       if (pos) {
03993          /* Can't copy more than 'count' bytes */
03994          if (pos > count)
03995             pos = count;
03996 
03997          /* Copy that many bytes */
03998          memcpy(cp2, whereweare, pos);
03999 
04000          count -= pos;
04001          cp2 += pos;
04002          whereweare += pos;
04003          *cp2 = 0;
04004       }
04005 
04006       if (nextvar) {
04007          /* We have a variable.  Find the start and end, and determine
04008             if we are going to have to recursively call ourselves on the
04009             contents */
04010          vars = vare = nextvar + 2;
04011          brackets = 1;
04012          needsub = 0;
04013 
04014          /* Find the end of it */
04015          while (brackets && *vare) {
04016             if ((vare[0] == '$') && (vare[1] == '{')) {
04017                needsub++;
04018             } else if (vare[0] == '{') {
04019                brackets++;
04020             } else if (vare[0] == '}') {
04021                brackets--;
04022             } else if ((vare[0] == '$') && (vare[1] == '['))
04023                needsub++;
04024             vare++;
04025          }
04026          if (brackets)
04027             ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n");
04028          len = vare - vars - 1;
04029 
04030          /* Skip totally over variable string */
04031          whereweare += (len + 3);
04032 
04033          if (!var)
04034             var = alloca(VAR_BUF_SIZE);
04035 
04036          /* Store variable name (and truncate) */
04037          ast_copy_string(var, vars, len + 1);
04038 
04039          /* Substitute if necessary */
04040          if (needsub) {
04041             size_t used;
04042             if (!ltmp)
04043                ltmp = alloca(VAR_BUF_SIZE);
04044 
04045             pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used);
04046             vars = ltmp;
04047          } else {
04048             vars = var;
04049          }
04050 
04051          if (!workspace)
04052             workspace = alloca(VAR_BUF_SIZE);
04053 
04054          workspace[0] = '\0';
04055 
04056          parse_variable_name(vars, &offset, &offset2, &isfunction);
04057          if (isfunction) {
04058             /* Evaluate function */
04059             if (c || !headp)
04060                cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
04061             else {
04062                struct varshead old;
04063                struct ast_channel *c = ast_dummy_channel_alloc();
04064                if (c) {
04065                   memcpy(&old, &c->varshead, sizeof(old));
04066                   memcpy(&c->varshead, headp, sizeof(c->varshead));
04067                   cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
04068                   /* Don't deallocate the varshead that was passed in */
04069                   memcpy(&c->varshead, &old, sizeof(c->varshead));
04070                   c = ast_channel_unref(c);
04071                } else {
04072                   ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution.  Function results may be blank.\n");
04073                }
04074             }
04075             ast_debug(2, "Function result is '%s'\n", cp4 ? cp4 : "(null)");
04076          } else {
04077             /* Retrieve variable value */
04078             pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp);
04079          }
04080          if (cp4) {
04081             cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE);
04082 
04083             length = strlen(cp4);
04084             if (length > count)
04085                length = count;
04086             memcpy(cp2, cp4, length);
04087             count -= length;
04088             cp2 += length;
04089             *cp2 = 0;
04090          }
04091       } else if (nextexp) {
04092          /* We have an expression.  Find the start and end, and determine
04093             if we are going to have to recursively call ourselves on the
04094             contents */
04095          vars = vare = nextexp + 2;
04096          brackets = 1;
04097          needsub = 0;
04098 
04099          /* Find the end of it */
04100          while (brackets && *vare) {
04101             if ((vare[0] == '$') && (vare[1] == '[')) {
04102                needsub++;
04103                brackets++;
04104                vare++;
04105             } else if (vare[0] == '[') {
04106                brackets++;
04107             } else if (vare[0] == ']') {
04108                brackets--;
04109             } else if ((vare[0] == '$') && (vare[1] == '{')) {
04110                needsub++;
04111                vare++;
04112             }
04113             vare++;
04114          }
04115          if (brackets)
04116             ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n");
04117          len = vare - vars - 1;
04118 
04119          /* Skip totally over expression */
04120          whereweare += (len + 3);
04121 
04122          if (!var)
04123             var = alloca(VAR_BUF_SIZE);
04124 
04125          /* Store variable name (and truncate) */
04126          ast_copy_string(var, vars, len + 1);
04127 
04128          /* Substitute if necessary */
04129          if (needsub) {
04130             size_t used;
04131             if (!ltmp)
04132                ltmp = alloca(VAR_BUF_SIZE);
04133 
04134             pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used);
04135             vars = ltmp;
04136          } else {
04137             vars = var;
04138          }
04139 
04140          length = ast_expr(vars, cp2, count, c);
04141 
04142          if (length) {
04143             ast_debug(1, "Expression result is '%s'\n", cp2);
04144             count -= length;
04145             cp2 += length;
04146             *cp2 = 0;
04147          }
04148       }
04149    }
04150    *used = cp2 - orig_cp2;
04151 }

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

Definition at line 4159 of file pbx.c.

References pbx_substitute_variables_helper_full().

Referenced by dundi_lookup_local(), and loopback_subst().

04160 {
04161    size_t used;
04162    pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count, &used);
04163 }

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

Definition at line 5333 of file pbx.c.

References __ast_pbx_run(), and decrease_call_count().

Referenced by ast_pbx_start().

05334 {
05335    /* Oh joyeous kernel, we're a new thread, with nothing to do but
05336       answer this channel and get it going.
05337    */
05338    /* NOTE:
05339       The launcher of this function _MUST_ increment 'countcalls'
05340       before invoking the function; it will be decremented when the
05341       PBX has finished running on the channel
05342     */
05343    struct ast_channel *c = data;
05344 
05345    __ast_pbx_run(c, NULL);
05346    decrease_call_count();
05347 
05348    pthread_exit(NULL);
05349 
05350    return NULL;
05351 }

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

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

05946 {
05947    /* Maximum number of characters added by terminal coloring is 22 */
05948    char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40], stxtitle[40], argtitle[40];
05949    char seealsotitle[40];
05950    char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL, *syntax = NULL, *arguments = NULL;
05951    char *seealso = NULL;
05952    int syntax_size, synopsis_size, description_size, arguments_size, seealso_size;
05953 
05954    snprintf(info, sizeof(info), "\n  -= Info about application '%s' =- \n\n", aa->name);
05955    term_color(infotitle, info, COLOR_MAGENTA, 0, sizeof(infotitle));
05956 
05957    term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
05958    term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
05959    term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40);
05960    term_color(argtitle, "[Arguments]\n", COLOR_MAGENTA, 0, 40);
05961    term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, 40);
05962 
05963 #ifdef AST_XML_DOCS
05964    if (aa->docsrc == AST_XML_DOC) {
05965       description = ast_xmldoc_printable(S_OR(aa->description, "Not available"), 1);
05966       arguments = ast_xmldoc_printable(S_OR(aa->arguments, "Not available"), 1);
05967       synopsis = ast_xmldoc_printable(S_OR(aa->synopsis, "Not available"), 1);
05968       seealso = ast_xmldoc_printable(S_OR(aa->seealso, "Not available"), 1);
05969 
05970       if (!synopsis || !description || !arguments || !seealso) {
05971          goto return_cleanup;
05972       }
05973    } else
05974 #endif
05975    {
05976       synopsis_size = strlen(S_OR(aa->synopsis, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
05977       synopsis = ast_malloc(synopsis_size);
05978 
05979       description_size = strlen(S_OR(aa->description, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
05980       description = ast_malloc(description_size);
05981 
05982       arguments_size = strlen(S_OR(aa->arguments, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
05983       arguments = ast_malloc(arguments_size);
05984 
05985       seealso_size = strlen(S_OR(aa->seealso, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
05986       seealso = ast_malloc(seealso_size);
05987 
05988       if (!synopsis || !description || !arguments || !seealso) {
05989          goto return_cleanup;
05990       }
05991 
05992       term_color(synopsis, S_OR(aa->synopsis, "Not available"), COLOR_CYAN, 0, synopsis_size);
05993       term_color(description, S_OR(aa->description, "Not available"),   COLOR_CYAN, 0, description_size);
05994       term_color(arguments, S_OR(aa->arguments, "Not available"), COLOR_CYAN, 0, arguments_size);
05995       term_color(seealso, S_OR(aa->seealso, "Not available"), COLOR_CYAN, 0, seealso_size);
05996    }
05997 
05998    /* Handle the syntax the same for both XML and raw docs */
05999    syntax_size = strlen(S_OR(aa->syntax, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
06000    if (!(syntax = ast_malloc(syntax_size))) {
06001       goto return_cleanup;
06002    }
06003    term_color(syntax, S_OR(aa->syntax, "Not available"), COLOR_CYAN, 0, syntax_size);
06004 
06005    ast_cli(fd, "%s%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n",
06006          infotitle, syntitle, synopsis, destitle, description,
06007          stxtitle, syntax, argtitle, arguments, seealsotitle, seealso);
06008 
06009 return_cleanup:
06010    ast_free(description);
06011    ast_free(arguments);
06012    ast_free(synopsis);
06013    ast_free(seealso);
06014    ast_free(syntax);
06015 }

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

helper function to print an extension

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

06372 {
06373    int prio = ast_get_extension_priority(e);
06374    if (prio == PRIORITY_HINT) {
06375       snprintf(buf, buflen, "hint: %s",
06376          ast_get_extension_app(e));
06377    } else {
06378       snprintf(buf, buflen, "%d. %s(%s)",
06379          prio, ast_get_extension_app(e),
06380          (!ast_strlen_zero(ast_get_extension_app_data(e)) ? (char *)ast_get_extension_app_data(e) : ""));
06381    }
06382 }

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

Definition at line 3296 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 pbx_builtin_raise_exception(), and pbx_builtin_waitexten().

03297 {
03298    struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL);
03299    struct pbx_exception *exception = NULL;
03300 
03301    if (!ds) {
03302       ds = ast_datastore_alloc(&exception_store_info, NULL);
03303       if (!ds)
03304          return -1;
03305       if (!(exception = ast_calloc_with_stringfields(1, struct pbx_exception, 128))) {
03306          ast_datastore_free(ds);
03307          return -1;
03308       }
03309       ds->data = exception;
03310       ast_channel_datastore_add(chan, ds);
03311    } else
03312       exception = ds->data;
03313 
03314    ast_string_field_set(exception, reason, reason);
03315    ast_string_field_set(exception, context, chan->context);
03316    ast_string_field_set(exception, exten, chan->exten);
03317    exception->priority = chan->priority;
03318    set_ext_pri(chan, "e", priority);
03319    return 0;
03320 }

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

04909 {
04910    ast_channel_lock(c);
04911    ast_copy_string(c->exten, exten, sizeof(c->exten));
04912    c->priority = pri;
04913    ast_channel_unlock(c);
04914 }

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

06537 {
06538    struct ast_context *c = NULL;
06539    int res = 0, old_total_exten = dpc->total_exten;
06540 
06541    ast_cli(fd,"\n     In-mem exten Trie for Fast Extension Pattern Matching:\n\n");
06542 
06543    ast_cli(fd,"\n           Explanation: Node Contents Format = <char(s) to match>:<pattern?>:<specif>:[matched extension]\n");
06544    ast_cli(fd,    "                        Where <char(s) to match> is a set of chars, any one of which should match the current character\n");
06545    ast_cli(fd,    "                              <pattern?>: Y if this a pattern match (eg. _XZN[5-7]), N otherwise\n");
06546    ast_cli(fd,    "                              <specif>: an assigned 'exactness' number for this matching char. The lower the number, the more exact the match\n");
06547    ast_cli(fd,    "                              [matched exten]: If all chars matched to this point, which extension this matches. In form: EXTEN:<exten string>\n");
06548    ast_cli(fd,    "                        In general, you match a trie node to a string character, from left to right. All possible matching chars\n");
06549    ast_cli(fd,    "                        are in a string vertically, separated by an unbroken string of '+' characters.\n\n");
06550    ast_rdlock_contexts();
06551 
06552    /* walk all contexts ... */
06553    while ( (c = ast_walk_contexts(c)) ) {
06554       int context_info_printed = 0;
06555 
06556       if (context && strcmp(ast_get_context_name(c), context))
06557          continue;   /* skip this one, name doesn't match */
06558 
06559       dpc->context_existence = 1;
06560 
06561       if (!c->pattern_tree) {
06562          /* Ignore check_return warning from Coverity for ast_exists_extension below */
06563          ast_exists_extension(NULL, c->name, "s", 1, ""); /* do this to force the trie to built, if it is not already */
06564       }
06565 
06566       ast_rdlock_context(c);
06567 
06568       dpc->total_context++;
06569       ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
06570          ast_get_context_name(c), ast_get_context_registrar(c));
06571       context_info_printed = 1;
06572 
06573       if (c->pattern_tree)
06574       {
06575          cli_match_char_tree(c->pattern_tree, " ", fd);
06576       } else {
06577          ast_cli(fd,"\n     No Pattern Trie present. Perhaps the context is empty...or there is trouble...\n\n");
06578       }
06579 
06580       ast_unlock_context(c);
06581 
06582       /* if we print something in context, make an empty line */
06583       if (context_info_printed)
06584          ast_cli(fd, "\n");
06585    }
06586    ast_unlock_contexts();
06587 
06588    return (dpc->total_exten == old_total_exten) ? -1 : res;
06589 }

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

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

Referenced by handle_show_dialplan().

06386 {
06387    struct ast_context *c = NULL;
06388    int res = 0, old_total_exten = dpc->total_exten;
06389 
06390    ast_rdlock_contexts();
06391 
06392    /* walk all contexts ... */
06393    while ( (c = ast_walk_contexts(c)) ) {
06394       struct ast_exten *e;
06395       struct ast_include *i;
06396       struct ast_ignorepat *ip;
06397       char buf[256], buf2[256];
06398       int context_info_printed = 0;
06399 
06400       if (context && strcmp(ast_get_context_name(c), context))
06401          continue;   /* skip this one, name doesn't match */
06402 
06403       dpc->context_existence = 1;
06404 
06405       ast_rdlock_context(c);
06406 
06407       /* are we looking for exten too? if yes, we print context
06408        * only if we find our extension.
06409        * Otherwise print context even if empty ?
06410        * XXX i am not sure how the rinclude is handled.
06411        * I think it ought to go inside.
06412        */
06413       if (!exten) {
06414          dpc->total_context++;
06415          ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
06416             ast_get_context_name(c), ast_get_context_registrar(c));
06417          context_info_printed = 1;
06418       }
06419 
06420       /* walk extensions ... */
06421       e = NULL;
06422       while ( (e = ast_walk_context_extensions(c, e)) ) {
06423          struct ast_exten *p;
06424 
06425          if (exten && !ast_extension_match(ast_get_extension_name(e), exten))
06426             continue;   /* skip, extension match failed */
06427 
06428          dpc->extension_existence = 1;
06429 
06430          /* may we print context info? */
06431          if (!context_info_printed) {
06432             dpc->total_context++;
06433             if (rinclude) { /* TODO Print more info about rinclude */
06434                ast_cli(fd, "[ Included context '%s' created by '%s' ]\n",
06435                   ast_get_context_name(c), ast_get_context_registrar(c));
06436             } else {
06437                ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
06438                   ast_get_context_name(c), ast_get_context_registrar(c));
06439             }
06440             context_info_printed = 1;
06441          }
06442          dpc->total_prio++;
06443 
06444          /* write extension name and first peer */
06445          if (e->matchcid)
06446             snprintf(buf, sizeof(buf), "'%s' (CID match '%s') => ", ast_get_extension_name(e), e->cidmatch);
06447          else
06448             snprintf(buf, sizeof(buf), "'%s' =>", ast_get_extension_name(e));
06449 
06450          print_ext(e, buf2, sizeof(buf2));
06451 
06452          ast_cli(fd, "  %-17s %-45s [%s]\n", buf, buf2,
06453             ast_get_extension_registrar(e));
06454 
06455          dpc->total_exten++;
06456          /* walk next extension peers */
06457          p = e;   /* skip the first one, we already got it */
06458          while ( (p = ast_walk_extension_priorities(e, p)) ) {
06459             const char *el = ast_get_extension_label(p);
06460             dpc->total_prio++;
06461             if (el)
06462                snprintf(buf, sizeof(buf), "   [%s]", el);
06463             else
06464                buf[0] = '\0';
06465             print_ext(p, buf2, sizeof(buf2));
06466 
06467             ast_cli(fd,"  %-17s %-45s [%s]\n", buf, buf2,
06468                ast_get_extension_registrar(p));
06469          }
06470       }
06471 
06472       /* walk included and write info ... */
06473       i = NULL;
06474       while ( (i = ast_walk_context_includes(c, i)) ) {
06475          snprintf(buf, sizeof(buf), "'%s'", ast_get_include_name(i));
06476          if (exten) {
06477             /* Check all includes for the requested extension */
06478             if (includecount >= AST_PBX_MAX_STACK) {
06479                ast_log(LOG_WARNING, "Maximum include depth exceeded!\n");
06480             } else {
06481                int dupe = 0;
06482                int x;
06483                for (x = 0; x < includecount; x++) {
06484                   if (!strcasecmp(includes[x], ast_get_include_name(i))) {
06485                      dupe++;
06486                      break;
06487                   }
06488                }
06489                if (!dupe) {
06490                   includes[includecount] = ast_get_include_name(i);
06491                   show_dialplan_helper(fd, ast_get_include_name(i), exten, dpc, i, includecount + 1, includes);
06492                } else {
06493                   ast_log(LOG_WARNING, "Avoiding circular include of %s within %s\n", ast_get_include_name(i), context);
06494                }
06495             }
06496          } else {
06497             ast_cli(fd, "  Include =>        %-45s [%s]\n",
06498                buf, ast_get_include_registrar(i));
06499          }
06500       }
06501 
06502       /* walk ignore patterns and write info ... */
06503       ip = NULL;
06504       while ( (ip = ast_walk_context_ignorepats(c, ip)) ) {
06505          const char *ipname = ast_get_ignorepat_name(ip);
06506          char ignorepat[AST_MAX_EXTENSION];
06507          snprintf(buf, sizeof(buf), "'%s'", ipname);
06508          snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname);
06509          if (!exten || ast_extension_match(ignorepat, exten)) {
06510             ast_cli(fd, "  Ignore pattern => %-45s [%s]\n",
06511                buf, ast_get_ignorepat_registrar(ip));
06512          }
06513       }
06514       if (!rinclude) {
06515          struct ast_sw *sw = NULL;
06516          while ( (sw = ast_walk_context_switches(c, sw)) ) {
06517             snprintf(buf, sizeof(buf), "'%s/%s'",
06518                ast_get_switch_name(sw),
06519                ast_get_switch_data(sw));
06520             ast_cli(fd, "  Alt. Switch =>    %-45s [%s]\n",
06521                buf, ast_get_switch_registrar(sw));
06522          }
06523       }
06524 
06525       ast_unlock_context(c);
06526 
06527       /* if we print something in context, make an empty line */
06528       if (context_info_printed)
06529          ast_cli(fd, "\n");
06530    }
06531    ast_unlock_contexts();
06532 
06533    return (dpc->total_exten == old_total_exten) ? -1 : res;
06534 }

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

Definition at line 10692 of file pbx.c.

References ast_state_cb::change_cb, CMP_MATCH, and CMP_STOP.

Referenced by ast_pbx_init().

10693 {
10694    const struct ast_state_cb *state_cb = obj;
10695    ast_state_cb_type change_cb = arg;
10696 
10697    return (state_cb->change_cb == change_cb) ? CMP_MATCH | CMP_STOP : 0;
10698 }

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

References ast_copy_string().

Referenced by pbx_substitute_variables_helper_full().

03047 {
03048    char *ret = workspace;
03049    int lr;  /* length of the input string after the copy */
03050 
03051    ast_copy_string(workspace, value, workspace_len); /* always make a copy */
03052 
03053    lr = strlen(ret); /* compute length after copy, so we never go out of the workspace */
03054 
03055    /* Quick check if no need to do anything */
03056    if (offset == 0 && length >= lr) /* take the whole string */
03057       return ret;
03058 
03059    if (offset < 0)   {  /* translate negative offset into positive ones */
03060       offset = lr + offset;
03061       if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */
03062          offset = 0;
03063    }
03064 
03065    /* too large offset result in empty string so we know what to return */
03066    if (offset >= lr)
03067       return ret + lr;  /* the final '\0' */
03068 
03069    ret += offset;    /* move to the start position */
03070    if (length >= 0 && length < lr - offset)  /* truncate if necessary */
03071       ret[length] = '\0';
03072    else if (length < 0) {
03073       if (lr > offset - length) /* After we remove from the front and from the rear, is there anything left? */
03074          ret[lr + length - offset] = '\0';
03075       else
03076          ret[0] = '\0';
03077    }
03078 
03079    return ret;
03080 }

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

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 unreference_cached_app ( struct ast_app app  )  [static]

Definition at line 7145 of file pbx.c.

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

Referenced by ast_unregister_application().

07146 {
07147    struct ast_context *context = NULL;
07148    struct ast_exten *eroot = NULL, *e = NULL;
07149 
07150    ast_rdlock_contexts();
07151    while ((context = ast_walk_contexts(context))) {
07152       while ((eroot = ast_walk_context_extensions(context, eroot))) {
07153          while ((e = ast_walk_extension_priorities(eroot, e))) {
07154             if (e->cached_app == app)
07155                e->cached_app = NULL;
07156          }
07157       }
07158    }
07159    ast_unlock_contexts();
07160 
07161    return;
07162 }

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

09310 {
09311    int res;
09312    struct ast_frame *f;
09313    double waitsec;
09314    int waittime;
09315 
09316    if (ast_strlen_zero(data) || (sscanf(data, "%30lg", &waitsec) != 1) || (waitsec < 0))
09317       waitsec = -1;
09318    if (waitsec > -1) {
09319       waittime = waitsec * 1000.0;
09320       ast_safe_sleep(chan, waittime);
09321    } else do {
09322       res = ast_waitfor(chan, -1);
09323       if (res < 0)
09324          return;
09325       f = ast_read(chan);
09326       if (f)
09327          ast_frfree(f);
09328    } while(f);
09329 }


Variable Documentation

int autofallthrough = 1 [static]

Definition at line 1156 of file pbx.c.

Referenced by 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().

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]

Definition at line 1206 of file pbx.c.

Referenced by __ast_context_destroy(), ast_context_destroy(), ast_context_find_or_create(), ast_merge_contexts_and_delete(), and ast_walk_contexts().

struct ast_hashtab* contexts_table = NULL [static]

Definition at line 1207 of file pbx.c.

Referenced by ast_context_destroy(), ast_context_find(), ast_context_find_or_create(), ast_merge_contexts_and_delete(), find_context(), and find_context_locked().

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

struct ast_taskprocessor* device_state_tps [static]

Definition at line 820 of file pbx.c.

Referenced by device_state_cb(), and load_pbx().

struct ast_custom_function exception_function [static]

Initial value:

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

Definition at line 3348 of file pbx.c.

Referenced by load_pbx().

struct ast_datastore_info exception_store_info [static]

Initial value:

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

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

struct cfextension_states extension_states[] [static]

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]

Definition at line 1154 of file pbx.c.

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

Definition at line 1153 of file pbx.c.

Referenced by ast_str_retrieve_variable(), handle_show_globals(), pbx_builtin_clear_globals(), pbx_builtin_getvar_helper(), pbx_builtin_pushvar_helper(), and pbx_builtin_setvar_helper().

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

struct ast_data_handler hints_data_provider [static]

Initial value:

Definition at line 10298 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 7741 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 7124 of file pbx.c.

Referenced by load_pbx().

struct ast_data_entry pbx_data_providers[] [static]

Initial value:

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

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

Referenced by pbx_builtin_resetcdr().

struct ao2_container* statecbs [static]

Definition at line 1237 of file pbx.c.

Referenced by ast_extension_state_add_destroy(), ast_extension_state_del(), ast_pbx_init(), and handle_statechange().

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

struct ast_custom_function testtime_function [static]

Initial value:

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

Definition at line 9541 of file pbx.c.

Referenced by load_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 Mon Oct 8 12:39:25 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7