Fri Nov 12 12:06:02 2010

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/event.h"
#include "asterisk/hashtab.h"
#include "asterisk/module.h"
#include "asterisk/indications.h"
#include "asterisk/taskprocessor.h"
#include "asterisk/xmldoc.h"
Include dependency graph for pbx.c:

Go to the source code of this file.

Data Structures

struct  acf_root
struct  app_tmp
struct  apps
struct  ast_app
 ast_app: A registered application More...
struct  ast_context
 ast_context: An extension context More...
struct  ast_exten
 ast_exten: An extension The dialplan is saved as a linked list with each context having it's own linked list of extensions - one item per priority. More...
struct  ast_hint
 Structure for dial plan hints. More...
struct  ast_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_extensionstate_buf (void)
static void __init_switch_data (void)
static int _extension_match_core (const char *pattern, const char *data, enum ext_match_t mode)
static int acf_exception_read (struct ast_channel *chan, const char *name, char *data, char *buf, size_t buflen)
static int acf_retrieve_docs (struct ast_custom_function *acf)
static struct match_charadd_exten_to_pattern_tree (struct ast_context *con, struct ast_exten *e1, int findonly)
static struct match_charadd_pattern_node (struct ast_context *con, struct match_char *current, 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)
 Main interface to add extensions to the list for out context.
static int ast_add_extension2_lockopt (struct ast_context *con, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar, int 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)
 Set the channel to next execute the specified dialplan location.
int ast_async_goto_by_name (const char *channame, const char *context, const char *exten, int priority)
 Set the channel to next execute the specified dialplan location.
int ast_async_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority)
int ast_async_parseable_goto (struct ast_channel *chan, const char *goto_string)
int ast_build_timing (struct ast_timing *i, const char *info_in)
 Construct a timing bitmap, for use in time-based conditionals.
int ast_canmatch_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
 Looks for a valid matching extension.
static int ast_change_hint (struct ast_exten *oe, struct ast_exten *ne)
 Change hint for an extension.
int ast_check_timing (const struct ast_timing *i)
 Evaluate a pre-constructed bitmap as to whether the current time falls within the range specified.
int ast_context_add_ignorepat (const char *context, const char *value, const char *registrar)
 Add an ignorepat.
int ast_context_add_ignorepat2 (struct ast_context *con, const char *value, const char *registrar)
int ast_context_add_include (const char *context, const char *include, const char *registrar)
 Add a context include.
int ast_context_add_include2 (struct ast_context *con, const char *value, const char *registrar)
 Add a context include.
int ast_context_add_switch (const char *context, const char *sw, const char *data, int eval, const char *registrar)
 Add a switch.
int ast_context_add_switch2 (struct ast_context *con, const char *value, const char *data, int eval, const char *registrar)
 Adds a switch (first param is a ast_context).
void ast_context_destroy (struct ast_context *con, const char *registrar)
 Destroy a context (matches the specified context (or ANY context if NULL).
struct ast_contextast_context_find (const char *name)
 Find a context.
struct ast_contextast_context_find_or_create (struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *name, const char *registrar)
 Register a new context or find an existing one.
int ast_context_lockmacro (const char *context)
 locks the macrolock in the given given context
int ast_context_remove_extension (const char *context, const char *extension, int priority, const char *registrar)
 Simply remove extension from context.
int ast_context_remove_extension2 (struct ast_context *con, const char *extension, int priority, const char *registrar, int already_locked)
 This functionc locks given context, search for the right extension and fires out all peer in this extensions with given priority. If priority is set to 0, all peers are removed. After that, unlock context and return.
int ast_context_remove_extension_callerid (const char *context, const char *extension, int priority, const char *callerid, int matchcallerid, const char *registrar)
int ast_context_remove_extension_callerid2 (struct ast_context *con, const char *extension, int priority, const char *callerid, int matchcallerid, const char *registrar, int already_locked)
int ast_context_remove_ignorepat (const char *context, const char *ignorepat, const char *registrar)
int ast_context_remove_ignorepat2 (struct ast_context *con, const char *ignorepat, const char *registrar)
int ast_context_remove_include (const char *context, const char *include, const char *registrar)
 Remove included contexts. This function locks contexts list by &conlist, search for the right context structure, leave context list locked and call ast_context_remove_include2 which removes include, unlock contexts list and return ...
int ast_context_remove_include2 (struct ast_context *con, const char *include, const char *registrar)
 Locks context, remove included contexts, unlocks context. When we call this function, &conlock lock must be locked, because when we giving *con argument, some process can remove/change this context and after that there can be segfault.
int ast_context_remove_switch (const char *context, const char *sw, const char *data, const char *registrar)
 Remove a switch.
int ast_context_remove_switch2 (struct ast_context *con, const char *sw, const char *data, const char *registrar)
 This function locks given context, removes switch, unlock context and return.
int ast_context_unlockmacro (const char *context)
 Unlocks the macrolock in the given context.
int ast_context_verify_includes (struct ast_context *con)
 Verifies includes in an ast_contect structure.
struct ast_custom_functionast_custom_function_find (const char *name)
int ast_custom_function_unregister (struct ast_custom_function *acf)
 Unregister a custom function.
int ast_destroy_timing (struct ast_timing *i)
 Deallocates memory structures associated with a timing bitmap.
enum ast_extension_states ast_devstate_to_extenstate (enum ast_device_state devstate)
 Map devstate to an extension state.
int ast_exists_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
 Determine whether an extension exists.
int ast_explicit_goto (struct ast_channel *chan, const char *context, const char *exten, int priority)
int ast_extension_close (const char *pattern, const char *data, int needmore)
int ast_extension_cmp (const char *a, const char *b)
 Determine if one extension should match before another.
int ast_extension_match (const char *pattern, const char *data)
 Determine if a given extension matches a given pattern (in NXX format).
int ast_extension_state (struct ast_channel *c, const char *context, const char *exten)
 Check extension state for an extension by using hint.
static int ast_extension_state2 (struct ast_exten *e)
 Check state of extension by using hints.
const char * ast_extension_state2str (int extension_state)
 Return extension_state as string.
int ast_extension_state_add (const char *context, const char *exten, ast_state_cb_type callback, void *data)
 Add watcher for extension states.
int ast_extension_state_del (int id, ast_state_cb_type callback)
 Remove a watcher from the callback list.
int ast_findlabel_extension (struct ast_channel *c, const char *context, const char *exten, const char *label, const char *callerid)
 Find the priority of an extension that has the specified label.
int ast_findlabel_extension2 (struct ast_channel *c, struct ast_context *con, const char *exten, const char *label, const char *callerid)
 Find the priority of an extension that has the specified label.
int ast_func_read (struct ast_channel *chan, const char *function, char *workspace, size_t len)
 executes a read operation on a function
int ast_func_write (struct ast_channel *chan, const char *function, const char *value)
 executes a write operation on a function
const char * ast_get_context_name (struct ast_context *con)
const char * ast_get_context_registrar (struct ast_context *c)
const char * ast_get_extension_app (struct ast_exten *e)
void * ast_get_extension_app_data (struct ast_exten *e)
const char * ast_get_extension_cidmatch (struct ast_exten *e)
struct ast_contextast_get_extension_context (struct ast_exten *exten)
const char * ast_get_extension_label (struct ast_exten *exten)
int ast_get_extension_matchcid (struct ast_exten *e)
const char * ast_get_extension_name (struct ast_exten *exten)
int ast_get_extension_priority (struct ast_exten *exten)
const char * ast_get_extension_registrar (struct ast_exten *e)
int ast_get_hint (char *hint, int hintsize, char *name, int namesize, struct ast_channel *c, const char *context, const char *exten)
 Get hint for channel.
const char * ast_get_ignorepat_name (struct ast_ignorepat *ip)
const char * ast_get_ignorepat_registrar (struct ast_ignorepat *ip)
const char * ast_get_include_name (struct ast_include *inc)
const char * ast_get_include_registrar (struct ast_include *i)
const char * ast_get_switch_data (struct ast_sw *sw)
int ast_get_switch_eval (struct ast_sw *sw)
const char * ast_get_switch_name (struct ast_sw *sw)
const char * ast_get_switch_registrar (struct ast_sw *sw)
int ast_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority)
int ast_hashtab_compare_contexts (const void *ah_a, const void *ah_b)
 hashtable functions for contexts
unsigned int ast_hashtab_hash_contexts (const void *obj)
static struct ast_extenast_hint_extension (struct ast_channel *c, const char *context, const char *exten)
static struct ast_extenast_hint_extension_nolock (struct ast_channel *c, const char *context, const char *exten)
 Find hint for given extension in context.
int ast_ignore_pattern (const char *context, const char *pattern)
 Checks to see if a number should be ignored.
int ast_matchmore_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
 Looks to see if adding anything to this extension might match something. (exists ^ canmatch).
void ast_merge_contexts_and_delete (struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *registrar)
 Merge the temporary contexts into a global contexts list and delete from the global list the ones that are being added.
int ast_parseable_goto (struct ast_channel *chan, const char *goto_string)
int ast_pbx_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)
 Dynamically register a new dial plan application.
int ast_register_switch (struct ast_switch *sw)
 Register an alternative dialplan switch.
static int ast_remove_hint (struct ast_exten *e)
 Remove hint from extension.
int ast_spawn_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid, int *found, int combined_find_spawn)
 Launch a new extension (i.e. new stack).
int ast_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.
struct ast_extenast_walk_context_extensions (struct ast_context *con, struct ast_exten *exten)
struct ast_ignorepatast_walk_context_ignorepats (struct ast_context *con, struct ast_ignorepat *ip)
struct ast_includeast_walk_context_includes (struct ast_context *con, struct ast_include *inc)
struct ast_swast_walk_context_switches (struct ast_context *con, struct ast_sw *sw)
struct ast_contextast_walk_contexts (struct ast_context *con)
struct ast_extenast_walk_extension_priorities (struct ast_exten *exten, struct ast_exten *priority)
int ast_wrlock_context (struct ast_context *con)
 Write locks a given context.
int ast_wrlock_contexts ()
 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, unsigned char *bitwise)
 helper functions to sort extensions and patterns in the desired way, so that more specific patterns appear first.
static int ext_strncpy (char *dst, const char *src, int len)
 copy a string skipping whitespace
static int extension_match_core (const char *pattern, const char *data, enum ext_match_t mode)
static struct ast_contextfind_context (const char *context)
 lookup for a context with a given name,
static struct ast_contextfind_context_locked (const char *context)
 lookup for a context with a given name,
static 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 1 minute
static char * handle_debug_dialplan (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 Send ack once.
static char * handle_set_chanvar (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_set_extenpatternmatchnew (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_set_global (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_show_application (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_show_applications (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_show_chanvar (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI support for listing chanvar's variables in a parseable way.
static char * handle_show_dialplan (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_show_function (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_show_functions (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_show_globals (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI support for listing global variables in a parseable way.
static char * handle_show_hint (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 handle_show_hint: CLI support for listing registered dial plan hint
static char * handle_show_hints (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 handle_show_hints: CLI support for listing registered dial plan hints
static char * handle_show_switches (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 handle_show_switches: CLI support for listing registered dial plan switches
static int handle_statechange (void *datap)
static char * handle_unset_extenpatternmatchnew (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int hashtab_compare_exten_labels (const void *ah_a, const void *ah_b)
static int hashtab_compare_exten_numbers (const void *ah_a, const void *ah_b)
static int hashtab_compare_extens (const void *ha_a, const void *ah_b)
static unsigned int hashtab_hash_extens (const void *obj)
static unsigned int hashtab_hash_labels (const void *obj)
static unsigned int hashtab_hash_priority (const void *obj)
static int 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)
 Return a pointer to the value of the corresponding channel variable.
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)
 Add a variable to the channel variable stack, without removing any previously set 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)
 Create a human-readable string, specifying all variables and their corresponding values.
static int pbx_builtin_setamaflags (struct ast_channel *, void *)
int pbx_builtin_setvar (struct ast_channel *, void *)
 Parse and set a single channel variable, where the name and value are separated with an '=' character.
void pbx_builtin_setvar_helper (struct ast_channel *chan, const char *name, const char *value)
 Add a variable to the channel variable stack, removing the most recently set value for the same name.
int pbx_builtin_setvar_multiple (struct ast_channel *, void *)
 Parse and set multiple channel variables, where the pairs are separated by the ',' character, and name and value are separated with an '=' character.
static int pbx_builtin_wait (struct ast_channel *, 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:.
struct ast_extenpbx_find_extension (struct ast_channel *chan, struct ast_context *bypass, struct pbx_find_info *q, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action)
struct ast_apppbx_findapp (const char *app)
 Find application handle in linked list.
static struct ast_switchpbx_findswitch (const char *sw)
static int pbx_parseable_goto (struct ast_channel *chan, const char *goto_string, int async)
void pbx_retrieve_variable (struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp)
 Support for Asterisk built-in variables in the dialplan.
int pbx_set_autofallthrough (int newval)
int pbx_set_extenpatternmatchnew (int newval)
void pbx_set_overrideswitch (const char *newval)
static void pbx_substitute_variables (char *passdata, int datalen, struct ast_channel *c, struct ast_exten *e)
void pbx_substitute_variables_helper (struct ast_channel *c, const char *cp1, char *cp2, int count)
void pbx_substitute_variables_helper_full (struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count, size_t *used)
void pbx_substitute_variables_varshead (struct varshead *headp, const char *cp1, char *cp2, int count)
static void * pbx_thread (void *data)
static void print_app_docs (struct ast_app *aa, int fd)
static void print_ext (struct ast_exten *e, char *buf, int buflen)
 helper function to print an extension
static 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 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 ast_threadstorage extensionstate_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_extensionstate_buf , .custom_init = NULL , }
static struct varshead globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE
static ast_rwlock_t globalslock = PTHREAD_RWLOCK_INITIALIZER
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 1359 of file pbx.c.

#define BACKGROUND_MATCHEXTEN   (1 << 2)

Definition at line 737 of file pbx.c.

Referenced by pbx_builtin_background().

#define BACKGROUND_NOANSWER   (1 << 1)

Definition at line 736 of file pbx.c.

Referenced by pbx_builtin_background().

#define BACKGROUND_PLAYBACK   (1 << 3)

Definition at line 738 of file pbx.c.

Referenced by pbx_builtin_background().

#define BACKGROUND_SKIP   (1 << 0)

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

Referenced by pbx_extension_helper(), and realtime_exec().

#define NEW_MATCHER_CHK_MATCH

Referenced by new_find_extension().

#define NEW_MATCHER_RECURSE

Referenced by new_find_extension().

#define SAY_STUBS

Definition at line 54 of file pbx.c.

#define STATUS_NO_CONTEXT   1

Definition at line 2451 of file pbx.c.

#define STATUS_NO_EXTENSION   2

Definition at line 2452 of file pbx.c.

#define STATUS_NO_LABEL   4

Definition at line 2454 of file pbx.c.

#define STATUS_NO_PRIORITY   3

Definition at line 2453 of file pbx.c.

#define STATUS_SUCCESS   5

Definition at line 2455 of file pbx.c.

#define SWITCH_DATA_LENGTH   256

Definition at line 727 of file pbx.c.

#define VAR_BUF_SIZE   4096
#define VAR_HARDTRAN   3

Definition at line 733 of file pbx.c.

#define VAR_NORMAL   1

Definition at line 731 of file pbx.c.

#define VAR_SOFTTRAN   2

Definition at line 732 of file pbx.c.

#define WAITEXTEN_DIALTONE   (1 << 1)

Definition at line 748 of file pbx.c.

Referenced by pbx_builtin_waitexten().

#define WAITEXTEN_MOH   (1 << 0)

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

References __ast_internal_context_destroy(), ast_context::alts, 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_context::ignorepats, ast_context::includes, ast_context::name, ast_include::next, ast_ignorepat::next, ast_context::next, ast_sw::next, ast_exten::peer_table, ast_exten::priority, ast_context::refcount, ast_exten::registrar, ast_sw::registrar, ast_include::registrar, ast_ignorepat::registrar, ast_context::registrar, ast_context::root, and ast_context::root_table.

Referenced by ast_context_destroy().

08277 {
08278    struct ast_context *tmp, *tmpl=NULL;
08279    struct ast_exten *exten_item, *prio_item;
08280 
08281    for (tmp = list; tmp; ) {
08282       struct ast_context *next = NULL; /* next starting point */
08283          /* The following code used to skip forward to the next
08284             context with matching registrar, but this didn't
08285             make sense; individual priorities registrar'd to
08286             the matching registrar could occur in any context! */
08287       ast_debug(1, "Investigate ctx %s %s\n", tmp->name, tmp->registrar);
08288       if (con) {
08289          for (; tmp; tmpl = tmp, tmp = tmp->next) { /* skip to the matching context */
08290             ast_debug(1, "check ctx %s %s\n", tmp->name, tmp->registrar);
08291             if ( !strcasecmp(tmp->name, con->name) ) {
08292                break;   /* found it */
08293             }
08294          }
08295       }
08296 
08297       if (!tmp)   /* not found, we are done */
08298          break;
08299       ast_wrlock_context(tmp);
08300 
08301       if (registrar) {
08302          /* then search thru and remove any extens that match registrar. */
08303          struct ast_hashtab_iter *exten_iter;
08304          struct ast_hashtab_iter *prio_iter;
08305          struct ast_ignorepat *ip, *ipl = NULL, *ipn = NULL;
08306          struct ast_include *i, *pi = NULL, *ni = NULL;
08307          struct ast_sw *sw = NULL;
08308 
08309          /* remove any ignorepats whose registrar matches */
08310          for (ip = tmp->ignorepats; ip; ip = ipn) {
08311             ipn = ip->next;
08312             if (!strcmp(ip->registrar, registrar)) {
08313                if (ipl) {
08314                   ipl->next = ip->next;
08315                   ast_free(ip);
08316                   continue; /* don't change ipl */
08317                } else {
08318                   tmp->ignorepats = ip->next;
08319                   ast_free(ip);
08320                   continue; /* don't change ipl */
08321                }
08322             }
08323             ipl = ip;
08324          }
08325          /* remove any includes whose registrar matches */
08326          for (i = tmp->includes; i; i = ni) {
08327             ni = i->next;
08328             if (strcmp(i->registrar, registrar) == 0) {
08329                /* remove from list */
08330                if (pi) {
08331                   pi->next = i->next;
08332                   /* free include */
08333                   ast_free(i);
08334                   continue; /* don't change pi */
08335                } else {
08336                   tmp->includes = i->next;
08337                   /* free include */
08338                   ast_free(i);
08339                   continue; /* don't change pi */
08340                }
08341             }
08342             pi = i;
08343          }
08344          /* remove any switches whose registrar matches */
08345          AST_LIST_TRAVERSE_SAFE_BEGIN(&tmp->alts, sw, list) {
08346             if (strcmp(sw->registrar,registrar) == 0) {
08347                AST_LIST_REMOVE_CURRENT(list);
08348                ast_free(sw);
08349             }
08350          }
08351          AST_LIST_TRAVERSE_SAFE_END;
08352 
08353          if (tmp->root_table) { /* it is entirely possible that the context is EMPTY */
08354             exten_iter = ast_hashtab_start_traversal(tmp->root_table);
08355             while ((exten_item=ast_hashtab_next(exten_iter))) {
08356                prio_iter = ast_hashtab_start_traversal(exten_item->peer_table);
08357                while ((prio_item=ast_hashtab_next(prio_iter))) {
08358                   if (!prio_item->registrar || strcmp(prio_item->registrar, registrar) != 0) {
08359                      continue;
08360                   }
08361                   ast_verb(3, "Remove %s/%s/%d, registrar=%s; con=%s(%p); con->root=%p\n",
08362                          tmp->name, prio_item->exten, prio_item->priority, registrar, con? con->name : "<nil>", con, con? con->root_table: NULL);
08363                   /* set matchcid to 1 to insure we get a direct match, and NULL registrar to make sure no wildcarding is done */
08364                   ast_context_remove_extension_callerid2(tmp, prio_item->exten, prio_item->priority, prio_item->cidmatch, 1, NULL, 1);
08365                }
08366                ast_hashtab_end_traversal(prio_iter);
08367             }
08368             ast_hashtab_end_traversal(exten_iter);
08369          }
08370 
08371          /* delete the context if it's registrar matches, is empty, has refcount of 1, */
08372          /* it's not empty, if it has includes, ignorepats, or switches that are registered from
08373             another registrar. It's not empty if there are any extensions */
08374          if (strcmp(tmp->registrar, registrar) == 0 && tmp->refcount < 2 && !tmp->root && !tmp->ignorepats && !tmp->includes && AST_LIST_EMPTY(&tmp->alts)) {
08375             ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar);
08376             ast_hashtab_remove_this_object(contexttab, tmp);
08377 
08378             next = tmp->next;
08379             if (tmpl)
08380                tmpl->next = next;
08381             else
08382                contexts = next;
08383             /* Okay, now we're safe to let it go -- in a sense, we were
08384                ready to let it go as soon as we locked it. */
08385             ast_unlock_context(tmp);
08386             __ast_internal_context_destroy(tmp);
08387          } else {
08388             ast_debug(1,"Couldn't delete ctx %s/%s; refc=%d; tmp.root=%p\n", tmp->name, tmp->registrar,
08389                     tmp->refcount, tmp->root);
08390             ast_unlock_context(tmp);
08391             next = tmp->next;
08392             tmpl = tmp;
08393          }
08394       } else if (con) {
08395          ast_verb(3, "Deleting context %s registrar=%s\n", tmp->name, tmp->registrar);
08396          ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar);
08397          ast_hashtab_remove_this_object(contexttab, tmp);
08398 
08399          next = tmp->next;
08400          if (tmpl)
08401             tmpl->next = next;
08402          else
08403             contexts = next;
08404          /* Okay, now we're safe to let it go -- in a sense, we were
08405             ready to let it go as soon as we locked it. */
08406          ast_unlock_context(tmp);
08407          __ast_internal_context_destroy(tmp);
08408       }
08409 
08410       /* if we have a specific match, we are done, otherwise continue */
08411       tmp = con ? NULL : next;
08412    }
08413 }

int __ast_custom_function_register ( struct ast_custom_function acf,
struct ast_module mod 
)

Register a custom function.

Definition at line 3289 of file pbx.c.

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

Referenced by load_pbx().

03290 {
03291    struct ast_custom_function *cur;
03292    char tmps[80];
03293 
03294    if (!acf) {
03295       return -1;
03296    }
03297 
03298    acf->mod = mod;
03299    acf->docsrc = AST_STATIC_DOC;
03300 
03301    if (acf_retrieve_docs(acf)) {
03302       return -1;
03303    }
03304 
03305    AST_RWLIST_WRLOCK(&acf_root);
03306 
03307    AST_RWLIST_TRAVERSE(&acf_root, cur, acflist) {
03308       if (!strcmp(acf->name, cur->name)) {
03309          ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name);
03310          AST_RWLIST_UNLOCK(&acf_root);
03311          return -1;
03312       }
03313    }
03314 
03315    /* Store in alphabetical order */
03316    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) {
03317       if (strcasecmp(acf->name, cur->name) < 0) {
03318          AST_RWLIST_INSERT_BEFORE_CURRENT(acf, acflist);
03319          break;
03320       }
03321    }
03322    AST_RWLIST_TRAVERSE_SAFE_END;
03323 
03324    if (!cur) {
03325       AST_RWLIST_INSERT_TAIL(&acf_root, acf, acflist);
03326    }
03327 
03328    AST_RWLIST_UNLOCK(&acf_root);
03329 
03330    ast_verb(2, "Registered custom function '%s'\n", term_color(tmps, acf->name, COLOR_BRCYAN, 0, sizeof(tmps)));
03331 
03332    return 0;
03333 }

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

Definition at line 9551 of file pbx.c.

References ast_async_goto(), ast_exists_extension(), ast_explicit_goto(), 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().

09552 {
09553    int (*goto_func)(struct ast_channel *chan, const char *context, const char *exten, int priority);
09554 
09555    if (!chan)
09556       return -2;
09557 
09558    if (context == NULL)
09559       context = chan->context;
09560    if (exten == NULL)
09561       exten = chan->exten;
09562 
09563    goto_func = (async) ? ast_async_goto : ast_explicit_goto;
09564    if (ast_exists_extension(chan, context, exten, priority, chan->cid.cid_num))
09565       return goto_func(chan, context, exten, priority);
09566    else
09567       return -3;
09568 }

static void __ast_internal_context_destroy ( struct ast_context con  )  [static]

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

08230 {
08231    struct ast_include *tmpi;
08232    struct ast_sw *sw;
08233    struct ast_exten *e, *el, *en;
08234    struct ast_ignorepat *ipi;
08235    struct ast_context *tmp = con;
08236 
08237    for (tmpi = tmp->includes; tmpi; ) { /* Free includes */
08238       struct ast_include *tmpil = tmpi;
08239       tmpi = tmpi->next;
08240       ast_free(tmpil);
08241    }
08242    for (ipi = tmp->ignorepats; ipi; ) { /* Free ignorepats */
08243       struct ast_ignorepat *ipl = ipi;
08244       ipi = ipi->next;
08245       ast_free(ipl);
08246    }
08247    if (tmp->registrar)
08248       ast_free(tmp->registrar);
08249 
08250    /* destroy the hash tabs */
08251    if (tmp->root_table) {
08252       ast_hashtab_destroy(tmp->root_table, 0);
08253    }
08254    /* and destroy the pattern tree */
08255    if (tmp->pattern_tree)
08256       destroy_pattern_tree(tmp->pattern_tree);
08257 
08258    while ((sw = AST_LIST_REMOVE_HEAD(&tmp->alts, list)))
08259       ast_free(sw);
08260    for (e = tmp->root; e;) {
08261       for (en = e->peer; en;) {
08262          el = en;
08263          en = en->peer;
08264          destroy_exten(el);
08265       }
08266       el = e;
08267       e = e->next;
08268       destroy_exten(el);
08269    }
08270    tmp->root = NULL;
08271    ast_rwlock_destroy(&tmp->lock);
08272    ast_free(tmp);
08273 }

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

Note:
We get here on a failure of some kind: non-existing extension or hangup. We have options, here. We can either catch the failure and continue, or we can drop out entirely.
If there is no match at priority 1, it is not a valid extension anymore. Try to continue at "i" (for invalid) or "e" (for exception) or exit if neither exist.

Definition at line 4214 of file pbx.c.

References ast_channel::_softhangup, ast_calloc, ast_cdr_end(), ast_cdr_update(), ast_check_hangup(), ast_clear_flag, ast_copy_string(), ast_debug, ast_exists_extension(), AST_FLAG_BRIDGE_HANGUP_RUN, AST_FLAG_IN_AUTOLOOP, ast_free, ast_hangup(), ast_log(), ast_matchmore_extension(), ast_opt_end_cdr_before_h_exten, AST_PBX_ERROR, AST_PBX_INCOMPLETE, ast_set2_flag, ast_set_flag, ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, AST_SOFTHANGUP_ASYNCGOTO, AST_SOFTHANGUP_TIMEOUT, ast_spawn_extension(), ast_strlen_zero(), ast_test_flag, ast_verb, autofallthrough, ast_channel::cdr, ast_channel::cid, ast_callerid::cid_num, collect_digits(), ast_channel::context, ast_pbx::dtimeoutms, ast_channel::exten, LOG_WARNING, ast_channel::name, ast_pbx_args::no_hangup_chan, ast_channel::pbx, pbx_builtin_busy(), pbx_builtin_congestion(), pbx_builtin_getvar_helper(), pbx_builtin_raise_exception(), pbx_builtin_setvar_helper(), pbx_destroy(), ast_channel::priority, ast_pbx::rtimeoutms, set_ext_pri(), status, and ast_channel::whentohangup.

Referenced by ast_pbx_run_args(), and pbx_thread().

04216 {
04217    int found = 0; /* set if we find at least one match */
04218    int res = 0;
04219    int autoloopflag;
04220    int error = 0;    /* set an error conditions */
04221 
04222    /* A little initial setup here */
04223    if (c->pbx) {
04224       ast_log(LOG_WARNING, "%s already has PBX structure??\n", c->name);
04225       /* XXX and now what ? */
04226       ast_free(c->pbx);
04227    }
04228    if (!(c->pbx = ast_calloc(1, sizeof(*c->pbx))))
04229       return -1;
04230    /* Set reasonable defaults */
04231    c->pbx->rtimeoutms = 10000;
04232    c->pbx->dtimeoutms = 5000;
04233 
04234    autoloopflag = ast_test_flag(c, AST_FLAG_IN_AUTOLOOP);   /* save value to restore at the end */
04235    ast_set_flag(c, AST_FLAG_IN_AUTOLOOP);
04236 
04237    /* Start by trying whatever the channel is set to */
04238    if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) {
04239       /* If not successful fall back to 's' */
04240       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);
04241       /* XXX the original code used the existing priority in the call to
04242        * ast_exists_extension(), and reset it to 1 afterwards.
04243        * I believe the correct thing is to set it to 1 immediately.
04244        */
04245       set_ext_pri(c, "s", 1);
04246       if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) {
04247          /* JK02: And finally back to default if everything else failed */
04248          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);
04249          ast_copy_string(c->context, "default", sizeof(c->context));
04250       }
04251    }
04252    if (c->cdr) {
04253       /* allow CDR variables that have been collected after channel was created to be visible during call */
04254       ast_cdr_update(c);
04255    }
04256    for (;;) {
04257       char dst_exten[256]; /* buffer to accumulate digits */
04258       int pos = 0;      /* XXX should check bounds */
04259       int digit = 0;
04260       int invalid = 0;
04261       int timeout = 0;
04262 
04263       /* loop on priorities in this context/exten */
04264       while ( !(res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num, &found,1))) {
04265          if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT && ast_exists_extension(c, c->context, "T", 1, c->cid.cid_num)) {
04266             set_ext_pri(c, "T", 0); /* 0 will become 1 with the c->priority++; at the end */
04267             /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
04268             memset(&c->whentohangup, 0, sizeof(c->whentohangup));
04269             c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT;
04270          } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT && ast_exists_extension(c, c->context, "e", 1, c->cid.cid_num)) {
04271             pbx_builtin_raise_exception(c, "ABSOLUTETIMEOUT");
04272             /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
04273             memset(&c->whentohangup, 0, sizeof(c->whentohangup));
04274             c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT;
04275          } else if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
04276             c->_softhangup = 0;
04277             continue;
04278          } else if (ast_check_hangup(c)) {
04279             ast_debug(1, "Extension %s, priority %d returned normally even though call was hung up\n",
04280                c->exten, c->priority);
04281             error = 1;
04282             break;
04283          }
04284          c->priority++;
04285       } /* end while  - from here on we can use 'break' to go out */
04286       if (found && res) {
04287          /* Something bad happened, or a hangup has been requested. */
04288          if (strchr("0123456789ABCDEF*#", res)) {
04289             ast_debug(1, "Oooh, got something to jump out with ('%c')!\n", res);
04290             pos = 0;
04291             dst_exten[pos++] = digit = res;
04292             dst_exten[pos] = '\0';
04293          } else if (res == AST_PBX_INCOMPLETE) {
04294             ast_debug(1, "Spawn extension (%s,%s,%d) exited INCOMPLETE on '%s'\n", c->context, c->exten, c->priority, c->name);
04295             ast_verb(2, "Spawn extension (%s, %s, %d) exited INCOMPLETE on '%s'\n", c->context, c->exten, c->priority, c->name);
04296 
04297             /* Don't cycle on incomplete - this will happen if the only extension that matches is our "incomplete" extension */
04298             if (!ast_matchmore_extension(c, c->context, c->exten, 1, c->cid.cid_num)) {
04299                invalid = 1;
04300             } else {
04301                ast_copy_string(dst_exten, c->exten, sizeof(dst_exten));
04302                digit = 1;
04303                pos = strlen(dst_exten);
04304             }
04305          } else {
04306             ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
04307             ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
04308 
04309             if ((res == AST_PBX_ERROR) && ast_exists_extension(c, c->context, "e", 1, c->cid.cid_num)) {
04310                /* if we are already on the 'e' exten, don't jump to it again */
04311                if (!strcmp(c->exten, "e")) {
04312                   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);
04313                   error = 1;
04314                } else {
04315                   pbx_builtin_raise_exception(c, "ERROR");
04316                   continue;
04317                }
04318             }
04319 
04320             if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
04321                c->_softhangup = 0;
04322                continue;
04323             } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT && ast_exists_extension(c, c->context, "T", 1, c->cid.cid_num)) {
04324                set_ext_pri(c, "T", 1);
04325                /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
04326                memset(&c->whentohangup, 0, sizeof(c->whentohangup));
04327                c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT;
04328                continue;
04329             } else {
04330                if (c->cdr)
04331                   ast_cdr_update(c);
04332                error = 1;
04333                break;
04334             }
04335          }
04336       }
04337       if (error)
04338          break;
04339 
04340       /*!\note
04341        * We get here on a failure of some kind:  non-existing extension or
04342        * hangup.  We have options, here.  We can either catch the failure
04343        * and continue, or we can drop out entirely. */
04344 
04345       if (invalid || !ast_exists_extension(c, c->context, c->exten, 1, c->cid.cid_num)) {
04346          /*!\note
04347           * If there is no match at priority 1, it is not a valid extension anymore.
04348           * Try to continue at "i" (for invalid) or "e" (for exception) or exit if
04349           * neither exist.
04350           */
04351          if (ast_exists_extension(c, c->context, "i", 1, c->cid.cid_num)) {
04352             ast_verb(3, "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, c->name);
04353             pbx_builtin_setvar_helper(c, "INVALID_EXTEN", c->exten);
04354             set_ext_pri(c, "i", 1);
04355          } else if (ast_exists_extension(c, c->context, "e", 1, c->cid.cid_num)) {
04356             pbx_builtin_raise_exception(c, "INVALID");
04357          } else {
04358             ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n",
04359                c->name, c->exten, c->context);
04360             error = 1; /* we know what to do with it */
04361             break;
04362          }
04363       } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) {
04364          /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */
04365          c->_softhangup = 0;
04366       } else { /* keypress received, get more digits for a full extension */
04367          int waittime = 0;
04368          if (digit)
04369             waittime = c->pbx->dtimeoutms;
04370          else if (!autofallthrough)
04371             waittime = c->pbx->rtimeoutms;
04372          if (!waittime) {
04373             const char *status = pbx_builtin_getvar_helper(c, "DIALSTATUS");
04374             if (!status)
04375                status = "UNKNOWN";
04376             ast_verb(3, "Auto fallthrough, channel '%s' status is '%s'\n", c->name, status);
04377             if (!strcasecmp(status, "CONGESTION"))
04378                res = pbx_builtin_congestion(c, "10");
04379             else if (!strcasecmp(status, "CHANUNAVAIL"))
04380                res = pbx_builtin_congestion(c, "10");
04381             else if (!strcasecmp(status, "BUSY"))
04382                res = pbx_builtin_busy(c, "10");
04383             error = 1; /* XXX disable message */
04384             break;   /* exit from the 'for' loop */
04385          }
04386 
04387          if (collect_digits(c, waittime, dst_exten, sizeof(dst_exten), pos))
04388             break;
04389          if (res == AST_PBX_INCOMPLETE && ast_strlen_zero(&dst_exten[pos]))
04390             timeout = 1;
04391          if (!timeout && ast_exists_extension(c, c->context, dst_exten, 1, c->cid.cid_num)) /* Prepare the next cycle */
04392             set_ext_pri(c, dst_exten, 1);
04393          else {
04394             /* No such extension */
04395             if (!timeout && !ast_strlen_zero(dst_exten)) {
04396                /* An invalid extension */
04397                if (ast_exists_extension(c, c->context, "i", 1, c->cid.cid_num)) {
04398                   ast_verb(3, "Invalid extension '%s' in context '%s' on %s\n", dst_exten, c->context, c->name);
04399                   pbx_builtin_setvar_helper(c, "INVALID_EXTEN", dst_exten);
04400                   set_ext_pri(c, "i", 1);
04401                } else if (ast_exists_extension(c, c->context, "e", 1, c->cid.cid_num)) {
04402                   pbx_builtin_raise_exception(c, "INVALID");
04403                } else {
04404                   ast_log(LOG_WARNING, "Invalid extension '%s', but no rule 'i' in context '%s'\n", dst_exten, c->context);
04405                   found = 1; /* XXX disable message */
04406                   break;
04407                }
04408             } else {
04409                /* A simple timeout */
04410                if (ast_exists_extension(c, c->context, "t", 1, c->cid.cid_num)) {
04411                   ast_verb(3, "Timeout on %s\n", c->name);
04412                   set_ext_pri(c, "t", 1);
04413                } else if (ast_exists_extension(c, c->context, "e", 1, c->cid.cid_num)) {
04414                   pbx_builtin_raise_exception(c, "RESPONSETIMEOUT");
04415                } else {
04416                   ast_log(LOG_WARNING, "Timeout, but no rule 't' in context '%s'\n", c->context);
04417                   found = 1; /* XXX disable message */
04418                   break;
04419                }
04420             }
04421          }
04422          if (c->cdr) {
04423             ast_verb(2, "CDR updated on %s\n",c->name);
04424             ast_cdr_update(c);
04425          }
04426       }
04427    }
04428 
04429    if (!found && !error) {
04430       ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name);
04431    }
04432 
04433    if (!args || !args->no_hangup_chan) {
04434       ast_softhangup(c, AST_SOFTHANGUP_APPUNLOAD);
04435    }
04436 
04437    if ((!args || !args->no_hangup_chan) &&
04438          !ast_test_flag(c, AST_FLAG_BRIDGE_HANGUP_RUN) &&
04439          ast_exists_extension(c, c->context, "h", 1, c->cid.cid_num)) {
04440       set_ext_pri(c, "h", 1);
04441       if (c->cdr && ast_opt_end_cdr_before_h_exten) {
04442          ast_cdr_end(c->cdr);
04443       }
04444       while ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num, &found, 1)) == 0) {
04445          c->priority++;
04446       }
04447       if (found && res) {
04448          /* Something bad happened, or a hangup has been requested. */
04449          ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
04450          ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
04451       }
04452    }
04453    ast_set2_flag(c, autoloopflag, AST_FLAG_IN_AUTOLOOP);
04454    ast_clear_flag(c, AST_FLAG_BRIDGE_HANGUP_RUN); /* from one round to the next, make sure this gets cleared */
04455    pbx_destroy(c->pbx);
04456    c->pbx = NULL;
04457 
04458    if (!args || !args->no_hangup_chan) {
04459       ast_hangup(c);
04460    }
04461 
04462    return 0;
04463 }

