Fri Jun 19 12:10:42 2009

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/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/stringfields.h"
#include "asterisk/event.h"
#include "asterisk/hashtab.h"
#include "asterisk/module.h"
#include "asterisk/indications.h"
#include "asterisk/taskprocessor.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  hints
struct  match_char
 match_char: forms a syntax tree for quick matching of extension patterns More...
struct  pbx_builtin
 Declaration of builtin applications. More...
struct  pbx_exception
struct  scoreboard
struct  statecbs
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 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_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 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, char *pattern, int is_pattern, int already, int specificity, struct match_char **parent)
static int add_pri (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 int add_pri_lockopt (struct ast_context *con, struct ast_exten *tmp, struct ast_exten *el, struct ast_exten *e, int replace, int lockhints)
 add the extension in the priority chain.
static struct match_charalready_in_tree (struct match_char *current, char *pat)
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 lockconts, int lockhints)
 Does all the work of ast_add_extension2, but adds two args, to determine if context and hint locking should be done. In merge_and_delete, we need to do this without locking, as the locks are already held.
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.
static int ast_add_hint_nolock (struct ast_exten *e)
 Add hint to hint list, check initial extension state; the hints had better be WRLOCKED already!
int ast_async_goto (struct ast_channel *chan, const char *context, const char *exten, int priority)
int ast_async_goto_by_name (const char *channame, const char *context, const char *exten, int priority)
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)
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)
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_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.
int ast_extension_state_add (const char *context, const char *exten, ast_state_cb_type callback, void *data)
 Registers a state change callback.
int ast_extension_state_del (int id, ast_state_cb_type callback)
 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_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)
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_outgoing_app (const char *type, int 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, int 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 ()
 Read locks the context list.
int ast_register_application2 (const char *app, int(*execute)(struct ast_channel *, void *), 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_unlock_context (struct ast_context *con)
int ast_unlock_contexts ()
 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 ()
 Write locks the context list.
int ast_wrlock_contexts_version (void)
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_pattern_tree (struct match_char *pattern_tree)
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)
 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 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 unsigned get_range (char *src, int max, 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 2 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_chanvar_deprecated (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_set_global_deprecated (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_globals_deprecated (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
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 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)
void log_match_char_tree (struct match_char *node, char *prefix)
static int lookup_name (const char *s, 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 *, void *)
static int pbx_builtin_background (struct ast_channel *, void *)
static int pbx_builtin_busy (struct ast_channel *, void *)
void pbx_builtin_clear_globals (void)
static int pbx_builtin_congestion (struct ast_channel *, void *)
static int pbx_builtin_execiftime (struct ast_channel *, void *)
const char * pbx_builtin_getvar_helper (struct ast_channel *chan, const char *name)
static int pbx_builtin_goto (struct ast_channel *, void *)
static int pbx_builtin_gotoif (struct ast_channel *, void *)
static int pbx_builtin_gotoiftime (struct ast_channel *, void *)
static int pbx_builtin_hangup (struct ast_channel *, void *)
static int pbx_builtin_importvar (struct ast_channel *, void *)
static int pbx_builtin_incomplete (struct ast_channel *, void *)
static int pbx_builtin_noop (struct ast_channel *, void *)
static int pbx_builtin_proceeding (struct ast_channel *, void *)
static int pbx_builtin_progress (struct ast_channel *, void *)
void pbx_builtin_pushvar_helper (struct ast_channel *chan, const char *name, const char *value)
int pbx_builtin_raise_exception (struct ast_channel *chan, void *vreason)
static int pbx_builtin_resetcdr (struct ast_channel *, void *)
static int pbx_builtin_ringing (struct ast_channel *, void *)
static int pbx_builtin_saycharacters (struct ast_channel *, void *)
static int pbx_builtin_saydigits (struct ast_channel *, void *)
static int pbx_builtin_saynumber (struct ast_channel *, void *)
static int pbx_builtin_sayphonetic (struct ast_channel *, void *)
int pbx_builtin_serialize_variables (struct ast_channel *chan, struct ast_str **buf)
static int pbx_builtin_setamaflags (struct ast_channel *, void *)
int pbx_builtin_setvar (struct ast_channel *, void *)
void pbx_builtin_setvar_helper (struct ast_channel *chan, const char *name, const char *value)
int pbx_builtin_setvar_multiple (struct ast_channel *, void *)
static int pbx_builtin_wait (struct ast_channel *, void *)
static int pbx_builtin_waitexten (struct ast_channel *, void *)
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, void *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)
 Support for Asterisk built-in variables in the dialplan.
int pbx_set_autofallthrough (int newval)
int pbx_set_extenpatternmatchnew (int newval)
void pbx_set_overrideswitch (const char *newval)
static void pbx_substitute_variables (char *passdata, int datalen, struct ast_channel *c, struct ast_exten *e)
void pbx_substitute_variables_helper (struct ast_channel *c, const char *cp1, char *cp2, int count)
static void pbx_substitute_variables_helper_full (struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count)
void pbx_substitute_variables_varshead (struct varshead *headp, const char *cp1, char *cp2, int count)
static void * pbx_thread (void *data)
static void print_ext (struct ast_exten *e, char *buf, int buflen)
 helper function to print an extension
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 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 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, 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 struct ast_cli_entry cli_set_chanvar_deprecated = { .handler = handle_set_chanvar_deprecated , .summary = "Set a channel variable." ,__VA_ARGS__ }
static struct ast_cli_entry cli_set_global_deprecated = { .handler = handle_set_global_deprecated , .summary = "Set global dialplan variable." ,__VA_ARGS__ }
static struct ast_cli_entry cli_show_globals_deprecated = { .handler = handle_show_globals_deprecated , .summary = "Show global dialplan variables." ,__VA_ARGS__ }
static ast_rwlock_t conlock = PTHREAD_RWLOCK_INITIALIZER
static int conlock_wrlock_version = 0
static struct ast_contextcontexts
static struct ast_hashtabcontexts_table = NULL
static int countcalls
static char * 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 varshead globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE
static ast_rwlock_t globalslock = PTHREAD_RWLOCK_INITIALIZER
static char mandescr_show_dialplan []
static ast_mutex_t maxcalllock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP )
static char * months []
static char * overrideswitch = NULL
static struct ast_cli_entry pbx_cli []
static struct ast_app_option resetcdr_opts [128] = { [ 'w' ] = { .flag = (1 << 1) }, [ 'a' ] = { .flag = (1 << 2) }, [ 'v' ] = { .flag = (1 << 0) }, [ 'e' ] = { .flag = (1 << 10) },}
static int stateid = 1
static struct ast_threadstorage switch_data = { .once = PTHREAD_ONCE_INIT, .key_init = __init_switch_data , .custom_init = NULL , }
static int totalcalls
static struct ast_app_option waitexten_opts [128] = { [ 'm' ] = { .flag = (1 << 0) , .arg_index = 0 + 1 }, [ 'd' ] = { .flag = (1 << 1) , .arg_index = 0 + 1 },}


Detailed Description

Core PBX routines.

Author:
Mark Spencer <markster@digium.com>

Definition in file pbx.c.


Define Documentation

#define AST_PBX_MAX_STACK   128

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

Definition at line 968 of file pbx.c.

Referenced by handle_debug_dialplan(), handle_show_dialplan(), pbx_find_extension(), and show_dialplan_helper().

#define BACKGROUND_MATCHEXTEN   (1 << 2)

Definition at line 106 of file pbx.c.

Referenced by pbx_builtin_background().

#define BACKGROUND_NOANSWER   (1 << 1)

Definition at line 105 of file pbx.c.

Referenced by pbx_builtin_background().

#define BACKGROUND_PLAYBACK   (1 << 3)

Definition at line 107 of file pbx.c.

Referenced by pbx_builtin_background().

#define BACKGROUND_SKIP   (1 << 0)

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

Referenced by pbx_extension_helper().

#define NEW_MATCHER_CHK_MATCH

Referenced by new_find_extension().

#define NEW_MATCHER_RECURSE

#define SAY_STUBS

Definition at line 55 of file pbx.c.

#define STATUS_NO_CONTEXT   1

Definition at line 2032 of file pbx.c.

Referenced by pbx_extension_helper(), and pbx_find_extension().

#define STATUS_NO_EXTENSION   2

Definition at line 2033 of file pbx.c.

Referenced by pbx_extension_helper(), and pbx_find_extension().

#define STATUS_NO_LABEL   4

Definition at line 2035 of file pbx.c.

Referenced by pbx_extension_helper(), and pbx_find_extension().

#define STATUS_NO_PRIORITY   3

Definition at line 2034 of file pbx.c.

Referenced by pbx_extension_helper(), and pbx_find_extension().

#define STATUS_SUCCESS   5

Definition at line 2036 of file pbx.c.

Referenced by pbx_find_extension().

#define SWITCH_DATA_LENGTH   256

Definition at line 96 of file pbx.c.

#define VAR_BUF_SIZE   4096

Definition at line 98 of file pbx.c.

Referenced by add_user_extension(), ast_add_extension2_lockopt(), build_user_routes(), pbx_builtin_importvar(), pbx_substitute_variables_helper_full(), phoneprov_callback(), pp_each_extension_exec(), and pp_each_user_exec().

#define VAR_HARDTRAN   3

Definition at line 102 of file pbx.c.

#define VAR_NORMAL   1

Definition at line 100 of file pbx.c.

#define VAR_SOFTTRAN   2

Definition at line 101 of file pbx.c.

#define WAITEXTEN_DIALTONE   (1 << 1)

Definition at line 117 of file pbx.c.

Referenced by pbx_builtin_waitexten().

#define WAITEXTEN_MOH   (1 << 0)

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

References __ast_internal_context_destroy(), ast_context_remove_extension_callerid2(), 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_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().

07660 {
07661    struct ast_context *tmp, *tmpl=NULL;
07662    struct ast_exten *exten_item, *prio_item;
07663 
07664    for (tmp = list; tmp; ) {
07665       struct ast_context *next = NULL; /* next starting point */
07666          /* The following code used to skip forward to the next
07667             context with matching registrar, but this didn't
07668             make sense; individual priorities registrar'd to 
07669             the matching registrar could occur in any context! */
07670       ast_debug(1, "Investigate ctx %s %s\n", tmp->name, tmp->registrar);
07671       if (con) {
07672          for (; tmp; tmpl = tmp, tmp = tmp->next) { /* skip to the matching context */
07673             ast_debug(1, "check ctx %s %s\n", tmp->name, tmp->registrar);
07674             if ( !strcasecmp(tmp->name, con->name) ) {
07675                break;   /* found it */
07676             }
07677          }
07678       }
07679       
07680       if (!tmp)   /* not found, we are done */
07681          break;
07682       ast_wrlock_context(tmp);
07683 
07684       if (registrar) {
07685          /* then search thru and remove any extens that match registrar. */
07686          struct ast_hashtab_iter *exten_iter;
07687          struct ast_hashtab_iter *prio_iter;
07688          struct ast_ignorepat *ip, *ipl = NULL, *ipn = NULL;
07689          struct ast_include *i, *pi = NULL, *ni = NULL;
07690          struct ast_sw *sw = NULL;
07691 
07692          /* remove any ignorepats whose registrar matches */
07693          for (ip = tmp->ignorepats; ip; ip = ipn) {
07694             ipn = ip->next;
07695             if (!strcmp(ip->registrar, registrar)) {
07696                if (ipl) {
07697                   ipl->next = ip->next;
07698                   ast_free(ip);
07699                   continue; /* don't change ipl */
07700                } else {
07701                   tmp->ignorepats = ip->next;
07702                   ast_free(ip);
07703                   continue; /* don't change ipl */
07704                }
07705             }
07706             ipl = ip;
07707          }
07708          /* remove any includes whose registrar matches */
07709          for (i = tmp->includes; i; i = ni) {
07710             ni = i->next;
07711             if (strcmp(i->registrar, registrar) == 0) {
07712                /* remove from list */
07713                if (pi) {
07714                   pi->next = i->next;
07715                   /* free include */
07716                   ast_free(i);
07717                   continue; /* don't change pi */
07718                } else {
07719                   tmp->includes = i->next;
07720                   /* free include */
07721                   ast_free(i);
07722                   continue; /* don't change pi */
07723                }
07724             }
07725             pi = i;
07726          }
07727          /* remove any switches whose registrar matches */
07728          AST_LIST_TRAVERSE_SAFE_BEGIN(&tmp->alts, sw, list) {
07729             if (strcmp(sw->registrar,registrar) == 0) {
07730                AST_LIST_REMOVE_CURRENT(list);
07731                ast_free(sw);
07732             }
07733          }
07734          AST_LIST_TRAVERSE_SAFE_END;
07735 
07736          if (tmp->root_table) { /* it is entirely possible that the context is EMPTY */
07737             exten_iter = ast_hashtab_start_traversal(tmp->root_table);
07738             while ((exten_item=ast_hashtab_next(exten_iter))) {
07739                prio_iter = ast_hashtab_start_traversal(exten_item->peer_table);
07740                while ((prio_item=ast_hashtab_next(prio_iter))) {
07741                   if (!prio_item->registrar || strcmp(prio_item->registrar, registrar) != 0) {
07742                      continue;
07743                   }
07744                   ast_verb(3, "Remove %s/%s/%d, registrar=%s; con=%s(%p); con->root=%p\n",
07745                          tmp->name, prio_item->exten, prio_item->priority, registrar, con? con->name : "<nil>", con, con? con->root_table: NULL);
07746                   /* set matchcid to 1 to insure we get a direct match, and NULL registrar to make sure no wildcarding is done */
07747                   ast_context_remove_extension_callerid2(tmp, prio_item->exten, prio_item->priority, prio_item->cidmatch, 1, NULL, 1);
07748                }
07749                ast_hashtab_end_traversal(prio_iter);
07750             }
07751             ast_hashtab_end_traversal(exten_iter);
07752          }
07753    
07754          /* delete the context if it's registrar matches, is empty, has refcount of 1, */
07755          /* it's not empty, if it has includes, ignorepats, or switches that are registered from
07756             another registrar. It's not empty if there are any extensions */
07757          if (strcmp(tmp->registrar, registrar) == 0 && tmp->refcount < 2 && !tmp->root && !tmp->ignorepats && !tmp->includes && AST_LIST_EMPTY(&tmp->alts)) {
07758             ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar);
07759             ast_hashtab_remove_this_object(contexttab, tmp);
07760             
07761             next = tmp->next;
07762             if (tmpl)
07763                tmpl->next = next;
07764             else
07765                contexts = next;
07766             /* Okay, now we're safe to let it go -- in a sense, we were
07767                ready to let it go as soon as we locked it. */
07768             ast_unlock_context(tmp);
07769             __ast_internal_context_destroy(tmp);
07770          } else {
07771             ast_debug(1,"Couldn't delete ctx %s/%s; refc=%d; tmp.root=%p\n", tmp->name, tmp->registrar,
07772                     tmp->refcount, tmp->root);
07773             ast_unlock_context(tmp);
07774             next = tmp->next;
07775             tmpl = tmp;
07776          }
07777       } else if (con) {
07778          ast_verb(3, "Deleting context %s registrar=%s\n", tmp->name, tmp->registrar);
07779          ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar);
07780          ast_hashtab_remove_this_object(contexttab, tmp);
07781          
07782          next = tmp->next;
07783          if (tmpl)
07784             tmpl->next = next;
07785          else
07786             contexts = next;
07787          /* Okay, now we're safe to let it go -- in a sense, we were
07788             ready to let it go as soon as we locked it. */
07789          ast_unlock_context(tmp);
07790          __ast_internal_context_destroy(tmp);
07791       }
07792 
07793       /* if we have a specific match, we are done, otherwise continue */
07794       tmp = con ? NULL : next;
07795    }
07796 }

int __ast_custom_function_register ( struct ast_custom_function acf,
struct ast_module mod 
)

Register a custom function.

Definition at line 2792 of file pbx.c.

References 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_verb, COLOR_BRCYAN, LOG_ERROR, ast_custom_function::mod, ast_custom_function::name, and term_color().

Referenced by load_pbx().

02793 {
02794    struct ast_custom_function *cur;
02795    char tmps[80];
02796 
02797    if (!acf)
02798       return -1;
02799 
02800    acf->mod = mod;
02801 
02802    AST_RWLIST_WRLOCK(&acf_root);
02803 
02804    AST_RWLIST_TRAVERSE(&acf_root, cur, acflist) {
02805       if (!strcmp(acf->name, cur->name)) {
02806          ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name);
02807          AST_RWLIST_UNLOCK(&acf_root);
02808          return -1;
02809       }
02810    }
02811 
02812    /* Store in alphabetical order */
02813    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) {
02814       if (strcasecmp(acf->name, cur->name) < 0) {
02815          AST_RWLIST_INSERT_BEFORE_CURRENT(acf, acflist);
02816          break;
02817       }
02818    }
02819    AST_RWLIST_TRAVERSE_SAFE_END;
02820    if (!cur)
02821       AST_RWLIST_INSERT_TAIL(&acf_root, acf, acflist);
02822 
02823    AST_RWLIST_UNLOCK(&acf_root);
02824 
02825    ast_verb(2, "Registered custom function '%s'\n", term_color(tmps, acf->name, COLOR_BRCYAN, 0, sizeof(tmps)));
02826 
02827    return 0;
02828 }

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

Definition at line 8879 of file pbx.c.

References ast_async_goto(), ast_exists_extension(), ast_explicit_goto(), chan, ast_channel::cid, ast_callerid::cid_num, ast_channel::context, and ast_channel::exten.

Referenced by ast_async_goto_if_exists(), and ast_goto_if_exists().

08880 {
08881    int (*goto_func)(struct ast_channel *chan, const char *context, const char *exten, int priority);
08882 
08883    if (!chan)
08884       return -2;
08885 
08886    if (context == NULL)
08887       context = chan->context;
08888    if (exten == NULL)
08889       exten = chan->exten;
08890 
08891    goto_func = (async) ? ast_async_goto : ast_explicit_goto;
08892    if (ast_exists_extension(chan, context, exten, priority, chan->cid.cid_num))
08893       return goto_func(chan, context, exten, priority);
08894    else
08895       return -3;
08896 }

static void __ast_internal_context_destroy ( struct ast_context con  )  [static]

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

07613 {
07614    struct ast_include *tmpi;
07615    struct ast_sw *sw;
07616    struct ast_exten *e, *el, *en;
07617    struct ast_ignorepat *ipi;
07618    struct ast_context *tmp = con;
07619    
07620    for (tmpi = tmp->includes; tmpi; ) { /* Free includes */
07621       struct ast_include *tmpil = tmpi;
07622       tmpi = tmpi->next;
07623       ast_free(tmpil);
07624    }
07625    for (ipi = tmp->ignorepats; ipi; ) { /* Free ignorepats */
07626       struct ast_ignorepat *ipl = ipi;
07627       ipi = ipi->next;
07628       ast_free(ipl);
07629    }
07630    if (tmp->registrar)
07631       ast_free(tmp->registrar);
07632    
07633    /* destroy the hash tabs */
07634    if (tmp->root_table) {
07635       ast_hashtab_destroy(tmp->root_table, 0);
07636    }
07637    /* and destroy the pattern tree */
07638    if (tmp->pattern_tree)
07639       destroy_pattern_tree(tmp->pattern_tree);
07640    
07641    while ((sw = AST_LIST_REMOVE_HEAD(&tmp->alts, list)))
07642       ast_free(sw);
07643    for (e = tmp->root; e;) {
07644       for (en = e->peer; en;) {
07645          el = en;
07646          en = en->peer;
07647          destroy_exten(el);
07648       }
07649       el = e;
07650       e = e->next;
07651       destroy_exten(el);
07652    }
07653    tmp->root = NULL;
07654    ast_rwlock_destroy(&tmp->lock);
07655    ast_free(tmp);
07656 }

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

Definition at line 3691 of file pbx.c.

References ast_channel::_softhangup, ast_calloc, ast_check_hangup(), ast_copy_string(), ast_debug, 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::cid, ast_callerid::cid_num, ast_channel::context, ast_pbx::dtimeoutms, ast_channel::exten, LOG_WARNING, ast_channel::name, ast_channel::pbx, pbx_builtin_raise_exception(), ast_channel::priority, ast_pbx::rtimeoutms, set_ext_pri(), and ast_channel::whentohangup.

Referenced by ast_pbx_run_args(), and pbx_thread().

03693 {
03694    int found = 0; /* set if we find at least one match */
03695    int res = 0;
03696    int autoloopflag;
03697    int error = 0;    /* set an error conditions */
03698 
03699    /* A little initial setup here */
03700    if (c->pbx) {
03701       ast_log(LOG_WARNING, "%s already has PBX structure??\n", c->name);
03702       /* XXX and now what ? */
03703       ast_free(c->pbx);
03704    }
03705    if (!(c->pbx = ast_calloc(1, sizeof(*c->pbx))))
03706       return -1;
03707    /* Set reasonable defaults */
03708    c->pbx->rtimeoutms = 10000;
03709    c->pbx->dtimeoutms = 5000;
03710 
03711    autoloopflag = ast_test_flag(c, AST_FLAG_IN_AUTOLOOP);   /* save value to restore at the end */
03712    ast_set_flag(c, AST_FLAG_IN_AUTOLOOP);
03713 
03714    /* Start by trying whatever the channel is set to */
03715    if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) {
03716       /* If not successful fall back to 's' */
03717       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);
03718       /* XXX the original code used the existing priority in the call to
03719        * ast_exists_extension(), and reset it to 1 afterwards.
03720        * I believe the correct thing is to set it to 1 immediately.
03721        */
03722       set_ext_pri(c, "s", 1);
03723       if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) {
03724          /* JK02: And finally back to default if everything else failed */
03725          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);
03726          ast_copy_string(c->context, "default", sizeof(c->context));
03727       }
03728    }
03729    for (;;) {
03730       char dst_exten[256]; /* buffer to accumulate digits */
03731       int pos = 0;      /* XXX should check bounds */
03732       int digit = 0;
03733       int invalid = 0;
03734       int timeout = 0;
03735 
03736       /* loop on priorities in this context/exten */
03737       while ( !(res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num, &found,1))) {
03738          if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT && ast_exists_extension(c, c->context, "T", 1, c->cid.cid_num)) {
03739             set_ext_pri(c, "T", 0); /* 0 will become 1 with the c->priority++; at the end */
03740             /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
03741             memset(&c->whentohangup, 0, sizeof(c->whentohangup));
03742             c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT;
03743          } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT && ast_exists_extension(c, c->context, "e", 1, c->cid.cid_num)) {
03744             pbx_builtin_raise_exception(c, "ABSOLUTETIMEOUT");
03745             /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
03746             memset(&c->whentohangup, 0, sizeof(c->whentohangup));
03747             c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT;
03748          } else if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
03749             c->_softhangup = 0;
03750             continue;
03751          } else if (ast_check_hangup(c)) {
03752             ast_debug(1, "Extension %s, priority %d returned normally even though call was hung up\n",
03753                c->exten, c->priority);
03754             error = 1;
03755             break;
03756          }
03757          c->priority++;
03758       } /* end while  - from here on we can use 'break' to go out */
03759       if (found && res) {
03760          /* Something bad happened, or a hangup has been requested. */
03761          if (strchr("0123456789ABCDEF*#", res)) {
03762             ast_debug(1, "Oooh, got something to jump out with ('%c')!\n", res);
03763             pos = 0;
03764             dst_exten[pos++] = digit = res;
03765             dst_exten[pos] = '\0';
03766          } else if (res == AST_PBX_INCOMPLETE) {
03767             ast_debug(1, "Spawn extension (%s,%s,%d) exited INCOMPLETE on '%s'\n", c->context, c->exten, c->priority, c->name);
03768             ast_verb(2, "Spawn extension (%s, %s, %d) exited INCOMPLETE on '%s'\n", c->context, c->exten, c->priority, c->name);
03769 
03770             /* Don't cycle on incomplete - this will happen if the only extension that matches is our "incomplete" extension */
03771             if (!ast_matchmore_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) {
03772                invalid = 1;
03773             } else {
03774                ast_copy_string(dst_exten, c->exten, sizeof(dst_exten));
03775                digit = 1;
03776                pos = strlen(dst_exten);
03777             }
03778          } else {
03779             ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
03780             ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
03781             
03782             if ((res == AST_PBX_ERROR) && ast_exists_extension(c, c->context, "e", 1, c->cid.cid_num)) {
03783                /* if we are already on the 'e' exten, don't jump to it again */
03784                if (!strcmp(c->exten, "e")) {
03785                   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);
03786                   error = 1;
03787                } else {
03788                   pbx_builtin_raise_exception(c, "ERROR");
03789                   continue;
03790                }
03791             }
03792             
03793             if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
03794                c->_softhangup = 0;
03795                continue;
03796             } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT && ast_exists_extension(c, c->context, "T", 1, c->cid.cid_num)) {
03797                set_ext_pri(c, "T", 1); 
03798                /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
03799                memset(&c->whentohangup, 0, sizeof(c->whentohangup));
03800                c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT;
03801                continue;
03802             } else {
03803                if (c->cdr)
03804                   ast_cdr_update(c);
03805                error = 1;
03806                break;
03807             }
03808          }
03809       }
03810       if (error)
03811          break;
03812 
03813       /*!\note
03814        * We get here on a failure of some kind:  non-existing extension or
03815        * hangup.  We have options, here.  We can either catch the failure
03816        * and continue, or we can drop out entirely. */
03817 
03818       if (invalid || !ast_exists_extension(c, c->context, c->exten, 1, c->cid.cid_num)) {
03819          /*!\note
03820           * If there is no match at priority 1, it is not a valid extension anymore.
03821           * Try to continue at "i" (for invalid) or "e" (for exception) or exit if
03822           * neither exist.
03823           */
03824          if (ast_exists_extension(c, c->context, "i", 1, c->cid.cid_num)) {
03825             ast_verb(3, "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, c->name);
03826             pbx_builtin_setvar_helper(c, "INVALID_EXTEN", c->exten);
03827             set_ext_pri(c, "i", 1);
03828          } else if (ast_exists_extension(c, c->context, "e", 1, c->cid.cid_num)) {
03829             pbx_builtin_raise_exception(c, "INVALID");
03830          } else {
03831             ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n",
03832                c->name, c->exten, c->context);
03833             error = 1; /* we know what to do with it */
03834             break;
03835          }
03836       } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) {
03837          /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */
03838          c->_softhangup = 0;
03839       } else { /* keypress received, get more digits for a full extension */
03840          int waittime = 0;
03841          if (digit)
03842             waittime = c->pbx->dtimeoutms;
03843          else if (!autofallthrough)
03844             waittime = c->pbx->rtimeoutms;
03845          if (!waittime) {
03846             const char *status = pbx_builtin_getvar_helper(c, "DIALSTATUS");
03847             if (!status)
03848                status = "UNKNOWN";
03849             ast_verb(3, "Auto fallthrough, channel '%s' status is '%s'\n", c->name, status);
03850             if (!strcasecmp(status, "CONGESTION"))
03851                res = pbx_builtin_congestion(c, "10");
03852             else if (!strcasecmp(status, "CHANUNAVAIL"))
03853                res = pbx_builtin_congestion(c, "10");
03854             else if (!strcasecmp(status, "BUSY"))
03855                res = pbx_builtin_busy(c, "10");
03856             error = 1; /* XXX disable message */
03857             break;   /* exit from the 'for' loop */
03858          }
03859 
03860          if (collect_digits(c, waittime, dst_exten, sizeof(dst_exten), pos))
03861             break;
03862          if (res == AST_PBX_INCOMPLETE && ast_strlen_zero(&dst_exten[pos]))
03863             timeout = 1;
03864          if (!timeout && ast_exists_extension(c, c->context, dst_exten, 1, c->cid.cid_num)) /* Prepare the next cycle */
03865             set_ext_pri(c, dst_exten, 1);
03866          else {
03867             /* No such extension */
03868             if (!timeout && !ast_strlen_zero(dst_exten)) {
03869                /* An invalid extension */
03870                if (ast_exists_extension(c, c->context, "i", 1, c->cid.cid_num)) {
03871                   ast_verb(3, "Invalid extension '%s' in context '%s' on %s\n", dst_exten, c->context, c->name);
03872                   pbx_builtin_setvar_helper(c, "INVALID_EXTEN", dst_exten);
03873                   set_ext_pri(c, "i", 1);
03874                } else if (ast_exists_extension(c, c->context, "e", 1, c->cid.cid_num)) {
03875                   pbx_builtin_raise_exception(c, "INVALID");
03876                } else {
03877                   ast_log(LOG_WARNING, "Invalid extension '%s', but no rule 'i' in context '%s'\n", dst_exten, c->context);
03878                   found = 1; /* XXX disable message */
03879                   break;
03880                }
03881             } else {
03882                /* A simple timeout */
03883                if (ast_exists_extension(c, c->context, "t", 1, c->cid.cid_num)) {
03884                   ast_verb(3, "Timeout on %s\n", c->name);
03885                   set_ext_pri(c, "t", 1);
03886                } else if (ast_exists_extension(c, c->context, "e", 1, c->cid.cid_num)) {
03887                   pbx_builtin_raise_exception(c, "RESPONSETIMEOUT");
03888                } else {
03889                   ast_log(LOG_WARNING, "Timeout, but no rule 't' in context '%s'\n", c->context);
03890                   found = 1; /* XXX disable message */
03891                   break;
03892                }
03893             }
03894          }
03895          if (c->cdr) {
03896             ast_verb(2, "CDR updated on %s\n",c->name);
03897             ast_cdr_update(c);
03898          }
03899       }
03900    }
03901 
03902    if (!found && !error) {
03903       ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name);
03904    }
03905 
03906    if (!args || !args->no_hangup_chan) {
03907       ast_softhangup(c, c->hangupcause ? c->hangupcause : AST_CAUSE_NORMAL_CLEARING);
03908    }
03909 
03910    if ((!args || !args->no_hangup_chan) &&
03911          !ast_test_flag(c, AST_FLAG_BRIDGE_HANGUP_RUN) && 
03912          ast_exists_extension(c, c->context, "h", 1, c->cid.cid_num)) {
03913       set_ext_pri(c, "h", 1);
03914       if (c->cdr && ast_opt_end_cdr_before_h_exten) {
03915          ast_cdr_end(c->cdr);
03916       }
03917       while ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num, &found, 1)) == 0) {
03918          c->priority++;
03919       }
03920       if (found && res) {
03921          /* Something bad happened, or a hangup has been requested. */
03922          ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
03923          ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
03924       }
03925    }
03926    ast_set2_flag(c, autoloopflag, AST_FLAG_IN_AUTOLOOP);
03927    ast_clear_flag(c, AST_FLAG_BRIDGE_HANGUP_RUN); /* from one round to the next, make sure this gets cleared */
03928    pbx_destroy(c->pbx);
03929    c->pbx = NULL;
03930 
03931    if (!args || !args->no_hangup_chan) {
03932       ast_hangup(c);
03933    }
03934 
03935    return 0;
03936 }

static void __init_switch_data ( void   )  [static]

Definition at line 129 of file pbx.c.

00132 : An extension

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

Definition at line 1808 of file pbx.c.

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

Referenced by extension_match_core().

01809 {
01810    mode &= E_MATCH_MASK;   /* only consider the relevant bits */
01811    
01812 #ifdef NEED_DEBUG_HERE
01813    ast_log(LOG_NOTICE,"match core: pat: '%s', dat: '%s', mode=%d\n", pattern, data, (int)mode);
01814 #endif
01815    
01816    if ( (mode == E_MATCH) && (pattern[0] == '_') && (!strcasecmp(pattern,data)) ) { /* note: if this test is left out, then _x. will not match _x. !!! */
01817 #ifdef NEED_DEBUG_HERE
01818       ast_log(LOG_NOTICE,"return (1) - pattern matches pattern\n");
01819 #endif
01820       return 1;
01821    }
01822 
01823    if (pattern[0] != '_') { /* not a pattern, try exact or partial match */
01824       int ld = strlen(data), lp = strlen(pattern);
01825       
01826       if (lp < ld) {    /* pattern too short, cannot match */
01827 #ifdef NEED_DEBUG_HERE
01828          ast_log(LOG_NOTICE,"return (0) - pattern too short, cannot match\n");
01829 #endif
01830          return 0;
01831       }
01832       /* depending on the mode, accept full or partial match or both */
01833       if (mode == E_MATCH) {
01834 #ifdef NEED_DEBUG_HERE
01835          ast_log(LOG_NOTICE,"return (!strcmp(%s,%s) when mode== E_MATCH)\n", pattern, data);
01836 #endif
01837          return !strcmp(pattern, data); /* 1 on match, 0 on fail */
01838       } 
01839       if (ld == 0 || !strncasecmp(pattern, data, ld)) { /* partial or full match */
01840 #ifdef NEED_DEBUG_HERE
01841          ast_log(LOG_NOTICE,"return (mode(%d) == E_MATCHMORE ? lp(%d) > ld(%d) : 1)\n", mode, lp, ld);
01842 #endif
01843          return (mode == E_MATCHMORE) ? lp > ld : 1; /* XXX should consider '!' and '/' ? */
01844       } else {
01845 #ifdef NEED_DEBUG_HERE
01846          ast_log(LOG_NOTICE,"return (0) when ld(%d) > 0 && pattern(%s) != data(%s)\n", ld, pattern, data);
01847 #endif
01848          return 0;
01849       }
01850    }
01851    pattern++; /* skip leading _ */
01852    /*
01853     * XXX below we stop at '/' which is a separator for the CID info. However we should
01854     * not store '/' in the pattern at all. When we insure it, we can remove the checks.
01855     */
01856    while (*data && *pattern && *pattern != '/') {
01857       const char *end;
01858 
01859       if (*data == '-') { /* skip '-' in data (just a separator) */
01860          data++;
01861          continue;
01862       }
01863       switch (toupper(*pattern)) {
01864       case '[':   /* a range */
01865          end = strchr(pattern+1, ']'); /* XXX should deal with escapes ? */
01866          if (end == NULL) {
01867             ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n");
01868             return 0;   /* unconditional failure */
01869          }
01870          for (pattern++; pattern != end; pattern++) {
01871             if (pattern+2 < end && pattern[1] == '-') { /* this is a range */
01872                if (*data >= pattern[0] && *data <= pattern[2])
01873                   break;   /* match found */
01874                else {
01875                   pattern += 2; /* skip a total of 3 chars */
01876                   continue;
01877                }
01878             } else if (*data == pattern[0])
01879                break;   /* match found */
01880          }
01881          if (pattern == end) {
01882 #ifdef NEED_DEBUG_HERE
01883             ast_log(LOG_NOTICE,"return (0) when pattern==end\n");
01884 #endif
01885             return 0;
01886          }
01887          pattern = end; /* skip and continue */
01888          break;
01889       case 'N':
01890          if (*data < '2' || *data > '9') {
01891 #ifdef NEED_DEBUG_HERE
01892             ast_log(LOG_NOTICE,"return (0) N is matched\n");
01893 #endif
01894             return 0;
01895          }
01896          break;
01897       case 'X':
01898          if (*data < '0' || *data > '9') {
01899 #ifdef NEED_DEBUG_HERE
01900             ast_log(LOG_NOTICE,"return (0) X is matched\n");
01901 #endif
01902             return 0;
01903          }
01904          break;
01905       case 'Z':
01906          if (*data < '1' || *data > '9') {
01907 #ifdef NEED_DEBUG_HERE
01908             ast_log(LOG_NOTICE,"return (0) Z is matched\n");
01909 #endif
01910             return 0;
01911          }
01912          break;
01913       case '.':   /* Must match, even with more digits */
01914 #ifdef NEED_DEBUG_HERE
01915          ast_log(LOG_NOTICE,"return (1) when '.' is matched\n");
01916 #endif
01917          return 1;
01918       case '!':   /* Early match */
01919 #ifdef NEED_DEBUG_HERE
01920          ast_log(LOG_NOTICE,"return (2) when '!' is matched\n");
01921 #endif
01922          return 2;
01923       case ' ':
01924       case '-':   /* Ignore these in patterns */
01925          data--; /* compensate the final data++ */
01926          break;
01927       default:
01928          if (*data != *pattern) {
01929 #ifdef NEED_DEBUG_HERE
01930             ast_log(LOG_NOTICE,"return (0) when *data(%c) != *pattern(%c)\n", *data, *pattern);
01931 #endif
01932             return 0;
01933          }
01934          
01935       }
01936       data++;
01937       pattern++;
01938    }
01939    if (*data)        /* data longer than pattern, no match */ {
01940 #ifdef NEED_DEBUG_HERE
01941       ast_log(LOG_NOTICE,"return (0) when data longer than pattern\n");
01942 #endif
01943       return 0;
01944    }
01945    
01946    /*
01947     * match so far, but ran off the end of the data.
01948     * Depending on what is next, determine match or not.
01949     */
01950    if (*pattern == '\0' || *pattern == '/') {   /* exact match */
01951 #ifdef NEED_DEBUG_HERE
01952       ast_log(LOG_NOTICE,"at end, return (%d) in 'exact match'\n", (mode==E_MATCHMORE) ? 0 : 1);
01953 #endif
01954       return (mode == E_MATCHMORE) ? 0 : 1;  /* this is a failure for E_MATCHMORE */
01955    } else if (*pattern == '!')   {     /* early match */
01956 #ifdef NEED_DEBUG_HERE
01957       ast_log(LOG_NOTICE,"at end, return (2) when '!' is matched\n");
01958 #endif
01959       return 2;
01960    } else {                /* partial match */
01961 #ifdef NEED_DEBUG_HERE
01962       ast_log(LOG_NOTICE,"at end, return (%d) which deps on E_MATCH\n", (mode == E_MATCH) ? 0 : 1);
01963 #endif
01964       return (mode == E_MATCH) ? 0 : 1;   /* this is a failure for E_MATCH */
01965    }
01966 }

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

Definition at line 2609 of file pbx.c.

References ast_channel_datastore_find(), ast_copy_string(), chan, pbx_exception::context, ast_datastore::data, exception_store_info, pbx_exception::exten, pbx_exception::priority, and pbx_exception::reason.

