Wed Aug 18 22:34:27 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/stringfields.h"
#include "asterisk/event.h"
#include "asterisk/hashtab.h"
#include "asterisk/module.h"
#include "asterisk/indications.h"
#include "asterisk/taskprocessor.h"

Go to the source code of this file.

Data Structures

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

Defines

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

Functions

void __ast_context_destroy (struct ast_context *list, struct ast_hashtab *contexttab, struct ast_context *con, const char *registrar)
int __ast_custom_function_register (struct ast_custom_function *acf, struct ast_module *mod)
 Register a custom function.
static int __ast_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority, int async)
static void __ast_internal_context_destroy (struct ast_context *con)
static enum ast_pbx_result __ast_pbx_run (struct ast_channel *c, struct ast_pbx_args *args)
static void __init_switch_data (void)
static int _extension_match_core (const char *pattern, const char *data, enum ext_match_t mode)
static int acf_exception_read (struct ast_channel *chan, const char *name, char *data, char *buf, size_t buflen)
static struct match_charadd_exten_to_pattern_tree (struct ast_context *con, struct ast_exten *e1, int findonly)
static struct match_charadd_pattern_node (struct ast_context *con, struct match_char *current, char *pattern, int is_pattern, int already, int specificity, struct match_char **parent)
static int add_pri (struct ast_context *con, struct ast_exten *tmp, struct ast_exten *el, struct ast_exten *e, int replace)
 add the extension in the priority chain.
static int add_pri_lockopt (struct ast_context *con, struct ast_exten *tmp, struct ast_exten *el, struct ast_exten *e, int replace, int lockhints)
 add the extension in the priority chain.
static struct match_charalready_in_tree (struct match_char *current, char *pat)
int ast_active_calls (void)
 Retrieve the number of active calls.
int ast_add_extension (const char *context, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar)
 Add and extension to an extension context.
int ast_add_extension2 (struct ast_context *con, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar)
 Add an extension to an extension context, this time with an ast_context *.
static int ast_add_extension2_lockopt (struct ast_context *con, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar, int lockconts, int lockhints)
 Does all the work of ast_add_extension2, but adds two args, to determine if context and hint locking should be done. In merge_and_delete, we need to do this without locking, as the locks are already held.
static int ast_add_extension_nolock (const char *context, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar)
static int ast_add_hint (struct ast_exten *e)
 Add hint to hint list, check initial extension state.
static int ast_add_hint_nolock (struct ast_exten *e)
 Add hint to hint list, check initial extension state; the hints had better be WRLOCKED already!
int ast_async_goto (struct ast_channel *chan, const char *context, const char *exten, int priority)
int ast_async_goto_by_name (const char *channame, const char *context, const char *exten, int priority)
int ast_async_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority)
int ast_async_parseable_goto (struct ast_channel *chan, const char *goto_string)
int ast_build_timing (struct ast_timing *i, const char *info_in)
int ast_canmatch_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
 Looks for a valid matching extension.
static int ast_change_hint (struct ast_exten *oe, struct ast_exten *ne)
 Change hint for an extension.
int ast_check_timing (const struct ast_timing *i)
int ast_context_add_ignorepat (const char *context, const char *value, const char *registrar)
 Add an ignorepat.
int ast_context_add_ignorepat2 (struct ast_context *con, const char *value, const char *registrar)
int ast_context_add_include (const char *context, const char *include, const char *registrar)
 Add a context include.
int ast_context_add_include2 (struct ast_context *con, const char *value, const char *registrar)
 Add a context include.
int ast_context_add_switch (const char *context, const char *sw, const char *data, int eval, const char *registrar)
 Add a switch.
int ast_context_add_switch2 (struct ast_context *con, const char *value, const char *data, int eval, const char *registrar)
 Adds a switch (first param is a ast_context).
void ast_context_destroy (struct ast_context *con, const char *registrar)
 Destroy a context (matches the specified context (or ANY context if NULL).
ast_contextast_context_find (const char *name)
 Find a context.
ast_contextast_context_find_or_create (struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *name, const char *registrar)
 Register a new context or find an existing one.
int ast_context_lockmacro (const char *context)
 locks the macrolock in the given given context
int ast_context_remove_extension (const char *context, const char *extension, int priority, const char *registrar)
 Simply remove extension from context.
int ast_context_remove_extension2 (struct ast_context *con, const char *extension, int priority, const char *registrar, int already_locked)
 This functionc locks given context, search for the right extension and fires out all peer in this extensions with given priority. If priority is set to 0, all peers are removed. After that, unlock context and return.
int ast_context_remove_extension_callerid (const char *context, const char *extension, int priority, const char *callerid, int matchcallerid, const char *registrar)
int ast_context_remove_extension_callerid2 (struct ast_context *con, const char *extension, int priority, const char *callerid, int matchcallerid, const char *registrar, int already_locked)
int ast_context_remove_ignorepat (const char *context, const char *ignorepat, const char *registrar)
int ast_context_remove_ignorepat2 (struct ast_context *con, const char *ignorepat, const char *registrar)
int ast_context_remove_include (const char *context, const char *include, const char *registrar)
 Remove a context include.
int ast_context_remove_include2 (struct ast_context *con, const char *include, const char *registrar)
 Removes an include by an ast_context structure.
int ast_context_remove_switch (const char *context, const char *sw, const char *data, const char *registrar)
 Remove a switch.
int ast_context_remove_switch2 (struct ast_context *con, const char *sw, const char *data, const char *registrar)
 This function locks given context, removes switch, unlock context and return.
int ast_context_unlockmacro (const char *context)
 Unlocks the macrolock in the given context.
int ast_context_verify_includes (struct ast_context *con)
 Verifies includes in an ast_contect structure.
ast_custom_functionast_custom_function_find (const char *name)
int ast_custom_function_unregister (struct ast_custom_function *acf)
 Unregister a custom function.
enum ast_extension_states ast_devstate_to_extenstate (enum ast_device_state devstate)
 Map devstate to an extension state.
int ast_exists_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
 Determine whether an extension exists.
int ast_explicit_goto (struct ast_channel *chan, const char *context, const char *exten, int priority)
int ast_extension_close (const char *pattern, const char *data, int needmore)
int ast_extension_cmp (const char *a, const char *b)
 Determine if one extension should match before another.
int ast_extension_match (const char *pattern, const char *data)
 Determine if a given extension matches a given pattern (in NXX format).
int ast_extension_state (struct ast_channel *c, const char *context, const char *exten)
 Uses hint and devicestate callback to get the state of an extension.
static int ast_extension_state2 (struct ast_exten *e)
 Check state of extension by using hints.
const char * ast_extension_state2str (int extension_state)
 Return string representation of the state of an extension.
int ast_extension_state_add (const char *context, const char *exten, ast_state_cb_type callback, void *data)
 Registers a state change callback.
int ast_extension_state_del (int id, ast_state_cb_type callback)
 Deletes a registered state change callback by ID.
int ast_findlabel_extension (struct ast_channel *c, const char *context, const char *exten, const char *label, const char *callerid)
 Find the priority of an extension that has the specified label.
int ast_findlabel_extension2 (struct ast_channel *c, struct ast_context *con, const char *exten, const char *label, const char *callerid)
 Find the priority of an extension that has the specified label.
int ast_func_read (struct ast_channel *chan, const char *function, char *workspace, size_t len)
 executes a read operation on a function
int ast_func_write (struct ast_channel *chan, const char *function, const char *value)
 executes a write operation on a function
const char * ast_get_context_name (struct ast_context *con)
const char * ast_get_context_registrar (struct ast_context *c)
const char * ast_get_extension_app (struct ast_exten *e)
void * ast_get_extension_app_data (struct ast_exten *e)
const char * ast_get_extension_cidmatch (struct ast_exten *e)
ast_contextast_get_extension_context (struct ast_exten *exten)
const char * ast_get_extension_label (struct ast_exten *exten)
int ast_get_extension_matchcid (struct ast_exten *e)
const char * ast_get_extension_name (struct ast_exten *exten)
int ast_get_extension_priority (struct ast_exten *exten)
const char * ast_get_extension_registrar (struct ast_exten *e)
int ast_get_hint (char *hint, int hintsize, char *name, int namesize, struct ast_channel *c, const char *context, const char *exten)
 If an extension hint exists, return non-zero.
const char * ast_get_ignorepat_name (struct ast_ignorepat *ip)
const char * ast_get_ignorepat_registrar (struct ast_ignorepat *ip)
const char * ast_get_include_name (struct ast_include *inc)
const char * ast_get_include_registrar (struct ast_include *i)
const char * ast_get_switch_data (struct ast_sw *sw)
int ast_get_switch_eval (struct ast_sw *sw)
const char * ast_get_switch_name (struct ast_sw *sw)
const char * ast_get_switch_registrar (struct ast_sw *sw)
int ast_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority)
int ast_hashtab_compare_contexts (const void *ah_a, const void *ah_b)
unsigned int ast_hashtab_hash_contexts (const void *obj)
static struct ast_extenast_hint_extension (struct ast_channel *c, const char *context, const char *exten)
static struct ast_extenast_hint_extension_nolock (struct ast_channel *c, const char *context, const char *exten)
 Find hint for given extension in context.
int ast_ignore_pattern (const char *context, const char *pattern)
 Checks to see if a number should be ignored.
int ast_matchmore_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
 Looks to see if adding anything to this extension might match something. (exists ^ canmatch).
void ast_merge_contexts_and_delete (struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *registrar)
 Merge the temporary contexts into a global contexts list and delete from the global list the ones that are being added.
int ast_parseable_goto (struct ast_channel *chan, const char *goto_string)
int ast_pbx_outgoing_app (const char *type, int format, void *data, int timeout, const char *app, const char *appdata, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel)
static int ast_pbx_outgoing_cdr_failed (void)
 Function to post an empty cdr after a spool call fails.
int ast_pbx_outgoing_exten (const char *type, int format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **channel)
enum ast_pbx_result ast_pbx_run (struct ast_channel *c)
 Execute the PBX in the current thread.
static void * ast_pbx_run_app (void *data)
 run the application and free the descriptor once done
enum ast_pbx_result ast_pbx_run_args (struct ast_channel *c, struct ast_pbx_args *args)
 Execute the PBX in the current thread.
enum ast_pbx_result ast_pbx_start (struct ast_channel *c)
 Create a new thread and start the PBX.
int ast_processed_calls (void)
 Retrieve the total number of calls processed through the PBX since last restart.
int ast_rdlock_context (struct ast_context *con)
 Read locks a given context.
int ast_rdlock_contexts ()
 Read locks the context list.
int ast_register_application2 (const char *app, int(*execute)(struct ast_channel *, void *), const char *synopsis, const char *description, void *mod)
 Register an application.
int ast_register_switch (struct ast_switch *sw)
 Register an alternative dialplan switch.
static int ast_remove_hint (struct ast_exten *e)
 Remove hint from extension.
int ast_spawn_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid, int *found, int combined_find_spawn)
 Launch a new extension (i.e. new stack).
int ast_unlock_context (struct ast_context *con)
int ast_unlock_contexts ()
 Unlocks contexts.
int ast_unregister_application (const char *app)
 Unregister an application.
void ast_unregister_switch (struct ast_switch *sw)
 Unregister an alternative switch.
ast_extenast_walk_context_extensions (struct ast_context *con, struct ast_exten *exten)
ast_ignorepatast_walk_context_ignorepats (struct ast_context *con, struct ast_ignorepat *ip)
ast_includeast_walk_context_includes (struct ast_context *con, struct ast_include *inc)
ast_swast_walk_context_switches (struct ast_context *con, struct ast_sw *sw)
ast_contextast_walk_contexts (struct ast_context *con)
ast_extenast_walk_extension_priorities (struct ast_exten *exten, struct ast_exten *priority)
int ast_wrlock_context (struct ast_context *con)
 Write locks a given context.
int ast_wrlock_contexts ()
 Write locks the context list.
int ast_wrlock_contexts_version (void)
static void * async_wait (void *data)
static void cli_match_char_tree (struct match_char *node, char *prefix, int fd)
static int collect_digits (struct ast_channel *c, int waittime, char *buf, int buflen, int pos)
 collect digits from the channel into the buffer.
static int compare_char (const void *a, const void *b)
static char * complete_core_show_hint (const char *line, const char *word, int pos, int state)
 autocomplete for CLI command 'core show hint'
static char * complete_show_dialplan_context (const char *line, const char *word, int pos, int state)
static void context_merge (struct ast_context **extcontexts, struct ast_hashtab *exttable, struct ast_context *context, const char *registrar)
static void context_merge_incls_swits_igps_other_registrars (struct ast_context *new, struct ast_context *old, const char *registrar)
static void create_match_char_tree (struct ast_context *con)
static void decrease_call_count (void)
static void destroy_exten (struct ast_exten *e)
static void destroy_pattern_tree (struct match_char *pattern_tree)
static void device_state_cb (const struct ast_event *event, void *unused)
static void exception_store_free (void *data)
static int ext_cmp (const char *a, const char *b)
 the full routine to compare extensions in rules.