static void __init_extensionstate_buf ( void   )  [static]

Definition at line 761 of file pbx.c.

00764 : An extension

static void __init_switch_data ( void   )  [static]

Definition at line 760 of file pbx.c.

00764 : An extension

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

Definition at line 2226 of file pbx.c.

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

Referenced by extension_match_core().

02227 {
02228    mode &= E_MATCH_MASK;   /* only consider the relevant bits */
02229 
02230 #ifdef NEED_DEBUG_HERE
02231    ast_log(LOG_NOTICE,"match core: pat: '%s', dat: '%s', mode=%d\n", pattern, data, (int)mode);
02232 #endif
02233 
02234    if ( (mode == E_MATCH) && (pattern[0] == '_') && (!strcasecmp(pattern,data)) ) { /* note: if this test is left out, then _x. will not match _x. !!! */
02235 #ifdef NEED_DEBUG_HERE
02236       ast_log(LOG_NOTICE,"return (1) - pattern matches pattern\n");
02237 #endif
02238       return 1;
02239    }
02240 
02241    if (pattern[0] != '_') { /* not a pattern, try exact or partial match */
02242       int ld = strlen(data), lp = strlen(pattern);
02243 
02244       if (lp < ld) {    /* pattern too short, cannot match */
02245 #ifdef NEED_DEBUG_HERE
02246          ast_log(LOG_NOTICE,"return (0) - pattern too short, cannot match\n");
02247 #endif
02248          return 0;
02249       }
02250       /* depending on the mode, accept full or partial match or both */
02251       if (mode == E_MATCH) {
02252 #ifdef NEED_DEBUG_HERE
02253          ast_log(LOG_NOTICE,"return (!strcmp(%s,%s) when mode== E_MATCH)\n", pattern, data);
02254 #endif
02255          return !strcmp(pattern, data); /* 1 on match, 0 on fail */
02256       }
02257       if (ld == 0 || !strncasecmp(pattern, data, ld)) { /* partial or full match */
02258 #ifdef NEED_DEBUG_HERE
02259          ast_log(LOG_NOTICE,"return (mode(%d) == E_MATCHMORE ? lp(%d) > ld(%d) : 1)\n", mode, lp, ld);
02260 #endif
02261          return (mode == E_MATCHMORE) ? lp > ld : 1; /* XXX should consider '!' and '/' ? */
02262       } else {
02263 #ifdef NEED_DEBUG_HERE
02264          ast_log(LOG_NOTICE,"return (0) when ld(%d) > 0 && pattern(%s) != data(%s)\n", ld, pattern, data);
02265 #endif
02266          return 0;
02267       }
02268    }
02269    pattern++; /* skip leading _ */
02270    /*
02271     * XXX below we stop at '/' which is a separator for the CID info. However we should
02272     * not store '/' in the pattern at all. When we insure it, we can remove the checks.
02273     */
02274    while (*data && *pattern && *pattern != '/') {
02275       const char *end;
02276 
02277       if (*data == '-') { /* skip '-' in data (just a separator) */
02278          data++;
02279          continue;
02280       }
02281       switch (toupper(*pattern)) {
02282       case '[':   /* a range */
02283          end = strchr(pattern+1, ']'); /* XXX should deal with escapes ? */
02284          if (end == NULL) {
02285             ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n");
02286             return 0;   /* unconditional failure */
02287          }
02288          for (pattern++; pattern != end; pattern++) {
02289             if (pattern+2 < end && pattern[1] == '-') { /* this is a range */
02290                if (*data >= pattern[0] && *data <= pattern[2])
02291                   break;   /* match found */
02292                else {
02293                   pattern += 2; /* skip a total of 3 chars */
02294                   continue;
02295                }
02296             } else if (*data == pattern[0])
02297                break;   /* match found */
02298          }
02299          if (pattern == end) {
02300 #ifdef NEED_DEBUG_HERE
02301             ast_log(LOG_NOTICE,"return (0) when pattern==end\n");
02302 #endif
02303             return 0;
02304          }
02305          pattern = end; /* skip and continue */
02306          break;
02307       case 'N':
02308          if (*data < '2' || *data > '9') {
02309 #ifdef NEED_DEBUG_HERE
02310             ast_log(LOG_NOTICE,"return (0) N is matched\n");
02311 #endif
02312             return 0;
02313          }
02314          break;
02315       case 'X':
02316          if (*data < '0' || *data > '9') {
02317 #ifdef NEED_DEBUG_HERE
02318             ast_log(LOG_NOTICE,"return (0) X is matched\n");
02319 #endif
02320             return 0;
02321          }
02322          break;
02323       case 'Z':
02324          if (*data < '1' || *data > '9') {
02325 #ifdef NEED_DEBUG_HERE
02326             ast_log(LOG_NOTICE,"return (0) Z is matched\n");
02327 #endif
02328             return 0;
02329          }
02330          break;
02331       case '.':   /* Must match, even with more digits */
02332 #ifdef NEED_DEBUG_HERE
02333          ast_log(LOG_NOTICE, "return (1) when '.' is matched\n");
02334 #endif
02335          return 1;
02336       case '!':   /* Early match */
02337 #ifdef NEED_DEBUG_HERE
02338          ast_log(LOG_NOTICE, "return (2) when '!' is matched\n");
02339 #endif
02340          return 2;
02341       case ' ':
02342       case '-':   /* Ignore these in patterns */
02343          data--; /* compensate the final data++ */
02344          break;
02345       default:
02346          if (*data != *pattern) {
02347 #ifdef NEED_DEBUG_HERE
02348             ast_log(LOG_NOTICE, "return (0) when *data(%c) != *pattern(%c)\n", *data, *pattern);
02349 #endif
02350             return 0;
02351          }
02352       }
02353       data++;
02354       pattern++;
02355    }
02356    if (*data)        /* data longer than pattern, no match */ {
02357 #ifdef NEED_DEBUG_HERE
02358       ast_log(LOG_NOTICE, "return (0) when data longer than pattern\n");
02359 #endif
02360       return 0;
02361    }
02362 
02363    /*
02364     * match so far, but ran off the end of the data.
02365     * Depending on what is next, determine match or not.
02366     */
02367    if (*pattern == '\0' || *pattern == '/') {   /* exact match */
02368 #ifdef NEED_DEBUG_HERE
02369       ast_log(LOG_NOTICE, "at end, return (%d) in 'exact match'\n", (mode==E_MATCHMORE) ? 0 : 1);
02370 #endif
02371       return (mode == E_MATCHMORE) ? 0 : 1;  /* this is a failure for E_MATCHMORE */
02372    } else if (*pattern == '!')   {     /* early match */
02373 #ifdef NEED_DEBUG_HERE
02374       ast_log(LOG_NOTICE, "at end, return (2) when '!' is matched\n");
02375 #endif
02376       return 2;
02377    } else {                /* partial match */
02378 #ifdef NEED_DEBUG_HERE
02379       ast_log(LOG_NOTICE, "at end, return (%d) which deps on E_MATCH\n", (mode == E_MATCH) ? 0 : 1);
02380 #endif
02381       return (mode == E_MATCH) ? 0 : 1;   /* this is a failure for E_MATCH */
02382    }
02383 }

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

Definition at line 3028 of file pbx.c.

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

03029 {
03030    struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL);
03031    struct pbx_exception *exception = NULL;
03032    if (!ds || !ds->data)
03033       return -1;
03034    exception = ds->data;
03035    if (!strcasecmp(data, "REASON"))
03036       ast_copy_string(buf, exception->reason, buflen);
03037    else if (!strcasecmp(data, "CONTEXT"))
03038       ast_copy_string(buf, exception->context, buflen);
03039    else if (!strncasecmp(data, "EXTEN", 5))
03040       ast_copy_string(buf, exception->exten, buflen);
03041    else if (!strcasecmp(data, "PRIORITY"))
03042       snprintf(buf, buflen, "%d", exception->priority);
03043    else
03044       return -1;
03045    return 0;
03046 }

static int acf_retrieve_docs ( struct ast_custom_function acf  )  [static]

Definition at line 3244 of file pbx.c.

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

Referenced by __ast_custom_function_register().

03245 {
03246 #ifdef AST_XML_DOCS
03247    char *tmpxml;
03248 
03249    /* Let's try to find it in the Documentation XML */
03250    if (!ast_strlen_zero(acf->desc) || !ast_strlen_zero(acf->synopsis)) {
03251       return 0;
03252    }
03253 
03254    if (ast_string_field_init(acf, 128)) {
03255       return -1;
03256    }
03257 
03258    /* load synopsis */
03259    tmpxml = ast_xmldoc_build_synopsis("function", acf->name);
03260    ast_string_field_set(acf, synopsis, tmpxml);
03261    ast_free(tmpxml);
03262 
03263    /* load description */
03264    tmpxml = ast_xmldoc_build_description("function", acf->name);
03265    ast_string_field_set(acf, desc, tmpxml);
03266    ast_free(tmpxml);
03267 
03268    /* load syntax */
03269    tmpxml = ast_xmldoc_build_syntax("function", acf->name);
03270    ast_string_field_set(acf, syntax, tmpxml);
03271    ast_free(tmpxml);
03272 
03273    /* load arguments */
03274    tmpxml = ast_xmldoc_build_arguments("function", acf->name);
03275    ast_string_field_set(acf, arguments, tmpxml);
03276    ast_free(tmpxml);
03277 
03278    /* load seealso */
03279    tmpxml = ast_xmldoc_build_seealso("function", acf->name);
03280    ast_string_field_set(acf, seealso, tmpxml);
03281    ast_free(tmpxml);
03282 
03283    acf->docsrc = AST_XML_DOC;
03284 #endif
03285 
03286    return 0;
03287 }

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

Definition at line 1873 of file pbx.c.

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

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

01874 {
01875    struct match_char *m1 = NULL, *m2 = NULL, **m0;
01876    int specif;
01877    int already;
01878    int pattern = 0;
01879    char buf[256];
01880    char extenbuf[512];
01881    char *s1 = extenbuf;
01882    int l1 = strlen(e1->exten) + strlen(e1->cidmatch) + 2;
01883 
01884 
01885    ast_copy_string(extenbuf, e1->exten, sizeof(extenbuf));
01886 
01887    if (e1->matchcid &&  l1 <= sizeof(extenbuf)) {
01888       strcat(extenbuf, "/");
01889       strcat(extenbuf, e1->cidmatch);
01890    } else if (l1 > sizeof(extenbuf)) {
01891       ast_log(LOG_ERROR, "The pattern %s/%s is too big to deal with: it will be ignored! Disaster!\n", e1->exten, e1->cidmatch);
01892       return 0;
01893    }
01894 #ifdef NEED_DEBUG
01895    ast_log(LOG_DEBUG, "Adding exten %s%c%s to tree\n", s1, e1->matchcid ? '/' : ' ', e1->matchcid ? e1->cidmatch : "");
01896 #endif
01897    m1 = con->pattern_tree; /* each pattern starts over at the root of the pattern tree */
01898    m0 = &con->pattern_tree;
01899    already = 1;
01900 
01901    if ( *s1 == '_') {
01902       pattern = 1;
01903       s1++;
01904    }
01905    while( *s1 ) {
01906       if (pattern && *s1 == '[' && *(s1-1) != '\\') {
01907          char *s2 = buf;
01908          buf[0] = 0;
01909          s1++; /* get past the '[' */
01910          while (*s1 != ']' && *(s1 - 1) != '\\' ) {
01911             if (*s1 == '\\') {
01912                if (*(s1 + 1) == ']') {
01913                   *s2++ = ']';
01914                   s1++; s1++;
01915                } else if (*(s1 + 1) == '\\') {
01916                   *s2++ = '\\';
01917                   s1++; s1++;
01918                } else if (*(s1 + 1) == '-') {
01919                   *s2++ = '-';
01920                   s1++; s1++;
01921                } else if (*(s1 + 1) == '[') {
01922                   *s2++ = '[';
01923                   s1++; s1++;
01924                }
01925             } else if (*s1 == '-') { /* remember to add some error checking to all this! */
01926                char s3 = *(s1 - 1);
01927                char s4 = *(s1 + 1);
01928                for (s3++; s3 <= s4; s3++) {
01929                   *s2++ = s3;
01930                }
01931                s1++; s1++;
01932             } else if (*s1 == '\0') {
01933                ast_log(LOG_WARNING, "A matching ']' was not found for '[' in pattern string '%s'\n", extenbuf);
01934                break;
01935             } else {
01936                *s2++ = *s1++;
01937             }
01938          }
01939          *s2 = 0; /* null terminate the exploded range */
01940          /* sort the characters */
01941 
01942          specif = strlen(buf);
01943          qsort(buf, specif, 1, compare_char);
01944          specif <<= 8;
01945          specif += buf[0];
01946       } else {
01947 
01948          if (*s1 == '\\') {
01949             s1++;
01950             buf[0] = *s1;
01951          } else {
01952             if (pattern) {
01953                if (*s1 == 'n') /* make sure n,x,z patterns are canonicalized to N,X,Z */
01954                   *s1 = 'N';
01955                else if (*s1 == 'x')
01956                   *s1 = 'X';
01957                else if (*s1 == 'z')
01958                   *s1 = 'Z';
01959             }
01960             buf[0] = *s1;
01961          }
01962          buf[1] = 0;
01963          specif = 1;
01964       }
01965       m2 = 0;
01966       if (already && (m2 = already_in_tree(m1,buf)) && m2->next_char) {
01967          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...
01968                           * a shorter pattern might win if the longer one doesn't match */
01969             m2->exten = e1;
01970             m2->deleted = 0;
01971          }
01972          m1 = m2->next_char; /* m1 points to the node to compare against */
01973          m0 = &m2->next_char; /* m0 points to the ptr that points to m1 */
01974       } else { /* not already OR not m2 OR nor m2->next_char */
01975          if (m2) {
01976             if (findonly) {
01977                return m2;
01978             }
01979             m1 = m2; /* while m0 stays the same */
01980          } else {
01981             if (findonly) {
01982                return m1;
01983             }
01984             m1 = add_pattern_node(con, m1, buf, pattern, already,specif, m0); /* m1 is the node just added */
01985             m0 = &m1->next_char;
01986          }
01987 
01988          if (!(*(s1 + 1))) {
01989             m1->deleted = 0;
01990             m1->exten = e1;
01991          }
01992 
01993          already = 0;
01994       }
01995       s1++; /* advance to next char */
01996    }
01997    return m1;
01998 }

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

Definition at line 1831 of file pbx.c.

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

Referenced by add_exten_to_pattern_tree().

01832 {
01833    struct match_char *m;
01834 
01835    if (!(m = ast_calloc(1, sizeof(*m)))) {
01836       return NULL;
01837    }
01838 
01839    if (!(m->x = ast_strdup(pattern))) {
01840       ast_free(m);
01841       return NULL;
01842    }
01843 
01844    /* the specificity scores are the same as used in the old
01845       pattern matcher. */
01846    m->is_pattern = is_pattern;
01847    if (specificity == 1 && is_pattern && pattern[0] == 'N')
01848       m->specificity = 0x0802;
01849    else if (specificity == 1 && is_pattern && pattern[0] == 'Z')
01850       m->specificity = 0x0901;
01851    else if (specificity == 1 && is_pattern && pattern[0] == 'X')
01852       m->specificity = 0x0a00;
01853    else if (specificity == 1 && is_pattern && pattern[0] == '.')
01854       m->specificity = 0x10000;
01855    else if (specificity == 1 && is_pattern && pattern[0] == '!')
01856       m->specificity = 0x20000;
01857    else
01858       m->specificity = specificity;
01859 
01860    if (!con->pattern_tree) {
01861       insert_in_next_chars_alt_char_list(&con->pattern_tree, m);
01862    } else {
01863       if (already) { /* switch to the new regime (traversing vs appending)*/
01864          insert_in_next_chars_alt_char_list(nextcharptr, m);
01865       } else {
01866          insert_in_next_chars_alt_char_list(&current->next_char, m);
01867       }
01868    }
01869 
01870    return m;
01871 }

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

References add_pri_lockopt().

Referenced by ast_add_extension2_lockopt().

07442 {
07443    return add_pri_lockopt(con, tmp, el, e, replace, 1);
07444 }

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

References add_exten_to_pattern_tree(), ast_add_hint(), ast_add_hint_nolock(), ast_change_hint(), ast_free, ast_hashtab_insert_safe(), ast_hashtab_remove_object_via_lookup(), ast_log(), ast_exten::data, ast_exten::datad, match_char::exten, ast_exten::exten, ast_exten::label, LOG_ERROR, LOG_WARNING, ast_context::name, ast_exten::next, ast_exten::peer, ast_exten::peer_label_table, ast_exten::peer_table, ast_exten::priority, PRIORITY_HINT, ast_context::root, ast_context::root_table, and match_char::x.

Referenced by add_pri().

07453 {
07454    struct ast_exten *ep;
07455    struct ast_exten *eh=e;
07456 
07457    for (ep = NULL; e ; ep = e, e = e->peer) {
07458       if (e->priority >= tmp->priority)
07459          break;
07460    }
07461    if (!e) {   /* go at the end, and ep is surely set because the list is not empty */
07462       ast_hashtab_insert_safe(eh->peer_table, tmp);
07463 
07464       if (tmp->label) {
07465          ast_hashtab_insert_safe(eh->peer_label_table, tmp);
07466       }
07467       ep->peer = tmp;
07468       return 0;   /* success */
07469    }
07470    if (e->priority == tmp->priority) {
07471       /* Can't have something exactly the same.  Is this a
07472          replacement?  If so, replace, otherwise, bonk. */
07473       if (!replace) {
07474          ast_log(LOG_WARNING, "Unable to register extension '%s', priority %d in '%s', already in use\n", tmp->exten, tmp->priority, con->name);
07475          if (tmp->datad) {
07476             tmp->datad(tmp->data);
07477             /* if you free this, null it out */
07478             tmp->data = NULL;
07479          }
07480 
07481          ast_free(tmp);
07482          return -1;
07483       }
07484       /* we are replacing e, so copy the link fields and then update
07485        * whoever pointed to e to point to us
07486        */
07487       tmp->next = e->next; /* not meaningful if we are not first in the peer list */
07488       tmp->peer = e->peer; /* always meaningful */
07489       if (ep)  {     /* We're in the peer list, just insert ourselves */
07490          ast_hashtab_remove_object_via_lookup(eh->peer_table,e);
07491 
07492          if (e->label) {
07493             ast_hashtab_remove_object_via_lookup(eh->peer_label_table,e);
07494          }
07495 
07496          ast_hashtab_insert_safe(eh->peer_table,tmp);
07497          if (tmp->label) {
07498             ast_hashtab_insert_safe(eh->peer_label_table,tmp);
07499          }
07500 
07501          ep->peer = tmp;
07502       } else if (el) {     /* We're the first extension. Take over e's functions */
07503          struct match_char *x = add_exten_to_pattern_tree(con, e, 1);
07504          tmp->peer_table = e->peer_table;
07505          tmp->peer_label_table = e->peer_label_table;
07506          ast_hashtab_remove_object_via_lookup(tmp->peer_table,e);
07507          ast_hashtab_insert_safe(tmp->peer_table,tmp);
07508          if (e->label) {
07509             ast_hashtab_remove_object_via_lookup(tmp->peer_label_table, e);
07510          }
07511          if (tmp->label) {
07512             ast_hashtab_insert_safe(tmp->peer_label_table, tmp);
07513          }
07514 
07515          ast_hashtab_remove_object_via_lookup(con->root_table, e);
07516          ast_hashtab_insert_safe(con->root_table, tmp);
07517          el->next = tmp;
07518          /* The pattern trie points to this exten; replace the pointer,
07519             and all will be well */
07520          if (x) { /* if the trie isn't formed yet, don't sweat this */
07521             if (x->exten) { /* this test for safety purposes */
07522                x->exten = tmp; /* replace what would become a bad pointer */
07523             } else {
07524                ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n");
07525             }
07526          }
07527       } else {       /* We're the very first extension.  */
07528          struct match_char *x = add_exten_to_pattern_tree(con, e, 1);
07529          ast_hashtab_remove_object_via_lookup(con->root_table, e);
07530          ast_hashtab_insert_safe(con->root_table, tmp);
07531          tmp->peer_table = e->peer_table;
07532          tmp->peer_label_table = e->peer_label_table;
07533          ast_hashtab_remove_object_via_lookup(tmp->peer_table, e);
07534          ast_hashtab_insert_safe(tmp->peer_table, tmp);
07535          if (e->label) {
07536             ast_hashtab_remove_object_via_lookup(tmp->peer_label_table, e);
07537          }
07538          if (tmp->label) {
07539             ast_hashtab_insert_safe(tmp->peer_label_table, tmp);
07540          }
07541 
07542          ast_hashtab_remove_object_via_lookup(con->root_table, e);
07543          ast_hashtab_insert_safe(con->root_table, tmp);
07544          con->root = tmp;
07545          /* The pattern trie points to this exten; replace the pointer,
07546             and all will be well */
07547          if (x) { /* if the trie isn't formed yet; no problem */
07548             if (x->exten) { /* this test for safety purposes */
07549                x->exten = tmp; /* replace what would become a bad pointer */
07550             } else {
07551                ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n");
07552             }
07553          }
07554       }
07555       if (tmp->priority == PRIORITY_HINT)
07556          ast_change_hint(e,tmp);
07557       /* Destroy the old one */
07558       if (e->datad)
07559          e->datad(e->data);
07560       ast_free(e);
07561    } else { /* Slip ourselves in just before e */
07562       tmp->peer = e;
07563       tmp->next = e->next; /* extension chain, or NULL if e is not the first extension */
07564       if (ep) {         /* Easy enough, we're just in the peer list */
07565          if (tmp->label) {
07566             ast_hashtab_insert_safe(eh->peer_label_table, tmp);
07567          }
07568          ast_hashtab_insert_safe(eh->peer_table, tmp);
07569          ep->peer = tmp;
07570       } else {       /* we are the first in some peer list, so link in the ext list */
07571          tmp->peer_table = e->peer_table;
07572          tmp->peer_label_table = e->peer_label_table;
07573          e->peer_table = 0;
07574          e->peer_label_table = 0;
07575          ast_hashtab_insert_safe(tmp->peer_table, tmp);
07576          if (tmp->label) {
07577             ast_hashtab_insert_safe(tmp->peer_label_table, tmp);
07578          }
07579          ast_hashtab_remove_object_via_lookup(con->root_table, e);
07580          ast_hashtab_insert_safe(con->root_table, tmp);
07581          if (el)
07582             el->next = tmp;   /* in the middle... */
07583          else
07584             con->root = tmp; /* ... or at the head */
07585          e->next = NULL;   /* e is no more at the head, so e->next must be reset */
07586       }
07587       /* And immediately return success. */
07588       if (tmp->priority == PRIORITY_HINT) {
07589          if (lockhints) {
07590             ast_add_hint(tmp);
07591          } else {
07592             ast_add_hint_nolock(tmp);
07593          }
07594       }
07595    }
07596    return 0;
07597 }

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

Definition at line 1778 of file pbx.c.

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

Referenced by add_exten_to_pattern_tree().

01779 {
01780    struct match_char *t;
01781 
01782    if (!current) {
01783       return 0;
01784    }
01785 
01786    for (t = current; t; t = t->alt_char) {
01787       if (!strcmp(pat, t->x)) { /* uh, we may want to sort exploded [] contents to make matching easy */
01788          return t;
01789       }
01790    }
01791 
01792    return 0;
01793 }

int ast_active_calls ( void   ) 

Retrieve the number of active calls.

Definition at line 4601 of file pbx.c.

References countcalls.

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

04602 {
04603    return countcalls;
04604 }

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

07308 {
07309    int ret = -1;
07310    struct ast_context *c = find_context_locked(context);
07311 
07312    if (c) {
07313       ret = ast_add_extension2(c, replace, extension, priority, label, callerid,
07314          application, data, datad, registrar);
07315       ast_unlock_contexts();
07316    }
07317 
07318    return ret;
07319 }

int ast_add_extension2 ( struct ast_context con,
int  replace,
const char *  extension,
int  priority,
const char *  label,
const char *  callerid,
const char *  application,
void *  data,
void(*)(void *)  datad,
const char *  registrar 
)

Main interface to add extensions to the list for out context.

Add an extension to an extension context, this time with an ast_context *.

We sort extensions in order of matching preference, so that we can stop the search as soon as we find a suitable match. This ordering also takes care of wildcards such as '.' (meaning "one or more of any character") and '!' (which is 'earlymatch', meaning "zero or more of any character" but also impacts the return value from CANMATCH and EARLYMATCH.

The extension match rules defined in the devmeeting 2006.05.05 are quite simple: WE SELECT THE LONGEST MATCH. In detail, "longest" means the number of matched characters in the extension. In case of ties (e.g. _XXX and 333) in the length of a pattern, we give priority to entries with the smallest cardinality (e.g, [5-9] comes before [2-8] before the former has only 5 elements, while the latter has 7, etc. In case of same cardinality, the first element in the range counts. If we still have a tie, any final '!' will make this as a possibly less specific pattern.

EBUSY - can't lock EEXIST - extension with the same priority exist and no replace is set

Definition at line 7624 of file pbx.c.

References ast_add_extension2_lockopt().

Referenced by add_extensions(), ast_add_extension(), build_parkinglot(), context_merge(), load_config(), load_module(), manage_parkinglot(), park_call_full(), pbx_load_config(), pbx_load_users(), sla_build_station(), and sla_build_trunk().

07628 {
07629    return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid, application, data, datad, registrar, 1, 1);
07630 }

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

07641 {
07642    /*
07643     * Sort extensions (or patterns) according to the rules indicated above.
07644     * These are implemented by the function ext_cmp()).
07645     * All priorities for the same ext/pattern/cid are kept in a list,
07646     * using the 'peer' field  as a link field..
07647     */
07648    struct ast_exten *tmp, *tmp2, *e, *el = NULL;
07649    int res;
07650    int length;
07651    char *p;
07652    char expand_buf[VAR_BUF_SIZE];
07653    struct ast_exten dummy_exten = {0};
07654    char dummy_name[1024];
07655 
07656    if (ast_strlen_zero(extension)) {
07657       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",
07658             con->name);
07659       return -1;
07660    }
07661 
07662    /* If we are adding a hint evalulate in variables and global variables */
07663    if (priority == PRIORITY_HINT && strstr(application, "${") && !strstr(extension, "_")) {
07664       struct ast_channel c = {0, };
07665 
07666       ast_copy_string(c.exten, extension, sizeof(c.exten));
07667       ast_copy_string(c.context, con->name, sizeof(c.context));
07668       pbx_substitute_variables_helper(&c, application, expand_buf, sizeof(expand_buf));
07669       application = expand_buf;
07670    }
07671 
07672    length = sizeof(struct ast_exten);
07673    length += strlen(extension) + 1;
07674    length += strlen(application) + 1;
07675    if (label)
07676       length += strlen(label) + 1;
07677    if (callerid)
07678       length += strlen(callerid) + 1;
07679    else
07680       length ++;  /* just the '\0' */
07681 
07682    /* Be optimistic:  Build the extension structure first */
07683    if (!(tmp = ast_calloc(1, length)))
07684       return -1;
07685 
07686    if (ast_strlen_zero(label)) /* let's turn empty labels to a null ptr */
07687       label = 0;
07688 
07689    /* use p as dst in assignments, as the fields are const char * */
07690    p = tmp->stuff;
07691    if (label) {
07692       tmp->label = p;
07693       strcpy(p, label);
07694       p += strlen(label) + 1;
07695    }
07696    tmp->exten = p;
07697    p += ext_strncpy(p, extension, strlen(extension) + 1) + 1;
07698    tmp->priority = priority;
07699    tmp->cidmatch = p;   /* but use p for assignments below */
07700 
07701    /* Blank callerid and NULL callerid are two SEPARATE things.  Do NOT confuse the two!!! */
07702    if (callerid) {
07703       p += ext_strncpy(p, callerid, strlen(callerid) + 1) + 1;
07704       tmp->matchcid = 1;
07705    } else {
07706       *p++ = '\0';
07707       tmp->matchcid = 0;
07708    }
07709    tmp->app = p;
07710    strcpy(p, application);
07711    tmp->parent = con;
07712    tmp->data = data;
07713    tmp->datad = datad;
07714    tmp->registrar = registrar;
07715 
07716    if (lockconts) {
07717       ast_wrlock_context(con);
07718    }
07719 
07720    if (con->pattern_tree) { /* usually, on initial load, the pattern_tree isn't formed until the first find_exten; so if we are adding
07721                         an extension, and the trie exists, then we need to incrementally add this pattern to it. */
07722       ast_copy_string(dummy_name, extension, sizeof(dummy_name));
07723       dummy_exten.exten = dummy_name;
07724       dummy_exten.matchcid = 0;
07725       dummy_exten.cidmatch = 0;
07726       tmp2 = ast_hashtab_lookup(con->root_table, &dummy_exten);
07727       if (!tmp2) {
07728          /* hmmm, not in the trie; */
07729          add_exten_to_pattern_tree(con, tmp, 0);
07730          ast_hashtab_insert_safe(con->root_table, tmp); /* for the sake of completeness */
07731       }
07732    }
07733    res = 0; /* some compilers will think it is uninitialized otherwise */
07734    for (e = con->root; e; el = e, e = e->next) {   /* scan the extension list */
07735       res = ext_cmp(e->exten, tmp->exten);
07736       if (res == 0) { /* extension match, now look at cidmatch */
07737          if (!e->matchcid && !tmp->matchcid)
07738             res = 0;
07739          else if (tmp->matchcid && !e->matchcid)
07740             res = 1;
07741          else if (e->matchcid && !tmp->matchcid)
07742             res = -1;
07743          else
07744             res = ext_cmp(e->cidmatch, tmp->cidmatch);
07745       }
07746       if (res >= 0)
07747          break;
07748    }
07749    if (e && res == 0) { /* exact match, insert in the pri chain */
07750       res = add_pri(con, tmp, el, e, replace);
07751       if (lockconts) {
07752          ast_unlock_context(con);
07753       }
07754       if (res < 0) {
07755          errno = EEXIST;   /* XXX do we care ? */
07756          return 0; /* XXX should we return -1 maybe ? */
07757       }
07758    } else {
07759       /*
07760        * not an exact match, this is the first entry with this pattern,
07761        * so insert in the main list right before 'e' (if any)
07762        */
07763       tmp->next = e;
07764       if (el) {  /* there is another exten already in this context */
07765          el->next = tmp;
07766          tmp->peer_table = ast_hashtab_create(13,
07767                      hashtab_compare_exten_numbers,
07768                      ast_hashtab_resize_java,
07769                      ast_hashtab_newsize_java,
07770                      hashtab_hash_priority,
07771                      0);
07772          tmp->peer_label_table = ast_hashtab_create(7,
07773                         hashtab_compare_exten_labels,
07774                         ast_hashtab_resize_java,
07775                         ast_hashtab_newsize_java,
07776                         hashtab_hash_labels,
07777                         0);
07778          if (label) {
07779             ast_hashtab_insert_safe(tmp->peer_label_table, tmp);
07780          }
07781          ast_hashtab_insert_safe(tmp->peer_table, tmp);
07782       } else {  /* this is the first exten in this context */
07783          if (!con->root_table)
07784             con->root_table = ast_hashtab_create(27,
07785                                        hashtab_compare_extens,
07786                                        ast_hashtab_resize_java,
07787                                        ast_hashtab_newsize_java,
07788                                        hashtab_hash_extens,
07789                                        0);
07790          con->root = tmp;
07791          con->root->peer_table = ast_hashtab_create(13,
07792                         hashtab_compare_exten_numbers,
07793                         ast_hashtab_resize_java,
07794                         ast_hashtab_newsize_java,
07795                         hashtab_hash_priority,
07796                         0);
07797          con->root->peer_label_table = ast_hashtab_create(7,
07798                            hashtab_compare_exten_labels,
07799                            ast_hashtab_resize_java,
07800                            ast_hashtab_newsize_java,
07801                            hashtab_hash_labels,
07802                            0);
07803          if (label) {
07804             ast_hashtab_insert_safe(con->root->peer_label_table, tmp);
07805          }
07806          ast_hashtab_insert_safe(con->root->peer_table, tmp);
07807 
07808       }
07809       ast_hashtab_insert_safe(con->root_table, tmp);
07810       if (lockconts) {
07811          ast_unlock_context(con);
07812       }
07813       if (tmp->priority == PRIORITY_HINT) {
07814          if (lockhints) {
07815             ast_add_hint(tmp);
07816          } else {
07817             ast_add_hint_nolock(tmp);
07818          }
07819       }
07820    }
07821    if (option_debug) {
07822       if (tmp->matchcid) {
07823          ast_debug(1, "Added extension '%s' priority %d (CID match '%s') to %s (%p)\n",
07824                  tmp->exten, tmp->priority, tmp->cidmatch, con->name, con);
07825       } else {
07826          ast_debug(1, "Added extension '%s' priority %d to %s (%p)\n",
07827                  tmp->exten, tmp->priority, con->name, con);
07828       }
07829    }
07830 
07831    if (tmp->matchcid) {
07832       ast_verb(3, "Added extension '%s' priority %d (CID match '%s') to %s (%p)\n",
07833              tmp->exten, tmp->priority, tmp->cidmatch, con->name, con);
07834    } else {
07835       ast_verb(3, "Added extension '%s' priority %d to %s (%p)\n",
07836              tmp->exten, tmp->priority, con->name, con);
07837    }
07838 
07839    return 0;
07840 }

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

References ast_add_extension2_lockopt(), and find_context().

Referenced by ast_merge_contexts_and_delete().

07289 {
07290    int ret = -1;
07291    struct ast_context *c = find_context(context);
07292 
07293    if (c) {
07294       ret = ast_add_extension2_lockopt(c, replace, extension, priority, label, callerid,
07295          application, data, datad, registrar, 0, 0);
07296    }
07297 
07298    return ret;
07299 }

static int ast_add_hint ( struct ast_exten e  )  [static]

Add hint to hint list, check initial extension state.

Definition at line 4060 of file pbx.c.

References ast_add_hint_nolock(), AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

Referenced by add_pri_lockopt(), and ast_add_extension2_lockopt().

04061 {
04062    int ret;
04063 
04064    AST_RWLIST_WRLOCK(&hints);
04065    ret = ast_add_hint_nolock(e);
04066    AST_RWLIST_UNLOCK(&hints);
04067 
04068    return ret;
04069 }

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 4031 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::laststate.

Referenced by add_pri_lockopt(), ast_add_extension2_lockopt(), and ast_add_hint().

04032 {
04033    struct ast_hint *hint;
04034 
04035    if (!e)
04036       return -1;
04037 
04038    /* Search if hint exists, do nothing */
04039    AST_RWLIST_TRAVERSE(&hints, hint, list) {
04040       if (hint->exten == e) {
04041          ast_debug(2, "HINTS: Not re-adding existing hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e));
04042          return -1;
04043       }
04044    }
04045 
04046    ast_debug(2, "HINTS: Adding hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e));
04047 
04048    if (!(hint = ast_calloc(1, sizeof(*hint)))) {
04049       return -1;
04050    }
04051    /* Initialize and insert new item at the top */
04052    hint->exten = e;
04053    hint->laststate = ast_extension_state2(e);
04054    AST_RWLIST_INSERT_HEAD(&hints, hint, list);
04055 
04056    return 0;
04057 }

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

Set the channel to next execute the specified dialplan location.

See also:
ast_async_parseable_goto, ast_async_goto_if_exists

Definition at line 7344 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, 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(), sip_read(), and socket_process().

07345 {
07346    int res = 0;
07347 
07348    ast_channel_lock(chan);
07349 
07350    if (chan->pbx) { /* This channel is currently in the PBX */
07351       ast_explicit_goto(chan, context, exten, priority + 1);
07352       ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO);
07353    } else {
07354       /* In order to do it when the channel doesn't really exist within
07355          the PBX, we have to make a new channel, masquerade, and start the PBX
07356          at the new location */
07357       struct ast_channel *tmpchan = ast_channel_alloc(0, chan->_state, 0, 0, chan->accountcode, chan->exten, chan->context, chan->amaflags, "AsyncGoto/%s", chan->name);
07358       if (!tmpchan) {
07359          res = -1;
07360       } else {
07361          if (chan->cdr) {
07362             ast_cdr_discard(tmpchan->cdr);
07363             tmpchan->cdr = ast_cdr_dup(chan->cdr);  /* share the love */
07364          }
07365          /* Make formats okay */
07366          tmpchan->readformat = chan->readformat;
07367          tmpchan->writeformat = chan->writeformat;
07368          /* Setup proper location */
07369          ast_explicit_goto(tmpchan,
07370             S_OR(context, chan->context), S_OR(exten, chan->exten), priority);
07371 
07372          /* Masquerade into temp channel */
07373          if (ast_channel_masquerade(tmpchan, chan)) {
07374             /* Failed to set up the masquerade.  It's probably chan_local
07375              * in the middle of optimizing itself out.  Sad. :( */
07376             ast_hangup(tmpchan);
07377             tmpchan = NULL;
07378             res = -1;
07379          } else {
07380             /* Grab the locks and get going */
07381             ast_channel_lock(tmpchan);
07382             ast_do_masquerade(tmpchan);
07383             ast_channel_unlock(tmpchan);
07384             /* Start the PBX going on our stolen channel */
07385             if (ast_pbx_start(tmpchan)) {
07386                ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name);
07387                ast_hangup(tmpchan);
07388                res = -1;
07389             }
07390          }
07391       }
07392    }
07393    ast_channel_unlock(chan);
07394    return res;
07395 }

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

Set the channel to next execute the specified dialplan location.

Definition at line 7397 of file pbx.c.

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

07398 {
07399    struct ast_channel *chan;
07400    int res = -1;
07401 
07402    chan = ast_get_channel_by_name_locked(channame);
07403    if (chan) {
07404       res = ast_async_goto(chan, context, exten, priority);
07405       ast_channel_unlock(chan);
07406    }
07407    return res;
07408 }

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

References __ast_goto_if_exists().

09576 {
09577    return __ast_goto_if_exists(chan, context, exten, priority, 1);
09578 }

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

References pbx_parseable_goto().

Referenced by asyncgoto_exec(), and handle_redirect().

09639 {
09640    return pbx_parseable_goto(chan, goto_string, 1);
09641 }

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

Construct a timing bitmap, for use in time-based conditionals.

Parameters:
i Pointer to an ast_timing structure.
info Standard string containing a timerange, weekday range, monthday range, and month range, as well as an optional timezone.
Return values:
Returns 1 on success or 0 on failure.