02610 {
02611    struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL);
02612    struct pbx_exception *exception = NULL;
02613    if (!ds || !ds->data)
02614       return -1;
02615    exception = ds->data;
02616    if (!strcasecmp(data, "REASON"))
02617       ast_copy_string(buf, exception->reason, buflen);
02618    else if (!strcasecmp(data, "CONTEXT"))
02619       ast_copy_string(buf, exception->context, buflen);
02620    else if (!strncasecmp(data, "EXTEN", 5))
02621       ast_copy_string(buf, exception->exten, buflen);
02622    else if (!strcasecmp(data, "PRIORITY"))
02623       snprintf(buf, buflen, "%d", exception->priority);
02624    else
02625       return -1;
02626    return 0;
02627 }

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

Definition at line 1475 of file pbx.c.

References add_pattern_node(), already_in_tree(), ast_copy_string(), ast_log(), buf, ast_exten::cidmatch, compare_char(), ast_exten::exten, LOG_DEBUG, LOG_ERROR, LOG_WARNING, m1, m2, ast_exten::matchcid, and ast_context::pattern_tree.

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

01476 {
01477    struct match_char *m1 = NULL, *m2 = NULL, **m0;
01478    int specif;
01479    int already;
01480    int pattern = 0;
01481    char buf[256];
01482    char extenbuf[512];
01483    char *s1 = extenbuf;
01484    int l1 = strlen(e1->exten) + strlen(e1->cidmatch) + 2;
01485    
01486 
01487    ast_copy_string(extenbuf, e1->exten, sizeof(extenbuf));
01488 
01489    if (e1->matchcid &&  l1 <= sizeof(extenbuf)) {
01490       strcat(extenbuf,"/");
01491       strcat(extenbuf,e1->cidmatch);
01492    } else if (l1 > sizeof(extenbuf)) {
01493       ast_log(LOG_ERROR,"The pattern %s/%s is too big to deal with: it will be ignored! Disaster!\n", e1->exten, e1->cidmatch);
01494       return 0;
01495    }
01496 #ifdef NEED_DEBUG
01497    ast_log(LOG_DEBUG,"Adding exten %s%c%s to tree\n", s1, e1->matchcid? '/':' ', e1->matchcid? e1->cidmatch : "");
01498 #endif
01499    m1 = con->pattern_tree; /* each pattern starts over at the root of the pattern tree */
01500    m0 = &con->pattern_tree;
01501    already = 1;
01502 
01503    if ( *s1 == '_') {
01504       pattern = 1;
01505       s1++;
01506    }
01507    while( *s1 ) {
01508       if (pattern && *s1 == '[' && *(s1-1) != '\\') {
01509          char *s2 = buf;
01510          buf[0] = 0;
01511          s1++; /* get past the '[' */
01512          while (*s1 != ']' && *(s1-1) != '\\' ) {
01513             if (*s1 == '\\') {
01514                if (*(s1+1) == ']') {
01515                   *s2++ = ']';
01516                   s1++;s1++;
01517                } else if (*(s1+1) == '\\') {
01518                   *s2++ = '\\';
01519                   s1++;s1++;
01520                } else if (*(s1+1) == '-') {
01521                   *s2++ = '-';
01522                   s1++; s1++;
01523                } else if (*(s1+1) == '[') {
01524                   *s2++ = '[';
01525                   s1++; s1++;
01526                }
01527             } else if (*s1 == '-') { /* remember to add some error checking to all this! */
01528                char s3 = *(s1-1);
01529                char s4 = *(s1+1);
01530                for (s3++; s3 <= s4; s3++) {
01531                   *s2++ = s3;
01532                }
01533                s1++; s1++;
01534             } else if (*s1 == '\0') {
01535                ast_log(LOG_WARNING, "A matching ']' was not found for '[' in pattern string '%s'\n", extenbuf);
01536                break;
01537             } else {
01538                *s2++ = *s1++;
01539             }
01540          }
01541          *s2 = 0; /* null terminate the exploded range */
01542          /* sort the characters */
01543 
01544          specif = strlen(buf);
01545          qsort(buf, specif, 1, compare_char);
01546          specif <<= 8;
01547          specif += buf[0];
01548       } else {
01549          
01550          if (*s1 == '\\') {
01551             s1++;
01552             buf[0] = *s1;
01553          } else {
01554             if (pattern) {
01555                if (*s1 == 'n') /* make sure n,x,z patterns are canonicalized to N,X,Z */
01556                   *s1 = 'N';
01557                else if (*s1 == 'x')
01558                   *s1 = 'X';
01559                else if (*s1 == 'z')
01560                   *s1 = 'Z';
01561             }
01562             buf[0] = *s1;
01563          }
01564          buf[1] = 0;
01565          specif = 1;
01566       }
01567       m2 = 0;
01568       if (already && (m2=already_in_tree(m1,buf)) && m2->next_char) {
01569          if (!(*(s1+1))) {  /* if this is the end of the pattern, but not the end of the tree, then mark this node with the exten...
01570                         a shorter pattern might win if the longer one doesn't match */
01571             m2->exten = e1;
01572             m2->deleted = 0;
01573          }
01574          m1 = m2->next_char; /* m1 points to the node to compare against */
01575          m0 = &m2->next_char; /* m0 points to the ptr that points to m1 */
01576       } else { /* not already OR not m2 OR nor m2->next_char */
01577          if (m2) {
01578             if (findonly)
01579                return m2;
01580             m1 = m2; /* while m0 stays the same */
01581          } else {
01582             if (findonly)
01583                return m1;
01584             m1 = add_pattern_node(con, m1, buf, pattern, already,specif, m0); /* m1 is the node just added */
01585             m0 = &m1->next_char;
01586          }
01587          
01588          if (!(*(s1+1))) {
01589             m1->deleted = 0;
01590             m1->exten = e1;
01591          }
01592          
01593          already = 0;
01594       }
01595       s1++; /* advance to next char */
01596    }
01597    return m1;
01598 }

static struct match_char * add_pattern_node ( struct ast_context con,
struct match_char current,
char *  pattern,
int  is_pattern,
int  already,
int  specificity,
struct match_char **  parent 
) [static]

Definition at line 1434 of file pbx.c.

References ast_calloc, ast_free, ast_strdup, insert_in_next_chars_alt_char_list(), match_char::next_char, and ast_context::pattern_tree.

Referenced by add_exten_to_pattern_tree().

01435 {
01436    struct match_char *m;
01437    
01438    if (!(m = ast_calloc(1, sizeof(*m))))
01439       return NULL;
01440 
01441    if (!(m->x = ast_strdup(pattern))) {
01442       ast_free(m);
01443       return NULL;
01444    }
01445 
01446    /* the specificity scores are the same as used in the old
01447       pattern matcher. */
01448    m->is_pattern = is_pattern;
01449    if (specificity == 1 && is_pattern && pattern[0] == 'N')
01450       m->specificity = 0x0802;
01451    else if (specificity == 1 && is_pattern && pattern[0] == 'Z')
01452       m->specificity = 0x0901;
01453    else if (specificity == 1 && is_pattern && pattern[0] == 'X')
01454       m->specificity = 0x0a00;
01455    else if (specificity == 1 && is_pattern && pattern[0] == '.')
01456       m->specificity = 0x10000;
01457    else if (specificity == 1 && is_pattern && pattern[0] == '!')
01458       m->specificity = 0x20000;
01459    else
01460       m->specificity = specificity;
01461    
01462    if (!con->pattern_tree) {
01463       insert_in_next_chars_alt_char_list(&con->pattern_tree, m);
01464    } else {
01465       if (already) { /* switch to the new regime (traversing vs appending)*/
01466          insert_in_next_chars_alt_char_list(nextcharptr, m);
01467       } else {
01468          insert_in_next_chars_alt_char_list(&current->next_char, m);
01469       }
01470    }
01471 
01472    return m;
01473 }

static int add_pri ( 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 6825 of file pbx.c.

References add_pri_lockopt(), and el.

Referenced by ast_add_extension2_lockopt().

06827 {
06828    return add_pri_lockopt(con, tmp, el, e, replace, 1);
06829 }

static int add_pri_lockopt ( struct ast_context con,
struct ast_exten tmp,
struct ast_exten el,
struct ast_exten e,
int  replace,
int  lockhints 
) [static]

add the extension in the priority chain.

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

Definition at line 6836 of file pbx.c.

References ast_hashtab_insert_safe(), ast_exten::label, ast_exten::peer, ast_exten::peer_label_table, ast_exten::peer_table, and ast_exten::priority.

Referenced by add_pri().

06838 {
06839    struct ast_exten *ep;
06840    struct ast_exten *eh=e;
06841 
06842    for (ep = NULL; e ; ep = e, e = e->peer) {
06843       if (e->priority >= tmp->priority)
06844          break;
06845    }
06846    if (!e) {   /* go at the end, and ep is surely set because the list is not empty */
06847       ast_hashtab_insert_safe(eh->peer_table, tmp);
06848       
06849       if (tmp->label) {
06850          ast_hashtab_insert_safe(eh->peer_label_table, tmp);
06851       }
06852       ep->peer = tmp;
06853       return 0;   /* success */
06854    }
06855    if (e->priority == tmp->priority) {
06856       /* Can't have something exactly the same.  Is this a
06857          replacement?  If so, replace, otherwise, bonk. */
06858       if (!replace) {
06859          ast_log(LOG_WARNING, "Unable to register extension '%s', priority %d in '%s', already in use\n", tmp->exten, tmp->priority, con->name);
06860          if (tmp->datad) {
06861             tmp->datad(tmp->data);
06862             /* if you free this, null it out */
06863             tmp->data = NULL;
06864          }
06865          
06866          ast_free(tmp);
06867          return -1;
06868       }
06869       /* we are replacing e, so copy the link fields and then update
06870        * whoever pointed to e to point to us
06871        */
06872       tmp->next = e->next; /* not meaningful if we are not first in the peer list */
06873       tmp->peer = e->peer; /* always meaningful */
06874       if (ep)  {     /* We're in the peer list, just insert ourselves */
06875          ast_hashtab_remove_object_via_lookup(eh->peer_table,e);
06876 
06877          if (e->label) {
06878             ast_hashtab_remove_object_via_lookup(eh->peer_label_table,e);
06879          }
06880          
06881          ast_hashtab_insert_safe(eh->peer_table,tmp);
06882          if (tmp->label) {
06883             ast_hashtab_insert_safe(eh->peer_label_table,tmp);
06884          }
06885          
06886          ep->peer = tmp;
06887       } else if (el) {     /* We're the first extension. Take over e's functions */
06888          struct match_char *x = add_exten_to_pattern_tree(con, e, 1);
06889          tmp->peer_table = e->peer_table;
06890          tmp->peer_label_table = e->peer_label_table;
06891          ast_hashtab_remove_object_via_lookup(tmp->peer_table,e);
06892          ast_hashtab_insert_safe(tmp->peer_table,tmp);
06893          if (e->label) {
06894             ast_hashtab_remove_object_via_lookup(tmp->peer_label_table, e);
06895          }
06896          if (tmp->label) {
06897             ast_hashtab_insert_safe(tmp->peer_label_table, tmp);
06898          }
06899          
06900          ast_hashtab_remove_object_via_lookup(con->root_table, e);
06901          ast_hashtab_insert_safe(con->root_table, tmp);
06902          el->next = tmp;
06903          /* The pattern trie points to this exten; replace the pointer,
06904             and all will be well */
06905          if (x) { /* if the trie isn't formed yet, don't sweat this */
06906             if (x->exten) { /* this test for safety purposes */
06907                x->exten = tmp; /* replace what would become a bad pointer */
06908             } else {
06909                ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n");
06910             }
06911          }
06912       } else {       /* We're the very first extension.  */
06913          struct match_char *x = add_exten_to_pattern_tree(con, e, 1);
06914          ast_hashtab_remove_object_via_lookup(con->root_table, e);
06915          ast_hashtab_insert_safe(con->root_table, tmp);
06916          tmp->peer_table = e->peer_table;
06917          tmp->peer_label_table = e->peer_label_table;
06918          ast_hashtab_remove_object_via_lookup(tmp->peer_table, e);
06919          ast_hashtab_insert_safe(tmp->peer_table, tmp);
06920          if (e->label) {
06921             ast_hashtab_remove_object_via_lookup(tmp->peer_label_table, e);
06922          }
06923          if (tmp->label) {
06924             ast_hashtab_insert_safe(tmp->peer_label_table, tmp);
06925          }
06926          
06927          ast_hashtab_remove_object_via_lookup(con->root_table, e);
06928          ast_hashtab_insert_safe(con->root_table, tmp);
06929          con->root = tmp;
06930          /* The pattern trie points to this exten; replace the pointer,
06931             and all will be well */
06932          if (x) { /* if the trie isn't formed yet; no problem */
06933             if (x->exten) { /* this test for safety purposes */
06934                x->exten = tmp; /* replace what would become a bad pointer */
06935             } else {
06936                ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n");
06937             }
06938          }
06939       }
06940       if (tmp->priority == PRIORITY_HINT)
06941          ast_change_hint(e,tmp);
06942       /* Destroy the old one */
06943       if (e->datad)
06944          e->datad(e->data);
06945       ast_free(e);
06946    } else { /* Slip ourselves in just before e */
06947       tmp->peer = e;
06948       tmp->next = e->next; /* extension chain, or NULL if e is not the first extension */
06949       if (ep) {         /* Easy enough, we're just in the peer list */
06950          if (tmp->label) {
06951             ast_hashtab_insert_safe(eh->peer_label_table, tmp);
06952          }
06953          ast_hashtab_insert_safe(eh->peer_table, tmp);
06954          ep->peer = tmp;
06955       } else {       /* we are the first in some peer list, so link in the ext list */
06956          tmp->peer_table = e->peer_table;
06957          tmp->peer_label_table = e->peer_label_table;
06958          e->peer_table = 0;
06959          e->peer_label_table = 0;
06960          ast_hashtab_insert_safe(tmp->peer_table, tmp);
06961          if (tmp->label) {
06962             ast_hashtab_insert_safe(tmp->peer_label_table, tmp);
06963          }
06964          ast_hashtab_remove_object_via_lookup(con->root_table, e);
06965          ast_hashtab_insert_safe(con->root_table, tmp);
06966          if (el)
06967             el->next = tmp;   /* in the middle... */
06968          else
06969             con->root = tmp; /* ... or at the head */
06970          e->next = NULL;   /* e is no more at the head, so e->next must be reset */
06971       }
06972       /* And immediately return success. */
06973       if (tmp->priority == PRIORITY_HINT) {
06974          if (lockhints) {
06975             ast_add_hint(tmp);
06976          } else {
06977             ast_add_hint_nolock(tmp);
06978          }
06979       }
06980    }
06981    return 0;
06982 }

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

Definition at line 1382 of file pbx.c.

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

Referenced by add_exten_to_pattern_tree().

01383 {
01384    struct match_char *t;
01385 
01386    if (!current)
01387       return 0;
01388 
01389    for (t = current; t; t = t->alt_char) {
01390       if (!strcmp(pat, t->x)) /* uh, we may want to sort exploded [] contents to make matching easy */
01391          return t;
01392    }
01393 
01394    return 0;
01395 }

int ast_active_calls ( void   ) 

Retrieve the number of active calls.

Definition at line 4074 of file pbx.c.

References countcalls.

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

04075 {
04076    return countcalls;
04077 }

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

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

Referenced by ast_extension_state_add(), handle_cli_dialplan_add_extension(), park_add_hints(), register_exten(), register_peer_exten(), and RegisterExtension().

06694 {
06695    int ret = -1;
06696    struct ast_context *c = find_context_locked(context);
06697 
06698    if (c) {
06699       ret = ast_add_extension2(c, replace, extension, priority, label, callerid,
06700          application, data, datad, registrar);
06701       ast_unlock_contexts();
06702    }
06703    
06704    return ret;
06705 }

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

References ast_add_extension2_lockopt().

Referenced by ast_add_extension(), ast_park_call_full(), build_parkinglot(), context_merge(), load_module(), manage_parkinglot(), pbx_load_config(), and pbx_load_users().

07013 {
07014    return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid, application, data, datad, registrar, 1, 1);
07015 }

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  lockconts,
int  lockhints 
) [static]

Does all the work of ast_add_extension2, but adds two args, to determine if context and hint locking should be done. In merge_and_delete, we need to do this without locking, as the locks are already held.

Definition at line 7022 of file pbx.c.

References add_exten_to_pattern_tree(), add_pri(), ast_exten::app, ast_add_hint(), ast_add_hint_nolock(), ast_calloc, ast_copy_string(), ast_debug, 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().

07026 {
07027    /*
07028     * Sort extensions (or patterns) according to the rules indicated above.
07029     * These are implemented by the function ext_cmp()).
07030     * All priorities for the same ext/pattern/cid are kept in a list,
07031     * using the 'peer' field  as a link field..
07032     */
07033    struct ast_exten *tmp, *tmp2, *e, *el = NULL;
07034    int res;
07035    int length;
07036    char *p;
07037    char expand_buf[VAR_BUF_SIZE];
07038    struct ast_exten dummy_exten = {0};
07039    char dummy_name[1024];
07040 
07041    if (ast_strlen_zero(extension)) {
07042       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",
07043             con->name);
07044       return -1;
07045    }
07046    
07047    /* If we are adding a hint evalulate in variables and global variables */
07048    if (priority == PRIORITY_HINT && strstr(application, "${") && !strstr(extension, "_")) {
07049       struct ast_channel c = {0, };
07050 
07051       ast_copy_string(c.exten, extension, sizeof(c.exten));
07052       ast_copy_string(c.context, con->name, sizeof(c.context));
07053       pbx_substitute_variables_helper(&c, application, expand_buf, sizeof(expand_buf));
07054       application = expand_buf;
07055    }
07056 
07057    length = sizeof(struct ast_exten);
07058    length += strlen(extension) + 1;
07059    length += strlen(application) + 1;
07060    if (label)
07061       length += strlen(label) + 1;
07062    if (callerid)
07063       length += strlen(callerid) + 1;
07064    else
07065       length ++;  /* just the '\0' */
07066 
07067    /* Be optimistic:  Build the extension structure first */
07068    if (!(tmp = ast_calloc(1, length)))
07069       return -1;
07070 
07071    if (ast_strlen_zero(label)) /* let's turn empty labels to a null ptr */
07072       label = 0;
07073 
07074    /* use p as dst in assignments, as the fields are const char * */
07075    p = tmp->stuff;
07076    if (label) {
07077       tmp->label = p;
07078       strcpy(p, label);
07079       p += strlen(label) + 1;
07080    }
07081    tmp->exten = p;
07082    p += ext_strncpy(p, extension, strlen(extension) + 1) + 1;
07083    tmp->priority = priority;
07084    tmp->cidmatch = p;   /* but use p for assignments below */
07085    if (!ast_strlen_zero(callerid)) {
07086       p += ext_strncpy(p, callerid, strlen(callerid) + 1) + 1;
07087       tmp->matchcid = 1;
07088    } else {
07089       *p++ = '\0';
07090       tmp->matchcid = 0;
07091    }
07092    tmp->app = p;
07093    strcpy(p, application);
07094    tmp->parent = con;
07095    tmp->data = data;
07096    tmp->datad = datad;
07097    tmp->registrar = registrar;
07098 
07099    if (lockconts) {
07100       ast_wrlock_context(con);
07101    }
07102    
07103    if (con->pattern_tree) { /* usually, on initial load, the pattern_tree isn't formed until the first find_exten; so if we are adding
07104                         an extension, and the trie exists, then we need to incrementally add this pattern to it. */
07105       ast_copy_string(dummy_name, extension, sizeof(dummy_name));
07106       dummy_exten.exten = dummy_name;
07107       dummy_exten.matchcid = 0;
07108       dummy_exten.cidmatch = 0;
07109       tmp2 = ast_hashtab_lookup(con->root_table, &dummy_exten);
07110       if (!tmp2) {
07111          /* hmmm, not in the trie; */
07112          add_exten_to_pattern_tree(con, tmp, 0);
07113          ast_hashtab_insert_safe(con->root_table, tmp); /* for the sake of completeness */
07114       }
07115    }
07116    res = 0; /* some compilers will think it is uninitialized otherwise */
07117    for (e = con->root; e; el = e, e = e->next) {   /* scan the extension list */
07118       res = ext_cmp(e->exten, tmp->exten);
07119       if (res == 0) { /* extension match, now look at cidmatch */
07120          if (!e->matchcid && !tmp->matchcid)
07121             res = 0;
07122          else if (tmp->matchcid && !e->matchcid)
07123             res = 1;
07124          else if (e->matchcid && !tmp->matchcid)
07125             res = -1;
07126          else
07127             res = strcasecmp(e->cidmatch, tmp->cidmatch);
07128       }
07129       if (res >= 0)
07130          break;
07131    }
07132    if (e && res == 0) { /* exact match, insert in the pri chain */
07133       res = add_pri(con, tmp, el, e, replace);
07134       if (lockconts) {
07135          ast_unlock_context(con);
07136       }
07137       if (res < 0) {
07138          errno = EEXIST;   /* XXX do we care ? */
07139          return 0; /* XXX should we return -1 maybe ? */
07140       }
07141    } else {
07142       /*
07143        * not an exact match, this is the first entry with this pattern,
07144        * so insert in the main list right before 'e' (if any)
07145        */
07146       tmp->next = e;
07147       if (el) {  /* there is another exten already in this context */
07148          el->next = tmp;
07149          tmp->peer_table = ast_hashtab_create(13,
07150                      hashtab_compare_exten_numbers,
07151                      ast_hashtab_resize_java,
07152                      ast_hashtab_newsize_java,
07153                      hashtab_hash_priority,
07154                      0);
07155          tmp->peer_label_table = ast_hashtab_create(7,
07156                         hashtab_compare_exten_labels,
07157                         ast_hashtab_resize_java,
07158                         ast_hashtab_newsize_java,
07159                         hashtab_hash_labels,
07160                         0);
07161          if (label) {
07162             ast_hashtab_insert_safe(tmp->peer_label_table, tmp);
07163          }
07164          ast_hashtab_insert_safe(tmp->peer_table, tmp);
07165       } else {  /* this is the first exten in this context */
07166          if (!con->root_table)
07167             con->root_table = ast_hashtab_create(27,
07168                                        hashtab_compare_extens,
07169                                        ast_hashtab_resize_java,
07170                                        ast_hashtab_newsize_java,
07171                                        hashtab_hash_extens,
07172                                        0);
07173          con->root = tmp;
07174          con->root->peer_table = ast_hashtab_create(13,
07175                         hashtab_compare_exten_numbers,
07176                         ast_hashtab_resize_java,
07177                         ast_hashtab_newsize_java,
07178                         hashtab_hash_priority,
07179                         0);
07180          con->root->peer_label_table = ast_hashtab_create(7,
07181                            hashtab_compare_exten_labels,
07182                            ast_hashtab_resize_java,
07183                            ast_hashtab_newsize_java,
07184                            hashtab_hash_labels,
07185                            0);
07186          if (label) {
07187             ast_hashtab_insert_safe(con->root->peer_label_table, tmp);
07188          }
07189          ast_hashtab_insert_safe(con->root->peer_table, tmp);
07190             
07191       }
07192       ast_hashtab_insert_safe(con->root_table, tmp);
07193       if (lockconts) {
07194          ast_unlock_context(con);
07195       }
07196       if (tmp->priority == PRIORITY_HINT) {
07197          if (lockhints) {
07198             ast_add_hint(tmp);
07199          } else {
07200             ast_add_hint_nolock(tmp);
07201          }
07202       }
07203    }
07204    if (option_debug) {
07205       if (tmp->matchcid) {
07206          ast_debug(1, "Added extension '%s' priority %d (CID match '%s') to %s (%p)\n",
07207                  tmp->exten, tmp->priority, tmp->cidmatch, con->name, con);
07208       } else {
07209          ast_debug(1, "Added extension '%s' priority %d to %s (%p)\n",
07210                  tmp->exten, tmp->priority, con->name, con);
07211       }
07212    }
07213 
07214    if (tmp->matchcid) {
07215       ast_verb(3, "Added extension '%s' priority %d (CID match '%s') to %s (%p)\n",
07216              tmp->exten, tmp->priority, tmp->cidmatch, con->name, con);
07217    } else {
07218       ast_verb(3, "Added extension '%s' priority %d to %s (%p)\n",
07219              tmp->exten, tmp->priority, con->name, con);
07220    }
07221    
07222    return 0;
07223 }

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

References ast_add_extension2_lockopt(), and find_context().

Referenced by ast_merge_contexts_and_delete().

06675 {
06676    int ret = -1;
06677    struct ast_context *c = find_context(context);
06678 
06679    if (c) {
06680       ret = ast_add_extension2_lockopt(c, replace, extension, priority, label, callerid,
06681          application, data, datad, registrar, 0, 0);
06682    }
06683    
06684    return ret;
06685 }

static int ast_add_hint ( struct ast_exten e  )  [static]

Add hint to hint list, check initial extension state.

Definition at line 3538 of file pbx.c.

References ast_add_hint_nolock(), AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

Referenced by ast_add_extension2_lockopt().

03539 {
03540    int ret;
03541 
03542    AST_RWLIST_WRLOCK(&hints);
03543    ret = ast_add_hint_nolock(e);
03544    AST_RWLIST_UNLOCK(&hints);
03545    
03546    return ret;
03547 }

static int ast_add_hint_nolock ( struct ast_exten e  )  [static]

Add hint to hint list, check initial extension state; the hints had better be WRLOCKED already!

Definition at line 3509 of file pbx.c.

References ast_calloc, ast_debug, ast_extension_state2(), ast_get_extension_app(), ast_get_extension_name(), AST_RWLIST_INSERT_HEAD, AST_RWLIST_TRAVERSE, ast_hint::exten, and ast_hint::list.

Referenced by ast_add_extension2_lockopt(), and ast_add_hint().

03510 {
03511    struct ast_hint *hint;
03512 
03513    if (!e)
03514       return -1;
03515 
03516    /* Search if hint exists, do nothing */
03517    AST_RWLIST_TRAVERSE(&hints, hint, list) {
03518       if (hint->exten == e) {
03519          ast_debug(2, "HINTS: Not re-adding existing hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e));
03520          return -1;
03521       }
03522    }
03523 
03524    ast_debug(2, "HINTS: Adding hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e));
03525 
03526    if (!(hint = ast_calloc(1, sizeof(*hint)))) {
03527       return -1;
03528    }
03529    /* Initialize and insert new item at the top */
03530    hint->exten = e;
03531    hint->laststate = ast_extension_state2(e);
03532    AST_RWLIST_INSERT_HEAD(&hints, hint, list);
03533 
03534    return 0;
03535 }

int ast_async_goto ( struct ast_channel chan,
const char *  context,
const char *  exten,
int  priority 
)

Definition at line 6730 of file pbx.c.

References ast_channel::_state, ast_channel::accountcode, ast_channel::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_channel::cdr, chan, ast_channel::context, ast_channel::exten, 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_dtmfup(), handle_request_bye(), handle_request_refer(), pbx_parseable_goto(), process_ast_dsp(), and socket_process().

06731 {
06732    int res = 0;
06733 
06734    ast_channel_lock(chan);
06735 
06736    if (chan->pbx) { /* This channel is currently in the PBX */
06737       ast_explicit_goto(chan, context, exten, priority + 1);
06738       ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO);
06739    } else {
06740       /* In order to do it when the channel doesn't really exist within
06741          the PBX, we have to make a new channel, masquerade, and start the PBX
06742          at the new location */
06743       struct ast_channel *tmpchan = ast_channel_alloc(0, chan->_state, 0, 0, chan->accountcode, chan->exten, chan->context, chan->amaflags, "AsyncGoto/%s", chan->name);
06744       if (!tmpchan) {
06745          res = -1;
06746       } else {
06747          if (chan->cdr) {
06748             ast_cdr_discard(tmpchan->cdr);
06749             tmpchan->cdr = ast_cdr_dup(chan->cdr);  /* share the love */
06750          }
06751          /* Make formats okay */
06752          tmpchan->readformat = chan->readformat;
06753          tmpchan->writeformat = chan->writeformat;
06754          /* Setup proper location */
06755          ast_explicit_goto(tmpchan,
06756             S_OR(context, chan->context), S_OR(exten, chan->exten), priority);
06757 
06758          /* Masquerade into temp channel */
06759          if (ast_channel_masquerade(tmpchan, chan)) {
06760             /* Failed to set up the masquerade.  It's probably chan_local
06761              * in the middle of optimizing itself out.  Sad. :( */
06762             ast_hangup(tmpchan);
06763             tmpchan = NULL;
06764             res = -1;
06765          } else {
06766             /* Grab the locks and get going */
06767             ast_channel_lock(tmpchan);
06768             ast_do_masquerade(tmpchan);
06769             ast_channel_unlock(tmpchan);
06770             /* Start the PBX going on our stolen channel */
06771             if (ast_pbx_start(tmpchan)) {
06772                ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name);
06773                ast_hangup(tmpchan);
06774                res = -1;
06775             }
06776          }
06777       }
06778    }
06779    ast_channel_unlock(chan);
06780    return res;
06781 }

int ast_async_goto_by_name ( const char *  channame,
const char *  context,
const char *  exten,
int  priority 
)

Definition at line 6783 of file pbx.c.

References ast_async_goto(), ast_channel_unlock, ast_get_channel_by_name_locked(), and chan.

06784 {
06785    struct ast_channel *chan;
06786    int res = -1;
06787 
06788    chan = ast_get_channel_by_name_locked(channame);
06789    if (chan) {
06790       res = ast_async_goto(chan, context, exten, priority);
06791       ast_channel_unlock(chan);
06792    }
06793    return res;
06794 }

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

References __ast_goto_if_exists(), and chan.

08904 {
08905    return __ast_goto_if_exists(chan, context, exten, priority, 1);
08906 }

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

References chan, and pbx_parseable_goto().

Referenced by asyncgoto_exec().

08967 {
08968    return pbx_parseable_goto(chan, goto_string, 1);
08969 }

int ast_build_timing ( struct ast_timing i,
const char *  info_in 
)

Definition at line 6351 of file pbx.c.

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

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

06352 {
06353    char info_save[256];
06354    char *info;
06355 
06356    /* Check for empty just in case */
06357    if (ast_strlen_zero(info_in))
06358       return 0;
06359    /* make a copy just in case we were passed a static string */
06360    ast_copy_string(info_save, info_in, sizeof(info_save));
06361    info = info_save;
06362    /* Assume everything except time */
06363    i->monthmask = 0xfff;   /* 12 bits */
06364    i->daymask = 0x7fffffffU; /* 31 bits */
06365    i->dowmask = 0x7f; /* 7 bits */
06366    /* on each call, use strsep() to move info to the next argument */
06367    get_timerange(i, strsep(&info, "|,"));
06368    if (info)
06369       i->dowmask = get_range(strsep(&info, "|,"), 7, days, "day of week");
06370    if (info)
06371       i->daymask = get_range(strsep(&info, "|,"), 31, NULL, "day");
06372    if (info)
06373       i->monthmask = get_range(strsep(&info, "|,"), 12, months, "month");
06374    return 1;
06375 }

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

References E_CANMATCH, and pbx_extension_helper().

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

03637 {
03638    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0);
03639 }

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

Change hint for an extension.

Definition at line 3550 of file pbx.c.

References AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_hint::exten, and ast_hint::list.

03551 {
03552    struct ast_hint *hint;
03553    int res = -1;
03554 
03555    AST_RWLIST_WRLOCK(&hints);
03556    AST_RWLIST_TRAVERSE(&hints, hint, list) {
03557       if (hint->exten == oe) {
03558             hint->exten = ne;
03559          res = 0;
03560          break;
03561       }
03562    }
03563    AST_RWLIST_UNLOCK(&hints);
03564 
03565    return res;
03566 }

int ast_check_timing ( const struct ast_timing i  ) 

Definition at line 6377 of file pbx.c.

References ast_localtime(), ast_log(), ast_tvnow(), ast_timing::daymask, ast_timing::dowmask, LOG_WARNING, ast_timing::minmask, ast_timing::monthmask, ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, and ast_tm::tm_wday.

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

06378 {
06379    struct ast_tm tm;
06380    struct timeval now = ast_tvnow();
06381 
06382    ast_localtime(&now, &tm, NULL);
06383 
06384    /* If it's not the right month, return */
06385    if (!(i->monthmask & (1 << tm.tm_mon)))
06386       return 0;
06387 
06388    /* If it's not that time of the month.... */
06389    /* Warning, tm_mday has range 1..31! */
06390    if (!(i->daymask & (1 << (tm.tm_mday-1))))
06391       return 0;
06392 
06393    /* If it's not the right day of the week */
06394    if (!(i->dowmask & (1 << tm.tm_wday)))
06395       return 0;
06396 
06397    /* Sanity check the hour just to be safe */
06398    if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) {
06399       ast_log(LOG_WARNING, "Insane time...\n");
06400       return 0;
06401    }
06402 
06403    /* Now the tough part, we calculate if it fits
06404       in the right time based on min/hour */
06405    if (!(i->minmask[tm.tm_hour] & (1 << (tm.tm_min / 2))))
06406       return 0;
06407 
06408    /* If we got this far, then we're good */
06409    return 1;
06410 }

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

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

Referenced by handle_cli_dialplan_add_ignorepat().

06604 {
06605    int ret = -1;
06606    struct ast_context *c = find_context_locked(context);
06607 
06608    if (c) {
06609       ret = ast_context_add_ignorepat2(c, value, registrar);
06610       ast_unlock_contexts();
06611    }
06612    return ret;
06613 }

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

Definition at line 6615 of file pbx.c.

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

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

06616 {
06617    struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL;
06618    int length;
06619    char *pattern;
06620    length = sizeof(struct ast_ignorepat);
06621    length += strlen(value) + 1;
06622    if (!(ignorepat = ast_calloc(1, length)))
06623       return -1;
06624    /* The cast to char * is because we need to write the initial value.
06625     * The field is not supposed to be modified otherwise.  Also, gcc 4.2
06626     * sees the cast as dereferencing a type-punned pointer and warns about
06627     * it.  This is the workaround (we're telling gcc, yes, that's really
06628     * what we wanted to do).
06629     */
06630    pattern = (char *) ignorepat->pattern;
06631    strcpy(pattern, value);
06632    ignorepat->next = NULL;
06633    ignorepat->registrar = registrar;
06634    ast_wrlock_context(con);
06635    for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) {
06636       ignorepatl = ignorepatc;
06637       if (!strcasecmp(ignorepatc->pattern, value)) {
06638          /* Already there */
06639          ast_unlock_context(con);
06640          errno = EEXIST;
06641          return -1;
06642       }
06643    }
06644    if (ignorepatl)
06645       ignorepatl->next = ignorepat;
06646    else
06647       con->ignorepats = ignorepat;
06648    ast_unlock_context(con);
06649    return 0;
06650 
06651 }

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

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

Referenced by handle_cli_dialplan_add_include().

06158 {
06159    int ret = -1;
06160    struct ast_context *c = find_context_locked(context);
06161 
06162    if (c) {
06163       ret = ast_context_add_include2(c, include, registrar);
06164       ast_unlock_contexts();
06165    }
06166    return ret;
06167 }

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

References ast_build_timing(), ast_calloc, 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(), context_merge_incls_swits_igps_other_registrars(), and pbx_load_config().