static int ext_cmp1 (const char **p, 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 2 minute
static char * handle_debug_dialplan (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 Send ack once.
static char * handle_set_chanvar (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_set_chanvar_deprecated (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_set_extenpatternmatchnew (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_set_global (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_set_global_deprecated (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_show_application (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_show_applications (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_show_chanvar (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI support for listing chanvar's variables in a parseable way.
static char * handle_show_dialplan (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_show_function (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_show_functions (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_show_globals (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI support for listing global variables in a parseable way.
static char * handle_show_globals_deprecated (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_show_hint (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 handle_show_hint: CLI support for listing registered dial plan hint
static char * handle_show_hints (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 handle_show_hints: CLI support for listing registered dial plan hints
static char * handle_show_switches (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 handle_show_switches: CLI support for listing registered dial plan switches
static int handle_statechange (void *datap)
static char * handle_unset_extenpatternmatchnew (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int hashtab_compare_exten_labels (const void *ah_a, const void *ah_b)
static int hashtab_compare_exten_numbers (const void *ah_a, const void *ah_b)
static int hashtab_compare_extens (const void *ha_a, const void *ah_b)
static unsigned int hashtab_hash_extens (const void *obj)
static unsigned int hashtab_hash_labels (const void *obj)
static unsigned int hashtab_hash_priority (const void *obj)
static int include_valid (struct ast_include *i)
static int increase_call_count (const struct ast_channel *c)
 Increase call count for channel.
static void insert_in_next_chars_alt_char_list (struct match_char **parent_ptr, struct match_char *node)
int load_pbx (void)
void log_match_char_tree (struct match_char *node, char *prefix)
static int lookup_name (const char *s, char *const names[], int max)
 Helper for get_range. return the index of the matching entry, starting from 1. If names is not supplied, try numeric values.
static void manager_dpsendack (struct mansession *s, const struct message *m)
 Send ack once.
static int manager_show_dialplan (struct mansession *s, const struct message *m)
 Manager listing of dial plan.
static int manager_show_dialplan_helper (struct mansession *s, const struct message *m, const char *actionidtext, const char *context, const char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude)
 Show dialplan extensions XXX this function is similar but not exactly the same as the CLI's show dialplan. Must check whether the difference is intentional or not.
static int matchcid (const char *cidpattern, const char *callerid)
static void new_find_extension (const char *str, struct scoreboard *score, struct match_char *tree, int length, int spec, const char *callerid, const char *label, enum ext_match_t action)
static int parse_variable_name (char *var, int *offset, int *length, int *isfunc)
 extract offset:length from variable name.
static int pbx_builtin_answer (struct ast_channel *, void *)
static int pbx_builtin_background (struct ast_channel *, void *)
static int pbx_builtin_busy (struct ast_channel *, void *)
void pbx_builtin_clear_globals (void)
static int pbx_builtin_congestion (struct ast_channel *, void *)
static int pbx_builtin_execiftime (struct ast_channel *, void *)
const char * pbx_builtin_getvar_helper (struct ast_channel *chan, const char *name)
static int pbx_builtin_goto (struct ast_channel *, void *)
static int pbx_builtin_gotoif (struct ast_channel *, void *)
static int pbx_builtin_gotoiftime (struct ast_channel *, void *)
static int pbx_builtin_hangup (struct ast_channel *, void *)
static int pbx_builtin_importvar (struct ast_channel *, void *)
static int pbx_builtin_incomplete (struct ast_channel *, void *)
static int pbx_builtin_noop (struct ast_channel *, void *)
static int pbx_builtin_proceeding (struct ast_channel *, void *)
static int pbx_builtin_progress (struct ast_channel *, void *)
void pbx_builtin_pushvar_helper (struct ast_channel *chan, const char *name, const char *value)
int pbx_builtin_raise_exception (struct ast_channel *chan, void *vreason)
static int pbx_builtin_resetcdr (struct ast_channel *, void *)
static int pbx_builtin_ringing (struct ast_channel *, void *)
static int pbx_builtin_saycharacters (struct ast_channel *, void *)
static int pbx_builtin_saydigits (struct ast_channel *, void *)
static int pbx_builtin_saynumber (struct ast_channel *, void *)
static int pbx_builtin_sayphonetic (struct ast_channel *, void *)
int pbx_builtin_serialize_variables (struct ast_channel *chan, struct ast_str **buf)
static int pbx_builtin_setamaflags (struct ast_channel *, void *)
int pbx_builtin_setvar (struct ast_channel *, void *)
void pbx_builtin_setvar_helper (struct ast_channel *chan, const char *name, const char *value)
int pbx_builtin_setvar_multiple (struct ast_channel *, void *)
static int pbx_builtin_wait (struct ast_channel *, void *)
static int pbx_builtin_waitexten (struct ast_channel *, void *)
int pbx_checkcondition (const char *condition)
 Evaluate a condition.
static void pbx_destroy (struct ast_pbx *p)
int pbx_exec (struct ast_channel *c, struct ast_app *app, void *data)
 Execute an application.
static int pbx_extension_helper (struct ast_channel *c, struct ast_context *con, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action, int *found, int combined_find_spawn)
 The return value depends on the action:.
ast_extenpbx_find_extension (struct ast_channel *chan, struct ast_context *bypass, struct pbx_find_info *q, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action)
ast_apppbx_findapp (const char *app)
 Look up an application.
static struct ast_switchpbx_findswitch (const char *sw)
static int pbx_parseable_goto (struct ast_channel *chan, const char *goto_string, int async)
void pbx_retrieve_variable (struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp)
 Support for Asterisk built-in variables in the dialplan.
int pbx_set_autofallthrough (int newval)
int pbx_set_extenpatternmatchnew (int newval)
void pbx_set_overrideswitch (const char *newval)
static void pbx_substitute_variables (char *passdata, int datalen, struct ast_channel *c, struct ast_exten *e)
void pbx_substitute_variables_helper (struct ast_channel *c, const char *cp1, char *cp2, int count)
static void pbx_substitute_variables_helper_full (struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count)
void pbx_substitute_variables_varshead (struct varshead *headp, const char *cp1, char *cp2, int count)
static void * pbx_thread (void *data)
static void print_ext (struct ast_exten *e, char *buf, int buflen)
 helper function to print an extension
static void set_ext_pri (struct ast_channel *c, const char *exten, int pri)
static int show_debug_helper (int fd, const char *context, const char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude, int includecount, const char *includes[])
static int show_dialplan_helper (int fd, const char *context, const char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude, int includecount, const char *includes[])
static char * substring (const char *value, int offset, int length, char *workspace, size_t workspace_len)
 takes a substring. It is ok to call with value == workspace.
static struct ast_extentrie_find_next_match (struct match_char *node)
static void unreference_cached_app (struct ast_app *app)
static void update_scoreboard (struct scoreboard *board, int length, int spec, struct ast_exten *exten, char last, const char *callerid, int deleted, struct match_char *node)
static void wait_for_hangup (struct ast_channel *chan, void *data)

Variables

static int autofallthrough = 1
static struct ast_app_option background_opts [128] = { [ 's' ] = { .flag = (1 << 0) }, [ 'n' ] = { .flag = (1 << 1) }, [ 'm' ] = { .flag = (1 << 2) }, [ 'p' ] = { .flag = (1 << 3) },}
static struct pbx_builtin builtins []
 Declaration of builtin applications.
static struct ast_cli_entry cli_set_chanvar_deprecated = { .handler = handle_set_chanvar_deprecated , .summary = "Set a channel variable." ,__VA_ARGS__ }
static struct ast_cli_entry cli_set_global_deprecated = { .handler = handle_set_global_deprecated , .summary = "Set global dialplan variable." ,__VA_ARGS__ }
static struct ast_cli_entry cli_show_globals_deprecated = { .handler = handle_show_globals_deprecated , .summary = "Show global dialplan variables." ,__VA_ARGS__ }
static ast_rwlock_t conlock = PTHREAD_RWLOCK_INITIALIZER
static int conlock_wrlock_version = 0
static struct ast_contextcontexts
static struct ast_hashtabcontexts_table = NULL
static int countcalls
static char * days []
static struct ast_event_subdevice_state_sub
 Subscription for device state change events.
static struct ast_taskprocessordevice_state_tps
static struct ast_custom_function exception_function
static struct ast_datastore_info exception_store_info
static int extenpatternmatchnew = 0
static struct cfextension_states extension_states []
static struct varshead globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE
static ast_rwlock_t globalslock = PTHREAD_RWLOCK_INITIALIZER
static char mandescr_show_dialplan []
static ast_mutex_t maxcalllock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP )
static char * months []
static char * overrideswitch = NULL
static struct ast_cli_entry pbx_cli []
static struct ast_app_option resetcdr_opts [128] = { [ 'w' ] = { .flag = (1 << 1) }, [ 'a' ] = { .flag = (1 << 2) }, [ 'v' ] = { .flag = (1 << 0) }, [ 'e' ] = { .flag = (1 << 10) },}
static int stateid = 1
static struct ast_threadstorage switch_data = { .once = PTHREAD_ONCE_INIT , .key_init = __init_switch_data , .custom_init = NULL , }
static int totalcalls
static struct ast_app_option waitexten_opts [128] = { [ 'm' ] = { .flag = (1 << 0) , .arg_index = 0 + 1 }, [ 'd' ] = { .flag = (1 << 1) , .arg_index = 0 + 1 },}


Detailed Description

Core PBX routines.

Author:
Mark Spencer <markster@digium.com>

Definition in file pbx.c.


Define Documentation

#define AST_PBX_MAX_STACK   128

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

Definition at line 971 of file pbx.c.

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

#define BACKGROUND_MATCHEXTEN   (1 << 2)

Definition at line 105 of file pbx.c.

Referenced by pbx_builtin_background().

#define BACKGROUND_NOANSWER   (1 << 1)

Definition at line 104 of file pbx.c.

Referenced by pbx_builtin_background().

#define BACKGROUND_PLAYBACK   (1 << 3)

Definition at line 106 of file pbx.c.

Referenced by pbx_builtin_background().

#define BACKGROUND_SKIP   (1 << 0)

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

Referenced by pbx_extension_helper().

#define NEW_MATCHER_CHK_MATCH

Referenced by new_find_extension().

#define NEW_MATCHER_RECURSE

#define SAY_STUBS

Definition at line 54 of file pbx.c.

#define STATUS_NO_CONTEXT   1

Definition at line 2051 of file pbx.c.

Referenced by pbx_extension_helper(), and pbx_find_extension().

#define STATUS_NO_EXTENSION   2

Definition at line 2052 of file pbx.c.

Referenced by pbx_extension_helper(), and pbx_find_extension().

#define STATUS_NO_LABEL   4

Definition at line 2054 of file pbx.c.

Referenced by pbx_extension_helper(), and pbx_find_extension().

#define STATUS_NO_PRIORITY   3

Definition at line 2053 of file pbx.c.

Referenced by pbx_extension_helper(), and pbx_find_extension().

#define STATUS_SUCCESS   5

Definition at line 2055 of file pbx.c.

Referenced by pbx_find_extension().

#define SWITCH_DATA_LENGTH   256

Definition at line 95 of file pbx.c.

#define VAR_BUF_SIZE   4096

Definition at line 97 of file pbx.c.

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

#define VAR_HARDTRAN   3

Definition at line 101 of file pbx.c.

#define VAR_NORMAL   1

Definition at line 99 of file pbx.c.

#define VAR_SOFTTRAN   2

Definition at line 100 of file pbx.c.

#define WAITEXTEN_DIALTONE   (1 << 1)

Definition at line 116 of file pbx.c.

Referenced by pbx_builtin_waitexten().

#define WAITEXTEN_MOH   (1 << 0)

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

References __ast_internal_context_destroy(), ast_context_remove_extension_callerid2(), ast_debug, ast_free, ast_hashtab_end_traversal(), ast_hashtab_next(), ast_hashtab_remove_this_object(), ast_hashtab_start_traversal(), AST_LIST_EMPTY, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_unlock_context(), ast_verb, ast_wrlock_context(), ast_exten::cidmatch, contexts, ast_exten::exten, ast_sw::list, ast_context::name, ast_sw::next, ast_include::next, ast_ignorepat::next, ast_context::next, ast_exten::next, ast_exten::peer_table, ast_exten::priority, ast_exten::registrar, ast_sw::registrar, ast_include::registrar, ast_ignorepat::registrar, ast_context::registrar, and ast_context::root_table.

Referenced by ast_context_destroy().

07730 {
07731    struct ast_context *tmp, *tmpl=NULL;
07732    struct ast_exten *exten_item, *prio_item;
07733 
07734    for (tmp = list; tmp; ) {
07735       struct ast_context *next = NULL; /* next starting point */
07736          /* The following code used to skip forward to the next
07737             context with matching registrar, but this didn't
07738             make sense; individual priorities registrar'd to 
07739             the matching registrar could occur in any context! */
07740       ast_debug(1, "Investigate ctx %s %s\n", tmp->name, tmp->registrar);
07741       if (con) {
07742          for (; tmp; tmpl = tmp, tmp = tmp->next) { /* skip to the matching context */
07743             ast_debug(1, "check ctx %s %s\n", tmp->name, tmp->registrar);
07744             if ( !strcasecmp(tmp->name, con->name) ) {
07745                break;   /* found it */
07746             }
07747          }
07748       }
07749       
07750       if (!tmp)   /* not found, we are done */
07751          break;
07752       ast_wrlock_context(tmp);
07753 
07754       if (registrar) {
07755          /* then search thru and remove any extens that match registrar. */
07756          struct ast_hashtab_iter *exten_iter;
07757          struct ast_hashtab_iter *prio_iter;
07758          struct ast_ignorepat *ip, *ipl = NULL, *ipn = NULL;
07759          struct ast_include *i, *pi = NULL, *ni = NULL;
07760          struct ast_sw *sw = NULL;
07761 
07762          /* remove any ignorepats whose registrar matches */
07763          for (ip = tmp->ignorepats; ip; ip = ipn) {
07764             ipn = ip->next;
07765             if (!strcmp(ip->registrar, registrar)) {
07766                if (ipl) {
07767                   ipl->next = ip->next;
07768                   ast_free(ip);
07769                   continue; /* don't change ipl */
07770                } else {
07771                   tmp->ignorepats = ip->next;
07772                   ast_free(ip);
07773                   continue; /* don't change ipl */
07774                }
07775             }
07776             ipl = ip;
07777          }
07778          /* remove any includes whose registrar matches */
07779          for (i = tmp->includes; i; i = ni) {
07780             ni = i->next;
07781             if (strcmp(i->registrar, registrar) == 0) {
07782                /* remove from list */
07783                if (pi) {
07784                   pi->next = i->next;
07785                   /* free include */
07786                   ast_free(i);
07787                   continue; /* don't change pi */
07788                } else {
07789                   tmp->includes = i->next;
07790                   /* free include */
07791                   ast_free(i);
07792                   continue; /* don't change pi */
07793                }
07794             }
07795             pi = i;
07796          }
07797          /* remove any switches whose registrar matches */
07798          AST_LIST_TRAVERSE_SAFE_BEGIN(&tmp->alts, sw, list) {
07799             if (strcmp(sw->registrar,registrar) == 0) {
07800                AST_LIST_REMOVE_CURRENT(list);
07801                ast_free(sw);
07802             }
07803          }
07804          AST_LIST_TRAVERSE_SAFE_END;
07805 
07806          if (tmp->root_table) { /* it is entirely possible that the context is EMPTY */
07807             exten_iter = ast_hashtab_start_traversal(tmp->root_table);
07808             while ((exten_item=ast_hashtab_next(exten_iter))) {
07809                prio_iter = ast_hashtab_start_traversal(exten_item->peer_table);
07810                while ((prio_item=ast_hashtab_next(prio_iter))) {
07811                   if (!prio_item->registrar || strcmp(prio_item->registrar, registrar) != 0) {
07812                      continue;
07813                   }
07814                   ast_verb(3, "Remove %s/%s/%d, registrar=%s; con=%s(%p); con->root=%p\n",
07815                          tmp->name, prio_item->exten, prio_item->priority, registrar, con? con->name : "<nil>", con, con? con->root_table: NULL);
07816                   /* set matchcid to 1 to insure we get a direct match, and NULL registrar to make sure no wildcarding is done */
07817                   ast_context_remove_extension_callerid2(tmp, prio_item->exten, prio_item->priority, prio_item->cidmatch, 1, NULL, 1);
07818                }
07819                ast_hashtab_end_traversal(prio_iter);
07820             }
07821             ast_hashtab_end_traversal(exten_iter);
07822          }
07823    
07824          /* delete the context if it's registrar matches, is empty, has refcount of 1, */
07825          /* it's not empty, if it has includes, ignorepats, or switches that are registered from
07826             another registrar. It's not empty if there are any extensions */
07827          if (strcmp(tmp->registrar, registrar) == 0 && tmp->refcount < 2 && !tmp->root && !tmp->ignorepats && !tmp->includes && AST_LIST_EMPTY(&tmp->alts)) {
07828             ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar);
07829             ast_hashtab_remove_this_object(contexttab, tmp);
07830             
07831             next = tmp->next;
07832             if (tmpl)
07833                tmpl->next = next;
07834             else
07835                contexts = next;
07836             /* Okay, now we're safe to let it go -- in a sense, we were
07837                ready to let it go as soon as we locked it. */
07838             ast_unlock_context(tmp);
07839             __ast_internal_context_destroy(tmp);
07840          } else {
07841             ast_debug(1,"Couldn't delete ctx %s/%s; refc=%d; tmp.root=%p\n", tmp->name, tmp->registrar,
07842                     tmp->refcount, tmp->root);
07843             ast_unlock_context(tmp);
07844             next = tmp->next;
07845             tmpl = tmp;
07846          }
07847       } else if (con) {
07848          ast_verb(3, "Deleting context %s registrar=%s\n", tmp->name, tmp->registrar);
07849          ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar);
07850          ast_hashtab_remove_this_object(contexttab, tmp);
07851          
07852          next = tmp->next;
07853          if (tmpl)
07854             tmpl->next = next;
07855          else
07856             contexts = next;
07857          /* Okay, now we're safe to let it go -- in a sense, we were
07858             ready to let it go as soon as we locked it. */
07859          ast_unlock_context(tmp);
07860          __ast_internal_context_destroy(tmp);
07861       }
07862 
07863       /* if we have a specific match, we are done, otherwise continue */
07864       tmp = con ? NULL : next;
07865    }
07866 }

int __ast_custom_function_register ( struct ast_custom_function acf,
struct ast_module mod 
)

Register a custom function.

Definition at line 2814 of file pbx.c.

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

Referenced by load_pbx().

02815 {
02816    struct ast_custom_function *cur;
02817    char tmps[80];
02818 
02819    if (!acf)
02820       return -1;
02821 
02822    acf->mod = mod;
02823 
02824    AST_RWLIST_WRLOCK(&acf_root);
02825 
02826    AST_RWLIST_TRAVERSE(&acf_root, cur, acflist) {
02827       if (!strcmp(acf->name, cur->name)) {
02828          ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name);
02829          AST_RWLIST_UNLOCK(&acf_root);
02830          return -1;
02831       }
02832    }
02833 
02834    /* Store in alphabetical order */
02835    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) {
02836       if (strcasecmp(acf->name, cur->name) < 0) {
02837          AST_RWLIST_INSERT_BEFORE_CURRENT(acf, acflist);
02838          break;
02839       }
02840    }
02841    AST_RWLIST_TRAVERSE_SAFE_END;
02842    if (!cur)
02843       AST_RWLIST_INSERT_TAIL(&acf_root, acf, acflist);
02844 
02845    AST_RWLIST_UNLOCK(&acf_root);
02846 
02847    ast_verb(2, "Registered custom function '%s'\n", term_color(tmps, acf->name, COLOR_BRCYAN, 0, sizeof(tmps)));
02848 
02849    return 0;
02850 }

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

Definition at line 8980 of file pbx.c.

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

Referenced by ast_async_goto_if_exists(), and ast_goto_if_exists().

08981 {
08982    int (*goto_func)(struct ast_channel *chan, const char *context, const char *exten, int priority);
08983 
08984    if (!chan)
08985       return -2;
08986 
08987    if (context == NULL)
08988       context = chan->context;
08989    if (exten == NULL)
08990       exten = chan->exten;
08991 
08992    goto_func = (async) ? ast_async_goto : ast_explicit_goto;
08993    if (ast_exists_extension(chan, context, exten, priority, chan->cid.cid_num))
08994       return goto_func(chan, context, exten, priority);
08995    else
08996       return -3;
08997 }

static void __ast_internal_context_destroy ( struct ast_context con  )  [static]

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

07683 {
07684    struct ast_include *tmpi;
07685    struct ast_sw *sw;
07686    struct ast_exten *e, *el, *en;
07687    struct ast_ignorepat *ipi;
07688    struct ast_context *tmp = con;
07689    
07690    for (tmpi = tmp->includes; tmpi; ) { /* Free includes */
07691       struct ast_include *tmpil = tmpi;
07692       tmpi = tmpi->next;
07693       ast_free(tmpil);
07694    }
07695    for (ipi = tmp->ignorepats; ipi; ) { /* Free ignorepats */
07696       struct ast_ignorepat *ipl = ipi;
07697       ipi = ipi->next;
07698       ast_free(ipl);
07699    }
07700    if (tmp->registrar)
07701       ast_free(tmp->registrar);
07702    
07703    /* destroy the hash tabs */
07704    if (tmp->root_table) {
07705       ast_hashtab_destroy(tmp->root_table, 0);
07706    }
07707    /* and destroy the pattern tree */
07708    if (tmp->pattern_tree)
07709       destroy_pattern_tree(tmp->pattern_tree);
07710    
07711    while ((sw = AST_LIST_REMOVE_HEAD(&tmp->alts, list)))
07712       ast_free(sw);
07713    for (e = tmp->root; e;) {
07714       for (en = e->peer; en;) {
07715          el = en;
07716          en = en->peer;
07717          destroy_exten(el);
07718       }
07719       el = e;
07720       e = e->next;
07721       destroy_exten(el);
07722    }
07723    tmp->root = NULL;
07724    ast_rwlock_destroy(&tmp->lock);
07725    ast_free(tmp);
07726 }

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

Definition at line 3721 of file pbx.c.

References ast_channel::_softhangup, ast_calloc, ast_cdr_update(), ast_check_hangup(), ast_copy_string(), ast_debug, ast_exists_extension(), AST_FLAG_IN_AUTOLOOP, ast_free, ast_log(), ast_set_flag, AST_SOFTHANGUP_ASYNCGOTO, AST_SOFTHANGUP_TIMEOUT, ast_spawn_extension(), ast_test_flag, ast_verb, ast_channel::cdr, ast_channel::cid, ast_callerid::cid_num, ast_channel::context, ast_pbx::dtimeoutms, ast_channel::exten, LOG_WARNING, ast_channel::name, ast_channel::pbx, pbx_builtin_raise_exception(), ast_channel::priority, ast_pbx::rtimeoutms, set_ext_pri(), and ast_channel::whentohangup.

Referenced by ast_pbx_run_args(), and pbx_thread().

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

static void __init_switch_data ( void   )  [static]

Definition at line 128 of file pbx.c.

00131 : An extension

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

Definition at line 1827 of file pbx.c.

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

Referenced by extension_match_core().

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

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

Definition at line 2628 of file pbx.c.

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

02629 {
02630    struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL);
02631    struct pbx_exception *exception = NULL;
02632    if (!ds || !ds->data)
02633       return -1;
02634    exception = ds->data;
02635    if (!strcasecmp(data, "REASON"))
02636       ast_copy_string(buf, exception->reason, buflen);
02637    else if (!strcasecmp(data, "CONTEXT"))
02638       ast_copy_string(buf, exception->context, buflen);
02639    else if (!strncasecmp(data, "EXTEN", 5))
02640       ast_copy_string(buf, exception->exten, buflen);
02641    else if (!strcasecmp(data, "PRIORITY"))
02642       snprintf(buf, buflen, "%d", exception->priority);
02643    else
02644       return -1;
02645    return 0;
02646 }

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

Definition at line 1478 of file pbx.c.

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

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

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

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

Definition at line 1437 of file pbx.c.

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

Referenced by add_exten_to_pattern_tree().

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

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

References add_pri_lockopt(), and el.

Referenced by ast_add_extension2_lockopt().

06895 {
06896    return add_pri_lockopt(con, tmp, el, e, replace, 1);
06897 }

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

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

Referenced by add_pri().

06906 {
06907    struct ast_exten *ep;
06908    struct ast_exten *eh=e;
06909 
06910    for (ep = NULL; e ; ep = e, e = e->peer) {
06911       if (e->priority >= tmp->priority)
06912          break;
06913    }
06914    if (!e) {   /* go at the end, and ep is surely set because the list is not empty */
06915       ast_hashtab_insert_safe(eh->peer_table, tmp);
06916       
06917       if (tmp->label) {
06918          ast_hashtab_insert_safe(eh->peer_label_table, tmp);
06919       }
06920       ep->peer = tmp;
06921       return 0;   /* success */
06922    }
06923    if (e->priority == tmp->priority) {
06924       /* Can't have something exactly the same.  Is this a
06925          replacement?  If so, replace, otherwise, bonk. */
06926       if (!replace) {
06927          ast_log(LOG_WARNING, "Unable to register extension '%s', priority %d in '%s', already in use\n", tmp->exten, tmp->priority, con->name);
06928          if (tmp->datad) {
06929             tmp->datad(tmp->data);
06930             /* if you free this, null it out */
06931             tmp->data = NULL;
06932          }
06933          
06934          ast_free(tmp);
06935          return -1;
06936       }
06937       /* we are replacing e, so copy the link fields and then update
06938        * whoever pointed to e to point to us
06939        */
06940       tmp->next = e->next; /* not meaningful if we are not first in the peer list */
06941       tmp->peer = e->peer; /* always meaningful */
06942       if (ep)  {     /* We're in the peer list, just insert ourselves */
06943          ast_hashtab_remove_object_via_lookup(eh->peer_table,e);
06944 
06945          if (e->label) {
06946             ast_hashtab_remove_object_via_lookup(eh->peer_label_table,e);
06947          }
06948          
06949          ast_hashtab_insert_safe(eh->peer_table,tmp);
06950          if (tmp->label) {
06951             ast_hashtab_insert_safe(eh->peer_label_table,tmp);
06952          }
06953          
06954          ep->peer = tmp;
06955       } else if (el) {     /* We're the first extension. Take over e's functions */
06956          struct match_char *x = add_exten_to_pattern_tree(con, e, 1);
06957          tmp->peer_table = e->peer_table;
06958          tmp->peer_label_table = e->peer_label_table;
06959          ast_hashtab_remove_object_via_lookup(tmp->peer_table,e);
06960          ast_hashtab_insert_safe(tmp->peer_table,tmp);
06961          if (e->label) {
06962             ast_hashtab_remove_object_via_lookup(tmp->peer_label_table, e);
06963          }
06964          if (tmp->label) {
06965             ast_hashtab_insert_safe(tmp->peer_label_table, tmp);
06966          }
06967          
06968          ast_hashtab_remove_object_via_lookup(con->root_table, e);
06969          ast_hashtab_insert_safe(con->root_table, tmp);
06970          el->next = tmp;
06971          /* The pattern trie points to this exten; replace the pointer,
06972             and all will be well */
06973          if (x) { /* if the trie isn't formed yet, don't sweat this */
06974             if (x->exten) { /* this test for safety purposes */
06975                x->exten = tmp; /* replace what would become a bad pointer */
06976             } else {
06977                ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n");
06978             }
06979          }
06980       } else {       /* We're the very first extension.  */
06981          struct match_char *x = add_exten_to_pattern_tree(con, e, 1);
06982          ast_hashtab_remove_object_via_lookup(con->root_table, e);
06983          ast_hashtab_insert_safe(con->root_table, tmp);
06984          tmp->peer_table = e->peer_table;
06985          tmp->peer_label_table = e->peer_label_table;
06986          ast_hashtab_remove_object_via_lookup(tmp->peer_table, e);
06987          ast_hashtab_insert_safe(tmp->peer_table, tmp);
06988          if (e->label) {
06989             ast_hashtab_remove_object_via_lookup(tmp->peer_label_table, e);
06990          }
06991          if (tmp->label) {
06992             ast_hashtab_insert_safe(tmp->peer_label_table, tmp);
06993          }
06994          
06995          ast_hashtab_remove_object_via_lookup(con->root_table, e);
06996          ast_hashtab_insert_safe(con->root_table, tmp);
06997          con->root = tmp;
06998          /* The pattern trie points to this exten; replace the pointer,
06999             and all will be well */
07000          if (x) { /* if the trie isn't formed yet; no problem */
07001             if (x->exten) { /* this test for safety purposes */
07002                x->exten = tmp; /* replace what would become a bad pointer */
07003             } else {
07004                ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n");
07005             }
07006          }
07007       }
07008       if (tmp->priority == PRIORITY_HINT)
07009          ast_change_hint(e,tmp);
07010       /* Destroy the old one */
07011       if (e->datad)
07012          e->datad(e->data);
07013       ast_free(e);
07014    } else { /* Slip ourselves in just before e */
07015       tmp->peer = e;
07016       tmp->next = e->next; /* extension chain, or NULL if e is not the first extension */
07017       if (ep) {         /* Easy enough, we're just in the peer list */
07018          if (tmp->label) {
07019             ast_hashtab_insert_safe(eh->peer_label_table, tmp);
07020          }
07021          ast_hashtab_insert_safe(eh->peer_table, tmp);
07022          ep->peer = tmp;
07023       } else {       /* we are the first in some peer list, so link in the ext list */
07024          tmp->peer_table = e->peer_table;
07025          tmp->peer_label_table = e->peer_label_table;
07026          e->peer_table = 0;
07027          e->peer_label_table = 0;
07028          ast_hashtab_insert_safe(tmp->peer_table, tmp);
07029          if (tmp->label) {
07030             ast_hashtab_insert_safe(tmp->peer_label_table, tmp);
07031          }
07032          ast_hashtab_remove_object_via_lookup(con->root_table, e);
07033          ast_hashtab_insert_safe(con->root_table, tmp);
07034          if (el)
07035             el->next = tmp;   /* in the middle... */
07036          else
07037             con->root = tmp; /* ... or at the head */
07038          e->next = NULL;   /* e is no more at the head, so e->next must be reset */
07039       }
07040       /* And immediately return success. */
07041       if (tmp->priority == PRIORITY_HINT) {
07042          if (lockhints) {
07043             ast_add_hint(tmp);
07044          } else {
07045             ast_add_hint_nolock(tmp);
07046          }
07047       }
07048    }
07049    return 0;
07050 }

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

Definition at line 1385 of file pbx.c.

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

Referenced by add_exten_to_pattern_tree().

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

int ast_active_calls ( void   ) 

Retrieve the number of active calls.

Definition at line 4108 of file pbx.c.

References countcalls.

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

04109 {
04110    return countcalls;
04111 }

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

06762 {
06763    int ret = -1;
06764    struct ast_context *c = find_context_locked(context);
06765 
06766    if (c) {
06767       ret = ast_add_extension2(c, replace, extension, priority, label, callerid,
06768          application, data, datad, registrar);
06769       ast_unlock_contexts();
06770    }
06771    
06772    return ret;
06773 }

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

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

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

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

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

Definition at line 7077 of file pbx.c.

References ast_add_extension2_lockopt().

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

07081 {
07082    return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid, application, data, datad, registrar, 1, 1);
07083 }

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

07094 {
07095    /*
07096     * Sort extensions (or patterns) according to the rules indicated above.
07097     * These are implemented by the function ext_cmp()).
07098     * All priorities for the same ext/pattern/cid are kept in a list,
07099     * using the 'peer' field  as a link field..
07100     */
07101    struct ast_exten *tmp, *tmp2, *e, *el = NULL;
07102    int res;
07103    int length;
07104    char *p;
07105    char expand_buf[VAR_BUF_SIZE];
07106    struct ast_exten dummy_exten = {0};
07107    char dummy_name[1024];
07108 
07109    if (ast_strlen_zero(extension)) {
07110       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",
07111             con->name);
07112       return -1;
07113    }
07114    
07115    /* If we are adding a hint evalulate in variables and global variables */
07116    if (priority == PRIORITY_HINT && strstr(application, "${") && !strstr(extension, "_")) {
07117       struct ast_channel c = {0, };
07118 
07119       ast_copy_string(c.exten, extension, sizeof(c.exten));
07120       ast_copy_string(c.context, con->name, sizeof(c.context));
07121       pbx_substitute_variables_helper(&c, application, expand_buf, sizeof(expand_buf));
07122       application = expand_buf;
07123    }
07124 
07125    length = sizeof(struct ast_exten);
07126    length += strlen(extension) + 1;
07127    length += strlen(application) + 1;
07128    if (label)
07129       length += strlen(label) + 1;
07130    if (callerid)
07131       length += strlen(callerid) + 1;
07132    else
07133       length ++;  /* just the '\0' */
07134 
07135    /* Be optimistic:  Build the extension structure first */
07136    if (!(tmp = ast_calloc(1, length)))
07137       return -1;
07138 
07139    if (ast_strlen_zero(label)) /* let's turn empty labels to a null ptr */
07140       label = 0;
07141 
07142    /* use p as dst in assignments, as the fields are const char * */
07143    p = tmp->stuff;
07144    if (label) {
07145       tmp->label = p;
07146       strcpy(p, label);
07147       p += strlen(label) + 1;
07148    }
07149    tmp->exten = p;
07150    p += ext_strncpy(p, extension, strlen(extension) + 1) + 1;
07151    tmp->priority = priority;
07152    tmp->cidmatch = p;   /* but use p for assignments below */
07153 
07154    /* Blank callerid and NULL callerid are two SEPARATE things.  Do NOT confuse the two!!! */
07155    if (callerid) {
07156       p += ext_strncpy(p, callerid, strlen(callerid) + 1) + 1;
07157       tmp->matchcid = 1;
07158    } else {
07159       *p++ = '\0';
07160       tmp->matchcid = 0;
07161    }
07162    tmp->app = p;
07163    strcpy(p, application);
07164    tmp->parent = con;
07165    tmp->data = data;
07166    tmp->datad = datad;
07167    tmp->registrar = registrar;
07168 
07169    if (lockconts) {
07170       ast_wrlock_context(con);
07171    }
07172    
07173    if (con->pattern_tree) { /* usually, on initial load, the pattern_tree isn't formed until the first find_exten; so if we are adding
07174                         an extension, and the trie exists, then we need to incrementally add this pattern to it. */
07175       ast_copy_string(dummy_name, extension, sizeof(dummy_name));
07176       dummy_exten.exten = dummy_name;
07177       dummy_exten.matchcid = 0;
07178       dummy_exten.cidmatch = 0;
07179       tmp2 = ast_hashtab_lookup(con->root_table, &dummy_exten);
07180       if (!tmp2) {
07181          /* hmmm, not in the trie; */
07182          add_exten_to_pattern_tree(con, tmp, 0);
07183          ast_hashtab_insert_safe(con->root_table, tmp); /* for the sake of completeness */
07184       }
07185    }
07186    res = 0; /* some compilers will think it is uninitialized otherwise */
07187    for (e = con->root; e; el = e, e = e->next) {   /* scan the extension list */
07188       res = ext_cmp(e->exten, tmp->exten);
07189       if (res == 0) { /* extension match, now look at cidmatch */
07190          if (!e->matchcid && !tmp->matchcid)
07191             res = 0;
07192          else if (tmp->matchcid && !e->matchcid)
07193             res = 1;
07194          else if (e->matchcid && !tmp->matchcid)
07195             res = -1;
07196          else
07197             res = ext_cmp(e->cidmatch, tmp->cidmatch);
07198       }
07199       if (res >= 0)
07200          break;
07201    }
07202    if (e && res == 0) { /* exact match, insert in the pri chain */
07203       res = add_pri(con, tmp, el, e, replace);
07204       if (lockconts) {
07205          ast_unlock_context(con);
07206       }
07207       if (res < 0) {
07208          errno = EEXIST;   /* XXX do we care ? */
07209          return 0; /* XXX should we return -1 maybe ? */
07210       }
07211    } else {
07212       /*
07213        * not an exact match, this is the first entry with this pattern,
07214        * so insert in the main list right before 'e' (if any)
07215        */
07216       tmp->next = e;
07217       if (el) {  /* there is another exten already in this context */
07218          el->next = tmp;
07219          tmp->peer_table = ast_hashtab_create(13,
07220                      hashtab_compare_exten_numbers,
07221                      ast_hashtab_resize_java,
07222                      ast_hashtab_newsize_java,
07223                      hashtab_hash_priority,
07224                      0);
07225          tmp->peer_label_table = ast_hashtab_create(7,
07226                         hashtab_compare_exten_labels,
07227                         ast_hashtab_resize_java,
07228                         ast_hashtab_newsize_java,
07229                         hashtab_hash_labels,
07230                         0);
07231          if (label) {
07232             ast_hashtab_insert_safe(tmp->peer_label_table, tmp);
07233          }
07234          ast_hashtab_insert_safe(tmp->peer_table, tmp);
07235       } else {  /* this is the first exten in this context */
07236          if (!con->root_table)
07237             con->root_table = ast_hashtab_create(27,
07238                                        hashtab_compare_extens,
07239                                        ast_hashtab_resize_java,
07240                                        ast_hashtab_newsize_java,
07241                                        hashtab_hash_extens,
07242                                        0);
07243          con->root = tmp;
07244          con->root->peer_table = ast_hashtab_create(13,
07245                         hashtab_compare_exten_numbers,
07246                         ast_hashtab_resize_java,
07247                         ast_hashtab_newsize_java,
07248                         hashtab_hash_priority,
07249                         0);
07250          con->root->peer_label_table = ast_hashtab_create(7,
07251                            hashtab_compare_exten_labels,
07252                            ast_hashtab_resize_java,
07253                            ast_hashtab_newsize_java,
07254                            hashtab_hash_labels,
07255                            0);
07256          if (label) {
07257             ast_hashtab_insert_safe(con->root->peer_label_table, tmp);
07258          }
07259          ast_hashtab_insert_safe(con->root->peer_table, tmp);
07260             
07261       }
07262       ast_hashtab_insert_safe(con->root_table, tmp);
07263       if (lockconts) {
07264          ast_unlock_context(con);
07265       }
07266       if (tmp->priority == PRIORITY_HINT) {
07267          if (lockhints) {
07268             ast_add_hint(tmp);
07269          } else {
07270             ast_add_hint_nolock(tmp);
07271          }
07272       }
07273    }
07274    if (option_debug) {
07275       if (tmp->matchcid) {
07276          ast_debug(1, "Added extension '%s' priority %d (CID match '%s') to %s (%p)\n",
07277                  tmp->exten, tmp->priority, tmp->cidmatch, con->name, con);
07278       } else {
07279          ast_debug(1, "Added extension '%s' priority %d to %s (%p)\n",
07280                  tmp->exten, tmp->priority, con->name, con);
07281       }
07282    }
07283 
07284    if (tmp->matchcid) {
07285       ast_verb(3, "Added extension '%s' priority %d (CID match '%s') to %s (%p)\n",
07286              tmp->exten, tmp->priority, tmp->cidmatch, con->name, con);
07287    } else {
07288       ast_verb(3, "Added extension '%s' priority %d to %s (%p)\n",
07289              tmp->exten, tmp->priority, con->name, con);
07290    }
07291    
07292    return 0;
07293 }

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

References ast_add_extension2_lockopt(), and find_context().

Referenced by ast_merge_contexts_and_delete().

06743 {
06744    int ret = -1;
06745    struct ast_context *c = find_context(context);
06746 
06747    if (c) {
06748       ret = ast_add_extension2_lockopt(c, replace, extension, priority, label, callerid,
06749          application, data, datad, registrar, 0, 0);
06750    }
06751    
06752    return ret;
06753 }

static int ast_add_hint ( struct ast_exten e  )  [static]

Add hint to hint list, check initial extension state.

Definition at line 3568 of file pbx.c.

References ast_add_hint_nolock(), AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

Referenced by ast_add_extension2_lockopt().

03569 {
03570    int ret;
03571 
03572    AST_RWLIST_WRLOCK(&hints);
03573    ret = ast_add_hint_nolock(e);
03574    AST_RWLIST_UNLOCK(&hints);
03575    
03576    return ret;
03577 }

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

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

Referenced by ast_add_extension2_lockopt(), and ast_add_hint().

03540 {
03541    struct ast_hint *hint;
03542 
03543    if (!e)
03544       return -1;
03545 
03546    /* Search if hint exists, do nothing */
03547    AST_RWLIST_TRAVERSE(&hints, hint, list) {
03548       if (hint->exten == e) {
03549          ast_debug(2, "HINTS: Not re-adding existing hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e));
03550          return -1;
03551       }
03552    }
03553 
03554    ast_debug(2, "HINTS: Adding hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e));
03555 
03556    if (!(hint = ast_calloc(1, sizeof(*hint)))) {
03557       return -1;
03558    }
03559    /* Initialize and insert new item at the top */
03560    hint->exten = e;
03561    hint->laststate = ast_extension_state2(e);
03562    AST_RWLIST_INSERT_HEAD(&hints, hint, list);
03563 
03564    return 0;
03565 }

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

Definition at line 6798 of file pbx.c.

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

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

06799 {
06800    int res = 0;
06801 
06802    ast_channel_lock(chan);
06803 
06804    if (chan->pbx) { /* This channel is currently in the PBX */
06805       ast_explicit_goto(chan, context, exten, priority + 1);
06806       ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO);
06807    } else {
06808       /* In order to do it when the channel doesn't really exist within
06809          the PBX, we have to make a new channel, masquerade, and start the PBX
06810          at the new location */
06811       struct ast_channel *tmpchan = ast_channel_alloc(0, chan->_state, 0, 0, chan->accountcode, chan->exten, chan->context, chan->amaflags, "AsyncGoto/%s", chan->name);
06812       if (!tmpchan) {
06813          res = -1;
06814       } else {
06815          if (chan->cdr) {
06816             ast_cdr_discard(tmpchan->cdr);
06817             tmpchan->cdr = ast_cdr_dup(chan->cdr);  /* share the love */
06818          }
06819          /* Make formats okay */
06820          tmpchan->readformat = chan->readformat;
06821          tmpchan->writeformat = chan->writeformat;
06822          /* Setup proper location */
06823          ast_explicit_goto(tmpchan,
06824             S_OR(context, chan->context), S_OR(exten, chan->exten), priority);
06825 
06826          /* Masquerade into temp channel */
06827          if (ast_channel_masquerade(tmpchan, chan)) {
06828             /* Failed to set up the masquerade.  It's probably chan_local
06829              * in the middle of optimizing itself out.  Sad. :( */
06830             ast_hangup(tmpchan);
06831             tmpchan = NULL;
06832             res = -1;
06833          } else {
06834             /* Grab the locks and get going */
06835             ast_channel_lock(tmpchan);
06836             ast_do_masquerade(tmpchan);
06837             ast_channel_unlock(tmpchan);
06838             /* Start the PBX going on our stolen channel */
06839             if (ast_pbx_start(tmpchan)) {
06840                ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name);
06841                ast_hangup(tmpchan);
06842                res = -1;
06843             }
06844          }
06845       }
06846    }
06847    ast_channel_unlock(chan);
06848    return res;
06849 }

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

Definition at line 6851 of file pbx.c.

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

06852 {
06853    struct ast_channel *chan;
06854    int res = -1;
06855 
06856    chan = ast_get_channel_by_name_locked(channame);
06857    if (chan) {
06858       res = ast_async_goto(chan, context, exten, priority);
06859       ast_channel_unlock(chan);
06860    }
06861    return res;
06862 }

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

References __ast_goto_if_exists(), and chan.

09005 {
09006    return __ast_goto_if_exists(chan, context, exten, priority, 1);
09007 }

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

References chan, and pbx_parseable_goto().

Referenced by asyncgoto_exec().

09068 {
09069    return pbx_parseable_goto(chan, goto_string, 1);
09070 }

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

Definition at line 6419 of file pbx.c.

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

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

06420 {
06421    char info_save[256];
06422    char *info;
06423 
06424    /* Check for empty just in case */
06425    if (ast_strlen_zero(info_in))
06426       return 0;
06427    /* make a copy just in case we were passed a static string */
06428    ast_copy_string(info_save, info_in, sizeof(info_save));
06429    info = info_save;
06430    /* Assume everything except time */
06431    i->monthmask = 0xfff;   /* 12 bits */
06432    i->daymask = 0x7fffffffU; /* 31 bits */
06433    i->dowmask = 0x7f; /* 7 bits */
06434    /* on each call, use strsep() to move info to the next argument */
06435    get_timerange(i, strsep(&info, "|,"));
06436    if (info)
06437       i->dowmask = get_range(strsep(&info, "|,"), 7, days, "day of week");
06438    if (info)
06439       i->daymask = get_range(strsep(&info, "|,"), 31, NULL, "day");
06440    if (info)
06441       i->monthmask = get_range(strsep(&info, "|,"), 12, months, "month");
06442    return 1;
06443 }

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 3666 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(), skinny_ss(), ss_thread(), and valid_exit().

03667 {
03668    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0);
03669 }

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

Change hint for an extension.

Definition at line 3580 of file pbx.c.

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

03581 {
03582    struct ast_hint *hint;
03583    int res = -1;
03584 
03585    AST_RWLIST_WRLOCK(&hints);
03586    AST_RWLIST_TRAVERSE(&hints, hint, list) {
03587       if (hint->exten == oe) {
03588             hint->exten = ne;
03589          res = 0;
03590          break;
03591       }
03592    }
03593    AST_RWLIST_UNLOCK(&hints);
03594 
03595    return res;
03596 }

int ast_check_timing ( const struct ast_timing i  ) 

Definition at line 6445 of file pbx.c.

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

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

06446 {
06447    struct ast_tm tm;
06448    struct timeval now = ast_tvnow();
06449 
06450    ast_localtime(&now, &tm, NULL);
06451 
06452    /* If it's not the right month, return */
06453    if (!(i->monthmask & (1 << tm.tm_mon)))
06454       return 0;
06455 
06456    /* If it's not that time of the month.... */
06457    /* Warning, tm_mday has range 1..31! */
06458    if (!(i->daymask & (1 << (tm.tm_mday-1))))
06459       return 0;
06460 
06461    /* If it's not the right day of the week */
06462    if (!(i->dowmask & (1 << tm.tm_wday)))
06463       return 0;
06464 
06465    /* Sanity check the hour just to be safe */
06466    if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) {
06467       ast_log(LOG_WARNING, "Insane time...\n");
06468       return 0;
06469    }
06470 
06471    /* Now the tough part, we calculate if it fits
06472       in the right time based on min/hour */
06473    if (!(i->minmask[tm.tm_hour] & (1 << (tm.tm_min / 2))))
06474       return 0;
06475 
06476    /* If we got this far, then we're good */
06477    return 1;
06478 }

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

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

Referenced by handle_cli_dialplan_add_ignorepat().

06672 {
06673    int ret = -1;
06674    struct ast_context *c = find_context_locked(context);
06675 
06676    if (c) {
06677       ret = ast_context_add_ignorepat2(c, value, registrar);
06678       ast_unlock_contexts();
06679    }
06680    return ret;
06681 }

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

Definition at line 6683 of file pbx.c.

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

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

06684 {
06685    struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL;
06686    int length;
06687    char *pattern;
06688    length = sizeof(struct ast_ignorepat);
06689    length += strlen(value) + 1;
06690    if (!(ignorepat = ast_calloc(1, length)))
06691       return -1;
06692    /* The cast to char * is because we need to write the initial value.
06693     * The field is not supposed to be modified otherwise.  Also, gcc 4.2
06694     * sees the cast as dereferencing a type-punned pointer and warns about
06695     * it.  This is the workaround (we're telling gcc, yes, that's really
06696     * what we wanted to do).
06697     */
06698    pattern = (char *) ignorepat->pattern;
06699    strcpy(pattern, value);
06700    ignorepat->next = NULL;
06701    ignorepat->registrar = registrar;
06702    ast_wrlock_context(con);
06703    for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) {
06704       ignorepatl = ignorepatc;
06705       if (!strcasecmp(ignorepatc->pattern, value)) {
06706          /* Already there */
06707          ast_unlock_context(con);
06708          errno = EEXIST;
06709          return -1;
06710       }
06711    }
06712    if (ignorepatl)
06713       ignorepatl->next = ignorepat;
06714    else
06715       con->ignorepats = ignorepat;
06716    ast_unlock_context(con);
06717    return 0;
06718 
06719 }

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

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

Referenced by handle_cli_dialplan_add_include().

06226 {
06227    int ret = -1;
06228    struct ast_context *c = find_context_locked(context);
06229 
06230    if (c) {
06231       ret = ast_context_add_include2(c, include, registrar);
06232       ast_unlock_contexts();
06233    }
06234    return ret;
06235 }

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

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

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

06489 {
06490    struct ast_include *new_include;
06491    char *c;
06492    struct ast_include *i, *il = NULL; /* include, include_last */
06493    int length;
06494    char *p;
06495 
06496    length = sizeof(struct ast_include);
06497    length += 2 * (strlen(value) + 1);
06498 
06499    /* allocate new include structure ... */
06500    if (!(new_include = ast_calloc(1, length)))
06501       return -1;
06502    /* Fill in this structure. Use 'p' for assignments, as the fields
06503     * in the structure are 'const char *'
06504     */
06505    p = new_include->stuff;
06506    new_include->name = p;
06507    strcpy(p, value);
06508    p += strlen(value) + 1;
06509    new_include->rname = p;
06510    strcpy(p, value);
06511    /* Strip off timing info, and process if it is there */
06512    if ( (c = strchr(p, ',')) ) {
06513       *c++ = '\0';
06514            new_include->hastime = ast_build_timing(&(new_include->timing), c);
06515    }
06516    new_include->next      = NULL;
06517    new_include->registrar = registrar;
06518 
06519    ast_wrlock_context(con);
06520 
06521    /* ... go to last include and check if context is already included too... */
06522    for (i = con->includes; i; i = i->next) {
06523       if (!strcasecmp(i->name, new_include->name)) {
06524          ast_free(new_include);
06525          ast_unlock_context(con);
06526          errno = EEXIST;
06527          return -1;
06528       }
06529       il = i;
06530    }
06531 
06532    /* ... include new context into context list, unlock, return */
06533    if (il)
06534       il->next = new_include;
06535    else
06536       con->includes = new_include;
06537    ast_verb(3, "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con));
06538 
06539    ast_unlock_context(con);
06540 
06541    return 0;
06542 }

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

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

06550 {
06551    int ret = -1;
06552    struct ast_context *c = find_context_locked(context);
06553 
06554    if (c) { /* found, add switch to this context */
06555       ret = ast_context_add_switch2(c, sw, data, eval, registrar);
06556       ast_unlock_contexts();
06557    }
06558    return ret;
06559 }

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

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

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

06570 {
06571    struct ast_sw *new_sw;
06572    struct ast_sw *i;
06573    int length;
06574    char *p;
06575 
06576    length = sizeof(struct ast_sw);
06577    length += strlen(value) + 1;
06578    if (data)
06579       length += strlen(data);
06580    length++;
06581 
06582    /* allocate new sw structure ... */
06583    if (!(new_sw = ast_calloc(1, length)))
06584       return -1;
06585    /* ... fill in this structure ... */
06586    p = new_sw->stuff;
06587    new_sw->name = p;
06588    strcpy(new_sw->name, value);
06589    p += strlen(value) + 1;
06590    new_sw->data = p;
06591    if (data) {
06592       strcpy(new_sw->data, data);
06593       p += strlen(data) + 1;
06594    } else {
06595       strcpy(new_sw->data, "");
06596       p++;
06597    }
06598    new_sw->eval     = eval;
06599    new_sw->registrar = registrar;
06600 
06601    /* ... try to lock this context ... */
06602    ast_wrlock_context(con);
06603 
06604    /* ... go to last sw and check if context is already swd too... */
06605    AST_LIST_TRAVERSE(&con->alts, i, list) {
06606       if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) {
06607          ast_free(new_sw);
06608          ast_unlock_context(con);
06609          errno = EEXIST;
06610          return -1;
06611       }
06612    }
06613 
06614    /* ... sw new context into context list, unlock, return */
06615    AST_LIST_INSERT_TAIL(&con->alts, new_sw, list);
06616 
06617    ast_verb(3, "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con));
06618 
06619    ast_unlock_context(con);
06620 
06621    return 0;
06622 }

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

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

Referenced by __unload_module(), cleanup_stale_contexts(), parkinglot_destroy(), sla_destroy(), and unload_module().

struct ast_context* ast_context_find ( const char *  name  ) 

Find a context.

Parameters:
name name of the context to find
Will search for the context with the given name.

Returns:
the ast_context on success, NULL on failure.

Definition at line 2031 of file pbx.c.

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

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

02032 {
02033    struct ast_context *tmp = NULL;
02034    struct fake_context item;
02035 
02036    ast_copy_string(item.name, name, sizeof(item.name));
02037 
02038    ast_rdlock_contexts();
02039    if( contexts_table ) {
02040       tmp = ast_hashtab_lookup(contexts_table,&item);
02041    } else {
02042       while ( (tmp = ast_walk_contexts(tmp)) ) {
02043          if (!name || !strcasecmp(name, tmp->name))
02044             break;
02045       }
02046    }
02047    ast_unlock_contexts();
02048    return tmp;
02049 }

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

Register a new context or find an existing one.

Parameters:
extcontexts pointer to the ast_context structure pointer
exttable pointer to the hashtable that contains all the elements in extcontexts
name name of the new context
registrar registrar of the context
This function allows you to play in two environments: the global contexts (active dialplan) or an external context set of your choosing. To act on the external set, make sure extcontexts and exttable are set; for the globals, make sure both extcontexts and exttable are NULL.

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

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

Definition at line 5881 of file pbx.c.

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

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

05882 {
05883    struct ast_context *tmp, **local_contexts;
05884    struct fake_context search;
05885    int length = sizeof(struct ast_context) + strlen(name) + 1;
05886 
05887    if (!contexts_table) {
05888       contexts_table = ast_hashtab_create(17,
05889                                  ast_hashtab_compare_contexts, 
05890                                  ast_hashtab_resize_java,
05891                                  ast_hashtab_newsize_java,
05892                                  ast_hashtab_hash_contexts,
05893                                  0);
05894    }
05895    
05896    ast_copy_string(search.name, name, sizeof(search.name));
05897    if (!extcontexts) {
05898       ast_rdlock_contexts();
05899       local_contexts = &contexts;
05900       tmp = ast_hashtab_lookup(contexts_table, &search);
05901       ast_unlock_contexts();
05902       if (tmp) {
05903          tmp->refcount++;
05904          return tmp;
05905       }
05906    } else { /* local contexts just in a linked list; search there for the new context; slow, linear search, but not frequent */
05907       local_contexts = extcontexts;
05908       tmp = ast_hashtab_lookup(exttable, &search);
05909       if (tmp) {
05910          tmp->refcount++;
05911          return tmp;
05912       }
05913    }
05914    
05915    if ((tmp = ast_calloc(1, length))) {
05916       ast_rwlock_init(&tmp->lock);
05917       ast_mutex_init(&tmp->macrolock);
05918       strcpy(tmp->name, name);
05919       tmp->root = NULL;
05920       tmp->root_table = NULL;
05921       tmp->registrar = ast_strdup(registrar);
05922       tmp->includes = NULL;
05923       tmp->ignorepats = NULL;
05924       tmp->refcount = 1;
05925    } else {
05926       ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name);
05927       return NULL;
05928    }
05929    
05930    if (!extcontexts) {
05931       ast_wrlock_contexts();
05932       tmp->next = *local_contexts;
05933       *local_contexts = tmp;
05934       ast_hashtab_insert_safe(contexts_table, tmp); /*put this context into the tree */
05935       ast_unlock_contexts();
05936       ast_debug(1, "Registered context '%s'(%p) in table %p registrar: %s\n", tmp->name, tmp, contexts_table, registrar);
05937       ast_verb(3, "Registered extension context '%s' (%p) in table %p; registrar: %s\n", tmp->name, tmp, contexts_table, registrar);
05938    } else {
05939       tmp->next = *local_contexts;
05940       if (exttable)
05941          ast_hashtab_insert_immediate(exttable, tmp); /*put this context into the tree */
05942       
05943       *local_contexts = tmp;
05944       ast_debug(1, "Registered context '%s'(%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar);
05945       ast_verb(3, "Registered extension context '%s' (%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar);
05946    }
05947    return tmp;
05948 }

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

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

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

References ast_context_remove_extension_callerid().

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

04303 {
04304    return ast_context_remove_extension_callerid(context, extension, priority, NULL, 0, registrar);
04305 }

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

References ast_context_remove_extension_callerid2().

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

04330 {
04331    return ast_context_remove_extension_callerid2(con, extension, priority, NULL, 0, registrar, already_locked);
04332 }

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

04308 {
04309    int ret = -1; /* default error return */
04310    struct ast_context *c = find_context_locked(context);
04311 
04312    if (c) { /* ... remove extension ... */
04313       ret = ast_context_remove_extension_callerid2(c, extension, priority, callerid, matchcallerid, registrar, 1);
04314       ast_unlock_contexts();
04315    }
04316    return ret;
04317 }

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

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

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

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

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

Definition at line 6628 of file pbx.c.

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

Referenced by handle_cli_dialplan_remove_ignorepat().

06629 {
06630    int ret = -1;
06631    struct ast_context *c = find_context_locked(context);
06632 
06633    if (c) {
06634       ret = ast_context_remove_ignorepat2(c, ignorepat, registrar);
06635       ast_unlock_contexts();
06636    }
06637    return ret;
06638 }

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

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

06641 {
06642    struct ast_ignorepat *ip, *ipl = NULL;
06643 
06644    ast_wrlock_context(con);
06645 
06646    for (ip = con->ignorepats; ip; ip = ip->next) {
06647       if (!strcmp(ip->pattern, ignorepat) &&
06648          (!registrar || (registrar == ip->registrar))) {
06649          if (ipl) {
06650             ipl->next = ip->next;
06651             ast_free(ip);
06652          } else {
06653             con->ignorepats = ip->next;
06654             ast_free(ip);
06655          }
06656          ast_unlock_context(con);
06657          return 0;
06658       }
06659       ipl = ip;
06660    }
06661 
06662    ast_unlock_context(con);
06663    errno = EINVAL;
06664    return -1;
06665 }

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

Remove a context include.

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

Definition at line 4194 of file pbx.c.

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

Referenced by handle_cli_dialplan_remove_include().

04195 {
04196    int ret = -1;
04197    struct ast_context *c = find_context_locked(context);
04198 
04199    if (c) {
04200       /* found, remove include from this context ... */
04201       ret = ast_context_remove_include2(c, include, registrar);
04202       ast_unlock_contexts();
04203    }
04204    return ret;
04205 }

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

Removes an include by an ast_context structure.

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

Definition at line 4216 of file pbx.c.

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

Referenced by ast_context_remove_include().

04217 {
04218    struct ast_include *i, *pi = NULL;
04219    int ret = -1;
04220 
04221    ast_wrlock_context(con);
04222 
04223    /* find our include */
04224    for (i = con->includes; i; pi = i, i = i->next) {
04225       if (!strcmp(i->name, include) &&
04226             (!registrar || !strcmp(i->registrar, registrar))) {
04227          /* remove from list */
04228          ast_verb(3, "Removing inclusion of context '%s' in context '%s; registrar=%s'\n", include, ast_get_context_name(con), registrar);
04229          if (pi)
04230             pi->next = i->next;
04231          else
04232             con->includes = i->next;
04233          /* free include and return */
04234          ast_free(i);
04235          ret = 0;
04236          break;
04237       }
04238    }
04239 
04240    ast_unlock_context(con);
04241 
04242    return ret;
04243 }

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

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

04251 {
04252    int ret = -1; /* default error return */
04253    struct ast_context *c = find_context_locked(context);
04254 
04255    if (c) {
04256       /* remove switch from this context ... */
04257       ret = ast_context_remove_switch2(c, sw, data, registrar);
04258       ast_unlock_contexts();
04259    }
04260    return ret;
04261 }

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

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

Referenced by ast_context_remove_switch().

04272 {
04273    struct ast_sw *i;
04274    int ret = -1;
04275 
04276    ast_wrlock_context(con);
04277 
04278    /* walk switches */
04279    AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) {
04280       if (!strcmp(i->name, sw) && !strcmp(i->data, data) &&
04281          (!registrar || !strcmp(i->registrar, registrar))) {
04282          /* found, remove from list */
04283          ast_verb(3, "Removing switch '%s' from context '%s; registrar=%s'\n", sw, ast_get_context_name(con), registrar);
04284          AST_LIST_REMOVE_CURRENT(list);
04285          ast_free(i); /* free switch and return */
04286          ret = 0;
04287          break;
04288       }
04289    }
04290    AST_LIST_TRAVERSE_SAFE_END;
04291 
04292    ast_unlock_context(con);
04293 
04294    return ret;
04295 }

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

04535 {
04536    struct ast_context *c = NULL;
04537    int ret = -1;
04538    struct fake_context item;
04539 
04540    ast_rdlock_contexts();
04541 
04542    ast_copy_string(item.name, context, sizeof(item.name));
04543 
04544    c = ast_hashtab_lookup(contexts_table,&item);
04545    if (c)
04546       ret = 0;
04547 #ifdef NOTNOW
04548 
04549    while ((c = ast_walk_contexts(c))) {
04550       if (!strcmp(ast_get_context_name(c), context)) {
04551          ret = 0;
04552          break;
04553       }
04554    }
04555 
04556 #endif
04557    ast_unlock_contexts();
04558 
04559    /* if we found context, unlock macrolock */
04560    if (ret == 0) 
04561       ret = ast_mutex_unlock(&c->macrolock);
04562 
04563    return ret;
04564 }

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

08962 {
08963    struct ast_include *inc = NULL;
08964    int res = 0;
08965 
08966    while ( (inc = ast_walk_context_includes(con, inc)) ) {
08967       if (ast_context_find(inc->rname))
08968          continue;
08969 
08970       res = -1;
08971       ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n",
08972          ast_get_context_name(con), inc->rname);
08973       break;
08974    }
08975 
08976    return res;
08977 }

struct ast_custom_function* ast_custom_function_find ( const char *  name  ) 

Definition at line 2785 of file pbx.c.

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

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

02786 {
02787    struct ast_custom_function *acf = NULL;
02788 
02789    AST_RWLIST_RDLOCK(&acf_root);
02790    AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) {
02791       if (!strcmp(name, acf->name))
02792          break;
02793    }
02794    AST_RWLIST_UNLOCK(&acf_root);
02795 
02796    return acf;
02797 }

int ast_custom_function_unregister ( struct ast_custom_function acf  ) 

Unregister a custom function.

Definition at line 2799 of file pbx.c.

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

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

02800 {
02801    struct ast_custom_function *cur;
02802 
02803    if (!acf)
02804       return -1;
02805 
02806    AST_RWLIST_WRLOCK(&acf_root);
02807    if ((cur = AST_RWLIST_REMOVE(&acf_root, acf, acflist)))
02808       ast_verb(2, "Unregistered custom function %s\n", cur->name);
02809    AST_RWLIST_UNLOCK(&acf_root);
02810 
02811    return cur ? 0 : -1;
02812 }

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

03282 {
03283    switch (devstate) {
03284    case AST_DEVICE_ONHOLD:
03285       return AST_EXTENSION_ONHOLD;
03286    case AST_DEVICE_BUSY:
03287       return AST_EXTENSION_BUSY;
03288    case AST_DEVICE_UNAVAILABLE:
03289    case AST_DEVICE_UNKNOWN:
03290    case AST_DEVICE_INVALID:
03291       return AST_EXTENSION_UNAVAILABLE;
03292    case AST_DEVICE_RINGINUSE:
03293       return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING);
03294    case AST_DEVICE_RINGING:
03295       return AST_EXTENSION_RINGING;
03296    case AST_DEVICE_INUSE:
03297       return AST_EXTENSION_INUSE;
03298    case AST_DEVICE_NOT_INUSE:
03299       return AST_EXTENSION_NOT_INUSE;
03300    case AST_DEVICE_TOTAL: /* not a device state, included for completeness */
03301       break;
03302    }
03303 
03304    return AST_EXTENSION_NOT_INUSE;
03305 }

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 3651 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(), ss_thread(), and waitstream_core().

03652 {
03653    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0);
03654 }

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

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

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

06776 {
06777    if (!chan)
06778       return -1;
06779 
06780    ast_channel_lock(chan);
06781 
06782    if (!ast_strlen_zero(context))
06783       ast_copy_string(chan->context, context, sizeof(chan->context));
06784    if (!ast_strlen_zero(exten))
06785       ast_copy_string(chan->exten, exten, sizeof(chan->exten));
06786    if (priority > -1) {
06787       chan->priority = priority;
06788       /* see flag description in channel.h for explanation */
06789       if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP))
06790          chan->priority--;
06791    }
06792 
06793    ast_channel_unlock(chan);
06794 
06795    return 0;
06796 }

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

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

02009 {
02010    if (needmore != E_MATCHMORE && needmore != E_CANMATCH)
02011       ast_log(LOG_WARNING, "invalid argument %d\n", needmore);
02012    return extension_match_core(pattern, data, needmore);
02013 }

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

References ext_cmp().

Referenced by lua_extension_cmp().

01811 {
01812    return ext_cmp(a, b);
01813 }

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

02004 {
02005    return extension_match_core(pattern, data, E_MATCH);
02006 }

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

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

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

Definition at line 3343 of file pbx.c.

References ast_extension_state2(), and ast_hint_extension().

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

03344 {
03345    struct ast_exten *e;
03346 
03347    e = ast_hint_extension(c, context, exten);   /* Do we have a hint for this extension ? */
03348    if (!e)
03349       return -1;           /* No hint, return -1 */
03350 
03351    return ast_extension_state2(e);        /* Check all devices in the hint */
03352 }

static int ast_extension_state2 ( struct ast_exten e  )  [static]

Check state of extension by using hints.

Definition at line 3308 of file pbx.c.

References ast_copy_string(), ast_device_state(), ast_devstate_aggregate_add(), ast_devstate_aggregate_init(), ast_devstate_aggregate_result(), ast_devstate_to_extenstate(), ast_get_extension_app(), AST_MAX_EXTENSION, and strsep().

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

03309 {
03310    char hint[AST_MAX_EXTENSION] = "";
03311    char *cur, *rest;
03312    struct ast_devstate_aggregate agg;
03313 
03314    if (!e)
03315       return -1;
03316 
03317    ast_devstate_aggregate_init(&agg);
03318 
03319    ast_copy_string(hint, ast_get_extension_app(e), sizeof(hint));
03320 
03321    rest = hint;   /* One or more devices separated with a & character */
03322 
03323    while ( (cur = strsep(&rest, "&")) ) {
03324       ast_devstate_aggregate_add(&agg, ast_device_state(cur));
03325    }
03326 
03327    return ast_devstate_to_extenstate(ast_devstate_aggregate_result(&agg));
03328 }

const char* ast_extension_state2str ( int  extension_state  ) 

Return string representation of the state of an extension.

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

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

03332 {
03333    int i;
03334 
03335    for (i = 0; (i < ARRAY_LEN(extension_states)); i++) {
03336       if (extension_states[i].extension_state == extension_state)
03337          return extension_states[i].text;
03338    }
03339    return "Unknown";
03340 }

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

Registers a state change callback.

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

Return values:
-1 on failure
ID on success

Definition at line 3404 of file pbx.c.

References ast_exten::app, ast_add_extension(), ast_calloc, ast_free_ptr, ast_hint_extension(), AST_LIST_INSERT_HEAD, AST_LIST_TRAVERSE, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_strdup, ast_state_cb::callback, ast_hint::callbacks, ast_exten::cidmatch, ast_state_cb::data, ast_exten::data, ast_exten::exten, ast_hint::exten, ast_exten::label, ast_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().

03406 {
03407    struct ast_hint *hint;
03408    struct ast_state_cb *cblist;
03409    struct ast_exten *e;
03410 
03411    /* If there's no context and extension:  add callback to statecbs list */
03412    if (!context && !exten) {
03413       AST_RWLIST_WRLOCK(&hints);
03414 
03415       AST_LIST_TRAVERSE(&statecbs, cblist, entry) {
03416          if (cblist->callback == callback) {
03417             cblist->data = data;
03418             AST_RWLIST_UNLOCK(&hints);
03419             return 0;
03420          }
03421       }
03422 
03423       /* Now insert the callback */
03424       if (!(cblist = ast_calloc(1, sizeof(*cblist)))) {
03425          AST_RWLIST_UNLOCK(&hints);
03426          return -1;
03427       }
03428       cblist->id = 0;
03429       cblist->callback = callback;
03430       cblist->data = data;
03431 
03432       AST_LIST_INSERT_HEAD(&statecbs, cblist, entry);
03433 
03434       AST_RWLIST_UNLOCK(&hints);
03435 
03436       return 0;
03437    }
03438 
03439    if (!context || !exten)
03440       return -1;
03441 
03442    /* This callback type is for only one hint, so get the hint */
03443    e = ast_hint_extension(NULL, context, exten);
03444    if (!e) {
03445       return -1;
03446    }
03447 
03448    /* If this is a pattern, dynamically create a new extension for this
03449     * particular match.  Note that this will only happen once for each
03450     * individual extension, because the pattern will no longer match first.
03451     */
03452    if (e->exten[0] == '_') {
03453       ast_add_extension(e->parent->name, 0, exten, e->priority, e->label,
03454          e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr,
03455          e->registrar);
03456       e = ast_hint_extension(NULL, context, exten);
03457       if (!e || e->exten[0] == '_') {
03458          return -1;
03459       }
03460    }
03461 
03462    /* Find the hint in the list of hints */
03463    AST_RWLIST_WRLOCK(&hints);
03464 
03465    AST_RWLIST_TRAVERSE(&hints, hint, list) {
03466       if (hint->exten == e)
03467          break;
03468    }
03469 
03470    if (!hint) {
03471       /* We have no hint, sorry */
03472       AST_RWLIST_UNLOCK(&hints);
03473       return -1;
03474    }
03475 
03476    /* Now insert the callback in the callback list  */
03477    if (!(cblist = ast_calloc(1, sizeof(*cblist)))) {
03478       AST_RWLIST_UNLOCK(&hints);
03479       return -1;
03480    }
03481 
03482    cblist->id = stateid++;    /* Unique ID for this callback */
03483    cblist->callback = callback;  /* Pointer to callback routine */
03484    cblist->data = data;    /* Data for the callback */
03485 
03486    AST_LIST_INSERT_HEAD(&hint->callbacks, cblist, entry);
03487 
03488    AST_RWLIST_UNLOCK(&hints);
03489 
03490    return cblist->id;
03491 }

int ast_extension_state_del ( int  id,
ast_state_cb_type  callback 
)

Deletes a registered state change callback by ID.

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

Return values:
0 success
-1 failure

Definition at line 3494 of file pbx.c.

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

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

03495 {
03496    struct ast_state_cb *p_cur = NULL;
03497    int ret = -1;
03498 
03499    if (!id && !callback)
03500       return -1;
03501 
03502    AST_RWLIST_WRLOCK(&hints);
03503 
03504    if (!id) {  /* id == 0 is a callback without extension */
03505       AST_LIST_TRAVERSE_SAFE_BEGIN(&statecbs, p_cur, entry) {
03506          if (p_cur->callback == callback) {
03507             AST_LIST_REMOVE_CURRENT(entry);
03508             break;
03509          }
03510       }
03511       AST_LIST_TRAVERSE_SAFE_END;
03512    } else { /* callback with extension, find the callback based on ID */
03513       struct ast_hint *hint;
03514       AST_RWLIST_TRAVERSE(&hints, hint, list) {
03515          AST_LIST_TRAVERSE_SAFE_BEGIN(&hint->callbacks, p_cur, entry) {
03516             if (p_cur->id == id) {
03517                AST_LIST_REMOVE_CURRENT(entry);
03518                break;
03519             }
03520          }
03521          AST_LIST_TRAVERSE_SAFE_END;
03522 
03523          if (p_cur)
03524             break;
03525       }
03526    }
03527 
03528    if (p_cur) {
03529       ast_free(p_cur);
03530    }
03531 
03532    AST_RWLIST_UNLOCK(&hints);
03533 
03534    return ret;
03535 }

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

03657 {
03658    return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
03659 }

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

References E_FINDLABEL, and pbx_extension_helper().

Referenced by pbx_load_config().

03662 {
03663    return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
03664 }

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

executes a read operation on a function

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

Returns:
zero on success, non-zero on failure

Definition at line 2872 of file pbx.c.

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

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

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

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

executes a write operation on a function

Parameters:
chan Channel to execute on
function Data containing the function call string (will be modified)
value A value parameter to pass for writing
This application executes a function in write mode on a given channel.

Returns:
zero on success, non-zero on failure

Definition at line 2895 of file pbx.c.

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

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

02896 {
02897    char *copy = ast_strdupa(function);
02898    char *args = func_args(copy);
02899    struct ast_custom_function *acfptr = ast_custom_function_find(copy);
02900 
02901    if (acfptr == NULL)
02902       ast_log(LOG_ERROR, "Function %s not registered\n", copy);
02903    else if (!acfptr->write)
02904       ast_log(LOG_ERROR, "Function %s cannot be written to\n", copy);
02905    else {
02906       int res;
02907       struct ast_module_user *u = NULL;
02908       if (acfptr->mod)
02909          u = __ast_module_user_add(acfptr->mod, chan);
02910       res = acfptr->write(chan, copy, args, value);
02911       if (acfptr->mod && u)
02912          __ast_module_user_remove(acfptr->mod, u);
02913       return res;
02914    }
02915 
02916    return -1;
02917 }

const char* ast_get_context_name ( struct ast_context con  ) 

Definition at line 8813 of file pbx.c.

References ast_context::name.

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

08814 {
08815    return con ? con->name : NULL;
08816 }

const char* ast_get_context_registrar ( struct ast_context c  ) 

Definition at line 8851 of file pbx.c.

References ast_context::registrar.

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

08852 {
08853    return c ? c->registrar : NULL;
08854 }

const char* ast_get_extension_app ( struct ast_exten e  ) 

Definition at line 8881 of file pbx.c.

References ast_exten::app.

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

08882 {
08883    return e ? e->app : NULL;
08884 }

void* ast_get_extension_app_data ( struct ast_exten e  ) 

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

08887 {
08888    return e ? e->data : NULL;
08889 }

const char* ast_get_extension_cidmatch ( struct ast_exten e  ) 

Definition at line 8876 of file pbx.c.

References ast_exten::cidmatch.

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

08877 {
08878    return e ? e->cidmatch : NULL;
08879 }

struct ast_context* ast_get_extension_context ( struct ast_exten exten  ) 

Definition at line 8818 of file pbx.c.

References exten.

Referenced by handle_show_hint(), and handle_show_hints().

08819 {
08820    return exten ? exten->parent : NULL;
08821 }

const char* ast_get_extension_label ( struct ast_exten exten  ) 

Definition at line 8828 of file pbx.c.

References exten.

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

08829 {
08830    return exten ? exten->label : NULL;
08831 }

int ast_get_extension_matchcid ( struct ast_exten e  ) 

Definition at line 8871 of file pbx.c.

References ast_exten::matchcid.

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

08872 {
08873    return e ? e->matchcid : 0;
08874 }

const char* ast_get_extension_name ( struct ast_exten exten  ) 

Definition at line 8823 of file pbx.c.

References exten.

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

08824 {
08825    return exten ? exten->exten : NULL;
08826 }

int ast_get_extension_priority ( struct ast_exten exten  ) 

Definition at line 8843 of file pbx.c.

References exten.

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

08844 {
08845    return exten ? exten->priority : -1;
08846 }

const char* ast_get_extension_registrar ( struct ast_exten e  ) 

Definition at line 8856 of file pbx.c.

References ast_exten::registrar.

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

08857 {
08858    return e ? e->registrar : NULL;
08859 }

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

If an extension hint exists, return non-zero.

Parameters:
hint buffer for hint
maxlen size of hint buffer
name buffer for name portion of hint
maxnamelen size of name buffer
c this is not important
context which context to look in
exten which extension to search for
Returns:
If an extension within the given context with the priority PRIORITY_HINT is found a non zero value will be returned. Otherwise, 0 is returned.

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

03635 {
03636    struct ast_exten *e = ast_hint_extension(c, context, exten);
03637 
03638    if (e) {
03639       if (hint)
03640          ast_copy_string(hint, ast_get_extension_app(e), hintsize);
03641       if (name) {
03642          const char *tmp = ast_get_extension_app_data(e);
03643          if (tmp)
03644             ast_copy_string(name, tmp, namesize);
03645       }
03646       return -1;
03647    }
03648    return 0;
03649 }

const char* ast_get_ignorepat_name ( struct ast_ignorepat ip  ) 

Definition at line 8838 of file pbx.c.

References ast_ignorepat::pattern.

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

08839 {
08840    return ip ? ip->pattern : NULL;
08841 }

const char* ast_get_ignorepat_registrar ( struct ast_ignorepat ip  ) 

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

08867 {
08868    return ip ? ip->registrar : NULL;
08869 }

const char* ast_get_include_name ( struct ast_include inc  ) 

Definition at line 8833 of file pbx.c.

References ast_include::name.

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

08834 {
08835    return inc ? inc->name : NULL;
08836 }

const char* ast_get_include_registrar ( struct ast_include i  ) 

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

08862 {
08863    return i ? i->registrar : NULL;
08864 }

const char* ast_get_switch_data ( struct ast_sw sw  ) 

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

08897 {
08898    return sw ? sw->data : NULL;
08899 }

int ast_get_switch_eval ( struct ast_sw sw  ) 

Definition at line 8901 of file pbx.c.

References ast_sw::eval.

Referenced by context_merge_incls_swits_igps_other_registrars().

08902 {
08903    return sw->eval;
08904 }

const char* ast_get_switch_name ( struct ast_sw sw  ) 

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

08892 {
08893    return sw ? sw->name : NULL;
08894 }

const char* ast_get_switch_registrar ( struct ast_sw sw  ) 

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

08907 {
08908    return sw ? sw->registrar : NULL;
08909 }

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

References __ast_goto_if_exists(), and chan.

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

09000 {
09001    return __ast_goto_if_exists(chan, context, exten, priority, 0);
09002 }

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

Definition at line 351 of file pbx.c.

References ast_context::name.

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

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

unsigned int ast_hashtab_hash_contexts ( const void *  obj  ) 

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

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

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

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

03273 {
03274    struct ast_exten *e;
03275    ast_rdlock_contexts();
03276    e = ast_hint_extension_nolock(c, context, exten);
03277    ast_unlock_contexts();
03278    return e;
03279 }

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

Find hint for given extension in context.

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

03267 {
03268    struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */
03269    return pbx_find_extension(c, NULL, &q, context, exten, PRIORITY_HINT, NULL, "", E_MATCH);
03270 }

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

06722 {
06723    struct ast_context *con = ast_context_find(context);
06724    if (con) {
06725       struct ast_ignorepat *pat;
06726       for (pat = con->ignorepats; pat; pat = pat->next) {
06727          if (ast_extension_match(pat->pattern, pattern))
06728             return 1;
06729       }
06730    }
06731 
06732    return 0;
06733 }

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

References E_MATCHMORE, and pbx_extension_helper().

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

03672 {
03673    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0);
03674 }

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

References __ast_internal_context_destroy(), ast_add_extension_nolock(), ast_calloc, AST_EXTENSION_REMOVED, ast_free, ast_free_ptr, ast_hashtab_destroy(), ast_hashtab_end_traversal(), ast_hashtab_next(), ast_hashtab_start_traversal(), ast_hint_extension_nolock(), AST_LIST_APPEND_LIST, AST_LIST_EMPTY, AST_LIST_HEAD_INIT_VALUE, AST_LIST_INSERT_HEAD, AST_LIST_REMOVE_HEAD, ast_log(), ast_rdlock_contexts(), AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_strdup, ast_tvdiff_us(), ast_tvnow(), ast_unlock_contexts(), ast_verb, ast_wrlock_contexts(), ast_wrlock_contexts_version(), ast_state_cb::callback, ast_hint::callbacks, context_merge(), contexts, contexts_table, ast_state_cb::data, E_MATCH, ast_hint::exten, ast_exten::exten, store_hint::exten, ast_hint::laststate, store_hint::list, LOG_WARNING, ast_context::name, store_hint::next, ast_context::next, ast_exten::parent, pbx_find_extension(), PRIORITY_HINT, and pbx_find_info::stacklen.

Referenced by lua_reload_extensions(), and pbx_load_module().

06081 {
06082    double ft;
06083    struct ast_context *tmp, *oldcontextslist;
06084    struct ast_hashtab *oldtable;
06085    struct store_hints store = AST_LIST_HEAD_INIT_VALUE;
06086    struct store_hint *this;
06087    struct ast_hint *hint;
06088    struct ast_exten *exten;
06089    int length;
06090    struct ast_state_cb *thiscb;
06091    struct ast_hashtab_iter *iter;
06092    
06093    /* it is very important that this function hold the hint list lock _and_ the conlock
06094       during its operation; not only do we need to ensure that the list of contexts
06095       and extensions does not change, but also that no hint callbacks (watchers) are
06096       added or removed during the merge/delete process
06097 
06098       in addition, the locks _must_ be taken in this order, because there are already
06099       other code paths that use this order
06100    */
06101    
06102    struct timeval begintime, writelocktime, endlocktime, enddeltime;
06103    int wrlock_ver;
06104    
06105    begintime = ast_tvnow();
06106    ast_rdlock_contexts();
06107    iter = ast_hashtab_start_traversal(contexts_table);
06108    while ((tmp = ast_hashtab_next(iter))) {
06109       context_merge(extcontexts, exttable, tmp, registrar);
06110    }
06111    ast_hashtab_end_traversal(iter);
06112    wrlock_ver = ast_wrlock_contexts_version();
06113    
06114    ast_unlock_contexts(); /* this feels real retarded, but you must do
06115                        what you must do If this isn't done, the following 
06116                         wrlock is a guraranteed deadlock */
06117    ast_wrlock_contexts();
06118    if (ast_wrlock_contexts_version() > wrlock_ver+1) {
06119       ast_log(LOG_WARNING,"==================!!!!!!!!!!!!!!!Something changed the contexts in the middle of merging contexts!\n");
06120    }
06121    
06122    AST_RWLIST_WRLOCK(&hints);
06123    writelocktime = ast_tvnow();
06124 
06125    /* preserve all watchers for hints */
06126    AST_RWLIST_TRAVERSE(&hints, hint, list) {
06127       if (!AST_LIST_EMPTY(&hint->callbacks)) {
06128          length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2 + sizeof(*this);
06129          if (!(this = ast_calloc(1, length)))
06130             continue;
06131          /* this removes all the callbacks from the hint into this. */
06132          AST_LIST_APPEND_LIST(&this->callbacks, &hint->callbacks, entry);
06133          this->laststate = hint->laststate;
06134          this->context = this->data;
06135          strcpy(this->data, hint->exten->parent->name);
06136          this->exten = this->data + strlen(this->context) + 1;
06137          strcpy(this->exten, hint->exten->exten);
06138          AST_LIST_INSERT_HEAD(&store, this, list);
06139       }
06140    }
06141 
06142    /* save the old table and list */
06143    oldtable = contexts_table;
06144    oldcontextslist = contexts;
06145 
06146    /* move in the new table and list */
06147    contexts_table = exttable;
06148    contexts = *extcontexts;
06149    
06150    /* restore the watchers for hints that can be found; notify those that
06151       cannot be restored
06152    */
06153    while ((this = AST_LIST_REMOVE_HEAD(&store, list))) {
06154       struct pbx_find_info q = { .stacklen = 0 };
06155       exten = pbx_find_extension(NULL, NULL, &q, this->context, this->exten, PRIORITY_HINT, NULL, "", E_MATCH);
06156       /* If this is a pattern, dynamically create a new extension for this
06157        * particular match.  Note that this will only happen once for each
06158        * individual extension, because the pattern will no longer match first.
06159        */
06160       if (exten && exten->exten[0] == '_') {
06161          ast_add_extension_nolock(exten->parent->name, 0, this->exten, PRIORITY_HINT, NULL,
06162             0, exten->app, ast_strdup(exten->data), ast_free_ptr, exten->registrar);
06163          /* rwlocks are not recursive locks */
06164          exten = ast_hint_extension_nolock(NULL, this->context, this->exten);
06165       }
06166 
06167       /* Find the hint in the list of hints */
06168       AST_RWLIST_TRAVERSE(&hints, hint, list) {
06169          if (hint->exten == exten)
06170             break;
06171       }
06172       if (!exten || !hint) {
06173          /* this hint has been removed, notify the watchers */
06174          while ((thiscb = AST_LIST_REMOVE_HEAD(&this->callbacks, entry))) {
06175             thiscb->callback(this->context, this->exten, AST_EXTENSION_REMOVED, thiscb->data);
06176             ast_free(thiscb);
06177          }
06178       } else {
06179          AST_LIST_APPEND_LIST(&hint->callbacks, &this->callbacks, entry);
06180          hint->laststate = this->laststate;
06181       }
06182       ast_free(this);
06183    }
06184 
06185    AST_RWLIST_UNLOCK(&hints);
06186    ast_unlock_contexts();
06187    endlocktime = ast_tvnow();
06188    
06189    /* the old list and hashtab no longer are relevant, delete them while the rest of asterisk
06190       is now freely using the new stuff instead */
06191    
06192    ast_hashtab_destroy(oldtable, NULL);
06193    
06194    for (tmp = oldcontextslist; tmp; ) {
06195       struct ast_context *next;  /* next starting point */
06196       next = tmp->next;
06197       __ast_internal_context_destroy(tmp);
06198       tmp = next;
06199    }
06200    enddeltime = ast_tvnow();
06201    
06202    ft = ast_tvdiff_us(writelocktime, begintime);
06203    ft /= 1000000.0;
06204    ast_verb(3,"Time to scan old dialplan and merge leftovers back into the new: %8.6f sec\n", ft);
06205    
06206    ft = ast_tvdiff_us(endlocktime, writelocktime);
06207    ft /= 1000000.0;
06208    ast_verb(3,"Time to restore hints and swap in new dialplan: %8.6f sec\n", ft);
06209 
06210    ft = ast_tvdiff_us(enddeltime, endlocktime);
06211    ft /= 1000000.0;
06212    ast_verb(3,"Time to delete the old dialplan: %8.6f sec\n", ft);
06213 
06214    ft = ast_tvdiff_us(enddeltime, begintime);
06215    ft /= 1000000.0;
06216    ast_verb(3,"Total time merge_contexts_delete: %8.6f sec\n", ft);
06217    return;
06218 }

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

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

This function will handle locking the channel as needed.

Definition at line 9062 of file pbx.c.

References chan, and pbx_parseable_goto().

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

09063 {
09064    return pbx_parseable_goto(chan, goto_string, 0);
09065 }

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

References __ast_request_and_dial(), ast_calloc, ast_cdr_disposition(), ast_cdr_failed(), ast_cdr_setaccount(), ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_free, ast_hangup(), ast_log(), ast_pbx_outgoing_cdr_failed(), ast_pbx_run_app(), ast_pthread_create_detached, ast_set_variables(), AST_STATE_UP, ast_strlen_zero(), ast_variables_destroy(), ast_verb, async_wait(), chan, errno, LOG_WARNING, and outgoing_helper::vars.

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

07560 {
07561    struct ast_channel *chan;
07562    struct app_tmp *tmp;
07563    int res = -1, cdr_res = -1;
07564    struct outgoing_helper oh;
07565 
07566    memset(&oh, 0, sizeof(oh));
07567    oh.vars = vars;
07568    oh.account = account;
07569 
07570    if (locked_channel)
07571       *locked_channel = NULL;
07572    if (ast_strlen_zero(app)) {
07573       res = -1;
07574       goto outgoing_app_cleanup;
07575    }
07576    if (synchronous) {
07577       chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
07578       if (chan) {
07579          ast_set_variables(chan, vars);
07580          if (account)
07581             ast_cdr_setaccount(chan, account);
07582          if (chan->_state == AST_STATE_UP) {
07583             res = 0;
07584             ast_verb(4, "Channel %s was answered.\n", chan->name);
07585             tmp = ast_calloc(1, sizeof(*tmp));
07586             if (!tmp)
07587                res = -1;
07588             else {
07589                ast_copy_string(tmp->app, app, sizeof(tmp->app));
07590                if (appdata)
07591                   ast_copy_string(tmp->data, appdata, sizeof(tmp->data));
07592                tmp->chan = chan;
07593                if (synchronous > 1) {
07594                   if (locked_channel)
07595                      ast_channel_unlock(chan);
07596                   ast_pbx_run_app(tmp);
07597                } else {
07598                   if (locked_channel)
07599                      ast_channel_lock(chan);
07600                   if (ast_pthread_create_detached(&tmp->t, NULL, ast_pbx_run_app, tmp)) {
07601                      ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno));
07602                      ast_free(tmp);
07603                      if (locked_channel)
07604                         ast_channel_unlock(chan);
07605                      ast_hangup(chan);
07606                      res = -1;
07607                   } else {
07608                      if (locked_channel)
07609                         *locked_channel = chan;
07610                   }
07611                }
07612             }
07613          } else {
07614             ast_verb(4, "Channel %s was never answered.\n", chan->name);
07615             if (chan->cdr) { /* update the cdr */
07616                /* here we update the status of the call, which sould be busy.
07617                 * if that fails then we set the status to failed */
07618                if (ast_cdr_disposition(chan->cdr, chan->hangupcause))
07619                   ast_cdr_failed(chan->cdr);
07620             }
07621             ast_hangup(chan);
07622          }
07623       }
07624 
07625       if (res < 0) { /* the call failed for some reason */
07626          if (*reason == 0) { /* if the call failed (not busy or no answer)
07627                         * update the cdr with the failed message */
07628             cdr_res = ast_pbx_outgoing_cdr_failed();
07629             if (cdr_res != 0) {
07630                res = cdr_res;
07631                goto outgoing_app_cleanup;
07632             }
07633          }
07634       }
07635 
07636    } else {
07637       struct async_stat *as;
07638       if (!(as = ast_calloc(1, sizeof(*as)))) {
07639          res = -1;
07640          goto outgoing_app_cleanup;
07641       }
07642       chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
07643       if (!chan) {
07644          ast_free(as);
07645          res = -1;
07646          goto outgoing_app_cleanup;
07647       }
07648       as->chan = chan;
07649       ast_copy_string(as->app, app, sizeof(as->app));
07650       if (appdata)
07651          ast_copy_string(as->appdata,  appdata, sizeof(as->appdata));
07652       as->timeout = timeout;
07653       ast_set_variables(chan, vars);
07654       if (account)
07655          ast_cdr_setaccount(chan, account);
07656       /* Start a new thread, and get something handling this channel. */
07657       if (locked_channel)
07658          ast_channel_lock(chan);
07659       if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) {
07660          ast_log(LOG_WARNING, "Failed to start async wait\n");
07661          ast_free(as);
07662          if (locked_channel)
07663             ast_channel_unlock(chan);
07664          ast_hangup(chan);
07665          res = -1;
07666          goto outgoing_app_cleanup;
07667       } else {
07668          if (locked_channel)
07669             *locked_channel = chan;
07670       }
07671       res = 0;
07672    }
07673 outgoing_app_cleanup:
07674    ast_variables_destroy(vars);
07675    return res;
07676 }

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

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