Definition at line 6939 of file pbx.c.

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

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

06940 {
06941    char *info_save, *info;
06942    int j, num_fields, last_sep = -1;
06943 
06944    /* Check for empty just in case */
06945    if (ast_strlen_zero(info_in)) {
06946       return 0;
06947    }
06948 
06949    /* make a copy just in case we were passed a static string */
06950    info_save = info = ast_strdupa(info_in);
06951 
06952    /* count the number of fields in the timespec */
06953    for (j = 0, num_fields = 1; info[j] != '\0'; j++) {
06954       if (info[j] == ',') {
06955          last_sep = j;
06956          num_fields++;
06957       }
06958    }
06959 
06960    /* save the timezone, if it is specified */
06961    if (num_fields == 5) {
06962       i->timezone = ast_strdup(info + last_sep + 1);
06963    } else {
06964       i->timezone = NULL;
06965    }
06966 
06967    /* Assume everything except time */
06968    i->monthmask = 0xfff;   /* 12 bits */
06969    i->daymask = 0x7fffffffU; /* 31 bits */
06970    i->dowmask = 0x7f; /* 7 bits */
06971    /* on each call, use strsep() to move info to the next argument */
06972    get_timerange(i, strsep(&info, "|,"));
06973    if (info)
06974       i->dowmask = get_range(strsep(&info, "|,"), 7, days, "day of week");
06975    if (info)
06976       i->daymask = get_range(strsep(&info, "|,"), 31, NULL, "day");
06977    if (info)
06978       i->monthmask = get_range(strsep(&info, "|,"), 12, months, "month");
06979    return 1;
06980 }

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

References E_CANMATCH, and pbx_extension_helper().

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

04159 {
04160    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0);
04161 }

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

Change hint for an extension.

Definition at line 4072 of file pbx.c.

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

Referenced by add_pri_lockopt().

04073 {
04074    struct ast_hint *hint;
04075    int res = -1;
04076 
04077    AST_RWLIST_WRLOCK(&hints);
04078    AST_RWLIST_TRAVERSE(&hints, hint, list) {
04079       if (hint->exten == oe) {
04080          hint->exten = ne;
04081          res = 0;
04082          break;
04083       }
04084    }
04085    AST_RWLIST_UNLOCK(&hints);
04086 
04087    return res;
04088 }

int ast_check_timing ( const struct ast_timing i  ) 

Evaluate a pre-constructed bitmap as to whether the current time falls within the range specified.

Parameters:
i Pointer to an ast_timing structure.
Return values:
Returns 1, if the time matches or 0, if the current time falls outside of the specified range.

Definition at line 6982 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_timing::timezone, ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, and ast_tm::tm_wday.

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

06983 {
06984    struct ast_tm tm;
06985    struct timeval now = ast_tvnow();
06986 
06987    ast_localtime(&now, &tm, i->timezone);
06988 
06989    /* If it's not the right month, return */
06990    if (!(i->monthmask & (1 << tm.tm_mon)))
06991       return 0;
06992 
06993    /* If it's not that time of the month.... */
06994    /* Warning, tm_mday has range 1..31! */
06995    if (!(i->daymask & (1 << (tm.tm_mday-1))))
06996       return 0;
06997 
06998    /* If it's not the right day of the week */
06999    if (!(i->dowmask & (1 << tm.tm_wday)))
07000       return 0;
07001 
07002    /* Sanity check the hour just to be safe */
07003    if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) {
07004       ast_log(LOG_WARNING, "Insane time...\n");
07005       return 0;
07006    }
07007 
07008    /* Now the tough part, we calculate if it fits
07009       in the right time based on min/hour */
07010    if (!(i->minmask[tm.tm_hour * 2 + (tm.tm_min >= 30 ? 1 : 0)] & (1 << (tm.tm_min >= 30 ? tm.tm_min - 30 : tm.tm_min))))
07011       return 0;
07012 
07013    /* If we got this far, then we're good */
07014    return 1;
07015 }

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

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

Referenced by handle_cli_dialplan_add_ignorepat().

07218 {
07219    int ret = -1;
07220    struct ast_context *c = find_context_locked(context);
07221 
07222    if (c) {
07223       ret = ast_context_add_ignorepat2(c, value, registrar);
07224       ast_unlock_contexts();
07225    }
07226    return ret;
07227 }

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

Definition at line 7229 of file pbx.c.

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

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

07230 {
07231    struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL;
07232    int length;
07233    char *pattern;
07234    length = sizeof(struct ast_ignorepat);
07235    length += strlen(value) + 1;
07236    if (!(ignorepat = ast_calloc(1, length)))
07237       return -1;
07238    /* The cast to char * is because we need to write the initial value.
07239     * The field is not supposed to be modified otherwise.  Also, gcc 4.2
07240     * sees the cast as dereferencing a type-punned pointer and warns about
07241     * it.  This is the workaround (we're telling gcc, yes, that's really
07242     * what we wanted to do).
07243     */
07244    pattern = (char *) ignorepat->pattern;
07245    strcpy(pattern, value);
07246    ignorepat->next = NULL;
07247    ignorepat->registrar = registrar;
07248    ast_wrlock_context(con);
07249    for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) {
07250       ignorepatl = ignorepatc;
07251       if (!strcasecmp(ignorepatc->pattern, value)) {
07252          /* Already there */
07253          ast_unlock_context(con);
07254          errno = EEXIST;
07255          return -1;
07256       }
07257    }
07258    if (ignorepatl)
07259       ignorepatl->next = ignorepat;
07260    else
07261       con->ignorepats = ignorepat;
07262    ast_unlock_context(con);
07263    return 0;
07264 
07265 }

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

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

Referenced by handle_cli_dialplan_add_include().

06769 {
06770    int ret = -1;
06771    struct ast_context *c = find_context_locked(context);
06772 
06773    if (c) {
06774       ret = ast_context_add_include2(c, include, registrar);
06775       ast_unlock_contexts();
06776    }
06777    return ret;
06778 }

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

References ast_build_timing(), ast_calloc, ast_destroy_timing(), ast_free, ast_get_context_name(), ast_unlock_context(), ast_verb, ast_wrlock_context(), errno, ast_include::hastime, ast_context::includes, ast_include::name, ast_include::next, ast_include::registrar, ast_include::rname, ast_include::stuff, and ast_include::timing.

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

07034 {
07035    struct ast_include *new_include;
07036    char *c;
07037    struct ast_include *i, *il = NULL; /* include, include_last */
07038    int length;
07039    char *p;
07040 
07041    length = sizeof(struct ast_include);
07042    length += 2 * (strlen(value) + 1);
07043 
07044    /* allocate new include structure ... */
07045    if (!(new_include = ast_calloc(1, length)))
07046       return -1;
07047    /* Fill in this structure. Use 'p' for assignments, as the fields
07048     * in the structure are 'const char *'
07049     */
07050    p = new_include->stuff;
07051    new_include->name = p;
07052    strcpy(p, value);
07053    p += strlen(value) + 1;
07054    new_include->rname = p;
07055    strcpy(p, value);
07056    /* Strip off timing info, and process if it is there */
07057    if ( (c = strchr(p, ',')) ) {
07058       *c++ = '\0';
07059       new_include->hastime = ast_build_timing(&(new_include->timing), c);
07060    }
07061    new_include->next      = NULL;
07062    new_include->registrar = registrar;
07063 
07064    ast_wrlock_context(con);
07065 
07066    /* ... go to last include and check if context is already included too... */
07067    for (i = con->includes; i; i = i->next) {
07068       if (!strcasecmp(i->name, new_include->name)) {
07069          ast_destroy_timing(&(new_include->timing));
07070          ast_free(new_include);
07071          ast_unlock_context(con);
07072          errno = EEXIST;
07073          return -1;
07074       }
07075       il = i;
07076    }
07077 
07078    /* ... include new context into context list, unlock, return */
07079    if (il)
07080       il->next = new_include;
07081    else
07082       con->includes = new_include;
07083    ast_verb(3, "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con));
07084 
07085    ast_unlock_context(con);
07086 
07087    return 0;
07088 }

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

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

07096 {
07097    int ret = -1;
07098    struct ast_context *c = find_context_locked(context);
07099 
07100    if (c) { /* found, add switch to this context */
07101       ret = ast_context_add_switch2(c, sw, data, eval, registrar);
07102       ast_unlock_contexts();
07103    }
07104    return ret;
07105 }

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

References ast_context::alts, ast_calloc, ast_free, ast_get_context_name(), AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, ast_unlock_context(), ast_verb, ast_wrlock_context(), ast_sw::data, errno, ast_sw::eval, ast_sw::name, ast_sw::registrar, and ast_sw::stuff.

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

07116 {
07117    struct ast_sw *new_sw;
07118    struct ast_sw *i;
07119    int length;
07120    char *p;
07121 
07122    length = sizeof(struct ast_sw);
07123    length += strlen(value) + 1;
07124    if (data)
07125       length += strlen(data);
07126    length++;
07127 
07128    /* allocate new sw structure ... */
07129    if (!(new_sw = ast_calloc(1, length)))
07130       return -1;
07131    /* ... fill in this structure ... */
07132    p = new_sw->stuff;
07133    new_sw->name = p;
07134    strcpy(new_sw->name, value);
07135    p += strlen(value) + 1;
07136    new_sw->data = p;
07137    if (data) {
07138       strcpy(new_sw->data, data);
07139       p += strlen(data) + 1;
07140    } else {
07141       strcpy(new_sw->data, "");
07142       p++;
07143    }
07144    new_sw->eval     = eval;
07145    new_sw->registrar = registrar;
07146 
07147    /* ... try to lock this context ... */
07148    ast_wrlock_context(con);
07149 
07150    /* ... go to last sw and check if context is already swd too... */
07151    AST_LIST_TRAVERSE(&con->alts, i, list) {
07152       if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) {
07153          ast_free(new_sw);
07154          ast_unlock_context(con);
07155          errno = EEXIST;
07156          return -1;
07157       }
07158    }
07159 
07160    /* ... sw new context into context list, unlock, return */
07161    AST_LIST_INSERT_TAIL(&con->alts, new_sw, list);
07162 
07163    ast_verb(3, "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con));
07164 
07165    ast_unlock_context(con);
07166 
07167    return 0;
07168 }

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 8415 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  )  [read]

Find a context.

Parameters:
name name of the context to find

Will search for the context with the given name.

Returns:
the ast_context on success, NULL on failure.

Definition at line 2430 of file pbx.c.

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

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

02431 {
02432    struct ast_context *tmp = NULL;
02433    struct fake_context item;
02434 
02435    ast_copy_string(item.name, name, sizeof(item.name));
02436 
02437    ast_rdlock_contexts();
02438    if( contexts_table ) {
02439       tmp = ast_hashtab_lookup(contexts_table,&item);
02440    } else {
02441       while ( (tmp = ast_walk_contexts(tmp)) ) {
02442          if (!name || !strcasecmp(name, tmp->name)) {
02443             break;
02444          }
02445       }
02446    }
02447    ast_unlock_contexts();
02448    return tmp;
02449 }

struct ast_context* ast_context_find_or_create ( struct ast_context **  extcontexts,
struct ast_hashtab exttable,
const char *  name,
const char *  registrar 
) [read]

Register a new context or find an existing one.

Parameters:
extcontexts pointer to the ast_context structure pointer
exttable pointer to the hashtable that contains all the elements in extcontexts
name name of the new context
registrar registrar of the context

This function allows you to play in two environments: the global contexts (active dialplan) or an external context set of your choosing. To act on the external set, make sure extcontexts and exttable are set; for the globals, make sure both extcontexts and exttable are NULL.

This will first search for a context with your name. If it exists already, it will not create a new one. If it does not exist, it will create a new one with the given name and registrar.

Returns:
NULL on failure, and an ast_context structure on success

Definition at line 6424 of file pbx.c.

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

Referenced by ast_compile_ael2(), build_parkinglot(), config_parse_variables(), context_merge(), load_config(), load_module(), lua_register_switches(), manage_parkinglot(), park_call_full(), pbx_load_config(), pbx_load_users(), reload_config(), set_config(), sla_build_station(), and sla_build_trunk().

06425 {
06426    struct ast_context *tmp, **local_contexts;
06427    struct fake_context search;
06428    int length = sizeof(struct ast_context) + strlen(name) + 1;
06429 
06430    if (!contexts_table) {
06431       contexts_table = ast_hashtab_create(17,
06432                                  ast_hashtab_compare_contexts,
06433                                  ast_hashtab_resize_java,
06434                                  ast_hashtab_newsize_java,
06435                                  ast_hashtab_hash_contexts,
06436                                  0);
06437    }
06438 
06439    ast_copy_string(search.name, name, sizeof(search.name));
06440    if (!extcontexts) {
06441       ast_rdlock_contexts();
06442       local_contexts = &contexts;
06443       tmp = ast_hashtab_lookup(contexts_table, &search);
06444       ast_unlock_contexts();
06445       if (tmp) {
06446          tmp->refcount++;
06447          return tmp;
06448       }
06449    } else { /* local contexts just in a linked list; search there for the new context; slow, linear search, but not frequent */
06450       local_contexts = extcontexts;
06451       tmp = ast_hashtab_lookup(exttable, &search);
06452       if (tmp) {
06453          tmp->refcount++;
06454          return tmp;
06455       }
06456    }
06457 
06458    if ((tmp = ast_calloc(1, length))) {
06459       ast_rwlock_init(&tmp->lock);
06460       ast_mutex_init(&tmp->macrolock);
06461       strcpy(tmp->name, name);
06462       tmp->root = NULL;
06463       tmp->root_table = NULL;
06464       tmp->registrar = ast_strdup(registrar);
06465       tmp->includes = NULL;
06466       tmp->ignorepats = NULL;
06467       tmp->refcount = 1;
06468    } else {
06469       ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name);
06470       return NULL;
06471    }
06472 
06473    if (!extcontexts) {
06474       ast_wrlock_contexts();
06475       tmp->next = *local_contexts;
06476       *local_contexts = tmp;
06477       ast_hashtab_insert_safe(contexts_table, tmp); /*put this context into the tree */
06478       ast_unlock_contexts();
06479       ast_debug(1, "Registered context '%s'(%p) in table %p registrar: %s\n", tmp->name, tmp, contexts_table, registrar);
06480       ast_verb(3, "Registered extension context '%s' (%p) in table %p; registrar: %s\n", tmp->name, tmp, contexts_table, registrar);
06481    } else {
06482       tmp->next = *local_contexts;
06483       if (exttable)
06484          ast_hashtab_insert_immediate(exttable, tmp); /*put this context into the tree */
06485 
06486       *local_contexts = tmp;
06487       ast_debug(1, "Registered context '%s'(%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar);
06488       ast_verb(3, "Registered extension context '%s' (%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar);
06489    }
06490    return tmp;
06491 }

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

04989 {
04990    struct ast_context *c = NULL;
04991    int ret = -1;
04992    struct fake_context item;
04993 
04994    ast_rdlock_contexts();
04995 
04996    ast_copy_string(item.name, context, sizeof(item.name));
04997 
04998    c = ast_hashtab_lookup(contexts_table,&item);
04999    if (c)
05000       ret = 0;
05001 
05002 
05003 #ifdef NOTNOW
05004 
05005    while ((c = ast_walk_contexts(c))) {
05006       if (!strcmp(ast_get_context_name(c), context)) {
05007          ret = 0;
05008          break;
05009       }
05010    }
05011 
05012 #endif
05013    ast_unlock_contexts();
05014 
05015    /* if we found context, lock macrolock */
05016    if (ret == 0) {
05017       ret = ast_mutex_lock(&c->macrolock);
05018    }
05019 
05020    return ret;
05021 }

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

References ast_context_remove_extension_callerid().

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

04797 {
04798    return ast_context_remove_extension_callerid(context, extension, priority, NULL, 0, registrar);
04799 }

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

References ast_context_remove_extension_callerid2().

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

04824 {
04825    return ast_context_remove_extension_callerid2(con, extension, priority, NULL, 0, registrar, already_locked);
04826 }

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

04802 {
04803    int ret = -1; /* default error return */
04804    struct ast_context *c = find_context_locked(context);
04805 
04806    if (c) { /* ... remove extension ... */
04807       ret = ast_context_remove_extension_callerid2(c, extension, priority, callerid, matchcallerid, registrar, 1);
04808       ast_unlock_contexts();
04809    }
04810    return ret;
04811 }

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

References add_exten_to_pattern_tree(), ast_copy_string(), ast_hashtab_insert_immediate(), ast_hashtab_lookup(), ast_hashtab_remove_this_object(), ast_hashtab_size(), ast_log(), ast_strlen_zero(), ast_unlock_context(), ast_verb, ast_wrlock_context(), ast_exten::cidmatch, match_char::deleted, destroy_exten(), match_char::exten, ast_exten::exten, ast_exten::label, LOG_ERROR, log_match_char_tree(), LOG_NOTICE, LOG_WARNING, ast_exten::matchcid, ast_context::name, ast_exten::next, ast_context::pattern_tree, ast_exten::peer, ast_exten::peer_label_table, ast_exten::peer_table, ast_exten::priority, ast_exten::registrar, ast_context::root, ast_context::root_table, and match_char::x.

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

04829 {
04830    struct ast_exten *exten, *prev_exten = NULL;
04831    struct ast_exten *peer;
04832    struct ast_exten ex, *exten2, *exten3;
04833    char dummy_name[1024];
04834    struct ast_exten *previous_peer = NULL;
04835    struct ast_exten *next_peer = NULL;
04836    int found = 0;
04837 
04838    if (!already_locked)
04839       ast_wrlock_context(con);
04840 
04841    /* Handle this is in the new world */
04842 
04843    /* FIXME For backwards compatibility, if callerid==NULL, then remove ALL
04844     * peers, not just those matching the callerid. */
04845 #ifdef NEED_DEBUG
04846    ast_verb(3,"Removing %s/%s/%d%s%s from trees, registrar=%s\n", con->name, extension, priority, matchcallerid ? "/" : "", matchcallerid ? callerid : "", registrar);
04847 #endif
04848 #ifdef CONTEXT_DEBUG
04849    check_contexts(__FILE__, __LINE__);
04850 #endif
04851    /* find this particular extension */
04852    ex.exten = dummy_name;
04853    ex.matchcid = matchcallerid && !ast_strlen_zero(callerid); /* don't say match if there's no callerid */
04854    ex.cidmatch = callerid;
04855    ast_copy_string(dummy_name, extension, sizeof(dummy_name));
04856    exten = ast_hashtab_lookup(con->root_table, &ex);
04857    if (exten) {
04858       if (priority == 0) {
04859          exten2 = ast_hashtab_remove_this_object(con->root_table, exten);
04860          if (!exten2)
04861             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);
04862          if (con->pattern_tree) {
04863             struct match_char *x = add_exten_to_pattern_tree(con, exten, 1);
04864 
04865             if (x->exten) { /* this test for safety purposes */
04866                x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */
04867                x->exten = 0; /* get rid of what will become a bad pointer */
04868             } else {
04869                ast_log(LOG_WARNING,"Trying to delete an exten from a context, but the pattern tree node returned isn't a full extension\n");
04870             }
04871          }
04872       } else {
04873          ex.priority = priority;
04874          exten2 = ast_hashtab_lookup(exten->peer_table, &ex);
04875          if (exten2) {
04876 
04877             if (exten2->label) { /* if this exten has a label, remove that, too */
04878                exten3 = ast_hashtab_remove_this_object(exten->peer_label_table,exten2);
04879                if (!exten3)
04880                   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);
04881             }
04882 
04883             exten3 = ast_hashtab_remove_this_object(exten->peer_table, exten2);
04884             if (!exten3)
04885                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);
04886             if (exten2 == exten && exten2->peer) {
04887                exten2 = ast_hashtab_remove_this_object(con->root_table, exten);
04888                ast_hashtab_insert_immediate(con->root_table, exten2->peer);
04889             }
04890             if (ast_hashtab_size(exten->peer_table) == 0) {
04891                /* well, if the last priority of an exten is to be removed,
04892                   then, the extension is removed, too! */
04893                exten3 = ast_hashtab_remove_this_object(con->root_table, exten);
04894                if (!exten3)
04895                   ast_log(LOG_ERROR,"Did not remove this exten (%s) from the context root_table (%s) (priority %d)\n", exten->exten, con->name, priority);
04896                if (con->pattern_tree) {
04897                   struct match_char *x = add_exten_to_pattern_tree(con, exten, 1);
04898                   if (x->exten) { /* this test for safety purposes */
04899                      x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */
04900                      x->exten = 0; /* get rid of what will become a bad pointer */
04901                   }
04902                }
04903             }
04904          } else {
04905             ast_log(LOG_ERROR,"Could not find priority %d of exten %s in context %s!\n",
04906                   priority, exten->exten, con->name);
04907          }
04908       }
04909    } else {
04910       /* hmmm? this exten is not in this pattern tree? */
04911       ast_log(LOG_WARNING,"Cannot find extension %s in root_table in context %s\n",
04912             extension, con->name);
04913    }
04914 #ifdef NEED_DEBUG
04915    if (con->pattern_tree) {
04916       ast_log(LOG_NOTICE,"match char tree after exten removal:\n");
04917       log_match_char_tree(con->pattern_tree, " ");
04918    }
04919 #endif
04920 
04921    /* scan the extension list to find first matching extension-registrar */
04922    for (exten = con->root; exten; prev_exten = exten, exten = exten->next) {
04923       if (!strcmp(exten->exten, extension) &&
04924          (!registrar || !strcmp(exten->registrar, registrar)) &&
04925          (!matchcallerid || (!ast_strlen_zero(callerid) && !ast_strlen_zero(exten->cidmatch) && !strcmp(exten->cidmatch, callerid)) || (ast_strlen_zero(callerid) && ast_strlen_zero(exten->cidmatch))))
04926          break;
04927    }
04928    if (!exten) {
04929       /* we can't find right extension */
04930       if (!already_locked)
04931          ast_unlock_context(con);
04932       return -1;
04933    }
04934 
04935    /* scan the priority list to remove extension with exten->priority == priority */
04936    for (peer = exten, next_peer = exten->peer ? exten->peer : exten->next;
04937        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)));
04938          peer = next_peer, next_peer = next_peer ? (next_peer->peer ? next_peer->peer : next_peer->next) : NULL) {
04939       if ((priority == 0 || peer->priority == priority) &&
04940             (!callerid || !matchcallerid || (matchcallerid && !strcmp(peer->cidmatch, callerid))) &&
04941             (!registrar || !strcmp(peer->registrar, registrar) )) {
04942          found = 1;
04943 
04944          /* we are first priority extension? */
04945          if (!previous_peer) {
04946             /*
04947              * We are first in the priority chain, so must update the extension chain.
04948              * The next node is either the next priority or the next extension
04949              */
04950             struct ast_exten *next_node = peer->peer ? peer->peer : peer->next;
04951             if (peer->peer) {
04952                /* move the peer_table and peer_label_table down to the next peer, if
04953                   it is there */
04954                peer->peer->peer_table = peer->peer_table;
04955                peer->peer->peer_label_table = peer->peer_label_table;
04956                peer->peer_table = NULL;
04957                peer->peer_label_table = NULL;
04958             }
04959             if (!prev_exten) {   /* change the root... */
04960                con->root = next_node;
04961             } else {
04962                prev_exten->next = next_node; /* unlink */
04963             }
04964             if (peer->peer)   { /* update the new head of the pri list */
04965                peer->peer->next = peer->next;
04966             }
04967          } else { /* easy, we are not first priority in extension */
04968             previous_peer->peer = peer->peer;
04969          }
04970 
04971          /* now, free whole priority extension */
04972          destroy_exten(peer);
04973       } else {
04974          previous_peer = peer;
04975       }
04976    }
04977    if (!already_locked)
04978       ast_unlock_context(con);
04979    return found ? 0 : -1;
04980 }

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

Definition at line 7174 of file pbx.c.

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

Referenced by handle_cli_dialplan_remove_ignorepat().

07175 {
07176    int ret = -1;
07177    struct ast_context *c = find_context_locked(context);
07178 
07179    if (c) {
07180       ret = ast_context_remove_ignorepat2(c, ignorepat, registrar);
07181       ast_unlock_contexts();
07182    }
07183    return ret;
07184 }

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

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

07187 {
07188    struct ast_ignorepat *ip, *ipl = NULL;
07189 
07190    ast_wrlock_context(con);
07191 
07192    for (ip = con->ignorepats; ip; ip = ip->next) {
07193       if (!strcmp(ip->pattern, ignorepat) &&
07194          (!registrar || (registrar == ip->registrar))) {
07195          if (ipl) {
07196             ipl->next = ip->next;
07197             ast_free(ip);
07198          } else {
07199             con->ignorepats = ip->next;
07200             ast_free(ip);
07201          }
07202          ast_unlock_context(con);
07203          return 0;
07204       }
07205       ipl = ip;
07206    }
07207 
07208    ast_unlock_context(con);
07209    errno = EINVAL;
07210    return -1;
07211 }

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

Remove included contexts. This function locks contexts list by &conlist, search for the right context structure, leave context list locked and call ast_context_remove_include2 which removes include, unlock contexts list and return ...

Remove a context include.

Definition at line 4687 of file pbx.c.

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

Referenced by handle_cli_dialplan_remove_include().

04688 {
04689    int ret = -1;
04690    struct ast_context *c = find_context_locked(context);
04691 
04692    if (c) {
04693       /* found, remove include from this context ... */
04694       ret = ast_context_remove_include2(c, include, registrar);
04695       ast_unlock_contexts();
04696    }
04697    return ret;
04698 }

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

Locks context, remove included contexts, unlocks context. When we call this function, &conlock lock must be locked, because when we giving *con argument, some process can remove/change this context and after that there can be segfault.

Removes an include by an ast_context structure.

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

Definition at line 4709 of file pbx.c.

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

Referenced by ast_context_remove_include().

04710 {
04711    struct ast_include *i, *pi = NULL;
04712    int ret = -1;
04713 
04714    ast_wrlock_context(con);
04715 
04716    /* find our include */
04717    for (i = con->includes; i; pi = i, i = i->next) {
04718       if (!strcmp(i->name, include) &&
04719             (!registrar || !strcmp(i->registrar, registrar))) {
04720          /* remove from list */
04721          ast_verb(3, "Removing inclusion of context '%s' in context '%s; registrar=%s'\n", include, ast_get_context_name(con), registrar);
04722          if (pi)
04723             pi->next = i->next;
04724          else
04725             con->includes = i->next;
04726          /* free include and return */
04727          ast_destroy_timing(&(i->timing));
04728          ast_free(i);
04729          ret = 0;
04730          break;
04731       }
04732    }
04733 
04734    ast_unlock_context(con);
04735 
04736    return ret;
04737 }

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

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

04745 {
04746    int ret = -1; /* default error return */
04747    struct ast_context *c = find_context_locked(context);
04748 
04749    if (c) {
04750       /* remove switch from this context ... */
04751       ret = ast_context_remove_switch2(c, sw, data, registrar);
04752       ast_unlock_contexts();
04753    }
04754    return ret;
04755 }

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

References ast_context::alts, ast_free, ast_get_context_name(), AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_unlock_context(), ast_verb, ast_wrlock_context(), ast_sw::data, ast_sw::name, and ast_sw::registrar.

Referenced by ast_context_remove_switch().

04766 {
04767    struct ast_sw *i;
04768    int ret = -1;
04769 
04770    ast_wrlock_context(con);
04771 
04772    /* walk switches */
04773    AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) {
04774       if (!strcmp(i->name, sw) && !strcmp(i->data, data) &&
04775          (!registrar || !strcmp(i->registrar, registrar))) {
04776          /* found, remove from list */
04777          ast_verb(3, "Removing switch '%s' from context '%s; registrar=%s'\n", sw, ast_get_context_name(con), registrar);
04778          AST_LIST_REMOVE_CURRENT(list);
04779          ast_free(i); /* free switch and return */
04780          ret = 0;
04781          break;
04782       }
04783    }
04784    AST_LIST_TRAVERSE_SAFE_END;
04785 
04786    ast_unlock_context(con);
04787 
04788    return ret;
04789 }

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

05029 {
05030    struct ast_context *c = NULL;
05031    int ret = -1;
05032    struct fake_context item;
05033 
05034    ast_rdlock_contexts();
05035 
05036    ast_copy_string(item.name, context, sizeof(item.name));
05037 
05038    c = ast_hashtab_lookup(contexts_table,&item);
05039    if (c)
05040       ret = 0;
05041 #ifdef NOTNOW
05042 
05043    while ((c = ast_walk_contexts(c))) {
05044       if (!strcmp(ast_get_context_name(c), context)) {
05045          ret = 0;
05046          break;
05047       }
05048    }
05049 
05050 #endif
05051    ast_unlock_contexts();
05052 
05053    /* if we found context, unlock macrolock */
05054    if (ret == 0) {
05055       ret = ast_mutex_unlock(&c->macrolock);
05056    }
05057 
05058    return ret;
05059 }

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

09533 {
09534    struct ast_include *inc = NULL;
09535    int res = 0;
09536 
09537    while ( (inc = ast_walk_context_includes(con, inc)) ) {
09538       if (ast_context_find(inc->rname))
09539          continue;
09540 
09541       res = -1;
09542       ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n",
09543          ast_get_context_name(con), inc->rname);
09544       break;
09545    }
09546 
09547    return res;
09548 }

struct ast_custom_function* ast_custom_function_find ( const char *  name  )  [read]
int ast_custom_function_unregister ( struct ast_custom_function acf  ) 

Unregister a custom function.

Definition at line 3216 of file pbx.c.

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

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

03217 {
03218    struct ast_custom_function *cur;
03219 
03220    if (!acf) {
03221       return -1;
03222    }
03223 
03224    AST_RWLIST_WRLOCK(&acf_root);
03225    if ((cur = AST_RWLIST_REMOVE(&acf_root, acf, acflist))) {
03226       if (cur->docsrc == AST_XML_DOC) {
03227          ast_string_field_free_memory(acf);
03228       }
03229       ast_verb(2, "Unregistered custom function %s\n", cur->name);
03230    }
03231    AST_RWLIST_UNLOCK(&acf_root);
03232 
03233    return cur ? 0 : -1;
03234 }

int ast_destroy_timing ( struct ast_timing i  ) 

Deallocates memory structures associated with a timing bitmap.

Parameters:
i Pointer to an ast_timing structure.
Return values:
0 success
non-zero failure (number suitable to pass to
See also:
strerror)

Definition at line 7017 of file pbx.c.

References ast_free, and ast_timing::timezone.

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

07018 {
07019    if (i->timezone) {
07020       ast_free(i->timezone);
07021       i->timezone = NULL;
07022    }
07023    return 0;
07024 }

enum ast_extension_states ast_devstate_to_extenstate ( enum ast_device_state  devstate  ) 

Map devstate to an extension state.

Parameters:
[in] device state
Returns:
the extension state mapping.

Definition at line 3770 of file pbx.c.

References AST_DEVICE_BUSY, AST_DEVICE_INUSE, AST_DEVICE_INVALID, AST_DEVICE_NOT_INUSE, AST_DEVICE_ONHOLD, AST_DEVICE_RINGING, AST_DEVICE_RINGINUSE, AST_DEVICE_TOTAL, AST_DEVICE_UNAVAILABLE, AST_DEVICE_UNKNOWN, AST_EXTENSION_BUSY, AST_EXTENSION_INUSE, AST_EXTENSION_NOT_INUSE, AST_EXTENSION_ONHOLD, AST_EXTENSION_RINGING, and AST_EXTENSION_UNAVAILABLE.

Referenced by ast_extension_state2().

03771 {
03772    switch (devstate) {
03773    case AST_DEVICE_ONHOLD:
03774       return AST_EXTENSION_ONHOLD;
03775    case AST_DEVICE_BUSY:
03776       return AST_EXTENSION_BUSY;
03777    case AST_DEVICE_UNAVAILABLE:
03778    case AST_DEVICE_UNKNOWN:
03779    case AST_DEVICE_INVALID:
03780       return AST_EXTENSION_UNAVAILABLE;
03781    case AST_DEVICE_RINGINUSE:
03782       return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING);
03783    case AST_DEVICE_RINGING:
03784       return AST_EXTENSION_RINGING;
03785    case AST_DEVICE_INUSE:
03786       return AST_EXTENSION_INUSE;
03787    case AST_DEVICE_NOT_INUSE:
03788       return AST_EXTENSION_NOT_INUSE;
03789    case AST_DEVICE_TOTAL: /* not a device state, included for completeness */
03790       break;
03791    }
03792 
03793    return AST_EXTENSION_NOT_INUSE;
03794 }

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 4143 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(), sip_read(), skinny_ss(), socket_process(), ss7_linkset(), ss_thread(), and waitstream_core().

04144 {
04145    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0);
04146 }

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

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

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

07322 {
07323    if (!chan)
07324       return -1;
07325 
07326    ast_channel_lock(chan);
07327 
07328    if (!ast_strlen_zero(context))
07329       ast_copy_string(chan->context, context, sizeof(chan->context));
07330    if (!ast_strlen_zero(exten))
07331       ast_copy_string(chan->exten, exten, sizeof(chan->exten));
07332    if (priority > -1) {
07333       chan->priority = priority;
07334       /* see flag description in channel.h for explanation */
07335       if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP))
07336          chan->priority--;
07337    }
07338 
07339    ast_channel_unlock(chan);
07340 
07341    return 0;
07342 }

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

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

02408 {
02409    if (needmore != E_MATCHMORE && needmore != E_CANMATCH)
02410       ast_log(LOG_WARNING, "invalid argument %d\n", needmore);
02411    return extension_match_core(pattern, data, needmore);
02412 }

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

References ext_cmp().

Referenced by lua_extension_cmp().

02210 {
02211    return ext_cmp(a, b);
02212 }

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

02403 {
02404    return extension_match_core(pattern, data, E_MATCH);
02405 }

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

Check extension state for an extension by using hint.

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

Definition at line 3832 of file pbx.c.

References ast_extension_state2(), and ast_hint_extension().

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

03833 {
03834    struct ast_exten *e;
03835 
03836    if (!(e = ast_hint_extension(c, context, exten))) {  /* Do we have a hint for this extension ? */
03837       return -1;                   /* No hint, return -1 */
03838    }
03839 
03840    return ast_extension_state2(e);  /* Check all devices in the hint */
03841 }

static int ast_extension_state2 ( struct ast_exten e  )  [static]

Check state of extension by using hints.

Definition at line 3797 of file pbx.c.

References ast_devstate_aggregate_add(), ast_devstate_aggregate_init(), ast_devstate_aggregate_result(), ast_devstate_to_extenstate(), ast_get_extension_app(), ast_str_buffer(), ast_str_set(), ast_str_thread_get(), and extensionstate_buf.

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

03798 {
03799    struct ast_str *hint = ast_str_thread_get(&extensionstate_buf, 16);
03800    char *cur, *rest;
03801    struct ast_devstate_aggregate agg;
03802 
03803    if (!e)
03804       return -1;
03805 
03806    ast_devstate_aggregate_init(&agg);
03807 
03808    ast_str_set(&hint, 0, "%s", ast_get_extension_app(e));
03809 
03810    rest = ast_str_buffer(hint);  /* One or more devices separated with a & character */
03811 
03812    while ( (cur = strsep(&rest, "&")) ) {
03813       ast_devstate_aggregate_add(&agg, ast_device_state(cur));
03814    }
03815 
03816    return ast_devstate_to_extenstate(ast_devstate_aggregate_result(&agg));
03817 }

const char* ast_extension_state2str ( int  extension_state  ) 

Return extension_state as string.

Return string representation of the state of an extension.

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

03821 {
03822    int i;
03823 
03824    for (i = 0; (i < ARRAY_LEN(extension_states)); i++) {
03825       if (extension_states[i].extension_state == extension_state)
03826          return extension_states[i].text;
03827    }
03828    return "Unknown";
03829 }

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

Add watcher for extension states.

Registers a state change callback.

Definition at line 3896 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_exten::data, ast_state_cb::data, ast_hint::exten, ast_exten::exten, ast_state_cb::id, ast_exten::label, ast_exten::matchcid, ast_context::name, ast_exten::parent, ast_exten::priority, ast_exten::registrar, and stateid.

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

03898 {
03899    struct ast_hint *hint;
03900    struct ast_state_cb *cblist;
03901    struct ast_exten *e;
03902 
03903    /* If there's no context and extension:  add callback to statecbs list */
03904    if (!context && !exten) {
03905       AST_RWLIST_WRLOCK(&hints);
03906 
03907       AST_LIST_TRAVERSE(&statecbs, cblist, entry) {
03908          if (cblist->callback == callback) {
03909             cblist->data = data;
03910             AST_RWLIST_UNLOCK(&hints);
03911             return 0;
03912          }
03913       }
03914 
03915       /* Now insert the callback */
03916       if (!(cblist = ast_calloc(1, sizeof(*cblist)))) {
03917          AST_RWLIST_UNLOCK(&hints);
03918          return -1;
03919       }
03920       cblist->id = 0;
03921       cblist->callback = callback;
03922       cblist->data = data;
03923 
03924       AST_LIST_INSERT_HEAD(&statecbs, cblist, entry);
03925 
03926       AST_RWLIST_UNLOCK(&hints);
03927 
03928       return 0;
03929    }
03930 
03931    if (!context || !exten)
03932       return -1;
03933 
03934    /* This callback type is for only one hint, so get the hint */
03935    e = ast_hint_extension(NULL, context, exten);
03936    if (!e) {
03937       return -1;
03938    }
03939 
03940    /* If this is a pattern, dynamically create a new extension for this
03941     * particular match.  Note that this will only happen once for each
03942     * individual extension, because the pattern will no longer match first.
03943     */
03944    if (e->exten[0] == '_') {
03945       ast_add_extension(e->parent->name, 0, exten, e->priority, e->label,
03946          e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr,
03947          e->registrar);
03948       e = ast_hint_extension(NULL, context, exten);
03949       if (!e || e->exten[0] == '_') {
03950          return -1;
03951       }
03952    }
03953 
03954    /* Find the hint in the list of hints */
03955    AST_RWLIST_WRLOCK(&hints);
03956 
03957    AST_RWLIST_TRAVERSE(&hints, hint, list) {
03958       if (hint->exten == e)
03959          break;
03960    }
03961 
03962    if (!hint) {
03963       /* We have no hint, sorry */
03964       AST_RWLIST_UNLOCK(&hints);
03965       return -1;
03966    }
03967 
03968    /* Now insert the callback in the callback list  */
03969    if (!(cblist = ast_calloc(1, sizeof(*cblist)))) {
03970       AST_RWLIST_UNLOCK(&hints);
03971       return -1;
03972    }
03973 
03974    cblist->id = stateid++;    /* Unique ID for this callback */
03975    cblist->callback = callback;  /* Pointer to callback routine */
03976    cblist->data = data;    /* Data for the callback */
03977 
03978    AST_LIST_INSERT_HEAD(&hint->callbacks, cblist, entry);
03979 
03980    AST_RWLIST_UNLOCK(&hints);
03981 
03982    return cblist->id;
03983 }