06421 {
06422    struct ast_include *new_include;
06423    char *c;
06424    struct ast_include *i, *il = NULL; /* include, include_last */
06425    int length;
06426    char *p;
06427 
06428    length = sizeof(struct ast_include);
06429    length += 2 * (strlen(value) + 1);
06430 
06431    /* allocate new include structure ... */
06432    if (!(new_include = ast_calloc(1, length)))
06433       return -1;
06434    /* Fill in this structure. Use 'p' for assignments, as the fields
06435     * in the structure are 'const char *'
06436     */
06437    p = new_include->stuff;
06438    new_include->name = p;
06439    strcpy(p, value);
06440    p += strlen(value) + 1;
06441    new_include->rname = p;
06442    strcpy(p, value);
06443    /* Strip off timing info, and process if it is there */
06444    if ( (c = strchr(p, ',')) ) {
06445       *c++ = '\0';
06446            new_include->hastime = ast_build_timing(&(new_include->timing), c);
06447    }
06448    new_include->next      = NULL;
06449    new_include->registrar = registrar;
06450 
06451    ast_wrlock_context(con);
06452 
06453    /* ... go to last include and check if context is already included too... */
06454    for (i = con->includes; i; i = i->next) {
06455       if (!strcasecmp(i->name, new_include->name)) {
06456          ast_free(new_include);
06457          ast_unlock_context(con);
06458          errno = EEXIST;
06459          return -1;
06460       }
06461       il = i;
06462    }
06463 
06464    /* ... include new context into context list, unlock, return */
06465    if (il)
06466       il->next = new_include;
06467    else
06468       con->includes = new_include;
06469    ast_verb(3, "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con));
06470 
06471    ast_unlock_context(con);
06472 
06473    return 0;
06474 }

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

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

06482 {
06483    int ret = -1;
06484    struct ast_context *c = find_context_locked(context);
06485 
06486    if (c) { /* found, add switch to this context */
06487       ret = ast_context_add_switch2(c, sw, data, eval, registrar);
06488       ast_unlock_contexts();
06489    }
06490    return ret;
06491 }

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 6500 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(), lua_register_switches(), and pbx_load_config().

06502 {
06503    struct ast_sw *new_sw;
06504    struct ast_sw *i;
06505    int length;
06506    char *p;
06507 
06508    length = sizeof(struct ast_sw);
06509    length += strlen(value) + 1;
06510    if (data)
06511       length += strlen(data);
06512    length++;
06513 
06514    /* allocate new sw structure ... */
06515    if (!(new_sw = ast_calloc(1, length)))
06516       return -1;
06517    /* ... fill in this structure ... */
06518    p = new_sw->stuff;
06519    new_sw->name = p;
06520    strcpy(new_sw->name, value);
06521    p += strlen(value) + 1;
06522    new_sw->data = p;
06523    if (data) {
06524       strcpy(new_sw->data, data);
06525       p += strlen(data) + 1;
06526    } else {
06527       strcpy(new_sw->data, "");
06528       p++;
06529    }
06530    new_sw->eval     = eval;
06531    new_sw->registrar = registrar;
06532 
06533    /* ... try to lock this context ... */
06534    ast_wrlock_context(con);
06535 
06536    /* ... go to last sw and check if context is already swd too... */
06537    AST_LIST_TRAVERSE(&con->alts, i, list) {
06538       if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) {
06539          ast_free(new_sw);
06540          ast_unlock_context(con);
06541          errno = EEXIST;
06542          return -1;
06543       }
06544    }
06545 
06546    /* ... sw new context into context list, unlock, return */
06547    AST_LIST_INSERT_TAIL(&con->alts, new_sw, list);
06548 
06549    ast_verb(3, "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con));
06550 
06551    ast_unlock_context(con);
06552 
06553    return 0;
06554 }

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

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

Referenced by __unload_module(), cleanup_stale_contexts(), parkinglot_destroy(), 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 2012 of file pbx.c.

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

Referenced by __unload_module(), _macro_exec(), ast_context_verify_includes(), ast_ignore_pattern(), cleanup_stale_contexts(), isexten_function_read(), manage_parkinglot(), park_exec_full(), parkinglot_destroy(), register_exten(), register_peer_exten(), unload_module(), and unregister_exten().

02013 {
02014    struct ast_context *tmp = NULL;
02015    struct fake_context item;
02016 
02017    ast_copy_string(item.name, name, sizeof(item.name));
02018 
02019    ast_rdlock_contexts();
02020    if( contexts_table ) {
02021       tmp = ast_hashtab_lookup(contexts_table,&item);
02022    } else {
02023       while ( (tmp = ast_walk_contexts(tmp)) ) {
02024          if (!name || !strcasecmp(name, tmp->name))
02025             break;
02026       }
02027    }
02028    ast_unlock_contexts();
02029    return tmp;
02030 }

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

Referenced by ast_park_call_full(), build_parkinglot(), context_merge(), load_module(), lua_register_switches(), manage_parkinglot(), pbx_load_config(), pbx_load_users(), reload_config(), and set_config().

05815 {
05816    struct ast_context *tmp, **local_contexts;
05817    struct fake_context search;
05818    int length = sizeof(struct ast_context) + strlen(name) + 1;
05819 
05820    if (!contexts_table) {
05821       contexts_table = ast_hashtab_create(17,
05822                                  ast_hashtab_compare_contexts, 
05823                                  ast_hashtab_resize_java,
05824                                  ast_hashtab_newsize_java,
05825                                  ast_hashtab_hash_contexts,
05826                                  0);
05827    }
05828    
05829    ast_copy_string(search.name, name, sizeof(search.name));
05830    if (!extcontexts) {
05831       ast_rdlock_contexts();
05832       local_contexts = &contexts;
05833       tmp = ast_hashtab_lookup(contexts_table, &search);
05834       ast_unlock_contexts();
05835       if (tmp) {
05836          tmp->refcount++;
05837          return tmp;
05838       }
05839    } else { /* local contexts just in a linked list; search there for the new context; slow, linear search, but not frequent */
05840       local_contexts = extcontexts;
05841       tmp = ast_hashtab_lookup(exttable, &search);
05842       if (tmp) {
05843          tmp->refcount++;
05844          return tmp;
05845       }
05846    }
05847    
05848    if ((tmp = ast_calloc(1, length))) {
05849       ast_rwlock_init(&tmp->lock);
05850       ast_mutex_init(&tmp->macrolock);
05851       strcpy(tmp->name, name);
05852       tmp->root = NULL;
05853       tmp->root_table = NULL;
05854       tmp->registrar = ast_strdup(registrar);
05855       tmp->includes = NULL;
05856       tmp->ignorepats = NULL;
05857       tmp->refcount = 1;
05858    } else {
05859       ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name);
05860       return NULL;
05861    }
05862    
05863    if (!extcontexts) {
05864       ast_wrlock_contexts();
05865       tmp->next = *local_contexts;
05866       *local_contexts = tmp;
05867       ast_hashtab_insert_safe(contexts_table, tmp); /*put this context into the tree */
05868       ast_unlock_contexts();
05869       ast_debug(1, "Registered context '%s'(%p) in table %p registrar: %s\n", tmp->name, tmp, contexts_table, registrar);
05870       ast_verb(3, "Registered extension context '%s' (%p) in table %p; registrar: %s\n", tmp->name, tmp, contexts_table, registrar);
05871    } else {
05872       tmp->next = *local_contexts;
05873       if (exttable)
05874          ast_hashtab_insert_immediate(exttable, tmp); /*put this context into the tree */
05875       
05876       *local_contexts = tmp;
05877       ast_debug(1, "Registered context '%s'(%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar);
05878       ast_verb(3, "Registered extension context '%s' (%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar);
05879    }
05880    return tmp;
05881 }

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

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

Referenced by _macro_exec().

04462 {
04463    struct ast_context *c = NULL;
04464    int ret = -1;
04465    struct fake_context item;
04466 
04467    ast_rdlock_contexts();
04468 
04469    ast_copy_string(item.name, context, sizeof(item.name));
04470 
04471    c = ast_hashtab_lookup(contexts_table,&item);
04472    if (c)
04473       ret = 0;
04474 
04475 
04476 #ifdef NOTNOW
04477 
04478    while ((c = ast_walk_contexts(c))) {
04479       if (!strcmp(ast_get_context_name(c), context)) {
04480          ret = 0;
04481          break;
04482       }
04483    }
04484 
04485 #endif
04486    ast_unlock_contexts();
04487 
04488    /* if we found context, lock macrolock */
04489    if (ret == 0) 
04490       ret = ast_mutex_lock(&c->macrolock);
04491 
04492    return ret;
04493 }

int ast_context_remove_extension ( const char *  context,
const char *  extension,
int  priority,
const char *  registrar 
)

Simply remove extension from context.

Parameters:
context context to remove extension from
extension which extension to remove
priority priority of extension to remove (0 to remove all)
callerid NULL to remove all; non-NULL to match a single record per priority
matchcid non-zero to match callerid element (if non-NULL); 0 to match default case
registrar registrar of the extension
This function removes an extension from a given context.

Return values:
0 on success
-1 on failure

Definition at line 4268 of file pbx.c.

References ast_context_remove_extension_callerid().

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

04269 {
04270    return ast_context_remove_extension_callerid(context, extension, priority, NULL, 0, registrar);
04271 }

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

References ast_context_remove_extension_callerid2().

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

04296 {
04297    return ast_context_remove_extension_callerid2(con, extension, priority, NULL, 0, registrar, already_locked);
04298 }

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

04274 {
04275    int ret = -1; /* default error return */
04276    struct ast_context *c = find_context_locked(context);
04277 
04278    if (c) { /* ... remove extension ... */
04279       ret = ast_context_remove_extension_callerid2(c, extension, priority, callerid, matchcallerid, registrar, 1);
04280       ast_unlock_contexts();
04281    }
04282    return ret;
04283 }

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 4300 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(), exten, ast_exten::exten, ast_exten::label, LOG_ERROR, log_match_char_tree(), 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().

04301 {
04302    struct ast_exten *exten, *prev_exten = NULL;
04303    struct ast_exten *peer;
04304    struct ast_exten ex, *exten2, *exten3;
04305    char dummy_name[1024];
04306    struct ast_exten *previous_peer = NULL;
04307    struct ast_exten *next_peer = NULL;
04308    int found = 0;
04309 
04310    if (!already_locked)
04311       ast_wrlock_context(con);
04312 
04313    /* Handle this is in the new world */
04314 
04315    /* FIXME For backwards compatibility, if callerid==NULL, then remove ALL
04316     * peers, not just those matching the callerid. */
04317 #ifdef NEED_DEBUG
04318    ast_verb(3,"Removing %s/%s/%d%s%s from trees, registrar=%s\n", con->name, extension, priority, matchcallerid ? "/" : "", matchcallerid ? callerid : "", registrar);
04319 #endif
04320 #ifdef CONTEXT_DEBUG
04321    check_contexts(__FILE__, __LINE__);
04322 #endif
04323    /* find this particular extension */
04324    ex.exten = dummy_name;
04325    ex.matchcid = matchcallerid && !ast_strlen_zero(callerid); /* don't say match if there's no callerid */
04326    ex.cidmatch = callerid;
04327    ast_copy_string(dummy_name, extension, sizeof(dummy_name));
04328    exten = ast_hashtab_lookup(con->root_table, &ex);
04329    if (exten) {
04330       if (priority == 0) {
04331          exten2 = ast_hashtab_remove_this_object(con->root_table, exten);
04332          if (!exten2)
04333             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);
04334          if (con->pattern_tree) {
04335             
04336             struct match_char *x = add_exten_to_pattern_tree(con, exten, 1);
04337             
04338             if (x->exten) { /* this test for safety purposes */
04339                x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */
04340                x->exten = 0; /* get rid of what will become a bad pointer */
04341             } else {
04342                ast_log(LOG_WARNING,"Trying to delete an exten from a context, but the pattern tree node returned isn't a full extension\n");
04343             }
04344          }
04345       } else {
04346          ex.priority = priority;
04347          exten2 = ast_hashtab_lookup(exten->peer_table, &ex);
04348          if (exten2) {
04349             
04350             if (exten2->label) { /* if this exten has a label, remove that, too */
04351                exten3 = ast_hashtab_remove_this_object(exten->peer_label_table,exten2);
04352                if (!exten3)
04353                   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);
04354             }
04355          
04356             exten3 = ast_hashtab_remove_this_object(exten->peer_table, exten2);
04357             if (!exten3)
04358                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);
04359             if (exten2 == exten && exten2->peer) {
04360                exten2 = ast_hashtab_remove_this_object(con->root_table, exten);
04361                ast_hashtab_insert_immediate(con->root_table, exten2->peer);
04362             }
04363             if (ast_hashtab_size(exten->peer_table) == 0) {
04364                /* well, if the last priority of an exten is to be removed,
04365                   then, the extension is removed, too! */
04366                exten3 = ast_hashtab_remove_this_object(con->root_table, exten);
04367                if (!exten3)
04368                   ast_log(LOG_ERROR,"Did not remove this exten (%s) from the context root_table (%s) (priority %d)\n", exten->exten, con->name, priority);
04369                if (con->pattern_tree) {
04370                   struct match_char *x = add_exten_to_pattern_tree(con, exten, 1);
04371                   if (x->exten) { /* this test for safety purposes */
04372                      x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */
04373                      x->exten = 0; /* get rid of what will become a bad pointer */
04374                   }
04375                }
04376             }
04377          } else {
04378             ast_log(LOG_ERROR,"Could not find priority %d of exten %s in context %s!\n",
04379                   priority, exten->exten, con->name);
04380          }
04381       }
04382    } else {
04383       /* hmmm? this exten is not in this pattern tree? */
04384       ast_log(LOG_WARNING,"Cannot find extension %s in root_table in context %s\n",
04385             extension, con->name);
04386    }
04387 #ifdef NEED_DEBUG
04388    if (con->pattern_tree) {
04389       ast_log(LOG_NOTICE,"match char tree after exten removal:\n");
04390       log_match_char_tree(con->pattern_tree, " ");
04391    }
04392 #endif
04393 
04394    /* scan the extension list to find first matching extension-registrar */
04395    for (exten = con->root; exten; prev_exten = exten, exten = exten->next) {
04396       if (!strcmp(exten->exten, extension) &&
04397          (!registrar || !strcmp(exten->registrar, registrar)) &&
04398          (!matchcallerid || (!ast_strlen_zero(callerid) && !ast_strlen_zero(exten->cidmatch) && !strcmp(exten->cidmatch, callerid)) || (ast_strlen_zero(callerid) && ast_strlen_zero(exten->cidmatch))))
04399          break;
04400    }
04401    if (!exten) {
04402       /* we can't find right extension */
04403       if (!already_locked)
04404          ast_unlock_context(con);
04405       return -1;
04406    }
04407 
04408    /* scan the priority list to remove extension with exten->priority == priority */
04409    for (peer = exten, next_peer = exten->peer ? exten->peer : exten->next;
04410        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)));
04411          peer = next_peer, next_peer = next_peer ? (next_peer->peer ? next_peer->peer : next_peer->next) : NULL) {
04412       if ((priority == 0 || peer->priority == priority) &&
04413             (!callerid || !matchcallerid || (matchcallerid && !strcmp(peer->cidmatch, callerid))) &&
04414             (!registrar || !strcmp(peer->registrar, registrar) )) {
04415          found = 1;
04416 
04417          /* we are first priority extension? */
04418          if (!previous_peer) {
04419             /*
04420              * We are first in the priority chain, so must update the extension chain.
04421              * The next node is either the next priority or the next extension
04422              */
04423             struct ast_exten *next_node = peer->peer ? peer->peer : peer->next;
04424             if (peer->peer) {
04425                /* move the peer_table and peer_label_table down to the next peer, if
04426                   it is there */
04427                peer->peer->peer_table = peer->peer_table;
04428                peer->peer->peer_label_table = peer->peer_label_table;
04429                peer->peer_table = NULL;
04430                peer->peer_label_table = NULL;
04431             }
04432             if (!prev_exten) {   /* change the root... */
04433                con->root = next_node;
04434             } else {
04435                prev_exten->next = next_node; /* unlink */
04436             }
04437             if (peer->peer)   { /* update the new head of the pri list */
04438                peer->peer->next = peer->next;
04439             }
04440          } else { /* easy, we are not first priority in extension */
04441             previous_peer->peer = peer->peer;
04442          }
04443 
04444          /* now, free whole priority extension */
04445          destroy_exten(peer);
04446       } else {
04447          previous_peer = peer;
04448       }
04449    }
04450    if (!already_locked)
04451       ast_unlock_context(con);
04452    return found ? 0 : -1;
04453 }

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

Definition at line 6560 of file pbx.c.

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

Referenced by handle_cli_dialplan_remove_ignorepat().

06561 {
06562    int ret = -1;
06563    struct ast_context *c = find_context_locked(context);
06564 
06565    if (c) {
06566       ret = ast_context_remove_ignorepat2(c, ignorepat, registrar);
06567       ast_unlock_contexts();
06568    }
06569    return ret;
06570 }

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

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

06573 {
06574    struct ast_ignorepat *ip, *ipl = NULL;
06575 
06576    ast_wrlock_context(con);
06577 
06578    for (ip = con->ignorepats; ip; ip = ip->next) {
06579       if (!strcmp(ip->pattern, ignorepat) &&
06580          (!registrar || (registrar == ip->registrar))) {
06581          if (ipl) {
06582             ipl->next = ip->next;
06583             ast_free(ip);
06584          } else {
06585             con->ignorepats = ip->next;
06586             ast_free(ip);
06587          }
06588          ast_unlock_context(con);
06589          return 0;
06590       }
06591       ipl = ip;
06592    }
06593 
06594    ast_unlock_context(con);
06595    errno = EINVAL;
06596    return -1;
06597 }

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

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

Referenced by handle_cli_dialplan_remove_include().

04161 {
04162    int ret = -1;
04163    struct ast_context *c = find_context_locked(context);
04164 
04165    if (c) {
04166       /* found, remove include from this context ... */
04167       ret = ast_context_remove_include2(c, include, registrar);
04168       ast_unlock_contexts();
04169    }
04170    return ret;
04171 }

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

References ast_free, ast_get_context_name(), ast_unlock_context(), ast_verb, ast_wrlock_context(), ast_context::includes, ast_include::name, ast_include::next, and ast_include::registrar.

Referenced by ast_context_remove_include().

04183 {
04184    struct ast_include *i, *pi = NULL;
04185    int ret = -1;
04186 
04187    ast_wrlock_context(con);
04188 
04189    /* find our include */
04190    for (i = con->includes; i; pi = i, i = i->next) {
04191       if (!strcmp(i->name, include) &&
04192             (!registrar || !strcmp(i->registrar, registrar))) {
04193          /* remove from list */
04194          ast_verb(3, "Removing inclusion of context '%s' in context '%s; registrar=%s'\n", include, ast_get_context_name(con), registrar);
04195          if (pi)
04196             pi->next = i->next;
04197          else
04198             con->includes = i->next;
04199          /* free include and return */
04200          ast_free(i);
04201          ret = 0;
04202          break;
04203       }
04204    }
04205 
04206    ast_unlock_context(con);
04207 
04208    return ret;
04209 }

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

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

04217 {
04218    int ret = -1; /* default error return */
04219    struct ast_context *c = find_context_locked(context);
04220 
04221    if (c) {
04222       /* remove switch from this context ... */
04223       ret = ast_context_remove_switch2(c, sw, data, registrar);
04224       ast_unlock_contexts();
04225    }
04226    return ret;
04227 }

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

04238 {
04239    struct ast_sw *i;
04240    int ret = -1;
04241 
04242    ast_wrlock_context(con);
04243 
04244    /* walk switches */
04245    AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) {
04246       if (!strcmp(i->name, sw) && !strcmp(i->data, data) &&
04247          (!registrar || !strcmp(i->registrar, registrar))) {
04248          /* found, remove from list */
04249          ast_verb(3, "Removing switch '%s' from context '%s; registrar=%s'\n", sw, ast_get_context_name(con), registrar);
04250          AST_LIST_REMOVE_CURRENT(list);
04251          ast_free(i); /* free switch and return */
04252          ret = 0;
04253          break;
04254       }
04255    }
04256    AST_LIST_TRAVERSE_SAFE_END;
04257 
04258    ast_unlock_context(con);
04259 
04260    return ret;
04261 }

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

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

Referenced by _macro_exec().

04501 {
04502    struct ast_context *c = NULL;
04503    int ret = -1;
04504    struct fake_context item;
04505 
04506    ast_rdlock_contexts();
04507 
04508    ast_copy_string(item.name, context, sizeof(item.name));
04509 
04510    c = ast_hashtab_lookup(contexts_table,&item);
04511    if (c)
04512       ret = 0;
04513 #ifdef NOTNOW
04514 
04515    while ((c = ast_walk_contexts(c))) {
04516       if (!strcmp(ast_get_context_name(c), context)) {
04517          ret = 0;
04518          break;
04519       }
04520    }
04521 
04522 #endif
04523    ast_unlock_contexts();
04524 
04525    /* if we found context, unlock macrolock */
04526    if (ret == 0) 
04527       ret = ast_mutex_unlock(&c->macrolock);
04528 
04529    return ret;
04530 }

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

08861 {
08862    struct ast_include *inc = NULL;
08863    int res = 0;
08864 
08865    while ( (inc = ast_walk_context_includes(con, inc)) ) {
08866       if (ast_context_find(inc->rname))
08867          continue;
08868 
08869       res = -1;
08870       ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n",
08871          ast_get_context_name(con), inc->rname);
08872       break;
08873    }
08874 
08875    return res;
08876 }

struct ast_custom_function* ast_custom_function_find ( const char *  name  ) 

Definition at line 2763 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_write(), config_curl(), destroy_curl(), handle_show_function(), op_func(), realtime_curl(), realtime_multi_curl(), require_curl(), store_curl(), and update_curl().

02764 {
02765    struct ast_custom_function *acf = NULL;
02766 
02767    AST_RWLIST_RDLOCK(&acf_root);
02768    AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) {
02769       if (!strcmp(name, acf->name))
02770          break;
02771    }
02772    AST_RWLIST_UNLOCK(&acf_root);
02773 
02774    return acf;
02775 }

int ast_custom_function_unregister ( struct ast_custom_function acf  ) 

Unregister a custom function.

Definition at line 2777 of file pbx.c.

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

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

02778 {
02779    struct ast_custom_function *cur;
02780 
02781    if (!acf)
02782       return -1;
02783 
02784    AST_RWLIST_WRLOCK(&acf_root);
02785    if ((cur = AST_RWLIST_REMOVE(&acf_root, acf, acflist)))
02786       ast_verb(2, "Unregistered custom function %s\n", cur->name);
02787    AST_RWLIST_UNLOCK(&acf_root);
02788 
02789    return cur ? 0 : -1;
02790 }

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

References E_MATCH, and pbx_extension_helper().

Referenced by __ast_goto_if_exists(), __ast_pbx_run(), _macro_exec(), acf_isexten_exec(), answer_call(), ast_app_dtget(), ast_bridge_call(), ast_pbx_outgoing_exten(), builtin_atxfer(), builtin_blindtransfer(), cb_events(), cli_console_dial(), conf_run(), console_dial(), console_transfer(), dahdi_handle_dtmfup(), dial_exec_full(), disa_exec(), dp_lookup(), dundi_lookup_local(), get_also_info(), get_destination(), get_refer_info(), gosub_exec(), handle_gosub(), handle_link_data(), handle_link_phone_dtmf(), handle_stimulus_message(), isexten_function_read(), leave_voicemail(), local_alloc(), local_call(), local_devicestate(), local_dtmf_helper(), loopback_exists(), metermaidstate(), mgcp_ss(), minivm_greet_exec(), misdn_overlap_dial_task(), park_space_reserve(), parkandannounce_exec(), pbx_builtin_waitexten(), phone_check_exception(), pri_dchannel(), privacy_exec(), process_ast_dsp(), readexten_exec(), register_peer_exten(), rpt_exec(), show_debug_helper(), skinny_ss(), socket_process(), ss_thread(), and waitstream_core().

03622 {
03623    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0);
03624 }

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

References ast_channel_lock, ast_channel_unlock, ast_copy_string(), AST_FLAG_IN_AUTOLOOP, ast_strlen_zero(), ast_test_flag, chan, 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().

06708 {
06709    if (!chan)
06710       return -1;
06711 
06712    ast_channel_lock(chan);
06713 
06714    if (!ast_strlen_zero(context))
06715       ast_copy_string(chan->context, context, sizeof(chan->context));
06716    if (!ast_strlen_zero(exten))
06717       ast_copy_string(chan->exten, exten, sizeof(chan->exten));
06718    if (priority > -1) {
06719       chan->priority = priority;
06720       /* see flag description in channel.h for explanation */
06721       if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP))
06722          chan->priority--;
06723    }
06724 
06725    ast_channel_unlock(chan);
06726 
06727    return 0;
06728 }

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

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

01990 {
01991    if (needmore != E_MATCHMORE && needmore != E_CANMATCH)
01992       ast_log(LOG_WARNING, "invalid argument %d\n", needmore);
01993    return extension_match_core(pattern, data, needmore);
01994 }

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

References ext_cmp().

Referenced by lua_extension_cmp().

01792 {
01793    return ext_cmp(a, b);
01794 }

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

References E_MATCH, and extension_match_core().

Referenced by ast_ignore_pattern(), do_say(), find_matching_priority(), load_module(), loopback_canmatch(), loopback_exists(), loopback_matchmore(), lua_find_extension(), manager_show_dialplan_helper(), matchcid(), misdn_cfg_is_msn_valid(), realtime_switch_common(), reload(), and show_dialplan_helper().

01985 {
01986    return extension_match_core(pattern, data, E_MATCH);
01987 }

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

References ast_extension_state2(), and ast_hint_extension().

Referenced by action_extensionstate(), extstate_read(), and handle_request_subscribe().

03314 {
03315    struct ast_exten *e;
03316 
03317    e = ast_hint_extension(c, context, exten);   /* Do we have a hint for this extension ? */
03318    if (!e)
03319       return -1;           /* No hint, return -1 */
03320 
03321    return ast_extension_state2(e);        /* Check all devices in the hint */
03322 }

static int ast_extension_state2 ( struct ast_exten e  )  [static]

Check state of extension by using hints.

Definition at line 3257 of file pbx.c.

References ast_copy_string(), AST_DEVICE_BUSY, AST_DEVICE_INUSE, AST_DEVICE_INVALID, AST_DEVICE_NOT_INUSE, AST_DEVICE_ONHOLD, AST_DEVICE_RINGING, AST_DEVICE_RINGINUSE, ast_device_state(), AST_DEVICE_UNAVAILABLE, AST_DEVICE_UNKNOWN, ast_devstate_aggregate_add(), ast_devstate_aggregate_init(), ast_devstate_aggregate_result(), AST_EXTENSION_BUSY, AST_EXTENSION_INUSE, AST_EXTENSION_NOT_INUSE, AST_EXTENSION_ONHOLD, AST_EXTENSION_RINGING, AST_EXTENSION_UNAVAILABLE, ast_get_extension_app(), AST_MAX_EXTENSION, and strsep().

Referenced by ast_add_hint_nolock(), ast_extension_state(), and handle_statechange().

03258 {
03259    char hint[AST_MAX_EXTENSION] = "";
03260    char *cur, *rest;
03261    struct ast_devstate_aggregate agg;
03262    enum ast_device_state state;
03263 
03264    if (!e)
03265       return -1;
03266 
03267    ast_devstate_aggregate_init(&agg);
03268 
03269    ast_copy_string(hint, ast_get_extension_app(e), sizeof(hint));
03270 
03271    rest = hint;   /* One or more devices separated with a & character */
03272 
03273    while ( (cur = strsep(&rest, "&")) )
03274       ast_devstate_aggregate_add(&agg, ast_device_state(cur));
03275 
03276    state = ast_devstate_aggregate_result(&agg);
03277 
03278    switch (state) {
03279    case AST_DEVICE_ONHOLD:
03280       return AST_EXTENSION_ONHOLD;
03281    case AST_DEVICE_BUSY:
03282       return AST_EXTENSION_BUSY;
03283    case AST_DEVICE_UNAVAILABLE:
03284       return AST_EXTENSION_UNAVAILABLE;
03285    case AST_DEVICE_RINGINUSE:
03286       return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING);
03287    case AST_DEVICE_RINGING:
03288       return AST_EXTENSION_RINGING;
03289    case AST_DEVICE_INUSE:
03290       return AST_EXTENSION_INUSE;
03291    case AST_DEVICE_UNKNOWN:
03292    case AST_DEVICE_INVALID:
03293    case AST_DEVICE_NOT_INUSE:
03294       return AST_EXTENSION_NOT_INUSE;
03295    }
03296 
03297    return AST_EXTENSION_NOT_INUSE;
03298 }

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

03302 {
03303    int i;
03304 
03305    for (i = 0; (i < ARRAY_LEN(extension_states)); i++) {
03306       if (extension_states[i].extension_state == extension_state)
03307          return extension_states[i].text;
03308    }
03309    return "Unknown";
03310 }

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

Registers a state change callback.

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

Return values:
-1 on failure
ID on success

Definition at line 3374 of file pbx.c.

References ast_exten::app, ast_add_extension(), ast_calloc, ast_free_ptr, ast_hint_extension(), AST_LIST_INSERT_HEAD, AST_LIST_TRAVERSE, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_strdup, ast_state_cb::callback, ast_hint::callbacks, ast_exten::cidmatch, ast_state_cb::data, ast_exten::data, ast_exten::exten, ast_hint::exten, ast_exten::label, ast_context::name, ast_exten::parent, ast_exten::priority, ast_exten::registrar, and stateid.

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

03376 {
03377    struct ast_hint *hint;
03378    struct ast_state_cb *cblist;
03379    struct ast_exten *e;
03380 
03381    /* If there's no context and extension:  add callback to statecbs list */
03382    if (!context && !exten) {
03383       AST_RWLIST_WRLOCK(&hints);
03384 
03385       AST_LIST_TRAVERSE(&statecbs, cblist, entry) {
03386          if (cblist->callback == callback) {
03387             cblist->data = data;
03388             AST_RWLIST_UNLOCK(&hints);
03389             return 0;
03390          }
03391       }
03392 
03393       /* Now insert the callback */
03394       if (!(cblist = ast_calloc(1, sizeof(*cblist)))) {
03395          AST_RWLIST_UNLOCK(&hints);
03396          return -1;
03397       }
03398       cblist->id = 0;
03399       cblist->callback = callback;
03400       cblist->data = data;
03401 
03402       AST_LIST_INSERT_HEAD(&statecbs, cblist, entry);
03403 
03404       AST_RWLIST_UNLOCK(&hints);
03405 
03406       return 0;
03407    }
03408 
03409    if (!context || !exten)
03410       return -1;
03411 
03412    /* This callback type is for only one hint, so get the hint */
03413    e = ast_hint_extension(NULL, context, exten);
03414    if (!e) {
03415       return -1;
03416    }
03417 
03418    /* If this is a pattern, dynamically create a new extension for this
03419     * particular match.  Note that this will only happen once for each
03420     * individual extension, because the pattern will no longer match first.
03421     */
03422    if (e->exten[0] == '_') {
03423       ast_add_extension(e->parent->name, 0, exten, e->priority, e->label,
03424          e->cidmatch, e->app, ast_strdup(e->data), ast_free_ptr,
03425          e->registrar);
03426       e = ast_hint_extension(NULL, context, exten);
03427       if (!e || e->exten[0] == '_') {
03428          return -1;
03429       }
03430    }
03431 
03432    /* Find the hint in the list of hints */
03433    AST_RWLIST_WRLOCK(&hints);
03434 
03435    AST_RWLIST_TRAVERSE(&hints, hint, list) {
03436       if (hint->exten == e)
03437          break;
03438    }
03439 
03440    if (!hint) {
03441       /* We have no hint, sorry */
03442       AST_RWLIST_UNLOCK(&hints);
03443       return -1;
03444    }
03445 
03446    /* Now insert the callback in the callback list  */
03447    if (!(cblist = ast_calloc(1, sizeof(*cblist)))) {
03448       AST_RWLIST_UNLOCK(&hints);
03449       return -1;
03450    }
03451 
03452    cblist->id = stateid++;    /* Unique ID for this callback */
03453    cblist->callback = callback;  /* Pointer to callback routine */
03454    cblist->data = data;    /* Data for the callback */
03455 
03456    AST_LIST_INSERT_HEAD(&hint->callbacks, cblist, entry);
03457 
03458    AST_RWLIST_UNLOCK(&hints);
03459 
03460    return cblist->id;
03461 }

int ast_extension_state_del ( int  id,
ast_state_cb_type  callback 
)

Deletes a registered state change callback by ID.

Parameters:
id of the callback to delete
callback callback
Removes the callback from list of callbacks

Return values:
0 success
-1 failure

Definition at line 3464 of file pbx.c.

References ast_free, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_state_cb::callback, ast_hint::callbacks, ast_state_cb::entry, ast_state_cb::id, and ast_hint::list.

Referenced by dialog_unlink_all(), handle_request_subscribe(), and skinny_unregister().

03465 {
03466    struct ast_state_cb *p_cur = NULL;
03467    int ret = -1;
03468 
03469    if (!id && !callback)
03470       return -1;
03471 
03472    AST_RWLIST_WRLOCK(&hints);
03473 
03474    if (!id) {  /* id == 0 is a callback without extension */
03475       AST_LIST_TRAVERSE_SAFE_BEGIN(&statecbs, p_cur, entry) {
03476          if (p_cur->callback == callback) {
03477             AST_LIST_REMOVE_CURRENT(entry);
03478             break;
03479          }
03480       }
03481       AST_LIST_TRAVERSE_SAFE_END;
03482    } else { /* callback with extension, find the callback based on ID */
03483       struct ast_hint *hint;
03484       AST_RWLIST_TRAVERSE(&hints, hint, list) {
03485          AST_LIST_TRAVERSE_SAFE_BEGIN(&hint->callbacks, p_cur, entry) {
03486             if (p_cur->id == id) {
03487                AST_LIST_REMOVE_CURRENT(entry);
03488                break;
03489             }
03490          }
03491          AST_LIST_TRAVERSE_SAFE_END;
03492 
03493          if (p_cur)
03494             break;
03495       }
03496    }
03497 
03498    if (p_cur) {
03499       ast_free(p_cur);
03500    }
03501 
03502    AST_RWLIST_UNLOCK(&hints);
03503 
03504    return ret;
03505 }

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

03627 {
03628    return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
03629 }

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

References E_FINDLABEL, and pbx_extension_helper().

Referenced by pbx_load_config().

03632 {
03633    return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
03634 }

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.

Returns:
zero on success, non-zero on failure

Definition at line 2850 of file pbx.c.

References __ast_module_user_add(), __ast_module_user_remove(), ast_custom_function_find(), ast_log(), ast_strdupa, chan, copy(), func_args(), LOG_ERROR, ast_custom_function::mod, and ast_custom_function::read.

Referenced by action_getvar(), action_status(), handle_getvariable(), lua_get_variable_value(), and pbx_substitute_variables_helper_full().

02851 {
02852    char *copy = ast_strdupa(function);
02853    char *args = func_args(copy);
02854    struct ast_custom_function *acfptr = ast_custom_function_find(copy);
02855 
02856    if (acfptr == NULL)
02857       ast_log(LOG_ERROR, "Function %s not registered\n", copy);
02858    else if (!acfptr->read)
02859       ast_log(LOG_ERROR, "Function %s cannot be read\n", copy);
02860    else {
02861       int res;
02862       struct ast_module_user *u = NULL;
02863       if (acfptr->mod)
02864          u = __ast_module_user_add(acfptr->mod, chan);
02865       res = acfptr->read(chan, copy, args, workspace, len);
02866       if (acfptr->mod && u)
02867          __ast_module_user_remove(acfptr->mod, u);
02868       return res;
02869    }
02870    return -1;
02871 }

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.

Returns:
zero on success, non-zero on failure

Definition at line 2873 of file pbx.c.

References __ast_module_user_add(), __ast_module_user_remove(), ast_custom_function_find(), ast_log(), ast_strdupa, chan, copy(), func_args(), LOG_ERROR, ast_custom_function::mod, and ast_custom_function::write.

Referenced by pbx_builtin_pushvar_helper(), and pbx_builtin_setvar_helper().

02874 {
02875    char *copy = ast_strdupa(function);
02876    char *args = func_args(copy);
02877    struct ast_custom_function *acfptr = ast_custom_function_find(copy);
02878 
02879    if (acfptr == NULL)
02880       ast_log(LOG_ERROR, "Function %s not registered\n", copy);
02881    else if (!acfptr->write)
02882       ast_log(LOG_ERROR, "Function %s cannot be written to\n", copy);
02883    else {
02884       int res;
02885       struct ast_module_user *u = NULL;
02886       if (acfptr->mod)
02887          u = __ast_module_user_add(acfptr->mod, chan);
02888       res = acfptr->write(chan, copy, args, value);
02889       if (acfptr->mod && u)
02890          __ast_module_user_remove(acfptr->mod, u);
02891       return res;
02892    }
02893 
02894    return -1;
02895 }

const char* ast_get_context_name ( struct ast_context con  ) 

Definition at line 8712 of file pbx.c.

References ast_context::name.

Referenced by _macro_exec(), ast_context_add_include2(), ast_context_add_switch2(), ast_context_lockmacro(), ast_context_remove_include2(), ast_context_remove_switch2(), ast_context_unlockmacro(), ast_context_verify_includes(), 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(), dundi_precache_full(), find_context_locked(), find_matching_endwhile(), find_matching_priority(), handle_cli_dialplan_save(), handle_show_hint(), handle_show_hints(), manager_show_dialplan_helper(), show_debug_helper(), and show_dialplan_helper().

08713 {
08714    return con ? con->name : NULL;
08715 }

const char* ast_get_context_registrar ( struct ast_context c  ) 

Definition at line 8750 of file pbx.c.

References ast_context::registrar.

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

08751 {
08752    return c ? c->registrar : NULL;
08753 }

const char* ast_get_extension_app ( struct ast_exten e  ) 

Definition at line 8780 of file pbx.c.

References ast_exten::app.

Referenced by _macro_exec(), ast_add_hint_nolock(), ast_extension_state2(), ast_get_hint(), find_matching_endwhile(), handle_cli_dialplan_save(), handle_show_hint(), handle_show_hints(), handle_statechange(), manager_show_dialplan_helper(), and print_ext().

08781 {
08782    return e ? e->app : NULL;
08783 }

void* ast_get_extension_app_data ( struct ast_exten e  ) 

Definition at line 8785 of file pbx.c.

References ast_exten::data.