Referenced by ast_pbx_outgoing_app(), and ast_pbx_outgoing_exten().

07368 {
07369    /* allocate a channel */
07370    struct ast_channel *chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "%s", "");
07371 
07372    if (!chan)
07373       return -1;  /* failure */
07374 
07375    if (!chan->cdr) {
07376       /* allocation of the cdr failed */
07377       ast_channel_free(chan);   /* free the channel */
07378       return -1;                /* return failure */
07379    }
07380 
07381    /* allocation of the cdr was successful */
07382    ast_cdr_init(chan->cdr, chan);  /* initialize our channel's cdr */
07383    ast_cdr_start(chan->cdr);       /* record the start and stop time */
07384    ast_cdr_end(chan->cdr);
07385    ast_cdr_failed(chan->cdr);      /* set the status to failed */
07386    ast_cdr_detach(chan->cdr);      /* post and free the record */
07387    chan->cdr = NULL;
07388    ast_channel_free(chan);         /* free the channel */
07389 
07390    return 0;  /* success */
07391 }

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

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

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

07394 {
07395    struct ast_channel *chan;
07396    struct async_stat *as;
07397    int res = -1, cdr_res = -1;
07398    struct outgoing_helper oh;
07399 
07400    if (synchronous) {
07401       oh.context = context;
07402       oh.exten = exten;
07403       oh.priority = priority;
07404       oh.cid_num = cid_num;
07405       oh.cid_name = cid_name;
07406       oh.account = account;
07407       oh.vars = vars;
07408       oh.parent_channel = NULL;
07409 
07410       chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
07411       if (channel) {
07412          *channel = chan;
07413          if (chan)
07414             ast_channel_lock(chan);
07415       }
07416       if (chan) {
07417          if (chan->_state == AST_STATE_UP) {
07418                res = 0;
07419             ast_verb(4, "Channel %s was answered.\n", chan->name);
07420 
07421             if (synchronous > 1) {
07422                if (channel)
07423                   ast_channel_unlock(chan);
07424                if (ast_pbx_run(chan)) {
07425                   ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name);
07426                   if (channel)
07427                      *channel = NULL;
07428                   ast_hangup(chan);
07429                   chan = NULL;
07430                   res = -1;
07431                }
07432             } else {
07433                if (ast_pbx_start(chan)) {
07434                   ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name);
07435                   if (channel) {
07436                      *channel = NULL;
07437                      ast_channel_unlock(chan);
07438                   }
07439                   ast_hangup(chan);
07440                   res = -1;
07441                }
07442                chan = NULL;
07443             }
07444          } else {
07445             ast_verb(4, "Channel %s was never answered.\n", chan->name);
07446 
07447             if (chan->cdr) { /* update the cdr */
07448                /* here we update the status of the call, which sould be busy.
07449                 * if that fails then we set the status to failed */
07450                if (ast_cdr_disposition(chan->cdr, chan->hangupcause))
07451                   ast_cdr_failed(chan->cdr);
07452             }
07453 
07454             if (channel) {
07455                *channel = NULL;
07456                ast_channel_unlock(chan);
07457             }
07458             ast_hangup(chan);
07459             chan = NULL;
07460          }
07461       }
07462 
07463       if (res < 0) { /* the call failed for some reason */
07464          if (*reason == 0) { /* if the call failed (not busy or no answer)
07465                         * update the cdr with the failed message */
07466             cdr_res = ast_pbx_outgoing_cdr_failed();
07467             if (cdr_res != 0) {
07468                res = cdr_res;
07469                goto outgoing_exten_cleanup;
07470             }
07471          }
07472 
07473          /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */
07474          /* check if "failed" exists */
07475          if (ast_exists_extension(chan, context, "failed", 1, NULL)) {
07476             chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "OutgoingSpoolFailed");
07477             if (chan) {
07478                char failed_reason[4] = "";
07479                if (!ast_strlen_zero(context))
07480                   ast_copy_string(chan->context, context, sizeof(chan->context));
07481                set_ext_pri(chan, "failed", 1);
07482                ast_set_variables(chan, vars);
07483                snprintf(failed_reason, sizeof(failed_reason), "%d", *reason);
07484                pbx_builtin_setvar_helper(chan, "REASON", failed_reason);
07485                if (account)
07486                   ast_cdr_setaccount(chan, account);
07487                if (ast_pbx_run(chan)) {
07488                   ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name);
07489                   ast_hangup(chan);
07490                }
07491                chan = NULL;
07492             }
07493          }
07494       }
07495    } else {
07496       if (!(as = ast_calloc(1, sizeof(*as)))) {
07497          res = -1;
07498          goto outgoing_exten_cleanup;
07499       }
07500       chan = ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name);
07501       if (channel) {
07502          *channel = chan;
07503          if (chan)
07504             ast_channel_lock(chan);
07505       }
07506       if (!chan) {
07507          ast_free(as);
07508          res = -1;
07509          goto outgoing_exten_cleanup;
07510       }
07511       as->chan = chan;
07512       ast_copy_string(as->context, context, sizeof(as->context));
07513       set_ext_pri(as->chan,  exten, priority);
07514       as->timeout = timeout;
07515       ast_set_variables(chan, vars);
07516       if (account)
07517          ast_cdr_setaccount(chan, account);
07518       if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) {
07519          ast_log(LOG_WARNING, "Failed to start async wait\n");
07520          ast_free(as);
07521          if (channel) {
07522             *channel = NULL;
07523             ast_channel_unlock(chan);
07524          }
07525          ast_hangup(chan);
07526          res = -1;
07527          goto outgoing_exten_cleanup;
07528       }
07529       res = 0;
07530    }
07531 outgoing_exten_cleanup:
07532    ast_variables_destroy(vars);
07533    return res;
07534 }

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