int ast_extension_state_del ( int  id,
ast_state_cb_type  callback 
)

Remove a watcher from the callback list.

Deletes a registered state change callback by ID.

Definition at line 3986 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, and ast_state_cb::id.

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

03987 {
03988    struct ast_state_cb *p_cur = NULL;
03989    int ret = -1;
03990 
03991    if (!id && !callback)
03992       return -1;
03993 
03994    AST_RWLIST_WRLOCK(&hints);
03995 
03996    if (!id) {  /* id == 0 is a callback without extension */
03997       AST_LIST_TRAVERSE_SAFE_BEGIN(&statecbs, p_cur, entry) {
03998          if (p_cur->callback == callback) {
03999             AST_LIST_REMOVE_CURRENT(entry);
04000             break;
04001          }
04002       }
04003       AST_LIST_TRAVERSE_SAFE_END;
04004    } else { /* callback with extension, find the callback based on ID */
04005       struct ast_hint *hint;
04006       AST_RWLIST_TRAVERSE(&hints, hint, list) {
04007          AST_LIST_TRAVERSE_SAFE_BEGIN(&hint->callbacks, p_cur, entry) {
04008             if (p_cur->id == id) {
04009                AST_LIST_REMOVE_CURRENT(entry);
04010                break;
04011             }
04012          }
04013          AST_LIST_TRAVERSE_SAFE_END;
04014 
04015          if (p_cur)
04016             break;
04017       }
04018    }
04019 
04020    if (p_cur) {
04021       ast_free(p_cur);
04022    }
04023 
04024    AST_RWLIST_UNLOCK(&hints);
04025 
04026    return ret;
04027 }

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

04149 {
04150    return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
04151 }

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

References E_FINDLABEL, and pbx_extension_helper().

Referenced by pbx_load_config().

04154 {
04155    return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
04156 }

int ast_func_read ( struct ast_channel chan,
const char *  function,
char *  workspace,
size_t  len 
)

executes a read operation on a function

Parameters:
chan Channel to execute on
function Data containing the function call string (will be modified)
workspace A pointer to safe memory to use for a return value
len the number of bytes in workspace

This application executes a function in read mode on a given channel.

Return values:
0 success
non-zero failure

Definition at line 3356 of file pbx.c.

References __ast_module_user_add(), __ast_module_user_remove(), ast_custom_function_find(), ast_log(), 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().

03357 {
03358    char *copy = ast_strdupa(function);
03359    char *args = func_args(copy);
03360    struct ast_custom_function *acfptr = ast_custom_function_find(copy);
03361 
03362    if (acfptr == NULL)
03363       ast_log(LOG_ERROR, "Function %s not registered\n", copy);
03364    else if (!acfptr->read)
03365       ast_log(LOG_ERROR, "Function %s cannot be read\n", copy);
03366    else {
03367       int res;
03368       struct ast_module_user *u = NULL;
03369       if (acfptr->mod)
03370          u = __ast_module_user_add(acfptr->mod, chan);
03371       res = acfptr->read(chan, copy, args, workspace, len);
03372       if (acfptr->mod && u)
03373          __ast_module_user_remove(acfptr->mod, u);
03374       return res;
03375    }
03376    return -1;
03377 }

int ast_func_write ( struct ast_channel chan,
const char *  function,
const char *  value 
)

executes a write operation on a function

Parameters:
chan Channel to execute on
function Data containing the function call string (will be modified)
value A value parameter to pass for writing

This application executes a function in write mode on a given channel.

Return values:
0 success
non-zero failure

Definition at line 3379 of file pbx.c.

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

Referenced by action_setvar(), pbx_builtin_pushvar_helper(), and pbx_builtin_setvar_helper().

03380 {
03381    char *copy = ast_strdupa(function);
03382    char *args = func_args(copy);
03383    struct ast_custom_function *acfptr = ast_custom_function_find(copy);
03384 
03385    if (acfptr == NULL)
03386       ast_log(LOG_ERROR, "Function %s not registered\n", copy);
03387    else if (!acfptr->write)
03388       ast_log(LOG_ERROR, "Function %s cannot be written to\n", copy);
03389    else {
03390       int res;
03391       struct ast_module_user *u = NULL;
03392       if (acfptr->mod)
03393          u = __ast_module_user_add(acfptr->mod, chan);
03394       res = acfptr->write(chan, copy, args, value);
03395       if (acfptr->mod && u)
03396          __ast_module_user_remove(acfptr->mod, u);
03397       return res;
03398    }
03399 
03400    return -1;
03401 }

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

Definition at line 9422 of file pbx.c.

References ast_context::registrar.

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

09423 {
09424    return c ? c->registrar : NULL;
09425 }

const char* ast_get_extension_app ( struct ast_exten e  ) 
void* ast_get_extension_app_data ( struct ast_exten e  ) 

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

09458 {
09459    return e ? e->data : NULL;
09460 }

const char* ast_get_extension_cidmatch ( struct ast_exten e  ) 

Definition at line 9447 of file pbx.c.

References ast_exten::cidmatch.

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

09448 {
09449    return e ? e->cidmatch : NULL;
09450 }

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

Definition at line 9389 of file pbx.c.

References ast_exten::parent.

Referenced by handle_show_hint(), and handle_show_hints().

09390 {
09391    return exten ? exten->parent : NULL;
09392 }

const char* ast_get_extension_label ( struct ast_exten exten  ) 

Definition at line 9399 of file pbx.c.

References ast_exten::label.

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

09400 {
09401    return exten ? exten->label : NULL;
09402 }

int ast_get_extension_matchcid ( struct ast_exten e  ) 

Definition at line 9442 of file pbx.c.

References ast_exten::matchcid.

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

09443 {
09444    return e ? e->matchcid : 0;
09445 }

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

Definition at line 9414 of file pbx.c.

References ast_exten::priority.

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

09415 {
09416    return exten ? exten->priority : -1;
09417 }

const char* ast_get_extension_registrar ( struct ast_exten e  ) 

Definition at line 9427 of file pbx.c.

References ast_exten::registrar.

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

09428 {
09429    return e ? e->registrar : NULL;
09430 }

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

Get hint for channel.

If an extension hint exists, return non-zero.

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

04127 {
04128    struct ast_exten *e = ast_hint_extension(c, context, exten);
04129 
04130    if (e) {
04131       if (hint)
04132          ast_copy_string(hint, ast_get_extension_app(e), hintsize);
04133       if (name) {
04134          const char *tmp = ast_get_extension_app_data(e);
04135          if (tmp)
04136             ast_copy_string(name, tmp, namesize);
04137       }
04138       return -1;
04139    }
04140    return 0;
04141 }

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

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

09438 {
09439    return ip ? ip->registrar : NULL;
09440 }

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

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

09433 {
09434    return i ? i->registrar : NULL;
09435 }

const char* ast_get_switch_data ( struct ast_sw sw  ) 

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

09468 {
09469    return sw ? sw->data : NULL;
09470 }

int ast_get_switch_eval ( struct ast_sw sw  ) 

Definition at line 9472 of file pbx.c.

References ast_sw::eval.

Referenced by context_merge_incls_swits_igps_other_registrars().

09473 {
09474    return sw->eval;
09475 }

const char* ast_get_switch_name ( struct ast_sw sw  ) 

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

09463 {
09464    return sw ? sw->name : NULL;
09465 }

const char* ast_get_switch_registrar ( struct ast_sw sw  ) 

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

09478 {
09479    return sw ? sw->registrar : NULL;
09480 }

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

References __ast_goto_if_exists().

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

09571 {
09572    return __ast_goto_if_exists(chan, context, exten, priority, 0);
09573 }

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

hashtable functions for contexts

Definition at line 994 of file pbx.c.

References ast_context::name.

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

00995 {
00996    const struct ast_context *ac = ah_a;
00997    const struct ast_context *bc = ah_b;
00998    if (!ac || !bc) /* safety valve, but it might prevent a crash you'd rather have happen */
00999       return 1;
01000    /* assume context names are registered in a string table! */
01001    return strcmp(ac->name, bc->name);
01002 }

unsigned int ast_hashtab_hash_contexts ( const void *  obj  ) 

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

01038 {
01039    const struct ast_context *ac = obj;
01040    return ast_hashtab_hash_string(ac->name);
01041 }

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

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

03762 {
03763    struct ast_exten *e;
03764    ast_rdlock_contexts();
03765    e = ast_hint_extension_nolock(c, context, exten);
03766    ast_unlock_contexts();
03767    return e;
03768 }

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

Find hint for given extension in context.

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

03756 {
03757    struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */
03758    return pbx_find_extension(c, NULL, &q, context, exten, PRIORITY_HINT, NULL, "", E_MATCH);
03759 }

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

07268 {
07269    struct ast_context *con = ast_context_find(context);
07270    if (con) {
07271       struct ast_ignorepat *pat;
07272       for (pat = con->ignorepats; pat; pat = pat->next) {
07273          if (ast_extension_match(pat->pattern, pattern))
07274             return 1;
07275       }
07276    }
07277 
07278    return 0;
07279 }

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

References E_MATCHMORE, and pbx_extension_helper().

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

04164 {
04165    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0);
04166 }

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

References __ast_internal_context_destroy(), ast_exten::app, ast_add_extension_nolock(), ast_calloc, AST_EXTENSION_REMOVED, ast_free, ast_free_ptr(), ast_hashtab_destroy(), ast_hashtab_end_traversal(), ast_hashtab_next(), ast_hashtab_start_traversal(), ast_hint_extension_nolock(), AST_LIST_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, ast_exten::data, E_MATCH, ast_exten::exten, ast_hint::exten, ast_hint::laststate, LOG_WARNING, ast_context::name, ast_context::next, ast_sw::next, ast_exten::parent, pbx_find_extension(), PRIORITY_HINT, ast_exten::registrar, and pbx_find_info::stacklen.

Referenced by lua_reload_extensions(), and pbx_load_module().

06624 {
06625    double ft;
06626    struct ast_context *tmp, *oldcontextslist;
06627    struct ast_hashtab *oldtable;
06628    struct store_hints store = AST_LIST_HEAD_INIT_VALUE;
06629    struct store_hint *this;
06630    struct ast_hint *hint;
06631    struct ast_exten *exten;
06632    int length;
06633    struct ast_state_cb *thiscb;
06634    struct ast_hashtab_iter *iter;
06635 
06636    /* it is very important that this function hold the hint list lock _and_ the conlock
06637       during its operation; not only do we need to ensure that the list of contexts
06638       and extensions does not change, but also that no hint callbacks (watchers) are
06639       added or removed during the merge/delete process
06640 
06641       in addition, the locks _must_ be taken in this order, because there are already
06642       other code paths that use this order
06643    */
06644 
06645    struct timeval begintime, writelocktime, endlocktime, enddeltime;
06646    int wrlock_ver;
06647 
06648    begintime = ast_tvnow();
06649    ast_rdlock_contexts();
06650    iter = ast_hashtab_start_traversal(contexts_table);
06651    while ((tmp = ast_hashtab_next(iter))) {
06652       context_merge(extcontexts, exttable, tmp, registrar);
06653    }
06654    ast_hashtab_end_traversal(iter);
06655    wrlock_ver = ast_wrlock_contexts_version();
06656 
06657    ast_unlock_contexts(); /* this feels real retarded, but you must do
06658                        what you must do If this isn't done, the following 
06659                         wrlock is a guraranteed deadlock */
06660    ast_wrlock_contexts();
06661    if (ast_wrlock_contexts_version() > wrlock_ver+1) {
06662       ast_log(LOG_WARNING,"==================!!!!!!!!!!!!!!!Something changed the contexts in the middle of merging contexts!\n");
06663    }
06664 
06665    AST_RWLIST_WRLOCK(&hints);
06666    writelocktime = ast_tvnow();
06667 
06668    /* preserve all watchers for hints */
06669    AST_RWLIST_TRAVERSE(&hints, hint, list) {
06670       if (!AST_LIST_EMPTY(&hint->callbacks)) {
06671          length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2 + sizeof(*this);
06672          if (!(this = ast_calloc(1, length)))
06673             continue;
06674          /* this removes all the callbacks from the hint into this. */
06675          AST_LIST_APPEND_LIST(&this->callbacks, &hint->callbacks, entry);
06676          this->laststate = hint->laststate;
06677          this->context = this->data;
06678          strcpy(this->data, hint->exten->parent->name);
06679          this->exten = this->data + strlen(this->context) + 1;
06680          strcpy(this->exten, hint->exten->exten);
06681          AST_LIST_INSERT_HEAD(&store, this, list);
06682       }
06683    }
06684 
06685    /* save the old table and list */
06686    oldtable = contexts_table;
06687    oldcontextslist = contexts;
06688 
06689    /* move in the new table and list */
06690    contexts_table = exttable;
06691    contexts = *extcontexts;
06692 
06693    /* restore the watchers for hints that can be found; notify those that
06694       cannot be restored
06695    */
06696    while ((this = AST_LIST_REMOVE_HEAD(&store, list))) {
06697       struct pbx_find_info q = { .stacklen = 0 };
06698       exten = pbx_find_extension(NULL, NULL, &q, this->context, this->exten, PRIORITY_HINT, NULL, "", E_MATCH);
06699       /* If this is a pattern, dynamically create a new extension for this
06700        * particular match.  Note that this will only happen once for each
06701        * individual extension, because the pattern will no longer match first.
06702        */
06703       if (exten && exten->exten[0] == '_') {
06704          ast_add_extension_nolock(exten->parent->name, 0, this->exten, PRIORITY_HINT, NULL,
06705             0, exten->app, ast_strdup(exten->data), ast_free_ptr, exten->registrar);
06706          /* rwlocks are not recursive locks */
06707          exten = ast_hint_extension_nolock(NULL, this->context, this->exten);
06708       }
06709 
06710       /* Find the hint in the list of hints */
06711       AST_RWLIST_TRAVERSE(&hints, hint, list) {
06712          if (hint->exten == exten)
06713             break;
06714       }
06715       if (!exten || !hint) {
06716          /* this hint has been removed, notify the watchers */
06717          while ((thiscb = AST_LIST_REMOVE_HEAD(&this->callbacks, entry))) {
06718             thiscb->callback(this->context, this->exten, AST_EXTENSION_REMOVED, thiscb->data);
06719             ast_free(thiscb);
06720          }
06721       } else {
06722          AST_LIST_APPEND_LIST(&hint->callbacks, &this->callbacks, entry);
06723          hint->laststate = this->laststate;
06724       }
06725       ast_free(this);
06726    }
06727 
06728    AST_RWLIST_UNLOCK(&hints);
06729    ast_unlock_contexts();
06730    endlocktime = ast_tvnow();
06731 
06732    /* the old list and hashtab no longer are relevant, delete them while the rest of asterisk
06733       is now freely using the new stuff instead */
06734 
06735    ast_hashtab_destroy(oldtable, NULL);
06736 
06737    for (tmp = oldcontextslist; tmp; ) {
06738       struct ast_context *next;  /* next starting point */
06739       next = tmp->next;
06740       __ast_internal_context_destroy(tmp);
06741       tmp = next;
06742    }
06743    enddeltime = ast_tvnow();
06744 
06745    ft = ast_tvdiff_us(writelocktime, begintime);
06746    ft /= 1000000.0;
06747    ast_verb(3,"Time to scan old dialplan and merge leftovers back into the new: %8.6f sec\n", ft);
06748 
06749    ft = ast_tvdiff_us(endlocktime, writelocktime);
06750    ft /= 1000000.0;
06751    ast_verb(3,"Time to restore hints and swap in new dialplan: %8.6f sec\n", ft);
06752 
06753    ft = ast_tvdiff_us(enddeltime, endlocktime);
06754    ft /= 1000000.0;
06755    ast_verb(3,"Time to delete the old dialplan: %8.6f sec\n", ft);
06756 
06757    ft = ast_tvdiff_us(enddeltime, begintime);
06758    ft /= 1000000.0;
06759    ast_verb(3,"Total time merge_contexts_delete: %8.6f sec\n", ft);
06760    return;
06761 }

int ast_parseable_goto ( struct ast_channel chan,
const char *  goto_string 
)
Note:
This function will handle locking the channel as needed.

Definition at line 9633 of file pbx.c.

References pbx_parseable_goto().

Referenced by _while_exec(), check_goto_on_transfer(), dial_exec_full(), gosub_exec(), ivr_dispatch(), parkandannounce_exec(), pbx_builtin_goto(), and while_continue_exec().

09634 {
09635    return pbx_parseable_goto(chan, goto_string, 0);
09636 }

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

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

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

08107 {
08108    struct ast_channel *chan;
08109    struct app_tmp *tmp;
08110    int res = -1, cdr_res = -1;
08111    struct outgoing_helper oh;
08112 
08113    memset(&oh, 0, sizeof(oh));
08114    oh.vars = vars;
08115    oh.account = account;
08116 
08117    if (locked_channel)
08118       *locked_channel = NULL;
08119    if (ast_strlen_zero(app)) {
08120       res = -1;
08121       goto outgoing_app_cleanup;
08122    }
08123    if (synchronous) {
08124       chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
08125       if (chan) {
08126          ast_set_variables(chan, vars);
08127          if (account)
08128             ast_cdr_setaccount(chan, account);
08129          if (chan->_state == AST_STATE_UP) {
08130             res = 0;
08131             ast_verb(4, "Channel %s was answered.\n", chan->name);
08132             tmp = ast_calloc(1, sizeof(*tmp));
08133             if (!tmp)
08134                res = -1;
08135             else {
08136                ast_copy_string(tmp->app, app, sizeof(tmp->app));
08137                if (appdata)
08138                   ast_copy_string(tmp->data, appdata, sizeof(tmp->data));
08139                tmp->chan = chan;
08140                if (synchronous > 1) {
08141                   if (locked_channel)
08142                      ast_channel_unlock(chan);
08143                   ast_pbx_run_app(tmp);
08144                } else {
08145                   if (locked_channel)
08146                      ast_channel_lock(chan);
08147                   if (ast_pthread_create_detached(&tmp->t, NULL, ast_pbx_run_app, tmp)) {
08148                      ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno));
08149                      ast_free(tmp);
08150                      if (locked_channel)
08151                         ast_channel_unlock(chan);
08152                      ast_hangup(chan);
08153                      res = -1;
08154                   } else {
08155                      if (locked_channel)
08156                         *locked_channel = chan;
08157                   }
08158                }
08159             }
08160          } else {
08161             ast_verb(4, "Channel %s was never answered.\n", chan->name);
08162             if (chan->cdr) { /* update the cdr */
08163                /* here we update the status of the call, which sould be busy.
08164                 * if that fails then we set the status to failed */
08165                if (ast_cdr_disposition(chan->cdr, chan->hangupcause))
08166                   ast_cdr_failed(chan->cdr);
08167             }
08168             ast_hangup(chan);
08169          }
08170       }
08171 
08172       if (res < 0) { /* the call failed for some reason */
08173          if (*reason == 0) { /* if the call failed (not busy or no answer)
08174                         * update the cdr with the failed message */
08175             cdr_res = ast_pbx_outgoing_cdr_failed();
08176             if (cdr_res != 0) {
08177                res = cdr_res;
08178                goto outgoing_app_cleanup;
08179             }
08180          }
08181       }
08182 
08183    } else {
08184       struct async_stat *as;
08185       if (!(as = ast_calloc(1, sizeof(*as)))) {
08186          res = -1;
08187          goto outgoing_app_cleanup;
08188       }
08189       chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
08190       if (!chan) {
08191          ast_free(as);
08192          res = -1;
08193          goto outgoing_app_cleanup;
08194       }
08195       as->chan = chan;
08196       ast_copy_string(as->app, app, sizeof(as->app));
08197       if (appdata)
08198          ast_copy_string(as->appdata,  appdata, sizeof(as->appdata));
08199       as->timeout = timeout;
08200       ast_set_variables(chan, vars);
08201       if (account)
08202          ast_cdr_setaccount(chan, account);
08203       /* Start a new thread, and get something handling this channel. */
08204       if (locked_channel)
08205          ast_channel_lock(chan);
08206       if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) {
08207          ast_log(LOG_WARNING, "Failed to start async wait\n");
08208          ast_free(as);
08209          if (locked_channel)
08210             ast_channel_unlock(chan);
08211          ast_hangup(chan);
08212          res = -1;
08213          goto outgoing_app_cleanup;
08214       } else {
08215          if (locked_channel)
08216             *locked_channel = chan;
08217       }
08218       res = 0;
08219    }
08220 outgoing_app_cleanup:
08221    ast_variables_destroy(vars);
08222    return res;
08223 }

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 7914 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, and ast_channel::cdr.

Referenced by ast_pbx_outgoing_app(), and ast_pbx_outgoing_exten().

07915 {
07916    /* allocate a channel */
07917    struct ast_channel *chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "%s", "");
07918 
07919    if (!chan)
07920       return -1;  /* failure */
07921 
07922    if (!chan->cdr) {
07923       /* allocation of the cdr failed */
07924       ast_channel_free(chan);   /* free the channel */
07925       return -1;                /* return failure */
07926    }
07927 
07928    /* allocation of the cdr was successful */
07929    ast_cdr_init(chan->cdr, chan);  /* initialize our channel's cdr */
07930    ast_cdr_start(chan->cdr);       /* record the start and stop time */
07931    ast_cdr_end(chan->cdr);
07932    ast_cdr_failed(chan->cdr);      /* set the status to failed */
07933    ast_cdr_detach(chan->cdr);      /* post and free the record */
07934    chan->cdr = NULL;
07935    ast_channel_free(chan);         /* free the channel */
07936 
07937    return 0;  /* success */
07938 }

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

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

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

07941 {
07942    struct ast_channel *chan;
07943    struct async_stat *as;
07944    int res = -1, cdr_res = -1;
07945    struct outgoing_helper oh;
07946 
07947    if (synchronous) {
07948       oh.context = context;
07949       oh.exten = exten;
07950       oh.priority = priority;
07951       oh.cid_num = cid_num;
07952       oh.cid_name = cid_name;
07953       oh.account = account;
07954       oh.vars = vars;
07955       oh.parent_channel = NULL;
07956 
07957       chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
07958       if (channel) {
07959          *channel = chan;
07960          if (chan)
07961             ast_channel_lock(chan);
07962       }
07963       if (chan) {
07964          if (chan->_state == AST_STATE_UP) {
07965                res = 0;
07966             ast_verb(4, "Channel %s was answered.\n", chan->name);
07967 
07968             if (synchronous > 1) {
07969                if (channel)
07970                   ast_channel_unlock(chan);
07971                if (ast_pbx_run(chan)) {
07972                   ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name);
07973                   if (channel)
07974                      *channel = NULL;
07975                   ast_hangup(chan);
07976                   chan = NULL;
07977                   res = -1;
07978                }
07979             } else {
07980                if (ast_pbx_start(chan)) {
07981                   ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name);
07982                   if (channel) {
07983                      *channel = NULL;
07984                      ast_channel_unlock(chan);
07985                   }
07986                   ast_hangup(chan);
07987                   res = -1;
07988                }
07989                chan = NULL;
07990             }
07991          } else {
07992             ast_verb(4, "Channel %s was never answered.\n", chan->name);
07993 
07994             if (chan->cdr) { /* update the cdr */
07995                /* here we update the status of the call, which sould be busy.
07996                 * if that fails then we set the status to failed */
07997                if (ast_cdr_disposition(chan->cdr, chan->hangupcause))
07998                   ast_cdr_failed(chan->cdr);
07999             }
08000 
08001             if (channel) {
08002                *channel = NULL;
08003                ast_channel_unlock(chan);
08004             }
08005             ast_hangup(chan);
08006             chan = NULL;
08007          }
08008       }
08009 
08010       if (res < 0) { /* the call failed for some reason */
08011          if (*reason == 0) { /* if the call failed (not busy or no answer)
08012                         * update the cdr with the failed message */
08013             cdr_res = ast_pbx_outgoing_cdr_failed();
08014             if (cdr_res != 0) {
08015                res = cdr_res;
08016                goto outgoing_exten_cleanup;
08017             }
08018          }
08019 
08020          /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */
08021          /* check if "failed" exists */
08022          if (ast_exists_extension(chan, context, "failed", 1, NULL)) {
08023             chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "OutgoingSpoolFailed");
08024             if (chan) {
08025                char failed_reason[4] = "";
08026                if (!ast_strlen_zero(context))
08027                   ast_copy_string(chan->context, context, sizeof(chan->context));
08028                set_ext_pri(chan, "failed", 1);
08029                ast_set_variables(chan, vars);
08030                snprintf(failed_reason, sizeof(failed_reason), "%d", *reason);
08031                pbx_builtin_setvar_helper(chan, "REASON", failed_reason);
08032                if (account)
08033                   ast_cdr_setaccount(chan, account);
08034                if (ast_pbx_run(chan)) {
08035                   ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name);
08036                   ast_hangup(chan);
08037                }
08038                chan = NULL;
08039             }
08040          }
08041       }
08042    } else {
08043       if (!(as = ast_calloc(1, sizeof(*as)))) {
08044          res = -1;
08045          goto outgoing_exten_cleanup;
08046       }
08047       chan = ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name);
08048       if (channel) {
08049          *channel = chan;
08050          if (chan)
08051             ast_channel_lock(chan);
08052       }
08053       if (!chan) {
08054          ast_free(as);
08055          res = -1;
08056          goto outgoing_exten_cleanup;
08057       }
08058       as->chan = chan;
08059       ast_copy_string(as->context, context, sizeof(as->context));
08060       set_ext_pri(as->chan,  exten, priority);
08061       as->timeout = timeout;
08062       ast_set_variables(chan, vars);
08063       if (account)
08064          ast_cdr_setaccount(chan, account);
08065       if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) {
08066          ast_log(LOG_WARNING, "Failed to start async wait\n");
08067          ast_free(as);
08068          if (channel) {
08069             *channel = NULL;
08070             ast_channel_unlock(chan);
08071          }
08072          ast_hangup(chan);
08073          res = -1;
08074          goto outgoing_exten_cleanup;
08075       }
08076       res = 0;
08077    }
08078 outgoing_exten_cleanup:
08079    ast_variables_destroy(vars);
08080    return res;
08081 }

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

04597 {
04598    return ast_pbx_run_args(c, NULL);
04599 }

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

run the application and free the descriptor once done

Definition at line 8091 of file pbx.c.

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

08092 {
08093    struct app_tmp *tmp = data;
08094    struct ast_app *app;
08095    app = pbx_findapp(tmp->app);
08096    if (app) {
08097       ast_verb(4, "Launching %s(%s) on %s\n", tmp->app, tmp->data, tmp->chan->name);
08098       pbx_exec(tmp->chan, app, tmp->data);
08099    } else
08100       ast_log(LOG_WARNING, "No such application '%s'\n", tmp->app);
08101    ast_hangup(tmp->chan);
08102    ast_free(tmp);
08103    return NULL;
08104 }

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

04582 {
04583    enum ast_pbx_result res = AST_PBX_SUCCESS;
04584 
04585    if (increase_call_count(c)) {
04586       return AST_PBX_CALL_LIMIT;
04587    }
04588 
04589    res = __ast_pbx_run(c, args);
04590 
04591    decrease_call_count();
04592 
04593    return res;
04594 }

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 4559 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_iax2_new(), ast_pbx_outgoing_exten(), bridge_call_thread(), 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(), pri_dchannel(), rpt_call(), sip_new(), skinny_new(), unistim_new(), and usbradio_new().

04560 {
04561    pthread_t t;
04562 
04563    if (!c) {
04564       ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
04565       return AST_PBX_FAILED;
04566    }
04567 
04568    if (increase_call_count(c))
04569       return AST_PBX_CALL_LIMIT;
04570 
04571    /* Start a new thread, and get something handling this channel. */
04572    if (ast_pthread_create_detached(&t, NULL, pbx_thread, c)) {
04573       ast_log(LOG_WARNING, "Failed to create new channel thread\n");
04574       decrease_call_count();
04575       return AST_PBX_FAILED;
04576    }
04577 
04578    return AST_PBX_SUCCESS;
04579 }

int ast_processed_calls ( void   ) 

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

Definition at line 4606 of file pbx.c.

References totalcalls.

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

04607 {
04608    return totalcalls;
04609 }

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

09372 {
09373    return ast_rwlock_rdlock(&con->lock);
09374 }

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

Dynamically register a new dial plan application.

Register an application.

Definition at line 5062 of file pbx.c.

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

Referenced by ast_features_init(), and load_pbx().

05063 {
05064    struct ast_app *tmp, *cur = NULL;
05065    char tmps[80];
05066    int length, res;
05067 #ifdef AST_XML_DOCS
05068    char *tmpxml;
05069 #endif
05070 
05071    AST_RWLIST_WRLOCK(&apps);
05072    AST_RWLIST_TRAVERSE(&apps, tmp, list) {
05073       if (!(res = strcasecmp(app, tmp->name))) {
05074          ast_log(LOG_WARNING, "Already have an application '%s'\n", app);
05075          AST_RWLIST_UNLOCK(&apps);
05076          return -1;
05077       } else if (res < 0)
05078          break;
05079    }
05080 
05081    length = sizeof(*tmp) + strlen(app) + 1;
05082 
05083    if (!(tmp = ast_calloc(1, length))) {
05084       AST_RWLIST_UNLOCK(&apps);
05085       return -1;
05086    }
05087 
05088    if (ast_string_field_init(tmp, 128)) {
05089       AST_RWLIST_UNLOCK(&apps);
05090       ast_free(tmp);
05091       return -1;
05092    }
05093 
05094 #ifdef AST_XML_DOCS
05095    /* Try to lookup the docs in our XML documentation database */
05096    if (ast_strlen_zero(synopsis) && ast_strlen_zero(description)) {
05097       /* load synopsis */
05098       tmpxml = ast_xmldoc_build_synopsis("application", app);
05099       ast_string_field_set(tmp, synopsis, tmpxml);
05100       ast_free(tmpxml);
05101 
05102       /* load description */
05103       tmpxml = ast_xmldoc_build_description("application", app);
05104       ast_string_field_set(tmp, description, tmpxml);
05105       ast_free(tmpxml);
05106 
05107       /* load syntax */
05108       tmpxml = ast_xmldoc_build_syntax("application", app);
05109       ast_string_field_set(tmp, syntax, tmpxml);
05110       ast_free(tmpxml);
05111 
05112       /* load arguments */
05113       tmpxml = ast_xmldoc_build_arguments("application", app);
05114       ast_string_field_set(tmp, arguments, tmpxml);
05115       ast_free(tmpxml);
05116 
05117       /* load seealso */
05118       tmpxml = ast_xmldoc_build_seealso("application", app);
05119       ast_string_field_set(tmp, seealso, tmpxml);
05120       ast_free(tmpxml);
05121       tmp->docsrc = AST_XML_DOC;
05122    } else {
05123 #endif
05124       ast_string_field_set(tmp, synopsis, synopsis);
05125       ast_string_field_set(tmp, description, description);
05126       tmp->docsrc = AST_STATIC_DOC;
05127 #ifdef AST_XML_DOCS
05128    }
05129 #endif
05130 
05131    strcpy(tmp->name, app);
05132    tmp->execute = execute;
05133    tmp->module = mod;
05134 
05135    /* Store in alphabetical order */
05136    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, cur, list) {
05137       if (strcasecmp(tmp->name, cur->name) < 0) {
05138          AST_RWLIST_INSERT_BEFORE_CURRENT(tmp, list);
05139          break;
05140       }
05141    }
05142    AST_RWLIST_TRAVERSE_SAFE_END;
05143    if (!cur)
05144       AST_RWLIST_INSERT_TAIL(&apps, tmp, list);
05145 
05146    ast_verb(2, "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps)));
05147 
05148    AST_RWLIST_UNLOCK(&apps);
05149 
05150    return 0;
05151 }

int ast_register_switch ( struct ast_switch sw  ) 

Register an alternative dialplan switch.

Parameters:
sw switch to register

This function registers a populated ast_switch structure with the asterisk switching architecture.

Return values:
0 success
non-zero failure

Definition at line 5157 of file pbx.c.

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

Referenced by load_module().

05158 {
05159    struct ast_switch *tmp;
05160 
05161    AST_RWLIST_WRLOCK(&switches);
05162    AST_RWLIST_TRAVERSE(&switches, tmp, list) {
05163       if (!strcasecmp(tmp->name, sw->name)) {
05164          AST_RWLIST_UNLOCK(&switches);
05165          ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name);
05166          return -1;
05167       }
05168    }
05169    AST_RWLIST_INSERT_TAIL(&switches, sw, list);
05170    AST_RWLIST_UNLOCK(&switches);
05171 
05172    return 0;
05173 }

static int ast_remove_hint ( struct ast_exten e  )  [static]

Remove hint from extension.

Definition at line 4091 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_exten::exten, ast_hint::exten, ast_context::name, and ast_exten::parent.

Referenced by destroy_exten().

04092 {
04093    /* Cleanup the Notifys if hint is removed */
04094    struct ast_hint *hint;
04095    struct ast_state_cb *cblist;
04096    int res = -1;
04097 
04098    if (!e)
04099       return -1;
04100 
04101    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&hints, hint, list) {
04102       if (hint->exten != e)
04103          continue;
04104 
04105       while ((cblist = AST_LIST_REMOVE_HEAD(&hint->callbacks, entry))) {
04106          /* Notify with -1 and remove all callbacks */
04107          cblist->callback(hint->exten->parent->name, hint->exten->exten,
04108             AST_EXTENSION_DEACTIVATED, cblist->data);
04109          ast_free(cblist);
04110       }
04111 
04112       AST_RWLIST_REMOVE_CURRENT(list);
04113       ast_free(hint);
04114 
04115       res = 0;
04116 
04117       break;
04118    }
04119    AST_RWLIST_TRAVERSE_SAFE_END;
04120 
04121    return res;
04122 }

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

04169 {
04170    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN, found, combined_find_spawn);
04171 }

int ast_unlock_context ( struct ast_context con  ) 
int ast_unlock_contexts ( void   ) 
int ast_unregister_application ( const char *  app  ) 

Unregister an application.

Parameters:
app name of the application (does not have to be the same string as the one that was registered)

This unregisters an application from Asterisk's internal application list.

Return values:
0 success
-1 failure

Definition at line 6403 of file pbx.c.

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

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

06404 {
06405    struct ast_app *tmp;
06406 
06407    AST_RWLIST_WRLOCK(&apps);
06408    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, tmp, list) {
06409       if (!strcasecmp(app, tmp->name)) {
06410          unreference_cached_app(tmp);
06411          AST_RWLIST_REMOVE_CURRENT(list);
06412          ast_verb(2, "Unregistered application '%s'\n", tmp->name);
06413          ast_string_field_free_memory(tmp);
06414          ast_free(tmp);
06415          break;
06416       }
06417    }
06418    AST_RWLIST_TRAVERSE_SAFE_END;
06419    AST_RWLIST_UNLOCK(&apps);
06420 
06421    return tmp ? 0 : -1;
06422 }

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

References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

Referenced by __unload_module(), and unload_module().

05176 {
05177    AST_RWLIST_WRLOCK(&switches);
05178    AST_RWLIST_REMOVE(&switches, sw, list);
05179    AST_RWLIST_UNLOCK(&switches);
05180 }

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

Definition at line 9490 of file pbx.c.

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

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

09492 {
09493    if (!exten)
09494       return con ? con->root : NULL;
09495    else
09496       return exten->next;
09497 }

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

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

09525 {
09526    if (!ip)
09527       return con ? con->ignorepats : NULL;
09528    else
09529       return ip->next;
09530 }

struct ast_include* ast_walk_context_includes ( struct ast_context con,
struct ast_include inc 
) [read]
struct ast_sw* ast_walk_context_switches ( struct ast_context con,
struct ast_sw sw 
) [read]

Definition at line 9499 of file pbx.c.

References ast_context::alts, AST_LIST_FIRST, and AST_LIST_NEXT.

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

09501 {
09502    if (!sw)
09503       return con ? AST_LIST_FIRST(&con->alts) : NULL;
09504    else
09505       return AST_LIST_NEXT(sw, list);
09506 }

struct ast_context* ast_walk_contexts ( struct ast_context con  )  [read]
struct ast_exten* ast_walk_extension_priorities ( struct ast_exten exten,
struct ast_exten priority 
) [read]
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 9366 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().

09367 {
09368    return ast_rwlock_wrlock(&con->lock);
09369 }

int ast_wrlock_contexts ( void   ) 

Write locks the context list.

Return values:
0 on success
-1 on error

Definition at line 9345 of file pbx.c.

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

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

09346 {
09347    int res = ast_rwlock_wrlock(&conlock);
09348    if (!res)
09349       ast_atomic_fetchadd_int(&conlock_wrlock_version, 1);
09350    return res;
09351 }

int ast_wrlock_contexts_version ( void   ) 

Definition at line 9337 of file pbx.c.

References conlock_wrlock_version.

Referenced by ast_merge_contexts_and_delete().

09338 {
09339    return conlock_wrlock_version;
09340 }

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

Definition at line 7853 of file pbx.c.

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

Referenced by ast_pbx_outgoing_app(), and ast_pbx_outgoing_exten().