Referenced by _macro_exec(), ast_get_hint(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and print_ext().

08786 {
08787    return e ? e->data : NULL;
08788 }

const char* ast_get_extension_cidmatch ( struct ast_exten e  ) 

Definition at line 8775 of file pbx.c.

References ast_exten::cidmatch.

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

08776 {
08777    return e ? e->cidmatch : NULL;
08778 }

struct ast_context* ast_get_extension_context ( struct ast_exten exten  ) 

Definition at line 8717 of file pbx.c.

References exten.

Referenced by handle_show_hint(), and handle_show_hints().

08718 {
08719    return exten ? exten->parent : NULL;
08720 }

const char* ast_get_extension_label ( struct ast_exten exten  ) 

Definition at line 8727 of file pbx.c.

References exten.

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

08728 {
08729    return exten ? exten->label : NULL;
08730 }

int ast_get_extension_matchcid ( struct ast_exten e  ) 

Definition at line 8770 of file pbx.c.

References ast_exten::matchcid.

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

08771 {
08772    return e ? e->matchcid : 0;
08773 }

const char* ast_get_extension_name ( struct ast_exten exten  ) 

Definition at line 8722 of file pbx.c.

References exten.

Referenced by ast_add_hint_nolock(), complete_core_show_hint(), complete_dialplan_remove_extension(), dundi_precache_full(), find_matching_priority(), handle_cli_dialplan_save(), handle_show_hint(), handle_show_hints(), manager_show_dialplan_helper(), and show_dialplan_helper().

08723 {
08724    return exten ? exten->exten : NULL;
08725 }

int ast_get_extension_priority ( struct ast_exten exten  ) 

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

08743 {
08744    return exten ? exten->priority : -1;
08745 }

const char* ast_get_extension_registrar ( struct ast_exten e  ) 

Definition at line 8755 of file pbx.c.

References ast_exten::registrar.

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

08756 {
08757    return e ? e->registrar : NULL;
08758 }

int ast_get_hint ( char *  hint,
int  maxlen,
char *  name,
int  maxnamelen,
struct ast_channel c,
const char *  context,
const char *  exten 
)

If an extension hint exists, return non-zero.

Parameters:
hint buffer for hint
maxlen size of hint buffer
name buffer for name portion of hint
maxnamelen size of name buffer
c this is not important
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 3604 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(), pbx_retrieve_variable(), skinny_extensionstate_cb(), and transmit_state_notify().

03605 {
03606    struct ast_exten *e = ast_hint_extension(c, context, exten);
03607 
03608    if (e) {
03609       if (hint)
03610          ast_copy_string(hint, ast_get_extension_app(e), hintsize);
03611       if (name) {
03612          const char *tmp = ast_get_extension_app_data(e);
03613          if (tmp)
03614             ast_copy_string(name, tmp, namesize);
03615       }
03616       return -1;
03617    }
03618    return 0;
03619 }

const char* ast_get_ignorepat_name ( struct ast_ignorepat ip  ) 

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

08738 {
08739    return ip ? ip->pattern : NULL;
08740 }

const char* ast_get_ignorepat_registrar ( struct ast_ignorepat ip  ) 

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

08766 {
08767    return ip ? ip->registrar : NULL;
08768 }

const char* ast_get_include_name ( struct ast_include inc  ) 

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

08733 {
08734    return inc ? inc->name : NULL;
08735 }

const char* ast_get_include_registrar ( struct ast_include i  ) 

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

08761 {
08762    return i ? i->registrar : NULL;
08763 }

const char* ast_get_switch_data ( struct ast_sw sw  ) 

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

08796 {
08797    return sw ? sw->data : NULL;
08798 }

int ast_get_switch_eval ( struct ast_sw sw  ) 

Definition at line 8800 of file pbx.c.

References ast_sw::eval.

Referenced by context_merge_incls_swits_igps_other_registrars().

08801 {
08802    return sw->eval;
08803 }

const char* ast_get_switch_name ( struct ast_sw sw  ) 

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

08791 {
08792    return sw ? sw->name : NULL;
08793 }

const char* ast_get_switch_registrar ( struct ast_sw sw  ) 

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

08806 {
08807    return sw ? sw->registrar : NULL;
08808 }

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

References __ast_goto_if_exists(), and chan.

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

08899 {
08900    return __ast_goto_if_exists(chan, context, exten, priority, 0);
08901 }

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

Definition at line 352 of file pbx.c.

References ast_context::name.

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

00353 {
00354    const struct ast_context *ac = ah_a;
00355    const struct ast_context *bc = ah_b;
00356    if (!ac || !bc) /* safety valve, but it might prevent a crash you'd rather have happen */
00357       return 1;
00358    /* assume context names are registered in a string table! */
00359    return strcmp(ac->name, bc->name);
00360 }

unsigned int ast_hashtab_hash_contexts ( const void *  obj  ) 

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

00396 {
00397    const struct ast_context *ac = obj;
00398    return ast_hashtab_hash_string(ac->name);
00399 }

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

Definition at line 3247 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(), and ast_get_hint().

03248 {
03249    struct ast_exten *e;
03250    ast_rdlock_contexts();
03251    e = ast_hint_extension_nolock(c, context, exten);
03252    ast_unlock_contexts();
03253    return e;
03254 }

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

03242 {
03243    struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */
03244    return pbx_find_extension(c, NULL, &q, context, exten, PRIORITY_HINT, NULL, "", E_MATCH);
03245 }

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

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

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

06654 {
06655    struct ast_context *con = ast_context_find(context);
06656    if (con) {
06657       struct ast_ignorepat *pat;
06658       for (pat = con->ignorepats; pat; pat = pat->next) {
06659          if (ast_extension_match(pat->pattern, pattern))
06660             return 1;
06661       }
06662    }
06663 
06664    return 0;
06665 }

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

References E_MATCHMORE, and pbx_extension_helper().

Referenced by ast_app_dtget(), collect_digits(), disa_exec(), dp_lookup(), dundi_lookup_local(), handle_link_data(), handle_link_phone_dtmf(), local_dtmf_helper(), loopback_matchmore(), mgcp_ss(), readexten_exec(), skinny_ss(), and ss_thread().

03642 {
03643    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0);
03644 }

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

References __ast_internal_context_destroy(), 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_APPEND_LIST, AST_LIST_EMPTY, AST_LIST_HEAD_INIT_VALUE, AST_LIST_INSERT_HEAD, AST_LIST_REMOVE_HEAD, ast_log(), ast_rdlock_contexts(), AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_strdup, ast_tvdiff_us(), ast_tvnow(), ast_unlock_contexts(), ast_verb, ast_wrlock_contexts(), ast_wrlock_contexts_version(), ast_state_cb::callback, ast_hint::callbacks, context_merge(), contexts, contexts_table, ast_state_cb::data, E_MATCH, store_hint::exten, ast_hint::exten, ast_exten::exten, ast_hint::laststate, store_hint::list, LOG_WARNING, ast_context::name, store_hint::next, ast_context::next, ast_exten::parent, pbx_find_extension(), PRIORITY_HINT, ast_context::registrar, and pbx_find_info::stacklen.

Referenced by lua_reload_extensions(), and pbx_load_module().

06014 {
06015    double ft;
06016    struct ast_context *tmp, *oldcontextslist;
06017    struct ast_hashtab *oldtable;
06018    struct store_hints store = AST_LIST_HEAD_INIT_VALUE;
06019    struct store_hint *this;
06020    struct ast_hint *hint;
06021    struct ast_exten *exten;
06022    int length;
06023    struct ast_state_cb *thiscb;
06024    struct ast_hashtab_iter *iter;
06025    
06026    /* it is very important that this function hold the hint list lock _and_ the conlock
06027       during its operation; not only do we need to ensure that the list of contexts
06028       and extensions does not change, but also that no hint callbacks (watchers) are
06029       added or removed during the merge/delete process
06030 
06031       in addition, the locks _must_ be taken in this order, because there are already
06032       other code paths that use this order
06033    */
06034    
06035    struct timeval begintime, writelocktime, endlocktime, enddeltime;
06036    int wrlock_ver;
06037    
06038    begintime = ast_tvnow();
06039    ast_rdlock_contexts();
06040    iter = ast_hashtab_start_traversal(contexts_table);
06041    while ((tmp = ast_hashtab_next(iter))) {
06042       context_merge(extcontexts, exttable, tmp, registrar);
06043    }
06044    ast_hashtab_end_traversal(iter);
06045    wrlock_ver = ast_wrlock_contexts_version();
06046    
06047    ast_unlock_contexts(); /* this feels real retarded, but you must do
06048                        what you must do If this isn't done, the following 
06049                         wrlock is a guraranteed deadlock */
06050    ast_wrlock_contexts();
06051    if (ast_wrlock_contexts_version() > wrlock_ver+1) {
06052       ast_log(LOG_WARNING,"==================!!!!!!!!!!!!!!!Something changed the contexts in the middle of merging contexts!\n");
06053    }
06054    
06055    AST_RWLIST_WRLOCK(&hints);
06056    writelocktime = ast_tvnow();
06057 
06058    /* preserve all watchers for hints associated with this registrar */
06059    AST_RWLIST_TRAVERSE(&hints, hint, list) {
06060       if (!AST_LIST_EMPTY(&hint->callbacks) && !strcmp(registrar, hint->exten->parent->registrar)) {
06061          length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2 + sizeof(*this);
06062          if (!(this = ast_calloc(1, length)))
06063             continue;
06064          AST_LIST_APPEND_LIST(&this->callbacks, &hint->callbacks, entry);
06065          this->laststate = hint->laststate;
06066          this->context = this->data;
06067          strcpy(this->data, hint->exten->parent->name);
06068          this->exten = this->data + strlen(this->context) + 1;
06069          strcpy(this->exten, hint->exten->exten);
06070          AST_LIST_INSERT_HEAD(&store, this, list);
06071       }
06072    }
06073 
06074    /* save the old table and list */
06075    oldtable = contexts_table;
06076    oldcontextslist = contexts;
06077 
06078    /* move in the new table and list */
06079    contexts_table = exttable;
06080    contexts = *extcontexts;
06081    
06082    /* restore the watchers for hints that can be found; notify those that
06083       cannot be restored
06084    */
06085    while ((this = AST_LIST_REMOVE_HEAD(&store, list))) {
06086       struct pbx_find_info q = { .stacklen = 0 };
06087       exten = pbx_find_extension(NULL, NULL, &q, this->context, this->exten, PRIORITY_HINT, NULL, "", E_MATCH);
06088       /* If this is a pattern, dynamically create a new extension for this
06089        * particular match.  Note that this will only happen once for each
06090        * individual extension, because the pattern will no longer match first.
06091        */
06092       if (exten && exten->exten[0] == '_') {
06093          ast_add_extension_nolock(exten->parent->name, 0, this->exten, PRIORITY_HINT, NULL,
06094             0, exten->app, ast_strdup(exten->data), ast_free_ptr, registrar);
06095          /* rwlocks are not recursive locks */
06096          exten = ast_hint_extension_nolock(NULL, this->context, this->exten);
06097       }
06098 
06099       /* Find the hint in the list of hints */
06100       AST_RWLIST_TRAVERSE(&hints, hint, list) {
06101          if (hint->exten == exten)
06102             break;
06103       }
06104       if (!exten || !hint) {
06105          /* this hint has been removed, notify the watchers */
06106          while ((thiscb = AST_LIST_REMOVE_HEAD(&this->callbacks, entry))) {
06107             thiscb->callback(this->context, this->exten, AST_EXTENSION_REMOVED, thiscb->data);
06108             ast_free(thiscb);
06109          }
06110       } else {
06111          AST_LIST_APPEND_LIST(&hint->callbacks, &this->callbacks, entry);
06112          hint->laststate = this->laststate;
06113       }
06114       ast_free(this);
06115    }
06116 
06117    AST_RWLIST_UNLOCK(&hints);
06118    ast_unlock_contexts();
06119    endlocktime = ast_tvnow();
06120    
06121    /* the old list and hashtab no longer are relevant, delete them while the rest of asterisk
06122       is now freely using the new stuff instead */
06123    
06124    ast_hashtab_destroy(oldtable, NULL);
06125    
06126    for (tmp = oldcontextslist; tmp; ) {
06127       struct ast_context *next;  /* next starting point */
06128       next = tmp->next;
06129       __ast_internal_context_destroy(tmp);
06130       tmp = next;
06131    }
06132    enddeltime = ast_tvnow();
06133    
06134    ft = ast_tvdiff_us(writelocktime, begintime);
06135    ft /= 1000000.0;
06136    ast_verb(3,"Time to scan old dialplan and merge leftovers back into the new: %8.6f sec\n", ft);
06137    
06138    ft = ast_tvdiff_us(endlocktime, writelocktime);
06139    ft /= 1000000.0;
06140    ast_verb(3,"Time to restore hints and swap in new dialplan: %8.6f sec\n", ft);
06141 
06142    ft = ast_tvdiff_us(enddeltime, endlocktime);
06143    ft /= 1000000.0;
06144    ast_verb(3,"Time to delete the old dialplan: %8.6f sec\n", ft);
06145 
06146    ft = ast_tvdiff_us(enddeltime, begintime);
06147    ft /= 1000000.0;
06148    ast_verb(3,"Total time merge_contexts_delete: %8.6f sec\n", ft);
06149    return;
06150 }

int ast_parseable_goto ( struct ast_channel chan,
const char *  goto_string 
)

Note:
I can find neither parsable nor parseable at dictionary.com, but google gives me 169000 hits for parseable and only 49,800 for parsable

This function will handle locking the channel as needed.

Definition at line 8961 of file pbx.c.

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

08962 {
08963    return pbx_parseable_goto(chan, goto_string, 0);
08964 }

int ast_pbx_outgoing_app ( const char *  type,
int  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 7489 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_strlen_zero(), ast_variables_destroy(), ast_verb, async_wait(), chan, errno, LOG_WARNING, and outgoing_helper::vars.

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

07490 {
07491    struct ast_channel *chan;
07492    struct app_tmp *tmp;
07493    int res = -1, cdr_res = -1;
07494    struct outgoing_helper oh;
07495 
07496    memset(&oh, 0, sizeof(oh));
07497    oh.vars = vars;
07498    oh.account = account;
07499 
07500    if (locked_channel)
07501       *locked_channel = NULL;
07502    if (ast_strlen_zero(app)) {
07503       res = -1;
07504       goto outgoing_app_cleanup;
07505    }
07506    if (synchronous) {
07507       chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
07508       if (chan) {
07509          ast_set_variables(chan, vars);
07510          if (account)
07511             ast_cdr_setaccount(chan, account);
07512          if (chan->_state == AST_STATE_UP) {
07513             res = 0;
07514             ast_verb(4, "Channel %s was answered.\n", chan->name);
07515             tmp = ast_calloc(1, sizeof(*tmp));
07516             if (!tmp)
07517                res = -1;
07518             else {
07519                ast_copy_string(tmp->app, app, sizeof(tmp->app));
07520                if (appdata)
07521                   ast_copy_string(tmp->data, appdata, sizeof(tmp->data));
07522                tmp->chan = chan;
07523                if (synchronous > 1) {
07524                   if (locked_channel)
07525                      ast_channel_unlock(chan);
07526                   ast_pbx_run_app(tmp);
07527                } else {
07528                   if (locked_channel)
07529                      ast_channel_lock(chan);
07530                   if (ast_pthread_create_detached(&tmp->t, NULL, ast_pbx_run_app, tmp)) {
07531                      ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno));
07532                      ast_free(tmp);
07533                      if (locked_channel)
07534                         ast_channel_unlock(chan);
07535                      ast_hangup(chan);
07536                      res = -1;
07537                   } else {
07538                      if (locked_channel)
07539                         *locked_channel = chan;
07540                   }
07541                }
07542             }
07543          } else {
07544             ast_verb(4, "Channel %s was never answered.\n", chan->name);
07545             if (chan->cdr) { /* update the cdr */
07546                /* here we update the status of the call, which sould be busy.
07547                 * if that fails then we set the status to failed */
07548                if (ast_cdr_disposition(chan->cdr, chan->hangupcause))
07549                   ast_cdr_failed(chan->cdr);
07550             }
07551             ast_hangup(chan);
07552          }
07553       }
07554 
07555       if (res < 0) { /* the call failed for some reason */
07556          if (*reason == 0) { /* if the call failed (not busy or no answer)
07557                         * update the cdr with the failed message */
07558             cdr_res = ast_pbx_outgoing_cdr_failed();
07559             if (cdr_res != 0) {
07560                res = cdr_res;
07561                goto outgoing_app_cleanup;
07562             }
07563          }
07564       }
07565 
07566    } else {
07567       struct async_stat *as;
07568       if (!(as = ast_calloc(1, sizeof(*as)))) {
07569          res = -1;
07570          goto outgoing_app_cleanup;
07571       }
07572       chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
07573       if (!chan) {
07574          ast_free(as);
07575          res = -1;
07576          goto outgoing_app_cleanup;
07577       }
07578       as->chan = chan;
07579       ast_copy_string(as->app, app, sizeof(as->app));
07580       if (appdata)
07581          ast_copy_string(as->appdata,  appdata, sizeof(as->appdata));
07582       as->timeout = timeout;
07583       ast_set_variables(chan, vars);
07584       if (account)
07585          ast_cdr_setaccount(chan, account);
07586       /* Start a new thread, and get something handling this channel. */
07587       if (locked_channel)
07588          ast_channel_lock(chan);
07589       if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) {
07590          ast_log(LOG_WARNING, "Failed to start async wait\n");
07591          ast_free(as);
07592          if (locked_channel)
07593             ast_channel_unlock(chan);
07594          ast_hangup(chan);
07595          res = -1;
07596          goto outgoing_app_cleanup;
07597       } else {
07598          if (locked_channel)
07599             *locked_channel = chan;
07600       }
07601       res = 0;
07602    }
07603 outgoing_app_cleanup:
07604    ast_variables_destroy(vars);
07605    return res;
07606 }

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

References ast_cdr_detach(), ast_cdr_end(), ast_cdr_failed(), ast_cdr_init(), ast_cdr_start(), ast_channel_alloc(), ast_channel_free(), AST_STATE_DOWN, ast_channel::cdr, and chan.

Referenced by ast_pbx_outgoing_app(), and ast_pbx_outgoing_exten().

07298 {
07299    /* allocate a channel */
07300    struct ast_channel *chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "%s", "");
07301 
07302    if (!chan)
07303       return -1;  /* failure */
07304 
07305    if (!chan->cdr) {
07306       /* allocation of the cdr failed */
07307       ast_channel_free(chan);   /* free the channel */
07308       return -1;                /* return failure */
07309    }
07310 
07311    /* allocation of the cdr was successful */
07312    ast_cdr_init(chan->cdr, chan);  /* initialize our channel's cdr */
07313    ast_cdr_start(chan->cdr);       /* record the start and stop time */
07314    ast_cdr_end(chan->cdr);
07315    ast_cdr_failed(chan->cdr);      /* set the status to failed */
07316    ast_cdr_detach(chan->cdr);      /* post and free the record */
07317    chan->cdr = NULL;
07318    ast_channel_free(chan);         /* free the channel */
07319 
07320    return 0;  /* success */
07321 }

int ast_pbx_outgoing_exten ( const char *  type,
int  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 7323 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, chan, outgoing_helper::cid_name, outgoing_helper::cid_num, outgoing_helper::context, ast_channel::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(), and orig_exten().

07324 {
07325    struct ast_channel *chan;
07326    struct async_stat *as;
07327    int res = -1, cdr_res = -1;
07328    struct outgoing_helper oh;
07329 
07330    if (synchronous) {
07331       oh.context = context;
07332       oh.exten = exten;
07333       oh.priority = priority;
07334       oh.cid_num = cid_num;
07335       oh.cid_name = cid_name;
07336       oh.account = account;
07337       oh.vars = vars;
07338       oh.parent_channel = NULL;
07339 
07340       chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
07341       if (channel) {
07342          *channel = chan;
07343          if (chan)
07344             ast_channel_lock(chan);
07345       }
07346       if (chan) {
07347          if (chan->_state == AST_STATE_UP) {
07348                res = 0;
07349             ast_verb(4, "Channel %s was answered.\n", chan->name);
07350 
07351             if (synchronous > 1) {
07352                if (channel)
07353                   ast_channel_unlock(chan);
07354                if (ast_pbx_run(chan)) {
07355                   ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name);
07356                   if (channel)
07357                      *channel = NULL;
07358                   ast_hangup(chan);
07359                   chan = NULL;
07360                   res = -1;
07361                }
07362             } else {
07363                if (ast_pbx_start(chan)) {
07364                   ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name);
07365                   if (channel) {
07366                      *channel = NULL;
07367                      ast_channel_unlock(chan);
07368                   }
07369                   ast_hangup(chan);
07370                   res = -1;
07371                }
07372                chan = NULL;
07373             }
07374          } else {
07375             ast_verb(4, "Channel %s was never answered.\n", chan->name);
07376 
07377             if (chan->cdr) { /* update the cdr */
07378                /* here we update the status of the call, which sould be busy.
07379                 * if that fails then we set the status to failed */
07380                if (ast_cdr_disposition(chan->cdr, chan->hangupcause))
07381                   ast_cdr_failed(chan->cdr);
07382             }
07383 
07384             if (channel) {
07385                *channel = NULL;
07386                ast_channel_unlock(chan);
07387             }
07388             ast_hangup(chan);
07389             chan = NULL;
07390          }
07391       }
07392 
07393       if (res < 0) { /* the call failed for some reason */
07394          if (*reason == 0) { /* if the call failed (not busy or no answer)
07395                         * update the cdr with the failed message */
07396             cdr_res = ast_pbx_outgoing_cdr_failed();
07397             if (cdr_res != 0) {
07398                res = cdr_res;
07399                goto outgoing_exten_cleanup;
07400             }
07401          }
07402 
07403          /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */
07404          /* check if "failed" exists */
07405          if (ast_exists_extension(chan, context, "failed", 1, NULL)) {
07406             chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "OutgoingSpoolFailed");
07407             if (chan) {
07408                char failed_reason[4] = "";
07409                if (!ast_strlen_zero(context))
07410                   ast_copy_string(chan->context, context, sizeof(chan->context));
07411                set_ext_pri(chan, "failed", 1);
07412                ast_set_variables(chan, vars);
07413                snprintf(failed_reason, sizeof(failed_reason), "%d", *reason);
07414                pbx_builtin_setvar_helper(chan, "REASON", failed_reason);
07415                if (account)
07416                   ast_cdr_setaccount(chan, account);
07417                if (ast_pbx_run(chan)) {
07418                   ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name);
07419                   ast_hangup(chan);
07420                }
07421                chan = NULL;
07422             }
07423          }
07424       }
07425    } else {
07426       if (!(as = ast_calloc(1, sizeof(*as)))) {
07427          res = -1;
07428          goto outgoing_exten_cleanup;
07429       }
07430       chan = ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name);
07431       if (channel) {
07432          *channel = chan;
07433          if (chan)
07434             ast_channel_lock(chan);
07435       }
07436       if (!chan) {
07437          ast_free(as);
07438          res = -1;
07439          goto outgoing_exten_cleanup;
07440       }
07441       as->chan = chan;
07442       ast_copy_string(as->context, context, sizeof(as->context));
07443       set_ext_pri(as->chan,  exten, priority);
07444       as->timeout = timeout;
07445       ast_set_variables(chan, vars);
07446       if (account)
07447          ast_cdr_setaccount(chan, account);
07448       if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) {
07449          ast_log(LOG_WARNING, "Failed to start async wait\n");
07450          ast_free(as);
07451          if (channel) {
07452             *channel = NULL;
07453             ast_channel_unlock(chan);
07454          }
07455          ast_hangup(chan);
07456          res = -1;
07457          goto outgoing_exten_cleanup;
07458       }
07459       res = 0;
07460    }
07461 outgoing_exten_cleanup:
07462    ast_variables_destroy(vars);
07463    return res;
07464 }

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

References ast_pbx_run_args().

Referenced by ast_pbx_outgoing_exten(), async_wait(), do_idle_thread(), mgcp_ss(), skinny_newcall(), ss_thread(), and unistim_ss().

04070 {
04071    return ast_pbx_run_args(c, NULL);
04072 }

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

run the application and free the descriptor once done

Definition at line 7474 of file pbx.c.

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

Referenced by ast_pbx_outgoing_app().

07475 {
07476    struct app_tmp *tmp = data;
07477    struct ast_app *app;
07478    app = pbx_findapp(tmp->app);
07479    if (app) {
07480       ast_verb(4, "Launching %s(%s) on %s\n", tmp->app, tmp->data, tmp->chan->name);
07481       pbx_exec(tmp->chan, app, tmp->data);
07482    } else
07483       ast_log(LOG_WARNING, "No such application '%s'\n", tmp->app);
07484    ast_hangup(tmp->chan);
07485    ast_free(tmp);
07486    return NULL;
07487 }

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

References __ast_pbx_run(), AST_PBX_CALL_LIMIT, AST_PBX_SUCCESS, decrease_call_count(), and increase_call_count().

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

04055 {
04056    enum ast_pbx_result res = AST_PBX_SUCCESS;
04057 
04058    if (increase_call_count(c)) {
04059       return AST_PBX_CALL_LIMIT;
04060    }
04061 
04062    res = __ast_pbx_run(c, args);
04063 
04064    decrease_call_count();
04065 
04066    return res;
04067 }

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

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

Referenced by __oh323_new(), alsa_new(), ast_async_goto(), ast_bridge_call_thread(), ast_iax2_new(), ast_pbx_outgoing_exten(), bridge_exec(), check_goto_on_transfer(), console_new(), dahdi_new(), dial_exec_full(), gtalk_new(), gtalk_newcall(), handle_request_invite(), jingle_new(), jingle_newcall(), local_call(), manage_parkinglot(), mgcp_new(), nbs_new(), oss_new(), pbx_start_chan(), phone_new(), rpt_call(), sip_new(), skinny_new(), unistim_new(), and usbradio_new().

04033 {
04034    pthread_t t;
04035 
04036    if (!c) {
04037       ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
04038       return AST_PBX_FAILED;
04039    }
04040 
04041    if (increase_call_count(c))
04042       return AST_PBX_CALL_LIMIT;
04043 
04044    /* Start a new thread, and get something handling this channel. */
04045    if (ast_pthread_create_detached(&t, NULL, pbx_thread, c)) {
04046       ast_log(LOG_WARNING, "Failed to create new channel thread\n");
04047       decrease_call_count();
04048       return AST_PBX_FAILED;
04049    }
04050 
04051    return AST_PBX_SUCCESS;
04052 }

int ast_processed_calls ( void   ) 

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

Definition at line 4079 of file pbx.c.

References totalcalls.

Referenced by handle_chanlist(), and handle_showcalls().

04080 {
04081    return totalcalls;
04082 }

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

08700 {
08701    return ast_rwlock_rdlock(&con->lock);
08702 }

int ast_rdlock_contexts ( void   ) 

Read locks the context list.

Return values:
0 on success
-1 on error

Definition at line 8681 of file pbx.c.

References ast_rwlock_rdlock(), and conlock.

Referenced by _macro_exec(), ast_context_find(), ast_context_find_or_create(), ast_context_lockmacro(), 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(), handle_statechange(), manager_show_dialplan_helper(), pbx_extension_helper(), show_debug_helper(), show_dialplan_helper(), and unreference_cached_app().

08682 {
08683    return ast_rwlock_rdlock(&conlock);
08684 }

int ast_register_application2 ( const char *  app,
int(*)(struct ast_channel *, void *)  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 4533 of file pbx.c.

References ast_calloc, 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_verb, COLOR_BRCYAN, ast_app::description, ast_app::execute, ast_app::list, LOG_WARNING, ast_app::module, ast_app::name, ast_app::synopsis, and term_color().

Referenced by ast_features_init(), and load_pbx().

04534 {
04535    struct ast_app *tmp, *cur = NULL;
04536    char tmps[80];
04537    int length, res;
04538 
04539    AST_RWLIST_WRLOCK(&apps);
04540    AST_RWLIST_TRAVERSE(&apps, tmp, list) {
04541       if (!(res = strcasecmp(app, tmp->name))) {
04542          ast_log(LOG_WARNING, "Already have an application '%s'\n", app);
04543          AST_RWLIST_UNLOCK(&apps);
04544          return -1;
04545       } else if (res < 0)
04546          break;
04547    }
04548 
04549    length = sizeof(*tmp) + strlen(app) + 1;
04550 
04551    if (!(tmp = ast_calloc(1, length))) {
04552       AST_RWLIST_UNLOCK(&apps);
04553       return -1;
04554    }
04555 
04556    strcpy(tmp->name, app);
04557    tmp->execute = execute;
04558    tmp->synopsis = synopsis;
04559    tmp->description = description;
04560    tmp->module = mod;
04561 
04562    /* Store in alphabetical order */
04563    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, cur, list) {
04564       if (strcasecmp(tmp->name, cur->name) < 0) {
04565          AST_RWLIST_INSERT_BEFORE_CURRENT(tmp, list);
04566          break;
04567       }
04568    }
04569    AST_RWLIST_TRAVERSE_SAFE_END;
04570    if (!cur)
04571       AST_RWLIST_INSERT_TAIL(&apps, tmp, list);
04572 
04573    ast_verb(2, "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps)));
04574 
04575    AST_RWLIST_UNLOCK(&apps);
04576 
04577    return 0;
04578 }

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.

Returns:
0 on success, and other than 0 on failure

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

04585 {
04586    struct ast_switch *tmp;
04587 
04588    AST_RWLIST_WRLOCK(&switches);
04589    AST_RWLIST_TRAVERSE(&switches, tmp, list) {
04590       if (!strcasecmp(tmp->name, sw->name)) {
04591          AST_RWLIST_UNLOCK(&switches);
04592          ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name);
04593          return -1;
04594       }
04595    }
04596    AST_RWLIST_INSERT_TAIL(&switches, sw, list);
04597    AST_RWLIST_UNLOCK(&switches);
04598 
04599    return 0;
04600 }

static int ast_remove_hint ( struct ast_exten e  )  [static]

Remove hint from extension.

Definition at line 3569 of file pbx.c.

References AST_EXTENSION_DEACTIVATED, ast_free, AST_LIST_REMOVE_HEAD, AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, ast_state_cb::callback, ast_hint::callbacks, ast_state_cb::data, ast_state_cb::entry, ast_exten::exten, ast_hint::exten, ast_context::name, and ast_exten::parent.

Referenced by destroy_exten().

03570 {
03571    /* Cleanup the Notifys if hint is removed */
03572    struct ast_hint *hint;
03573    struct ast_state_cb *cblist;
03574    int res = -1;
03575 
03576    if (!e)
03577       return -1;
03578 
03579    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&hints, hint, list) {
03580       if (hint->exten != e)
03581          continue;
03582 
03583       while ((cblist = AST_LIST_REMOVE_HEAD(&hint->callbacks, entry))) {
03584          /* Notify with -1 and remove all callbacks */
03585          cblist->callback(hint->exten->parent->name, hint->exten->exten, 
03586             AST_EXTENSION_DEACTIVATED, cblist->data);
03587          ast_free(cblist);
03588       }
03589 
03590       AST_RWLIST_REMOVE_CURRENT(list);
03591       ast_free(hint);
03592 
03593          res = 0;
03594 
03595       break;
03596    }
03597    AST_RWLIST_TRAVERSE_SAFE_END;
03598 
03599    return res;
03600 }

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

03647 {
03648    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN, found, combined_find_spawn);
03649 }

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

08705 {
08706    return ast_rwlock_unlock(&con->lock);
08707 }

int ast_unlock_contexts ( void   ) 

Unlocks contexts.

Return values:
0 on success
-1 on failure

Definition at line 8686 of file pbx.c.

References ast_rwlock_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(), handle_statechange(), manager_show_dialplan_helper(), pbx_extension_helper(), show_debug_helper(), show_dialplan_helper(), and unreference_cached_app().

08687 {
08688    return ast_rwlock_unlock(&conlock);
08689 }

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

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

05795 {
05796    struct ast_app *tmp;
05797 
05798    AST_RWLIST_WRLOCK(&apps);
05799    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, tmp, list) {
05800       if (!strcasecmp(app, tmp->name)) {
05801          unreference_cached_app(tmp);
05802          AST_RWLIST_REMOVE_CURRENT(list);
05803          ast_verb(2, "Unregistered application '%s'\n", tmp->name);
05804          ast_free(tmp);
05805          break;
05806       }
05807    }
05808    AST_RWLIST_TRAVERSE_SAFE_END;
05809    AST_RWLIST_UNLOCK(&apps);
05810 
05811    return tmp ? 0 : -1;
05812 }

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

04603 {
04604    AST_RWLIST_WRLOCK(&switches);
04605    AST_RWLIST_REMOVE(&switches, sw, list);
04606    AST_RWLIST_UNLOCK(&switches);
04607 }

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

Definition at line 8818 of file pbx.c.

References exten, and ast_context::root.

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

08820 {
08821    if (!exten)
08822       return con ? con->root : NULL;
08823    else
08824       return exten->next;
08825 }

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

Definition at line 8851 of file pbx.c.

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

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

08853 {
08854    if (!ip)
08855       return con ? con->ignorepats : NULL;
08856    else
08857       return ip->next;
08858 }

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

Definition at line 8842 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(), find_matching_priority(), handle_cli_dialplan_save(), lookup_ci(), manager_show_dialplan_helper(), and show_dialplan_helper().

08844 {
08845    if (!inc)
08846       return con ? con->includes : NULL;
08847    else
08848       return inc->next;
08849 }

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

Definition at line 8827 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(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().

08829 {
08830    if (!sw)
08831       return con ? AST_LIST_FIRST(&con->alts) : NULL;
08832    else
08833       return AST_LIST_NEXT(sw, list);
08834 }

struct ast_context* ast_walk_contexts ( struct ast_context con  ) 

Definition at line 8813 of file pbx.c.

References contexts, and ast_context::next.

Referenced by _macro_exec(), ast_context_find(), ast_context_lockmacro(), ast_context_unlockmacro(), 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(), find_matching_priority(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), pbx_find_extension(), pbx_load_module(), show_debug_helper(), show_dialplan_helper(), and unreference_cached_app().

08814 {
08815    return con ? con->next : contexts;
08816 }

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

Definition at line 8836 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(), pbx_find_extension(), show_dialplan_helper(), and unreference_cached_app().

08838 {
08839    return priority ? priority->peer : exten;
08840 }

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

08695 {
08696    return ast_rwlock_wrlock(&con->lock);
08697 }

int ast_wrlock_contexts ( void   ) 

Write locks the context list.

Return values:
0 on success
-1 on error

Definition at line 8673 of file pbx.c.

References ast_atomic_fetchadd_int(), ast_rwlock_wrlock(), and conlock.

Referenced by ast_context_destroy(), ast_context_find_or_create(), ast_merge_contexts_and_delete(), and complete_dialplan_remove_include().

08674 {
08675    int res = ast_rwlock_wrlock(&conlock);
08676    if (!res)
08677       ast_atomic_fetchadd_int(&conlock_wrlock_version, 1);
08678    return res;
08679 }

int ast_wrlock_contexts_version ( void   ) 

Definition at line 8665 of file pbx.c.

Referenced by ast_merge_contexts_and_delete().

08666 {
08667    return conlock_wrlock_version;
08668 }

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

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

07237 {
07238    struct async_stat *as = data;
07239    struct ast_channel *chan = as->chan;
07240    int timeout = as->timeout;
07241    int res;
07242    struct ast_frame *f;
07243    struct ast_app *app;
07244 
07245    while (timeout && (chan->_state != AST_STATE_UP)) {
07246       res = ast_waitfor(chan, timeout);
07247       if (res < 1)
07248          break;
07249       if (timeout > -1)
07250          timeout = res;
07251       f = ast_read(chan);
07252       if (!f)
07253          break;
07254       if (f->frametype == AST_FRAME_CONTROL) {
07255          if ((f->subclass == AST_CONTROL_BUSY)  ||
07256              (f->subclass == AST_CONTROL_CONGESTION) ) {
07257             ast_frfree(f);
07258             break;
07259          }
07260       }
07261       ast_frfree(f);
07262    }
07263    if (chan->_state == AST_STATE_UP) {
07264       if (!ast_strlen_zero(as->app)) {
07265          app = pbx_findapp(as->app);
07266          if (app) {
07267             ast_verb(3, "Launching %s(%s) on %s\n", as->app, as->appdata, chan->name);
07268             pbx_exec(chan, app, as->appdata);
07269          } else
07270             ast_log(LOG_WARNING, "No such application '%s'\n", as->app);
07271       } else {
07272          if (!ast_strlen_zero(as->context))
07273             ast_copy_string(chan->context, as->context, sizeof(chan->context));
07274          if (!ast_strlen_zero(as->exten))
07275             ast_copy_string(chan->exten, as->exten, sizeof(chan->exten));
07276          if (as->priority > 0)
07277             chan->priority = as->priority;
07278          /* Run the PBX */
07279          if (ast_pbx_run(chan)) {
07280             ast_log(LOG_ERROR, "Failed to start PBX on %s\n", chan->name);
07281          } else {
07282             /* PBX will have taken care of this */
07283             chan = NULL;
07284          }
07285       }
07286    }
07287    ast_free(as);
07288    if (chan)
07289       ast_hangup(chan);
07290    return NULL;
07291 }

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

Definition at line 1132 of file pbx.c.

References match_char::alt_char, ast_cli(), ast_str_alloca, ast_str_set(), match_char::deleted, ast_exten::exten, match_char::exten, match_char::is_pattern, match_char::next_char, match_char::specificity, ast_str::str, and match_char::x.

Referenced by show_debug_helper().

01133 {
01134    char extenstr[40];
01135    struct ast_str *my_prefix = ast_str_alloca(1024);
01136    
01137    extenstr[0] = '\0';
01138 
01139    if (node && node->exten && node->exten)
01140       snprintf(extenstr, sizeof(extenstr), "(%p)", node->exten);
01141    
01142    if (strlen(node->x) > 1) {
01143       ast_cli(fd, "%s[%s]:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N', 
01144          node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "", 
01145          node->exten ? node->exten->exten : "", extenstr);
01146    } else {
01147       ast_cli(fd, "%s%s:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N', 
01148          node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "", 
01149          node->exten ? node->exten->exten : "", extenstr);
01150    }
01151 
01152    ast_str_set(&my_prefix, 0, "%s+       ", prefix);
01153 
01154    if (node->next_char)
01155       cli_match_char_tree(node->next_char, my_prefix->str, fd);
01156 
01157    if (node->alt_char)
01158       cli_match_char_tree(node->alt_char, prefix, fd);
01159 }

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.

Return values:
0 on timeout or done.
-1 on error.

Definition at line 3665 of file pbx.c.

References ast_channel::_softhangup, ast_matchmore_extension(), AST_SOFTHANGUP_ASYNCGOTO, ast_waitfordigit(), ast_channel::cid, ast_callerid::cid_num, ast_channel::context, ast_pbx::dtimeoutms, and ast_channel::pbx.

03666 {
03667    int digit;
03668 
03669    buf[pos] = '\0';  /* make sure it is properly terminated */
03670    while (ast_matchmore_extension(c, c->context, buf, 1, c->cid.cid_num)) {
03671       /* As long as we're willing to wait, and as long as it's not defined,
03672          keep reading digits until we can't possibly get a right answer anymore.  */
03673       digit = ast_waitfordigit(c, waittime);
03674       if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
03675          c->_softhangup = 0;
03676       } else {
03677          if (!digit) /* No entry */
03678             break;
03679          if (digit < 0) /* Error, maybe a  hangup */
03680             return -1;
03681          if (pos < buflen - 1) { /* XXX maybe error otherwise ? */
03682             buf[pos++] = digit;
03683             buf[pos] = '\0';
03684          }
03685          waittime = c->pbx->dtimeoutms;
03686       }
03687    }
03688    return 0;
03689 }

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

Definition at line 339 of file pbx.c.

Referenced by add_exten_to_pattern_tree().