04104 {
04105    return ast_pbx_run_args(c, NULL);
04106 }

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

run the application and free the descriptor once done

Definition at line 7544 of file pbx.c.

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

Referenced by ast_pbx_outgoing_app().

07545 {
07546    struct app_tmp *tmp = data;
07547    struct ast_app *app;
07548    app = pbx_findapp(tmp->app);
07549    if (app) {
07550       ast_verb(4, "Launching %s(%s) on %s\n", tmp->app, tmp->data, tmp->chan->name);
07551       pbx_exec(tmp->chan, app, tmp->data);
07552    } else
07553       ast_log(LOG_WARNING, "No such application '%s'\n", tmp->app);
07554    ast_hangup(tmp->chan);
07555    ast_free(tmp);
07556    return NULL;
07557 }

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

04089 {
04090    enum ast_pbx_result res = AST_PBX_SUCCESS;
04091 
04092    if (increase_call_count(c)) {
04093       return AST_PBX_CALL_LIMIT;
04094    }
04095 
04096    res = __ast_pbx_run(c, args);
04097 
04098    decrease_call_count();
04099 
04100    return res;
04101 }

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

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

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

04067 {
04068    pthread_t t;
04069 
04070    if (!c) {
04071       ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
04072       return AST_PBX_FAILED;
04073    }
04074 
04075    if (increase_call_count(c))
04076       return AST_PBX_CALL_LIMIT;
04077 
04078    /* Start a new thread, and get something handling this channel. */
04079    if (ast_pthread_create_detached(&t, NULL, pbx_thread, c)) {
04080       ast_log(LOG_WARNING, "Failed to create new channel thread\n");
04081       decrease_call_count();
04082       return AST_PBX_FAILED;
04083    }
04084 
04085    return AST_PBX_SUCCESS;
04086 }