07854 {
07855    struct async_stat *as = data;
07856    struct ast_channel *chan = as->chan;
07857    int timeout = as->timeout;
07858    int res;
07859    struct ast_frame *f;
07860    struct ast_app *app;
07861 
07862    while (timeout && (chan->_state != AST_STATE_UP)) {
07863       res = ast_waitfor(chan, timeout);
07864       if (res < 1)
07865          break;
07866       if (timeout > -1)
07867          timeout = res;
07868       f = ast_read(chan);
07869       if (!f)
07870          break;
07871       if (f->frametype == AST_FRAME_CONTROL) {
07872          if ((f->subclass == AST_CONTROL_BUSY)  ||
07873              (f->subclass == AST_CONTROL_CONGESTION) ) {
07874             ast_frfree(f);
07875             break;
07876          }
07877       }
07878       ast_frfree(f);
07879    }
07880    if (chan->_state == AST_STATE_UP) {
07881       if (!ast_strlen_zero(as->app)) {
07882          app = pbx_findapp(as->app);
07883          if (app) {
07884             ast_verb(3, "Launching %s(%s) on %s\n", as->app, as->appdata, chan->name);
07885             pbx_exec(chan, app, as->appdata);
07886          } else
07887             ast_log(LOG_WARNING, "No such application '%s'\n", as->app);
07888       } else {
07889          if (!ast_strlen_zero(as->context))
07890             ast_copy_string(chan->context, as->context, sizeof(chan->context));
07891          if (!ast_strlen_zero(as->exten))
07892             ast_copy_string(chan->exten, as->exten, sizeof(chan->exten));
07893          if (as->priority > 0)
07894             chan->priority = as->priority;
07895          /* Run the PBX */
07896          if (ast_pbx_run(chan)) {
07897             ast_log(LOG_ERROR, "Failed to start PBX on %s\n", chan->name);
07898          } else {
07899             /* PBX will have taken care of this */
07900             chan = NULL;
07901          }
07902       }
07903    }
07904    ast_free(as);
07905    if (chan)
07906       ast_hangup(chan);
07907    return NULL;
07908 }

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

Definition at line 1523 of file pbx.c.

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

Referenced by show_debug_helper().

01524 {
01525    char extenstr[40];
01526    struct ast_str *my_prefix = ast_str_alloca(1024);
01527 
01528    extenstr[0] = '\0';
01529 
01530    if (node && node->exten && node->exten)
01531       snprintf(extenstr, sizeof(extenstr), "(%p)", node->exten);
01532 
01533    if (strlen(node->x) > 1) {
01534       ast_cli(fd, "%s[%s]:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N',
01535          node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "",
01536          node->exten ? node->exten->exten : "", extenstr);
01537    } else {
01538       ast_cli(fd, "%s%s:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N',
01539          node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "",
01540          node->exten ? node->exten->exten : "", extenstr);
01541    }
01542 
01543    ast_str_set(&my_prefix, 0, "%s+       ", prefix);
01544 
01545    if (node->next_char)
01546       cli_match_char_tree(node->next_char, ast_str_buffer(my_prefix), fd);
01547 
01548    if (node->alt_char)
01549       cli_match_char_tree(node->alt_char, prefix, fd);
01550 }

static int collect_digits ( struct ast_channel c,
int  waittime,
char *  buf,
int  buflen,
int  pos 
) [static]

collect digits from the channel into the buffer.

Parameters:
waittime is in milliseconds
Return values:
0 on timeout or done.
-1 on error.

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

Referenced by __ast_pbx_run().

04189 {
04190    int digit;
04191 
04192    buf[pos] = '\0';  /* make sure it is properly terminated */
04193    while (ast_matchmore_extension(c, c->context, buf, 1, c->cid.cid_num)) {
04194       /* As long as we're willing to wait, and as long as it's not defined,
04195          keep reading digits until we can't possibly get a right answer anymore.  */
04196       digit = ast_waitfordigit(c, waittime);
04197       if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
04198          c->_softhangup = 0;
04199       } else {
04200          if (!digit) /* No entry */
04201             break;
04202          if (digit < 0) /* Error, maybe a  hangup */
04203             return -1;
04204          if (pos < buflen - 1) { /* XXX maybe error otherwise ? */
04205             buf[pos++] = digit;
04206             buf[pos] = '\0';
04207          }
04208          waittime = c->pbx->dtimeoutms;
04209       }
04210    }
04211    return 0;
04212 }

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

Definition at line 981 of file pbx.c.

Referenced by add_exten_to_pattern_tree().

00982 {
00983    const char *ac = a;
00984    const char *bc = b;
00985    if ((*ac) < (*bc))
00986       return -1;
00987    else if ((*ac) == (*bc))
00988       return 0;
00989    else
00990       return 1;
00991 }

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

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

Referenced by handle_show_hint().

05372 {
05373    struct ast_hint *hint;
05374    char *ret = NULL;
05375    int which = 0;
05376    int wordlen;
05377 
05378    if (pos != 3)
05379       return NULL;
05380 
05381    wordlen = strlen(word);
05382 
05383    AST_RWLIST_RDLOCK(&hints);
05384    /* walk through all hints */
05385    AST_RWLIST_TRAVERSE(&hints, hint, list) {
05386       if (!strncasecmp(word, ast_get_extension_name(hint->exten), wordlen) && ++which > state) {
05387          ret = ast_strdup(ast_get_extension_name(hint->exten));
05388          break;
05389       }
05390    }
05391    AST_RWLIST_UNLOCK(&hints);
05392 
05393    return ret;
05394 }

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

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

05569 {
05570    struct ast_context *c = NULL;
05571    char *ret = NULL;
05572    int which = 0;
05573    int wordlen;
05574 
05575    /* we are do completion of [exten@]context on second position only */
05576    if (pos != 2)
05577       return NULL;
05578 
05579    ast_rdlock_contexts();
05580 
05581    wordlen = strlen(word);
05582 
05583    /* walk through all contexts and return the n-th match */
05584    while ( (c = ast_walk_contexts(c)) ) {
05585       if (!strncasecmp(word, ast_get_context_name(c), wordlen) && ++which > state) {
05586          ret = ast_strdup(ast_get_context_name(c));
05587          break;
05588       }
05589    }
05590 
05591    ast_unlock_contexts();
05592 
05593    return ret;
05594 }

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

Definition at line 6539 of file pbx.c.

References ast_exten::app, ast_add_extension2(), ast_context_find_or_create(), ast_hashtab_end_traversal(), ast_hashtab_lookup(), ast_hashtab_next(), ast_hashtab_start_traversal(), ast_log(), ast_strdup, ast_verb, ast_exten::cidmatch, context_merge_incls_swits_igps_other_registrars(), ast_exten::data, ast_exten::datad, ast_exten::exten, first, ast_exten::label, LOG_ERROR, ast_exten::matchcid, ast_context::name, ast_exten::peer_table, ast_exten::priority, ast_context::refcount, ast_context::registrar, ast_exten::registrar, and ast_context::root_table.

Referenced by ast_merge_contexts_and_delete().

06540 {
06541    struct ast_context *new = ast_hashtab_lookup(exttable, context); /* is there a match in the new set? */
06542    struct ast_exten *exten_item, *prio_item, *new_exten_item, *new_prio_item;
06543    struct ast_hashtab_iter *exten_iter;
06544    struct ast_hashtab_iter *prio_iter;
06545    int insert_count = 0;
06546    int first = 1;
06547 
06548    /* We'll traverse all the extensions/prios, and see which are not registrar'd with
06549       the current registrar, and copy them to the new context. If the new context does not
06550       exist, we'll create it "on demand". If no items are in this context to copy, then we'll
06551       only create the empty matching context if the old one meets the criteria */
06552 
06553    if (context->root_table) {
06554       exten_iter = ast_hashtab_start_traversal(context->root_table);
06555       while ((exten_item=ast_hashtab_next(exten_iter))) {
06556          if (new) {
06557             new_exten_item = ast_hashtab_lookup(new->root_table, exten_item);
06558          } else {
06559             new_exten_item = NULL;
06560          }
06561          prio_iter = ast_hashtab_start_traversal(exten_item->peer_table);
06562          while ((prio_item=ast_hashtab_next(prio_iter))) {
06563             int res1;
06564             char *dupdstr;
06565 
06566             if (new_exten_item) {
06567                new_prio_item = ast_hashtab_lookup(new_exten_item->peer_table, prio_item);
06568             } else {
06569                new_prio_item = NULL;
06570             }
06571             if (strcmp(prio_item->registrar,registrar) == 0) {
06572                continue;
06573             }
06574             /* make sure the new context exists, so we have somewhere to stick this exten/prio */
06575             if (!new) {
06576                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 */
06577             }
06578 
06579             /* copy in the includes, switches, and ignorepats */
06580             if (first) { /* but, only need to do this once */
06581                context_merge_incls_swits_igps_other_registrars(new, context, registrar);
06582                first = 0;
06583             }
06584 
06585             if (!new) {
06586                ast_log(LOG_ERROR,"Could not allocate a new context for %s in merge_and_delete! Danger!\n", context->name);
06587                return; /* no sense continuing. */
06588             }
06589             /* we will not replace existing entries in the new context with stuff from the old context.
06590                but, if this is because of some sort of registrar conflict, we ought to say something... */
06591 
06592             dupdstr = ast_strdup(prio_item->data);
06593 
06594             res1 = ast_add_extension2(new, 0, prio_item->exten, prio_item->priority, prio_item->label, 
06595                                 prio_item->matchcid ? prio_item->cidmatch : NULL, prio_item->app, dupdstr, prio_item->datad, prio_item->registrar);
06596             if (!res1 && new_exten_item && new_prio_item){
06597                ast_verb(3,"Dropping old dialplan item %s/%s/%d [%s(%s)] (registrar=%s) due to conflict with new dialplan\n",
06598                      context->name, prio_item->exten, prio_item->priority, prio_item->app, (char*)prio_item->data, prio_item->registrar);
06599             } else {
06600                /* 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,
06601                 and no double frees take place, either! */
06602                insert_count++;
06603             }
06604          }
06605          ast_hashtab_end_traversal(prio_iter);
06606       }
06607       ast_hashtab_end_traversal(exten_iter);
06608    }
06609 
06610    if (!insert_count && !new && (strcmp(context->registrar, registrar) != 0 ||
06611         (strcmp(context->registrar, registrar) == 0 && context->refcount > 1))) {
06612       /* we could have given it the registrar of the other module who incremented the refcount,
06613          but that's not available, so we give it the registrar we know about */
06614       new = ast_context_find_or_create(extcontexts, exttable, context->name, context->registrar);
06615 
06616       /* copy in the includes, switches, and ignorepats */
06617       context_merge_incls_swits_igps_other_registrars(new, context, registrar);
06618    }
06619 }

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

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

06507 {
06508    struct ast_include *i;
06509    struct ast_ignorepat *ip;
06510    struct ast_sw *sw;
06511 
06512    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);
06513    /* copy in the includes, switches, and ignorepats */
06514    /* walk through includes */
06515    for (i = NULL; (i = ast_walk_context_includes(old, i)) ; ) {
06516       if (strcmp(ast_get_include_registrar(i), registrar) == 0)
06517          continue; /* not mine */
06518       ast_context_add_include2(new, ast_get_include_name(i), ast_get_include_registrar(i));
06519    }
06520 
06521    /* walk through switches */
06522    for (sw = NULL; (sw = ast_walk_context_switches(old, sw)) ; ) {
06523       if (strcmp(ast_get_switch_registrar(sw), registrar) == 0)
06524          continue; /* not mine */
06525       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));
06526    }
06527 
06528    /* walk thru ignorepats ... */
06529    for (ip = NULL; (ip = ast_walk_context_ignorepats(old, ip)); ) {
06530       if (strcmp(ast_get_ignorepat_registrar(ip), registrar) == 0)
06531          continue; /* not mine */
06532       ast_context_add_ignorepat2(new, ast_get_ignorepat_name(ip), ast_get_ignorepat_registrar(ip));
06533    }
06534 }

static void create_match_char_tree ( struct ast_context con  )  [static]

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

02001 {
02002    struct ast_hashtab_iter *t1;
02003    struct ast_exten *e1;
02004 #ifdef NEED_DEBUG
02005    int biggest_bucket, resizes, numobjs, numbucks;
02006 
02007    ast_log(LOG_DEBUG,"Creating Extension Trie for context %s\n", con->name);
02008    ast_hashtab_get_stats(con->root_table, &biggest_bucket, &resizes, &numobjs, &numbucks);
02009    ast_log(LOG_DEBUG,"This tree has %d objects in %d bucket lists, longest list=%d objects, and has resized %d times\n",
02010          numobjs, numbucks, biggest_bucket, resizes);
02011 #endif
02012    t1 = ast_hashtab_start_traversal(con->root_table);
02013    while ((e1 = ast_hashtab_next(t1))) {
02014       if (e1->exten) {
02015          add_exten_to_pattern_tree(con, e1, 0);
02016       } else {
02017          ast_log(LOG_ERROR, "Attempt to create extension with no extension name.\n");
02018       }
02019    }
02020    ast_hashtab_end_traversal(t1);
02021 }

static void decrease_call_count ( void   )  [static]

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

04518 {
04519    ast_mutex_lock(&maxcalllock);
04520    if (countcalls > 0)
04521       countcalls--;
04522    ast_mutex_unlock(&maxcalllock);
04523 }

static void destroy_exten ( struct ast_exten e  )  [static]
static void destroy_pattern_tree ( struct match_char pattern_tree  )  [static]

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

02024 {
02025    /* destroy all the alternates */
02026    if (pattern_tree->alt_char) {
02027       destroy_pattern_tree(pattern_tree->alt_char);
02028       pattern_tree->alt_char = 0;
02029    }
02030    /* destroy all the nexts */
02031    if (pattern_tree->next_char) {
02032       destroy_pattern_tree(pattern_tree->next_char);
02033       pattern_tree->next_char = 0;
02034    }
02035    pattern_tree->exten = 0; /* never hurts to make sure there's no pointers laying around */
02036    if (pattern_tree->x) {
02037       free(pattern_tree->x);
02038    }
02039    free(pattern_tree);
02040 }

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

Definition at line 9283 of file pbx.c.

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

Referenced by load_pbx().

09284 {
09285    const char *device;
09286    struct statechange *sc;
09287 
09288    device = ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE);
09289    if (ast_strlen_zero(device)) {
09290       ast_log(LOG_ERROR, "Received invalid event that had no device IE\n");
09291       return;
09292    }
09293 
09294    if (!(sc = ast_calloc(1, sizeof(*sc) + strlen(device) + 1)))
09295       return;
09296    strcpy(sc->dev, device);
09297    if (ast_taskprocessor_push(device_state_tps, handle_statechange, sc) < 0) {
09298       ast_free(sc);
09299    }
09300 }

static void exception_store_free ( void *  data  )  [static]

Definition at line 2983 of file pbx.c.

References ast_free, and ast_string_field_free_memory.

02984 {
02985    struct pbx_exception *exception = data;
02986    ast_string_field_free_memory(exception);
02987    ast_free(exception);
02988 }

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

the full routine to compare extensions in rules.

Definition at line 2176 of file pbx.c.

References ext_cmp1().

Referenced by ast_add_extension2_lockopt(), and ast_extension_cmp().

02177 {
02178    /* make sure non-patterns come first.
02179     * If a is not a pattern, it either comes first or
02180     * we do a more complex pattern comparison.
02181     */
02182    int ret = 0;
02183 
02184    if (a[0] != '_')
02185       return (b[0] == '_') ? -1 : strcmp(a, b);
02186 
02187    /* Now we know a is a pattern; if b is not, a comes first */
02188    if (b[0] != '_')
02189       return 1;
02190 
02191    /* ok we need full pattern sorting routine.
02192     * skip past the underscores */
02193    ++a; ++b;
02194    do {
02195       unsigned char bitwise[2][32] = { { 0, } };
02196       ret = ext_cmp1(&a, bitwise[0]) - ext_cmp1(&b, bitwise[1]);
02197       if (ret == 0) {
02198          /* Are the classes different, even though they score the same? */
02199          ret = memcmp(bitwise[0], bitwise[1], 32);
02200       }
02201    } while (!ret && a && b);
02202    if (ret == 0) {
02203       return 0;
02204    } else {
02205       return (ret > 0) ? 1 : -1;
02206    }
02207 }

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

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

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

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

Definition at line 2096 of file pbx.c.

References ast_log(), and LOG_WARNING.

Referenced by ext_cmp().

02097 {
02098    int c, cmin = 0xff, count = 0;
02099    const char *end;
02100 
02101    /* load value and advance pointer */
02102    c = *(*p)++;
02103 
02104    /* always return unless we have a set of chars */
02105    switch (toupper(c)) {
02106    default: /* ordinary character */
02107       bitwise[c / 8] = 1 << (c % 8);
02108       return 0x0100 | (c & 0xff);
02109 
02110    case 'N':   /* 2..9 */
02111       bitwise[6] = 0xfc;
02112       bitwise[7] = 0x03;
02113       return 0x0800 | '2';
02114 
02115    case 'X':   /* 0..9 */
02116       bitwise[6] = 0xff;
02117       bitwise[7] = 0x03;
02118       return 0x0A00 | '0';
02119 
02120    case 'Z':   /* 1..9 */
02121       bitwise[6] = 0xfe;
02122       bitwise[7] = 0x03;
02123       return 0x0900 | '1';
02124 
02125    case '.':   /* wildcard */
02126       return 0x10000;
02127 
02128    case '!':   /* earlymatch */
02129       return 0x20000;   /* less specific than NULL */
02130 
02131    case '\0':  /* empty string */
02132       *p = NULL;
02133       return 0x30000;
02134 
02135    case '[':   /* pattern */
02136       break;
02137    }
02138    /* locate end of set */
02139    end = strchr(*p, ']');
02140 
02141    if (end == NULL) {
02142       ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n");
02143       return 0x40000;   /* XXX make this entry go last... */
02144    }
02145 
02146    for (; *p < end  ; (*p)++) {
02147       unsigned char c1, c2;   /* first-last char in range */
02148       c1 = (unsigned char)((*p)[0]);
02149       if (*p + 2 < end && (*p)[1] == '-') { /* this is a range */
02150          c2 = (unsigned char)((*p)[2]);
02151          *p += 2;    /* skip a total of 3 chars */
02152       } else {        /* individual character */
02153          c2 = c1;
02154       }
02155       if (c1 < cmin) {
02156          cmin = c1;
02157       }
02158       for (; c1 <= c2; c1++) {
02159          unsigned char mask = 1 << (c1 % 8);
02160          /*!\note If two patterns score the same, the one with the lowest
02161           * ascii values will compare as coming first. */
02162          /* Flag the character as included (used) and count it. */
02163          if (!(bitwise[ c1 / 8 ] & mask)) {
02164             bitwise[ c1 / 8 ] |= mask;
02165             count += 0x100;
02166          }
02167       }
02168    }
02169    (*p)++;
02170    return count == 0 ? 0x30000 : (count | cmin);
02171 }

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

copy a string skipping whitespace

Definition at line 7411 of file pbx.c.

Referenced by ast_add_extension2_lockopt().

07412 {
07413    int count = 0;
07414    int insquares = 0;
07415 
07416    while (*src && (count < len - 1)) {
07417       if (*src == '[') {
07418          insquares = 1;
07419       } else if (*src == ']') {
07420          insquares = 0;
07421       } else if (*src == ' ' && !insquares) {
07422          src++;
07423          continue;
07424       }
07425       *dst = *src;
07426       dst++;
07427       src++;
07428       count++;
07429    }
07430    *dst = '\0';
07431 
07432    return count;
07433 }

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

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

02390 {
02391    int i;
02392    static int prof_id = -2;   /* marker for 'unallocated' id */
02393    if (prof_id == -2) {
02394       prof_id = ast_add_profile("ext_match", 0);
02395    }
02396    ast_mark(prof_id, 1);
02397    i = _extension_match_core(pattern, data, mode);
02398    ast_mark(prof_id, 0);
02399    return i;
02400 }

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

lookup for a context with a given name,

Return values:
found context or NULL if not found.

Definition at line 4641 of file pbx.c.

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

04642 {
04643    struct ast_context *c = NULL;
04644    struct fake_context item;
04645 
04646    ast_copy_string(item.name, context, sizeof(item.name));
04647 
04648    c = ast_hashtab_lookup(contexts_table,&item);
04649 
04650    return c;
04651 }

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

lookup for a context with a given name,

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

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

04659 {
04660    struct ast_context *c = NULL;
04661    struct fake_context item;
04662 
04663    ast_copy_string(item.name, context, sizeof(item.name));
04664 
04665    ast_rdlock_contexts();
04666    c = ast_hashtab_lookup(contexts_table,&item);
04667 
04668 #ifdef NOTNOW
04669 
04670    while ( (c = ast_walk_contexts(c)) ) {
04671       if (!strcmp(ast_get_context_name(c), context))
04672          return c;
04673    }
04674 #endif
04675    if (!c)
04676       ast_unlock_contexts();
04677 
04678    return c;
04679 }

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

References ast_log(), and LOG_WARNING.

Referenced by ast_func_read(), and ast_func_write().

03339 {
03340    char *args = strchr(function, '(');
03341 
03342    if (!args) {
03343       ast_log(LOG_WARNING, "Function '%s' doesn't contain parentheses.  Assuming null argument.\n", function);
03344    } else {
03345       char *p;
03346       *args++ = '\0';
03347       if ((p = strrchr(args, ')'))) {
03348          *p = '\0';
03349       } else {
03350          ast_log(LOG_WARNING, "Can't find trailing parenthesis for function '%s(%s'?\n", function, args);
03351       }
03352    }
03353    return args;
03354 }

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

Definition at line 1552 of file pbx.c.

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

01553 {
01554    /* find the exten at the end of the rope */
01555    struct match_char *node2 = node;
01556 
01557    for (node2 = node; node2; node2 = node2->next_char) {
01558       if (node2->exten) {
01559 #ifdef NEED_DEBUG_HERE
01560          ast_log(LOG_NOTICE,"CanMatch_exten returns exten %s(%p)\n", node2->exten->exten, node2->exten);
01561 #endif
01562          return node2->exten;
01563       }
01564    }
01565 #ifdef NEED_DEBUG_HERE
01566    ast_log(LOG_NOTICE,"CanMatch_exten returns NULL, match_char=%s\n", node->x);
01567 #endif
01568    return 0;
01569 }

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

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

Referenced by ast_build_timing().

06808 {
06809    int start, end; /* start and ending position */
06810    unsigned int mask = 0;
06811    char *part;
06812 
06813    /* Check for whole range */
06814    if (ast_strlen_zero(src) || !strcmp(src, "*")) {
06815       return (1 << max) - 1;
06816    }
06817 
06818    while ((part = strsep(&src, "&"))) {
06819       /* Get start and ending position */
06820       char *endpart = strchr(part, '-');
06821       if (endpart) {
06822          *endpart++ = '\0';
06823       }
06824       /* Find the start */
06825       if ((start = lookup_name(part, names, max)) < 0) {
06826          ast_log(LOG_WARNING, "Invalid %s '%s', skipping element\n", msg, part);
06827          continue;
06828       }
06829       if (endpart) { /* find end of range */
06830          if ((end = lookup_name(endpart, names, max)) < 0) {
06831             ast_log(LOG_WARNING, "Invalid end %s '%s', skipping element\n", msg, endpart);
06832             continue;
06833          }
06834       } else {
06835          end = start;
06836       }
06837       /* Fill the mask. Remember that ranges are cyclic */
06838       mask |= (1 << end);   /* initialize with last element */
06839       while (start != end) {
06840          mask |= (1 << start);
06841          if (++start >= max) {
06842             start = 0;
06843          }
06844       }
06845    }
06846    return mask;
06847 }

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

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

Definition at line 6850 of file pbx.c.

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

Referenced by ast_build_timing().