00340 {
00341    const char *ac = a;
00342    const char *bc = b;
00343    if ((*ac) < (*bc))
00344       return -1;
00345    else if ((*ac) == (*bc))
00346       return 0;
00347    else
00348       return 1;
00349 }

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

References ast_get_extension_name(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strdup, ast_hint::exten, and ast_hint::list.

Referenced by handle_show_hint().

04763 {
04764    struct ast_hint *hint;
04765    char *ret = NULL;
04766    int which = 0;
04767    int wordlen;
04768 
04769    if (pos != 3)
04770       return NULL;
04771    
04772    wordlen = strlen(word);
04773 
04774    AST_RWLIST_RDLOCK(&hints);
04775    /* walk through all hints */
04776    AST_RWLIST_TRAVERSE(&hints, hint, list) {
04777       if (!strncasecmp(word, ast_get_extension_name(hint->exten), wordlen) && ++which > state) {
04778          ret = ast_strdup(ast_get_extension_name(hint->exten));
04779          break;
04780       }
04781    }
04782    AST_RWLIST_UNLOCK(&hints);
04783 
04784    return ret;
04785 }

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

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

04960 {
04961    struct ast_context *c = NULL;
04962    char *ret = NULL;
04963    int which = 0;
04964    int wordlen;
04965 
04966    /* we are do completion of [exten@]context on second position only */
04967    if (pos != 2)
04968       return NULL;
04969 
04970    ast_rdlock_contexts();
04971 
04972    wordlen = strlen(word);
04973 
04974    /* walk through all contexts and return the n-th match */
04975    while ( (c = ast_walk_contexts(c)) ) {
04976       if (!strncasecmp(word, ast_get_context_name(c), wordlen) && ++which > state) {
04977          ret = ast_strdup(ast_get_context_name(c));
04978          break;
04979       }
04980    }
04981 
04982    ast_unlock_contexts();
04983 
04984    return ret;
04985 }

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

Definition at line 5929 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::peer_table, ast_exten::priority, and ast_exten::registrar.

Referenced by ast_merge_contexts_and_delete().

05930 {
05931    struct ast_context *new = ast_hashtab_lookup(exttable, context); /* is there a match in the new set? */
05932    struct ast_exten *exten_item, *prio_item, *new_exten_item, *new_prio_item;
05933    struct ast_hashtab_iter *exten_iter;
05934    struct ast_hashtab_iter *prio_iter;
05935    int insert_count = 0;
05936    int first = 1;
05937    
05938    /* We'll traverse all the extensions/prios, and see which are not registrar'd with
05939       the current registrar, and copy them to the new context. If the new context does not
05940       exist, we'll create it "on demand". If no items are in this context to copy, then we'll
05941       only create the empty matching context if the old one meets the criteria */
05942    
05943    if (context->root_table) {
05944       exten_iter = ast_hashtab_start_traversal(context->root_table);
05945       while ((exten_item=ast_hashtab_next(exten_iter))) {
05946          if (new) {
05947             new_exten_item = ast_hashtab_lookup(new->root_table, exten_item);
05948          } else {
05949             new_exten_item = NULL;
05950          }
05951          prio_iter = ast_hashtab_start_traversal(exten_item->peer_table);
05952          while ((prio_item=ast_hashtab_next(prio_iter))) {
05953             int res1;
05954             char *dupdstr;
05955             
05956             if (new_exten_item) {
05957                new_prio_item = ast_hashtab_lookup(new_exten_item->peer_table, prio_item);
05958             } else {
05959                new_prio_item = NULL;
05960             }
05961             if (strcmp(prio_item->registrar,registrar) == 0) {
05962                continue;
05963             }
05964             /* make sure the new context exists, so we have somewhere to stick this exten/prio */
05965             if (!new) {
05966                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 */
05967             }
05968 
05969             /* copy in the includes, switches, and ignorepats */
05970             if (first) { /* but, only need to do this once */
05971                context_merge_incls_swits_igps_other_registrars(new, context, registrar);
05972                first = 0;
05973             }
05974             
05975             if (!new) {
05976                ast_log(LOG_ERROR,"Could not allocate a new context for %s in merge_and_delete! Danger!\n", context->name);
05977                return; /* no sense continuing. */
05978             }
05979             /* we will not replace existing entries in the new context with stuff from the old context.
05980                but, if this is because of some sort of registrar conflict, we ought to say something... */
05981             
05982             dupdstr = ast_strdup(prio_item->data);
05983             
05984             res1 = ast_add_extension2(new, 0, prio_item->exten, prio_item->priority, prio_item->label, 
05985                                 prio_item->cidmatch, prio_item->app, dupdstr, prio_item->datad, prio_item->registrar);
05986             if (!res1 && new_exten_item && new_prio_item){
05987                ast_verb(3,"Dropping old dialplan item %s/%s/%d [%s(%s)] (registrar=%s) due to conflict with new dialplan\n",
05988                      context->name, prio_item->exten, prio_item->priority, prio_item->app, (char*)prio_item->data, prio_item->registrar);
05989             } else {
05990                /* 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,
05991                 and no double frees take place, either! */
05992                insert_count++;
05993             }
05994          }
05995          ast_hashtab_end_traversal(prio_iter);
05996       }
05997       ast_hashtab_end_traversal(exten_iter);
05998    }
05999    
06000    if (!insert_count && !new && (strcmp(context->registrar, registrar) != 0 ||
06001         (strcmp(context->registrar, registrar) == 0 && context->refcount > 1))) {
06002       /* we could have given it the registrar of the other module who incremented the refcount,
06003          but that's not available, so we give it the registrar we know about */
06004       new = ast_context_find_or_create(extcontexts, exttable, context->name, context->registrar);
06005       
06006       /* copy in the includes, switches, and ignorepats */
06007       context_merge_incls_swits_igps_other_registrars(new, context, registrar);
06008    }
06009 }

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

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

05897 {
05898    struct ast_include *i;
05899    struct ast_ignorepat *ip;
05900    struct ast_sw *sw;
05901    
05902    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);
05903    /* copy in the includes, switches, and ignorepats */
05904    /* walk through includes */
05905    for (i = NULL; (i = ast_walk_context_includes(old, i)) ; ) {
05906       if (strcmp(ast_get_include_registrar(i), registrar) == 0)
05907          continue; /* not mine */
05908       ast_context_add_include2(new, ast_get_include_name(i), ast_get_include_registrar(i));
05909    }
05910    
05911    /* walk through switches */
05912    for (sw = NULL; (sw = ast_walk_context_switches(old, sw)) ; ) {
05913       if (strcmp(ast_get_switch_registrar(sw), registrar) == 0)
05914          continue; /* not mine */
05915       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));
05916    }
05917    
05918    /* walk thru ignorepats ... */
05919    for (ip = NULL; (ip = ast_walk_context_ignorepats(old, ip)); ) {
05920       if (strcmp(ast_get_ignorepat_registrar(ip), registrar) == 0)
05921          continue; /* not mine */
05922       ast_context_add_ignorepat2(new, ast_get_ignorepat_name(ip), ast_get_ignorepat_registrar(ip));
05923    }
05924 }

static void create_match_char_tree ( struct ast_context con  )  [static]

Definition at line 1600 of file pbx.c.

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

Referenced by pbx_find_extension().

01601 {
01602    struct ast_hashtab_iter *t1;
01603    struct ast_exten *e1;
01604 #ifdef NEED_DEBUG
01605    int biggest_bucket, resizes, numobjs, numbucks;
01606    
01607    ast_log(LOG_DEBUG,"Creating Extension Trie for context %s\n", con->name);
01608    ast_hashtab_get_stats(con->root_table, &biggest_bucket, &resizes, &numobjs, &numbucks);
01609    ast_log(LOG_DEBUG,"This tree has %d objects in %d bucket lists, longest list=%d objects, and has resized %d times\n",
01610          numobjs, numbucks, biggest_bucket, resizes);
01611 #endif
01612    t1 = ast_hashtab_start_traversal(con->root_table);
01613    while( (e1 = ast_hashtab_next(t1)) ) {
01614       if (e1->exten)
01615          add_exten_to_pattern_tree(con, e1, 0);
01616       else
01617          ast_log(LOG_ERROR,"Attempt to create extension with no extension name.\n");
01618    }
01619    ast_hashtab_end_traversal(t1);
01620 }

static void decrease_call_count ( void   )  [static]

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

03991 {
03992    ast_mutex_lock(&maxcalllock);
03993    if (countcalls > 0)
03994       countcalls--;
03995    ast_mutex_unlock(&maxcalllock);
03996 }

static void destroy_exten ( struct ast_exten e  )  [static]

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

03999 {
04000    if (e->priority == PRIORITY_HINT)
04001       ast_remove_hint(e);
04002 
04003    if (e->peer_table)
04004       ast_hashtab_destroy(e->peer_table,0);
04005    if (e->peer_label_table)
04006       ast_hashtab_destroy(e->peer_label_table, 0);
04007    if (e->datad)
04008       e->datad(e->data);
04009    ast_free(e);
04010 }

static void destroy_pattern_tree ( struct match_char pattern_tree  )  [static]

Definition at line 1622 of file pbx.c.

References match_char::alt_char, match_char::exten, free, match_char::next_char, and match_char::x.

Referenced by __ast_internal_context_destroy().

01623 {
01624    /* destroy all the alternates */
01625    if (pattern_tree->alt_char) {
01626       destroy_pattern_tree(pattern_tree->alt_char);
01627       pattern_tree->alt_char = 0;
01628    }
01629    /* destroy all the nexts */
01630    if (pattern_tree->next_char) {
01631       destroy_pattern_tree(pattern_tree->next_char);
01632       pattern_tree->next_char = 0;
01633    }
01634    pattern_tree->exten = 0; /* never hurts to make sure there's no pointers laying around */
01635    if (pattern_tree->x)
01636       free(pattern_tree->x);
01637    free(pattern_tree);
01638 }

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

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

Referenced by load_module(), and load_pbx().

08612 {
08613    const char *device;
08614    struct statechange *sc;
08615 
08616    device = ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE);
08617    if (ast_strlen_zero(device)) {
08618       ast_log(LOG_ERROR, "Received invalid event that had no device IE\n");
08619       return;
08620    }
08621 
08622    if (!(sc = ast_calloc(1, sizeof(*sc) + strlen(device) + 1)))
08623       return;
08624    strcpy(sc->dev, device);
08625    if (ast_taskprocessor_push(device_state_tps, handle_statechange, sc) < 0) {
08626       ast_free(sc);
08627    }
08628 }

static void exception_store_free ( void *  data  )  [static]

Definition at line 2564 of file pbx.c.

References ast_free, and ast_string_field_free_memory.

02565 {
02566    struct pbx_exception *exception = data;
02567    ast_string_field_free_memory(exception);
02568    ast_free(exception);
02569 }

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

the full routine to compare extensions in rules.

Definition at line 1765 of file pbx.c.

References ext_cmp1().

Referenced by ast_add_extension2_lockopt(), and ast_extension_cmp().

01766 {
01767    /* make sure non-patterns come first.
01768     * If a is not a pattern, it either comes first or
01769     * we use strcmp to compare the strings.
01770     */
01771    int ret = 0;
01772 
01773    if (a[0] != '_')
01774       return (b[0] == '_') ? -1 : strcmp(a, b);
01775 
01776    /* Now we know a is a pattern; if b is not, a comes first */
01777    if (b[0] != '_')
01778       return 1;
01779 #if 0 /* old mode for ext matching */
01780    return strcmp(a, b);
01781 #endif
01782    /* ok we need full pattern sorting routine */
01783    while (!ret && a && b)
01784       ret = ext_cmp1(&a) - ext_cmp1(&b);
01785    if (ret == 0)
01786       return 0;
01787    else
01788       return (ret > 0) ? 1 : -1;
01789 }

static int ext_cmp1 ( const char **  p  )  [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.

Definition at line 1694 of file pbx.c.

References ast_log(), and LOG_WARNING.

Referenced by ext_cmp().

01695 {
01696    uint32_t chars[8];
01697    int c, cmin = 0xff, count = 0;
01698    const char *end;
01699 
01700    /* load, sign extend and advance pointer until we find
01701     * a valid character.
01702     */
01703    c = *(*p)++;
01704 
01705    /* always return unless we have a set of chars */
01706    switch (toupper(c)) {
01707    default: /* ordinary character */
01708       return 0x0000 | (c & 0xff);
01709 
01710    case 'N':   /* 2..9 */
01711       return 0x0800 | '2' ;
01712 
01713    case 'X':   /* 0..9 */
01714       return 0x0A00 | '0';
01715 
01716    case 'Z':   /* 1..9 */
01717       return 0x0900 | '1';
01718 
01719    case '.':   /* wildcard */
01720       return 0x10000;
01721 
01722    case '!':   /* earlymatch */
01723       return 0x20000;   /* less specific than NULL */
01724 
01725    case '\0':  /* empty string */
01726       *p = NULL;
01727       return 0x30000;
01728 
01729    case '[':   /* pattern */
01730       break;
01731    }
01732    /* locate end of set */
01733    end = strchr(*p, ']');  
01734 
01735    if (end == NULL) {
01736       ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n");
01737       return 0x40000;   /* XXX make this entry go last... */
01738    }
01739 
01740    memset(chars, '\0', sizeof(chars)); /* clear all chars in the set */
01741    for (; *p < end  ; (*p)++) {
01742       unsigned char c1, c2;   /* first-last char in range */
01743       c1 = (unsigned char)((*p)[0]);
01744       if (*p + 2 < end && (*p)[1] == '-') { /* this is a range */
01745          c2 = (unsigned char)((*p)[2]);
01746          *p += 2; /* skip a total of 3 chars */
01747       } else         /* individual character */
01748          c2 = c1;
01749       if (c1 < cmin)
01750          cmin = c1;
01751       for (; c1 <= c2; c1++) {
01752          uint32_t mask = 1 << (c1 % 32);
01753          if ( (chars[ c1 / 32 ] & mask) == 0)
01754             count += 0x100;
01755          chars[ c1 / 32 ] |= mask;
01756       }
01757    }
01758    (*p)++;
01759    return count == 0 ? 0x30000 : (count | cmin);
01760 }

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

copy a string skipping whitespace

Definition at line 6797 of file pbx.c.

Referenced by ast_add_extension2_lockopt().

06798 {
06799    int count = 0;
06800 
06801    while (*src && (count < len - 1)) {
06802       switch (*src) {
06803       case ' ':
06804          /* otherwise exten => [a-b],1,... doesn't work */
06805          /*    case '-': */
06806          /* Ignore */
06807          break;
06808       default:
06809          *dst = *src;
06810          dst++;
06811       }
06812       src++;
06813       count++;
06814    }
06815    *dst = '\0';
06816 
06817    return count;
06818 }

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

Definition at line 1972 of file pbx.c.

References _extension_match_core(), ast_add_profile(), and ast_mark().

Referenced by ast_extension_close(), ast_extension_match(), and pbx_find_extension().

01973 {
01974    int i;
01975    static int prof_id = -2;   /* marker for 'unallocated' id */
01976    if (prof_id == -2)
01977       prof_id = ast_add_profile("ext_match", 0);
01978    ast_mark(prof_id, 1);
01979    i = _extension_match_core(pattern, data, mode);
01980    ast_mark(prof_id, 0);
01981    return i;
01982 }

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

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

Referenced by ast_add_extension_nolock().

04115 {
04116    struct ast_context *c = NULL;
04117    struct fake_context item;
04118 
04119    ast_copy_string(item.name, context, sizeof(item.name));
04120 
04121    c = ast_hashtab_lookup(contexts_table,&item);
04122 
04123    return c;
04124 }

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

References ast_copy_string(), ast_get_context_name(), ast_hashtab_lookup(), ast_rdlock_contexts(), ast_unlock_contexts(), ast_walk_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_remove_extension_callerid(), ast_context_remove_ignorepat(), ast_context_remove_include(), and ast_context_remove_switch().

04132 {
04133    struct ast_context *c = NULL;
04134    struct fake_context item;
04135 
04136    ast_copy_string(item.name, context, sizeof(item.name));
04137 
04138    ast_rdlock_contexts();
04139    c = ast_hashtab_lookup(contexts_table,&item);
04140 
04141 #ifdef NOTNOW
04142 
04143    while ( (c = ast_walk_contexts(c)) ) {
04144       if (!strcmp(ast_get_context_name(c), context))
04145          return c;
04146    }
04147 #endif
04148    if (!c)
04149       ast_unlock_contexts();
04150 
04151    return c;
04152 }

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

References ast_log(), and LOG_WARNING.

Referenced by ast_func_read(), and ast_func_write().

02834 {
02835    char *args = strchr(function, '(');
02836 
02837    if (!args)
02838       ast_log(LOG_WARNING, "Function doesn't contain parentheses.  Assuming null argument.\n");
02839    else {
02840       char *p;
02841       *args++ = '\0';
02842       if ((p = strrchr(args, ')')) )
02843          *p = '\0';
02844       else
02845          ast_log(LOG_WARNING, "Can't find trailing parenthesis?\n");
02846    }
02847    return args;
02848 }

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

Definition at line 1161 of file pbx.c.

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

01162 {
01163    /* find the exten at the end of the rope */
01164    struct match_char *node2 = node;
01165 
01166    for (node2 = node; node2; node2 = node2->next_char) {
01167       if (node2->exten) {
01168 #ifdef NEED_DEBUG_HERE
01169          ast_log(LOG_NOTICE,"CanMatch_exten returns exten %s(%p)\n", node2->exten->exten, node2->exten);
01170 #endif
01171          return node2->exten;
01172       }
01173    }
01174 #ifdef NEED_DEBUG_HERE
01175    ast_log(LOG_NOTICE,"CanMatch_exten returns NULL, match_char=%s\n", node->x);
01176 #endif
01177    return 0;
01178 }

static unsigned get_range ( char *  src,
int  max,
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 6191 of file pbx.c.

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

Referenced by ast_build_timing().

06192 {
06193    int s, e; /* start and ending position */
06194    unsigned int mask = 0;
06195 
06196    /* Check for whole range */
06197    if (ast_strlen_zero(src) || !strcmp(src, "*")) {
06198       s = 0;
06199       e = max - 1;
06200    } else {
06201       /* Get start and ending position */
06202       char *c = strchr(src, '-');
06203       if (c)
06204          *c++ = '\0';
06205       /* Find the start */
06206       s = lookup_name(src, names, max);
06207       if (!s) {
06208          ast_log(LOG_WARNING, "Invalid %s '%s', assuming none\n", msg, src);
06209          return 0;
06210       }
06211       s--;
06212       if (c) { /* find end of range */
06213          e = lookup_name(c, names, max);
06214          if (!e) {
06215             ast_log(LOG_WARNING, "Invalid end %s '%s', assuming none\n", msg, c);
06216             return 0;
06217          }
06218          e--;
06219       } else
06220          e = s;
06221    }
06222    /* Fill the mask. Remember that ranges are cyclic */
06223    mask = 1 << e; /* initialize with last element */
06224    while (s != e) {
06225       if (s >= max) {
06226          s = 0;
06227          mask |= (1 << s);
06228       } else {
06229          mask |= (1 << s);
06230          s++;
06231       }
06232    }
06233    return mask;
06234 }

static void get_timerange ( struct ast_timing i,
char *  times 
) [static]

store a bitmask of valid times, one bit each 2 minute

Definition at line 6237 of file pbx.c.

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

Referenced by ast_build_timing().

06238 {
06239    char *e;
06240    int x;
06241    int s1, s2;
06242    int e1, e2;
06243    /* int cth, ctm; */
06244 
06245    /* start disabling all times, fill the fields with 0's, as they may contain garbage */
06246    memset(i->minmask, 0, sizeof(i->minmask));
06247 
06248    /* 2-minutes per bit, since the mask has only 32 bits :( */
06249    /* Star is all times */
06250    if (ast_strlen_zero(times) || !strcmp(times, "*")) {
06251       for (x = 0; x < 24; x++)
06252          i->minmask[x] = 0x3fffffff; /* 30 bits */
06253       return;
06254    }
06255    /* Otherwise expect a range */
06256    e = strchr(times, '-');
06257    if (!e) {
06258       ast_log(LOG_WARNING, "Time range is not valid. Assuming no restrictions based on time.\n");
06259       return;
06260    }
06261    *e++ = '\0';
06262    /* XXX why skip non digits ? */
06263    while (*e && !isdigit(*e))
06264       e++;
06265    if (!*e) {
06266       ast_log(LOG_WARNING, "Invalid time range.  Assuming no restrictions based on time.\n");
06267       return;
06268    }
06269    if (sscanf(times, "%d:%d", &s1, &s2) != 2) {
06270       ast_log(LOG_WARNING, "%s isn't a time.  Assuming no restrictions based on time.\n", times);
06271       return;
06272    }
06273    if (sscanf(e, "%d:%d", &e1, &e2) != 2) {
06274       ast_log(LOG_WARNING, "%s isn't a time.  Assuming no restrictions based on time.\n", e);
06275       return;
06276    }
06277    /* XXX this needs to be optimized */
06278 #if 1
06279    s1 = s1 * 30 + s2/2;
06280    if ((s1 < 0) || (s1 >= 24*30)) {
06281       ast_log(LOG_WARNING, "%s isn't a valid start time. Assuming no time.\n", times);
06282       return;
06283    }
06284    e1 = e1 * 30 + e2/2;
06285    if ((e1 < 0) || (e1 >= 24*30)) {
06286       ast_log(LOG_WARNING, "%s isn't a valid end time. Assuming no time.\n", e);
06287       return;
06288    }
06289    /* Go through the time and enable each appropriate bit */
06290    for (x=s1;x != e1;x = (x + 1) % (24 * 30)) {
06291       i->minmask[x/30] |= (1 << (x % 30));
06292    }
06293    /* Do the last one */
06294    i->minmask[x/30] |= (1 << (x % 30));
06295 #else
06296    for (cth = 0; cth < 24; cth++) {
06297       /* Initialize masks to blank */
06298       i->minmask[cth] = 0;
06299       for (ctm = 0; ctm < 30; ctm++) {
06300          if (
06301          /* First hour with more than one hour */
06302                (((cth == s1) && (ctm >= s2)) &&
06303                 ((cth < e1)))
06304          /* Only one hour */
06305          ||    (((cth == s1) && (ctm >= s2)) &&
06306                 ((cth == e1) && (ctm <= e2)))
06307          /* In between first and last hours (more than 2 hours) */
06308          ||    ((cth > s1) &&
06309                 (cth < e1))
06310          /* Last hour with more than one hour */
06311          ||    ((cth > s1) &&
06312                 ((cth == e1) && (ctm <= e2)))
06313          )
06314             i->minmask[cth] |= (1 << (ctm / 2));
06315       }
06316    }
06317 #endif
06318    /* All done */
06319    return;
06320 }

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

Send ack once.

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

05284 {
05285    char *exten = NULL, *context = NULL;
05286    /* Variables used for different counters */
05287    struct dialplan_counters counters;
05288    const char *incstack[AST_PBX_MAX_STACK];
05289 
05290    switch (cmd) {
05291    case CLI_INIT:
05292       e->command = "dialplan debug";
05293       e->usage = 
05294          "Usage: dialplan debug [context]\n"
05295          "       Show dialplan context Trie(s). Usually only useful to folks debugging the deep internals of the fast pattern matcher\n";
05296       return NULL;
05297    case CLI_GENERATE:   
05298       return complete_show_dialplan_context(a->line, a->word, a->pos, a->n);
05299    }
05300 
05301    memset(&counters, 0, sizeof(counters));
05302 
05303    if (a->argc != 2 && a->argc != 3)
05304       return CLI_SHOWUSAGE;
05305 
05306    /* we obtain [exten@]context? if yes, split them ... */
05307    /* note: we ignore the exten totally here .... */
05308    if (a->argc == 3) {
05309       if (strchr(a->argv[2], '@')) {   /* split into exten & context */
05310          context = ast_strdupa(a->argv[2]);
05311          exten = strsep(&context, "@");
05312          /* change empty strings to NULL */
05313          if (ast_strlen_zero(exten))
05314             exten = NULL;
05315       } else { /* no '@' char, only context given */
05316          context = a->argv[2];
05317       }
05318       if (ast_strlen_zero(context))
05319          context = NULL;
05320    }
05321    /* else Show complete dial plan, context and exten are NULL */
05322    show_debug_helper(a->fd, context, exten, &counters, NULL, 0, incstack);
05323 
05324    /* check for input failure and throw some error messages */
05325    if (context && !counters.context_existence) {
05326       ast_cli(a->fd, "There is no existence of '%s' context\n", context);
05327       return CLI_FAILURE;
05328    }
05329 
05330 
05331    ast_cli(a->fd,"-= %d %s. =-\n",
05332          counters.total_context, counters.total_context == 1 ? "context" : "contexts");
05333 
05334    /* everything ok */
05335    return CLI_SUCCESS;
05336 }

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

Definition at line 5647 of file pbx.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_channel_unlock, ast_cli(), ast_complete_channels(), ast_get_channel_by_name_locked(), chan, 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.

Referenced by handle_set_chanvar_deprecated().

05648 {
05649    struct ast_channel *chan;
05650    const char *chan_name, *var_name, *var_value;
05651 
05652    switch (cmd) {
05653    case CLI_INIT:
05654       e->command = "dialplan set chanvar";
05655       e->usage = 
05656          "Usage: dialplan set chanvar <channel> <varname> <value>\n"
05657          "       Set channel variable <varname> to <value>\n";
05658       return NULL;
05659    case CLI_GENERATE:
05660       return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
05661    }
05662 
05663    if (a->argc != e->args + 3)
05664       return CLI_SHOWUSAGE;
05665 
05666    chan_name = a->argv[e->args];
05667    var_name = a->argv[e->args + 1];
05668    var_value = a->argv[e->args + 2];
05669 
05670    if (!(chan = ast_get_channel_by_name_locked(chan_name))) {
05671       ast_cli(a->fd, "Channel '%s' not found\n", chan_name);
05672       return CLI_FAILURE;
05673    }
05674 
05675    pbx_builtin_setvar_helper(chan, var_name, var_value);
05676    ast_channel_unlock(chan);
05677    ast_cli(a->fd, "\n    -- Channel variable '%s' set to '%s' for '%s'\n",  var_name, var_value, chan_name);
05678 
05679    return CLI_SUCCESS;
05680 }

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

Definition at line 5682 of file pbx.c.

References CLI_INIT, ast_cli_entry::command, and handle_set_chanvar().

05683 {
05684    char *res = handle_set_chanvar(e, cmd, a);
05685    if (cmd == CLI_INIT)
05686       e->command = "core set chanvar";
05687    return res;
05688 }

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

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

05691 {
05692    int oldval = 0;
05693    
05694    switch (cmd) {
05695    case CLI_INIT:
05696       e->command = "dialplan set extenpatternmatchnew true";
05697       e->usage = 
05698          "Usage: dialplan set extenpatternmatchnew true|false\n"
05699          "       Use the NEW extension pattern matching algorithm, true or false.\n";
05700       return NULL;
05701    case CLI_GENERATE:
05702       return NULL;   
05703    }
05704 
05705    if (a->argc != 4)
05706       return CLI_SHOWUSAGE;
05707 
05708    oldval =  pbx_set_extenpatternmatchnew(1);
05709    
05710    if (oldval)
05711       ast_cli(a->fd, "\n    -- Still using the NEW pattern match algorithm for extension names in the dialplan.\n");
05712    else
05713       ast_cli(a->fd, "\n    -- Switched to using the NEW pattern match algorithm for extension names in the dialplan.\n");
05714 
05715    return CLI_SUCCESS;
05716 }

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

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

Referenced by handle_set_global_deprecated().

05618 {
05619    switch (cmd) {
05620    case CLI_INIT:
05621       e->command = "dialplan set global";
05622       e->usage = 
05623          "Usage: dialplan set global <name> <value>\n"
05624          "       Set global dialplan variable <name> to <value>\n";
05625       return NULL;
05626    case CLI_GENERATE:
05627       return NULL;   
05628    }
05629 
05630    if (a->argc != e->args + 2)
05631       return CLI_SHOWUSAGE;
05632 
05633    pbx_builtin_setvar_helper(NULL, a->argv[3], a->argv[4]);
05634    ast_cli(a->fd, "\n    -- Global variable '%s' set to '%s'\n", a->argv[3], a->argv[4]);
05635 
05636    return CLI_SUCCESS;
05637 }

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

Definition at line 5639 of file pbx.c.

References CLI_INIT, ast_cli_entry::command, and handle_set_global().

05640 {
05641    char *res = handle_set_global(e, cmd, a);
05642    if (cmd == CLI_INIT)
05643       e->command = "core set global";
05644    return res;
05645 }

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

Definition at line 4616 of file pbx.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), AST_MAX_APP, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strdup, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, COLOR_CYAN, COLOR_MAGENTA, ast_cli_entry::command, ast_app::description, ast_cli_args::fd, ast_app::list, ast_cli_args::n, ast_app::name, ast_app::synopsis, term_color(), ast_cli_entry::usage, and ast_cli_args::word.

04617 {
04618    struct ast_app *aa;
04619    int app, no_registered_app = 1;
04620    char *ret = NULL;
04621    int which = 0;
04622    int wordlen;
04623 
04624    switch (cmd) {
04625    case CLI_INIT: 
04626       e->command = "core show application";
04627       e->usage = 
04628          "Usage: core show application <application> [<application> [<application> [...]]]\n"
04629          "       Describes a particular application.\n";
04630       return NULL;
04631    case CLI_GENERATE:
04632       /*
04633        * There is a possibility to show informations about more than one
04634        * application at one time. You can type 'show application Dial Echo' and
04635        * you will see informations about these two applications ...
04636        */
04637       wordlen = strlen(a->word);
04638       /* return the n-th [partial] matching entry */
04639       AST_RWLIST_RDLOCK(&apps);
04640       AST_RWLIST_TRAVERSE(&apps, aa, list) {
04641          if (!strncasecmp(a->word, aa->name, wordlen) && ++which > a->n) {
04642             ret = ast_strdup(aa->name);
04643             break;
04644          }
04645       }
04646       AST_RWLIST_UNLOCK(&apps);
04647 
04648       return ret;
04649    }
04650 
04651    if (a->argc < 4)
04652       return CLI_SHOWUSAGE;
04653 
04654    /* ... go through all applications ... */
04655    AST_RWLIST_RDLOCK(&apps);
04656    AST_RWLIST_TRAVERSE(&apps, aa, list) {
04657       /* ... compare this application name with all arguments given
04658        * to 'show application' command ... */
04659       for (app = 3; app < a->argc; app++) {
04660          if (!strcasecmp(aa->name, a->argv[app])) {
04661             /* Maximum number of characters added by terminal coloring is 22 */
04662             char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40];
04663             char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL;
04664             int synopsis_size, description_size;
04665 
04666             no_registered_app = 0;
04667 
04668             if (aa->synopsis)
04669                synopsis_size = strlen(aa->synopsis) + 23;
04670             else
04671                synopsis_size = strlen("Not available") + 23;
04672             synopsis = alloca(synopsis_size);
04673 
04674             if (aa->description)
04675                description_size = strlen(aa->description) + 23;
04676             else
04677                description_size = strlen("Not available") + 23;
04678             description = alloca(description_size);
04679 
04680             if (synopsis && description) {
04681                snprintf(info, 64 + AST_MAX_APP, "\n  -= Info about application '%s' =- \n\n", aa->name);
04682                term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22);
04683                term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
04684                term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
04685                term_color(synopsis,
04686                            aa->synopsis ? aa->synopsis : "Not available",
04687                            COLOR_CYAN, 0, synopsis_size);
04688                term_color(description,
04689                            aa->description ? aa->description : "Not available",
04690                            COLOR_CYAN, 0, description_size);
04691 
04692                ast_cli(a->fd,"%s%s%s\n\n%s%s\n", infotitle, syntitle, synopsis, destitle, description);
04693             } else {
04694                /* ... one of our applications, show info ...*/
04695                ast_cli(a->fd,"\n  -= Info about application '%s' =- \n\n"
04696                   "[Synopsis]\n  %s\n\n"
04697                   "[Description]\n%s\n",
04698                   aa->name,
04699                   aa->synopsis ? aa->synopsis : "Not available",
04700                   aa->description ? aa->description : "Not available");
04701             }
04702          }
04703       }
04704    }
04705    AST_RWLIST_UNLOCK(&apps);
04706 
04707    /* we found at least one app? no? */
04708    if (no_registered_app) {
04709       ast_cli(a->fd, "Your application(s) is (are) not registered\n");
04710       return CLI_FAILURE;
04711    }
04712 
04713    return CLI_SUCCESS;
04714 }

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

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

04873 {
04874    struct ast_app *aa;
04875    int like = 0, describing = 0;
04876    int total_match = 0;    /* Number of matches in like clause */
04877    int total_apps = 0;  /* Number of apps registered */
04878    static char* choices[] = { "like", "describing", NULL };
04879 
04880    switch (cmd) {
04881    case CLI_INIT:
04882       e->command = "core show applications [like|describing]";
04883       e->usage = 
04884          "Usage: core show applications [{like|describing} <text>]\n"
04885          "       List applications which are currently available.\n"
04886          "       If 'like', <text> will be a substring of the app name\n"
04887          "       If 'describing', <text> will be a substring of the description\n";
04888       return NULL;
04889    case CLI_GENERATE:
04890       return (a->pos != 3) ? NULL : ast_cli_complete(a->word, choices, a->n);
04891    }
04892 
04893    AST_RWLIST_RDLOCK(&apps);
04894 
04895    if (AST_RWLIST_EMPTY(&apps)) {
04896       ast_cli(a->fd, "There are no registered applications\n");
04897       AST_RWLIST_UNLOCK(&apps);
04898       return CLI_SUCCESS;
04899    }
04900 
04901    /* core list applications like <keyword> */
04902    if ((a->argc == 5) && (!strcmp(a->argv[3], "like"))) {
04903       like = 1;
04904    } else if ((a->argc > 4) && (!strcmp(a->argv[3], "describing"))) {
04905       describing = 1;
04906    }
04907 
04908    /* core list applications describing <keyword1> [<keyword2>] [...] */
04909    if ((!like) && (!describing)) {
04910       ast_cli(a->fd, "    -= Registered Asterisk Applications =-\n");
04911    } else {
04912       ast_cli(a->fd, "    -= Matching Asterisk Applications =-\n");
04913    }
04914 
04915    AST_RWLIST_TRAVERSE(&apps, aa, list) {
04916       int printapp = 0;
04917       total_apps++;
04918       if (like) {
04919          if (strcasestr(aa->name, a->argv[4])) {
04920             printapp = 1;
04921             total_match++;
04922          }
04923       } else if (describing) {
04924          if (aa->description) {
04925             /* Match all words on command line */
04926             int i;
04927             printapp = 1;
04928             for (i = 4; i < a->argc; i++) {
04929                if (!strcasestr(aa->description, a->argv[i])) {
04930                   printapp = 0;
04931                } else {
04932                   total_match++;
04933                }
04934             }
04935          }
04936       } else {
04937          printapp = 1;
04938       }
04939 
04940       if (printapp) {
04941          ast_cli(a->fd,"  %20s: %s\n", aa->name, aa->synopsis ? aa->synopsis : "<Synopsis not available>");
04942       }
04943    }
04944    if ((!like) && (!describing)) {
04945       ast_cli(a->fd, "    -= %d Applications Registered =-\n",total_apps);
04946    } else {
04947       ast_cli(a->fd, "    -= %d Applications Matching =-\n",total_match);
04948    }
04949 
04950    AST_RWLIST_UNLOCK(&apps);
04951 
04952    return CLI_SUCCESS;
04953 }

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

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_channel_unlock, ast_cli(), ast_complete_channels(), ast_get_channel_by_name_locked(), ast_str_alloca, chan, 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_str::str, ast_cli_entry::usage, and ast_cli_args::word.

05586 {
05587    struct ast_channel *chan = NULL;
05588    struct ast_str *vars = ast_str_alloca(BUFSIZ * 4); /* XXX large because we might have lots of channel vars */
05589 
05590    switch (cmd) {
05591    case CLI_INIT:
05592       e->command = "dialplan show chanvar";
05593       e->usage = 
05594          "Usage: dialplan show chanvar <channel>\n"
05595          "       List current channel variables and their values\n";
05596       return NULL;
05597    case CLI_GENERATE:
05598       return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
05599    }
05600 
05601    if (a->argc != e->args + 1)
05602       return CLI_SHOWUSAGE;
05603 
05604    if (!(chan = ast_get_channel_by_name_locked(a->argv[e->args]))) {
05605       ast_cli(a->fd, "Channel '%s' not found\n", a->argv[e->args]);
05606       return CLI_FAILURE;
05607    }
05608 
05609    pbx_builtin_serialize_variables(chan, &vars);
05610    if (vars->str) {
05611       ast_cli(a->fd, "\nVariables for channel %s:\n%s\n", a->argv[e->args], vars->str);
05612    }
05613    ast_channel_unlock(chan);
05614    return CLI_SUCCESS;
05615 }

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

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