int ast_processed_calls ( void   ) 

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

Definition at line 4113 of file pbx.c.

References totalcalls.

Referenced by handle_chanlist(), and handle_showcalls().

04114 {
04115    return totalcalls;
04116 }

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

08801 {
08802    return ast_rwlock_rdlock(&con->lock);
08803 }

int ast_rdlock_contexts ( void   ) 

Read locks the context list.

Return values:
0 on success
-1 on error

Definition at line 8782 of file pbx.c.

References ast_rwlock_rdlock(), and conlock.

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

08783 {
08784    return ast_rwlock_rdlock(&conlock);
08785 }

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

Register an application.

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

Definition at line 4567 of file pbx.c.

References ast_calloc, ast_log(), AST_RWLIST_INSERT_BEFORE_CURRENT, AST_RWLIST_INSERT_TAIL, AST_RWLIST_TRAVERSE, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_verb, COLOR_BRCYAN, ast_app::description, ast_app::execute, ast_app::list, LOG_WARNING, ast_app::module, ast_app::name, ast_app::synopsis, and term_color().

Referenced by ast_features_init(), and load_pbx().

04568 {
04569    struct ast_app *tmp, *cur = NULL;
04570    char tmps[80];
04571    int length, res;
04572 
04573    AST_RWLIST_WRLOCK(&apps);
04574    AST_RWLIST_TRAVERSE(&apps, tmp, list) {
04575       if (!(res = strcasecmp(app, tmp->name))) {
04576          ast_log(LOG_WARNING, "Already have an application '%s'\n", app);
04577          AST_RWLIST_UNLOCK(&apps);
04578          return -1;
04579       } else if (res < 0)
04580          break;
04581    }
04582 
04583    length = sizeof(*tmp) + strlen(app) + 1;
04584 
04585    if (!(tmp = ast_calloc(1, length))) {
04586       AST_RWLIST_UNLOCK(&apps);
04587       return -1;
04588    }
04589 
04590    strcpy(tmp->name, app);
04591    tmp->execute = execute;
04592    tmp->synopsis = synopsis;
04593    tmp->description = description;
04594    tmp->module = mod;
04595 
04596    /* Store in alphabetical order */
04597    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, cur, list) {
04598       if (strcasecmp(tmp->name, cur->name) < 0) {
04599          AST_RWLIST_INSERT_BEFORE_CURRENT(tmp, list);
04600          break;
04601       }
04602    }
04603    AST_RWLIST_TRAVERSE_SAFE_END;
04604    if (!cur)
04605       AST_RWLIST_INSERT_TAIL(&apps, tmp, list);
04606 
04607    ast_verb(2, "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps)));
04608 
04609    AST_RWLIST_UNLOCK(&apps);
04610 
04611    return 0;
04612 }

int ast_register_switch ( struct ast_switch sw  ) 

Register an alternative dialplan switch.

Parameters:
sw switch to register
This function registers a populated ast_switch structure with the asterisk switching architecture.

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

Definition at line 4618 of file pbx.c.

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

Referenced by load_module().

04619 {
04620    struct ast_switch *tmp;
04621 
04622    AST_RWLIST_WRLOCK(&switches);
04623    AST_RWLIST_TRAVERSE(&switches, tmp, list) {
04624       if (!strcasecmp(tmp->name, sw->name)) {
04625          AST_RWLIST_UNLOCK(&switches);
04626          ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name);
04627          return -1;
04628       }
04629    }
04630    AST_RWLIST_INSERT_TAIL(&switches, sw, list);
04631    AST_RWLIST_UNLOCK(&switches);
04632 
04633    return 0;
04634 }

static int ast_remove_hint ( struct ast_exten e  )  [static]

Remove hint from extension.

Definition at line 3599 of file pbx.c.

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

Referenced by destroy_exten().

03600 {
03601    /* Cleanup the Notifys if hint is removed */
03602    struct ast_hint *hint;
03603    struct ast_state_cb *cblist;
03604    int res = -1;
03605 
03606    if (!e)
03607       return -1;
03608 
03609    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&hints, hint, list) {
03610       if (hint->exten != e)
03611          continue;
03612 
03613       while ((cblist = AST_LIST_REMOVE_HEAD(&hint->callbacks, entry))) {
03614          /* Notify with -1 and remove all callbacks */
03615          cblist->callback(hint->exten->parent->name, hint->exten->exten, 
03616             AST_EXTENSION_DEACTIVATED, cblist->data);
03617          ast_free(cblist);
03618       }
03619 
03620       AST_RWLIST_REMOVE_CURRENT(list);
03621       ast_free(hint);
03622 
03623          res = 0;
03624 
03625       break;
03626    }
03627    AST_RWLIST_TRAVERSE_SAFE_END;
03628 
03629    return res;
03630 }

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

03677 {
03678    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN, found, combined_find_spawn);
03679 }

int ast_unlock_context ( struct ast_context con  ) 

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

Definition at line 8805 of file pbx.c.

References ast_rwlock_unlock(), and ast_context::lock.

Referenced by __ast_context_destroy(), _macro_exec(), ast_add_extension2_lockopt(), ast_context_add_ignorepat2(), ast_context_add_include2(), ast_context_add_switch2(), ast_context_remove_extension_callerid2(), ast_context_remove_ignorepat2(), ast_context_remove_include2(), ast_context_remove_switch2(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), dundi_precache_full(), find_matching_endwhile(), handle_cli_dialplan_save(), lookup_c_ip(), lookup_ci(), manager_show_dialplan_helper(), show_debug_helper(), and show_dialplan_helper().

08806 {
08807    return ast_rwlock_unlock(&con->lock);
08808 }

int ast_unlock_contexts ( void   ) 

Unlocks contexts.

Return values:
0 on success
-1 on failure

Definition at line 8787 of file pbx.c.

References ast_rwlock_unlock(), and conlock.

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

08788 {
08789    return ast_rwlock_unlock(&conlock);
08790 }

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

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

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

05862 {
05863    struct ast_app *tmp;
05864 
05865    AST_RWLIST_WRLOCK(&apps);
05866    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, tmp, list) {
05867       if (!strcasecmp(app, tmp->name)) {
05868          unreference_cached_app(tmp);
05869          AST_RWLIST_REMOVE_CURRENT(list);
05870          ast_verb(2, "Unregistered application '%s'\n", tmp->name);
05871          ast_free(tmp);
05872          break;
05873       }
05874    }
05875    AST_RWLIST_TRAVERSE_SAFE_END;
05876    AST_RWLIST_UNLOCK(&apps);
05877 
05878    return tmp ? 0 : -1;
05879 }

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

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

Referenced by __unload_module(), and unload_module().

04637 {
04638    AST_RWLIST_WRLOCK(&switches);
04639    AST_RWLIST_REMOVE(&switches, sw, list);
04640    AST_RWLIST_UNLOCK(&switches);
04641 }

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

Definition at line 8919 of file pbx.c.

References exten, and ast_context::root.

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

08921 {
08922    if (!exten)
08923       return con ? con->root : NULL;
08924    else
08925       return exten->next;
08926 }

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

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

08954 {
08955    if (!ip)
08956       return con ? con->ignorepats : NULL;
08957    else
08958       return ip->next;
08959 }

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

Definition at line 8943 of file pbx.c.

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

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

08945 {
08946    if (!inc)
08947       return con ? con->includes : NULL;
08948    else
08949       return inc->next;
08950 }

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

Definition at line 8928 of file pbx.c.

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

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

08930 {
08931    if (!sw)
08932       return con ? AST_LIST_FIRST(&con->alts) : NULL;
08933    else
08934       return AST_LIST_NEXT(sw, list);
08935 }

struct ast_context* ast_walk_contexts ( struct ast_context con  ) 

Definition at line 8914 of file pbx.c.

References contexts, and ast_context::next.

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

08915 {
08916    return con ? con->next : contexts;
08917 }

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

Definition at line 8937 of file pbx.c.

References exten, and ast_exten::priority.

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

08939 {
08940    return priority ? priority->peer : exten;
08941 }

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

08796 {
08797    return ast_rwlock_wrlock(&con->lock);
08798 }

int ast_wrlock_contexts ( void   ) 

Write locks the context list.

Return values:
0 on success
-1 on error

Definition at line 8774 of file pbx.c.

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

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

08775 {
08776    int res = ast_rwlock_wrlock(&conlock);
08777    if (!res)
08778       ast_atomic_fetchadd_int(&conlock_wrlock_version, 1);
08779    return res;
08780 }

int ast_wrlock_contexts_version ( void   ) 

Definition at line 8766 of file pbx.c.

Referenced by ast_merge_contexts_and_delete().

08767 {
08768    return conlock_wrlock_version;
08769 }

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

Definition at line 7306 of file pbx.c.

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

Referenced by ast_pbx_outgoing_app(), and ast_pbx_outgoing_exten().

07307 {
07308    struct async_stat *as = data;
07309    struct ast_channel *chan = as->chan;
07310    int timeout = as->timeout;
07311    int res;
07312    struct ast_frame *f;
07313    struct ast_app *app;
07314 
07315    while (timeout && (chan->_state != AST_STATE_UP)) {
07316       res = ast_waitfor(chan, timeout);
07317       if (res < 1)
07318          break;
07319       if (timeout > -1)
07320          timeout = res;
07321       f = ast_read(chan);
07322       if (!f)
07323          break;
07324       if (f->frametype == AST_FRAME_CONTROL) {
07325          if ((f->subclass == AST_CONTROL_BUSY)  ||
07326              (f->subclass == AST_CONTROL_CONGESTION) ) {
07327             ast_frfree(f);
07328             break;
07329          }
07330       }
07331       ast_frfree(f);
07332    }
07333    if (chan->_state == AST_STATE_UP) {
07334       if (!ast_strlen_zero(as->app)) {
07335          app = pbx_findapp(as->app);
07336          if (app) {
07337             ast_verb(3, "Launching %s(%s) on %s\n", as->app, as->appdata, chan->name);
07338             pbx_exec(chan, app, as->appdata);
07339          } else
07340             ast_log(LOG_WARNING, "No such application '%s'\n", as->app);
07341       } else {
07342          if (!ast_strlen_zero(as->context))
07343             ast_copy_string(chan->context, as->context, sizeof(chan->context));
07344          if (!ast_strlen_zero(as->exten))
07345             ast_copy_string(chan->exten, as->exten, sizeof(chan->exten));
07346          if (as->priority > 0)
07347             chan->priority = as->priority;
07348          /* Run the PBX */
07349          if (ast_pbx_run(chan)) {
07350             ast_log(LOG_ERROR, "Failed to start PBX on %s\n", chan->name);
07351          } else {
07352             /* PBX will have taken care of this */
07353             chan = NULL;
07354          }
07355       }
07356    }
07357    ast_free(as);
07358    if (chan)
07359       ast_hangup(chan);
07360    return NULL;
07361 }

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

Definition at line 1135 of file pbx.c.

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

Referenced by show_debug_helper().

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

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

collect digits from the channel into the buffer.

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

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

03696 {
03697    int digit;
03698 
03699    buf[pos] = '\0';  /* make sure it is properly terminated */
03700    while (ast_matchmore_extension(c, c->context, buf, 1, c->cid.cid_num)) {
03701       /* As long as we're willing to wait, and as long as it's not defined,
03702          keep reading digits until we can't possibly get a right answer anymore.  */
03703       digit = ast_waitfordigit(c, waittime);
03704       if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
03705          c->_softhangup = 0;
03706       } else {
03707          if (!digit) /* No entry */
03708             break;
03709          if (digit < 0) /* Error, maybe a  hangup */
03710             return -1;
03711          if (pos < buflen - 1) { /* XXX maybe error otherwise ? */
03712             buf[pos++] = digit;
03713             buf[pos] = '\0';
03714          }
03715          waittime = c->pbx->dtimeoutms;
03716       }
03717    }
03718    return 0;
03719 }

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

Definition at line 338 of file pbx.c.

Referenced by add_exten_to_pattern_tree().

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

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

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

Referenced by handle_show_hint().

04797 {
04798    struct ast_hint *hint;
04799    char *ret = NULL;
04800    int which = 0;
04801    int wordlen;
04802 
04803    if (pos != 3)
04804       return NULL;
04805    
04806    wordlen = strlen(word);
04807 
04808    AST_RWLIST_RDLOCK(&hints);
04809    /* walk through all hints */
04810    AST_RWLIST_TRAVERSE(&hints, hint, list) {
04811       if (!strncasecmp(word, ast_get_extension_name(hint->exten), wordlen) && ++which > state) {
04812          ret = ast_strdup(ast_get_extension_name(hint->exten));
04813          break;
04814       }
04815    }
04816    AST_RWLIST_UNLOCK(&hints);
04817 
04818    return ret;
04819 }

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

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

04994 {
04995    struct ast_context *c = NULL;
04996    char *ret = NULL;
04997    int which = 0;
04998    int wordlen;
04999 
05000    /* we are do completion of [exten@]context on second position only */
05001    if (pos != 2)
05002       return NULL;
05003 
05004    ast_rdlock_contexts();
05005 
05006    wordlen = strlen(word);
05007 
05008    /* walk through all contexts and return the n-th match */
05009    while ( (c = ast_walk_contexts(c)) ) {
05010       if (!strncasecmp(word, ast_get_context_name(c), wordlen) && ++which > state) {
05011          ret = ast_strdup(ast_get_context_name(c));
05012          break;
05013       }
05014    }
05015 
05016    ast_unlock_contexts();
05017 
05018    return ret;
05019 }

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

Definition at line 5996 of file pbx.c.

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

Referenced by ast_merge_contexts_and_delete().

05997 {
05998    struct ast_context *new = ast_hashtab_lookup(exttable, context); /* is there a match in the new set? */
05999    struct ast_exten *exten_item, *prio_item, *new_exten_item, *new_prio_item;
06000    struct ast_hashtab_iter *exten_iter;
06001    struct ast_hashtab_iter *prio_iter;
06002    int insert_count = 0;
06003    int first = 1;
06004    
06005    /* We'll traverse all the extensions/prios, and see which are not registrar'd with
06006       the current registrar, and copy them to the new context. If the new context does not
06007       exist, we'll create it "on demand". If no items are in this context to copy, then we'll
06008       only create the empty matching context if the old one meets the criteria */
06009    
06010    if (context->root_table) {
06011       exten_iter = ast_hashtab_start_traversal(context->root_table);
06012       while ((exten_item=ast_hashtab_next(exten_iter))) {
06013          if (new) {
06014             new_exten_item = ast_hashtab_lookup(new->root_table, exten_item);
06015          } else {
06016             new_exten_item = NULL;
06017          }
06018          prio_iter = ast_hashtab_start_traversal(exten_item->peer_table);
06019          while ((prio_item=ast_hashtab_next(prio_iter))) {
06020             int res1;
06021             char *dupdstr;
06022             
06023             if (new_exten_item) {
06024                new_prio_item = ast_hashtab_lookup(new_exten_item->peer_table, prio_item);
06025             } else {
06026                new_prio_item = NULL;
06027             }
06028             if (strcmp(prio_item->registrar,registrar) == 0) {
06029                continue;
06030             }
06031             /* make sure the new context exists, so we have somewhere to stick this exten/prio */
06032             if (!new) {
06033                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 */
06034             }
06035 
06036             /* copy in the includes, switches, and ignorepats */
06037             if (first) { /* but, only need to do this once */
06038                context_merge_incls_swits_igps_other_registrars(new, context, registrar);
06039                first = 0;
06040             }
06041             
06042             if (!new) {
06043                ast_log(LOG_ERROR,"Could not allocate a new context for %s in merge_and_delete! Danger!\n", context->name);
06044                return; /* no sense continuing. */
06045             }
06046             /* we will not replace existing entries in the new context with stuff from the old context.
06047                but, if this is because of some sort of registrar conflict, we ought to say something... */
06048             
06049             dupdstr = ast_strdup(prio_item->data);
06050             
06051             res1 = ast_add_extension2(new, 0, prio_item->exten, prio_item->priority, prio_item->label, 
06052                                 prio_item->matchcid ? prio_item->cidmatch : NULL, prio_item->app, dupdstr, prio_item->datad, prio_item->registrar);
06053             if (!res1 && new_exten_item && new_prio_item){
06054                ast_verb(3,"Dropping old dialplan item %s/%s/%d [%s(%s)] (registrar=%s) due to conflict with new dialplan\n",
06055                      context->name, prio_item->exten, prio_item->priority, prio_item->app, (char*)prio_item->data, prio_item->registrar);
06056             } else {
06057                /* 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,
06058                 and no double frees take place, either! */
06059                insert_count++;
06060             }
06061          }
06062          ast_hashtab_end_traversal(prio_iter);
06063       }
06064       ast_hashtab_end_traversal(exten_iter);
06065    }
06066    
06067    if (!insert_count && !new && (strcmp(context->registrar, registrar) != 0 ||
06068         (strcmp(context->registrar, registrar) == 0 && context->refcount > 1))) {
06069       /* we could have given it the registrar of the other module who incremented the refcount,
06070          but that's not available, so we give it the registrar we know about */
06071       new = ast_context_find_or_create(extcontexts, exttable, context->name, context->registrar);
06072       
06073       /* copy in the includes, switches, and ignorepats */
06074       context_merge_incls_swits_igps_other_registrars(new, context, registrar);
06075    }
06076 }

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

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

05964 {
05965    struct ast_include *i;
05966    struct ast_ignorepat *ip;
05967    struct ast_sw *sw;
05968    
05969    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);
05970    /* copy in the includes, switches, and ignorepats */
05971    /* walk through includes */
05972    for (i = NULL; (i = ast_walk_context_includes(old, i)) ; ) {
05973       if (strcmp(ast_get_include_registrar(i), registrar) == 0)
05974          continue; /* not mine */
05975       ast_context_add_include2(new, ast_get_include_name(i), ast_get_include_registrar(i));
05976    }
05977    
05978    /* walk through switches */
05979    for (sw = NULL; (sw = ast_walk_context_switches(old, sw)) ; ) {
05980       if (strcmp(ast_get_switch_registrar(sw), registrar) == 0)
05981          continue; /* not mine */
05982       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));
05983    }
05984    
05985    /* walk thru ignorepats ... */
05986    for (ip = NULL; (ip = ast_walk_context_ignorepats(old, ip)); ) {
05987       if (strcmp(ast_get_ignorepat_registrar(ip), registrar) == 0)
05988          continue; /* not mine */
05989       ast_context_add_ignorepat2(new, ast_get_ignorepat_name(ip), ast_get_ignorepat_registrar(ip));
05990    }
05991 }

static void create_match_char_tree ( struct ast_context con  )  [static]

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

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

static void decrease_call_count ( void   )  [static]

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