06851 {
06852    char *endpart, *part;
06853    int x;
06854    int st_h, st_m;
06855    int endh, endm;
06856    int minute_start, minute_end;
06857 
06858    /* start disabling all times, fill the fields with 0's, as they may contain garbage */
06859    memset(i->minmask, 0, sizeof(i->minmask));
06860 
06861    /* 1-minute per bit */
06862    /* Star is all times */
06863    if (ast_strlen_zero(times) || !strcmp(times, "*")) {
06864       /* 48, because each hour takes 2 integers; 30 bits each */
06865       for (x = 0; x < 48; x++) {
06866          i->minmask[x] = 0x3fffffff; /* 30 bits */
06867       }
06868       return;
06869    }
06870    /* Otherwise expect a range */
06871    while ((part = strsep(&times, "&"))) {
06872       if (!(endpart = strchr(part, '-'))) {
06873          if (sscanf(part, "%2d:%2d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) {
06874             ast_log(LOG_WARNING, "%s isn't a valid time.\n", part);
06875             continue;
06876          }
06877          i->minmask[st_h * 2 + (st_m >= 30 ? 1 : 0)] |= (1 << (st_m % 30));
06878          continue;
06879       }
06880       *endpart++ = '\0';
06881       /* why skip non digits? Mostly to skip spaces */
06882       while (*endpart && !isdigit(*endpart)) {
06883          endpart++;
06884       }
06885       if (!*endpart) {
06886          ast_log(LOG_WARNING, "Invalid time range starting with '%s-'.\n", part);
06887          continue;
06888       }
06889       if (sscanf(part, "%2d:%2d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) {
06890          ast_log(LOG_WARNING, "'%s' isn't a valid start time.\n", part);
06891          continue;
06892       }
06893       if (sscanf(endpart, "%2d:%2d", &endh, &endm) != 2 || endh < 0 || endh > 23 || endm < 0 || endm > 59) {
06894          ast_log(LOG_WARNING, "'%s' isn't a valid end time.\n", endpart);
06895          continue;
06896       }
06897       minute_start = st_h * 60 + st_m;
06898       minute_end = endh * 60 + endm;
06899       /* Go through the time and enable each appropriate bit */
06900       for (x = minute_start; x != minute_end; x = (x + 1) % (24 * 60)) {
06901          i->minmask[x / 30] |= (1 << (x % 30));
06902       }
06903       /* Do the last one */
06904       i->minmask[x / 30] |= (1 << (x % 30));
06905    }
06906    /* All done */
06907    return;
06908 }

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

Send ack once.

Definition at line 5892 of file pbx.c.

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

05893 {
05894    char *exten = NULL, *context = NULL;
05895    /* Variables used for different counters */
05896    struct dialplan_counters counters;
05897    const char *incstack[AST_PBX_MAX_STACK];
05898 
05899    switch (cmd) {
05900    case CLI_INIT:
05901       e->command = "dialplan debug";
05902       e->usage =
05903          "Usage: dialplan debug [context]\n"
05904          "       Show dialplan context Trie(s). Usually only useful to folks debugging the deep internals of the fast pattern matcher\n";
05905       return NULL;
05906    case CLI_GENERATE:
05907       return complete_show_dialplan_context(a->line, a->word, a->pos, a->n);
05908    }
05909 
05910    memset(&counters, 0, sizeof(counters));
05911 
05912    if (a->argc != 2 && a->argc != 3)
05913       return CLI_SHOWUSAGE;
05914 
05915    /* we obtain [exten@]context? if yes, split them ... */
05916    /* note: we ignore the exten totally here .... */
05917    if (a->argc == 3) {
05918       if (strchr(a->argv[2], '@')) {   /* split into exten & context */
05919          context = ast_strdupa(a->argv[2]);
05920          exten = strsep(&context, "@");
05921          /* change empty strings to NULL */
05922          if (ast_strlen_zero(exten))
05923             exten = NULL;
05924       } else { /* no '@' char, only context given */
05925          context = a->argv[2];
05926       }
05927       if (ast_strlen_zero(context))
05928          context = NULL;
05929    }
05930    /* else Show complete dial plan, context and exten are NULL */
05931    show_debug_helper(a->fd, context, exten, &counters, NULL, 0, incstack);
05932 
05933    /* check for input failure and throw some error messages */
05934    if (context && !counters.context_existence) {
05935       ast_cli(a->fd, "There is no existence of '%s' context\n", context);
05936       return CLI_FAILURE;
05937    }
05938 
05939 
05940    ast_cli(a->fd,"-= %d %s. =-\n",
05941          counters.total_context, counters.total_context == 1 ? "context" : "contexts");
05942 
05943    /* everything ok */
05944    return CLI_SUCCESS;
05945 }

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

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

06270 {
06271    struct ast_channel *chan;
06272    const char *chan_name, *var_name, *var_value;
06273 
06274    switch (cmd) {
06275    case CLI_INIT:
06276       e->command = "dialplan set chanvar";
06277       e->usage =
06278          "Usage: dialplan set chanvar <channel> <varname> <value>\n"
06279          "       Set channel variable <varname> to <value>\n";
06280       return NULL;
06281    case CLI_GENERATE:
06282       return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
06283    }
06284 
06285    if (a->argc != e->args + 3)
06286       return CLI_SHOWUSAGE;
06287 
06288    chan_name = a->argv[e->args];
06289    var_name = a->argv[e->args + 1];
06290    var_value = a->argv[e->args + 2];
06291 
06292    if (!(chan = ast_get_channel_by_name_locked(chan_name))) {
06293       ast_cli(a->fd, "Channel '%s' not found\n", chan_name);
06294       return CLI_FAILURE;
06295    }
06296 
06297    pbx_builtin_setvar_helper(chan, var_name, var_value);
06298    ast_channel_unlock(chan);
06299    ast_cli(a->fd, "\n    -- Channel variable '%s' set to '%s' for '%s'\n",  var_name, var_value, chan_name);
06300 
06301    return CLI_SUCCESS;
06302 }

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

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

06305 {
06306    int oldval = 0;
06307 
06308    switch (cmd) {
06309    case CLI_INIT:
06310       e->command = "dialplan set extenpatternmatchnew true";
06311       e->usage =
06312          "Usage: dialplan set extenpatternmatchnew true|false\n"
06313          "       Use the NEW extension pattern matching algorithm, true or false.\n";
06314       return NULL;
06315    case CLI_GENERATE:
06316       return NULL;
06317    }
06318 
06319    if (a->argc != 4)
06320       return CLI_SHOWUSAGE;
06321 
06322    oldval =  pbx_set_extenpatternmatchnew(1);
06323 
06324    if (oldval)
06325       ast_cli(a->fd, "\n    -- Still using the NEW pattern match algorithm for extension names in the dialplan.\n");
06326    else
06327       ast_cli(a->fd, "\n    -- Switched to using the NEW pattern match algorithm for extension names in the dialplan.\n");
06328 
06329    return CLI_SUCCESS;
06330 }

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

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

06248 {
06249    switch (cmd) {
06250    case CLI_INIT:
06251       e->command = "dialplan set global";
06252       e->usage =
06253          "Usage: dialplan set global <name> <value>\n"
06254          "       Set global dialplan variable <name> to <value>\n";
06255       return NULL;
06256    case CLI_GENERATE:
06257       return NULL;
06258    }
06259 
06260    if (a->argc != e->args + 2)
06261       return CLI_SHOWUSAGE;
06262 
06263    pbx_builtin_setvar_helper(NULL, a->argv[3], a->argv[4]);
06264    ast_cli(a->fd, "\n    -- Global variable '%s' set to '%s'\n", a->argv[3], a->argv[4]);
06265 
06266    return CLI_SUCCESS;
06267 }

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

Definition at line 5261 of file pbx.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strdup, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, ast_cli_args::n, ast_app::name, print_app_docs(), ast_cli_entry::usage, and ast_cli_args::word.

05262 {
05263    struct ast_app *aa;
05264    int app, no_registered_app = 1;
05265    char *ret = NULL;
05266    int which = 0;
05267    int wordlen;
05268 
05269    switch (cmd) {
05270    case CLI_INIT:
05271       e->command = "core show application";
05272       e->usage =
05273          "Usage: core show application <application> [<application> [<application> [...]]]\n"
05274          "       Describes a particular application.\n";
05275       return NULL;
05276    case CLI_GENERATE:
05277       /*
05278        * There is a possibility to show informations about more than one
05279        * application at one time. You can type 'show application Dial Echo' and
05280        * you will see informations about these two applications ...
05281        */
05282       wordlen = strlen(a->word);
05283       /* return the n-th [partial] matching entry */
05284       AST_RWLIST_RDLOCK(&apps);
05285       AST_RWLIST_TRAVERSE(&apps, aa, list) {
05286          if (!strncasecmp(a->word, aa->name, wordlen) && ++which > a->n) {
05287             ret = ast_strdup(aa->name);
05288             break;
05289          }
05290       }
05291       AST_RWLIST_UNLOCK(&apps);
05292 
05293       return ret;
05294    }
05295 
05296    if (a->argc < 4) {
05297       return CLI_SHOWUSAGE;
05298    }
05299 
05300    AST_RWLIST_RDLOCK(&apps);
05301    AST_RWLIST_TRAVERSE(&apps, aa, list) {
05302       /* Check for each app that was supplied as an argument */
05303       for (app = 3; app < a->argc; app++) {
05304          if (strcasecmp(aa->name, a->argv[app])) {
05305             continue;
05306          }
05307 
05308          /* We found it! */
05309          no_registered_app = 0;
05310 
05311          print_app_docs(aa, a->fd);
05312       }
05313    }
05314    AST_RWLIST_UNLOCK(&apps);
05315 
05316    /* we found at least one app? no? */
05317    if (no_registered_app) {
05318       ast_cli(a->fd, "Your application(s) is (are) not registered\n");
05319       return CLI_FAILURE;
05320    }
05321 
05322    return CLI_SUCCESS;
05323 }

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

Definition at line 5481 of file pbx.c.

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

05482 {
05483    struct ast_app *aa;
05484    int like = 0, describing = 0;
05485    int total_match = 0;    /* Number of matches in like clause */
05486    int total_apps = 0;     /* Number of apps registered */
05487    static char* choices[] = { "like", "describing", NULL };
05488 
05489    switch (cmd) {
05490    case CLI_INIT:
05491       e->command = "core show applications [like|describing]";
05492       e->usage =
05493          "Usage: core show applications [{like|describing} <text>]\n"
05494          "       List applications which are currently available.\n"
05495          "       If 'like', <text> will be a substring of the app name\n"
05496          "       If 'describing', <text> will be a substring of the description\n";
05497       return NULL;
05498    case CLI_GENERATE:
05499       return (a->pos != 3) ? NULL : ast_cli_complete(a->word, choices, a->n);
05500    }
05501 
05502    AST_RWLIST_RDLOCK(&apps);
05503 
05504    if (AST_RWLIST_EMPTY(&apps)) {
05505       ast_cli(a->fd, "There are no registered applications\n");
05506       AST_RWLIST_UNLOCK(&apps);
05507       return CLI_SUCCESS;
05508    }
05509 
05510    /* core list applications like <keyword> */
05511    if ((a->argc == 5) && (!strcmp(a->argv[3], "like"))) {
05512       like = 1;
05513    } else if ((a->argc > 4) && (!strcmp(a->argv[3], "describing"))) {
05514       describing = 1;
05515    }
05516 
05517    /* core list applications describing <keyword1> [<keyword2>] [...] */
05518    if ((!like) && (!describing)) {
05519       ast_cli(a->fd, "    -= Registered Asterisk Applications =-\n");
05520    } else {
05521       ast_cli(a->fd, "    -= Matching Asterisk Applications =-\n");
05522    }
05523 
05524    AST_RWLIST_TRAVERSE(&apps, aa, list) {
05525       int printapp = 0;
05526       total_apps++;
05527       if (like) {
05528          if (strcasestr(aa->name, a->argv[4])) {
05529             printapp = 1;
05530             total_match++;
05531          }
05532       } else if (describing) {
05533          if (aa->description) {
05534             /* Match all words on command line */
05535             int i;
05536             printapp = 1;
05537             for (i = 4; i < a->argc; i++) {
05538                if (!strcasestr(aa->description, a->argv[i])) {
05539                   printapp = 0;
05540                } else {
05541                   total_match++;
05542                }
05543             }
05544          }
05545       } else {
05546          printapp = 1;
05547       }
05548 
05549       if (printapp) {
05550          ast_cli(a->fd,"  %20s: %s\n", aa->name, aa->synopsis ? aa->synopsis : "<Synopsis not available>");
05551       }
05552    }
05553    if ((!like) && (!describing)) {
05554       ast_cli(a->fd, "    -= %d Applications Registered =-\n",total_apps);
05555    } else {
05556       ast_cli(a->fd, "    -= %d Applications Matching =-\n",total_match);
05557    }
05558 
05559    AST_RWLIST_UNLOCK(&apps);
05560 
05561    return CLI_SUCCESS;
05562 }

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 6215 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, ast_str_buffer(), ast_str_strlen(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, pbx_builtin_serialize_variables(), ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.

06216 {
06217    struct ast_channel *chan = NULL;
06218    struct ast_str *vars = ast_str_alloca(BUFSIZ * 4); /* XXX large because we might have lots of channel vars */
06219 
06220    switch (cmd) {
06221    case CLI_INIT:
06222       e->command = "dialplan show chanvar";
06223       e->usage =
06224          "Usage: dialplan show chanvar <channel>\n"
06225          "       List current channel variables and their values\n";
06226       return NULL;
06227    case CLI_GENERATE:
06228       return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
06229    }
06230 
06231    if (a->argc != e->args + 1)
06232       return CLI_SHOWUSAGE;
06233 
06234    if (!(chan = ast_get_channel_by_name_locked(a->argv[e->args]))) {
06235       ast_cli(a->fd, "Channel '%s' not found\n", a->argv[e->args]);
06236       return CLI_FAILURE;
06237    }
06238 
06239    pbx_builtin_serialize_variables(chan, &vars);
06240    if (ast_str_strlen(vars)) {
06241       ast_cli(a->fd, "\nVariables for channel %s:\n%s\n", a->argv[e->args], ast_str_buffer(vars));
06242    }
06243    ast_channel_unlock(chan);
06244    return CLI_SUCCESS;
06245 }

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

Definition at line 5825 of file pbx.c.

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

05826 {
05827    char *exten = NULL, *context = NULL;
05828    /* Variables used for different counters */
05829    struct dialplan_counters counters;
05830    const char *incstack[AST_PBX_MAX_STACK];
05831 
05832    switch (cmd) {
05833    case CLI_INIT:
05834       e->command = "dialplan show";
05835       e->usage =
05836          "Usage: dialplan show [[exten@]context]\n"
05837          "       Show dialplan\n";
05838       return NULL;
05839    case CLI_GENERATE:
05840       return complete_show_dialplan_context(a->line, a->word, a->pos, a->n);
05841    }
05842 
05843    memset(&counters, 0, sizeof(counters));
05844 
05845    if (a->argc != 2 && a->argc != 3)
05846       return CLI_SHOWUSAGE;
05847 
05848    /* we obtain [exten@]context? if yes, split them ... */
05849    if (a->argc == 3) {
05850       if (strchr(a->argv[2], '@')) {   /* split into exten & context */
05851          context = ast_strdupa(a->argv[2]);
05852          exten = strsep(&context, "@");
05853          /* change empty strings to NULL */
05854          if (ast_strlen_zero(exten))
05855             exten = NULL;
05856       } else { /* no '@' char, only context given */
05857          context = a->argv[2];
05858       }
05859       if (ast_strlen_zero(context))
05860          context = NULL;
05861    }
05862    /* else Show complete dial plan, context and exten are NULL */
05863    show_dialplan_helper(a->fd, context, exten, &counters, NULL, 0, incstack);
05864 
05865    /* check for input failure and throw some error messages */
05866    if (context && !counters.context_existence) {
05867       ast_cli(a->fd, "There is no existence of '%s' context\n", context);
05868       return CLI_FAILURE;
05869    }
05870 
05871    if (exten && !counters.extension_existence) {
05872       if (context)
05873          ast_cli(a->fd, "There is no existence of %s@%s extension\n",
05874             exten, context);
05875       else
05876          ast_cli(a->fd,
05877             "There is no existence of '%s' extension in all contexts\n",
05878             exten);
05879       return CLI_FAILURE;
05880    }
05881 
05882    ast_cli(a->fd,"-= %d %s (%d %s) in %d %s. =-\n",
05883             counters.total_exten, counters.total_exten == 1 ? "extension" : "extensions",
05884             counters.total_prio, counters.total_prio == 1 ? "priority" : "priorities",
05885             counters.total_context, counters.total_context == 1 ? "context" : "contexts");
05886 
05887    /* everything ok */
05888    return CLI_SUCCESS;
05889 }

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

Definition at line 3095 of file pbx.c.

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

03096 {
03097    struct ast_custom_function *acf;
03098    /* Maximum number of characters added by terminal coloring is 22 */
03099    char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40], argtitle[40], seealsotitle[40];
03100    char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL, *seealso = NULL;
03101    char stxtitle[40], *syntax = NULL, *arguments = NULL;
03102    int syntax_size, description_size, synopsis_size, arguments_size, seealso_size;
03103    char *ret = NULL;
03104    int which = 0;
03105    int wordlen;
03106 
03107    switch (cmd) {
03108    case CLI_INIT:
03109       e->command = "core show function";
03110       e->usage =
03111          "Usage: core show function <function>\n"
03112          "       Describe a particular dialplan function.\n";
03113       return NULL;
03114    case CLI_GENERATE:
03115       wordlen = strlen(a->word);
03116       /* case-insensitive for convenience in this 'complete' function */
03117       AST_RWLIST_RDLOCK(&acf_root);
03118       AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) {
03119          if (!strncasecmp(a->word, acf->name, wordlen) && ++which > a->n) {
03120             ret = ast_strdup(acf->name);
03121             break;
03122          }
03123       }
03124       AST_RWLIST_UNLOCK(&acf_root);
03125 
03126       return ret;
03127    }
03128 
03129    if (a->argc < 4) {
03130       return CLI_SHOWUSAGE;
03131    }
03132 
03133    if (!(acf = ast_custom_function_find(a->argv[3]))) {
03134       ast_cli(a->fd, "No function by that name registered.\n");
03135       return CLI_FAILURE;
03136    }
03137 
03138    syntax_size = strlen(S_OR(acf->syntax, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
03139    if (!(syntax = ast_malloc(syntax_size))) {
03140       ast_cli(a->fd, "Memory allocation failure!\n");
03141       return CLI_FAILURE;
03142    }
03143 
03144    snprintf(info, sizeof(info), "\n  -= Info about function '%s' =- \n\n", acf->name);
03145    term_color(infotitle, info, COLOR_MAGENTA, 0, sizeof(infotitle));
03146    term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
03147    term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
03148    term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40);
03149    term_color(argtitle, "[Arguments]\n", COLOR_MAGENTA, 0, 40);
03150    term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, 40);
03151    term_color(syntax, S_OR(acf->syntax, "Not available"), COLOR_CYAN, 0, syntax_size);
03152 #ifdef AST_XML_DOCS
03153    if (acf->docsrc == AST_XML_DOC) {
03154       arguments = ast_xmldoc_printable(S_OR(acf->arguments, "Not available"), 1);
03155       synopsis = ast_xmldoc_printable(S_OR(acf->synopsis, "Not available"), 1);
03156       description = ast_xmldoc_printable(S_OR(acf->desc, "Not available"), 1);
03157       seealso = ast_xmldoc_printable(S_OR(acf->seealso, "Not available"), 1);
03158    } else
03159 #endif
03160    {
03161       synopsis_size = strlen(S_OR(acf->synopsis, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
03162       synopsis = ast_malloc(synopsis_size);
03163 
03164       description_size = strlen(S_OR(acf->desc, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
03165       description = ast_malloc(description_size);
03166 
03167       arguments_size = strlen(S_OR(acf->arguments, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
03168       arguments = ast_malloc(arguments_size);
03169 
03170       seealso_size = strlen(S_OR(acf->seealso, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
03171       seealso = ast_malloc(seealso_size);
03172 
03173       /* check allocated memory. */
03174       if (!synopsis || !description || !arguments || !seealso) {
03175          ast_free(synopsis);
03176          ast_free(description);
03177          ast_free(arguments);
03178          ast_free(seealso);
03179          ast_free(syntax);
03180          return CLI_FAILURE;
03181       }
03182 
03183       term_color(arguments, S_OR(acf->arguments, "Not available"), COLOR_CYAN, 0, arguments_size);
03184       term_color(synopsis, S_OR(acf->synopsis, "Not available"), COLOR_CYAN, 0, synopsis_size);
03185       term_color(description, S_OR(acf->desc, "Not available"), COLOR_CYAN, 0, description_size);
03186       term_color(seealso, S_OR(acf->seealso, "Not available"), COLOR_CYAN, 0, seealso_size);
03187    }
03188 
03189    ast_cli(a->fd, "%s%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n",
03190          infotitle, syntitle, synopsis, destitle, description,
03191          stxtitle, syntax, argtitle, arguments, seealsotitle, seealso);
03192 
03193    ast_free(arguments);
03194    ast_free(synopsis);
03195    ast_free(description);
03196    ast_free(seealso);
03197    ast_free(syntax);
03198 
03199    return CLI_SUCCESS;
03200 }

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

Definition at line 3053 of file pbx.c.

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

03054 {
03055    struct ast_custom_function *acf;
03056    int count_acf = 0;
03057    int like = 0;
03058 
03059    switch (cmd) {
03060    case CLI_INIT:
03061       e->command = "core show functions [like]";
03062       e->usage =
03063          "Usage: core show functions [like <text>]\n"
03064          "       List builtin functions, optionally only those matching a given string\n";
03065       return NULL;
03066    case CLI_GENERATE:
03067       return NULL;
03068    }
03069 
03070    if (a->argc == 5 && (!strcmp(a->argv[3], "like")) ) {
03071       like = 1;
03072    } else if (a->argc != 3) {
03073       return CLI_SHOWUSAGE;
03074    }
03075 
03076    ast_cli(a->fd, "%s Custom Functions:\n--------------------------------------------------------------------------------\n", like ? "Matching" : "Installed");
03077 
03078    AST_RWLIST_RDLOCK(&acf_root);
03079    AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) {
03080       if (!like || strstr(acf->name, a->argv[4])) {
03081          count_acf++;
03082          ast_cli(a->fd, "%-20.20s  %-35.35s  %s\n",
03083             S_OR(acf->name, ""),
03084             S_OR(acf->syntax, ""),
03085             S_OR(acf->synopsis, ""));
03086       }
03087    }
03088    AST_RWLIST_UNLOCK(&acf_root);
03089 
03090    ast_cli(a->fd, "%d %scustom functions installed.\n", count_acf, like ? "matching " : "");
03091 
03092    return CLI_SUCCESS;
03093 }

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

06158 {
06159    int i = 0;
06160    struct ast_var_t *newvariable;
06161 
06162    switch (cmd) {
06163    case CLI_INIT:
06164       e->command = "dialplan show globals";
06165       e->usage =
06166          "Usage: dialplan show globals\n"
06167          "       List current global dialplan variables and their values\n";
06168       return NULL;
06169    case CLI_GENERATE:
06170       return NULL;
06171    }
06172 
06173    ast_rwlock_rdlock(&globalslock);
06174    AST_LIST_TRAVERSE (&globals, newvariable, entries) {
06175       i++;
06176       ast_cli(a->fd, "   %s=%s\n", ast_var_name(newvariable), ast_var_value(newvariable));
06177    }
06178    ast_rwlock_unlock(&globalslock);
06179    ast_cli(a->fd, "\n    -- %d variable(s)\n", i);
06180 
06181    return CLI_SUCCESS;
06182 }

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 5397 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_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.

05398 {
05399    struct ast_hint *hint;
05400    int watchers;
05401    int num = 0, extenlen;
05402    struct ast_state_cb *watcher;
05403 
05404    switch (cmd) {
05405    case CLI_INIT:
05406       e->command = "core show hint";
05407       e->usage =
05408          "Usage: core show hint <exten>\n"
05409          "       List registered hint\n";
05410       return NULL;
05411    case CLI_GENERATE:
05412       return complete_core_show_hint(a->line, a->word, a->pos, a->n);
05413    }
05414 
05415    if (a->argc < 4)
05416       return CLI_SHOWUSAGE;
05417 
05418    AST_RWLIST_RDLOCK(&hints);
05419    if (AST_RWLIST_EMPTY(&hints)) {
05420       ast_cli(a->fd, "There are no registered dialplan hints\n");
05421       AST_RWLIST_UNLOCK(&hints);
05422       return CLI_SUCCESS;
05423    }
05424    extenlen = strlen(a->argv[3]);
05425    AST_RWLIST_TRAVERSE(&hints, hint, list) {
05426       if (!strncasecmp(ast_get_extension_name(hint->exten), a->argv[3], extenlen)) {
05427          watchers = 0;
05428          AST_LIST_TRAVERSE(&hint->callbacks, watcher, entry) {
05429             watchers++;
05430          }
05431          ast_cli(a->fd, "   %20s@%-20.20s: %-20.20s  State:%-15.15s Watchers %2d\n",
05432             ast_get_extension_name(hint->exten),
05433             ast_get_context_name(ast_get_extension_context(hint->exten)),
05434             ast_get_extension_app(hint->exten),
05435             ast_extension_state2str(hint->laststate), watchers);
05436          num++;
05437       }
05438    }
05439    AST_RWLIST_UNLOCK(&hints);
05440    if (!num)
05441       ast_cli(a->fd, "No hints matching extension %s\n", a->argv[3]);
05442    else
05443       ast_cli(a->fd, "%d hint%s matching extension %s\n", num, (num!=1 ? "s":""), a->argv[3]);
05444    return CLI_SUCCESS;
05445 }

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 5326 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_hint::exten, ast_cli_args::fd, ast_hint::laststate, num, and ast_cli_entry::usage.

05327 {
05328    struct ast_hint *hint;
05329    int num = 0;
05330    int watchers;
05331    struct ast_state_cb *watcher;
05332 
05333    switch (cmd) {
05334    case CLI_INIT:
05335       e->command = "core show hints";
05336       e->usage =
05337          "Usage: core show hints\n"
05338          "       List registered hints\n";
05339       return NULL;
05340    case CLI_GENERATE:
05341       return NULL;
05342    }
05343 
05344    AST_RWLIST_RDLOCK(&hints);
05345    if (AST_RWLIST_EMPTY(&hints)) {
05346       ast_cli(a->fd, "There are no registered dialplan hints\n");
05347       AST_RWLIST_UNLOCK(&hints);
05348       return CLI_SUCCESS;
05349    }
05350    /* ... we have hints ... */
05351    ast_cli(a->fd, "\n    -= Registered Asterisk Dial Plan Hints =-\n");
05352    AST_RWLIST_TRAVERSE(&hints, hint, list) {
05353       watchers = 0;
05354       AST_LIST_TRAVERSE(&hint->callbacks, watcher, entry) {
05355          watchers++;
05356       }
05357       ast_cli(a->fd, "   %20s@%-20.20s: %-20.20s  State:%-15.15s Watchers %2d\n",
05358          ast_get_extension_name(hint->exten),
05359          ast_get_context_name(ast_get_extension_context(hint->exten)),
05360          ast_get_extension_app(hint->exten),
05361          ast_extension_state2str(hint->laststate), watchers);
05362       num++;
05363    }
05364    ast_cli(a->fd, "----------------\n");
05365    ast_cli(a->fd, "- %d hints registered\n", num);
05366    AST_RWLIST_UNLOCK(&hints);
05367    return CLI_SUCCESS;
05368 }

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

References ast_cli(), AST_RWLIST_EMPTY, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_switch::description, ast_cli_args::fd, ast_switch::name, and ast_cli_entry::usage.

05450 {
05451    struct ast_switch *sw;
05452 
05453    switch (cmd) {
05454    case CLI_INIT:
05455       e->command = "core show switches";
05456       e->usage =
05457          "Usage: core show switches\n"
05458          "       List registered switches\n";
05459       return NULL;
05460    case CLI_GENERATE:
05461       return NULL;
05462    }
05463 
05464    AST_RWLIST_RDLOCK(&switches);
05465 
05466    if (AST_RWLIST_EMPTY(&switches)) {
05467       AST_RWLIST_UNLOCK(&switches);
05468       ast_cli(a->fd, "There are no registered alternative switches\n");
05469       return CLI_SUCCESS;
05470    }
05471 
05472    ast_cli(a->fd, "\n    -= Registered Asterisk Alternative Switches =-\n");
05473    AST_RWLIST_TRAVERSE(&switches, sw, list)
05474       ast_cli(a->fd, "%s: %s\n", sw->name, sw->description);
05475 
05476    AST_RWLIST_UNLOCK(&switches);
05477 
05478    return CLI_SUCCESS;
05479 }

static int handle_statechange ( void *  datap  )  [static]

Definition at line 3843 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_exten::exten, ast_hint::exten, ast_hint::laststate, ast_context::name, ast_exten::parent, and parse().

Referenced by device_state_cb().

03844 {
03845    struct ast_hint *hint;
03846    struct statechange *sc = datap;
03847 
03848    ast_rdlock_contexts();
03849    AST_RWLIST_RDLOCK(&hints);
03850 
03851    AST_RWLIST_TRAVERSE(&hints, hint, list) {
03852       struct ast_state_cb *cblist;
03853       char buf[AST_MAX_EXTENSION];
03854       char *parse = buf;
03855       char *cur;
03856       int state;
03857 
03858       ast_copy_string(buf, ast_get_extension_app(hint->exten), sizeof(buf));
03859       while ( (cur = strsep(&parse, "&")) ) {
03860          if (!strcasecmp(cur, sc->dev)) {
03861             break;
03862          }
03863       }
03864       if (!cur) {
03865          continue;
03866       }
03867 
03868       /* Get device state for this hint */
03869       state = ast_extension_state2(hint->exten);
03870 
03871       if ((state == -1) || (state == hint->laststate)) {
03872          continue;
03873       }
03874 
03875       /* Device state changed since last check - notify the watchers */
03876 
03877       /* For general callbacks */
03878       AST_LIST_TRAVERSE(&statecbs, cblist, entry) {
03879          cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data);
03880       }
03881 
03882       /* For extension callbacks */
03883       AST_LIST_TRAVERSE(&hint->callbacks, cblist, entry) {
03884          cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data);
03885       }
03886 
03887       hint->laststate = state;   /* record we saw the change */
03888    }
03889    AST_RWLIST_UNLOCK(&hints);
03890    ast_unlock_contexts();
03891    ast_free(sc);
03892    return 0;
03893 }

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

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

06333 {
06334    int oldval = 0;
06335 
06336    switch (cmd) {
06337    case CLI_INIT:
06338       e->command = "dialplan set extenpatternmatchnew false";
06339       e->usage =
06340          "Usage: dialplan set extenpatternmatchnew true|false\n"
06341          "       Use the NEW extension pattern matching algorithm, true or false.\n";
06342       return NULL;
06343    case CLI_GENERATE:
06344       return NULL;
06345    }
06346 
06347    if (a->argc != 4)
06348       return CLI_SHOWUSAGE;
06349 
06350    oldval =  pbx_set_extenpatternmatchnew(0);
06351 
06352    if (!oldval)
06353       ast_cli(a->fd, "\n    -- Still using the OLD pattern match algorithm for extension names in the dialplan.\n");
06354    else
06355       ast_cli(a->fd, "\n    -- Switched to using the OLD pattern match algorithm for extension names in the dialplan.\n");
06356 
06357    return CLI_SUCCESS;
06358 }

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

Definition at line 1030 of file pbx.c.

References ast_exten::label, and S_OR.

Referenced by ast_add_extension2_lockopt().

01031 {
01032    const struct ast_exten *ac = ah_a;
01033    const struct ast_exten *bc = ah_b;
01034    return strcmp(S_OR(ac->label, ""), S_OR(bc->label, ""));
01035 }

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

Definition at line 1023 of file pbx.c.

References ast_exten::priority.

Referenced by ast_add_extension2_lockopt().

01024 {
01025    const struct ast_exten *ac = ah_a;
01026    const struct ast_exten *bc = ah_b;
01027    return ac->priority != bc->priority;
01028 }

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

Definition at line 1004 of file pbx.c.

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

Referenced by ast_add_extension2_lockopt().

01005 {
01006    const struct ast_exten *ac = ah_a;
01007    const struct ast_exten *bc = ah_b;
01008    int x = strcmp(ac->exten, bc->exten);
01009    if (x) { /* if exten names are diff, then return */
01010       return x;
01011    }
01012 
01013    /* but if they are the same, do the cidmatch values match? */
01014    if (ac->matchcid && bc->matchcid) {
01015       return strcmp(ac->cidmatch,bc->cidmatch);
01016    } else if (!ac->matchcid && !bc->matchcid) {
01017       return 0; /* if there's no matchcid on either side, then this is a match */
01018    } else {
01019       return 1; /* if there's matchcid on one but not the other, they are different */
01020    }
01021 }

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

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

01044 {
01045    const struct ast_exten *ac = obj;
01046    unsigned int x = ast_hashtab_hash_string(ac->exten);
01047    unsigned int y = 0;
01048    if (ac->matchcid)
01049       y = ast_hashtab_hash_string(ac->cidmatch);
01050    return x+y;
01051 }

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

Definition at line 1059 of file pbx.c.

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

Referenced by ast_add_extension2_lockopt().

01060 {
01061    const struct ast_exten *ac = obj;
01062    return ast_hashtab_hash_string(S_OR(ac->label, ""));
01063 }

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

Definition at line 1053 of file pbx.c.

References ast_hashtab_hash_int(), and ast_exten::priority.

Referenced by ast_add_extension2_lockopt().

01054 {
01055    const struct ast_exten *ac = obj;
01056    return ast_hashtab_hash_int(ac->priority);
01057 }

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

Definition at line 1391 of file pbx.c.

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

Referenced by pbx_find_extension().

01392 {
01393    if (!i->hastime)
01394       return 1;
01395 
01396    return ast_check_timing(&(i->timing));
01397 }

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

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

Referenced by ast_pbx_run_args(), and ast_pbx_start().

04471 {
04472    int failed = 0;
04473    double curloadavg;
04474 #if defined(HAVE_SYSINFO)
04475    long curfreemem;
04476    struct sysinfo sys_info;
04477 #endif
04478 
04479    ast_mutex_lock(&maxcalllock);
04480    if (option_maxcalls) {
04481       if (countcalls >= option_maxcalls) {
04482          ast_log(LOG_WARNING, "Maximum call limit of %d calls exceeded by '%s'!\n", option_maxcalls, c->name);
04483          failed = -1;
04484       }
04485    }
04486    if (option_maxload) {
04487       getloadavg(&curloadavg, 1);
04488       if (curloadavg >= option_maxload) {
04489          ast_log(LOG_WARNING, "Maximum loadavg limit of %f load exceeded by '%s' (currently %f)!\n", option_maxload, c->name, curloadavg);
04490          failed = -1;
04491       }
04492    }
04493 #if defined(HAVE_SYSINFO)
04494    if (option_minmemfree) {
04495       if (!sysinfo(&sys_info)) {
04496          /* make sure that the free system memory is above the configured low watermark
04497           * convert the amount of freeram from mem_units to MB */
04498          curfreemem = sys_info.freeram / sys_info.mem_unit;
04499          curfreemem /= 1024 * 1024;
04500          if (curfreemem < option_minmemfree) {
04501             ast_log(LOG_WARNING, "Available system memory (~%ldMB) is below the configured low watermark (%ldMB)\n", curfreemem, option_minmemfree);
04502             failed = -1;
04503          }
04504       }
04505    }
04506 #endif
04507 
04508    if (!failed) {
04509       countcalls++;
04510       totalcalls++;
04511    }
04512    ast_mutex_unlock(&maxcalllock);
04513 
04514    return failed;
04515 }

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

Definition at line 1799 of file pbx.c.

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

Referenced by add_pattern_node().

01800 {
01801    struct match_char *curr, *lcurr;
01802 
01803    /* insert node into the tree at "current", so the alt_char list from current is
01804       sorted in increasing value as you go to the leaves */
01805    if (!(*parent_ptr)) {
01806       *parent_ptr = node;
01807    } else {
01808       if ((*parent_ptr)->specificity > node->specificity) {
01809          /* insert at head */
01810          node->alt_char = (*parent_ptr);
01811          *parent_ptr = node;
01812       } else {
01813          lcurr = *parent_ptr;
01814          for (curr = (*parent_ptr)->alt_char; curr; curr = curr->alt_char) {
01815             if (curr->specificity > node->specificity) {
01816                node->alt_char = curr;
01817                lcurr->alt_char = node;
01818                break;
01819             }
01820             lcurr = curr;
01821          }
01822          if (!curr) {
01823             lcurr->alt_char = node;
01824          }
01825       }
01826    }
01827 }

int load_pbx ( void   ) 

Provided by pbx.c

Definition at line 9302 of file pbx.c.

References __ast_custom_function_register(), ARRAY_LEN, 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, EVENT_FLAG_CONFIG, EVENT_FLAG_REPORTING, exception_function, LOG_ERROR, LOG_WARNING, manager_show_dialplan(), mandescr_show_dialplan, and pbx_cli.

Referenced by main().

09303 {
09304    int x;
09305 
09306    /* Initialize the PBX */
09307    ast_verb(1, "Asterisk PBX Core Initializing\n");
09308    if (!(device_state_tps = ast_taskprocessor_get("pbx-core", 0))) {
09309       ast_log(LOG_WARNING, "failed to create pbx-core taskprocessor\n");
09310    }
09311 
09312    ast_verb(1, "Registering builtin applications:\n");
09313    ast_cli_register_multiple(pbx_cli, ARRAY_LEN(pbx_cli));
09314    __ast_custom_function_register(&exception_function, NULL);
09315 
09316    /* Register builtin applications */
09317    for (x = 0; x < ARRAY_LEN(builtins); x++) {
09318       ast_verb(1, "[%s]\n", builtins[x].name);
09319       if (ast_register_application2(builtins[x].name, builtins[x].execute, NULL, NULL, NULL)) {
09320          ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name);
09321          return -1;
09322       }
09323    }
09324 
09325    /* Register manager application */
09326    ast_manager_register2("ShowDialPlan", EVENT_FLAG_CONFIG | EVENT_FLAG_REPORTING, manager_show_dialplan, "List dialplan", mandescr_show_dialplan);
09327 
09328    if (!(device_state_sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE, device_state_cb, NULL,
09329          AST_EVENT_IE_END))) {
09330       return -1;
09331    }
09332 
09333    return 0;
09334 }

void log_match_char_tree ( struct match_char node,
char *  prefix 
)

Definition at line 1494 of file pbx.c.

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

Referenced by ast_context_remove_extension_callerid2(), and pbx_find_extension().

01495 {
01496    char extenstr[40];
01497    struct ast_str *my_prefix = ast_str_alloca(1024);
01498 
01499    extenstr[0] = '\0';
01500 
01501    if (node && node->exten && node->exten)
01502       snprintf(extenstr, sizeof(extenstr), "(%p)", node->exten);
01503 
01504    if (strlen(node->x) > 1) {
01505       ast_debug(1, "%s[%s]:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y':'N',
01506          node->deleted? 'D':'-', node->specificity, node->exten? "EXTEN:":"",
01507          node->exten ? node->exten->exten : "", extenstr);
01508    } else {
01509       ast_debug(1, "%s%s:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y':'N',
01510          node->deleted? 'D':'-', node->specificity, node->exten? "EXTEN:":"",
01511          node->exten ? node->exten->exten : "", extenstr);
01512    }
01513 
01514    ast_str_set(&my_prefix, 0, "%s+       ", prefix);
01515 
01516    if (node->next_char)
01517       log_match_char_tree(node->next_char, ast_str_buffer(my_prefix));
01518 
01519    if (node->alt_char)
01520       log_match_char_tree(node->alt_char, prefix);
01521 }

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

Referenced by get_range().

06785 {
06786    int i;
06787 
06788    if (names && *s > '9') {
06789       for (i = 0; names[i]; i++) {
06790          if (!strcasecmp(s, names[i])) {
06791             return i;
06792          }
06793       }
06794    }
06795 
06796    /* Allow months and weekdays to be specified as numbers, as well */
06797    if (sscanf(s, "%2d", &i) == 1 && i >= 1 && i <= max) {
06798       /* What the array offset would have been: "1" would be at offset 0 */
06799       return i - 1;
06800    }
06801    return -1; /* error return */
06802 }

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

Send ack once.

Definition at line 5948 of file pbx.c.

References astman_send_listack().

Referenced by manager_show_dialplan_helper().

05949 {
05950    astman_send_listack(s, m, "DialPlan list will follow", "start");
05951 }

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

Manager listing of dial plan.

Definition at line 6094 of file pbx.c.

References ast_strlen_zero(), astman_get_header(), astman_send_error(), dialplan_counters::context_existence, EVENT_FLAG_CONFIG, dialplan_counters::extension_existence, manager_event, manager_show_dialplan_helper(), dialplan_counters::total_context, dialplan_counters::total_exten, dialplan_counters::total_items, and dialplan_counters::total_prio.

Referenced by load_pbx().

06095 {
06096    const char *exten, *context;
06097    const char *id = astman_get_header(m, "ActionID");
06098    char idtext[256];
06099    int res;
06100 
06101    /* Variables used for different counters */
06102    struct dialplan_counters counters;
06103 
06104    if (!ast_strlen_zero(id))
06105       snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id);
06106    else
06107       idtext[0] = '\0';
06108 
06109    memset(&counters, 0, sizeof(counters));
06110 
06111    exten = astman_get_header(m, "Extension");
06112    context = astman_get_header(m, "Context");
06113 
06114    res = manager_show_dialplan_helper(s, m, idtext, context, exten, &counters, NULL);
06115 
06116    if (context && !counters.context_existence) {
06117       char errorbuf[BUFSIZ];
06118 
06119       snprintf(errorbuf, sizeof(errorbuf), "Did not find context %s", context);
06120       astman_send_error(s, m, errorbuf);
06121       return 0;
06122    }
06123    if (exten && !counters.extension_existence) {
06124       char errorbuf[BUFSIZ];
06125 
06126       if (context)
06127          snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s@%s", exten, context);
06128       else
06129          snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s in any context", exten);
06130       astman_send_error(s, m, errorbuf);
06131       return 0;
06132    }
06133 
06134    manager_event(EVENT_FLAG_CONFIG, "ShowDialPlanComplete",
06135       "EventList: Complete\r\n"
06136       "ListItems: %d\r\n"
06137       "ListExtensions: %d\r\n"
06138       "ListPriorities: %d\r\n"
06139       "ListContexts: %d\r\n"
06140       "%s"
06141       "\r\n", counters.total_items, counters.total_exten, counters.total_prio, counters.total_context, idtext);
06142 
06143    /* everything ok */
06144    return 0;
06145 }

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

References ast_debug, ast_extension_match(), ast_get_context_name(), ast_get_extension_app(), ast_get_extension_app_data(), ast_get_extension_label(), ast_get_extension_name(), ast_get_extension_priority(), ast_get_extension_registrar(), ast_get_ignorepat_name(), ast_get_ignorepat_registrar(), ast_get_include_name(), ast_get_include_registrar(), ast_get_switch_data(), ast_get_switch_name(), ast_get_switch_registrar(), ast_log(), AST_MAX_EXTENSION, ast_rdlock_context(), ast_rdlock_contexts(), ast_strlen_zero(), ast_unlock_context(), ast_unlock_contexts(), ast_walk_context_extensions(), ast_walk_context_ignorepats(), ast_walk_context_includes(), ast_walk_context_switches(), ast_walk_contexts(), ast_walk_extension_priorities(), astman_append(), astman_send_error(), dialplan_counters::context_existence, dialplan_counters::extension_existence, LOG_WARNING, manager_dpsendack(), PRIORITY_HINT, dialplan_counters::total_context, dialplan_counters::total_exten, dialplan_counters::total_items, and dialplan_counters::total_prio.

Referenced by manager_show_dialplan().

05961 {
05962    struct ast_context *c;
05963    int res = 0, old_total_exten = dpc->total_exten;
05964 
05965    if (ast_strlen_zero(exten))
05966       exten = NULL;
05967    if (ast_strlen_zero(context))
05968       context = NULL;
05969 
05970    ast_debug(3, "manager_show_dialplan: Context: -%s- Extension: -%s-\n", context, exten);
05971 
05972    /* try to lock contexts */
05973    if (ast_rdlock_contexts()) {
05974       astman_send_error(s, m, "Failed to lock contexts");
05975       ast_log(LOG_WARNING, "Failed to lock contexts list for manager: listdialplan\n");
05976       return -1;
05977    }
05978 
05979    c = NULL;      /* walk all contexts ... */
05980    while ( (c = ast_walk_contexts(c)) ) {
05981       struct ast_exten *e;
05982       struct ast_include *i;
05983       struct ast_ignorepat *ip;
05984 
05985       if (context && strcmp(ast_get_context_name(c), context) != 0)
05986          continue;   /* not the name we want */
05987 
05988       dpc->context_existence = 1;
05989 
05990       ast_debug(3, "manager_show_dialplan: Found Context: %s \n", ast_get_context_name(c));
05991 
05992       if (ast_rdlock_context(c)) {  /* failed to lock */
05993          ast_debug(3, "manager_show_dialplan: Failed to lock context\n");
05994          continue;
05995       }
05996 
05997       /* XXX note- an empty context is not printed */
05998       e = NULL;      /* walk extensions in context  */
05999       while ( (e = ast_walk_context_extensions(c, e)) ) {
06000          struct ast_exten *p;
06001 
06002          /* looking for extension? is this our extension? */
06003          if (exten && !ast_extension_match(ast_get_extension_name(e), exten)) {
06004             /* not the one we are looking for, continue */
06005             ast_debug(3, "manager_show_dialplan: Skipping extension %s\n", ast_get_extension_name(e));
06006             continue;
06007          }
06008          ast_debug(3, "manager_show_dialplan: Found Extension: %s \n", ast_get_extension_name(e));
06009 
06010          dpc->extension_existence = 1;
06011 
06012          /* may we print context info? */
06013          dpc->total_context++;
06014          dpc->total_exten++;
06015 
06016          p = NULL;      /* walk next extension peers */
06017          while ( (p = ast_walk_extension_priorities(e, p)) ) {
06018             int prio = ast_get_extension_priority(p);
06019 
06020             dpc->total_prio++;
06021             if (!dpc->total_items++)
06022                manager_dpsendack(s, m);
06023             astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
06024             astman_append(s, "Context: %s\r\nExtension: %s\r\n", ast_get_context_name(c), ast_get_extension_name(e) );
06025 
06026             /* XXX maybe make this conditional, if p != e ? */
06027             if (ast_get_extension_label(p))
06028                astman_append(s, "ExtensionLabel: %s\r\n", ast_get_extension_label(p));
06029 
06030             if (prio == PRIORITY_HINT) {
06031                astman_append(s, "Priority: hint\r\nApplication: %s\r\n", ast_get_extension_app(p));
06032             } else {
06033                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));
06034             }
06035             astman_append(s, "Registrar: %s\r\n\r\n", ast_get_extension_registrar(e));
06036          }
06037       }
06038 
06039       i = NULL;      /* walk included and write info ... */
06040       while ( (i = ast_walk_context_includes(c, i)) ) {
06041          if (exten) {
06042             /* Check all includes for the requested extension */
06043             manager_show_dialplan_helper(s, m, actionidtext, ast_get_include_name(i), exten, dpc, i);
06044          } else {
06045             if (!dpc->total_items++)
06046                manager_dpsendack(s, m);
06047             astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
06048             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));
06049             astman_append(s, "\r\n");
06050             ast_debug(3, "manager_show_dialplan: Found Included context: %s \n", ast_get_include_name(i));
06051          }
06052       }
06053 
06054       ip = NULL;  /* walk ignore patterns and write info ... */
06055       while ( (ip = ast_walk_context_ignorepats(c, ip)) ) {
06056          const char *ipname = ast_get_ignorepat_name(ip);
06057          char ignorepat[AST_MAX_EXTENSION];
06058 
06059          snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname);
06060          if (!exten || ast_extension_match(ignorepat, exten)) {
06061             if (!dpc->total_items++)
06062                manager_dpsendack(s, m);
06063             astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
06064             astman_append(s, "Context: %s\r\nIgnorePattern: %s\r\nRegistrar: %s\r\n", ast_get_context_name(c), ipname, ast_get_ignorepat_registrar(ip));
06065             astman_append(s, "\r\n");
06066          }
06067       }
06068       if (!rinclude) {
06069          struct ast_sw *sw = NULL;
06070          while ( (sw = ast_walk_context_switches(c, sw)) ) {
06071             if (!dpc->total_items++)
06072                manager_dpsendack(s, m);
06073             astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
06074             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));  
06075             astman_append(s, "\r\n");
06076             ast_debug(3, "manager_show_dialplan: Found Switch : %s \n", ast_get_switch_name(sw));
06077          }
06078       }
06079 
06080       ast_unlock_context(c);
06081    }
06082    ast_unlock_contexts();
06083 
06084    if (dpc->total_exten == old_total_exten) {
06085       ast_debug(3, "manager_show_dialplan: Found nothing new\n");
06086       /* Nothing new under the sun */
06087       return -1;
06088    } else {
06089       return res;
06090    }
06091 }

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

Definition at line 2457 of file pbx.c.

References ast_extension_match(), and ast_strlen_zero().

Referenced by pbx_find_extension().

02458 {
02459    /* If the Caller*ID pattern is empty, then we're matching NO Caller*ID, so
02460       failing to get a number should count as a match, otherwise not */
02461 
02462    if (ast_strlen_zero(callerid)) {
02463       return ast_strlen_zero(cidpattern) ? 1 : 0;
02464    }
02465 
02466    return ast_extension_match(cidpattern, callerid);
02467 }

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

References match_char::alt_char, ast_debug, ast_log(), scoreboard::canmatch, match_char::deleted, E_CANMATCH, E_MATCHMORE, ast_exten::exten, scoreboard::exten, match_char::exten, ast_exten::label, LOG_NOTICE, NEW_MATCHER_CHK_MATCH, NEW_MATCHER_RECURSE, match_char::next_char, match_char::specificity, update_scoreboard(), and match_char::x.

Referenced by pbx_find_extension().

01630 {
01631    struct match_char *p; /* note minimal stack storage requirements */
01632    struct ast_exten pattern = { .label = label };
01633 #ifdef DEBUG_THIS
01634    if (tree)
01635       ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree %s action=%s\n", str, tree->x, action2str(action));
01636    else
01637       ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree NULL action=%s\n", str, action2str(action));
01638 #endif
01639    for (p = tree; p; p = p->alt_char) {
01640       if (p->x[0] == 'N') {
01641          if (p->x[1] == 0 && *str >= '2' && *str <= '9' ) {
01642 #define NEW_MATCHER_CHK_MATCH        \
01643             if (p->exten && !(*(str + 1))) { /* if a shorter pattern matches along the way, might as well report it */           \
01644                if (action == E_MATCH || action == E_SPAWN || action == E_FINDLABEL) { /* if in CANMATCH/MATCHMORE, don't let matches get in the way */   \
01645                   update_scoreboard(score, length + 1, spec + p->specificity, p->exten, 0, callerid, p->deleted, p);           \
01646                   if (!p->deleted) {                                                                                           \
01647                      if (action == E_FINDLABEL) {                                                                             \
01648                         if (ast_hashtab_lookup(score->exten->peer_label_table, &pattern)) {                                  \
01649                            ast_debug(4, "Found label in preferred extension\n");                                            \
01650                            return;                                                                                          \
01651                         }                                                                                                    \
01652                      } else {                                                                                                 \
01653                         ast_debug(4,"returning an exact match-- first found-- %s\n", p->exten->exten);                       \
01654                         return; /* the first match, by definition, will be the best, because of the sorted tree */           \
01655                      }                                                                                                        \
01656                   }                                                                                                            \
01657                }                                                                                                                \
01658             }
01659 
01660 #define NEW_MATCHER_RECURSE              \
01661             if (p->next_char && ( *(str + 1) || (p->next_char->x[0] == '/' && p->next_char->x[1] == 0)               \
01662                                                  || p->next_char->x[0] == '!')) {                                        \
01663                if (*(str + 1) || p->next_char->x[0] == '!') {                                                       \
01664                   new_find_extension(str + 1, score, p->next_char, length + 1, spec+p->specificity, callerid, label, action); \
01665                   if (score->exten)  {                                                                             \
01666                        ast_debug(4, "returning an exact match-- %s\n", score->exten->exten);                        \
01667                      return; /* the first match is all we need */                                                 \
01668                   }                                                                                    \
01669                } else {                                                                                             \
01670                   new_find_extension("/", score, p->next_char, length + 1, spec+p->specificity, callerid, label, action);   \
01671                   if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) {      \
01672                        ast_debug(4,"returning a (can/more) match--- %s\n", score->exten ? score->exten->exten :     \
01673                                        "NULL");                                                                          \
01674                      return; /* the first match is all we need */                                                 \
01675                   }                                                                                    \
01676                }                                                                                                    \
01677             } else if (p->next_char && !*(str + 1)) {                                                                \
01678                score->canmatch = 1;                                                                                 \
01679                score->canmatch_exten = get_canmatch_exten(p);                                                       \
01680                if (action == E_CANMATCH || action == E_MATCHMORE) {                                                 \
01681                     ast_debug(4, "returning a canmatch/matchmore--- str=%s\n", str);                                 \
01682                   return;                                                                                          \
01683                }                                                                                        \
01684             }
01685 
01686             NEW_MATCHER_CHK_MATCH;
01687             NEW_MATCHER_RECURSE;
01688          }
01689       } else if (p->x[0] == 'Z') {
01690          if (p->x[1] == 0 && *str >= '1' && *str <= '9' ) {
01691             NEW_MATCHER_CHK_MATCH;
01692             NEW_MATCHER_RECURSE;
01693          }
01694       } else if (p->x[0] == 'X') {
01695          if (p->x[1] == 0 && *str >= '0' && *str <= '9' ) {
01696             NEW_MATCHER_CHK_MATCH;
01697             NEW_MATCHER_RECURSE;
01698          }
01699       } else if (p->x[0] == '.' && p->x[1] == 0) {
01700          /* how many chars will the . match against? */
01701          int i = 0;
01702          const char *str2 = str;
01703          while (*str2 && *str2 != '/') {
01704             str2++;
01705             i++;
01706          }
01707          if (p->exten && *str2 != '/') {
01708             update_scoreboard(score, length+i, spec+(i*p->specificity), p->exten, '.', callerid, p->deleted, p);
01709             if (score->exten) {
01710                ast_debug(4,"return because scoreboard has a match with '/'--- %s\n", score->exten->exten);
01711                return; /* the first match is all we need */
01712             }
01713          }
01714          if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) {
01715             new_find_extension("/", score, p->next_char, length+i, spec+(p->specificity*i), callerid, label, action);
01716             if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) {
01717                ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set--- %s\n", score->exten ? score->exten->exten : "NULL");
01718                return; /* the first match is all we need */
01719             }
01720          }
01721       } else if (p->x[0] == '!' && p->x[1] == 0) {
01722          /* how many chars will the . match against? */
01723          int i = 1;
01724          const char *str2 = str;
01725          while (*str2 && *str2 != '/') {
01726             str2++;
01727             i++;
01728          }
01729          if (p->exten && *str2 != '/') {
01730             update_scoreboard(score, length + 1, spec+(p->specificity * i), p->exten, '!', callerid, p->deleted, p);
01731             if (score->exten) {
01732                ast_debug(4, "return because scoreboard has a '!' match--- %s\n", score->exten->exten);
01733                return; /* the first match is all we need */
01734             }
01735          }
01736          if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) {
01737             new_find_extension("/", score, p->next_char, length + i, spec + (p->specificity * i), callerid, label, action);
01738             if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) {
01739                ast_debug(4,"return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set with '/' and '!'--- %s\n", score->exten ? score->exten->exten : "NULL");
01740                return; /* the first match is all we need */
01741             }
01742          }
01743       } else if (p->x[0] == '/' && p->x[1] == 0) {
01744          /* the pattern in the tree includes the cid match! */
01745          if (p->next_char && callerid && *callerid) {
01746             new_find_extension(callerid, score, p->next_char, length+1, spec, callerid, label, action);
01747             if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) {
01748                ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set with '/'--- %s\n", score->exten ? score->exten->exten : "NULL");
01749                return; /* the first match is all we need */
01750             }
01751          }
01752       } else if (strchr(p->x, *str)) {
01753          ast_debug(4, "Nothing strange about this match\n");
01754          NEW_MATCHER_CHK_MATCH;
01755          NEW_MATCHER_RECURSE;
01756       }
01757    }
01758    ast_debug(4, "return at end of func\n");
01759 }

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