05217 {
05218    char *exten = NULL, *context = NULL;
05219    /* Variables used for different counters */
05220    struct dialplan_counters counters;
05221    const char *incstack[AST_PBX_MAX_STACK];
05222 
05223    switch (cmd) {
05224    case CLI_INIT:
05225       e->command = "dialplan show";
05226       e->usage = 
05227          "Usage: dialplan show [[exten@]context]\n"
05228          "       Show dialplan\n";
05229       return NULL;
05230    case CLI_GENERATE:   
05231       return complete_show_dialplan_context(a->line, a->word, a->pos, a->n);
05232    }
05233 
05234    memset(&counters, 0, sizeof(counters));
05235 
05236    if (a->argc != 2 && a->argc != 3)
05237       return CLI_SHOWUSAGE;
05238 
05239    /* we obtain [exten@]context? if yes, split them ... */
05240    if (a->argc == 3) {
05241       if (strchr(a->argv[2], '@')) {   /* split into exten & context */
05242          context = ast_strdupa(a->argv[2]);
05243          exten = strsep(&context, "@");
05244          /* change empty strings to NULL */
05245          if (ast_strlen_zero(exten))
05246             exten = NULL;
05247       } else { /* no '@' char, only context given */
05248          context = a->argv[2];
05249       }
05250       if (ast_strlen_zero(context))
05251          context = NULL;
05252    }
05253    /* else Show complete dial plan, context and exten are NULL */
05254    show_dialplan_helper(a->fd, context, exten, &counters, NULL, 0, incstack);
05255 
05256    /* check for input failure and throw some error messages */
05257    if (context && !counters.context_existence) {
05258       ast_cli(a->fd, "There is no existence of '%s' context\n", context);
05259       return CLI_FAILURE;
05260    }
05261 
05262    if (exten && !counters.extension_existence) {
05263       if (context)
05264          ast_cli(a->fd, "There is no existence of %s@%s extension\n",
05265             exten, context);
05266       else
05267          ast_cli(a->fd,
05268             "There is no existence of '%s' extension in all contexts\n",
05269             exten);
05270       return CLI_FAILURE;
05271    }
05272 
05273    ast_cli(a->fd,"-= %d %s (%d %s) in %d %s. =-\n",
05274             counters.total_exten, counters.total_exten == 1 ? "extension" : "extensions",
05275             counters.total_prio, counters.total_prio == 1 ? "priority" : "priorities",
05276             counters.total_context, counters.total_context == 1 ? "context" : "contexts");
05277 
05278    /* everything ok */
05279    return CLI_SUCCESS;
05280 }

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

Definition at line 2682 of file pbx.c.

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

02683 {
02684    struct ast_custom_function *acf;
02685    /* Maximum number of characters added by terminal coloring is 22 */
02686    char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40];
02687    char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL;
02688    char stxtitle[40], *syntax = NULL;
02689    int synopsis_size, description_size, syntax_size;
02690    char *ret = NULL;
02691    int which = 0;
02692    int wordlen;
02693 
02694    switch (cmd) {
02695    case CLI_INIT:
02696       e->command = "core show function";
02697       e->usage = 
02698          "Usage: core show function <function>\n"
02699          "       Describe a particular dialplan function.\n";
02700       return NULL;
02701    case CLI_GENERATE:   
02702       wordlen = strlen(a->word);
02703       /* case-insensitive for convenience in this 'complete' function */
02704       AST_RWLIST_RDLOCK(&acf_root);
02705       AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) {
02706          if (!strncasecmp(a->word, acf->name, wordlen) && ++which > a->n) {
02707             ret = ast_strdup(acf->name);
02708             break;
02709          }
02710       }
02711       AST_RWLIST_UNLOCK(&acf_root);
02712 
02713       return ret;
02714    }
02715 
02716    if (a->argc < 4)
02717       return CLI_SHOWUSAGE;
02718 
02719    if (!(acf = ast_custom_function_find(a->argv[3]))) {
02720       ast_cli(a->fd, "No function by that name registered.\n");
02721       return CLI_FAILURE;
02722 
02723    }
02724 
02725    if (acf->synopsis)
02726       synopsis_size = strlen(acf->synopsis) + 23;
02727    else
02728       synopsis_size = strlen("Not available") + 23;
02729    synopsis = alloca(synopsis_size);
02730 
02731    if (acf->desc)
02732       description_size = strlen(acf->desc) + 23;
02733    else
02734       description_size = strlen("Not available") + 23;
02735    description = alloca(description_size);
02736 
02737    if (acf->syntax)
02738       syntax_size = strlen(acf->syntax) + 23;
02739    else
02740       syntax_size = strlen("Not available") + 23;
02741    syntax = alloca(syntax_size);
02742 
02743    snprintf(info, 64 + AST_MAX_APP, "\n  -= Info about function '%s' =- \n\n", acf->name);
02744    term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22);
02745    term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40);
02746    term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
02747    term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
02748    term_color(syntax,
02749          acf->syntax ? acf->syntax : "Not available",
02750          COLOR_CYAN, 0, syntax_size);
02751    term_color(synopsis,
02752          acf->synopsis ? acf->synopsis : "Not available",
02753          COLOR_CYAN, 0, synopsis_size);
02754    term_color(description,
02755          acf->desc ? acf->desc : "Not available",
02756          COLOR_CYAN, 0, description_size);
02757 
02758    ast_cli(a->fd,"%s%s%s\n\n%s%s\n\n%s%s\n", infotitle, stxtitle, syntax, syntitle, synopsis, destitle, description);
02759 
02760    return CLI_SUCCESS;
02761 }

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

Definition at line 2643 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, ast_custom_function::synopsis, ast_custom_function::syntax, and ast_cli_entry::usage.

02644 {
02645    struct ast_custom_function *acf;
02646    int count_acf = 0;
02647    int like = 0;
02648 
02649    switch (cmd) {
02650    case CLI_INIT:
02651       e->command = "core show functions [like]";
02652       e->usage = 
02653          "Usage: core show functions [like <text>]\n"
02654          "       List builtin functions, optionally only those matching a given string\n";
02655       return NULL;
02656    case CLI_GENERATE:
02657       return NULL;
02658    }
02659 
02660    if (a->argc == 5 && (!strcmp(a->argv[3], "like")) ) {
02661       like = 1;
02662    } else if (a->argc != 3) {
02663       return CLI_SHOWUSAGE;
02664    }
02665 
02666    ast_cli(a->fd, "%s Custom Functions:\n--------------------------------------------------------------------------------\n", like ? "Matching" : "Installed");
02667 
02668    AST_RWLIST_RDLOCK(&acf_root);
02669    AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) {
02670       if (!like || strstr(acf->name, a->argv[4])) {
02671          count_acf++;
02672          ast_cli(a->fd, "%-20.20s  %-35.35s  %s\n", acf->name, acf->syntax, acf->synopsis);
02673       }
02674    }
02675    AST_RWLIST_UNLOCK(&acf_root);
02676 
02677    ast_cli(a->fd, "%d %scustom functions installed.\n", count_acf, like ? "matching " : "");
02678 
02679    return CLI_SUCCESS;
02680 }

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

Referenced by handle_show_globals_deprecated().

05549 {
05550    int i = 0;
05551    struct ast_var_t *newvariable;
05552 
05553    switch (cmd) {
05554    case CLI_INIT:
05555       e->command = "dialplan show globals";
05556       e->usage = 
05557          "Usage: dialplan show globals\n"
05558          "       List current global dialplan variables and their values\n";
05559       return NULL;
05560    case CLI_GENERATE:
05561       return NULL;
05562    }
05563 
05564    ast_rwlock_rdlock(&globalslock);
05565    AST_LIST_TRAVERSE (&globals, newvariable, entries) {
05566       i++;
05567       ast_cli(a->fd, "   %s=%s\n", ast_var_name(newvariable), ast_var_value(newvariable));
05568    }
05569    ast_rwlock_unlock(&globalslock);
05570    ast_cli(a->fd, "\n    -- %d variable(s)\n", i);
05571 
05572    return CLI_SUCCESS;
05573 }

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

Definition at line 5575 of file pbx.c.

References CLI_INIT, ast_cli_entry::command, and handle_show_globals().

05576 {
05577 
05578    char *res = handle_show_globals(e, cmd, a);
05579    if (cmd == CLI_INIT)
05580       e->command = "core show globals";
05581    return res;
05582 }

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

References 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_LIST_TRAVERSE, AST_RWLIST_EMPTY, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_hint::callbacks, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_core_show_hint(), ast_state_cb::entry, ast_hint::exten, ast_cli_args::fd, ast_hint::laststate, ast_cli_args::line, ast_cli_args::n, num, ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.

04789 {
04790    struct ast_hint *hint;
04791    int watchers;
04792    int num = 0, extenlen;
04793    struct ast_state_cb *watcher;
04794 
04795    switch (cmd) {
04796    case CLI_INIT:
04797       e->command = "core show hint";
04798       e->usage =
04799          "Usage: core show hint <exten>\n"
04800          "       List registered hint\n";
04801       return NULL;
04802    case CLI_GENERATE:
04803       return complete_core_show_hint(a->line, a->word, a->pos, a->n);
04804    }
04805 
04806    if (a->argc < 4)
04807       return CLI_SHOWUSAGE;
04808 
04809    AST_RWLIST_RDLOCK(&hints);
04810    if (AST_RWLIST_EMPTY(&hints)) {
04811       ast_cli(a->fd, "There are no registered dialplan hints\n");
04812       AST_RWLIST_UNLOCK(&hints);
04813       return CLI_SUCCESS;
04814    }
04815    extenlen = strlen(a->argv[3]);
04816    AST_RWLIST_TRAVERSE(&hints, hint, list) {
04817       if (!strncasecmp(ast_get_extension_name(hint->exten), a->argv[3], extenlen)) {
04818          watchers = 0;
04819          AST_LIST_TRAVERSE(&hint->callbacks, watcher, entry) {
04820             watchers++;
04821          }
04822          ast_cli(a->fd, "   %20s@%-20.20s: %-20.20s  State:%-15.15s Watchers %2d\n",
04823             ast_get_extension_name(hint->exten),
04824             ast_get_context_name(ast_get_extension_context(hint->exten)),
04825             ast_get_extension_app(hint->exten),
04826             ast_extension_state2str(hint->laststate), watchers);
04827          num++;
04828       }
04829    }
04830    AST_RWLIST_UNLOCK(&hints);
04831    if (!num)
04832       ast_cli(a->fd, "No hints matching extension %s\n", a->argv[3]);
04833    else
04834       ast_cli(a->fd, "%d hint%s matching extension %s\n", num, (num!=1 ? "s":""), a->argv[3]);
04835    return CLI_SUCCESS;
04836 }

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

References ast_cli(), ast_extension_state2str(), ast_get_context_name(), ast_get_extension_app(), ast_get_extension_context(), ast_get_extension_name(), AST_LIST_TRAVERSE, AST_RWLIST_EMPTY, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_hint::callbacks, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_state_cb::entry, ast_hint::exten, ast_cli_args::fd, ast_hint::laststate, num, and ast_cli_entry::usage.

04718 {
04719    struct ast_hint *hint;
04720    int num = 0;
04721    int watchers;
04722    struct ast_state_cb *watcher;
04723 
04724    switch (cmd) {
04725    case CLI_INIT:
04726       e->command = "core show hints";
04727       e->usage = 
04728          "Usage: core show hints\n"
04729          "       List registered hints\n";
04730       return NULL;
04731    case CLI_GENERATE:
04732       return NULL;   
04733    }
04734 
04735    AST_RWLIST_RDLOCK(&hints);
04736    if (AST_RWLIST_EMPTY(&hints)) {
04737       ast_cli(a->fd, "There are no registered dialplan hints\n");
04738       AST_RWLIST_UNLOCK(&hints);
04739       return CLI_SUCCESS;
04740    }
04741    /* ... we have hints ... */
04742    ast_cli(a->fd, "\n    -= Registered Asterisk Dial Plan Hints =-\n");
04743    AST_RWLIST_TRAVERSE(&hints, hint, list) {
04744       watchers = 0;
04745       AST_LIST_TRAVERSE(&hint->callbacks, watcher, entry) {
04746          watchers++;
04747       }
04748       ast_cli(a->fd, "   %20s@%-20.20s: %-20.20s  State:%-15.15s Watchers %2d\n",
04749          ast_get_extension_name(hint->exten),
04750          ast_get_context_name(ast_get_extension_context(hint->exten)),
04751          ast_get_extension_app(hint->exten),
04752          ast_extension_state2str(hint->laststate), watchers);
04753       num++;
04754    }
04755    ast_cli(a->fd, "----------------\n");
04756    ast_cli(a->fd, "- %d hints registered\n", num);
04757    AST_RWLIST_UNLOCK(&hints);
04758    return CLI_SUCCESS;
04759 }

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

04841 {
04842    struct ast_switch *sw;
04843 
04844    switch (cmd) {
04845    case CLI_INIT:
04846       e->command = "core show switches";
04847       e->usage = 
04848          "Usage: core show switches\n"
04849          "       List registered switches\n";
04850       return NULL;
04851    case CLI_GENERATE:
04852       return NULL;   
04853    }
04854 
04855    AST_RWLIST_RDLOCK(&switches);
04856 
04857    if (AST_RWLIST_EMPTY(&switches)) {
04858       AST_RWLIST_UNLOCK(&switches);
04859       ast_cli(a->fd, "There are no registered alternative switches\n");
04860       return CLI_SUCCESS;
04861    }
04862 
04863    ast_cli(a->fd, "\n    -= Registered Asterisk Alternative Switches =-\n");
04864    AST_RWLIST_TRAVERSE(&switches, sw, list)
04865       ast_cli(a->fd, "%s: %s\n", sw->name, sw->description);
04866 
04867    AST_RWLIST_UNLOCK(&switches);
04868 
04869    return CLI_SUCCESS;
04870 }

static int handle_statechange ( void *  datap  )  [static]

Definition at line 3324 of file pbx.c.

References ast_copy_string(), ast_extension_state2(), ast_free, ast_get_extension_app(), AST_LIST_TRAVERSE, AST_MAX_EXTENSION, ast_rdlock_contexts(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_unlock_contexts(), buf, ast_state_cb::callback, ast_hint::callbacks, ast_state_cb::data, statechange::dev, ast_state_cb::entry, ast_exten::exten, ast_hint::exten, ast_hint::laststate, ast_context::name, ast_exten::parent, parse(), and strsep().

Referenced by device_state_cb().

03325 {
03326    struct ast_hint *hint;
03327    struct statechange *sc = datap;
03328 
03329    ast_rdlock_contexts();
03330    AST_RWLIST_RDLOCK(&hints);
03331 
03332    AST_RWLIST_TRAVERSE(&hints, hint, list) {
03333       struct ast_state_cb *cblist;
03334       char buf[AST_MAX_EXTENSION];
03335       char *parse = buf;
03336       char *cur;
03337       int state;
03338 
03339       ast_copy_string(buf, ast_get_extension_app(hint->exten), sizeof(buf));
03340       while ( (cur = strsep(&parse, "&")) ) {
03341          if (!strcasecmp(cur, sc->dev))
03342             break;
03343       }
03344       if (!cur)
03345          continue;
03346 
03347       /* Get device state for this hint */
03348       state = ast_extension_state2(hint->exten);
03349 
03350       if ((state == -1) || (state == hint->laststate))
03351          continue;
03352 
03353       /* Device state changed since last check - notify the watchers */
03354 
03355       /* For general callbacks */
03356       AST_LIST_TRAVERSE(&statecbs, cblist, entry) {
03357          cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data);
03358       }
03359 
03360       /* For extension callbacks */
03361       AST_LIST_TRAVERSE(&hint->callbacks, cblist, entry) {
03362          cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data);
03363       }
03364 
03365       hint->laststate = state;   /* record we saw the change */
03366    }
03367    AST_RWLIST_UNLOCK(&hints);
03368    ast_unlock_contexts();
03369    ast_free(sc);
03370    return 0;
03371 }

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

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

05719 {
05720    int oldval = 0;
05721    
05722    switch (cmd) {
05723    case CLI_INIT:
05724       e->command = "dialplan set extenpatternmatchnew false";
05725       e->usage = 
05726          "Usage: dialplan set extenpatternmatchnew true|false\n"
05727          "       Use the NEW extension pattern matching algorithm, true or false.\n";
05728       return NULL;
05729    case CLI_GENERATE:
05730       return NULL;   
05731    }
05732 
05733    if (a->argc != 4)
05734       return CLI_SHOWUSAGE;
05735 
05736    oldval =  pbx_set_extenpatternmatchnew(0);
05737    
05738    if (!oldval)
05739       ast_cli(a->fd, "\n    -- Still using the OLD pattern match algorithm for extension names in the dialplan.\n");
05740    else
05741       ast_cli(a->fd, "\n    -- Switched to using the OLD pattern match algorithm for extension names in the dialplan.\n");
05742 
05743    return CLI_SUCCESS;
05744 }

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

Definition at line 388 of file pbx.c.

References ast_exten::label.

Referenced by ast_add_extension2_lockopt().

00389 {
00390    const struct ast_exten *ac = ah_a;
00391    const struct ast_exten *bc = ah_b;
00392    return strcmp(ac->label, bc->label);
00393 }

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

Definition at line 381 of file pbx.c.

References ast_exten::priority.

Referenced by ast_add_extension2_lockopt().

00382 {
00383    const struct ast_exten *ac = ah_a;
00384    const struct ast_exten *bc = ah_b;
00385    return ac->priority != bc->priority;
00386 }

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

Definition at line 362 of file pbx.c.

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

Referenced by ast_add_extension2_lockopt().

00363 {
00364    const struct ast_exten *ac = ah_a;
00365    const struct ast_exten *bc = ah_b;
00366    int x = strcmp(ac->exten, bc->exten);
00367    if (x) { /* if exten names are diff, then return */
00368       return x;
00369    }
00370    
00371    /* but if they are the same, do the cidmatch values match? */
00372    if (ac->matchcid && bc->matchcid) {
00373       return strcmp(ac->cidmatch,bc->cidmatch);
00374    } else if (!ac->matchcid && !bc->matchcid) {
00375       return 0; /* if there's no matchcid on either side, then this is a match */
00376    } else {
00377       return 1; /* if there's matchcid on one but not the other, they are different */
00378    }
00379 }

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

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

00402 {
00403    const struct ast_exten *ac = obj;
00404    unsigned int x = ast_hashtab_hash_string(ac->exten);
00405    unsigned int y = 0;
00406    if (ac->matchcid)
00407       y = ast_hashtab_hash_string(ac->cidmatch);
00408    return x+y;
00409 }

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

Definition at line 417 of file pbx.c.

References ast_hashtab_hash_string(), and ast_exten::label.

Referenced by ast_add_extension2_lockopt().

00418 {
00419    const struct ast_exten *ac = obj;
00420    return ast_hashtab_hash_string(ac->label);
00421 }

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

Definition at line 411 of file pbx.c.

References ast_hashtab_hash_int(), and ast_exten::priority.

Referenced by ast_add_extension2_lockopt().

00412 {
00413    const struct ast_exten *ac = obj;
00414    return ast_hashtab_hash_int(ac->priority);
00415 }

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

Definition at line 1000 of file pbx.c.

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

Referenced by pbx_find_extension().

01001 {
01002    if (!i->hastime)
01003       return 1;
01004 
01005    return ast_check_timing(&(i->timing));
01006 }

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

03944 {
03945    int failed = 0;
03946    double curloadavg;
03947 #if defined(HAVE_SYSINFO)
03948    long curfreemem;
03949    struct sysinfo sys_info;
03950 #endif
03951 
03952    ast_mutex_lock(&maxcalllock);
03953    if (option_maxcalls) {
03954       if (countcalls >= option_maxcalls) {
03955          ast_log(LOG_WARNING, "Maximum call limit of %d calls exceeded by '%s'!\n", option_maxcalls, c->name);
03956          failed = -1;
03957       }
03958    }
03959    if (option_maxload) {
03960       getloadavg(&curloadavg, 1);
03961       if (curloadavg >= option_maxload) {
03962          ast_log(LOG_WARNING, "Maximum loadavg limit of %f load exceeded by '%s' (currently %f)!\n", option_maxload, c->name, curloadavg);
03963          failed = -1;
03964       }
03965    }
03966 #if defined(HAVE_SYSINFO)
03967    if (option_minmemfree) {
03968       if (!sysinfo(&sys_info)) {
03969          /* make sure that the free system memory is above the configured low watermark
03970           * convert the amount of freeram from mem_units to MB */
03971          curfreemem = sys_info.freeram / sys_info.mem_unit; 
03972          curfreemem /= 1024*1024; 
03973          if (curfreemem < option_minmemfree) {
03974             ast_log(LOG_WARNING, "Available system memory (~%ldMB) is below the configured low watermark (%ldMB)\n", curfreemem, option_minmemfree);
03975             failed = -1;
03976          }
03977       }
03978    }
03979 #endif
03980       
03981    if (!failed) {
03982       countcalls++;
03983       totalcalls++;
03984    }
03985    ast_mutex_unlock(&maxcalllock);
03986 
03987    return failed;
03988 }

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

Definition at line 1401 of file pbx.c.

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

Referenced by add_pattern_node().

01402 {
01403    struct match_char *curr, *lcurr;
01404    
01405    /* insert node into the tree at "current", so the alt_char list from current is
01406       sorted in increasing value as you go to the leaves */
01407    if (!(*parent_ptr)) {
01408       *parent_ptr = node;
01409    } else {
01410       if ((*parent_ptr)->specificity > node->specificity){
01411          /* insert at head */
01412          node->alt_char = (*parent_ptr);
01413          *parent_ptr = node;
01414       } else {
01415          lcurr = *parent_ptr;
01416          for (curr=(*parent_ptr)->alt_char; curr; curr = curr->alt_char) {
01417             if (curr->specificity > node->specificity) {
01418                node->alt_char = curr;
01419                lcurr->alt_char = node;
01420                break;
01421             }
01422             lcurr = curr;
01423          }
01424          if (!curr)
01425          {
01426             lcurr->alt_char = node;
01427          }
01428       }
01429    }
01430 }

int load_pbx ( void   ) 

Provided by pbx.c

Definition at line 8630 of file pbx.c.

References __ast_custom_function_register(), ast_cli_register_multiple(), AST_EVENT_DEVICE_STATE, AST_EVENT_IE_END, ast_event_subscribe(), ast_log(), ast_manager_register2(), 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(), and pbx_cli.

Referenced by main().

08631 {
08632    int x;
08633 
08634    /* Initialize the PBX */
08635    ast_verb(1, "Asterisk PBX Core Initializing\n");
08636    if (!(device_state_tps = ast_taskprocessor_get("pbx-core", 0))) {
08637       ast_log(LOG_WARNING, "failed to create pbx-core taskprocessor\n");
08638    }
08639 
08640    ast_verb(1, "Registering builtin applications:\n");
08641    ast_cli_register_multiple(pbx_cli, sizeof(pbx_cli) / sizeof(struct ast_cli_entry));
08642    __ast_custom_function_register(&exception_function, NULL);
08643 
08644    /* Register builtin applications */
08645    for (x = 0; x < sizeof(builtins) / sizeof(struct pbx_builtin); x++) {
08646       ast_verb(1, "[%s]\n", builtins[x].name);
08647       if (ast_register_application2(builtins[x].name, builtins[x].execute, builtins[x].synopsis, builtins[x].description, NULL)) {
08648          ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name);
08649          return -1;
08650       }
08651    }
08652    
08653    /* Register manager application */
08654    ast_manager_register2("ShowDialPlan", EVENT_FLAG_CONFIG | EVENT_FLAG_REPORTING, manager_show_dialplan, "List dialplan", mandescr_show_dialplan);
08655 
08656    if (!(device_state_sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE, device_state_cb, NULL,
08657          AST_EVENT_IE_END))) {
08658       return -1;
08659    }
08660 
08661    return 0;
08662 }

void log_match_char_tree ( struct match_char node,
char *  prefix 
)

Definition at line 1103 of file pbx.c.

References match_char::alt_char, ast_debug, ast_str_alloca, ast_str_set(), match_char::deleted, ast_exten::exten, match_char::exten, match_char::is_pattern, match_char::next_char, match_char::specificity, ast_str::str, and match_char::x.

Referenced by ast_context_remove_extension_callerid2(), and pbx_find_extension().

01104 {
01105    char extenstr[40];
01106    struct ast_str *my_prefix = ast_str_alloca(1024); 
01107 
01108    extenstr[0] = '\0';
01109 
01110    if (node && node->exten && node->exten)
01111       snprintf(extenstr, sizeof(extenstr), "(%p)", node->exten);
01112    
01113    if (strlen(node->x) > 1) {
01114       ast_debug(1, "%s[%s]:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y':'N', 
01115          node->deleted? 'D':'-', node->specificity, node->exten? "EXTEN:":"", 
01116          node->exten ? node->exten->exten : "", extenstr);
01117    } else {
01118       ast_debug(1, "%s%s:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y':'N', 
01119          node->deleted? 'D':'-', node->specificity, node->exten? "EXTEN:":"", 
01120          node->exten ? node->exten->exten : "", extenstr);
01121    }
01122 
01123    ast_str_set(&my_prefix, 0, "%s+       ", prefix);
01124 
01125    if (node->next_char)
01126       log_match_char_tree(node->next_char, my_prefix->str);
01127 
01128    if (node->alt_char)
01129       log_match_char_tree(node->alt_char, prefix);
01130 }

static int lookup_name ( const char *  s,
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 6173 of file pbx.c.

Referenced by get_range().

06174 {
06175    int i;
06176 
06177    if (names) {
06178       for (i = 0; names[i]; i++) {
06179          if (!strcasecmp(s, names[i]))
06180             return i+1;
06181       }
06182    } else if (sscanf(s, "%d", &i) == 1 && i >= 1 && i <= max) {
06183       return i;
06184    }
06185    return 0; /* error return */
06186 }

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

Send ack once.

Definition at line 5339 of file pbx.c.

References astman_send_listack(), and s.

Referenced by manager_show_dialplan_helper().

05340 {
05341    astman_send_listack(s, m, "DialPlan list will follow", "start");
05342 }

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

Manager listing of dial plan.

Definition at line 5485 of file pbx.c.

References ast_strlen_zero(), astman_get_header(), astman_send_error(), EVENT_FLAG_CONFIG, exten, manager_event, manager_show_dialplan_helper(), and s.

Referenced by load_pbx().

05486 {
05487    const char *exten, *context;
05488    const char *id = astman_get_header(m, "ActionID");
05489    char idtext[256];
05490    int res;
05491 
05492    /* Variables used for different counters */
05493    struct dialplan_counters counters;
05494 
05495    if (!ast_strlen_zero(id))
05496       snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id);
05497    else
05498       idtext[0] = '\0';
05499 
05500    memset(&counters, 0, sizeof(counters));
05501 
05502    exten = astman_get_header(m, "Extension");
05503    context = astman_get_header(m, "Context");
05504    
05505    res = manager_show_dialplan_helper(s, m, idtext, context, exten, &counters, NULL);
05506 
05507    if (context && !counters.context_existence) {
05508       char errorbuf[BUFSIZ];
05509    
05510       snprintf(errorbuf, sizeof(errorbuf), "Did not find context %s", context);
05511       astman_send_error(s, m, errorbuf);
05512       return 0;
05513    }
05514    if (exten && !counters.extension_existence) {
05515       char errorbuf[BUFSIZ];
05516 
05517       if (context)
05518          snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s@%s", exten, context);
05519       else
05520          snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s in any context", exten);
05521       astman_send_error(s, m, errorbuf);
05522       return 0;
05523    }
05524 
05525    manager_event(EVENT_FLAG_CONFIG, "ShowDialPlanComplete",
05526       "EventList: Complete\r\n"
05527       "ListItems: %d\r\n"
05528       "ListExtensions: %d\r\n"
05529       "ListPriorities: %d\r\n"   
05530       "ListContexts: %d\r\n"  
05531       "%s"
05532       "\r\n", counters.total_items, counters.total_exten, counters.total_prio, counters.total_context, idtext);
05533 
05534    /* everything ok */
05535    return 0;
05536 }

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 5348 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, s, dialplan_counters::total_context, dialplan_counters::total_exten, dialplan_counters::total_items, and dialplan_counters::total_prio.

Referenced by manager_show_dialplan().

05352 {
05353    struct ast_context *c;
05354    int res = 0, old_total_exten = dpc->total_exten;
05355 
05356    if (ast_strlen_zero(exten))
05357       exten = NULL;
05358    if (ast_strlen_zero(context))
05359       context = NULL;
05360 
05361    ast_debug(3, "manager_show_dialplan: Context: -%s- Extension: -%s-\n", context, exten);
05362 
05363    /* try to lock contexts */
05364    if (ast_rdlock_contexts()) {
05365       astman_send_error(s, m, "Failed to lock contexts");
05366       ast_log(LOG_WARNING, "Failed to lock contexts list for manager: listdialplan\n");
05367       return -1;
05368    }
05369 
05370    c = NULL;      /* walk all contexts ... */
05371    while ( (c = ast_walk_contexts(c)) ) {
05372       struct ast_exten *e;
05373       struct ast_include *i;
05374       struct ast_ignorepat *ip;
05375 
05376       if (context && strcmp(ast_get_context_name(c), context) != 0)
05377          continue;   /* not the name we want */
05378 
05379       dpc->context_existence = 1;
05380 
05381       ast_debug(3, "manager_show_dialplan: Found Context: %s \n", ast_get_context_name(c));
05382 
05383       if (ast_rdlock_context(c)) {  /* failed to lock */
05384          ast_debug(3, "manager_show_dialplan: Failed to lock context\n");
05385          continue;
05386       }
05387 
05388       /* XXX note- an empty context is not printed */
05389       e = NULL;      /* walk extensions in context  */
05390       while ( (e = ast_walk_context_extensions(c, e)) ) {
05391          struct ast_exten *p;
05392 
05393          /* looking for extension? is this our extension? */
05394          if (exten && !ast_extension_match(ast_get_extension_name(e), exten)) {
05395             /* not the one we are looking for, continue */
05396             ast_debug(3, "manager_show_dialplan: Skipping extension %s\n", ast_get_extension_name(e));
05397             continue;
05398          }
05399          ast_debug(3, "manager_show_dialplan: Found Extension: %s \n", ast_get_extension_name(e));
05400 
05401          dpc->extension_existence = 1;
05402 
05403          /* may we print context info? */ 
05404          dpc->total_context++;
05405          dpc->total_exten++;
05406 
05407          p = NULL;      /* walk next extension peers */
05408          while ( (p = ast_walk_extension_priorities(e, p)) ) {
05409             int prio = ast_get_extension_priority(p);
05410 
05411             dpc->total_prio++;
05412             if (!dpc->total_items++)
05413                manager_dpsendack(s, m);
05414             astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
05415             astman_append(s, "Context: %s\r\nExtension: %s\r\n", ast_get_context_name(c), ast_get_extension_name(e) );
05416 
05417             /* XXX maybe make this conditional, if p != e ? */
05418             if (ast_get_extension_label(p))
05419                astman_append(s, "ExtensionLabel: %s\r\n", ast_get_extension_label(p));
05420 
05421             if (prio == PRIORITY_HINT) {
05422                astman_append(s, "Priority: hint\r\nApplication: %s\r\n", ast_get_extension_app(p));
05423             } else {
05424                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));
05425             }
05426             astman_append(s, "Registrar: %s\r\n\r\n", ast_get_extension_registrar(e));
05427          }
05428       }
05429 
05430       i = NULL;      /* walk included and write info ... */
05431       while ( (i = ast_walk_context_includes(c, i)) ) {
05432          if (exten) {
05433             /* Check all includes for the requested extension */
05434             manager_show_dialplan_helper(s, m, actionidtext, ast_get_include_name(i), exten, dpc, i);
05435          } else {
05436             if (!dpc->total_items++)
05437                manager_dpsendack(s, m);
05438             astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
05439             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));
05440             astman_append(s, "\r\n");
05441             ast_debug(3, "manager_show_dialplan: Found Included context: %s \n", ast_get_include_name(i));
05442          }
05443       }
05444 
05445       ip = NULL;  /* walk ignore patterns and write info ... */
05446       while ( (ip = ast_walk_context_ignorepats(c, ip)) ) {
05447          const char *ipname = ast_get_ignorepat_name(ip);
05448          char ignorepat[AST_MAX_EXTENSION];
05449 
05450          snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname);
05451          if (!exten || ast_extension_match(ignorepat, exten)) {
05452             if (!dpc->total_items++)
05453                manager_dpsendack(s, m);
05454             astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
05455             astman_append(s, "Context: %s\r\nIgnorePattern: %s\r\nRegistrar: %s\r\n", ast_get_context_name(c), ipname, ast_get_ignorepat_registrar(ip));
05456             astman_append(s, "\r\n");
05457          }
05458       }
05459       if (!rinclude) {
05460          struct ast_sw *sw = NULL;
05461          while ( (sw = ast_walk_context_switches(c, sw)) ) {
05462             if (!dpc->total_items++)
05463                manager_dpsendack(s, m);
05464             astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
05465             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));  
05466             astman_append(s, "\r\n");
05467             ast_debug(3, "manager_show_dialplan: Found Switch : %s \n", ast_get_switch_name(sw));
05468          }
05469       }
05470 
05471       ast_unlock_context(c);
05472    }
05473    ast_unlock_contexts();
05474 
05475    if (dpc->total_exten == old_total_exten) {
05476       ast_debug(3, "manager_show_dialplan: Found nothing new\n");
05477       /* Nothing new under the sun */
05478       return -1;
05479    } else {
05480       return res;
05481    }
05482 }

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

Definition at line 2038 of file pbx.c.

References ast_extension_match(), and ast_strlen_zero().

Referenced by pbx_find_extension().

02039 {
02040    /* If the Caller*ID pattern is empty, then we're matching NO Caller*ID, so
02041       failing to get a number should count as a match, otherwise not */
02042 
02043    if (ast_strlen_zero(callerid))
02044       return ast_strlen_zero(cidpattern) ? 1 : 0;
02045 
02046    return ast_extension_match(cidpattern, callerid);
02047 }

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 1233 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, ast_exten::label, LOG_NOTICE, NEW_MATCHER_CHK_MATCH, match_char::specificity, update_scoreboard(), and match_char::x.

Referenced by pbx_find_extension().

01234 {
01235    struct match_char *p; /* note minimal stack storage requirements */
01236    struct ast_exten pattern = { .label = label };
01237 #ifdef DEBUG_THIS
01238    if (tree)
01239       ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree %s action=%s\n", str, tree->x, action2str(action));
01240    else
01241       ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree NULL action=%s\n", str, action2str(action));
01242 #endif
01243    for (p=tree; p; p=p->alt_char) {
01244       if (p->x[0] == 'N') {
01245          if (p->x[1] == 0 && *str >= '2' && *str <= '9' ) {
01246 #define NEW_MATCHER_CHK_MATCH        \
01247             if (p->exten && !(*(str+1))) { /* if a shorter pattern matches along the way, might as well report it */             \
01248                if (action == E_MATCH || action == E_SPAWN || action == E_FINDLABEL) { /* if in CANMATCH/MATCHMORE, don't let matches get in the way */   \
01249                   update_scoreboard(score, length+1, spec+p->specificity, p->exten,0,callerid, p->deleted, p);                 \
01250                   if (!p->deleted) {                                                                                           \
01251                      if (action == E_FINDLABEL) {                                                                             \
01252                         if (ast_hashtab_lookup(score->exten->peer_label_table, &pattern)) {                                  \
01253                            ast_debug(4, "Found label in preferred extension\n");                                            \
01254                            return;                                                                                          \
01255                         }                                                                                                    \
01256                      } else {                                                                                                 \
01257                         ast_debug(4,"returning an exact match-- first found-- %s\n", p->exten->exten);                       \
01258                         return; /* the first match, by definition, will be the best, because of the sorted tree */           \
01259                      }                                                                                                        \
01260                   }                                                                                                            \
01261                }                                                                                                                \
01262             }
01263             
01264 #define NEW_MATCHER_RECURSE              \
01265             if (p->next_char && ( *(str+1) || (p->next_char->x[0] == '/' && p->next_char->x[1] == 0)                 \
01266                                                || p->next_char->x[0] == '!')) {                                          \
01267                if (*(str+1) || p->next_char->x[0] == '!') {                                                         \
01268                   new_find_extension(str+1, score, p->next_char, length+1, spec+p->specificity, callerid, label, action); \
01269                   if (score->exten)  {                                                                             \
01270                        ast_debug(4,"returning an exact match-- %s\n", score->exten->exten);                         \
01271                      return; /* the first match is all we need */                                                 \
01272                   }                                                                                    \
01273                } else {                                                                                             \
01274                   new_find_extension("/", score, p->next_char, length+1, spec+p->specificity, callerid, label, action);  \
01275                   if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) {      \
01276                        ast_debug(4,"returning a (can/more) match--- %s\n", score->exten ? score->exten->exten :     \
01277                                        "NULL");                                                                        \
01278                      return; /* the first match is all we need */                                                 \
01279                   }                                                                                    \
01280                }                                                                                                    \
01281             } else if (p->next_char && !*(str+1)) {                                                                  \
01282                score->canmatch = 1;                                                                                 \
01283                score->canmatch_exten = get_canmatch_exten(p);                                                       \
01284                if (action == E_CANMATCH || action == E_MATCHMORE) {                                                 \
01285                     ast_debug(4,"returning a canmatch/matchmore--- str=%s\n", str);                                  \
01286                   return;                                                                                          \
01287                }                                                                                        \
01288             }
01289             
01290             NEW_MATCHER_CHK_MATCH;
01291             NEW_MATCHER_RECURSE;
01292          }
01293       } else if (p->x[0] == 'Z') {
01294          if (p->x[1] == 0 && *str >= '1' && *str <= '9' ) {
01295             NEW_MATCHER_CHK_MATCH;
01296             NEW_MATCHER_RECURSE;
01297          }
01298       } else if (p->x[0] == 'X') { 
01299          if (p->x[1] == 0 && *str >= '0' && *str <= '9' ) {
01300             NEW_MATCHER_CHK_MATCH;
01301             NEW_MATCHER_RECURSE;
01302          }
01303       } else if (p->x[0] == '.' && p->x[1] == 0) {
01304          /* how many chars will the . match against? */
01305          int i = 0;
01306          const char *str2 = str;
01307          while (*str2 && *str2 != '/') {
01308             str2++;
01309             i++;
01310          }
01311          if (p->exten && *str2 != '/') {
01312             update_scoreboard(score, length+i, spec+(i*p->specificity), p->exten, '.', callerid, p->deleted, p);
01313             if (score->exten) {
01314                ast_debug(4,"return because scoreboard has a match with '/'--- %s\n", score->exten->exten);
01315                return; /* the first match is all we need */
01316             }
01317          }
01318          if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) {
01319             new_find_extension("/", score, p->next_char, length+i, spec+(p->specificity*i), callerid, label, action);
01320             if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) {
01321                ast_debug(4,"return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set--- %s\n", score->exten ? score->exten->exten : "NULL");
01322                return; /* the first match is all we need */
01323             }
01324          }
01325       } else if (p->x[0] == '!' && p->x[1] == 0) {
01326          /* how many chars will the . match against? */
01327          int i = 1;
01328          const char *str2 = str;
01329          while (*str2 && *str2 != '/') {
01330             str2++;
01331             i++;
01332          }
01333          if (p->exten && *str2 != '/') {
01334             update_scoreboard(score, length+1, spec+(p->specificity*i), p->exten, '!', callerid, p->deleted, p);
01335             if (score->exten) {
01336                ast_debug(4,"return because scoreboard has a '!' match--- %s\n", score->exten->exten);
01337                return; /* the first match is all we need */
01338             }
01339          }
01340          if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) {
01341             new_find_extension("/", score, p->next_char, length+i, spec+(p->specificity*i), callerid, label, action);
01342             if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) {
01343                ast_debug(4,"return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set with '/' and '!'--- %s\n", score->exten ? score->exten->exten : "NULL");
01344                return; /* the first match is all we need */
01345             }
01346          }
01347       } else if (p->x[0] == '/' && p->x[1] == 0) {
01348          /* the pattern in the tree includes the cid match! */
01349          if (p->next_char && callerid && *callerid) {
01350             new_find_extension(callerid, score, p->next_char, length+1, spec, callerid, label, action);
01351             if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) {
01352                ast_debug(4,"return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set with '/'--- %s\n", score->exten ? score->exten->exten : "NULL");
01353                return; /* the first match is all we need */
01354             }
01355          }
01356       } else if (strchr(p->x, *str)) {
01357          ast_debug(4, "Nothing strange about this match\n");
01358          NEW_MATCHER_CHK_MATCH;
01359          NEW_MATCHER_RECURSE;
01360       }
01361    }
01362    ast_debug(4,"return at end of func\n");
01363 }

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