04025 {
04026    ast_mutex_lock(&maxcalllock);
04027    if (countcalls > 0)
04028       countcalls--;
04029    ast_mutex_unlock(&maxcalllock);
04030 }

static void destroy_exten ( struct ast_exten e  )  [static]

Definition at line 4032 of file pbx.c.

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

Referenced by __ast_internal_context_destroy(), and ast_context_remove_extension_callerid2().

04033 {
04034    if (e->priority == PRIORITY_HINT)
04035       ast_remove_hint(e);
04036 
04037    if (e->peer_table)
04038       ast_hashtab_destroy(e->peer_table,0);
04039    if (e->peer_label_table)
04040       ast_hashtab_destroy(e->peer_label_table, 0);
04041    if (e->datad)
04042       e->datad(e->data);
04043    ast_free(e);
04044 }

static void destroy_pattern_tree ( struct match_char pattern_tree  )  [static]

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

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

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

Definition at line 8712 of file pbx.c.

References ast_calloc, ast_event_get_ie_str(), AST_EVENT_IE_DEVICE, ast_free, ast_log(), ast_strlen_zero(), ast_taskprocessor_push(), device_state_tps, handle_statechange(), and LOG_ERROR.

Referenced by load_module(), and load_pbx().

08713 {
08714    const char *device;
08715    struct statechange *sc;
08716 
08717    device = ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE);
08718    if (ast_strlen_zero(device)) {
08719       ast_log(LOG_ERROR, "Received invalid event that had no device IE\n");
08720       return;
08721    }
08722 
08723    if (!(sc = ast_calloc(1, sizeof(*sc) + strlen(device) + 1)))
08724       return;
08725    strcpy(sc->dev, device);
08726    if (ast_taskprocessor_push(device_state_tps, handle_statechange, sc) < 0) {
08727       ast_free(sc);
08728    }
08729 }

static void exception_store_free ( void *  data  )  [static]

Definition at line 2583 of file pbx.c.

References ast_free, and ast_string_field_free_memory.

02584 {
02585    struct pbx_exception *exception = data;
02586    ast_string_field_free_memory(exception);
02587    ast_free(exception);
02588 }

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

the full routine to compare extensions in rules.

Definition at line 1777 of file pbx.c.

References ext_cmp1().

Referenced by ast_add_extension2_lockopt(), and ast_extension_cmp().

01778 {
01779    /* make sure non-patterns come first.
01780     * If a is not a pattern, it either comes first or
01781     * we do a more complex pattern comparison.
01782     */
01783    int ret = 0;
01784 
01785    if (a[0] != '_')
01786       return (b[0] == '_') ? -1 : strcmp(a, b);
01787 
01788    /* Now we know a is a pattern; if b is not, a comes first */
01789    if (b[0] != '_')
01790       return 1;
01791 
01792    /* ok we need full pattern sorting routine.
01793     * skip past the underscores */
01794    ++a; ++b;
01795    do {
01796       unsigned char bitwise[2][32] = { { 0, } };
01797       ret = ext_cmp1(&a, bitwise[0]) - ext_cmp1(&b, bitwise[1]);
01798       if (ret == 0) {
01799          /* Are the classes different, even though they score the same? */
01800          ret = memcmp(bitwise[0], bitwise[1], 32);
01801       }
01802    } while (!ret && a && b);
01803    if (ret == 0) {
01804       return 0;
01805    } else {
01806       return (ret > 0) ? 1 : -1;
01807    }
01808 }

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

References ast_log(), and LOG_WARNING.

Referenced by ext_cmp().

01698 {
01699    int c, cmin = 0xff, count = 0;
01700    const char *end;
01701 
01702    /* load value and advance pointer */
01703    c = *(*p)++;
01704 
01705    /* always return unless we have a set of chars */
01706    switch (toupper(c)) {
01707    default: /* ordinary character */
01708       bitwise[c / 8] = 1 << (c % 8);
01709       return 0x0100 | (c & 0xff);
01710 
01711    case 'N':   /* 2..9 */
01712       bitwise[6] = 0xfc;
01713       bitwise[7] = 0x03;
01714       return 0x0800 | '2';
01715 
01716    case 'X':   /* 0..9 */
01717       bitwise[6] = 0xff;
01718       bitwise[7] = 0x03;
01719       return 0x0A00 | '0';
01720 
01721    case 'Z':   /* 1..9 */
01722       bitwise[6] = 0xfe;
01723       bitwise[7] = 0x03;
01724       return 0x0900 | '1';
01725 
01726    case '.':   /* wildcard */
01727       return 0x10000;
01728 
01729    case '!':   /* earlymatch */
01730       return 0x20000;   /* less specific than NULL */
01731 
01732    case '\0':  /* empty string */
01733       *p = NULL;
01734       return 0x30000;
01735 
01736    case '[':   /* pattern */
01737       break;
01738    }
01739    /* locate end of set */
01740    end = strchr(*p, ']');  
01741 
01742    if (end == NULL) {
01743       ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n");
01744       return 0x40000;   /* XXX make this entry go last... */
01745    }
01746 
01747    for (; *p < end  ; (*p)++) {
01748       unsigned char c1, c2;   /* first-last char in range */
01749       c1 = (unsigned char)((*p)[0]);
01750       if (*p + 2 < end && (*p)[1] == '-') { /* this is a range */
01751          c2 = (unsigned char)((*p)[2]);
01752          *p += 2;    /* skip a total of 3 chars */
01753       } else {        /* individual character */
01754          c2 = c1;
01755       }
01756       if (c1 < cmin) {
01757          cmin = c1;
01758       }
01759       for (; c1 <= c2; c1++) {
01760          unsigned char mask = 1 << (c1 % 8);
01761          /*!\note If two patterns score the same, the one with the lowest
01762           * ascii values will compare as coming first. */
01763          /* Flag the character as included (used) and count it. */
01764          if (!(bitwise[ c1 / 8 ] & mask)) {
01765             bitwise[ c1 / 8 ] |= mask;
01766             count += 0x100;
01767          }
01768       }
01769    }
01770    (*p)++;
01771    return count == 0 ? 0x30000 : (count | cmin);
01772 }

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

copy a string skipping whitespace

Definition at line 6865 of file pbx.c.

Referenced by ast_add_extension2_lockopt().

06866 {
06867    int count = 0;
06868 
06869    while (*src && (count < len - 1)) {
06870       switch (*src) {
06871       case ' ':
06872          /* otherwise exten => [a-b],1,... doesn't work */
06873          /*    case '-': */
06874          /* Ignore */
06875          break;
06876       default:
06877          *dst = *src;
06878          dst++;
06879       }
06880       src++;
06881       count++;
06882    }
06883    *dst = '\0';
06884 
06885    return count;
06886 }

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

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

01992 {
01993    int i;
01994    static int prof_id = -2;   /* marker for 'unallocated' id */
01995    if (prof_id == -2)
01996       prof_id = ast_add_profile("ext_match", 0);
01997    ast_mark(prof_id, 1);
01998    i = _extension_match_core(pattern, data, mode);
01999    ast_mark(prof_id, 0);
02000    return i;
02001 }

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

lookup for a context with a given name,

Return values:
found context or NULL if not found.

Definition at line 4148 of file pbx.c.

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

Referenced by ast_add_extension_nolock().

04149 {
04150    struct ast_context *c = NULL;
04151    struct fake_context item;
04152 
04153    ast_copy_string(item.name, context, sizeof(item.name));
04154 
04155    c = ast_hashtab_lookup(contexts_table,&item);
04156 
04157    return c;
04158 }

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

lookup for a context with a given name,

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

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

04166 {
04167    struct ast_context *c = NULL;
04168    struct fake_context item;
04169 
04170    ast_copy_string(item.name, context, sizeof(item.name));
04171 
04172    ast_rdlock_contexts();
04173    c = ast_hashtab_lookup(contexts_table,&item);
04174 
04175 #ifdef NOTNOW
04176 
04177    while ( (c = ast_walk_contexts(c)) ) {
04178       if (!strcmp(ast_get_context_name(c), context))
04179          return c;
04180    }
04181 #endif
04182    if (!c)
04183       ast_unlock_contexts();
04184 
04185    return c;
04186 }

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

References ast_log(), and LOG_WARNING.

Referenced by ast_func_read(), and ast_func_write().

02856 {
02857    char *args = strchr(function, '(');
02858 
02859    if (!args)
02860       ast_log(LOG_WARNING, "Function '%s' doesn't contain parentheses.  Assuming null argument.\n", function);
02861    else {
02862       char *p;
02863       *args++ = '\0';
02864       if ((p = strrchr(args, ')')) )
02865          *p = '\0';
02866       else
02867          ast_log(LOG_WARNING, "Can't find trailing parenthesis for function '%s(%s'?\n", function, args);
02868    }
02869    return args;
02870 }

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

Definition at line 1164 of file pbx.c.

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

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

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

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

Referenced by ast_build_timing().

06260 {
06261    int s, e; /* start and ending position */
06262    unsigned int mask = 0;
06263 
06264    /* Check for whole range */
06265    if (ast_strlen_zero(src) || !strcmp(src, "*")) {
06266       s = 0;
06267       e = max - 1;
06268    } else {
06269       /* Get start and ending position */
06270       char *c = strchr(src, '-');
06271       if (c)
06272          *c++ = '\0';
06273       /* Find the start */
06274       s = lookup_name(src, names, max);
06275       if (!s) {
06276          ast_log(LOG_WARNING, "Invalid %s '%s', assuming none\n", msg, src);
06277          return 0;
06278       }
06279       s--;
06280       if (c) { /* find end of range */
06281          e = lookup_name(c, names, max);
06282          if (!e) {
06283             ast_log(LOG_WARNING, "Invalid end %s '%s', assuming none\n", msg, c);
06284             return 0;
06285          }
06286          e--;
06287       } else
06288          e = s;
06289    }
06290    /* Fill the mask. Remember that ranges are cyclic */
06291    mask = 1 << e; /* initialize with last element */
06292    while (s != e) {
06293       if (s >= max) {
06294          s = 0;
06295          mask |= (1 << s);
06296       } else {
06297          mask |= (1 << s);
06298          s++;
06299       }
06300    }
06301    return mask;
06302 }

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

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

Definition at line 6305 of file pbx.c.

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

Referenced by ast_build_timing().

06306 {
06307    char *e;
06308    int x;
06309    int s1, s2;
06310    int e1, e2;
06311    /* int cth, ctm; */
06312 
06313    /* start disabling all times, fill the fields with 0's, as they may contain garbage */
06314    memset(i->minmask, 0, sizeof(i->minmask));
06315 
06316    /* 2-minutes per bit, since the mask has only 32 bits :( */
06317    /* Star is all times */
06318    if (ast_strlen_zero(times) || !strcmp(times, "*")) {
06319       for (x = 0; x < 24; x++)
06320          i->minmask[x] = 0x3fffffff; /* 30 bits */
06321       return;
06322    }
06323    /* Otherwise expect a range */
06324    e = strchr(times, '-');
06325    if (!e) {
06326       ast_log(LOG_WARNING, "Time range is not valid. Assuming no restrictions based on time.\n");
06327       return;
06328    }
06329    *e++ = '\0';
06330    /* XXX why skip non digits ? */
06331    while (*e && !isdigit(*e))
06332       e++;
06333    if (!*e) {
06334       ast_log(LOG_WARNING, "Invalid time range.  Assuming no restrictions based on time.\n");
06335       return;
06336    }
06337    if (sscanf(times, "%2d:%2d", &s1, &s2) != 2) {
06338       ast_log(LOG_WARNING, "%s isn't a time.  Assuming no restrictions based on time.\n", times);
06339       return;
06340    }
06341    if (sscanf(e, "%2d:%2d", &e1, &e2) != 2) {
06342       ast_log(LOG_WARNING, "%s isn't a time.  Assuming no restrictions based on time.\n", e);
06343       return;
06344    }
06345    /* XXX this needs to be optimized */
06346 #if 1
06347    s1 = s1 * 30 + s2/2;
06348    if ((s1 < 0) || (s1 >= 24*30)) {
06349       ast_log(LOG_WARNING, "%s isn't a valid start time. Assuming no time.\n", times);
06350       return;
06351    }
06352    e1 = e1 * 30 + e2/2;
06353    if ((e1 < 0) || (e1 >= 24*30)) {
06354       ast_log(LOG_WARNING, "%s isn't a valid end time. Assuming no time.\n", e);
06355       return;
06356    }
06357    /* Go through the time and enable each appropriate bit */
06358    for (x=s1;x != e1;x = (x + 1) % (24 * 30)) {
06359       i->minmask[x/30] |= (1 << (x % 30));
06360    }
06361    /* Do the last one */
06362    i->minmask[x/30] |= (1 << (x % 30));
06363 #else
06364    for (cth = 0; cth < 24; cth++) {
06365       /* Initialize masks to blank */
06366       i->minmask[cth] = 0;
06367       for (ctm = 0; ctm < 30; ctm++) {
06368          if (
06369          /* First hour with more than one hour */
06370                (((cth == s1) && (ctm >= s2)) &&
06371                 ((cth < e1)))
06372          /* Only one hour */
06373          ||    (((cth == s1) && (ctm >= s2)) &&
06374                 ((cth == e1) && (ctm <= e2)))
06375          /* In between first and last hours (more than 2 hours) */
06376          ||    ((cth > s1) &&
06377                 (cth < e1))
06378          /* Last hour with more than one hour */
06379          ||    ((cth > s1) &&
06380                 ((cth == e1) && (ctm <= e2)))
06381          )
06382             i->minmask[cth] |= (1 << (ctm / 2));
06383       }
06384    }
06385 #endif
06386    /* All done */
06387    return;
06388 }

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

Send ack once.

Definition at line 5317 of file pbx.c.

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

05318 {
05319    char *exten = NULL, *context = NULL;
05320    /* Variables used for different counters */
05321    struct dialplan_counters counters;
05322    const char *incstack[AST_PBX_MAX_STACK];
05323 
05324    switch (cmd) {
05325    case CLI_INIT:
05326       e->command = "dialplan debug";
05327       e->usage = 
05328          "Usage: dialplan debug [context]\n"
05329          "       Show dialplan context Trie(s). Usually only useful to folks debugging the deep internals of the fast pattern matcher\n";
05330       return NULL;
05331    case CLI_GENERATE:   
05332       return complete_show_dialplan_context(a->line, a->word, a->pos, a->n);
05333    }
05334 
05335    memset(&counters, 0, sizeof(counters));
05336 
05337    if (a->argc != 2 && a->argc != 3)
05338       return CLI_SHOWUSAGE;
05339 
05340    /* we obtain [exten@]context? if yes, split them ... */
05341    /* note: we ignore the exten totally here .... */
05342    if (a->argc == 3) {
05343       if (strchr(a->argv[2], '@')) {   /* split into exten & context */
05344          context = ast_strdupa(a->argv[2]);
05345          exten = strsep(&context, "@");
05346          /* change empty strings to NULL */
05347          if (ast_strlen_zero(exten))
05348             exten = NULL;
05349       } else { /* no '@' char, only context given */
05350          context = a->argv[2];
05351       }
05352       if (ast_strlen_zero(context))
05353          context = NULL;
05354    }
05355    /* else Show complete dial plan, context and exten are NULL */
05356    show_debug_helper(a->fd, context, exten, &counters, NULL, 0, incstack);
05357 
05358    /* check for input failure and throw some error messages */
05359    if (context && !counters.context_existence) {
05360       ast_cli(a->fd, "There is no existence of '%s' context\n", context);
05361       return CLI_FAILURE;
05362    }
05363 
05364 
05365    ast_cli(a->fd,"-= %d %s. =-\n",
05366          counters.total_context, counters.total_context == 1 ? "context" : "contexts");
05367 
05368    /* everything ok */
05369    return CLI_SUCCESS;
05370 }

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

Definition at line 5711 of file pbx.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_channel_unlock, ast_cli(), ast_complete_channels(), ast_get_channel_by_name_locked(), chan, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, pbx_builtin_setvar_helper(), ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.

Referenced by handle_set_chanvar_deprecated().

05712 {
05713    struct ast_channel *chan;
05714    const char *chan_name, *var_name, *var_value;
05715 
05716    switch (cmd) {
05717    case CLI_INIT:
05718       e->command = "dialplan set chanvar";
05719       e->usage = 
05720          "Usage: dialplan set chanvar <channel> <varname> <value>\n"
05721          "       Set channel variable <varname> to <value>\n";
05722       return NULL;
05723    case CLI_GENERATE:
05724       return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
05725    }
05726 
05727    if (a->argc != e->args + 3)
05728       return CLI_SHOWUSAGE;
05729 
05730    chan_name = a->argv[e->args];
05731    var_name = a->argv[e->args + 1];
05732    var_value = a->argv[e->args + 2];
05733 
05734    if (!(chan = ast_get_channel_by_name_locked(chan_name))) {
05735       ast_cli(a->fd, "Channel '%s' not found\n", chan_name);
05736       return CLI_FAILURE;
05737    }
05738 
05739    pbx_builtin_setvar_helper(chan, var_name, var_value);
05740    ast_channel_unlock(chan);
05741    ast_cli(a->fd, "\n    -- Channel variable '%s' set to '%s' for '%s'\n",  var_name, var_value, chan_name);
05742 
05743    return CLI_SUCCESS;
05744 }

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

Definition at line 5746 of file pbx.c.

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

05747 {
05748    char *res = handle_set_chanvar(e, cmd, a);
05749    if (cmd == CLI_INIT)
05750       e->command = "core set chanvar";
05751    return res;
05752 }

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

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

05755 {
05756    int oldval = 0;
05757    
05758    switch (cmd) {
05759    case CLI_INIT:
05760       e->command = "dialplan set extenpatternmatchnew true";
05761       e->usage = 
05762          "Usage: dialplan set extenpatternmatchnew true|false\n"
05763          "       Use the NEW extension pattern matching algorithm, true or false.\n";
05764       return NULL;
05765    case CLI_GENERATE:
05766       return NULL;   
05767    }
05768 
05769    if (a->argc != 4)
05770       return CLI_SHOWUSAGE;
05771 
05772    oldval =  pbx_set_extenpatternmatchnew(1);
05773    
05774    if (oldval)
05775       ast_cli(a->fd, "\n    -- Still using the NEW pattern match algorithm for extension names in the dialplan.\n");
05776    else
05777       ast_cli(a->fd, "\n    -- Switched to using the NEW pattern match algorithm for extension names in the dialplan.\n");
05778 
05779    return CLI_SUCCESS;
05780 }

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

Definition at line 5681 of file pbx.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, pbx_builtin_setvar_helper(), and ast_cli_entry::usage.

Referenced by handle_set_global_deprecated().

05682 {
05683    switch (cmd) {
05684    case CLI_INIT:
05685       e->command = "dialplan set global";
05686       e->usage = 
05687          "Usage: dialplan set global <name> <value>\n"
05688          "       Set global dialplan variable <name> to <value>\n";
05689       return NULL;
05690    case CLI_GENERATE:
05691       return NULL;   
05692    }
05693 
05694    if (a->argc != e->args + 2)
05695       return CLI_SHOWUSAGE;
05696 
05697    pbx_builtin_setvar_helper(NULL, a->argv[3], a->argv[4]);
05698    ast_cli(a->fd, "\n    -- Global variable '%s' set to '%s'\n", a->argv[3], a->argv[4]);
05699 
05700    return CLI_SUCCESS;
05701 }

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

Definition at line 5703 of file pbx.c.

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

05704 {
05705    char *res = handle_set_global(e, cmd, a);
05706    if (cmd == CLI_INIT)
05707       e->command = "core set global";
05708    return res;
05709 }

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

Definition at line 4650 of file pbx.c.

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

04651 {
04652    struct ast_app *aa;
04653    int app, no_registered_app = 1;
04654    char *ret = NULL;
04655    int which = 0;
04656    int wordlen;
04657 
04658    switch (cmd) {
04659    case CLI_INIT: 
04660       e->command = "core show application";
04661       e->usage = 
04662          "Usage: core show application <application> [<application> [<application> [...]]]\n"
04663          "       Describes a particular application.\n";
04664       return NULL;
04665    case CLI_GENERATE:
04666       /*
04667        * There is a possibility to show informations about more than one
04668        * application at one time. You can type 'show application Dial Echo' and
04669        * you will see informations about these two applications ...
04670        */
04671       wordlen = strlen(a->word);
04672       /* return the n-th [partial] matching entry */
04673       AST_RWLIST_RDLOCK(&apps);
04674       AST_RWLIST_TRAVERSE(&apps, aa, list) {
04675          if (!strncasecmp(a->word, aa->name, wordlen) && ++which > a->n) {
04676             ret = ast_strdup(aa->name);
04677             break;
04678          }
04679       }
04680       AST_RWLIST_UNLOCK(&apps);
04681 
04682       return ret;
04683    }
04684 
04685    if (a->argc < 4)
04686       return CLI_SHOWUSAGE;
04687 
04688    /* ... go through all applications ... */
04689    AST_RWLIST_RDLOCK(&apps);
04690    AST_RWLIST_TRAVERSE(&apps, aa, list) {
04691       /* ... compare this application name with all arguments given
04692        * to 'show application' command ... */
04693       for (app = 3; app < a->argc; app++) {
04694          if (!strcasecmp(aa->name, a->argv[app])) {
04695             /* Maximum number of characters added by terminal coloring is 22 */
04696             char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40];
04697             char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL;
04698             int synopsis_size, description_size;
04699 
04700             no_registered_app = 0;
04701 
04702             if (aa->synopsis)
04703                synopsis_size = strlen(aa->synopsis) + 23;
04704             else
04705                synopsis_size = strlen("Not available") + 23;
04706             synopsis = alloca(synopsis_size);
04707 
04708             if (aa->description)
04709                description_size = strlen(aa->description) + 23;
04710             else
04711                description_size = strlen("Not available") + 23;
04712             description = alloca(description_size);
04713 
04714             if (synopsis && description) {
04715                snprintf(info, 64 + AST_MAX_APP, "\n  -= Info about application '%s' =- \n\n", aa->name);
04716                term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22);
04717                term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
04718                term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
04719                term_color(synopsis,
04720                            aa->synopsis ? aa->synopsis : "Not available",
04721                            COLOR_CYAN, 0, synopsis_size);
04722                term_color(description,
04723                            aa->description ? aa->description : "Not available",
04724                            COLOR_CYAN, 0, description_size);
04725 
04726                ast_cli(a->fd,"%s%s%s\n\n%s%s\n", infotitle, syntitle, synopsis, destitle, description);
04727             } else {
04728                /* ... one of our applications, show info ...*/
04729                ast_cli(a->fd,"\n  -= Info about application '%s' =- \n\n"
04730                   "[Synopsis]\n  %s\n\n"
04731                   "[Description]\n%s\n",
04732                   aa->name,
04733                   aa->synopsis ? aa->synopsis : "Not available",
04734                   aa->description ? aa->description : "Not available");
04735             }
04736          }
04737       }
04738    }
04739    AST_RWLIST_UNLOCK(&apps);
04740 
04741    /* we found at least one app? no? */
04742    if (no_registered_app) {
04743       ast_cli(a->fd, "Your application(s) is (are) not registered\n");
04744       return CLI_FAILURE;
04745    }
04746 
04747    return CLI_SUCCESS;
04748 }

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

Definition at line 4906 of file pbx.c.

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

04907 {
04908    struct ast_app *aa;
04909    int like = 0, describing = 0;
04910    int total_match = 0;    /* Number of matches in like clause */
04911    int total_apps = 0;  /* Number of apps registered */
04912    static char* choices[] = { "like", "describing", NULL };
04913 
04914    switch (cmd) {
04915    case CLI_INIT:
04916       e->command = "core show applications [like|describing]";
04917       e->usage = 
04918          "Usage: core show applications [{like|describing} <text>]\n"
04919          "       List applications which are currently available.\n"
04920          "       If 'like', <text> will be a substring of the app name\n"
04921          "       If 'describing', <text> will be a substring of the description\n";
04922       return NULL;
04923    case CLI_GENERATE:
04924       return (a->pos != 3) ? NULL : ast_cli_complete(a->word, choices, a->n);
04925    }
04926 
04927    AST_RWLIST_RDLOCK(&apps);
04928 
04929    if (AST_RWLIST_EMPTY(&apps)) {
04930       ast_cli(a->fd, "There are no registered applications\n");
04931       AST_RWLIST_UNLOCK(&apps);
04932       return CLI_SUCCESS;
04933    }
04934 
04935    /* core list applications like <keyword> */
04936    if ((a->argc == 5) && (!strcmp(a->argv[3], "like"))) {
04937       like = 1;
04938    } else if ((a->argc > 4) && (!strcmp(a->argv[3], "describing"))) {
04939       describing = 1;
04940    }
04941 
04942    /* core list applications describing <keyword1> [<keyword2>] [...] */
04943    if ((!like) && (!describing)) {
04944       ast_cli(a->fd, "    -= Registered Asterisk Applications =-\n");
04945    } else {
04946       ast_cli(a->fd, "    -= Matching Asterisk Applications =-\n");
04947    }
04948 
04949    AST_RWLIST_TRAVERSE(&apps, aa, list) {
04950       int printapp = 0;
04951       total_apps++;
04952       if (like) {
04953          if (strcasestr(aa->name, a->argv[4])) {
04954             printapp = 1;
04955             total_match++;
04956          }
04957       } else if (describing) {
04958          if (aa->description) {
04959             /* Match all words on command line */
04960             int i;
04961             printapp = 1;
04962             for (i = 4; i < a->argc; i++) {
04963                if (!strcasestr(aa->description, a->argv[i])) {
04964                   printapp = 0;
04965                } else {
04966                   total_match++;
04967                }
04968             }
04969          }
04970       } else {
04971          printapp = 1;
04972       }
04973 
04974       if (printapp) {
04975          ast_cli(a->fd,"  %20s: %s\n", aa->name, aa->synopsis ? aa->synopsis : "<Synopsis not available>");
04976       }
04977    }
04978    if ((!like) && (!describing)) {
04979       ast_cli(a->fd, "    -= %d Applications Registered =-\n",total_apps);
04980    } else {
04981       ast_cli(a->fd, "    -= %d Applications Matching =-\n",total_match);
04982    }
04983 
04984    AST_RWLIST_UNLOCK(&apps);
04985 
04986    return CLI_SUCCESS;
04987 }

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

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_channel_unlock, ast_cli(), ast_complete_channels(), ast_get_channel_by_name_locked(), ast_str_alloca, chan, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, pbx_builtin_serialize_variables(), ast_cli_args::pos, ast_str::str, ast_cli_entry::usage, and ast_cli_args::word.