Referenced by pbx_retrieve_variable(), and pbx_substitute_variables_helper_full().

02793 {
02794    int parens = 0;
02795 
02796    *offset = 0;
02797    *length = INT_MAX;
02798    *isfunc = 0;
02799    for (; *var; var++) {
02800       if (*var == '(') {
02801          (*isfunc)++;
02802          parens++;
02803       } else if (*var == ')') {
02804          parens--;
02805       } else if (*var == ':' && parens == 0) {
02806          *var++ = '\0';
02807          sscanf(var, "%30d:%30d", offset, length);
02808          return 1; /* offset:length valid */
02809       }
02810    }
02811    return 0;
02812 }

void pbx_builtin_clear_globals ( void   ) 

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

09183 {
09184    struct ast_var_t *vardata;
09185 
09186    ast_rwlock_wrlock(&globalslock);
09187    while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries)))
09188       ast_var_delete(vardata);
09189    ast_rwlock_unlock(&globalslock);
09190 }

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

Return a pointer to the value of the corresponding channel variable.

Note:
Will lock the channel.
This function will return a pointer to the buffer inside the channel variable. This value should only be accessed with the channel locked. If the value needs to be kept around, it should be done by using the following thread-safe code:
      const char *var;

      ast_channel_lock(chan);
      if ((var = pbx_builtin_getvar_helper(chan, "MYVAR"))) {
         var = ast_strdupa(var);
      }
      ast_channel_unlock(chan);

Definition at line 8951 of file pbx.c.

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

Referenced by __ast_pbx_run(), _macro_exec(), _while_exec(), agent_hangup(), agent_read(), agentmonitoroutgoing_exec(), array(), ast_bridge_call(), ast_call_forward(), ast_eivr_getvariable(), ast_monitor_stop(), bridge_play_sounds(), builtin_atxfer(), builtin_automixmonitor(), builtin_automonitor(), check_goto_on_transfer(), common_exec(), conf_exec(), conf_run(), confbridge_exec(), dahdi_call(), dahdi_hangup(), dial_exec_full(), do_forward(), do_timelimit(), dundi_exec(), dundi_helper(), feature_interpret(), find_by_mark(), find_conf_realtime(), findparkinglotname(), get_also_info(), get_index(), get_refer_info(), global_read(), hash_read(), iax2_call(), iax2_exec(), import_ch(), leave_voicemail(), listfilter(), local_attended_transfer(), local_hangup(), local_read(), login_exec(), macro_fixup(), minivm_delete_exec(), minivm_notify_exec(), misdn_answer(), misdn_hangup(), morsecode_exec(), notify_new_message(), oh323_call(), oh323_hangup(), park_call_full(), park_space_reserve(), pbx_builtin_background(), 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(), update_bridge_vars(), and wait_for_answer().

08952 {
08953    struct ast_var_t *variables;
08954    const char *ret = NULL;
08955    int i;
08956    struct varshead *places[2] = { NULL, &globals };
08957 
08958    if (!name)
08959       return NULL;
08960 
08961    if (chan) {
08962       ast_channel_lock(chan);
08963       places[0] = &chan->varshead;
08964    }
08965 
08966    for (i = 0; i < 2; i++) {
08967       if (!places[i])
08968          continue;
08969       if (places[i] == &globals)
08970          ast_rwlock_rdlock(&globalslock);
08971       AST_LIST_TRAVERSE(places[i], variables, entries) {
08972          if (!strcmp(name, ast_var_name(variables))) {
08973             ret = ast_var_value(variables);
08974             break;
08975          }
08976       }
08977       if (places[i] == &globals)
08978          ast_rwlock_unlock(&globalslock);
08979       if (ret)
08980          break;
08981    }
08982 
08983    if (chan)
08984       ast_channel_unlock(chan);
08985 
08986    return ret;
08987 }

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

Definition at line 9204 of file pbx.c.

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

09205 {
09206    char *condition, *branch1, *branch2, *branch;
09207    char *stringp;
09208 
09209    if (ast_strlen_zero(data)) {
09210       ast_log(LOG_WARNING, "Ignoring, since there is no variable to check\n");
09211       return 0;
09212    }
09213 
09214    stringp = ast_strdupa(data);
09215    condition = strsep(&stringp,"?");
09216    branch1 = strsep(&stringp,":");
09217    branch2 = strsep(&stringp,"");
09218    branch = pbx_checkcondition(condition) ? branch1 : branch2;
09219 
09220    if (ast_strlen_zero(branch)) {
09221       ast_debug(1, "Not taking any branch\n");
09222       return 0;
09223    }
09224 
09225    return pbx_builtin_goto(chan, branch);
09226 }

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

Todo:
XXX should do !ast_strlen_zero(..) of the args ?

Definition at line 9140 of file pbx.c.

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

09141 {
09142    char *name;
09143    char *value;
09144    char *channel;
09145    char tmp[VAR_BUF_SIZE];
09146    static int deprecation_warning = 0;
09147 
09148    if (ast_strlen_zero(data)) {
09149       ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n");
09150       return 0;
09151    }
09152    tmp[0] = 0;
09153    if (!deprecation_warning) {
09154       ast_log(LOG_WARNING, "ImportVar is deprecated.  Please use Set(varname=${IMPORT(channel,variable)}) instead.\n");
09155       deprecation_warning = 1;
09156    }
09157 
09158    value = ast_strdupa(data);
09159    name = strsep(&value,"=");
09160    channel = strsep(&value,",");
09161    if (channel && value && name) { /*! \todo XXX should do !ast_strlen_zero(..) of the args ? */
09162       struct ast_channel *chan2 = ast_get_channel_by_name_locked(channel);
09163       if (chan2) {
09164          char *s = alloca(strlen(value) + 4);
09165          if (s) {
09166             sprintf(s, "${%s}", value);
09167             pbx_substitute_variables_helper(chan2, s, tmp, sizeof(tmp) - 1);
09168          }
09169          ast_channel_unlock(chan2);
09170       }
09171       pbx_builtin_setvar_helper(chan, name, tmp);
09172    }
09173 
09174    return(0);
09175 }

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

Definition at line 8536 of file pbx.c.

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

08537 {
08538    char *options = data;
08539    int answer = 1;
08540 
08541    /* Some channels can receive DTMF in unanswered state; some cannot */
08542    if (!ast_strlen_zero(options) && strchr(options, 'n')) {
08543       answer = 0;
08544    }
08545 
08546    /* If the channel is hungup, stop waiting */
08547    if (ast_check_hangup(chan)) {
08548       return -1;
08549    } else if (chan->_state != AST_STATE_UP && answer) {
08550       __ast_answer(chan, 0, 1);
08551    }
08552 
08553    return AST_PBX_INCOMPLETE;
08554 }

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

Definition at line 9177 of file pbx.c.

09178 {
09179    return 0;
09180 }

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

Add a variable to the channel variable stack, without removing any previously set value.

Note:
Will lock the channel.

Definition at line 8989 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_var_assign(), ast_verb, globals, globalslock, LOG_WARNING, and ast_channel::varshead.

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

08990 {
08991    struct ast_var_t *newvariable;
08992    struct varshead *headp;
08993 
08994    if (name[strlen(name)-1] == ')') {
08995       char *function = ast_strdupa(name);
08996 
08997       ast_log(LOG_WARNING, "Cannot push a value onto a function\n");
08998       ast_func_write(chan, function, value);
08999       return;
09000    }
09001 
09002    if (chan) {
09003       ast_channel_lock(chan);
09004       headp = &chan->varshead;
09005    } else {
09006       ast_rwlock_wrlock(&globalslock);
09007       headp = &globals;
09008    }
09009 
09010    if (value) {
09011       if (headp == &globals)
09012          ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value);
09013       newvariable = ast_var_assign(name, value);
09014       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
09015    }
09016 
09017    if (chan)
09018       ast_channel_unlock(chan);
09019    else
09020       ast_rwlock_unlock(&globalslock);
09021 }

int pbx_builtin_raise_exception ( struct ast_channel chan,
void *  vreason 
)

Definition at line 2995 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, ast_channel::context, ast_datastore::data, exception_store_info, ast_channel::exten, ast_channel::priority, pbx_exception::priority, and set_ext_pri().

Referenced by __ast_pbx_run().

02996 {
02997    const char *reason = vreason;
02998    struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL);
02999    struct pbx_exception *exception = NULL;
03000 
03001    if (!ds) {
03002       ds = ast_datastore_alloc(&exception_store_info, NULL);
03003       if (!ds)
03004          return -1;
03005       exception = ast_calloc(1, sizeof(struct pbx_exception));
03006       if (!exception) {
03007          ast_datastore_free(ds);
03008          return -1;
03009       }
03010       if (ast_string_field_init(exception, 128)) {
03011          ast_free(exception);
03012          ast_datastore_free(ds);
03013          return -1;
03014       }
03015       ds->data = exception;
03016       ast_channel_datastore_add(chan, ds);
03017    } else
03018       exception = ds->data;
03019 
03020    ast_string_field_set(exception, reason, reason);
03021    ast_string_field_set(exception, context, chan->context);
03022    ast_string_field_set(exception, exten, chan->exten);
03023    exception->priority = chan->priority;
03024    set_ext_pri(chan, "e", 0);
03025    return 0;
03026 }

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

Definition at line 9265 of file pbx.c.

References ast_say_character_str(), and ast_channel::language.

09266 {
09267    int res = 0;
09268 
09269    if (data)
09270       res = ast_say_character_str(chan, data, "", chan->language);
09271    return res;
09272 }

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

Definition at line 9256 of file pbx.c.

References ast_say_digit_str(), and ast_channel::language.

09257 {
09258    int res = 0;
09259 
09260    if (data)
09261       res = ast_say_digit_str(chan, data, "", chan->language);
09262    return res;
09263 }

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

Definition at line 9228 of file pbx.c.

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

09229 {
09230    char tmp[256];
09231    char *number = tmp;
09232    char *options;
09233 
09234    if (ast_strlen_zero(data)) {
09235       ast_log(LOG_WARNING, "SayNumber requires an argument (number)\n");
09236       return -1;
09237    }
09238    ast_copy_string(tmp, data, sizeof(tmp));
09239    strsep(&number, ",");
09240    options = strsep(&number, ",");
09241    if (options) {
09242       if ( strcasecmp(options, "f") && strcasecmp(options, "m") &&
09243          strcasecmp(options, "c") && strcasecmp(options, "n") ) {
09244          ast_log(LOG_WARNING, "SayNumber gender option is either 'f', 'm', 'c' or 'n'\n");
09245          return -1;
09246       }
09247    }
09248 
09249    if (ast_say_number(chan, atoi(tmp), "", chan->language, options)) {
09250       ast_log(LOG_WARNING, "We were unable to say the number %s, is it too large?\n", tmp);
09251    }
09252 
09253    return 0;
09254 }

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

Definition at line 9274 of file pbx.c.

References ast_say_phonetic_str(), and ast_channel::language.

09275 {
09276    int res = 0;
09277 
09278    if (data)
09279       res = ast_say_phonetic_str(chan, data, "", chan->language);
09280    return res;
09281 }

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

Create a human-readable string, specifying all variables and their corresponding values.

Parameters:
chan Channel from which to read variables
buf Dynamic string in which to place the result (should be allocated with
See also:
ast_str_create).
Note:
Will lock the channel.

Definition at line 8920 of file pbx.c.

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

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

08921 {
08922    struct ast_var_t *variables;
08923    const char *var, *val;
08924    int total = 0;
08925 
08926    if (!chan)
08927       return 0;
08928 
08929    ast_str_reset(*buf);
08930 
08931    ast_channel_lock(chan);
08932 
08933    AST_LIST_TRAVERSE(&chan->varshead, variables, entries) {
08934       if ((var = ast_var_name(variables)) && (val = ast_var_value(variables))
08935          /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */
08936          ) {
08937          if (ast_str_append(buf, 0, "%s=%s\n", var, val) < 0) {
08938             ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
08939             break;
08940          } else
08941             total++;
08942       } else
08943          break;
08944    }
08945 
08946    ast_channel_unlock(chan);
08947 
08948    return total;
08949 }

int pbx_builtin_setvar ( struct ast_channel chan,
void *  data 
)

Parse and set a single channel variable, where the name and value are separated with an '=' character.

Note:
Will lock the channel.

Definition at line 9081 of file pbx.c.

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

Referenced by ast_compile_ael2(), and rpt_exec().

09082 {
09083    char *name, *value, *mydata;
09084 
09085    if (ast_compat_app_set) {
09086       return pbx_builtin_setvar_multiple(chan, data);
09087    }
09088 
09089    if (ast_strlen_zero(data)) {
09090       ast_log(LOG_WARNING, "Set requires one variable name/value pair.\n");
09091       return 0;
09092    }
09093 
09094    mydata = ast_strdupa(data);
09095    name = strsep(&mydata, "=");
09096    value = mydata;
09097    if (strchr(name, ' '))
09098       ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, mydata);
09099 
09100    pbx_builtin_setvar_helper(chan, name, value);
09101    return(0);
09102 }

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

Add a variable to the channel variable stack, removing the most recently set value for the same name.

Note:
Will lock the channel. May also be used to set a channel dialplan function to a particular value.
See also:
ast_func_write

Definition at line 9023 of file pbx.c.

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

Referenced by __ast_pbx_run(), __oh323_new(), _macro_exec(), _while_exec(), acf_curl_exec(), acf_fetch(), acf_odbc_read(), acf_odbc_write(), acf_transaction_write(), action_atxfer(), action_setvar(), admin_exec(), agi_exec_full(), aji_status_exec(), aqm_exec(), array(), ast_bridge_call(), ast_eivr_setvariable(), 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(), commit_exec(), conf_run(), controlplayback_exec(), count_exec(), dahdi_handle_dtmfup(), dahdi_new(), dial_exec_full(), disa_exec(), do_waiting(), end_bridge_callback(), export_aoc_vars(), export_ch(), feature_request_and_dial(), 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(), originate_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(), pri_dchannel(), privacy_exec(), process_ast_dsp(), read_exec(), readexten_exec(), readfile_exec(), realtimefield_read(), record_exec(), return_exec(), rollback_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(), sip_read(), skinny_new(), sla_calc_trunk_timeouts(), sla_station_exec(), sla_trunk_exec(), socket_process(), speech_create(), ss7_start_call(), 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().

09024 {
09025    struct ast_var_t *newvariable;
09026    struct varshead *headp;
09027    const char *nametail = name;
09028 
09029    if (name[strlen(name) - 1] == ')') {
09030       char *function = ast_strdupa(name);
09031 
09032       ast_func_write(chan, function, value);
09033       return;
09034    }
09035 
09036    if (chan) {
09037       ast_channel_lock(chan);
09038       headp = &chan->varshead;
09039    } else {
09040       ast_rwlock_wrlock(&globalslock);
09041       headp = &globals;
09042    }
09043 
09044    /* For comparison purposes, we have to strip leading underscores */
09045    if (*nametail == '_') {
09046       nametail++;
09047       if (*nametail == '_')
09048          nametail++;
09049    }
09050 
09051    AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) {
09052       if (strcasecmp(ast_var_name(newvariable), nametail) == 0) {
09053          /* there is already such a variable, delete it */
09054          AST_LIST_REMOVE_CURRENT(entries);
09055          ast_var_delete(newvariable);
09056          break;
09057       }
09058    }
09059    AST_LIST_TRAVERSE_SAFE_END;
09060 
09061    if (value) {
09062       if (headp == &globals)
09063          ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value);
09064       newvariable = ast_var_assign(name, value);
09065       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
09066       manager_event(EVENT_FLAG_DIALPLAN, "VarSet",
09067          "Channel: %s\r\n"
09068          "Variable: %s\r\n"
09069          "Value: %s\r\n"
09070          "Uniqueid: %s\r\n",
09071          chan ? chan->name : "none", name, value,
09072          chan ? chan->uniqueid : "none");
09073    }
09074 
09075    if (chan)
09076       ast_channel_unlock(chan);
09077    else
09078       ast_rwlock_unlock(&globalslock);
09079 }

int pbx_builtin_setvar_multiple ( struct ast_channel chan,
void *  vdata 
)

Parse and set multiple channel variables, where the pairs are separated by the ',' character, and name and value are separated with an '=' character.

Note:
Will lock the channel.

Definition at line 9104 of file pbx.c.

References AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), AST_NONSTANDARD_APP_ARGS, AST_STANDARD_APP_ARGS, ast_strlen_zero(), 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().

09105 {
09106    char *data;
09107    int x;
09108    AST_DECLARE_APP_ARGS(args,
09109       AST_APP_ARG(pair)[24];
09110    );
09111    AST_DECLARE_APP_ARGS(pair,
09112       AST_APP_ARG(name);
09113       AST_APP_ARG(value);
09114    );
09115 
09116    if (ast_strlen_zero(vdata)) {
09117       ast_log(LOG_WARNING, "MSet requires at least one variable name/value pair.\n");
09118       return 0;
09119    }
09120 
09121    data = ast_strdupa(vdata);
09122    AST_STANDARD_APP_ARGS(args, data);
09123 
09124    for (x = 0; x < args.argc; x++) {
09125       AST_NONSTANDARD_APP_ARGS(pair, args.pair[x], '=');
09126       if (pair.argc == 2) {
09127          pbx_builtin_setvar_helper(chan, pair.name, pair.value);
09128          if (strchr(pair.name, ' '))
09129             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);
09130       } else if (!chan) {
09131          ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '='\n", pair.name);
09132       } else {
09133          ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '=' (in %s@%s:%d\n", pair.name, chan->exten, chan->context, chan->priority);
09134       }
09135    }
09136 
09137    return 0;
09138 }

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

09193 {
09194    int res;
09195    if (ast_strlen_zero(condition)) {                /* NULL or empty strings are false */
09196       return 0;
09197    } else if (sscanf(condition, "%30d", &res) == 1) { /* Numbers are evaluated for truth */
09198       return res;
09199    } else {                                         /* Strings are true */
09200       return 1;
09201    }
09202 }

static void pbx_destroy ( struct ast_pbx p  )  [static]

Definition at line 1399 of file pbx.c.

References ast_free.

Referenced by __ast_pbx_run().

01400 {
01401    ast_free(p);
01402 }

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.

Return values:
0 success
-1 failure
Parameters:
c Channel
app Application
data Data for execution

Definition at line 1322 of file pbx.c.

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

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

01325 {
01326    int res;
01327    struct ast_module_user *u = NULL;
01328    const char *saved_c_appl;
01329    const char *saved_c_data;
01330 
01331    if (c->cdr && !ast_check_hangup(c))
01332       ast_cdr_setapp(c->cdr, app->name, data);
01333 
01334    /* save channel values */
01335    saved_c_appl= c->appl;
01336    saved_c_data= c->data;
01337 
01338    c->appl = app->name;
01339    c->data = data;
01340    if (app->module)
01341       u = __ast_module_user_add(app->module, c);
01342    if (strcasecmp(app->name, "system") && !ast_strlen_zero(data) &&
01343          strchr(data, '|') && !strchr(data, ',') && !ast_opt_dont_warn) {
01344       ast_log(LOG_WARNING, "The application delimiter is now the comma, not "
01345          "the pipe.  Did you forget to convert your dialplan?  (%s(%s))\n",
01346          app->name, (char *) data);
01347    }
01348    res = app->execute(c, S_OR((char *) data, ""));
01349    if (app->module && u)
01350       __ast_module_user_remove(app->module, u);
01351    /* restore channel values */
01352    c->appl = saved_c_appl;
01353    c->data = saved_c_data;
01354    return res;
01355 }

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 3647 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, ast_app::name, pbx_exec(), pbx_find_extension(), pbx_findapp(), pbx_substitute_variables(), ast_channel::priority, ast_exten::priority, S_OR, pbx_find_info::stacklen, pbx_find_info::status, STATUS_NO_CONTEXT, STATUS_NO_EXTENSION, STATUS_NO_LABEL, STATUS_NO_PRIORITY, pbx_find_info::swo, term_color(), 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().

03650 {
03651    struct ast_exten *e;
03652    struct ast_app *app;
03653    int res;
03654    struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */
03655    char passdata[EXT_DATA_SIZE];
03656 
03657    int matching_action = (action == E_MATCH || action == E_CANMATCH || action == E_MATCHMORE);
03658 
03659    ast_rdlock_contexts();
03660    if (found)
03661       *found = 0;
03662 
03663    e = pbx_find_extension(c, con, &q, context, exten, priority, label, callerid, action);
03664    if (e) {
03665       if (found)
03666          *found = 1;
03667       if (matching_action) {
03668          ast_unlock_contexts();
03669          return -1;  /* success, we found it */
03670       } else if (action == E_FINDLABEL) { /* map the label to a priority */
03671          res = e->priority;
03672          ast_unlock_contexts();
03673          return res; /* the priority we were looking for */
03674       } else { /* spawn */
03675          if (!e->cached_app)
03676             e->cached_app = pbx_findapp(e->app);
03677          app = e->cached_app;
03678          ast_unlock_contexts();
03679          if (!app) {
03680             ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority);
03681             return -1;
03682          }
03683          if (c->context != context)
03684             ast_copy_string(c->context, context, sizeof(c->context));
03685          if (c->exten != exten)
03686             ast_copy_string(c->exten, exten, sizeof(c->exten));
03687          c->priority = priority;
03688          pbx_substitute_variables(passdata, sizeof(passdata), c, e);
03689 #ifdef CHANNEL_TRACE
03690          ast_channel_trace_update(c);
03691 #endif
03692          ast_debug(1, "Launching '%s'\n", app->name);
03693          if (VERBOSITY_ATLEAST(3)) {
03694             char tmp[80], tmp2[80], tmp3[EXT_DATA_SIZE];
03695             ast_verb(3, "Executing [%s@%s:%d] %s(\"%s\", \"%s\") %s\n",
03696                exten, context, priority,
03697                term_color(tmp, app->name, COLOR_BRCYAN, 0, sizeof(tmp)),
03698                term_color(tmp2, c->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)),
03699                term_color(tmp3, passdata, COLOR_BRMAGENTA, 0, sizeof(tmp3)),
03700                "in new stack");
03701          }
03702          manager_event(EVENT_FLAG_DIALPLAN, "Newexten",
03703                "Channel: %s\r\n"
03704                "Context: %s\r\n"
03705                "Extension: %s\r\n"
03706                "Priority: %d\r\n"
03707                "Application: %s\r\n"
03708                "AppData: %s\r\n"
03709                "Uniqueid: %s\r\n",
03710                c->name, c->context, c->exten, c->priority, app->name, passdata, c->uniqueid);
03711          return pbx_exec(c, app, passdata);  /* 0 on success, -1 on failure */
03712       }
03713    } else if (q.swo) {  /* not found here, but in another switch */
03714       if (found)
03715          *found = 1;
03716       ast_unlock_contexts();
03717       if (matching_action) {
03718          return -1;
03719       } else {
03720          if (!q.swo->exec) {
03721             ast_log(LOG_WARNING, "No execution engine for switch %s\n", q.swo->name);
03722             res = -1;
03723          }
03724          return q.swo->exec(c, q.foundcontext ? q.foundcontext : context, exten, priority, callerid, q.data);
03725       }
03726    } else { /* not found anywhere, see what happened */
03727       ast_unlock_contexts();
03728       /* Using S_OR here because Solaris doesn't like NULL being passed to ast_log */
03729       switch (q.status) {
03730       case STATUS_NO_CONTEXT:
03731          if (!matching_action && !combined_find_spawn)
03732             ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", S_OR(context, ""));
03733          break;
03734       case STATUS_NO_EXTENSION:
03735          if (!matching_action && !combined_find_spawn)
03736             ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, S_OR(context, ""));
03737          break;
03738       case STATUS_NO_PRIORITY:
03739          if (!matching_action && !combined_find_spawn)
03740             ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, S_OR(context, ""));
03741          break;
03742       case STATUS_NO_LABEL:
03743          if (context && !combined_find_spawn)
03744             ast_log(LOG_NOTICE, "No such label '%s' in extension '%s' in context '%s'\n", label, exten, S_OR(context, ""));
03745          break;
03746       default:
03747          ast_debug(1, "Shouldn't happen!\n");
03748       }
03749 
03750       return (matching_action) ? 0 : -1;
03751    }
03752 }

struct ast_exten* pbx_find_extension ( struct ast_channel chan,
struct ast_context bypass,
struct pbx_find_info q,
const char *  context,
const char *  exten,
int  priority,
const char *  label,
const char *  callerid,
enum ext_match_t  action 
) [read]

Definition at line 2469 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_buffer(), ast_str_size(), ast_str_thread_get(), ast_strlen_zero(), ast_walk_context_extensions(), ast_walk_contexts(), ast_walk_extension_priorities(), ast_switch::canmatch, scoreboard::canmatch_exten, contexts_table, create_match_char_tree(), ast_sw::data, pbx_find_info::data, E_CANMATCH, E_FINDLABEL, E_MATCHMORE, ast_sw::eval, ast_switch::exists, ast_exten::exten, scoreboard::exten, extenpatternmatchnew, extension_match_core(), pbx_find_info::foundcontext, include_valid(), ast_context::includes, pbx_find_info::incstack, ast_exten::label, scoreboard::last_char, LOG_DEBUG, log_match_char_tree(), LOG_NOTICE, LOG_WARNING, match(), matchcid(), ast_switch::matchmore, ast_sw::name, ast_context::name, fake_context::name, new_find_extension(), ast_include::next, scoreboard::node, overrideswitch, ast_context::pattern_tree, pbx_find_extension(), pbx_findswitch(), pbx_substitute_variables_helper(), ast_exten::priority, ast_include::rname, ast_context::root_table, pbx_find_info::stacklen, pbx_find_info::status, STATUS_NO_CONTEXT, STATUS_NO_EXTENSION, STATUS_NO_LABEL, STATUS_NO_PRIORITY, STATUS_SUCCESS, switch_data, pbx_find_info::swo, scoreboard::total_length, scoreboard::total_specificity, and trie_find_next_match().

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

02473 {
02474    int x, res;
02475    struct ast_context *tmp = NULL;
02476    struct ast_exten *e = NULL, *eroot = NULL;
02477    struct ast_include *i = NULL;
02478    struct ast_sw *sw = NULL;
02479    struct ast_exten pattern = {NULL, };
02480    struct scoreboard score = {0, };
02481    struct ast_str *tmpdata = NULL;
02482 
02483    pattern.label = label;
02484    pattern.priority = priority;
02485 #ifdef NEED_DEBUG_HERE
02486    ast_log(LOG_NOTICE, "Looking for cont/ext/prio/label/action = %s/%s/%d/%s/%d\n", context, exten, priority, label, (int) action);
02487 #endif
02488 
02489    /* Initialize status if appropriate */
02490    if (q->stacklen == 0) {
02491       q->status = STATUS_NO_CONTEXT;
02492       q->swo = NULL;
02493       q->data = NULL;
02494       q->foundcontext = NULL;
02495    } else if (q->stacklen >= AST_PBX_MAX_STACK) {
02496       ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n");
02497       return NULL;
02498    }
02499 
02500    /* Check first to see if we've already been checked */
02501    for (x = 0; x < q->stacklen; x++) {
02502       if (!strcasecmp(q->incstack[x], context))
02503          return NULL;
02504    }
02505 
02506    if (bypass) { /* bypass means we only look there */
02507       tmp = bypass;
02508    } else {      /* look in contexts */
02509       struct fake_context item;
02510 
02511       ast_copy_string(item.name, context, sizeof(item.name));
02512 
02513       tmp = ast_hashtab_lookup(contexts_table, &item);
02514 #ifdef NOTNOW
02515       tmp = NULL;
02516       while ((tmp = ast_walk_contexts(tmp)) ) {
02517          if (!strcmp(tmp->name, context)) {
02518             break;
02519          }
02520       }
02521 #endif
02522       if (!tmp) {
02523          return NULL;
02524       }
02525    }
02526 
02527    if (q->status < STATUS_NO_EXTENSION)
02528       q->status = STATUS_NO_EXTENSION;
02529 
02530    /* Do a search for matching extension */
02531 
02532    eroot = NULL;
02533    score.total_specificity = 0;
02534    score.exten = 0;
02535    score.total_length = 0;
02536    if (!tmp->pattern_tree && tmp->root_table) {
02537       create_match_char_tree(tmp);
02538 #ifdef NEED_DEBUG
02539       ast_log(LOG_DEBUG, "Tree Created in context %s:\n", context);
02540       log_match_char_tree(tmp->pattern_tree," ");
02541 #endif
02542    }
02543 #ifdef NEED_DEBUG
02544    ast_log(LOG_NOTICE, "The Trie we are searching in:\n");
02545    log_match_char_tree(tmp->pattern_tree, "::  ");
02546 #endif
02547 
02548    do {
02549       if (!ast_strlen_zero(overrideswitch)) {
02550          char *osw = ast_strdupa(overrideswitch), *name;
02551          struct ast_switch *asw;
02552          ast_switch_f *aswf = NULL;
02553          char *datap;
02554          int eval = 0;
02555 
02556          name = strsep(&osw, "/");
02557          asw = pbx_findswitch(name);
02558 
02559          if (!asw) {
02560             ast_log(LOG_WARNING, "No such switch '%s'\n", name);
02561             break;
02562          }
02563 
02564          if (osw && strchr(osw, '$')) {
02565             eval = 1;
02566          }
02567 
02568          if (eval && !(tmpdata = ast_str_thread_get(&switch_data, 512))) {
02569             ast_log(LOG_WARNING, "Can't evaluate overrideswitch?!");
02570             break;
02571          } else if (eval) {
02572             /* Substitute variables now */
02573             pbx_substitute_variables_helper(chan, osw, ast_str_buffer(tmpdata), ast_str_size(tmpdata));
02574             datap = ast_str_buffer(tmpdata);
02575          } else {
02576             datap = osw;
02577          }
02578 
02579          /* equivalent of extension_match_core() at the switch level */
02580          if (action == E_CANMATCH)
02581             aswf = asw->canmatch;
02582          else if (action == E_MATCHMORE)
02583             aswf = asw->matchmore;
02584          else /* action == E_MATCH */
02585             aswf = asw->exists;
02586          if (!aswf) {
02587             res = 0;
02588          } else {
02589             if (chan) {
02590                ast_autoservice_start(chan);
02591             }
02592             res = aswf(chan, context, exten, priority, callerid, datap);
02593             if (chan) {
02594                ast_autoservice_stop(chan);
02595             }
02596          }
02597          if (res) {  /* Got a match */
02598             q->swo = asw;
02599             q->data = datap;
02600             q->foundcontext = context;
02601             /* XXX keep status = STATUS_NO_CONTEXT ? */
02602             return NULL;
02603          }
02604       }
02605    } while (0);
02606 
02607    if (extenpatternmatchnew) {
02608       new_find_extension(exten, &score, tmp->pattern_tree, 0, 0, callerid, label, action);
02609       eroot = score.exten;
02610 
02611       if (score.last_char == '!' && action == E_MATCHMORE) {
02612          /* We match an extension ending in '!'.
02613           * The decision in this case is final and is NULL (no match).
02614           */
02615 #ifdef NEED_DEBUG_HERE
02616          ast_log(LOG_NOTICE,"Returning MATCHMORE NULL with exclamation point.\n");
02617 #endif
02618          return NULL;
02619       }
02620 
02621       if (!eroot && (action == E_CANMATCH || action == E_MATCHMORE) && score.canmatch_exten) {
02622          q->status = STATUS_SUCCESS;
02623 #ifdef NEED_DEBUG_HERE
02624          ast_log(LOG_NOTICE,"Returning CANMATCH exten %s\n", score.canmatch_exten->exten);
02625 #endif
02626          return score.canmatch_exten;
02627       }
02628 
02629       if ((action == E_MATCHMORE || action == E_CANMATCH)  && eroot) {
02630          if (score.node) {
02631             struct ast_exten *z = trie_find_next_match(score.node);
02632             if (z) {
02633 #ifdef NEED_DEBUG_HERE
02634                ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten %s\n", z->exten);
02635 #endif
02636             } else {
02637                if (score.canmatch_exten) {
02638 #ifdef NEED_DEBUG_HERE
02639                   ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE canmatchmatch exten %s(%p)\n", score.canmatch_exten->exten, score.canmatch_exten);
02640 #endif
02641                   return score.canmatch_exten;
02642                } else {
02643 #ifdef NEED_DEBUG_HERE
02644                   ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten NULL\n");
02645 #endif
02646                }
02647             }
02648             return z;
02649          }
02650 #ifdef NEED_DEBUG_HERE
02651          ast_log(LOG_NOTICE, "Returning CANMATCH/MATCHMORE NULL (no next_match)\n");
02652 #endif
02653          return NULL;  /* according to the code, complete matches are null matches in MATCHMORE mode */
02654       }
02655 
02656       if (eroot) {
02657          /* found entry, now look for the right priority */
02658          if (q->status < STATUS_NO_PRIORITY)
02659             q->status = STATUS_NO_PRIORITY;
02660          e = NULL;
02661          if (action == E_FINDLABEL && label ) {
02662             if (q->status < STATUS_NO_LABEL)
02663                q->status = STATUS_NO_LABEL;
02664             e = ast_hashtab_lookup(eroot->peer_label_table, &pattern);
02665          } else {
02666             e = ast_hashtab_lookup(eroot->peer_table, &pattern);
02667          }
02668          if (e) { /* found a valid match */
02669             q->status = STATUS_SUCCESS;
02670             q->foundcontext = context;
02671 #ifdef NEED_DEBUG_HERE
02672             ast_log(LOG_NOTICE,"Returning complete match of exten %s\n", e->exten);
02673 #endif
02674             return e;
02675          }
02676       }
02677    } else {   /* the old/current default exten pattern match algorithm */
02678 
02679       /* scan the list trying to match extension and CID */
02680       eroot = NULL;
02681       while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) {
02682          int match = extension_match_core(eroot->exten, exten, action);
02683          /* 0 on fail, 1 on match, 2 on earlymatch */
02684 
02685          if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid)))
02686             continue;   /* keep trying */
02687          if (match == 2 && action == E_MATCHMORE) {
02688             /* We match an extension ending in '!'.
02689              * The decision in this case is final and is NULL (no match).
02690              */
02691             return NULL;
02692          }
02693          /* found entry, now look for the right priority */
02694          if (q->status < STATUS_NO_PRIORITY)
02695             q->status = STATUS_NO_PRIORITY;
02696          e = NULL;
02697          if (action == E_FINDLABEL && label ) {
02698             if (q->status < STATUS_NO_LABEL)
02699                q->status = STATUS_NO_LABEL;
02700             e = ast_hashtab_lookup(eroot->peer_label_table, &pattern);
02701          } else {
02702             e = ast_hashtab_lookup(eroot->peer_table, &pattern);
02703          }
02704 #ifdef NOTNOW
02705          while ( (e = ast_walk_extension_priorities(eroot, e)) ) {
02706             /* Match label or priority */
02707             if (action == E_FINDLABEL) {
02708                if (q->status < STATUS_NO_LABEL)
02709                   q->status = STATUS_NO_LABEL;
02710                if (label && e->label && !strcmp(label, e->label))
02711                   break;   /* found it */
02712             } else if (e->priority == priority) {
02713                break;   /* found it */
02714             } /* else keep searching */
02715          }
02716 #endif
02717          if (e) { /* found a valid match */
02718             q->status = STATUS_SUCCESS;
02719             q->foundcontext = context;
02720             return e;
02721          }
02722       }
02723    }
02724 
02725    /* Check alternative switches */
02726    AST_LIST_TRAVERSE(&tmp->alts, sw, list) {
02727       struct ast_switch *asw = pbx_findswitch(sw->name);
02728       ast_switch_f *aswf = NULL;
02729       char *datap;
02730 
02731       if (!asw) {
02732          ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name);
02733          continue;
02734       }
02735 
02736       /* Substitute variables now */
02737       if (sw->eval) {
02738          if (!(tmpdata = ast_str_thread_get(&switch_data, 512))) {
02739             ast_log(LOG_WARNING, "Can't evaluate switch?!");
02740             continue;
02741          }
02742          pbx_substitute_variables_helper(chan, sw->data, ast_str_buffer(tmpdata), ast_str_size(tmpdata));
02743       }
02744 
02745       /* equivalent of extension_match_core() at the switch level */
02746       if (action == E_CANMATCH)
02747          aswf = asw->canmatch;
02748       else if (action == E_MATCHMORE)
02749          aswf = asw->matchmore;
02750       else /* action == E_MATCH */
02751          aswf = asw->exists;
02752       datap = sw->eval ? ast_str_buffer(tmpdata) : sw->data;
02753       if (!aswf)
02754          res = 0;
02755       else {
02756          if (chan)
02757             ast_autoservice_start(chan);
02758          res = aswf(chan, context, exten, priority, callerid, datap);
02759          if (chan)
02760             ast_autoservice_stop(chan);
02761       }
02762       if (res) {  /* Got a match */
02763          q->swo = asw;
02764          q->data = datap;
02765          q->foundcontext = context;
02766          /* XXX keep status = STATUS_NO_CONTEXT ? */
02767          return NULL;
02768       }
02769    }
02770    q->incstack[q->stacklen++] = tmp->name;   /* Setup the stack */
02771    /* Now try any includes we have in this context */
02772    for (i = tmp->includes; i; i = i->next) {
02773       if (include_valid(i)) {
02774          if ((e = pbx_find_extension(chan, bypass, q, i->rname, exten, priority, label, callerid, action))) {
02775 #ifdef NEED_DEBUG_HERE
02776             ast_log(LOG_NOTICE,"Returning recursive match of %s\n", e->exten);
02777 #endif
02778             return e;
02779          }
02780          if (q->swo)
02781             return NULL;
02782       }
02783    }
02784    return NULL;
02785 }

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