Referenced by pbx_retrieve_variable(), and pbx_substitute_variables_helper_full().

02374 {
02375    int parens = 0;
02376 
02377    *offset = 0;
02378    *length = INT_MAX;
02379    *isfunc = 0;
02380    for (; *var; var++) {
02381       if (*var == '(') {
02382          (*isfunc)++;
02383          parens++;
02384       } else if (*var == ')') {
02385          parens--;
02386       } else if (*var == ':' && parens == 0) {
02387          *var++ = '\0';
02388          sscanf(var, "%d:%d", offset, length);
02389          return 1; /* offset:length valid */
02390       }
02391    }
02392    return 0;
02393 }

void pbx_builtin_clear_globals ( void   ) 

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

08511 {
08512    struct ast_var_t *vardata;
08513 
08514    ast_rwlock_wrlock(&globalslock);
08515    while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries)))
08516       ast_var_delete(vardata);
08517    ast_rwlock_unlock(&globalslock);
08518 }

const char* pbx_builtin_getvar_helper ( struct ast_channel chan,
const char *  name 
)

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 8280 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(), chan, globals, and globalslock.

Referenced by _macro_exec(), _while_exec(), agent_hangup(), agent_read(), agentmonitoroutgoing_exec(), array(), ast_bridge_call(), ast_eivr_getvariable(), ast_feature_interpret(), ast_monitor_stop(), ast_park_call_full(), bridge_play_sounds(), builtin_atxfer(), builtin_automixmonitor(), builtin_automonitor(), check_goto_on_transfer(), common_exec(), conf_exec(), conf_run(), dahdi_call(), dahdi_hangup(), dial_exec_full(), do_forward(), do_timelimit(), dundi_exec(), dundi_helper(), findparkinglotname(), get_also_info(), get_index(), get_refer_info(), global_read(), hash_read(), iax2_exec(), import_ch(), leave_voicemail(), 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_space_reserve(), pickup_by_mark(), queue_exec(), real_ctx(), retrydial_exec(), ring_entry(), run_agi(), set_config_flags(), set_local_info(), sip_addheader(), sla_trunk_exec(), speech_background(), try_calling(), try_suggested_sip_codec(), and update_bridge_vars().

08281 {
08282    struct ast_var_t *variables;
08283    const char *ret = NULL;
08284    int i;
08285    struct varshead *places[2] = { NULL, &globals };
08286 
08287    if (!name)
08288       return NULL;
08289 
08290    if (chan) {
08291       ast_channel_lock(chan);
08292       places[0] = &chan->varshead;
08293    }
08294 
08295    for (i = 0; i < 2; i++) {
08296       if (!places[i])
08297          continue;
08298       if (places[i] == &globals)
08299          ast_rwlock_rdlock(&globalslock);
08300       AST_LIST_TRAVERSE(places[i], variables, entries) {
08301          if (!strcmp(name, ast_var_name(variables))) {
08302             ret = ast_var_value(variables);
08303             break;
08304          }
08305       }
08306       if (places[i] == &globals)
08307          ast_rwlock_unlock(&globalslock);
08308       if (ret)
08309          break;
08310    }
08311 
08312    if (chan)
08313       ast_channel_unlock(chan);
08314 
08315    return ret;
08316 }

static int pbx_builtin_gotoif ( struct ast_channel ,
void *   
) [static]

Definition at line 8532 of file pbx.c.

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

08533 {
08534    char *condition, *branch1, *branch2, *branch;
08535    char *stringp;
08536 
08537    if (ast_strlen_zero(data)) {
08538       ast_log(LOG_WARNING, "Ignoring, since there is no variable to check\n");
08539       return 0;
08540    }
08541 
08542    stringp = ast_strdupa(data);
08543    condition = strsep(&stringp,"?");
08544    branch1 = strsep(&stringp,":");
08545    branch2 = strsep(&stringp,"");
08546    branch = pbx_checkcondition(condition) ? branch1 : branch2;
08547 
08548    if (ast_strlen_zero(branch)) {
08549       ast_debug(1, "Not taking any branch\n");
08550       return 0;
08551    }
08552 
08553    return pbx_builtin_goto(chan, branch);
08554 }

int pbx_builtin_importvar ( struct ast_channel ,
void *   
) [static]

Definition at line 8468 of file pbx.c.

References ast_channel_unlock, ast_get_channel_by_name_locked(), ast_log(), ast_strdupa, ast_strlen_zero(), chan, LOG_WARNING, pbx_builtin_setvar_helper(), pbx_substitute_variables_helper(), s, strsep(), and VAR_BUF_SIZE.

08469 {
08470    char *name;
08471    char *value;
08472    char *channel;
08473    char tmp[VAR_BUF_SIZE];
08474    static int deprecation_warning = 0;
08475 
08476    if (ast_strlen_zero(data)) {
08477       ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n");
08478       return 0;
08479    }
08480    tmp[0] = 0;
08481    if (!deprecation_warning) {
08482       ast_log(LOG_WARNING, "ImportVar is deprecated.  Please use Set(varname=${IMPORT(channel,variable)}) instead.\n");
08483       deprecation_warning = 1;
08484    }
08485 
08486    value = ast_strdupa(data);
08487    name = strsep(&value,"=");
08488    channel = strsep(&value,",");
08489    if (channel && value && name) { /*! \todo XXX should do !ast_strlen_zero(..) of the args ? */
08490       struct ast_channel *chan2 = ast_get_channel_by_name_locked(channel);
08491       if (chan2) {
08492          char *s = alloca(strlen(value) + 4);
08493          if (s) {
08494             sprintf(s, "${%s}", value);
08495             pbx_substitute_variables_helper(chan2, s, tmp, sizeof(tmp) - 1);
08496          }
08497          ast_channel_unlock(chan2);
08498       }
08499       pbx_builtin_setvar_helper(chan, name, tmp);
08500    }
08501 
08502    return(0);
08503 }

static int pbx_builtin_incomplete ( struct ast_channel ,
void *   
) [static]

Definition at line 7901 of file pbx.c.

References __ast_answer(), ast_channel::_state, ast_check_hangup(), AST_PBX_INCOMPLETE, AST_STATE_UP, ast_strlen_zero(), and chan.

07902 {
07903    char *options = data;
07904    int answer = 1;
07905 
07906    /* Some channels can receive DTMF in unanswered state; some cannot */
07907    if (!ast_strlen_zero(options) && strchr(options, 'n')) {
07908       answer = 0;
07909    }
07910 
07911    /* If the channel is hungup, stop waiting */
07912    if (ast_check_hangup(chan)) {
07913       return -1;
07914    } else if (chan->_state != AST_STATE_UP && answer) {
07915       __ast_answer(chan, 0, 1);
07916    }
07917 
07918    return AST_PBX_INCOMPLETE;
07919 }

static int pbx_builtin_noop ( struct ast_channel ,
void *   
) [static]

Definition at line 8505 of file pbx.c.

08506 {
08507    return 0;
08508 }

void pbx_builtin_pushvar_helper ( struct ast_channel chan,
const char *  name,
const char *  value 
)

Note:
Will lock the channel.

Definition at line 8318 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, chan, globals, globalslock, and LOG_WARNING.

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

08319 {
08320    struct ast_var_t *newvariable;
08321    struct varshead *headp;
08322 
08323    if (name[strlen(name)-1] == ')') {
08324       char *function = ast_strdupa(name);
08325 
08326       ast_log(LOG_WARNING, "Cannot push a value onto a function\n");
08327       ast_func_write(chan, function, value);
08328       return;
08329    }
08330 
08331    if (chan) {
08332       ast_channel_lock(chan);
08333       headp = &chan->varshead;
08334    } else {
08335       ast_rwlock_wrlock(&globalslock);
08336       headp = &globals;
08337    }
08338 
08339    if (value) {
08340       if (headp == &globals)
08341          ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value);
08342       newvariable = ast_var_assign(name, value);
08343       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
08344    }
08345 
08346    if (chan)
08347       ast_channel_unlock(chan);
08348    else
08349       ast_rwlock_unlock(&globalslock);
08350 }

int pbx_builtin_raise_exception ( struct ast_channel chan,
void *  vreason 
)

Definition at line 2576 of file pbx.c.

References ast_calloc, ast_channel_datastore_add(), ast_channel_datastore_find(), ast_datastore_alloc(), ast_datastore_free(), ast_free, ast_string_field_init, ast_string_field_set, chan, ast_channel::context, ast_datastore::data, exception_store_info, exten, ast_channel::exten, pbx_exception::priority, ast_channel::priority, and set_ext_pri().

Referenced by __ast_pbx_run().

02577 {
02578    const char *reason = vreason;
02579    struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL);
02580    struct pbx_exception *exception = NULL;
02581 
02582    if (!ds) {
02583       ds = ast_datastore_alloc(&exception_store_info, NULL);
02584       if (!ds)
02585          return -1;
02586       exception = ast_calloc(1, sizeof(struct pbx_exception));
02587       if (!exception) {
02588          ast_datastore_free(ds);
02589          return -1;
02590       }
02591       if (ast_string_field_init(exception, 128)) {
02592          ast_free(exception);
02593          ast_datastore_free(ds);
02594          return -1;
02595       }
02596       ds->data = exception;
02597       ast_channel_datastore_add(chan, ds);
02598    } else
02599       exception = ds->data;
02600 
02601    ast_string_field_set(exception, reason, reason);
02602    ast_string_field_set(exception, context, chan->context);
02603    ast_string_field_set(exception, exten, chan->exten);
02604    exception->priority = chan->priority;
02605    set_ext_pri(chan, "e", 0);
02606    return 0;
02607 }

static int pbx_builtin_saycharacters ( struct ast_channel ,
void *   
) [static]

Definition at line 8593 of file pbx.c.

References ast_say_character_str(), chan, and ast_channel::language.

08594 {
08595    int res = 0;
08596 
08597    if (data)
08598       res = ast_say_character_str(chan, data, "", chan->language);
08599    return res;
08600 }

static int pbx_builtin_saydigits ( struct ast_channel ,
void *   
) [static]

Definition at line 8584 of file pbx.c.

References ast_say_digit_str(), chan, and ast_channel::language.

08585 {
08586    int res = 0;
08587 
08588    if (data)
08589       res = ast_say_digit_str(chan, data, "", chan->language);
08590    return res;
08591 }

static int pbx_builtin_saynumber ( struct ast_channel ,
void *   
) [static]

Definition at line 8556 of file pbx.c.

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

08557 {
08558    char tmp[256];
08559    char *number = tmp;
08560    char *options;
08561 
08562    if (ast_strlen_zero(data)) {
08563       ast_log(LOG_WARNING, "SayNumber requires an argument (number)\n");
08564       return -1;
08565    }
08566    ast_copy_string(tmp, data, sizeof(tmp));
08567    strsep(&number, ",");
08568    options = strsep(&number, ",");
08569    if (options) {
08570       if ( strcasecmp(options, "f") && strcasecmp(options, "m") &&
08571          strcasecmp(options, "c") && strcasecmp(options, "n") ) {
08572          ast_log(LOG_WARNING, "SayNumber gender option is either 'f', 'm', 'c' or 'n'\n");
08573          return -1;
08574       }
08575    }
08576 
08577    if (ast_say_number(chan, atoi(tmp), "", chan->language, options)) {
08578       ast_log(LOG_WARNING, "We were unable to say the number %s, is it too large?\n", tmp);
08579    }
08580 
08581    return 0;
08582 }

static int pbx_builtin_sayphonetic ( struct ast_channel ,
void *   
) [static]

Definition at line 8602 of file pbx.c.

References ast_say_phonetic_str(), chan, and ast_channel::language.

08603 {
08604    int res = 0;
08605 
08606    if (data)
08607       res = ast_say_phonetic_str(chan, data, "", chan->language);
08608    return res;
08609 }

int pbx_builtin_serialize_variables ( struct ast_channel chan,
struct ast_str **  buf 
)

Note:
Will lock the channel.

Definition at line 8248 of file pbx.c.

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

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

08249 {
08250    struct ast_var_t *variables;
08251    const char *var, *val;
08252    int total = 0;
08253 
08254    if (!chan)
08255       return 0;
08256 
08257    (*buf)->used = 0;
08258    (*buf)->str[0] = '\0';
08259 
08260    ast_channel_lock(chan);
08261 
08262    AST_LIST_TRAVERSE(&chan->varshead, variables, entries) {
08263       if ((var = ast_var_name(variables)) && (val = ast_var_value(variables))
08264          /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */
08265          ) {
08266          if (ast_str_append(buf, 0, "%s=%s\n", var, val) < 0) {
08267             ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
08268             break;
08269          } else
08270             total++;
08271       } else
08272          break;
08273    }
08274 
08275    ast_channel_unlock(chan);
08276 
08277    return total;
08278 }

int pbx_builtin_setvar ( struct ast_channel ,
void *   
)

Definition at line 8409 of file pbx.c.

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

Referenced by rpt_exec().

08410 {
08411    char *name, *value, *mydata;
08412 
08413    if (ast_compat_app_set) {
08414       return pbx_builtin_setvar_multiple(chan, data);
08415    }
08416 
08417    if (ast_strlen_zero(data)) {
08418       ast_log(LOG_WARNING, "Set requires one variable name/value pair.\n");
08419       return 0;
08420    }
08421 
08422    mydata = ast_strdupa(data);
08423    name = strsep(&mydata, "=");
08424    value = mydata;
08425    if (strchr(name, ' '))
08426       ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, mydata);
08427 
08428    pbx_builtin_setvar_helper(chan, name, value);
08429    return(0);
08430 }

void pbx_builtin_setvar_helper ( struct ast_channel chan,
const char *  name,
const char *  value 
)

Note:
Will lock the channel.

Definition at line 8352 of file pbx.c.

References ast_channel_lock, ast_channel_unlock, ast_func_write(), AST_LIST_INSERT_HEAD, AST_LIST_REMOVE, AST_LIST_TRAVERSE, ast_rwlock_unlock(), ast_rwlock_wrlock(), ast_strdupa, ast_var_assign(), ast_var_delete(), ast_var_name(), ast_verb, chan, EVENT_FLAG_DIALPLAN, globals, globalslock, manager_event, ast_channel::name, and ast_channel::uniqueid.

Referenced by __oh323_new(), _macro_exec(), _while_exec(), acf_fetch(), acf_odbc_read(), acf_odbc_write(), action_atxfer(), action_setvar(), agi_exec_full(), aji_status_exec(), aqm_exec(), array(), ast_bridge_call(), ast_eivr_setvariable(), ast_feature_request_and_dial(), ast_iax2_new(), ast_monitor_start(), ast_pbx_outgoing_exten(), ast_rtp_set_vars(), ast_set_variables(), asyncgoto_exec(), background_detect_exec(), bridge_exec(), bridge_play_sounds(), builtin_atxfer(), builtin_automixmonitor(), builtin_automonitor(), builtin_blindtransfer(), cb_events(), chanavail_exec(), channel_spy(), conf_run(), controlplayback_exec(), count_exec(), dahdi_handle_dtmfup(), dahdi_new(), dial_exec_full(), do_waiting(), end_bridge_callback(), export_aoc_vars(), export_ch(), frame_set_var(), function_db_delete(), function_db_exists(), function_db_read(), function_realtime_store(), get_rdnis(), get_refer_info(), global_write(), gosub_release_frame(), handle_request_bye(), handle_request_refer(), handle_set_chanvar(), handle_set_global(), handle_setvariable(), hash_read(), hash_write(), isAnsweringMachine(), leave_voicemail(), local_hangup(), lua_set_variable(), lua_set_variable_value(), macro_fixup(), manage_parkinglot(), minivm_accmess_exec(), minivm_delete_exec(), minivm_greet_exec(), minivm_notify_exec(), minivm_record_exec(), misdn_call(), mixmonitor_exec(), ospauth_exec(), ospfinished_exec(), osplookup_exec(), ospnext_exec(), park_exec_full(), parse_moved_contact(), pbx_builtin_background(), 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(), read_exec(), readexten_exec(), readfile_exec(), record_exec(), return_exec(), rotate_file(), rpt_exec(), rqm_exec(), sendimage_exec(), sendtext_exec(), sendurl_exec(), set(), set_agentbycallerid(), set_queue_result(), sip_addheader(), sip_hangup(), sip_new(), skinny_new(), sla_calc_trunk_timeouts(), sla_station_exec(), sla_trunk_exec(), socket_process(), speech_create(), ss_thread(), start_monitor_exec(), system_exec_helper(), transfer_exec(), transmit(), tryexec_exec(), update_bridge_vars(), update_qe_rule(), upqm_exec(), vm_box_exists(), vm_exec(), vmauthenticate(), waituntil_exec(), and zapateller_exec().

08353 {
08354    struct ast_var_t *newvariable;
08355    struct varshead *headp;
08356    const char *nametail = name;
08357 
08358    if (name[strlen(name) - 1] == ')') {
08359       char *function = ast_strdupa(name);
08360 
08361       ast_func_write(chan, function, value);
08362       return;
08363    }
08364 
08365    if (chan) {
08366       ast_channel_lock(chan);
08367       headp = &chan->varshead;
08368    } else {
08369       ast_rwlock_wrlock(&globalslock);
08370       headp = &globals;
08371    }
08372 
08373    /* For comparison purposes, we have to strip leading underscores */
08374    if (*nametail == '_') {
08375       nametail++;
08376       if (*nametail == '_')
08377          nametail++;
08378    }
08379 
08380    AST_LIST_TRAVERSE (headp, newvariable, entries) {
08381       if (strcasecmp(ast_var_name(newvariable), nametail) == 0) {
08382          /* there is already such a variable, delete it */
08383          AST_LIST_REMOVE(headp, newvariable, entries);
08384          ast_var_delete(newvariable);
08385          break;
08386       }
08387    }
08388 
08389    if (value) {
08390       if (headp == &globals)
08391          ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value);
08392       newvariable = ast_var_assign(name, value);
08393       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
08394       manager_event(EVENT_FLAG_DIALPLAN, "VarSet", 
08395          "Channel: %s\r\n"
08396          "Variable: %s\r\n"
08397          "Value: %s\r\n"
08398          "Uniqueid: %s\r\n", 
08399          chan ? chan->name : "none", name, value, 
08400          chan ? chan->uniqueid : "none");
08401    }
08402 
08403    if (chan)
08404       ast_channel_unlock(chan);
08405    else
08406       ast_rwlock_unlock(&globalslock);
08407 }

int pbx_builtin_setvar_multiple ( struct ast_channel ,
void *   
)

Definition at line 8432 of file pbx.c.

References AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), AST_NONSTANDARD_APP_ARGS, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), chan, ast_channel::context, ast_channel::exten, LOG_WARNING, ast_channel::name, pbx_builtin_setvar_helper(), and ast_channel::priority.

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

08433 {
08434    char *data;
08435    int x;
08436    AST_DECLARE_APP_ARGS(args,
08437       AST_APP_ARG(pair)[24];
08438    );
08439    AST_DECLARE_APP_ARGS(pair,
08440       AST_APP_ARG(name);
08441       AST_APP_ARG(value);
08442    );
08443 
08444    if (ast_strlen_zero(vdata)) {
08445       ast_log(LOG_WARNING, "MSet requires at least one variable name/value pair.\n");
08446       return 0;
08447    }
08448 
08449    data = ast_strdupa(vdata);
08450    AST_STANDARD_APP_ARGS(args, data);
08451 
08452    for (x = 0; x < args.argc; x++) {
08453       AST_NONSTANDARD_APP_ARGS(pair, args.pair[x], '=');
08454       if (pair.argc == 2) {
08455          pbx_builtin_setvar_helper(chan, pair.name, pair.value);
08456          if (strchr(pair.name, ' '))
08457             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);
08458       } else if (!chan) {
08459          ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '='\n", pair.name);
08460       } else {
08461          ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '=' (in %s@%s:%d\n", pair.name, chan->exten, chan->context, chan->priority);
08462       }
08463    }
08464 
08465    return 0;
08466 }

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

References ast_strlen_zero().

Referenced by _macro_exec(), _while_exec(), acf_if(), execif_exec(), gosubif_exec(), macroif_exec(), and pbx_builtin_gotoif().

08521 {
08522    int res;
08523    if (ast_strlen_zero(condition)) {                /* NULL or empty strings are false */
08524       return 0;
08525    } else if (sscanf(condition, "%d", &res) == 1) { /* Numbers are evaluated for truth */
08526       return res;
08527    } else {                                         /* Strings are true */
08528       return 1;
08529    }
08530 }

static void pbx_destroy ( struct ast_pbx p  )  [static]

Definition at line 1008 of file pbx.c.

References ast_free.

01009 {
01010    ast_free(p);
01011 }

int pbx_exec ( struct ast_channel c,
struct ast_app app,
void *  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.

Returns:
0 on success, and -1 on failure
Parameters:
c  Channel
app  Application
data  Data for execution

Definition at line 932 of file pbx.c.

References __ast_module_user_add(), __ast_module_user_remove(), app, ast_channel::appl, ast_cdr_setapp(), ast_check_hangup(), ast_log(), ast_strlen_zero(), ast_channel::cdr, ast_channel::data, LOG_WARNING, ast_channel::name, and S_OR.

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

00935 {
00936    int res;
00937    struct ast_module_user *u = NULL;
00938    const char *saved_c_appl;
00939    const char *saved_c_data;
00940 
00941    if (c->cdr && !ast_check_hangup(c))
00942       ast_cdr_setapp(c->cdr, app->name, data);
00943 
00944    /* save channel values */
00945    saved_c_appl= c->appl;
00946    saved_c_data= c->data;
00947 
00948    c->appl = app->name;
00949    c->data = data;
00950    if (app->module)
00951       u = __ast_module_user_add(app->module, c);
00952    if (!ast_strlen_zero(data) && strchr(data, '|') && !strchr(data, ',')) {
00953       ast_log(LOG_WARNING, "The application delimiter is now the comma, not "
00954          "the pipe.  Did you forget to convert your dialplan?  (%s(%s))\n",
00955          app->name, (char *) data);
00956    }
00957    res = app->execute(c, S_OR(data, ""));
00958    if (app->module && u)
00959       __ast_module_user_remove(app->module, u);
00960    /* restore channel values */
00961    c->appl = saved_c_appl;
00962    c->data = saved_c_data;
00963    return res;
00964 }

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

03137 {
03138    struct ast_exten *e;
03139    struct ast_app *app;
03140    int res;
03141    struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */
03142    char passdata[EXT_DATA_SIZE];
03143 
03144    int matching_action = (action == E_MATCH || action == E_CANMATCH || action == E_MATCHMORE);
03145 
03146    ast_rdlock_contexts();
03147    if (found)
03148       *found = 0;
03149 
03150    e = pbx_find_extension(c, con, &q, context, exten, priority, label, callerid, action);
03151    if (e) {
03152       if (found)
03153          *found = 1;
03154       if (matching_action) {
03155          ast_unlock_contexts();
03156          return -1;  /* success, we found it */
03157       } else if (action == E_FINDLABEL) { /* map the label to a priority */
03158          res = e->priority;
03159          ast_unlock_contexts();
03160          return res; /* the priority we were looking for */
03161       } else { /* spawn */
03162          if (!e->cached_app)
03163             e->cached_app = pbx_findapp(e->app);
03164          app = e->cached_app;
03165          ast_unlock_contexts();
03166          if (!app) {
03167             ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority);
03168             return -1;
03169          }
03170          if (c->context != context)
03171             ast_copy_string(c->context, context, sizeof(c->context));
03172          if (c->exten != exten)
03173             ast_copy_string(c->exten, exten, sizeof(c->exten));
03174          c->priority = priority;
03175          pbx_substitute_variables(passdata, sizeof(passdata), c, e);
03176 #ifdef CHANNEL_TRACE
03177          ast_channel_trace_update(c);
03178 #endif
03179          ast_debug(1, "Launching '%s'\n", app->name);
03180          if (VERBOSITY_ATLEAST(3)) {
03181             char tmp[80], tmp2[80], tmp3[EXT_DATA_SIZE];
03182             ast_verb(3, "Executing [%s@%s:%d] %s(\"%s\", \"%s\") %s\n",
03183                exten, context, priority,
03184                term_color(tmp, app->name, COLOR_BRCYAN, 0, sizeof(tmp)),
03185                term_color(tmp2, c->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)),
03186                term_color(tmp3, passdata, COLOR_BRMAGENTA, 0, sizeof(tmp3)),
03187                "in new stack");
03188          }
03189          manager_event(EVENT_FLAG_DIALPLAN, "Newexten",
03190                "Channel: %s\r\n"
03191                "Context: %s\r\n"
03192                "Extension: %s\r\n"
03193                "Priority: %d\r\n"
03194                "Application: %s\r\n"
03195                "AppData: %s\r\n"
03196                "Uniqueid: %s\r\n",
03197                c->name, c->context, c->exten, c->priority, app->name, passdata, c->uniqueid);
03198          return pbx_exec(c, app, passdata);  /* 0 on success, -1 on failure */
03199       }
03200    } else if (q.swo) {  /* not found here, but in another switch */
03201       if (found)
03202          *found = 1;
03203       ast_unlock_contexts();
03204       if (matching_action) {
03205          return -1;
03206       } else {
03207          if (!q.swo->exec) {
03208             ast_log(LOG_WARNING, "No execution engine for switch %s\n", q.swo->name);
03209             res = -1;
03210          }
03211          return q.swo->exec(c, q.foundcontext ? q.foundcontext : context, exten, priority, callerid, q.data);
03212       }
03213    } else { /* not found anywhere, see what happened */
03214       ast_unlock_contexts();
03215       switch (q.status) {
03216       case STATUS_NO_CONTEXT:
03217          if (!matching_action && !combined_find_spawn)
03218             ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", context);
03219          break;
03220       case STATUS_NO_EXTENSION:
03221          if (!matching_action && !combined_find_spawn)
03222             ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, context);
03223          break;
03224       case STATUS_NO_PRIORITY:
03225          if (!matching_action && !combined_find_spawn)
03226             ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, context);
03227          break;
03228       case STATUS_NO_LABEL:
03229          if (context && !combined_find_spawn)
03230             ast_log(LOG_NOTICE, "No such label '%s' in extension '%s' in context '%s'\n", label, exten, context);
03231          break;
03232       default:
03233          ast_debug(1, "Shouldn't happen!\n");
03234       }
03235 
03236       return (matching_action) ? 0 : -1;
03237    }
03238 }

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

References ast_context::alts, ast_autoservice_start(), ast_autoservice_stop(), ast_copy_string(), ast_hashtab_lookup(), AST_LIST_TRAVERSE, ast_log(), AST_PBX_MAX_STACK, ast_str_thread_get(), ast_strdupa, ast_strlen_zero(), ast_walk_context_extensions(), ast_walk_contexts(), ast_walk_extension_priorities(), ast_switch::canmatch, scoreboard::canmatch_exten, chan, contexts_table, create_match_char_tree(), pbx_find_info::data, ast_sw::data, E_CANMATCH, E_FINDLABEL, E_MATCHMORE, ast_sw::eval, ast_switch::exists, scoreboard::exten, ast_exten::exten, extenpatternmatchnew, extension_match_core(), pbx_find_info::foundcontext, include_valid(), ast_context::includes, pbx_find_info::incstack, ast_exten::label, scoreboard::last_char, ast_str::len, LOG_DEBUG, log_match_char_tree(), LOG_NOTICE, LOG_WARNING, match(), matchcid(), ast_switch::matchmore, fake_context::name, 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, ast_str::str, 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(), pbx_extension_helper(), pbx_find_extension(), and register_peer_exten().

02053 {
02054    int x, res;
02055    struct ast_context *tmp = NULL;
02056    struct ast_exten *e = NULL, *eroot = NULL;
02057    struct ast_include *i = NULL;
02058    struct ast_sw *sw = NULL;
02059    struct ast_exten pattern = {NULL, };
02060    struct scoreboard score = {0, };
02061    struct ast_str *tmpdata = NULL;
02062 
02063    pattern.label = label;
02064    pattern.priority = priority;
02065 #ifdef NEED_DEBUG_HERE
02066    ast_log(LOG_NOTICE,"Looking for cont/ext/prio/label/action = %s/%s/%d/%s/%d\n", context, exten, priority, label, (int)action);
02067 #endif
02068 
02069    /* Initialize status if appropriate */
02070    if (q->stacklen == 0) {
02071       q->status = STATUS_NO_CONTEXT;
02072       q->swo = NULL;
02073       q->data = NULL;
02074       q->foundcontext = NULL;
02075    } else if (q->stacklen >= AST_PBX_MAX_STACK) {
02076       ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n");
02077       return NULL;
02078    }
02079 
02080    /* Check first to see if we've already been checked */
02081    for (x = 0; x < q->stacklen; x++) {
02082       if (!strcasecmp(q->incstack[x], context))
02083          return NULL;
02084    }
02085 
02086    if (bypass) /* bypass means we only look there */
02087       tmp = bypass;
02088    else {   /* look in contexts */
02089       struct fake_context item;
02090 
02091       ast_copy_string(item.name, context, sizeof(item.name));
02092 
02093       tmp = ast_hashtab_lookup(contexts_table, &item);
02094 #ifdef NOTNOW
02095       tmp = NULL;
02096       while ((tmp = ast_walk_contexts(tmp)) ) {
02097          if (!strcmp(tmp->name, context))
02098             break;
02099       }
02100 #endif
02101       if (!tmp)
02102          return NULL;
02103       
02104    }
02105 
02106    if (q->status < STATUS_NO_EXTENSION)
02107       q->status = STATUS_NO_EXTENSION;
02108    
02109    /* Do a search for matching extension */
02110 
02111    eroot = NULL;
02112    score.total_specificity = 0;
02113    score.exten = 0;
02114    score.total_length = 0;
02115    if (!tmp->pattern_tree && tmp->root_table)
02116    {
02117       create_match_char_tree(tmp);
02118 #ifdef NEED_DEBUG
02119       ast_log(LOG_DEBUG,"Tree Created in context %s:\n", context);
02120       log_match_char_tree(tmp->pattern_tree," ");
02121 #endif
02122    }
02123 #ifdef NEED_DEBUG
02124    ast_log(LOG_NOTICE,"The Trie we are searching in:\n");
02125    log_match_char_tree(tmp->pattern_tree, "::  ");
02126 #endif
02127 
02128    do {
02129       if (!ast_strlen_zero(overrideswitch)) {
02130          char *osw = ast_strdupa(overrideswitch), *name;
02131          struct ast_switch *asw;
02132          ast_switch_f *aswf = NULL;
02133          char *datap;
02134          int eval = 0;
02135 
02136          name = strsep(&osw, "/");
02137          asw = pbx_findswitch(name);
02138 
02139          if (!asw) {
02140             ast_log(LOG_WARNING, "No such switch '%s'\n", name);
02141             break;
02142          }
02143 
02144          if (osw && strchr(osw, '$')) {
02145             eval = 1;
02146          }
02147 
02148          if (eval && !(tmpdata = ast_str_thread_get(&switch_data, 512))) {
02149             ast_log(LOG_WARNING, "Can't evaluate overrideswitch?!");
02150             break;
02151          } else if (eval) {
02152             /* Substitute variables now */
02153             pbx_substitute_variables_helper(chan, osw, tmpdata->str, tmpdata->len);
02154             datap = tmpdata->str;
02155          } else {
02156             datap = osw;
02157          }
02158 
02159          /* equivalent of extension_match_core() at the switch level */
02160          if (action == E_CANMATCH)
02161             aswf = asw->canmatch;
02162          else if (action == E_MATCHMORE)
02163             aswf = asw->matchmore;
02164          else /* action == E_MATCH */
02165             aswf = asw->exists;
02166          if (!aswf) {
02167             res = 0;
02168          } else {
02169             if (chan) {
02170                ast_autoservice_start(chan);
02171             }
02172             res = aswf(chan, context, exten, priority, callerid, datap);
02173             if (chan) {
02174                ast_autoservice_stop(chan);
02175             }
02176          }
02177          if (res) {  /* Got a match */
02178             q->swo = asw;
02179             q->data = datap;
02180             q->foundcontext = context;
02181             /* XXX keep status = STATUS_NO_CONTEXT ? */
02182             return NULL;
02183          }
02184       }
02185    } while (0);
02186 
02187    if (extenpatternmatchnew) {
02188       new_find_extension(exten, &score, tmp->pattern_tree, 0, 0, callerid, label, action);
02189       eroot = score.exten;
02190       
02191       if (score.last_char == '!' && action == E_MATCHMORE) {
02192          /* We match an extension ending in '!'.
02193           * The decision in this case is final and is NULL (no match).
02194           */
02195 #ifdef NEED_DEBUG_HERE
02196          ast_log(LOG_NOTICE,"Returning MATCHMORE NULL with exclamation point.\n");
02197 #endif
02198          return NULL;
02199       }
02200       
02201       if (!eroot && (action == E_CANMATCH || action == E_MATCHMORE) && score.canmatch_exten) {
02202          q->status = STATUS_SUCCESS;
02203 #ifdef NEED_DEBUG_HERE
02204          ast_log(LOG_NOTICE,"Returning CANMATCH exten %s\n", score.canmatch_exten->exten);
02205 #endif
02206          return score.canmatch_exten;
02207       }
02208       
02209       if ((action == E_MATCHMORE || action == E_CANMATCH)  && eroot) {
02210          if (score.node) {
02211             struct ast_exten *z = trie_find_next_match(score.node);
02212             if (z) {
02213 #ifdef NEED_DEBUG_HERE
02214                ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten %s\n", z->exten);
02215 #endif
02216             } else {
02217                if (score.canmatch_exten) {
02218 #ifdef NEED_DEBUG_HERE
02219                   ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE canmatchmatch exten %s(%p)\n", score.canmatch_exten->exten, score.canmatch_exten);
02220 #endif
02221                   return score.canmatch_exten;
02222                } else {
02223 #ifdef NEED_DEBUG_HERE
02224                   ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten NULL\n");
02225 #endif
02226                }
02227             }
02228             return z;
02229          }
02230 #ifdef NEED_DEBUG_HERE
02231          ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE NULL (no next_match)\n");
02232 #endif
02233          return NULL;  /* according to the code, complete matches are null matches in MATCHMORE mode */
02234       }
02235       
02236       if (eroot) {
02237          /* found entry, now look for the right priority */
02238          if (q->status < STATUS_NO_PRIORITY)
02239             q->status = STATUS_NO_PRIORITY;
02240          e = NULL;
02241          if (action == E_FINDLABEL && label ) {
02242             if (q->status < STATUS_NO_LABEL)
02243                q->status = STATUS_NO_LABEL;
02244             e = ast_hashtab_lookup(eroot->peer_label_table, &pattern);
02245          } else {
02246             e = ast_hashtab_lookup(eroot->peer_table, &pattern);
02247          }
02248          if (e) { /* found a valid match */
02249             q->status = STATUS_SUCCESS;
02250             q->foundcontext = context;
02251 #ifdef NEED_DEBUG_HERE
02252             ast_log(LOG_NOTICE,"Returning complete match of exten %s\n", e->exten);
02253 #endif
02254             return e;
02255          }
02256       }
02257    } else {   /* the old/current default exten pattern match algorithm */
02258       
02259       /* scan the list trying to match extension and CID */
02260       eroot = NULL;
02261       while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) {
02262          int match = extension_match_core(eroot->exten, exten, action);
02263          /* 0 on fail, 1 on match, 2 on earlymatch */
02264          
02265          if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid)))
02266             continue;   /* keep trying */
02267          if (match == 2 && action == E_MATCHMORE) {
02268             /* We match an extension ending in '!'.
02269              * The decision in this case is final and is NULL (no match).
02270              */
02271             return NULL;
02272          }
02273          /* found entry, now look for the right priority */
02274          if (q->status < STATUS_NO_PRIORITY)
02275             q->status = STATUS_NO_PRIORITY;
02276          e = NULL;
02277          if (action == E_FINDLABEL && label ) {
02278             if (q->status < STATUS_NO_LABEL)
02279                q->status = STATUS_NO_LABEL;
02280             e = ast_hashtab_lookup(eroot->peer_label_table, &pattern);
02281          } else {
02282             e = ast_hashtab_lookup(eroot->peer_table, &pattern);
02283          }
02284 #ifdef NOTNOW
02285          while ( (e = ast_walk_extension_priorities(eroot, e)) ) {
02286             /* Match label or priority */
02287             if (action == E_FINDLABEL) {
02288                if (q->status < STATUS_NO_LABEL)
02289                   q->status = STATUS_NO_LABEL;
02290                if (label && e->label && !strcmp(label, e->label))
02291                   break;   /* found it */
02292             } else if (e->priority == priority) {
02293                break;   /* found it */
02294             } /* else keep searching */
02295          }
02296 #endif
02297          if (e) { /* found a valid match */
02298             q->status = STATUS_SUCCESS;
02299             q->foundcontext = context;
02300             return e;
02301          }
02302       }
02303    }
02304    
02305    
02306    /* Check alternative switches */
02307    AST_LIST_TRAVERSE(&tmp->alts, sw, list) {
02308       struct ast_switch *asw = pbx_findswitch(sw->name);
02309       ast_switch_f *aswf = NULL;
02310       char *datap;
02311 
02312       if (!asw) {
02313          ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name);
02314          continue;
02315       }
02316       /* Substitute variables now */
02317       
02318       if (sw->eval) {
02319          if (!(tmpdata = ast_str_thread_get(&switch_data, 512))) {
02320             ast_log(LOG_WARNING, "Can't evaluate switch?!");
02321             continue;
02322          }
02323          pbx_substitute_variables_helper(chan, sw->data, tmpdata->str, tmpdata->len);
02324       }
02325 
02326       /* equivalent of extension_match_core() at the switch level */
02327       if (action == E_CANMATCH)
02328          aswf = asw->canmatch;
02329       else if (action == E_MATCHMORE)
02330          aswf = asw->matchmore;
02331       else /* action == E_MATCH */
02332          aswf = asw->exists;
02333       datap = sw->eval ? tmpdata->str : sw->data;
02334       if (!aswf)
02335          res = 0;
02336       else {
02337          if (chan)
02338             ast_autoservice_start(chan);
02339          res = aswf(chan, context, exten, priority, callerid, datap);
02340          if (chan)
02341             ast_autoservice_stop(chan);
02342       }
02343       if (res) {  /* Got a match */
02344          q->swo = asw;
02345          q->data = datap;
02346          q->foundcontext = context;
02347          /* XXX keep status = STATUS_NO_CONTEXT ? */
02348          return NULL;
02349       }
02350    }
02351    q->incstack[q->stacklen++] = tmp->name;   /* Setup the stack */
02352    /* Now try any includes we have in this context */
02353    for (i = tmp->includes; i; i = i->next) {
02354       if (include_valid(i)) {
02355          if ((e = pbx_find_extension(chan, bypass, q, i->rname, exten, priority, label, callerid, action))) {
02356 #ifdef NEED_DEBUG_HERE
02357             ast_log(LOG_NOTICE,"Returning recursive match of %s\n", e->exten);
02358 #endif
02359             return e;
02360          }
02361          if (q->swo)
02362             return NULL;
02363       }
02364    }
02365    return NULL;
02366 }

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

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

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