05650 {
05651    struct ast_channel *chan = NULL;
05652    struct ast_str *vars = ast_str_alloca(BUFSIZ * 4); /* XXX large because we might have lots of channel vars */
05653 
05654    switch (cmd) {
05655    case CLI_INIT:
05656       e->command = "dialplan show chanvar";
05657       e->usage = 
05658          "Usage: dialplan show chanvar <channel>\n"
05659          "       List current channel variables and their values\n";
05660       return NULL;
05661    case CLI_GENERATE:
05662       return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
05663    }
05664 
05665    if (a->argc != e->args + 1)
05666       return CLI_SHOWUSAGE;
05667 
05668    if (!(chan = ast_get_channel_by_name_locked(a->argv[e->args]))) {
05669       ast_cli(a->fd, "Channel '%s' not found\n", a->argv[e->args]);
05670       return CLI_FAILURE;
05671    }
05672 
05673    pbx_builtin_serialize_variables(chan, &vars);
05674    if (vars->str) {
05675       ast_cli(a->fd, "\nVariables for channel %s:\n%s\n", a->argv[e->args], vars->str);
05676    }
05677    ast_channel_unlock(chan);
05678    return CLI_SUCCESS;
05679 }

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

Definition at line 5250 of file pbx.c.

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

05251 {
05252    char *exten = NULL, *context = NULL;
05253    /* Variables used for different counters */
05254    struct dialplan_counters counters;
05255    const char *incstack[AST_PBX_MAX_STACK];
05256 
05257    switch (cmd) {
05258    case CLI_INIT:
05259       e->command = "dialplan show";
05260       e->usage = 
05261          "Usage: dialplan show [[exten@]context]\n"
05262          "       Show dialplan\n";
05263       return NULL;
05264    case CLI_GENERATE:   
05265       return complete_show_dialplan_context(a->line, a->word, a->pos, a->n);
05266    }
05267 
05268    memset(&counters, 0, sizeof(counters));
05269 
05270    if (a->argc != 2 && a->argc != 3)
05271       return CLI_SHOWUSAGE;
05272 
05273    /* we obtain [exten@]context? if yes, split them ... */
05274    if (a->argc == 3) {
05275       if (strchr(a->argv[2], '@')) {   /* split into exten & context */
05276          context = ast_strdupa(a->argv[2]);
05277          exten = strsep(&context, "@");
05278          /* change empty strings to NULL */
05279          if (ast_strlen_zero(exten))
05280             exten = NULL;
05281       } else { /* no '@' char, only context given */
05282          context = a->argv[2];
05283       }
05284       if (ast_strlen_zero(context))
05285          context = NULL;
05286    }
05287    /* else Show complete dial plan, context and exten are NULL */
05288    show_dialplan_helper(a->fd, context, exten, &counters, NULL, 0, incstack);
05289 
05290    /* check for input failure and throw some error messages */
05291    if (context && !counters.context_existence) {
05292       ast_cli(a->fd, "There is no existence of '%s' context\n", context);
05293       return CLI_FAILURE;
05294    }
05295 
05296    if (exten && !counters.extension_existence) {
05297       if (context)
05298          ast_cli(a->fd, "There is no existence of %s@%s extension\n",
05299             exten, context);
05300       else
05301          ast_cli(a->fd,
05302             "There is no existence of '%s' extension in all contexts\n",
05303             exten);
05304       return CLI_FAILURE;
05305    }
05306 
05307    ast_cli(a->fd,"-= %d %s (%d %s) in %d %s. =-\n",
05308             counters.total_exten, counters.total_exten == 1 ? "extension" : "extensions",
05309             counters.total_prio, counters.total_prio == 1 ? "priority" : "priorities",
05310             counters.total_context, counters.total_context == 1 ? "context" : "contexts");
05311 
05312    /* everything ok */
05313    return CLI_SUCCESS;
05314 }

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

Definition at line 2704 of file pbx.c.

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

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

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

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

02663 {
02664    struct ast_custom_function *acf;
02665    int count_acf = 0;
02666    int like = 0;
02667 
02668    switch (cmd) {
02669    case CLI_INIT:
02670       e->command = "core show functions [like]";
02671       e->usage = 
02672          "Usage: core show functions [like <text>]\n"
02673          "       List builtin functions, optionally only those matching a given string\n";
02674       return NULL;
02675    case CLI_GENERATE:
02676       return NULL;
02677    }
02678 
02679    if (a->argc == 5 && (!strcmp(a->argv[3], "like")) ) {
02680       like = 1;
02681    } else if (a->argc != 3) {
02682       return CLI_SHOWUSAGE;
02683    }
02684 
02685    ast_cli(a->fd, "%s Custom Functions:\n--------------------------------------------------------------------------------\n", like ? "Matching" : "Installed");
02686 
02687    AST_RWLIST_RDLOCK(&acf_root);
02688    AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) {
02689       if (!like || strstr(acf->name, a->argv[4])) {
02690          count_acf++;
02691          ast_cli(a->fd, "%-20.20s  %-35.35s  %s\n",
02692             S_OR(acf->name, ""),
02693             S_OR(acf->syntax, ""),
02694             S_OR(acf->synopsis, ""));
02695       }
02696    }
02697    AST_RWLIST_UNLOCK(&acf_root);
02698 
02699    ast_cli(a->fd, "%d %scustom functions installed.\n", count_acf, like ? "matching " : "");
02700 
02701    return CLI_SUCCESS;
02702 }

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

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

Referenced by handle_show_globals_deprecated().

05583 {
05584    int i = 0;
05585    struct ast_var_t *newvariable;
05586 
05587    switch (cmd) {
05588    case CLI_INIT:
05589       e->command = "dialplan show globals";
05590       e->usage = 
05591          "Usage: dialplan show globals\n"
05592          "       List current global dialplan variables and their values\n";
05593       return NULL;
05594    case CLI_GENERATE:
05595       return NULL;
05596    }
05597 
05598    ast_rwlock_rdlock(&globalslock);
05599    AST_LIST_TRAVERSE (&globals, newvariable, entries) {
05600       i++;
05601       ast_cli(a->fd, "   %s=%s\n", ast_var_name(newvariable), ast_var_value(newvariable));
05602    }
05603    ast_rwlock_unlock(&globalslock);
05604    ast_cli(a->fd, "\n    -- %d variable(s)\n", i);
05605 
05606    return CLI_SUCCESS;
05607 }

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

Definition at line 5609 of file pbx.c.

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

05610 {
05611 
05612    char *res = handle_show_globals(e, cmd, a);
05613    if (cmd == CLI_INIT)
05614       e->command = "core show globals";
05615    return res;
05616 }

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

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

04823 {
04824    struct ast_hint *hint;
04825    int watchers;
04826    int num = 0, extenlen;
04827    struct ast_state_cb *watcher;
04828 
04829    switch (cmd) {
04830    case CLI_INIT:
04831       e->command = "core show hint";
04832       e->usage =
04833          "Usage: core show hint <exten>\n"
04834          "       List registered hint\n";
04835       return NULL;
04836    case CLI_GENERATE:
04837       return complete_core_show_hint(a->line, a->word, a->pos, a->n);
04838    }
04839 
04840    if (a->argc < 4)
04841       return CLI_SHOWUSAGE;
04842 
04843    AST_RWLIST_RDLOCK(&hints);
04844    if (AST_RWLIST_EMPTY(&hints)) {
04845       ast_cli(a->fd, "There are no registered dialplan hints\n");
04846       AST_RWLIST_UNLOCK(&hints);
04847       return CLI_SUCCESS;
04848    }
04849    extenlen = strlen(a->argv[3]);
04850    AST_RWLIST_TRAVERSE(&hints, hint, list) {
04851       if (!strncasecmp(ast_get_extension_name(hint->exten), a->argv[3], extenlen)) {
04852          watchers = 0;
04853          AST_LIST_TRAVERSE(&hint->callbacks, watcher, entry) {
04854             watchers++;
04855          }
04856          ast_cli(a->fd, "   %20s@%-20.20s: %-20.20s  State:%-15.15s Watchers %2d\n",
04857             ast_get_extension_name(hint->exten),
04858             ast_get_context_name(ast_get_extension_context(hint->exten)),
04859             ast_get_extension_app(hint->exten),
04860             ast_extension_state2str(hint->laststate), watchers);
04861          num++;
04862       }
04863    }
04864    AST_RWLIST_UNLOCK(&hints);
04865    if (!num)
04866       ast_cli(a->fd, "No hints matching extension %s\n", a->argv[3]);
04867    else
04868       ast_cli(a->fd, "%d hint%s matching extension %s\n", num, (num!=1 ? "s":""), a->argv[3]);
04869    return CLI_SUCCESS;
04870 }

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

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

04752 {
04753    struct ast_hint *hint;
04754    int num = 0;
04755    int watchers;
04756    struct ast_state_cb *watcher;
04757 
04758    switch (cmd) {
04759    case CLI_INIT:
04760       e->command = "core show hints";
04761       e->usage = 
04762          "Usage: core show hints\n"
04763          "       List registered hints\n";
04764       return NULL;
04765    case CLI_GENERATE:
04766       return NULL;   
04767    }
04768 
04769    AST_RWLIST_RDLOCK(&hints);
04770    if (AST_RWLIST_EMPTY(&hints)) {
04771       ast_cli(a->fd, "There are no registered dialplan hints\n");
04772       AST_RWLIST_UNLOCK(&hints);
04773       return CLI_SUCCESS;
04774    }
04775    /* ... we have hints ... */
04776    ast_cli(a->fd, "\n    -= Registered Asterisk Dial Plan Hints =-\n");
04777    AST_RWLIST_TRAVERSE(&hints, hint, list) {
04778       watchers = 0;
04779       AST_LIST_TRAVERSE(&hint->callbacks, watcher, entry) {
04780          watchers++;
04781       }
04782       ast_cli(a->fd, "   %20s@%-20.20s: %-20.20s  State:%-15.15s Watchers %2d\n",
04783          ast_get_extension_name(hint->exten),
04784          ast_get_context_name(ast_get_extension_context(hint->exten)),
04785          ast_get_extension_app(hint->exten),
04786          ast_extension_state2str(hint->laststate), watchers);
04787       num++;
04788    }
04789    ast_cli(a->fd, "----------------\n");
04790    ast_cli(a->fd, "- %d hints registered\n", num);
04791    AST_RWLIST_UNLOCK(&hints);
04792    return CLI_SUCCESS;
04793 }

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

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

04875 {
04876    struct ast_switch *sw;
04877 
04878    switch (cmd) {
04879    case CLI_INIT:
04880       e->command = "core show switches";
04881       e->usage = 
04882          "Usage: core show switches\n"
04883          "       List registered switches\n";
04884       return NULL;
04885    case CLI_GENERATE:
04886       return NULL;   
04887    }
04888 
04889    AST_RWLIST_RDLOCK(&switches);
04890 
04891    if (AST_RWLIST_EMPTY(&switches)) {
04892       AST_RWLIST_UNLOCK(&switches);
04893       ast_cli(a->fd, "There are no registered alternative switches\n");
04894       return CLI_SUCCESS;
04895    }
04896 
04897    ast_cli(a->fd, "\n    -= Registered Asterisk Alternative Switches =-\n");
04898    AST_RWLIST_TRAVERSE(&switches, sw, list)
04899       ast_cli(a->fd, "%s: %s\n", sw->name, sw->description);
04900 
04901    AST_RWLIST_UNLOCK(&switches);
04902 
04903    return CLI_SUCCESS;
04904 }

static int handle_statechange ( void *  datap  )  [static]

Definition at line 3354 of file pbx.c.

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

Referenced by device_state_cb().

03355 {
03356    struct ast_hint *hint;
03357    struct statechange *sc = datap;
03358 
03359    ast_rdlock_contexts();
03360    AST_RWLIST_RDLOCK(&hints);
03361 
03362    AST_RWLIST_TRAVERSE(&hints, hint, list) {
03363       struct ast_state_cb *cblist;
03364       char buf[AST_MAX_EXTENSION];
03365       char *parse = buf;
03366       char *cur;
03367       int state;
03368 
03369       ast_copy_string(buf, ast_get_extension_app(hint->exten), sizeof(buf));
03370       while ( (cur = strsep(&parse, "&")) ) {
03371          if (!strcasecmp(cur, sc->dev))
03372             break;
03373       }
03374       if (!cur)
03375          continue;
03376 
03377       /* Get device state for this hint */
03378       state = ast_extension_state2(hint->exten);
03379 
03380       if ((state == -1) || (state == hint->laststate))
03381          continue;
03382 
03383       /* Device state changed since last check - notify the watchers */
03384 
03385       /* For general callbacks */
03386       AST_LIST_TRAVERSE(&statecbs, cblist, entry) {
03387          cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data);
03388       }
03389 
03390       /* For extension callbacks */
03391       AST_LIST_TRAVERSE(&hint->callbacks, cblist, entry) {
03392          cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data);
03393       }
03394 
03395       hint->laststate = state;   /* record we saw the change */
03396    }
03397    AST_RWLIST_UNLOCK(&hints);
03398    ast_unlock_contexts();
03399    ast_free(sc);
03400    return 0;
03401 }

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

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

05783 {
05784    int oldval = 0;
05785    
05786    switch (cmd) {
05787    case CLI_INIT:
05788       e->command = "dialplan set extenpatternmatchnew false";
05789       e->usage = 
05790          "Usage: dialplan set extenpatternmatchnew true|false\n"
05791          "       Use the NEW extension pattern matching algorithm, true or false.\n";
05792       return NULL;
05793    case CLI_GENERATE:
05794       return NULL;   
05795    }
05796 
05797    if (a->argc != 4)
05798       return CLI_SHOWUSAGE;
05799 
05800    oldval =  pbx_set_extenpatternmatchnew(0);
05801    
05802    if (!oldval)
05803       ast_cli(a->fd, "\n    -- Still using the OLD pattern match algorithm for extension names in the dialplan.\n");
05804    else
05805       ast_cli(a->fd, "\n    -- Switched to using the OLD pattern match algorithm for extension names in the dialplan.\n");
05806 
05807    return CLI_SUCCESS;
05808 }

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

Definition at line 387 of file pbx.c.

References ast_exten::label, and S_OR.

Referenced by ast_add_extension2_lockopt().

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

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

Definition at line 380 of file pbx.c.

References ast_exten::priority.

Referenced by ast_add_extension2_lockopt().

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

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

Definition at line 361 of file pbx.c.

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

Referenced by ast_add_extension2_lockopt().

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

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

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

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

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

Definition at line 416 of file pbx.c.

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

Referenced by ast_add_extension2_lockopt().

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

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

Definition at line 410 of file pbx.c.

References ast_hashtab_hash_int(), and ast_exten::priority.

Referenced by ast_add_extension2_lockopt().

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

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

Definition at line 1003 of file pbx.c.

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

Referenced by pbx_find_extension().

01004 {
01005    if (!i->hastime)
01006       return 1;
01007 
01008    return ast_check_timing(&(i->timing));
01009 }

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

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

Referenced by ast_pbx_run_args(), and ast_pbx_start().

03978 {
03979    int failed = 0;
03980    double curloadavg;
03981 #if defined(HAVE_SYSINFO)
03982    long curfreemem;
03983    struct sysinfo sys_info;
03984 #endif
03985 
03986    ast_mutex_lock(&maxcalllock);
03987    if (option_maxcalls) {
03988       if (countcalls >= option_maxcalls) {
03989          ast_log(LOG_WARNING, "Maximum call limit of %d calls exceeded by '%s'!\n", option_maxcalls, c->name);
03990          failed = -1;
03991       }
03992    }
03993    if (option_maxload) {
03994       getloadavg(&curloadavg, 1);
03995       if (curloadavg >= option_maxload) {
03996          ast_log(LOG_WARNING, "Maximum loadavg limit of %f load exceeded by '%s' (currently %f)!\n", option_maxload, c->name, curloadavg);
03997          failed = -1;
03998       }
03999    }
04000 #if defined(HAVE_SYSINFO)
04001    if (option_minmemfree) {
04002       if (!sysinfo(&sys_info)) {
04003          /* make sure that the free system memory is above the configured low watermark
04004           * convert the amount of freeram from mem_units to MB */
04005          curfreemem = sys_info.freeram / sys_info.mem_unit; 
04006          curfreemem /= 1024*1024; 
04007          if (curfreemem < option_minmemfree) {
04008             ast_log(LOG_WARNING, "Available system memory (~%ldMB) is below the configured low watermark (%ldMB)\n", curfreemem, option_minmemfree);
04009             failed = -1;
04010          }
04011       }
04012    }
04013 #endif
04014       
04015    if (!failed) {
04016       countcalls++;
04017       totalcalls++;
04018    }
04019    ast_mutex_unlock(&maxcalllock);
04020 
04021    return failed;
04022 }

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

Definition at line 1404 of file pbx.c.

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

Referenced by add_pattern_node().

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

int load_pbx ( void   ) 

Provided by pbx.c

Definition at line 8731 of file pbx.c.

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

Referenced by main().

08732 {
08733    int x;
08734 
08735    /* Initialize the PBX */
08736    ast_verb(1, "Asterisk PBX Core Initializing\n");
08737    if (!(device_state_tps = ast_taskprocessor_get("pbx-core", 0))) {
08738       ast_log(LOG_WARNING, "failed to create pbx-core taskprocessor\n");
08739    }
08740 
08741    ast_verb(1, "Registering builtin applications:\n");
08742    ast_cli_register_multiple(pbx_cli, sizeof(pbx_cli) / sizeof(struct ast_cli_entry));
08743    __ast_custom_function_register(&exception_function, NULL);
08744 
08745    /* Register builtin applications */
08746    for (x = 0; x < sizeof(builtins) / sizeof(struct pbx_builtin); x++) {
08747       ast_verb(1, "[%s]\n", builtins[x].name);
08748       if (ast_register_application2(builtins[x].name, builtins[x].execute, builtins[x].synopsis, builtins[x].description, NULL)) {
08749          ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name);
08750          return -1;
08751       }
08752    }
08753    
08754    /* Register manager application */
08755    ast_manager_register2("ShowDialPlan", EVENT_FLAG_CONFIG | EVENT_FLAG_REPORTING, manager_show_dialplan, "List dialplan", mandescr_show_dialplan);
08756 
08757    if (!(device_state_sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE, device_state_cb, NULL,
08758          AST_EVENT_IE_END))) {
08759       return -1;
08760    }
08761 
08762    return 0;
08763 }

void log_match_char_tree ( struct match_char node,
char *  prefix 
)

Definition at line 1106 of file pbx.c.

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

Referenced by ast_context_remove_extension_callerid2(), and pbx_find_extension().

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

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

Referenced by get_range().

06242 {
06243    int i;
06244 
06245    if (names) {
06246       for (i = 0; names[i]; i++) {
06247          if (!strcasecmp(s, names[i]))
06248             return i+1;
06249       }
06250    } else if (sscanf(s, "%2d", &i) == 1 && i >= 1 && i <= max) {
06251       return i;
06252    }
06253    return 0; /* error return */
06254 }

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

Send ack once.

Definition at line 5373 of file pbx.c.

References astman_send_listack(), and s.

Referenced by manager_show_dialplan_helper().

05374 {
05375    astman_send_listack(s, m, "DialPlan list will follow", "start");
05376 }

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

Manager listing of dial plan.

Definition at line 5519 of file pbx.c.

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

Referenced by load_pbx().

05520 {
05521    const char *exten, *context;
05522    const char *id = astman_get_header(m, "ActionID");
05523    char idtext[256];
05524    int res;
05525 
05526    /* Variables used for different counters */
05527    struct dialplan_counters counters;
05528 
05529    if (!ast_strlen_zero(id))
05530       snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id);
05531    else
05532       idtext[0] = '\0';
05533 
05534    memset(&counters, 0, sizeof(counters));
05535 
05536    exten = astman_get_header(m, "Extension");
05537    context = astman_get_header(m, "Context");
05538    
05539    res = manager_show_dialplan_helper(s, m, idtext, context, exten, &counters, NULL);
05540 
05541    if (context && !counters.context_existence) {
05542       char errorbuf[BUFSIZ];
05543    
05544       snprintf(errorbuf, sizeof(errorbuf), "Did not find context %s", context);
05545       astman_send_error(s, m, errorbuf);
05546       return 0;
05547    }
05548    if (exten && !counters.extension_existence) {
05549       char errorbuf[BUFSIZ];
05550 
05551       if (context)
05552          snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s@%s", exten, context);
05553       else
05554          snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s in any context", exten);
05555       astman_send_error(s, m, errorbuf);
05556       return 0;
05557    }
05558 
05559    manager_event(EVENT_FLAG_CONFIG, "ShowDialPlanComplete",
05560       "EventList: Complete\r\n"
05561       "ListItems: %d\r\n"
05562       "ListExtensions: %d\r\n"
05563       "ListPriorities: %d\r\n"   
05564       "ListContexts: %d\r\n"  
05565       "%s"
05566       "\r\n", counters.total_items, counters.total_exten, counters.total_prio, counters.total_context, idtext);
05567 
05568    /* everything ok */
05569    return 0;
05570 }

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

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

Referenced by manager_show_dialplan().

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

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

Definition at line 2057 of file pbx.c.

References ast_extension_match(), and ast_strlen_zero().

Referenced by pbx_find_extension().

02058 {
02059    /* If the Caller*ID pattern is empty, then we're matching NO Caller*ID, so
02060       failing to get a number should count as a match, otherwise not */
02061 
02062    if (ast_strlen_zero(callerid))
02063       return ast_strlen_zero(cidpattern) ? 1 : 0;
02064 
02065    return ast_extension_match(cidpattern, callerid);
02066 }

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

References match_char::alt_char, ast_debug, ast_hashtab_lookup(), ast_log(), match_char::deleted, E_FINDLABEL, E_MATCH, E_SPAWN, ast_exten::exten, match_char::exten, ast_exten::label, LOG_NOTICE, NEW_MATCHER_CHK_MATCH, match_char::specificity, update_scoreboard(), and match_char::x.

Referenced by pbx_find_extension().

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

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

Referenced by pbx_retrieve_variable(), and pbx_substitute_variables_helper_full().

02393 {
02394    int parens = 0;
02395 
02396    *offset = 0;
02397    *length = INT_MAX;
02398    *isfunc = 0;
02399    for (; *var; var++) {
02400       if (*var == '(') {
02401          (*isfunc)++;
02402          parens++;
02403       } else if (*var == ')') {
02404          parens--;
02405       } else if (*var == ':' && parens == 0) {
02406          *var++ = '\0';
02407          sscanf(var, "%30d:%30d", offset, length);
02408          return 1; /* offset:length valid */
02409       }
02410    }
02411    return 0;
02412 }

void pbx_builtin_clear_globals ( void   ) 

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

08612 {
08613    struct ast_var_t *vardata;
08614 
08615    ast_rwlock_wrlock(&globalslock);
08616    while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries)))
08617       ast_var_delete(vardata);
08618    ast_rwlock_unlock(&globalslock);
08619 }

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

Note:
Will lock the channel.

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

      const char *var;

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

Definition at line 8380 of file pbx.c.

References ast_channel_lock, ast_channel_unlock, AST_LIST_TRAVERSE, ast_rwlock_rdlock(), ast_rwlock_unlock(), ast_var_name(), ast_var_value(), chan, globals, and globalslock.

Referenced by _macro_exec(), _while_exec(), agent_hangup(), agent_read(), agentmonitoroutgoing_exec(), array(), ast_bridge_call(), ast_call_forward(), ast_eivr_getvariable(), ast_feature_interpret(), ast_monitor_stop(), ast_park_call_full(), bridge_play_sounds(), builtin_atxfer(), builtin_automixmonitor(), builtin_automonitor(), check_goto_on_transfer(), common_exec(), conf_exec(), conf_run(), dahdi_call(), dahdi_hangup(), dial_exec_full(), do_forward(), do_timelimit(), dundi_exec(), dundi_helper(), findparkinglotname(), get_also_info(), get_index(), get_refer_info(), global_read(), hash_read(), iax2_call(), iax2_exec(), import_ch(), leave_voicemail(), local_hangup(), local_read(), login_exec(), macro_fixup(), minivm_delete_exec(), minivm_notify_exec(), misdn_answer(), misdn_hangup(), morsecode_exec(), notify_new_message(), oh323_call(), oh323_hangup(), park_space_reserve(), pbx_builtin_background(), pickup_by_mark(), queue_exec(), real_ctx(), retrydial_exec(), ring_entry(), run_agi(), set_config_flags(), set_local_info(), sip_addheader(), sla_trunk_exec(), speech_background(), try_suggested_sip_codec(), and update_bridge_vars().

08381 {
08382    struct ast_var_t *variables;
08383    const char *ret = NULL;
08384    int i;
08385    struct varshead *places[2] = { NULL, &globals };
08386 
08387    if (!name)
08388       return NULL;
08389 
08390    if (chan) {
08391       ast_channel_lock(chan);
08392       places[0] = &chan->varshead;
08393    }
08394 
08395    for (i = 0; i < 2; i++) {
08396       if (!places[i])
08397          continue;
08398       if (places[i] == &globals)
08399          ast_rwlock_rdlock(&globalslock);
08400       AST_LIST_TRAVERSE(places[i], variables, entries) {
08401          if (!strcmp(name, ast_var_name(variables))) {
08402             ret = ast_var_value(variables);
08403             break;
08404          }
08405       }
08406       if (places[i] == &globals)
08407          ast_rwlock_unlock(&globalslock);
08408       if (ret)
08409          break;
08410    }
08411 
08412    if (chan)
08413       ast_channel_unlock(chan);
08414 
08415    return ret;
08416 }

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

Definition at line 8633 of file pbx.c.

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