Definition at line 1377 of file pbx.c.

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

Referenced by pbx_find_extension().

01378 {
01379    struct ast_switch *asw;
01380 
01381    AST_RWLIST_RDLOCK(&switches);
01382    AST_RWLIST_TRAVERSE(&switches, asw, list) {
01383       if (!strcasecmp(asw->name, sw))
01384          break;
01385    }
01386    AST_RWLIST_UNLOCK(&switches);
01387 
01388    return asw;
01389 }

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

Definition at line 9580 of file pbx.c.

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

Referenced by ast_async_parseable_goto(), and ast_parseable_goto().

09581 {
09582    char *exten, *pri, *context;
09583    char *stringp;
09584    int ipri;
09585    int mode = 0;
09586 
09587    if (ast_strlen_zero(goto_string)) {
09588       ast_log(LOG_WARNING, "Goto requires an argument ([[context,]extension,]priority)\n");
09589       return -1;
09590    }
09591    stringp = ast_strdupa(goto_string);
09592    context = strsep(&stringp, ","); /* guaranteed non-null */
09593    exten = strsep(&stringp, ",");
09594    pri = strsep(&stringp, ",");
09595    if (!exten) {  /* Only a priority in this one */
09596       pri = context;
09597       exten = NULL;
09598       context = NULL;
09599    } else if (!pri) {   /* Only an extension and priority in this one */
09600       pri = exten;
09601       exten = context;
09602       context = NULL;
09603    }
09604    if (*pri == '+') {
09605       mode = 1;
09606       pri++;
09607    } else if (*pri == '-') {
09608       mode = -1;
09609       pri++;
09610    }
09611    if (sscanf(pri, "%30d", &ipri) != 1) {
09612       if ((ipri = ast_findlabel_extension(chan, context ? context : chan->context, exten ? exten : chan->exten,
09613          pri, chan->cid.cid_num)) < 1) {
09614          ast_log(LOG_WARNING, "Priority '%s' must be a number > 0, or valid label\n", pri);
09615          return -1;
09616       } else
09617          mode = 0;
09618    }
09619    /* At this point we have a priority and maybe an extension and a context */
09620 
09621    if (mode)
09622       ipri = chan->priority + (ipri * mode);
09623 
09624    if (async)
09625       ast_async_goto(chan, context, exten, ipri);
09626    else
09627       ast_explicit_goto(chan, context, exten, ipri);
09628 
09629    return 0;
09630 
09631 }

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

Support for Asterisk built-in variables in the dialplan.

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

Note:
See also

Definition at line 2867 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_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_var_t::entries, ast_channel::exten, globals, globalslock, ast_channel::hangupcause, ast_channel::name, parse_variable_name(), ast_channel::priority, s, substring(), ast_channel::uniqueid, and ast_channel::varshead.

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

02868 {
02869    const char not_found = '\0';
02870    char *tmpvar;
02871    const char *s; /* the result */
02872    int offset, length;
02873    int i, need_substring;
02874    struct varshead *places[2] = { headp, &globals };  /* list of places where we may look */
02875 
02876    if (c) {
02877       ast_channel_lock(c);
02878       places[0] = &c->varshead;
02879    }
02880    /*
02881     * Make a copy of var because parse_variable_name() modifies the string.
02882     * Then if called directly, we might need to run substring() on the result;
02883     * remember this for later in 'need_substring', 'offset' and 'length'
02884     */
02885    tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */
02886    need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */);
02887 
02888    /*
02889     * Look first into predefined variables, then into variable lists.
02890     * Variable 's' points to the result, according to the following rules:
02891     * s == &not_found (set at the beginning) means that we did not find a
02892     * matching variable and need to look into more places.
02893     * If s != &not_found, s is a valid result string as follows:
02894     * s = NULL if the variable does not have a value;
02895     * you typically do this when looking for an unset predefined variable.
02896     * s = workspace if the result has been assembled there;
02897     * typically done when the result is built e.g. with an snprintf(),
02898     * so we don't need to do an additional copy.
02899     * s != workspace in case we have a string, that needs to be copied
02900     * (the ast_copy_string is done once for all at the end).
02901     * Typically done when the result is already available in some string.
02902     */
02903    s = &not_found;   /* default value */
02904    if (c) { /* This group requires a valid channel */
02905       /* Names with common parts are looked up a piece at a time using strncmp. */
02906       if (!strncmp(var, "CALL", 4)) {
02907          if (!strncmp(var + 4, "ING", 3)) {
02908             if (!strcmp(var + 7, "PRES")) {        /* CALLINGPRES */
02909                snprintf(workspace, workspacelen, "%d", c->cid.cid_pres);
02910                s = workspace;
02911             } else if (!strcmp(var + 7, "ANI2")) {    /* CALLINGANI2 */
02912                snprintf(workspace, workspacelen, "%d", c->cid.cid_ani2);
02913                s = workspace;
02914             } else if (!strcmp(var + 7, "TON")) {     /* CALLINGTON */
02915                snprintf(workspace, workspacelen, "%d", c->cid.cid_ton);
02916                s = workspace;
02917             } else if (!strcmp(var + 7, "TNS")) {     /* CALLINGTNS */
02918                snprintf(workspace, workspacelen, "%d", c->cid.cid_tns);
02919                s = workspace;
02920             }
02921          }
02922       } else if (!strcmp(var, "HINT")) {
02923          s = ast_get_hint(workspace, workspacelen, NULL, 0, c, c->context, c->exten) ? workspace : NULL;
02924       } else if (!strcmp(var, "HINTNAME")) {
02925          s = ast_get_hint(NULL, 0, workspace, workspacelen, c, c->context, c->exten) ? workspace : NULL;
02926       } else if (!strcmp(var, "EXTEN")) {
02927          s = c->exten;
02928       } else if (!strcmp(var, "CONTEXT")) {
02929          s = c->context;
02930       } else if (!strcmp(var, "PRIORITY")) {
02931          snprintf(workspace, workspacelen, "%d", c->priority);
02932          s = workspace;
02933       } else if (!strcmp(var, "CHANNEL")) {
02934          s = c->name;
02935       } else if (!strcmp(var, "UNIQUEID")) {
02936          s = c->uniqueid;
02937       } else if (!strcmp(var, "HANGUPCAUSE")) {
02938          snprintf(workspace, workspacelen, "%d", c->hangupcause);
02939          s = workspace;
02940       }
02941    }
02942    if (s == &not_found) { /* look for more */
02943       if (!strcmp(var, "EPOCH")) {
02944          snprintf(workspace, workspacelen, "%u",(int)time(NULL));
02945          s = workspace;
02946       } else if (!strcmp(var, "SYSTEMNAME")) {
02947          s = ast_config_AST_SYSTEM_NAME;
02948       } else if (!strcmp(var, "ENTITYID")) {
02949          ast_eid_to_str(workspace, workspacelen, &ast_eid_default);
02950          s = workspace;
02951       }
02952    }
02953    /* if not found, look into chanvars or global vars */
02954    for (i = 0; s == &not_found && i < ARRAY_LEN(places); i++) {
02955       struct ast_var_t *variables;
02956       if (!places[i])
02957          continue;
02958       if (places[i] == &globals)
02959          ast_rwlock_rdlock(&globalslock);
02960       AST_LIST_TRAVERSE(places[i], variables, entries) {
02961          if (!strcasecmp(ast_var_name(variables), var)) {
02962             s = ast_var_value(variables);
02963             break;
02964          }
02965       }
02966       if (places[i] == &globals)
02967          ast_rwlock_unlock(&globalslock);
02968    }
02969    if (s == &not_found || s == NULL)
02970       *ret = NULL;
02971    else {
02972       if (s != workspace)
02973          ast_copy_string(workspace, s, workspacelen);
02974       *ret = workspace;
02975       if (need_substring)
02976          *ret = substring(*ret, offset, length, workspace, workspacelen);
02977    }
02978 
02979    if (c)
02980       ast_channel_unlock(c);
02981 }

int pbx_set_autofallthrough ( int  newval  ) 

Set "autofallthrough" flag, if newval is <0, does not actually set. If set to 1, sets to auto fall through. If newval set to 0, sets to no auto fall through (reads extension instead). Returns previous value.

Definition at line 4611 of file pbx.c.

References autofallthrough.

Referenced by pbx_load_module().

04612 {
04613    int oldval = autofallthrough;
04614    autofallthrough = newval;
04615    return oldval;
04616 }

int pbx_set_extenpatternmatchnew ( int  newval  ) 

Set "extenpatternmatchnew" flag, if newval is <0, does not actually set. If set to 1, sets to use the new Trie-based pattern matcher. If newval set to 0, sets to use the old linear-search algorithm. Returns previous value.

Definition at line 4618 of file pbx.c.

References extenpatternmatchnew.

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

04619 {
04620    int oldval = extenpatternmatchnew;
04621    extenpatternmatchnew = newval;
04622    return oldval;
04623 }

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

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

Referenced by pbx_load_module().

04626 {
04627    if (overrideswitch) {
04628       ast_free(overrideswitch);
04629    }
04630    if (!ast_strlen_zero(newval)) {
04631       overrideswitch = ast_strdup(newval);
04632    } else {
04633       overrideswitch = NULL;
04634    }
04635 }

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

Definition at line 3610 of file pbx.c.

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

Referenced by pbx_extension_helper().

03611 {
03612    const char *tmp;
03613 
03614    /* Nothing more to do */
03615    if (!e->data) {
03616       *passdata = '\0';
03617       return;
03618    }
03619 
03620    /* No variables or expressions in e->data, so why scan it? */
03621    if ((!(tmp = strchr(e->data, '$'))) || (!strstr(tmp, "${") && !strstr(tmp, "$["))) {
03622       ast_copy_string(passdata, e->data, datalen);
03623       return;
03624    }
03625 
03626    pbx_substitute_variables_helper(c, e->data, passdata, datalen - 1);
03627 }

void pbx_substitute_variables_helper ( struct ast_channel c,
const char *  cp1,
char *  cp2,
int  count 
)
void pbx_substitute_variables_helper_full ( struct ast_channel c,
struct varshead headp,
const char *  cp1,
char *  cp2,
int  count,
size_t *  used 
)

Definition at line 3403 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(), pbx_substitute_variables_helper_full(), substring(), var, VAR_BUF_SIZE, and ast_channel::varshead.

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

03404 {
03405    /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!!  */
03406    char *cp4;
03407    const char *tmp, *whereweare, *orig_cp2 = cp2;
03408    int length, offset, offset2, isfunction;
03409    char *workspace = NULL;
03410    char *ltmp = NULL, *var = NULL;
03411    char *nextvar, *nextexp, *nextthing;
03412    char *vars, *vare;
03413    int pos, brackets, needsub, len;
03414 
03415    *cp2 = 0; /* just in case nothing ends up there */
03416    whereweare=tmp=cp1;
03417    while (!ast_strlen_zero(whereweare) && count) {
03418       /* Assume we're copying the whole remaining string */
03419       pos = strlen(whereweare);
03420       nextvar = NULL;
03421       nextexp = NULL;
03422       nextthing = strchr(whereweare, '$');
03423       if (nextthing) {
03424          switch (nextthing[1]) {
03425          case '{':
03426             nextvar = nextthing;
03427             pos = nextvar - whereweare;
03428             break;
03429          case '[':
03430             nextexp = nextthing;
03431             pos = nextexp - whereweare;
03432             break;
03433          default:
03434             pos = 1;
03435          }
03436       }
03437 
03438       if (pos) {
03439          /* Can't copy more than 'count' bytes */
03440          if (pos > count)
03441             pos = count;
03442 
03443          /* Copy that many bytes */
03444          memcpy(cp2, whereweare, pos);
03445 
03446          count -= pos;
03447          cp2 += pos;
03448          whereweare += pos;
03449          *cp2 = 0;
03450       }
03451 
03452       if (nextvar) {
03453          /* We have a variable.  Find the start and end, and determine
03454             if we are going to have to recursively call ourselves on the
03455             contents */
03456          vars = vare = nextvar + 2;
03457          brackets = 1;
03458          needsub = 0;
03459 
03460          /* Find the end of it */
03461          while (brackets && *vare) {
03462             if ((vare[0] == '$') && (vare[1] == '{')) {
03463                needsub++;
03464             } else if (vare[0] == '{') {
03465                brackets++;
03466             } else if (vare[0] == '}') {
03467                brackets--;
03468             } else if ((vare[0] == '$') && (vare[1] == '['))
03469                needsub++;
03470             vare++;
03471          }
03472          if (brackets)
03473             ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n");
03474          len = vare - vars - 1;
03475 
03476          /* Skip totally over variable string */
03477          whereweare += (len + 3);
03478 
03479          if (!var)
03480             var = alloca(VAR_BUF_SIZE);
03481 
03482          /* Store variable name (and truncate) */
03483          ast_copy_string(var, vars, len + 1);
03484 
03485          /* Substitute if necessary */
03486          if (needsub) {
03487             size_t used;
03488             if (!ltmp)
03489                ltmp = alloca(VAR_BUF_SIZE);
03490 
03491             pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used);
03492             vars = ltmp;
03493          } else {
03494             vars = var;
03495          }
03496 
03497          if (!workspace)
03498             workspace = alloca(VAR_BUF_SIZE);
03499 
03500          workspace[0] = '\0';
03501 
03502          parse_variable_name(vars, &offset, &offset2, &isfunction);
03503          if (isfunction) {
03504             /* Evaluate function */
03505             if (c || !headp)
03506                cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
03507             else {
03508                struct varshead old;
03509                struct ast_channel *bogus = ast_channel_alloc(0, 0, "", "", "", "", "", 0, "Bogus/%p", vars);
03510                if (bogus) {
03511                   memcpy(&old, &bogus->varshead, sizeof(old));
03512                   memcpy(&bogus->varshead, headp, sizeof(bogus->varshead));
03513                   cp4 = ast_func_read(bogus, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
03514                   /* Don't deallocate the varshead that was passed in */
03515                   memcpy(&bogus->varshead, &old, sizeof(bogus->varshead));
03516                   ast_channel_free(bogus);
03517                } else
03518                   ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution.  Function results may be blank.\n");
03519             }
03520             ast_debug(2, "Function result is '%s'\n", cp4 ? cp4 : "(null)");
03521          } else {
03522             /* Retrieve variable value */
03523             pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp);
03524          }
03525          if (cp4) {
03526             cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE);
03527 
03528             length = strlen(cp4);
03529             if (length > count)
03530                length = count;
03531             memcpy(cp2, cp4, length);
03532             count -= length;
03533             cp2 += length;
03534             *cp2 = 0;
03535          }
03536       } else if (nextexp) {
03537          /* We have an expression.  Find the start and end, and determine
03538             if we are going to have to recursively call ourselves on the
03539             contents */
03540          vars = vare = nextexp + 2;
03541          brackets = 1;
03542          needsub = 0;
03543 
03544          /* Find the end of it */
03545          while (brackets && *vare) {
03546             if ((vare[0] == '$') && (vare[1] == '[')) {
03547                needsub++;
03548                brackets++;
03549                vare++;
03550             } else if (vare[0] == '[') {
03551                brackets++;
03552             } else if (vare[0] == ']') {
03553                brackets--;
03554             } else if ((vare[0] == '$') && (vare[1] == '{')) {
03555                needsub++;
03556                vare++;
03557             }
03558             vare++;
03559          }
03560          if (brackets)
03561             ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n");
03562          len = vare - vars - 1;
03563 
03564          /* Skip totally over expression */
03565          whereweare += (len + 3);
03566 
03567          if (!var)
03568             var = alloca(VAR_BUF_SIZE);
03569 
03570          /* Store variable name (and truncate) */
03571          ast_copy_string(var, vars, len + 1);
03572 
03573          /* Substitute if necessary */
03574          if (needsub) {
03575             size_t used;
03576             if (!ltmp)
03577                ltmp = alloca(VAR_BUF_SIZE);
03578 
03579             pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used);
03580             vars = ltmp;
03581          } else {
03582             vars = var;
03583          }
03584 
03585          length = ast_expr(vars, cp2, count, c);
03586 
03587          if (length) {
03588             ast_debug(1, "Expression result is '%s'\n", cp2);
03589             count -= length;
03590             cp2 += length;
03591             *cp2 = 0;
03592          }
03593       }
03594    }
03595    *used = cp2 - orig_cp2;
03596 }

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

Definition at line 3604 of file pbx.c.

References pbx_substitute_variables_helper_full().

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

03605 {
03606    size_t used;
03607    pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count, &used);
03608 }

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

Definition at line 4539 of file pbx.c.

References __ast_pbx_run(), and decrease_call_count().

Referenced by ast_pbx_start().

04540 {
04541    /* Oh joyeous kernel, we're a new thread, with nothing to do but
04542       answer this channel and get it going.
04543    */
04544    /* NOTE:
04545       The launcher of this function _MUST_ increment 'countcalls'
04546       before invoking the function; it will be decremented when the
04547       PBX has finished running on the channel
04548     */
04549    struct ast_channel *c = data;
04550 
04551    __ast_pbx_run(c, NULL);
04552    decrease_call_count();
04553 
04554    pthread_exit(NULL);
04555 
04556    return NULL;
04557 }

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

Definition at line 5186 of file pbx.c.

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

Referenced by handle_show_application().

05187 {
05188    /* Maximum number of characters added by terminal coloring is 22 */
05189    char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40], stxtitle[40], argtitle[40];
05190    char seealsotitle[40];
05191    char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL, *syntax = NULL, *arguments = NULL;
05192    char *seealso = NULL;
05193    int syntax_size, synopsis_size, description_size, arguments_size, seealso_size;
05194 
05195    snprintf(info, sizeof(info), "\n  -= Info about application '%s' =- \n\n", aa->name);
05196    term_color(infotitle, info, COLOR_MAGENTA, 0, sizeof(infotitle));
05197 
05198    term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
05199    term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
05200    term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40);
05201    term_color(argtitle, "[Arguments]\n", COLOR_MAGENTA, 0, 40);
05202    term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, 40);
05203 
05204 #ifdef AST_XML_DOCS
05205    if (aa->docsrc == AST_XML_DOC) {
05206       description = ast_xmldoc_printable(S_OR(aa->description, "Not available"), 1);
05207       arguments = ast_xmldoc_printable(S_OR(aa->arguments, "Not available"), 1);
05208       synopsis = ast_xmldoc_printable(S_OR(aa->synopsis, "Not available"), 1);
05209       seealso = ast_xmldoc_printable(S_OR(aa->seealso, "Not available"), 1);
05210 
05211       if (!synopsis || !description || !arguments || !seealso) {
05212          goto return_cleanup;
05213       }
05214    } else
05215 #endif
05216    {
05217       synopsis_size = strlen(S_OR(aa->synopsis, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
05218       synopsis = ast_malloc(synopsis_size);
05219 
05220       description_size = strlen(S_OR(aa->description, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
05221       description = ast_malloc(description_size);
05222 
05223       arguments_size = strlen(S_OR(aa->arguments, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
05224       arguments = ast_malloc(arguments_size);
05225 
05226       seealso_size = strlen(S_OR(aa->seealso, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
05227       seealso = ast_malloc(seealso_size);
05228 
05229       if (!synopsis || !description || !arguments || !seealso) {
05230          goto return_cleanup;
05231       }
05232 
05233       term_color(synopsis, S_OR(aa->synopsis, "Not available"), COLOR_CYAN, 0, synopsis_size);
05234       term_color(description, S_OR(aa->description, "Not available"),   COLOR_CYAN, 0, description_size);
05235       term_color(arguments, S_OR(aa->arguments, "Not available"), COLOR_CYAN, 0, arguments_size);
05236       term_color(seealso, S_OR(aa->seealso, "Not available"), COLOR_CYAN, 0, seealso_size);
05237    }
05238 
05239    /* Handle the syntax the same for both XML and raw docs */
05240    syntax_size = strlen(S_OR(aa->syntax, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
05241    if (!(syntax = ast_malloc(syntax_size))) {
05242       goto return_cleanup;
05243    }
05244    term_color(syntax, S_OR(aa->syntax, "Not available"), COLOR_CYAN, 0, syntax_size);
05245 
05246    ast_cli(fd, "%s%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n",
05247          infotitle, syntitle, synopsis, destitle, description,
05248          stxtitle, syntax, argtitle, arguments, seealsotitle, seealso);
05249 
05250 return_cleanup:
05251    ast_free(description);
05252    ast_free(arguments);
05253    ast_free(synopsis);
05254    ast_free(seealso);
05255    ast_free(syntax);
05256 }

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

helper function to print an extension

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

05608 {
05609    int prio = ast_get_extension_priority(e);
05610    if (prio == PRIORITY_HINT) {
05611       snprintf(buf, buflen, "hint: %s",
05612          ast_get_extension_app(e));
05613    } else {
05614       snprintf(buf, buflen, "%d. %s(%s)",
05615          prio, ast_get_extension_app(e),
05616          (!ast_strlen_zero(ast_get_extension_app_data(e)) ? (char *)ast_get_extension_app_data(e) : ""));
05617    }
05618 }

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

04175 {
04176    ast_channel_lock(c);
04177    ast_copy_string(c->exten, exten, sizeof(c->exten));
04178    c->priority = pri;
04179    ast_channel_unlock(c);
04180 }

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

05773 {
05774    struct ast_context *c = NULL;
05775    int res = 0, old_total_exten = dpc->total_exten;
05776 
05777    ast_cli(fd,"\n     In-mem exten Trie for Fast Extension Pattern Matching:\n\n");
05778 
05779    ast_cli(fd,"\n           Explanation: Node Contents Format = <char(s) to match>:<pattern?>:<specif>:[matched extension]\n");
05780    ast_cli(fd,    "                        Where <char(s) to match> is a set of chars, any one of which should match the current character\n");
05781    ast_cli(fd,    "                              <pattern?>: Y if this a pattern match (eg. _XZN[5-7]), N otherwise\n");
05782    ast_cli(fd,    "                              <specif>: an assigned 'exactness' number for this matching char. The lower the number, the more exact the match\n");
05783    ast_cli(fd,    "                              [matched exten]: If all chars matched to this point, which extension this matches. In form: EXTEN:<exten string>\n");
05784    ast_cli(fd,    "                        In general, you match a trie node to a string character, from left to right. All possible matching chars\n");
05785    ast_cli(fd,    "                        are in a string vertically, separated by an unbroken string of '+' characters.\n\n");
05786    ast_rdlock_contexts();
05787 
05788    /* walk all contexts ... */
05789    while ( (c = ast_walk_contexts(c)) ) {
05790       int context_info_printed = 0;
05791 
05792       if (context && strcmp(ast_get_context_name(c), context))
05793          continue;   /* skip this one, name doesn't match */
05794 
05795       dpc->context_existence = 1;
05796 
05797       if (!c->pattern_tree)
05798          ast_exists_extension(NULL, c->name, "s", 1, ""); /* do this to force the trie to built, if it is not already */
05799 
05800       ast_rdlock_context(c);
05801 
05802       dpc->total_context++;
05803       ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
05804          ast_get_context_name(c), ast_get_context_registrar(c));
05805       context_info_printed = 1;
05806 
05807       if (c->pattern_tree)
05808       {
05809          cli_match_char_tree(c->pattern_tree, " ", fd);
05810       } else {
05811          ast_cli(fd,"\n     No Pattern Trie present. Perhaps the context is empty...or there is trouble...\n\n");
05812       }
05813 
05814       ast_unlock_context(c);
05815 
05816       /* if we print something in context, make an empty line */
05817       if (context_info_printed)
05818          ast_cli(fd, "\n");
05819    }
05820    ast_unlock_contexts();
05821 
05822    return (dpc->total_exten == old_total_exten) ? -1 : res;
05823 }

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 5621 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, buf2, ast_exten::cidmatch, dialplan_counters::context_existence, el, dialplan_counters::extension_existence, LOG_WARNING, ast_exten::matchcid, print_ext(), dialplan_counters::total_context, dialplan_counters::total_exten, and dialplan_counters::total_prio.

Referenced by handle_show_dialplan().

05622 {
05623    struct ast_context *c = NULL;
05624    int res = 0, old_total_exten = dpc->total_exten;
05625 
05626    ast_rdlock_contexts();
05627 
05628    /* walk all contexts ... */
05629    while ( (c = ast_walk_contexts(c)) ) {
05630       struct ast_exten *e;
05631       struct ast_include *i;
05632       struct ast_ignorepat *ip;
05633       char buf[256], buf2[256];
05634       int context_info_printed = 0;
05635 
05636       if (context && strcmp(ast_get_context_name(c), context))
05637          continue;   /* skip this one, name doesn't match */
05638 
05639       dpc->context_existence = 1;
05640 
05641       ast_rdlock_context(c);
05642 
05643       /* are we looking for exten too? if yes, we print context
05644        * only if we find our extension.
05645        * Otherwise print context even if empty ?
05646        * XXX i am not sure how the rinclude is handled.
05647        * I think it ought to go inside.
05648        */
05649       if (!exten) {
05650          dpc->total_context++;
05651          ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
05652             ast_get_context_name(c), ast_get_context_registrar(c));
05653          context_info_printed = 1;
05654       }
05655 
05656       /* walk extensions ... */
05657       e = NULL;
05658       while ( (e = ast_walk_context_extensions(c, e)) ) {
05659          struct ast_exten *p;
05660 
05661          if (exten && !ast_extension_match(ast_get_extension_name(e), exten))
05662             continue;   /* skip, extension match failed */
05663 
05664          dpc->extension_existence = 1;
05665 
05666          /* may we print context info? */
05667          if (!context_info_printed) {
05668             dpc->total_context++;
05669             if (rinclude) { /* TODO Print more info about rinclude */
05670                ast_cli(fd, "[ Included context '%s' created by '%s' ]\n",
05671                   ast_get_context_name(c), ast_get_context_registrar(c));
05672             } else {
05673                ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
05674                   ast_get_context_name(c), ast_get_context_registrar(c));
05675             }
05676             context_info_printed = 1;
05677          }
05678          dpc->total_prio++;
05679 
05680          /* write extension name and first peer */
05681          if (e->matchcid)
05682             snprintf(buf, sizeof(buf), "'%s' (CID match '%s') => ", ast_get_extension_name(e), e->cidmatch);
05683          else
05684             snprintf(buf, sizeof(buf), "'%s' =>", ast_get_extension_name(e));
05685 
05686          print_ext(e, buf2, sizeof(buf2));
05687 
05688          ast_cli(fd, "  %-17s %-45s [%s]\n", buf, buf2,
05689             ast_get_extension_registrar(e));
05690 
05691          dpc->total_exten++;
05692          /* walk next extension peers */
05693          p = e;   /* skip the first one, we already got it */
05694          while ( (p = ast_walk_extension_priorities(e, p)) ) {
05695             const char *el = ast_get_extension_label(p);
05696             dpc->total_prio++;
05697             if (el)
05698                snprintf(buf, sizeof(buf), "   [%s]", el);
05699             else
05700                buf[0] = '\0';
05701             print_ext(p, buf2, sizeof(buf2));
05702 
05703             ast_cli(fd,"  %-17s %-45s [%s]\n", buf, buf2,
05704                ast_get_extension_registrar(p));
05705          }
05706       }
05707 
05708       /* walk included and write info ... */
05709       i = NULL;
05710       while ( (i = ast_walk_context_includes(c, i)) ) {
05711          snprintf(buf, sizeof(buf), "'%s'", ast_get_include_name(i));
05712          if (exten) {
05713             /* Check all includes for the requested extension */
05714             if (includecount >= AST_PBX_MAX_STACK) {
05715                ast_log(LOG_WARNING, "Maximum include depth exceeded!\n");
05716             } else {
05717                int dupe = 0;
05718                int x;
05719                for (x = 0; x < includecount; x++) {
05720                   if (!strcasecmp(includes[x], ast_get_include_name(i))) {
05721                      dupe++;
05722                      break;
05723                   }
05724                }
05725                if (!dupe) {
05726                   includes[includecount] = ast_get_include_name(i);
05727                   show_dialplan_helper(fd, ast_get_include_name(i), exten, dpc, i, includecount + 1, includes);
05728                } else {
05729                   ast_log(LOG_WARNING, "Avoiding circular include of %s within %s\n", ast_get_include_name(i), context);
05730                }
05731             }
05732          } else {
05733             ast_cli(fd, "  Include =>        %-45s [%s]\n",
05734                buf, ast_get_include_registrar(i));
05735          }
05736       }
05737 
05738       /* walk ignore patterns and write info ... */
05739       ip = NULL;
05740       while ( (ip = ast_walk_context_ignorepats(c, ip)) ) {
05741          const char *ipname = ast_get_ignorepat_name(ip);
05742          char ignorepat[AST_MAX_EXTENSION];
05743          snprintf(buf, sizeof(buf), "'%s'", ipname);
05744          snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname);
05745          if (!exten || ast_extension_match(ignorepat, exten)) {
05746             ast_cli(fd, "  Ignore pattern => %-45s [%s]\n",
05747                buf, ast_get_ignorepat_registrar(ip));
05748          }
05749       }
05750       if (!rinclude) {
05751          struct ast_sw *sw = NULL;
05752          while ( (sw = ast_walk_context_switches(c, sw)) ) {
05753             snprintf(buf, sizeof(buf), "'%s/%s'",
05754                ast_get_switch_name(sw),
05755                ast_get_switch_data(sw));
05756             ast_cli(fd, "  Alt. Switch =>    %-45s [%s]\n",
05757                buf, ast_get_switch_registrar(sw));
05758          }
05759       }
05760 
05761       ast_unlock_context(c);
05762 
05763       /* if we print something in context, make an empty line */
05764       if (context_info_printed)
05765          ast_cli(fd, "\n");
05766    }
05767    ast_unlock_contexts();
05768 
05769    return (dpc->total_exten == old_total_exten) ? -1 : res;
05770 }

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

References ast_copy_string().

Referenced by pbx_retrieve_variable(), and pbx_substitute_variables_helper_full().

02826 {
02827    char *ret = workspace;
02828    int lr;  /* length of the input string after the copy */
02829 
02830    ast_copy_string(workspace, value, workspace_len); /* always make a copy */
02831 
02832    lr = strlen(ret); /* compute length after copy, so we never go out of the workspace */
02833 
02834    /* Quick check if no need to do anything */
02835    if (offset == 0 && length >= lr) /* take the whole string */
02836       return ret;
02837 
02838    if (offset < 0)   {  /* translate negative offset into positive ones */
02839       offset = lr + offset;
02840       if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */
02841          offset = 0;
02842    }
02843 
02844    /* too large offset result in empty string so we know what to return */
02845    if (offset >= lr)
02846       return ret + lr;  /* the final '\0' */
02847 
02848    ret += offset;    /* move to the start position */
02849    if (length >= 0 && length < lr - offset)  /* truncate if necessary */
02850       ret[length] = '\0';
02851    else if (length < 0) {
02852       if (lr > offset - length) /* After we remove from the front and from the rear, is there anything left? */
02853          ret[lr + length - offset] = '\0';
02854       else
02855          ret[0] = '\0';
02856    }
02857 
02858    return ret;
02859 }

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

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

01572 {
01573    struct match_char *m3;
01574    struct match_char *m4;
01575    struct ast_exten *e3;
01576 
01577    if (node && node->x[0] == '.' && !node->x[1]) { /* dot and ! will ALWAYS be next match in a matchmore */
01578       return node->exten;
01579    }
01580 
01581    if (node && node->x[0] == '!' && !node->x[1]) {
01582       return node->exten;
01583    }
01584 
01585    if (!node || !node->next_char) {
01586       return NULL;
01587    }
01588 
01589    m3 = node->next_char;
01590 
01591    if (m3->exten) {
01592       return m3->exten;
01593    }
01594    for (m4 = m3->alt_char; m4; m4 = m4->alt_char) {
01595       if (m4->exten) {
01596          return m4->exten;
01597       }
01598    }
01599    for (m4 = m3; m4; m4 = m4->alt_char) {
01600       e3 = trie_find_next_match(m3);
01601       if (e3) {
01602          return e3;
01603       }
01604    }
01605    return NULL;
01606 }

static void unreference_cached_app ( struct ast_app app  )  [static]

Definition at line 6384 of file pbx.c.

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

Referenced by ast_unregister_application().

06385 {
06386    struct ast_context *context = NULL;
06387    struct ast_exten *eroot = NULL, *e = NULL;
06388 
06389    ast_rdlock_contexts();
06390    while ((context = ast_walk_contexts(context))) {
06391       while ((eroot = ast_walk_context_extensions(context, eroot))) {
06392          while ((e = ast_walk_extension_priorities(eroot, e))) {
06393             if (e->cached_app == app)
06394                e->cached_app = NULL;
06395          }
06396       }
06397    }
06398    ast_unlock_contexts();
06399 
06400    return;
06401 }

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

References ast_log(), ast_exten::exten, scoreboard::exten, scoreboard::last_char, LOG_NOTICE, scoreboard::node, scoreboard::total_length, and scoreboard::total_specificity.

Referenced by new_find_extension().

01479 {
01480    /* if this extension is marked as deleted, then skip this -- if it never shows
01481       on the scoreboard, it will never be found, nor will halt the traversal. */
01482    if (deleted)
01483       return;
01484    board->total_specificity = spec;
01485    board->total_length = length;
01486    board->exten = exten;
01487    board->last_char = last;
01488    board->node = node;
01489 #ifdef NEED_DEBUG_HERE
01490    ast_log(LOG_NOTICE,"Scoreboarding (LONGER) %s, len=%d, score=%d\n", exten->exten, length, spec);
01491 #endif
01492 }

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

Definition at line 8422 of file pbx.c.

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

Referenced by pbx_builtin_busy(), and pbx_builtin_congestion().

08423 {
08424    int res;
08425    struct ast_frame *f;
08426    double waitsec;
08427    int waittime;
08428 
08429    if (ast_strlen_zero(data) || (sscanf(data, "%30lg", &waitsec) != 1) || (waitsec < 0))
08430       waitsec = -1;
08431    if (waitsec > -1) {
08432       waittime = waitsec * 1000.0;
08433       ast_safe_sleep(chan, waittime);
08434    } else do {
08435       res = ast_waitfor(chan, -1);
08436       if (res < 0)
08437          return;
08438       f = ast_read(chan);
08439       if (f)
08440          ast_frfree(f);
08441    } while(f);
08442 }


Variable Documentation

int autofallthrough = 1 [static]

Definition at line 1069 of file pbx.c.

Referenced by __ast_pbx_run(), and pbx_set_autofallthrough().

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

Definition at line 745 of file pbx.c.

Referenced by pbx_builtin_background().

struct pbx_builtin builtins[] [static]

Declaration of builtin applications.

Referenced by load_pbx().

ast_rwlock_t conlock = PTHREAD_RWLOCK_INITIALIZER [static]

Lock for the ast_context list

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

Referenced by ast_wrlock_contexts(), and ast_wrlock_contexts_version().

struct ast_context* contexts [static]
struct ast_hashtab* contexts_table = NULL [static]
int countcalls [static]

Definition at line 1077 of file pbx.c.

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

char* days[] [static]

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

Referenced by load_pbx().

Definition at line 758 of file pbx.c.

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

Definition at line 3048 of file pbx.c.

Referenced by load_pbx().

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

Definition at line 2990 of file pbx.c.

Referenced by acf_exception_read(), and pbx_builtin_raise_exception().

int extenpatternmatchnew = 0 [static]

Definition at line 1070 of file pbx.c.

Referenced by pbx_find_extension(), and pbx_set_extenpatternmatchnew().

Referenced by ast_extension_state2str().

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

Definition at line 761 of file pbx.c.

Referenced by ast_extension_state2().

struct varshead globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE [static]
ast_rwlock_t globalslock = PTHREAD_RWLOCK_INITIALIZER [static]
char mandescr_show_dialplan[] [static]

Definition at line 6147 of file pbx.c.

Referenced by load_pbx().

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

Definition at line 1076 of file pbx.c.

Referenced by decrease_call_count(), and increase_call_count().

char* months[] [static]

Definition at line 6922 of file pbx.c.

Referenced by ast_build_timing().

char* overrideswitch = NULL [static]

Definition at line 1071 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 6363 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 8561 of file pbx.c.

Referenced by pbx_builtin_resetcdr().

int stateid = 1 [static]

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

Referenced by pbx_find_extension().

int totalcalls [static]

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

Referenced by pbx_builtin_waitexten().


Generated by  doxygen 1.6.2