00973 {
00974    struct ast_app *tmp;
00975 
00976    AST_RWLIST_RDLOCK(&apps);
00977    AST_RWLIST_TRAVERSE(&apps, tmp, list) {
00978       if (!strcasecmp(tmp->name, app))
00979          break;
00980    }
00981    AST_RWLIST_UNLOCK(&apps);
00982 
00983    return tmp;
00984 }

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

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

00987 {
00988    struct ast_switch *asw;
00989 
00990    AST_RWLIST_RDLOCK(&switches);
00991    AST_RWLIST_TRAVERSE(&switches, asw, list) {
00992       if (!strcasecmp(asw->name, sw))
00993          break;
00994    }
00995    AST_RWLIST_UNLOCK(&switches);
00996 
00997    return asw;
00998 }

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

Definition at line 8908 of file pbx.c.

References ast_async_goto(), ast_explicit_goto(), ast_findlabel_extension(), ast_log(), ast_strdupa, ast_strlen_zero(), chan, ast_channel::cid, ast_callerid::cid_num, ast_channel::context, ast_channel::exten, exten, LOG_WARNING, ast_channel::priority, and strsep().

Referenced by ast_async_parseable_goto(), and ast_parseable_goto().

08909 {
08910    char *exten, *pri, *context;
08911    char *stringp;
08912    int ipri;
08913    int mode = 0;
08914 
08915    if (ast_strlen_zero(goto_string)) {
08916       ast_log(LOG_WARNING, "Goto requires an argument ([[context,]extension,]priority)\n");
08917       return -1;
08918    }
08919    stringp = ast_strdupa(goto_string);
08920    context = strsep(&stringp, ","); /* guaranteed non-null */
08921    exten = strsep(&stringp, ",");
08922    pri = strsep(&stringp, ",");
08923    if (!exten) {  /* Only a priority in this one */
08924       pri = context;
08925       exten = NULL;
08926       context = NULL;
08927    } else if (!pri) {   /* Only an extension and priority in this one */
08928       pri = exten;
08929       exten = context;
08930       context = NULL;
08931    }
08932    if (*pri == '+') {
08933       mode = 1;
08934       pri++;
08935    } else if (*pri == '-') {
08936       mode = -1;
08937       pri++;
08938    }
08939    if (sscanf(pri, "%d", &ipri) != 1) {
08940       if ((ipri = ast_findlabel_extension(chan, context ? context : chan->context, exten ? exten : chan->exten,
08941          pri, chan->cid.cid_num)) < 1) {
08942          ast_log(LOG_WARNING, "Priority '%s' must be a number > 0, or valid label\n", pri);
08943          return -1;
08944       } else
08945          mode = 0;
08946    }
08947    /* At this point we have a priority and maybe an extension and a context */
08948 
08949    if (mode)
08950       ipri = chan->priority + (ipri * mode);
08951 
08952    if (async)
08953       ast_async_goto(chan, context, exten, ipri);
08954    else
08955       ast_explicit_goto(chan, context, exten, ipri);
08956    
08957    return 0;
08958 
08959 }

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

Support for Asterisk built-in variables in the dialplan.

Note:
See also

Definition at line 2448 of file pbx.c.

References ARRAY_LEN, ast_channel_lock, ast_channel_unlock, ast_config_AST_SYSTEM_NAME, ast_copy_string(), ast_eid_default, ast_eid_to_str(), ast_get_hint(), AST_LIST_TRAVERSE, ast_rwlock_rdlock(), ast_rwlock_unlock(), ast_strdupa, ast_var_name(), ast_var_value(), ast_channel::cid, ast_callerid::cid_ani2, ast_callerid::cid_pres, ast_callerid::cid_tns, ast_callerid::cid_ton, ast_channel::context, ast_channel::exten, globals, globalslock, ast_channel::hangupcause, ast_channel::name, parse_variable_name(), ast_channel::priority, s, substring(), and ast_channel::uniqueid.

Referenced by action_getvar(), action_status(), handle_getvariable(), lua_get_variable(), lua_get_variable_value(), and pbx_substitute_variables_helper_full().

02449 {
02450    const char not_found = '\0';
02451    char *tmpvar;
02452    const char *s; /* the result */
02453    int offset, length;
02454    int i, need_substring;
02455    struct varshead *places[2] = { headp, &globals };  /* list of places where we may look */
02456 
02457    if (c) {
02458       ast_channel_lock(c);
02459       places[0] = &c->varshead;
02460    }
02461    /*
02462     * Make a copy of var because parse_variable_name() modifies the string.
02463     * Then if called directly, we might need to run substring() on the result;
02464     * remember this for later in 'need_substring', 'offset' and 'length'
02465     */
02466    tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */
02467    need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */);
02468 
02469    /*
02470     * Look first into predefined variables, then into variable lists.
02471     * Variable 's' points to the result, according to the following rules:
02472     * s == &not_found (set at the beginning) means that we did not find a
02473     * matching variable and need to look into more places.
02474     * If s != &not_found, s is a valid result string as follows:
02475     * s = NULL if the variable does not have a value;
02476     * you typically do this when looking for an unset predefined variable.
02477     * s = workspace if the result has been assembled there;
02478     * typically done when the result is built e.g. with an snprintf(),
02479     * so we don't need to do an additional copy.
02480     * s != workspace in case we have a string, that needs to be copied
02481     * (the ast_copy_string is done once for all at the end).
02482     * Typically done when the result is already available in some string.
02483     */
02484    s = &not_found;   /* default value */
02485    if (c) { /* This group requires a valid channel */
02486       /* Names with common parts are looked up a piece at a time using strncmp. */
02487       if (!strncmp(var, "CALL", 4)) {
02488          if (!strncmp(var + 4, "ING", 3)) {
02489             if (!strcmp(var + 7, "PRES")) {        /* CALLINGPRES */
02490                snprintf(workspace, workspacelen, "%d", c->cid.cid_pres);
02491                s = workspace;
02492             } else if (!strcmp(var + 7, "ANI2")) {    /* CALLINGANI2 */
02493                snprintf(workspace, workspacelen, "%d", c->cid.cid_ani2);
02494                s = workspace;
02495             } else if (!strcmp(var + 7, "TON")) {     /* CALLINGTON */
02496                snprintf(workspace, workspacelen, "%d", c->cid.cid_ton);
02497                s = workspace;
02498             } else if (!strcmp(var + 7, "TNS")) {     /* CALLINGTNS */
02499                snprintf(workspace, workspacelen, "%d", c->cid.cid_tns);
02500                s = workspace;
02501             }
02502          }
02503       } else if (!strcmp(var, "HINT")) {
02504          s = ast_get_hint(workspace, workspacelen, NULL, 0, c, c->context, c->exten) ? workspace : NULL;
02505       } else if (!strcmp(var, "HINTNAME")) {
02506          s = ast_get_hint(NULL, 0, workspace, workspacelen, c, c->context, c->exten) ? workspace : NULL;
02507       } else if (!strcmp(var, "EXTEN")) {
02508          s = c->exten;
02509       } else if (!strcmp(var, "CONTEXT")) {
02510          s = c->context;
02511       } else if (!strcmp(var, "PRIORITY")) {
02512          snprintf(workspace, workspacelen, "%d", c->priority);
02513          s = workspace;
02514       } else if (!strcmp(var, "CHANNEL")) {
02515          s = c->name;
02516       } else if (!strcmp(var, "UNIQUEID")) {
02517          s = c->uniqueid;
02518       } else if (!strcmp(var, "HANGUPCAUSE")) {
02519          snprintf(workspace, workspacelen, "%d", c->hangupcause);
02520          s = workspace;
02521       }
02522    }
02523    if (s == &not_found) { /* look for more */
02524       if (!strcmp(var, "EPOCH")) {
02525          snprintf(workspace, workspacelen, "%u",(int)time(NULL));
02526          s = workspace;
02527       } else if (!strcmp(var, "SYSTEMNAME")) {
02528          s = ast_config_AST_SYSTEM_NAME;
02529       } else if (!strcmp(var, "ENTITYID")) {
02530          ast_eid_to_str(workspace, workspacelen, &ast_eid_default);
02531          s = workspace;
02532       }
02533    }
02534    /* if not found, look into chanvars or global vars */
02535    for (i = 0; s == &not_found && i < ARRAY_LEN(places); i++) {
02536       struct ast_var_t *variables;
02537       if (!places[i])
02538          continue;
02539       if (places[i] == &globals)
02540          ast_rwlock_rdlock(&globalslock);
02541       AST_LIST_TRAVERSE(places[i], variables, entries) {
02542          if (!strcasecmp(ast_var_name(variables), var)) {
02543             s = ast_var_value(variables);
02544             break;
02545          }
02546       }
02547       if (places[i] == &globals)
02548          ast_rwlock_unlock(&globalslock);
02549    }
02550    if (s == &not_found || s == NULL)
02551       *ret = NULL;
02552    else {
02553       if (s != workspace)
02554          ast_copy_string(workspace, s, workspacelen);
02555       *ret = workspace;
02556       if (need_substring)
02557          *ret = substring(*ret, offset, length, workspace, workspacelen);
02558    }
02559 
02560    if (c)
02561       ast_channel_unlock(c);
02562 }

int pbx_set_autofallthrough ( int  newval  ) 

Set "autofallthrough" flag, if newval is <0, does not acutally 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 4084 of file pbx.c.

References autofallthrough.

Referenced by pbx_load_module().

04085 {
04086    int oldval = autofallthrough;
04087    autofallthrough = newval;
04088    return oldval;
04089 }

int pbx_set_extenpatternmatchnew ( int  newval  ) 

Set "extenpatternmatchnew" flag, if newval is <0, does not acutally 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 4091 of file pbx.c.

References extenpatternmatchnew.

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

04092 {
04093    int oldval = extenpatternmatchnew;
04094    extenpatternmatchnew = newval;
04095    return oldval;
04096 }

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

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

Referenced by pbx_load_module().

04099 {
04100    if (overrideswitch) {
04101       ast_free(overrideswitch);
04102    }
04103    if (!ast_strlen_zero(newval)) {
04104       overrideswitch = ast_strdup(newval);
04105    } else {
04106       overrideswitch = NULL;
04107    }
04108 }

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

Definition at line 3099 of file pbx.c.

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

Referenced by pbx_extension_helper().

03100 {
03101    const char *tmp;
03102 
03103    /* Nothing more to do */
03104    if (!e->data)
03105       return;
03106 
03107    /* No variables or expressions in e->data, so why scan it? */
03108    if ((!(tmp = strchr(e->data, '$'))) || (!strstr(tmp, "${") && !strstr(tmp, "$["))) {
03109       ast_copy_string(passdata, e->data, datalen);
03110       return;
03111    }
03112 
03113    pbx_substitute_variables_helper(c, e->data, passdata, datalen - 1);
03114 }

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

Definition at line 3089 of file pbx.c.

References pbx_substitute_variables_helper_full(), and ast_channel::varshead.

Referenced by _macro_exec(), acf_import(), acf_odbc_read(), acf_odbc_write(), ast_add_extension2_lockopt(), config_curl(), custom_log(), cut_internal(), destroy_curl(), exec_exec(), function_eval(), function_fieldqty(), get_mapping_weight(), handle_getvariablefull(), launch_monitor_thread(), make_email_file(), manager_log(), pbx_builtin_importvar(), pbx_find_extension(), pbx_load_config(), pbx_substitute_variables(), realtime_curl(), realtime_multi_curl(), require_curl(), rotate_file(), rpt_do_lstats(), rpt_exec(), sendmail(), sendpage(), sqlite3_log(), store_curl(), substituted(), try_calling(), tryexec_exec(), and update_curl().

03090 {
03091    pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count);
03092 }

static void pbx_substitute_variables_helper_full ( struct ast_channel c,
struct varshead headp,
const char *  cp1,
char *  cp2,
int  count 
) [static]

Definition at line 2897 of file pbx.c.

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

Referenced by pbx_substitute_variables_helper(), and pbx_substitute_variables_varshead().

02898 {
02899    /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!!  */
02900    char *cp4;
02901    const char *tmp, *whereweare;
02902    int length, offset, offset2, isfunction;
02903    char *workspace = NULL;
02904    char *ltmp = NULL, *var = NULL;
02905    char *nextvar, *nextexp, *nextthing;
02906    char *vars, *vare;
02907    int pos, brackets, needsub, len;
02908    
02909    *cp2 = 0; /* just in case nothing ends up there */
02910    whereweare=tmp=cp1;
02911    while (!ast_strlen_zero(whereweare) && count) {
02912       /* Assume we're copying the whole remaining string */
02913       pos = strlen(whereweare);
02914       nextvar = NULL;
02915       nextexp = NULL;
02916       nextthing = strchr(whereweare, '$');
02917       if (nextthing) {
02918          switch (nextthing[1]) {
02919          case '{':
02920             nextvar = nextthing;
02921             pos = nextvar - whereweare;
02922             break;
02923          case '[':
02924             nextexp = nextthing;
02925             pos = nextexp - whereweare;
02926             break;
02927          default:
02928             pos = 1;
02929          }
02930       }
02931 
02932       if (pos) {
02933          /* Can't copy more than 'count' bytes */
02934          if (pos > count)
02935             pos = count;
02936 
02937          /* Copy that many bytes */
02938          memcpy(cp2, whereweare, pos);
02939 
02940          count -= pos;
02941          cp2 += pos;
02942          whereweare += pos;
02943          *cp2 = 0;
02944       }
02945 
02946       if (nextvar) {
02947          /* We have a variable.  Find the start and end, and determine
02948             if we are going to have to recursively call ourselves on the
02949             contents */
02950          vars = vare = nextvar + 2;
02951          brackets = 1;
02952          needsub = 0;
02953 
02954          /* Find the end of it */
02955          while (brackets && *vare) {
02956             if ((vare[0] == '$') && (vare[1] == '{')) {
02957                needsub++;
02958             } else if (vare[0] == '{') {
02959                brackets++;
02960             } else if (vare[0] == '}') {
02961                brackets--;
02962             } else if ((vare[0] == '$') && (vare[1] == '['))
02963                needsub++;
02964             vare++;
02965          }
02966          if (brackets)
02967             ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n");
02968          len = vare - vars - 1;
02969 
02970          /* Skip totally over variable string */
02971          whereweare += (len + 3);
02972 
02973          if (!var)
02974             var = alloca(VAR_BUF_SIZE);
02975 
02976          /* Store variable name (and truncate) */
02977          ast_copy_string(var, vars, len + 1);
02978 
02979          /* Substitute if necessary */
02980          if (needsub) {
02981             if (!ltmp)
02982                ltmp = alloca(VAR_BUF_SIZE);
02983 
02984             pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1);
02985             vars = ltmp;
02986          } else {
02987             vars = var;
02988          }
02989 
02990          if (!workspace)
02991             workspace = alloca(VAR_BUF_SIZE);
02992 
02993          workspace[0] = '\0';
02994 
02995          parse_variable_name(vars, &offset, &offset2, &isfunction);
02996          if (isfunction) {
02997             /* Evaluate function */
02998             if (c || !headp)
02999                cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
03000             else {
03001                struct varshead old;
03002                struct ast_channel *bogus = ast_channel_alloc(0, 0, "", "", "", "", "", 0, "Bogus/%p", vars);
03003                if (bogus) {
03004                   memcpy(&old, &bogus->varshead, sizeof(old));
03005                   memcpy(&bogus->varshead, headp, sizeof(bogus->varshead));
03006                   cp4 = ast_func_read(bogus, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
03007                   /* Don't deallocate the varshead that was passed in */
03008                   memcpy(&bogus->varshead, &old, sizeof(bogus->varshead));
03009                   ast_channel_free(bogus);
03010                } else
03011                   ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution.  Function results may be blank.\n");
03012             }
03013             ast_debug(2, "Function result is '%s'\n", cp4 ? cp4 : "(null)");
03014          } else {
03015             /* Retrieve variable value */
03016             pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp);
03017          }
03018          if (cp4) {
03019             cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE);
03020 
03021             length = strlen(cp4);
03022             if (length > count)
03023                length = count;
03024             memcpy(cp2, cp4, length);
03025             count -= length;
03026             cp2 += length;
03027             *cp2 = 0;
03028          }
03029       } else if (nextexp) {
03030          /* We have an expression.  Find the start and end, and determine
03031             if we are going to have to recursively call ourselves on the
03032             contents */
03033          vars = vare = nextexp + 2;
03034          brackets = 1;
03035          needsub = 0;
03036 
03037          /* Find the end of it */
03038          while (brackets && *vare) {
03039             if ((vare[0] == '$') && (vare[1] == '[')) {
03040                needsub++;
03041                brackets++;
03042                vare++;
03043             } else if (vare[0] == '[') {
03044                brackets++;
03045             } else if (vare[0] == ']') {
03046                brackets--;
03047             } else if ((vare[0] == '$') && (vare[1] == '{')) {
03048                needsub++;
03049                vare++;
03050             }
03051             vare++;
03052          }
03053          if (brackets)
03054             ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n");
03055          len = vare - vars - 1;
03056 
03057          /* Skip totally over expression */
03058          whereweare += (len + 3);
03059 
03060          if (!var)
03061             var = alloca(VAR_BUF_SIZE);
03062 
03063          /* Store variable name (and truncate) */
03064          ast_copy_string(var, vars, len + 1);
03065 
03066          /* Substitute if necessary */
03067          if (needsub) {
03068             if (!ltmp)
03069                ltmp = alloca(VAR_BUF_SIZE);
03070 
03071             pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1);
03072             vars = ltmp;
03073          } else {
03074             vars = var;
03075          }
03076 
03077          length = ast_expr(vars, cp2, count, c);
03078 
03079          if (length) {
03080             ast_debug(1, "Expression result is '%s'\n", cp2);
03081             count -= length;
03082             cp2 += length;
03083             *cp2 = 0;
03084          }
03085       }
03086    }
03087 }

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

Definition at line 3094 of file pbx.c.

References pbx_substitute_variables_helper_full().

Referenced by add_user_extension(), build_user_routes(), dundi_lookup_local(), loopback_subst(), phoneprov_callback(), pp_each_extension_exec(), and pp_each_user_exec().

03095 {
03096    pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count);
03097 }

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

Definition at line 4012 of file pbx.c.

References __ast_pbx_run(), and decrease_call_count().

Referenced by ast_pbx_start().

04013 {
04014    /* Oh joyeous kernel, we're a new thread, with nothing to do but
04015       answer this channel and get it going.
04016    */
04017    /* NOTE:
04018       The launcher of this function _MUST_ increment 'countcalls'
04019       before invoking the function; it will be decremented when the
04020       PBX has finished running on the channel
04021     */
04022    struct ast_channel *c = data;
04023 
04024    __ast_pbx_run(c, NULL);
04025    decrease_call_count();
04026 
04027    pthread_exit(NULL);
04028 
04029    return NULL;
04030 }

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

helper function to print an extension

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

04999 {
05000    int prio = ast_get_extension_priority(e);
05001    if (prio == PRIORITY_HINT) {
05002       snprintf(buf, buflen, "hint: %s",
05003          ast_get_extension_app(e));
05004    } else {
05005       snprintf(buf, buflen, "%d. %s(%s)",
05006          prio, ast_get_extension_app(e),
05007          (!ast_strlen_zero(ast_get_extension_app_data(e)) ? (char *)ast_get_extension_app_data(e) : ""));
05008    }
05009 }

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 3652 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_raise_exception(), and pbx_builtin_waitexten().

03653 {
03654    ast_channel_lock(c);
03655    ast_copy_string(c->exten, exten, sizeof(c->exten));
03656    c->priority = pri;
03657    ast_channel_unlock(c);
03658 }

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

05164 {
05165    struct ast_context *c = NULL;
05166    int res = 0, old_total_exten = dpc->total_exten;
05167 
05168    ast_cli(fd,"\n     In-mem exten Trie for Fast Extension Pattern Matching:\n\n");
05169 
05170    ast_cli(fd,"\n           Explanation: Node Contents Format = <char(s) to match>:<pattern?>:<specif>:[matched extension]\n");
05171    ast_cli(fd,    "                        Where <char(s) to match> is a set of chars, any one of which should match the current character\n");
05172    ast_cli(fd,    "                              <pattern?>: Y if this a pattern match (eg. _XZN[5-7]), N otherwise\n");
05173    ast_cli(fd,    "                              <specif>: an assigned 'exactness' number for this matching char. The lower the number, the more exact the match\n");
05174    ast_cli(fd,    "                              [matched exten]: If all chars matched to this point, which extension this matches. In form: EXTEN:<exten string>\n");
05175    ast_cli(fd,    "                        In general, you match a trie node to a string character, from left to right. All possible matching chars\n");
05176    ast_cli(fd,    "                        are in a string vertically, separated by an unbroken string of '+' characters.\n\n");
05177    ast_rdlock_contexts();
05178 
05179    /* walk all contexts ... */
05180    while ( (c = ast_walk_contexts(c)) ) {
05181       int context_info_printed = 0;
05182 
05183       if (context && strcmp(ast_get_context_name(c), context))
05184          continue;   /* skip this one, name doesn't match */
05185 
05186       dpc->context_existence = 1;
05187 
05188       if (!c->pattern_tree)
05189          ast_exists_extension(NULL, c->name, "s", 1, ""); /* do this to force the trie to built, if it is not already */
05190 
05191       ast_rdlock_context(c);
05192 
05193       dpc->total_context++;
05194       ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
05195          ast_get_context_name(c), ast_get_context_registrar(c));
05196       context_info_printed = 1;
05197       
05198       if (c->pattern_tree)
05199       {
05200          cli_match_char_tree(c->pattern_tree, " ", fd);
05201       } else {
05202          ast_cli(fd,"\n     No Pattern Trie present. Perhaps the context is empty...or there is trouble...\n\n");
05203       }
05204 
05205       ast_unlock_context(c);
05206 
05207       /* if we print something in context, make an empty line */
05208       if (context_info_printed)
05209          ast_cli(fd, "\n");
05210    }
05211    ast_unlock_contexts();
05212 
05213    return (dpc->total_exten == old_total_exten) ? -1 : res;
05214 }

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

05013 {
05014    struct ast_context *c = NULL;
05015    int res = 0, old_total_exten = dpc->total_exten;
05016 
05017    ast_rdlock_contexts();
05018 
05019    /* walk all contexts ... */
05020    while ( (c = ast_walk_contexts(c)) ) {
05021       struct ast_exten *e;
05022       struct ast_include *i;
05023       struct ast_ignorepat *ip;
05024       char buf[256], buf2[256];
05025       int context_info_printed = 0;
05026 
05027       if (context && strcmp(ast_get_context_name(c), context))
05028          continue;   /* skip this one, name doesn't match */
05029 
05030       dpc->context_existence = 1;
05031 
05032       ast_rdlock_context(c);
05033 
05034       /* are we looking for exten too? if yes, we print context
05035        * only if we find our extension.
05036        * Otherwise print context even if empty ?
05037        * XXX i am not sure how the rinclude is handled.
05038        * I think it ought to go inside.
05039        */
05040       if (!exten) {
05041          dpc->total_context++;
05042          ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
05043             ast_get_context_name(c), ast_get_context_registrar(c));
05044          context_info_printed = 1;
05045       }
05046 
05047       /* walk extensions ... */
05048       e = NULL;
05049       while ( (e = ast_walk_context_extensions(c, e)) ) {
05050          struct ast_exten *p;
05051 
05052          if (exten && !ast_extension_match(ast_get_extension_name(e), exten))
05053             continue;   /* skip, extension match failed */
05054 
05055          dpc->extension_existence = 1;
05056 
05057          /* may we print context info? */
05058          if (!context_info_printed) {
05059             dpc->total_context++;
05060             if (rinclude) { /* TODO Print more info about rinclude */
05061                ast_cli(fd, "[ Included context '%s' created by '%s' ]\n",
05062                   ast_get_context_name(c), ast_get_context_registrar(c));
05063             } else {
05064                ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
05065                   ast_get_context_name(c), ast_get_context_registrar(c));
05066             }
05067             context_info_printed = 1;
05068          }
05069          dpc->total_prio++;
05070 
05071          /* write extension name and first peer */
05072          if (e->matchcid)
05073             snprintf(buf, sizeof(buf), "'%s' (CID match '%s') => ", ast_get_extension_name(e), e->cidmatch);
05074          else
05075             snprintf(buf, sizeof(buf), "'%s' =>", ast_get_extension_name(e));
05076 
05077          print_ext(e, buf2, sizeof(buf2));
05078 
05079          ast_cli(fd, "  %-17s %-45s [%s]\n", buf, buf2,
05080             ast_get_extension_registrar(e));
05081 
05082          dpc->total_exten++;
05083          /* walk next extension peers */
05084          p = e;   /* skip the first one, we already got it */
05085          while ( (p = ast_walk_extension_priorities(e, p)) ) {
05086             const char *el = ast_get_extension_label(p);
05087             dpc->total_prio++;
05088             if (el)
05089                snprintf(buf, sizeof(buf), "   [%s]", el);
05090             else
05091                buf[0] = '\0';
05092             print_ext(p, buf2, sizeof(buf2));
05093 
05094             ast_cli(fd,"  %-17s %-45s [%s]\n", buf, buf2,
05095                ast_get_extension_registrar(p));
05096          }
05097       }
05098 
05099       /* walk included and write info ... */
05100       i = NULL;
05101       while ( (i = ast_walk_context_includes(c, i)) ) {
05102          snprintf(buf, sizeof(buf), "'%s'", ast_get_include_name(i));
05103          if (exten) {
05104             /* Check all includes for the requested extension */
05105             if (includecount >= AST_PBX_MAX_STACK) {
05106                ast_log(LOG_WARNING, "Maximum include depth exceeded!\n");
05107             } else {
05108                int dupe = 0;
05109                int x;
05110                for (x = 0; x < includecount; x++) {
05111                   if (!strcasecmp(includes[x], ast_get_include_name(i))) {
05112                      dupe++;
05113                      break;
05114                   }
05115                }
05116                if (!dupe) {
05117                   includes[includecount] = ast_get_include_name(i);
05118                   show_dialplan_helper(fd, ast_get_include_name(i), exten, dpc, i, includecount + 1, includes);
05119                } else {
05120                   ast_log(LOG_WARNING, "Avoiding circular include of %s within %s\n", ast_get_include_name(i), context);
05121                }
05122             }
05123          } else {
05124             ast_cli(fd, "  Include =>        %-45s [%s]\n",
05125                buf, ast_get_include_registrar(i));
05126          }
05127       }
05128 
05129       /* walk ignore patterns and write info ... */
05130       ip = NULL;
05131       while ( (ip = ast_walk_context_ignorepats(c, ip)) ) {
05132          const char *ipname = ast_get_ignorepat_name(ip);
05133          char ignorepat[AST_MAX_EXTENSION];
05134          snprintf(buf, sizeof(buf), "'%s'", ipname);
05135          snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname);
05136          if (!exten || ast_extension_match(ignorepat, exten)) {
05137             ast_cli(fd, "  Ignore pattern => %-45s [%s]\n",
05138                buf, ast_get_ignorepat_registrar(ip));
05139          }
05140       }
05141       if (!rinclude) {
05142          struct ast_sw *sw = NULL;
05143          while ( (sw = ast_walk_context_switches(c, sw)) ) {
05144             snprintf(buf, sizeof(buf), "'%s/%s'",
05145                ast_get_switch_name(sw),
05146                ast_get_switch_data(sw));
05147             ast_cli(fd, "  Alt. Switch =>    %-45s [%s]\n",
05148                buf, ast_get_switch_registrar(sw));
05149          }
05150       }
05151       
05152       ast_unlock_context(c);
05153 
05154       /* if we print something in context, make an empty line */
05155       if (context_info_printed)
05156          ast_cli(fd, "\n");
05157    }
05158    ast_unlock_contexts();
05159 
05160    return (dpc->total_exten == old_total_exten) ? -1 : res;
05161 }

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

References ast_copy_string().

Referenced by pbx_retrieve_variable(), and pbx_substitute_variables_helper_full().

02407 {
02408    char *ret = workspace;
02409    int lr;  /* length of the input string after the copy */
02410 
02411    ast_copy_string(workspace, value, workspace_len); /* always make a copy */
02412 
02413    lr = strlen(ret); /* compute length after copy, so we never go out of the workspace */
02414 
02415    /* Quick check if no need to do anything */
02416    if (offset == 0 && length >= lr) /* take the whole string */
02417       return ret;
02418 
02419    if (offset < 0)   {  /* translate negative offset into positive ones */
02420       offset = lr + offset;
02421       if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */
02422          offset = 0;
02423    }
02424 
02425    /* too large offset result in empty string so we know what to return */
02426    if (offset >= lr)
02427       return ret + lr;  /* the final '\0' */
02428 
02429    ret += offset;    /* move to the start position */
02430    if (length >= 0 && length < lr - offset)  /* truncate if necessary */
02431       ret[length] = '\0';
02432    else if (length < 0) {
02433       if (lr > offset - length) /* After we remove from the front and from the rear, is there anything left? */
02434          ret[lr + length - offset] = '\0';
02435       else
02436          ret[0] = '\0';
02437    }
02438 
02439    return ret;
02440 }

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

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

01181 {
01182    struct match_char *m3;
01183    struct match_char *m4;
01184    struct ast_exten *e3;
01185    
01186    if (node && node->x[0] == '.' && !node->x[1]) /* dot and ! will ALWAYS be next match in a matchmore */
01187       return node->exten;
01188    
01189    if (node && node->x[0] == '!' && !node->x[1])
01190       return node->exten;
01191    
01192    if (!node || !node->next_char)
01193       return NULL;
01194    
01195    m3 = node->next_char;
01196 
01197    if (m3->exten)
01198       return m3->exten;
01199    for(m4=m3->alt_char; m4; m4 = m4->alt_char) {
01200       if (m4->exten)
01201          return m4->exten;
01202    }
01203    for(m4=m3; m4; m4 = m4->alt_char) {
01204       e3 = trie_find_next_match(m3);
01205       if (e3)
01206          return e3;
01207    }
01208    return NULL;
01209 }

static void unreference_cached_app ( struct ast_app app  )  [static]

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

05776 {
05777    struct ast_context *context = NULL;
05778    struct ast_exten *eroot = NULL, *e = NULL;
05779 
05780    ast_rdlock_contexts();
05781    while ((context = ast_walk_contexts(context))) {
05782       while ((eroot = ast_walk_context_extensions(context, eroot))) {
05783          while ((e = ast_walk_extension_priorities(eroot, e))) {
05784             if (e->cached_app == app)
05785                e->cached_app = NULL;
05786          }
05787       }
05788    }
05789    ast_unlock_contexts();
05790 
05791    return;
05792 }

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

01088 {
01089    /* if this extension is marked as deleted, then skip this -- if it never shows
01090       on the scoreboard, it will never be found, nor will halt the traversal. */
01091    if (deleted)
01092       return;
01093    board->total_specificity = spec;
01094    board->total_length = length;
01095    board->exten = exten;
01096    board->last_char = last;
01097    board->node = node;
01098 #ifdef NEED_DEBUG_HERE
01099    ast_log(LOG_NOTICE,"Scoreboarding (LONGER) %s, len=%d, score=%d\n", exten->exten, length, spec);
01100 #endif
01101 }

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

Definition at line 7805 of file pbx.c.

References ast_frfree, ast_read(), ast_safe_sleep(), ast_strlen_zero(), ast_waitfor(), chan, and f.

Referenced by pbx_builtin_busy(), and pbx_builtin_congestion().

07806 {
07807    int res;
07808    struct ast_frame *f;
07809    double waitsec;
07810    int waittime;
07811 
07812    if (ast_strlen_zero(data) || (sscanf(data, "%lg", &waitsec) != 1) || (waitsec < 0))
07813       waitsec = -1;
07814    if (waitsec > -1) {
07815       waittime = waitsec * 1000.0;
07816       ast_safe_sleep(chan, waittime);
07817    } else do {
07818       res = ast_waitfor(chan, -1);
07819       if (res < 0)
07820          return;
07821       f = ast_read(chan);
07822       if (f)
07823          ast_frfree(f);
07824    } while(f);
07825 }


Variable Documentation

int autofallthrough = 1 [static]

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

Referenced by pbx_builtin_background().

struct pbx_builtin builtins[] [static]

Declaration of builtin applications.

Referenced by load_pbx().

struct ast_cli_entry cli_set_chanvar_deprecated = { .handler = handle_set_chanvar_deprecated , .summary = "Set a channel variable." ,__VA_ARGS__ } [static]

Definition at line 5751 of file pbx.c.

struct ast_cli_entry cli_set_global_deprecated = { .handler = handle_set_global_deprecated , .summary = "Set global dialplan variable." ,__VA_ARGS__ } [static]

Definition at line 5752 of file pbx.c.

struct ast_cli_entry cli_show_globals_deprecated = { .handler = handle_show_globals_deprecated , .summary = "Show global dialplan variables." ,__VA_ARGS__ } [static]

Definition at line 5750 of file pbx.c.

ast_rwlock_t conlock = PTHREAD_RWLOCK_INITIALIZER [static]

Lock for the ast_context list

Definition at line 732 of file pbx.c.

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

int conlock_wrlock_version = 0 [static]

Definition at line 8663 of file pbx.c.

struct ast_context* contexts [static]

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

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

int countcalls [static]

Definition at line 435 of file pbx.c.

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

char* days[] [static]

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

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

struct ast_taskprocessor* device_state_tps [static]

Definition at line 127 of file pbx.c.

Referenced by device_state_cb(), and load_pbx().

struct ast_custom_function exception_function [static]

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

Referenced by acf_exception_read(), and pbx_builtin_raise_exception().

int extenpatternmatchnew = 0 [static]

Definition at line 428 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 varshead globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE [static]

Definition at line 425 of file pbx.c.

Referenced by handle_show_globals(), load_config(), load_module(), pbx_builtin_clear_globals(), pbx_builtin_getvar_helper(), pbx_builtin_pushvar_helper(), pbx_builtin_setvar_helper(), pbx_retrieve_variable(), set_active(), set_pvt_defaults(), store_config_core(), and unload_module().

ast_rwlock_t globalslock = PTHREAD_RWLOCK_INITIALIZER [static]

Definition at line 424 of file pbx.c.

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

char mandescr_show_dialplan[] [static]

Definition at line 5538 of file pbx.c.

ast_mutex_t maxcalllock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static]

Definition at line 434 of file pbx.c.

Referenced by decrease_call_count(), and increase_call_count().

char* months[] [static]

Definition at line 6334 of file pbx.c.

Referenced by ast_build_timing().

char* overrideswitch = NULL [static]

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

Referenced by load_pbx().

struct ast_app_option resetcdr_opts[128] = { [ 'w' ] = { .flag = (1 << 1) }, [ 'a' ] = { .flag = (1 << 2) }, [ 'v' ] = { .flag = (1 << 0) }, [ 'e' ] = { .flag = (1 << 10) },} [static]

Definition at line 7926 of file pbx.c.

Referenced by pbx_builtin_resetcdr().

int stateid = 1 [static]

Definition at line 738 of file pbx.c.

Referenced by ast_extension_state_add().

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

Definition at line 129 of file pbx.c.

Referenced by pbx_find_extension().

int totalcalls [static]

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

Referenced by pbx_builtin_waitexten().


Generated on Fri Jun 19 12:10:44 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7