08634 {
08635    char *condition, *branch1, *branch2, *branch;
08636    char *stringp;
08637 
08638    if (ast_strlen_zero(data)) {
08639       ast_log(LOG_WARNING, "Ignoring, since there is no variable to check\n");
08640       return 0;
08641    }
08642 
08643    stringp = ast_strdupa(data);
08644    condition = strsep(&stringp,"?");
08645    branch1 = strsep(&stringp,":");
08646    branch2 = strsep(&stringp,"");
08647    branch = pbx_checkcondition(condition) ? branch1 : branch2;
08648 
08649    if (ast_strlen_zero(branch)) {
08650       ast_debug(1, "Not taking any branch\n");
08651       return 0;
08652    }
08653 
08654    return pbx_builtin_goto(chan, branch);
08655 }

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

Definition at line 8569 of file pbx.c.

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

08570 {
08571    char *name;
08572    char *value;
08573    char *channel;
08574    char tmp[VAR_BUF_SIZE];
08575    static int deprecation_warning = 0;
08576 
08577    if (ast_strlen_zero(data)) {
08578       ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n");
08579       return 0;
08580    }
08581    tmp[0] = 0;
08582    if (!deprecation_warning) {
08583       ast_log(LOG_WARNING, "ImportVar is deprecated.  Please use Set(varname=${IMPORT(channel,variable)}) instead.\n");
08584       deprecation_warning = 1;
08585    }
08586 
08587    value = ast_strdupa(data);
08588    name = strsep(&value,"=");
08589    channel = strsep(&value,",");
08590    if (channel && value && name) { /*! \todo XXX should do !ast_strlen_zero(..) of the args ? */
08591       struct ast_channel *chan2 = ast_get_channel_by_name_locked(channel);
08592       if (chan2) {
08593          char *s = alloca(strlen(value) + 4);
08594          if (s) {
08595             sprintf(s, "${%s}", value);
08596             pbx_substitute_variables_helper(chan2, s, tmp, sizeof(tmp) - 1);
08597          }
08598          ast_channel_unlock(chan2);
08599       }
08600       pbx_builtin_setvar_helper(chan, name, tmp);
08601    }
08602 
08603    return(0);
08604 }

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

Definition at line 7971 of file pbx.c.

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

07972 {
07973    char *options = data;
07974    int answer = 1;
07975 
07976    /* Some channels can receive DTMF in unanswered state; some cannot */
07977    if (!ast_strlen_zero(options) && strchr(options, 'n')) {
07978       answer = 0;
07979    }
07980 
07981    /* If the channel is hungup, stop waiting */
07982    if (ast_check_hangup(chan)) {
07983       return -1;
07984    } else if (chan->_state != AST_STATE_UP && answer) {
07985       __ast_answer(chan, 0, 1);
07986    }
07987 
07988    return AST_PBX_INCOMPLETE;
07989 }

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

Definition at line 8606 of file pbx.c.

08607 {
08608    return 0;
08609 }

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

Note:
Will lock the channel.

Definition at line 8418 of file pbx.c.

References ast_channel_lock, ast_channel_unlock, ast_func_write(), AST_LIST_INSERT_HEAD, ast_log(), ast_rwlock_unlock(), ast_rwlock_wrlock(), ast_strdupa, ast_var_assign(), ast_verb, chan, globals, globalslock, and LOG_WARNING.

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

08419 {
08420    struct ast_var_t *newvariable;
08421    struct varshead *headp;
08422 
08423    if (name[strlen(name)-1] == ')') {
08424       char *function = ast_strdupa(name);
08425 
08426       ast_log(LOG_WARNING, "Cannot push a value onto a function\n");
08427       ast_func_write(chan, function, value);
08428       return;
08429    }
08430 
08431    if (chan) {
08432       ast_channel_lock(chan);
08433       headp = &chan->varshead;
08434    } else {
08435       ast_rwlock_wrlock(&globalslock);
08436       headp = &globals;
08437    }
08438 
08439    if (value) {
08440       if (headp == &globals)
08441          ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value);
08442       newvariable = ast_var_assign(name, value);
08443       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
08444    }
08445 
08446    if (chan)
08447       ast_channel_unlock(chan);
08448    else
08449       ast_rwlock_unlock(&globalslock);
08450 }

int pbx_builtin_raise_exception ( struct ast_channel chan,
void *  vreason 
)

Definition at line 2595 of file pbx.c.

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

Referenced by __ast_pbx_run().

02596 {
02597    const char *reason = vreason;
02598    struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL);
02599    struct pbx_exception *exception = NULL;
02600 
02601    if (!ds) {
02602       ds = ast_datastore_alloc(&exception_store_info, NULL);
02603       if (!ds)
02604          return -1;
02605       exception = ast_calloc(1, sizeof(struct pbx_exception));
02606       if (!exception) {
02607          ast_datastore_free(ds);
02608          return -1;
02609       }
02610       if (ast_string_field_init(exception, 128)) {
02611          ast_free(exception);
02612          ast_datastore_free(ds);
02613          return -1;
02614       }
02615       ds->data = exception;
02616       ast_channel_datastore_add(chan, ds);
02617    } else
02618       exception = ds->data;
02619 
02620    ast_string_field_set(exception, reason, reason);
02621    ast_string_field_set(exception, context, chan->context);
02622    ast_string_field_set(exception, exten, chan->exten);
02623    exception->priority = chan->priority;
02624    set_ext_pri(chan, "e", 0);
02625    return 0;
02626 }

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

Definition at line 8694 of file pbx.c.

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

08695 {
08696    int res = 0;
08697 
08698    if (data)
08699       res = ast_say_character_str(chan, data, "", chan->language);
08700    return res;
08701 }

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

Definition at line 8685 of file pbx.c.

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

08686 {
08687    int res = 0;
08688 
08689    if (data)
08690       res = ast_say_digit_str(chan, data, "", chan->language);
08691    return res;
08692 }

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

Definition at line 8657 of file pbx.c.

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

08658 {
08659    char tmp[256];
08660    char *number = tmp;
08661    char *options;
08662 
08663    if (ast_strlen_zero(data)) {
08664       ast_log(LOG_WARNING, "SayNumber requires an argument (number)\n");
08665       return -1;
08666    }
08667    ast_copy_string(tmp, data, sizeof(tmp));
08668    strsep(&number, ",");
08669    options = strsep(&number, ",");
08670    if (options) {
08671       if ( strcasecmp(options, "f") && strcasecmp(options, "m") &&
08672          strcasecmp(options, "c") && strcasecmp(options, "n") ) {
08673          ast_log(LOG_WARNING, "SayNumber gender option is either 'f', 'm', 'c' or 'n'\n");
08674          return -1;
08675       }
08676    }
08677 
08678    if (ast_say_number(chan, atoi(tmp), "", chan->language, options)) {
08679       ast_log(LOG_WARNING, "We were unable to say the number %s, is it too large?\n", tmp);
08680    }
08681 
08682    return 0;
08683 }

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

Definition at line 8703 of file pbx.c.

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

08704 {
08705    int res = 0;
08706 
08707    if (data)
08708       res = ast_say_phonetic_str(chan, data, "", chan->language);
08709    return res;
08710 }

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

Note:
Will lock the channel.

Definition at line 8348 of file pbx.c.

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

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

08349 {
08350    struct ast_var_t *variables;
08351    const char *var, *val;
08352    int total = 0;
08353 
08354    if (!chan)
08355       return 0;
08356 
08357    (*buf)->used = 0;
08358    (*buf)->str[0] = '\0';
08359 
08360    ast_channel_lock(chan);
08361 
08362    AST_LIST_TRAVERSE(&chan->varshead, variables, entries) {
08363       if ((var = ast_var_name(variables)) && (val = ast_var_value(variables))
08364          /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */
08365          ) {
08366          if (ast_str_append(buf, 0, "%s=%s\n", var, val) < 0) {
08367             ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
08368             break;
08369          } else
08370             total++;
08371       } else
08372          break;
08373    }
08374 
08375    ast_channel_unlock(chan);
08376 
08377    return total;
08378 }

int pbx_builtin_setvar ( struct ast_channel ,
void *   
)

Definition at line 8510 of file pbx.c.

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

Referenced by rpt_exec().

08511 {
08512    char *name, *value, *mydata;
08513 
08514    if (ast_compat_app_set) {
08515       return pbx_builtin_setvar_multiple(chan, data);
08516    }
08517 
08518    if (ast_strlen_zero(data)) {
08519       ast_log(LOG_WARNING, "Set requires one variable name/value pair.\n");
08520       return 0;
08521    }
08522 
08523    mydata = ast_strdupa(data);
08524    name = strsep(&mydata, "=");
08525    value = mydata;
08526    if (strchr(name, ' '))
08527       ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, mydata);
08528 
08529    pbx_builtin_setvar_helper(chan, name, value);
08530    return(0);
08531 }

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

Note:
Will lock the channel.

Definition at line 8452 of file pbx.c.

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

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

08453 {
08454    struct ast_var_t *newvariable;
08455    struct varshead *headp;
08456    const char *nametail = name;
08457 
08458    if (name[strlen(name) - 1] == ')') {
08459       char *function = ast_strdupa(name);
08460 
08461       ast_func_write(chan, function, value);
08462       return;
08463    }
08464 
08465    if (chan) {
08466       ast_channel_lock(chan);
08467       headp = &chan->varshead;
08468    } else {
08469       ast_rwlock_wrlock(&globalslock);
08470       headp = &globals;
08471    }
08472 
08473    /* For comparison purposes, we have to strip leading underscores */
08474    if (*nametail == '_') {
08475       nametail++;
08476       if (*nametail == '_')
08477          nametail++;
08478    }
08479 
08480    AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) {
08481       if (strcasecmp(ast_var_name(newvariable), nametail) == 0) {
08482          /* there is already such a variable, delete it */
08483          AST_LIST_REMOVE_CURRENT(entries);
08484          ast_var_delete(newvariable);
08485          break;
08486       }
08487    }
08488    AST_LIST_TRAVERSE_SAFE_END;
08489 
08490    if (value) {
08491       if (headp == &globals)
08492          ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value);
08493       newvariable = ast_var_assign(name, value);
08494       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
08495       manager_event(EVENT_FLAG_DIALPLAN, "VarSet", 
08496          "Channel: %s\r\n"
08497          "Variable: %s\r\n"
08498          "Value: %s\r\n"
08499          "Uniqueid: %s\r\n", 
08500          chan ? chan->name : "none", name, value, 
08501          chan ? chan->uniqueid : "none");
08502    }
08503 
08504    if (chan)
08505       ast_channel_unlock(chan);
08506    else
08507       ast_rwlock_unlock(&globalslock);
08508 }

int pbx_builtin_setvar_multiple ( struct ast_channel ,
void *   
)

Definition at line 8533 of file pbx.c.

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

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

08534 {
08535    char *data;
08536    int x;
08537    AST_DECLARE_APP_ARGS(args,
08538       AST_APP_ARG(pair)[24];
08539    );
08540    AST_DECLARE_APP_ARGS(pair,
08541       AST_APP_ARG(name);
08542       AST_APP_ARG(value);
08543    );
08544 
08545    if (ast_strlen_zero(vdata)) {
08546       ast_log(LOG_WARNING, "MSet requires at least one variable name/value pair.\n");
08547       return 0;
08548    }
08549 
08550    data = ast_strdupa(vdata);
08551    AST_STANDARD_APP_ARGS(args, data);
08552 
08553    for (x = 0; x < args.argc; x++) {
08554       AST_NONSTANDARD_APP_ARGS(pair, args.pair[x], '=');
08555       if (pair.argc == 2) {
08556          pbx_builtin_setvar_helper(chan, pair.name, pair.value);
08557          if (strchr(pair.name, ' '))
08558             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);
08559       } else if (!chan) {
08560          ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '='\n", pair.name);
08561       } else {
08562          ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '=' (in %s@%s:%d\n", pair.name, chan->exten, chan->context, chan->priority);
08563       }
08564    }
08565 
08566    return 0;
08567 }

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

08622 {
08623    int res;
08624    if (ast_strlen_zero(condition)) {                /* NULL or empty strings are false */
08625       return 0;
08626    } else if (sscanf(condition, "%30d", &res) == 1) { /* Numbers are evaluated for truth */
08627       return res;
08628    } else {                                         /* Strings are true */
08629       return 1;
08630    }
08631 }

static void pbx_destroy ( struct ast_pbx p  )  [static]

Definition at line 1011 of file pbx.c.

References ast_free.

01012 {
01013    ast_free(p);
01014 }

int pbx_exec ( struct ast_channel c,
struct ast_app app,
void *  data 
)

Execute an application.

Parameters:
c channel to execute on
app which app to execute
data the data passed into the app
This application executes an application on a given channel. It saves the stack and executes the given application passing in the given data.

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

Definition at line 934 of file pbx.c.

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

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

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

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

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

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

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

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

Definition at line 2068 of file pbx.c.

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

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

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

struct ast_app* pbx_findapp ( const char *  app  ) 

Look up an application.

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

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

Definition at line 975 of file pbx.c.

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

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

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

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

Definition at line 989 of file pbx.c.

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

Referenced by pbx_find_extension().

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

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

Definition at line 9009 of file pbx.c.

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

Referenced by ast_async_parseable_goto(), and ast_parseable_goto().

09010 {
09011    char *exten, *pri, *context;
09012    char *stringp;
09013    int ipri;
09014    int mode = 0;
09015 
09016    if (ast_strlen_zero(goto_string)) {
09017       ast_log(LOG_WARNING, "Goto requires an argument ([[context,]extension,]priority)\n");
09018       return -1;
09019    }
09020    stringp = ast_strdupa(goto_string);
09021    context = strsep(&stringp, ","); /* guaranteed non-null */
09022    exten = strsep(&stringp, ",");
09023    pri = strsep(&stringp, ",");
09024    if (!exten) {  /* Only a priority in this one */
09025       pri = context;
09026       exten = NULL;
09027       context = NULL;
09028    } else if (!pri) {   /* Only an extension and priority in this one */
09029       pri = exten;
09030       exten = context;
09031       context = NULL;
09032    }
09033    if (*pri == '+') {
09034       mode = 1;
09035       pri++;
09036    } else if (*pri == '-') {
09037       mode = -1;
09038       pri++;
09039    }
09040    if (sscanf(pri, "%30d", &ipri) != 1) {
09041       if ((ipri = ast_findlabel_extension(chan, context ? context : chan->context, exten ? exten : chan->exten,
09042          pri, chan->cid.cid_num)) < 1) {
09043          ast_log(LOG_WARNING, "Priority '%s' must be a number > 0, or valid label\n", pri);
09044          return -1;
09045       } else
09046          mode = 0;
09047    }
09048    /* At this point we have a priority and maybe an extension and a context */
09049 
09050    if (mode)
09051       ipri = chan->priority + (ipri * mode);
09052 
09053    if (async)
09054       ast_async_goto(chan, context, exten, ipri);
09055    else
09056       ast_explicit_goto(chan, context, exten, ipri);
09057    
09058    return 0;
09059 
09060 }

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

Support for Asterisk built-in variables in the dialplan.

Note:
See also

Definition at line 2467 of file pbx.c.

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

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

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

int pbx_set_autofallthrough ( int  newval  ) 

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

Definition at line 4118 of file pbx.c.

References autofallthrough.

Referenced by pbx_load_module().

04119 {
04120    int oldval = autofallthrough;
04121    autofallthrough = newval;
04122    return oldval;
04123 }

int pbx_set_extenpatternmatchnew ( int  newval  ) 

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

Definition at line 4125 of file pbx.c.

References extenpatternmatchnew.

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

04126 {
04127    int oldval = extenpatternmatchnew;
04128    extenpatternmatchnew = newval;
04129    return oldval;
04130 }

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

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

Referenced by pbx_load_module().

04133 {
04134    if (overrideswitch) {
04135       ast_free(overrideswitch);
04136    }
04137    if (!ast_strlen_zero(newval)) {
04138       overrideswitch = ast_strdup(newval);
04139    } else {
04140       overrideswitch = NULL;
04141    }
04142 }

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

Definition at line 3121 of file pbx.c.

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

Referenced by pbx_extension_helper().

03122 {
03123    const char *tmp;
03124 
03125    /* Nothing more to do */
03126    if (!e->data) {
03127       *passdata = '\0';
03128       return;
03129    }
03130 
03131    /* No variables or expressions in e->data, so why scan it? */
03132    if ((!(tmp = strchr(e->data, '$'))) || (!strstr(tmp, "${") && !strstr(tmp, "$["))) {
03133       ast_copy_string(passdata, e->data, datalen);
03134       return;
03135    }
03136 
03137    pbx_substitute_variables_helper(c, e->data, passdata, datalen - 1);
03138 }

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

Definition at line 3111 of file pbx.c.

References pbx_substitute_variables_helper_full(), and ast_channel::varshead.

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

03112 {
03113    pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count);
03114 }

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

Definition at line 2919 of file pbx.c.

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

Referenced by pbx_substitute_variables_helper(), and pbx_substitute_variables_varshead().

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

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

Definition at line 3116 of file pbx.c.

References pbx_substitute_variables_helper_full().

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

03117 {
03118    pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count);
03119 }

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

Definition at line 4046 of file pbx.c.

References __ast_pbx_run(), and decrease_call_count().

Referenced by ast_pbx_start().

04047 {
04048    /* Oh joyeous kernel, we're a new thread, with nothing to do but
04049       answer this channel and get it going.
04050    */
04051    /* NOTE:
04052       The launcher of this function _MUST_ increment 'countcalls'
04053       before invoking the function; it will be decremented when the
04054       PBX has finished running on the channel
04055     */
04056    struct ast_channel *c = data;
04057 
04058    __ast_pbx_run(c, NULL);
04059    decrease_call_count();
04060 
04061    pthread_exit(NULL);
04062 
04063    return NULL;
04064 }

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

helper function to print an extension

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

05033 {
05034    int prio = ast_get_extension_priority(e);
05035    if (prio == PRIORITY_HINT) {
05036       snprintf(buf, buflen, "hint: %s",
05037          ast_get_extension_app(e));
05038    } else {
05039       snprintf(buf, buflen, "%d. %s(%s)",
05040          prio, ast_get_extension_app(e),
05041          (!ast_strlen_zero(ast_get_extension_app_data(e)) ? (char *)ast_get_extension_app_data(e) : ""));
05042    }
05043 }

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

03683 {
03684    ast_channel_lock(c);
03685    ast_copy_string(c->exten, exten, sizeof(c->exten));
03686    c->priority = pri;
03687    ast_channel_unlock(c);
03688 }

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

05198 {
05199    struct ast_context *c = NULL;
05200    int res = 0, old_total_exten = dpc->total_exten;
05201 
05202    ast_cli(fd,"\n     In-mem exten Trie for Fast Extension Pattern Matching:\n\n");
05203 
05204    ast_cli(fd,"\n           Explanation: Node Contents Format = <char(s) to match>:<pattern?>:<specif>:[matched extension]\n");
05205    ast_cli(fd,    "                        Where <char(s) to match> is a set of chars, any one of which should match the current character\n");
05206    ast_cli(fd,    "                              <pattern?>: Y if this a pattern match (eg. _XZN[5-7]), N otherwise\n");
05207    ast_cli(fd,    "                              <specif>: an assigned 'exactness' number for this matching char. The lower the number, the more exact the match\n");
05208    ast_cli(fd,    "                              [matched exten]: If all chars matched to this point, which extension this matches. In form: EXTEN:<exten string>\n");
05209    ast_cli(fd,    "                        In general, you match a trie node to a string character, from left to right. All possible matching chars\n");
05210    ast_cli(fd,    "                        are in a string vertically, separated by an unbroken string of '+' characters.\n\n");
05211    ast_rdlock_contexts();
05212 
05213    /* walk all contexts ... */
05214    while ( (c = ast_walk_contexts(c)) ) {
05215       int context_info_printed = 0;
05216 
05217       if (context && strcmp(ast_get_context_name(c), context))
05218          continue;   /* skip this one, name doesn't match */
05219 
05220       dpc->context_existence = 1;
05221 
05222       if (!c->pattern_tree)
05223          ast_exists_extension(NULL, c->name, "s", 1, ""); /* do this to force the trie to built, if it is not already */
05224 
05225       ast_rdlock_context(c);
05226 
05227       dpc->total_context++;
05228       ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
05229          ast_get_context_name(c), ast_get_context_registrar(c));
05230       context_info_printed = 1;
05231       
05232       if (c->pattern_tree)
05233       {
05234          cli_match_char_tree(c->pattern_tree, " ", fd);
05235       } else {
05236          ast_cli(fd,"\n     No Pattern Trie present. Perhaps the context is empty...or there is trouble...\n\n");
05237       }
05238 
05239       ast_unlock_context(c);
05240 
05241       /* if we print something in context, make an empty line */
05242       if (context_info_printed)
05243          ast_cli(fd, "\n");
05244    }
05245    ast_unlock_contexts();
05246 
05247    return (dpc->total_exten == old_total_exten) ? -1 : res;
05248 }

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

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

Referenced by handle_show_dialplan().

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

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

References ast_copy_string().

Referenced by pbx_retrieve_variable(), and pbx_substitute_variables_helper_full().

02426 {
02427    char *ret = workspace;
02428    int lr;  /* length of the input string after the copy */
02429 
02430    ast_copy_string(workspace, value, workspace_len); /* always make a copy */
02431 
02432    lr = strlen(ret); /* compute length after copy, so we never go out of the workspace */
02433 
02434    /* Quick check if no need to do anything */
02435    if (offset == 0 && length >= lr) /* take the whole string */
02436       return ret;
02437 
02438    if (offset < 0)   {  /* translate negative offset into positive ones */
02439       offset = lr + offset;
02440       if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */
02441          offset = 0;
02442    }
02443 
02444    /* too large offset result in empty string so we know what to return */
02445    if (offset >= lr)
02446       return ret + lr;  /* the final '\0' */
02447 
02448    ret += offset;    /* move to the start position */
02449    if (length >= 0 && length < lr - offset)  /* truncate if necessary */
02450       ret[length] = '\0';
02451    else if (length < 0) {
02452       if (lr > offset - length) /* After we remove from the front and from the rear, is there anything left? */
02453          ret[lr + length - offset] = '\0';
02454       else
02455          ret[0] = '\0';
02456    }
02457 
02458    return ret;
02459 }

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

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

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

static void unreference_cached_app ( struct ast_app app  )  [static]

Definition at line 5842 of file pbx.c.

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

Referenced by ast_unregister_application().

05843 {
05844    struct ast_context *context = NULL;
05845    struct ast_exten *eroot = NULL, *e = NULL;
05846 
05847    ast_rdlock_contexts();
05848    while ((context = ast_walk_contexts(context))) {
05849       while ((eroot = ast_walk_context_extensions(context, eroot))) {
05850          while ((e = ast_walk_extension_priorities(eroot, e))) {
05851             if (e->cached_app == app)
05852                e->cached_app = NULL;
05853          }
05854       }
05855    }
05856    ast_unlock_contexts();
05857 
05858    return;
05859 }

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

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

Referenced by new_find_extension().

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

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

Definition at line 7875 of file pbx.c.

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

Referenced by pbx_builtin_busy(), and pbx_builtin_congestion().

07876 {
07877    int res;
07878    struct ast_frame *f;
07879    double waitsec;
07880    int waittime;
07881 
07882    if (ast_strlen_zero(data) || (sscanf(data, "%30lg", &waitsec) != 1) || (waitsec < 0))
07883       waitsec = -1;
07884    if (waitsec > -1) {
07885       waittime = waitsec * 1000.0;
07886       ast_safe_sleep(chan, waittime);
07887    } else do {
07888       res = ast_waitfor(chan, -1);
07889       if (res < 0)
07890          return;
07891       f = ast_read(chan);
07892       if (f)
07893          ast_frfree(f);
07894    } while(f);
07895 }


Variable Documentation

int autofallthrough = 1 [static]

Definition at line 426 of file pbx.c.

Referenced by pbx_set_autofallthrough().

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

Definition at line 113 of file pbx.c.

Referenced by pbx_builtin_background().

struct pbx_builtin builtins[] [static]

Declaration of builtin applications.

Referenced by load_pbx().

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

Definition at line 5815 of file pbx.c.

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

Definition at line 5816 of file pbx.c.

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

Definition at line 5814 of file pbx.c.

ast_rwlock_t conlock = PTHREAD_RWLOCK_INITIALIZER [static]

Lock for the ast_context list

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

struct ast_context* contexts [static]

Definition at line 731 of file pbx.c.

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

struct ast_hashtab* contexts_table = NULL [static]

Definition at line 732 of file pbx.c.

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

int countcalls [static]

Definition at line 434 of file pbx.c.

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

char* days[] [static]

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

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

struct ast_taskprocessor* device_state_tps [static]

Definition at line 126 of file pbx.c.

Referenced by device_state_cb(), and load_pbx().

struct ast_custom_function exception_function [static]

Definition at line 2648 of file pbx.c.

Referenced by load_pbx().

struct ast_datastore_info exception_store_info [static]

Initial value:

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

Definition at line 2590 of file pbx.c.

Referenced by acf_exception_read(), and pbx_builtin_raise_exception().

int extenpatternmatchnew = 0 [static]

Definition at line 427 of file pbx.c.

Referenced by pbx_find_extension(), and pbx_set_extenpatternmatchnew().

struct cfextension_states extension_states[] [static]

Referenced by ast_extension_state2str().

struct varshead globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE [static]

Definition at line 424 of file pbx.c.

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

ast_rwlock_t globalslock = PTHREAD_RWLOCK_INITIALIZER [static]

Definition at line 423 of file pbx.c.

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

char mandescr_show_dialplan[] [static]

Definition at line 5572 of file pbx.c.

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

Definition at line 433 of file pbx.c.

Referenced by decrease_call_count(), and increase_call_count().

char* months[] [static]

Definition at line 6402 of file pbx.c.

Referenced by ast_build_timing().

char* overrideswitch = NULL [static]

Definition at line 428 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 5821 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 7996 of file pbx.c.

Referenced by pbx_builtin_resetcdr().

int stateid = 1 [static]

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

Referenced by pbx_find_extension().

int totalcalls [static]

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

Referenced by pbx_builtin_waitexten().


Generated on Wed Aug 18 22:34:28 2010 for Asterisk - the Open Source PBX by  doxygen 1.4.7