Wed Apr 6 11:30:06 2011

Asterisk developer's documentation


pbx.c File Reference

Core PBX routines. More...

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

Go to the source code of this file.

Data Structures

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

Defines

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

Functions

void __ast_context_destroy (struct ast_context *list, struct ast_hashtab *contexttab, struct ast_context *con, const char *registrar)
int __ast_custom_function_register (struct ast_custom_function *acf, struct ast_module *mod)
 Register a custom function.
static int __ast_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority, int async)
static void __ast_internal_context_destroy (struct ast_context *con)
static enum ast_pbx_result __ast_pbx_run (struct ast_channel *c, struct ast_pbx_args *args)
static void __init_extensionstate_buf (void)
static void __init_switch_data (void)
static int _extension_match_core (const char *pattern, const char *data, enum ext_match_t mode)
static int acf_exception_read (struct ast_channel *chan, const char *name, char *data, char *buf, size_t buflen)
static int acf_retrieve_docs (struct ast_custom_function *acf)
static struct match_charadd_exten_to_pattern_tree (struct ast_context *con, struct ast_exten *e1, int findonly)
static struct match_charadd_pattern_node (struct ast_context *con, struct match_char *current, char *pattern, int is_pattern, int already, int specificity, struct match_char **parent)
static int add_pri (struct ast_context *con, struct ast_exten *tmp, struct ast_exten *el, struct ast_exten *e, int replace)
 add the extension in the priority chain.
static int add_pri_lockopt (struct ast_context *con, struct ast_exten *tmp, struct ast_exten *el, struct ast_exten *e, int replace, int lockhints)
 add the extension in the priority chain.
static struct match_charalready_in_tree (struct match_char *current, char *pat, int is_pattern)
int ast_active_calls (void)
 Retrieve the number of active calls.
int ast_add_extension (const char *context, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar)
 Add and extension to an extension context.
int ast_add_extension2 (struct ast_context *con, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar)
 Add an extension to an extension context, this time with an ast_context *.
static int ast_add_extension2_lockopt (struct ast_context *con, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar, int 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.
int ast_async_goto (struct ast_channel *chan, const char *context, const char *exten, int priority)
 Set the channel to next execute the specified dialplan location.
int ast_async_goto_by_name (const char *channame, const char *context, const char *exten, int priority)
 Set the channel to next execute the specified dialplan location.
int ast_async_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority)
int ast_async_parseable_goto (struct ast_channel *chan, const char *goto_string)
int ast_build_timing (struct ast_timing *i, const char *info_in)
 Construct a timing bitmap, for use in time-based conditionals.
int ast_canmatch_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
 Looks for a valid matching extension.
static int ast_change_hint (struct ast_exten *oe, struct ast_exten *ne)
 Change hint for an extension.
int ast_check_timing (const struct ast_timing *i)
 Evaluate a pre-constructed bitmap as to whether the current time falls within the range specified.
int ast_check_timing2 (const struct ast_timing *i, const struct timeval tv)
 Evaluate a pre-constructed bitmap as to whether a particular time falls within the range specified.
char * ast_complete_applications (const char *line, const char *word, int state)
 Command completion for the list of installed applications.
int ast_context_add_ignorepat (const char *context, const char *value, const char *registrar)
 Add an ignorepat.
int ast_context_add_ignorepat2 (struct ast_context *con, const char *value, const char *registrar)
int ast_context_add_include (const char *context, const char *include, const char *registrar)
 Add a context include.
int ast_context_add_include2 (struct ast_context *con, const char *value, const char *registrar)
 Add a context include.
int ast_context_add_switch (const char *context, const char *sw, const char *data, int eval, const char *registrar)
 Add a switch.
int ast_context_add_switch2 (struct ast_context *con, const char *value, const char *data, int eval, const char *registrar)
 Adds a switch (first param is a ast_context).
void ast_context_destroy (struct ast_context *con, const char *registrar)
 Destroy a context (matches the specified context (or ANY context if NULL).
ast_contextast_context_find (const char *name)
 Find a context.
ast_contextast_context_find_or_create (struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *name, const char *registrar)
 Register a new context or find an existing one.
int ast_context_lockmacro (const char *context)
 locks the macrolock in the given given context
int ast_context_remove_extension (const char *context, const char *extension, int priority, const char *registrar)
 Simply remove extension from context.
int ast_context_remove_extension2 (struct ast_context *con, const char *extension, int priority, const char *registrar, int already_locked)
 This functionc locks given context, search for the right extension and fires out all peer in this extensions with given priority. If priority is set to 0, all peers are removed. After that, unlock context and return.
int ast_context_remove_extension_callerid (const char *context, const char *extension, int priority, const char *callerid, int matchcallerid, const char *registrar)
int ast_context_remove_extension_callerid2 (struct ast_context *con, const char *extension, int priority, const char *callerid, int matchcallerid, const char *registrar, int already_locked)
int ast_context_remove_ignorepat (const char *context, const char *ignorepat, const char *registrar)
int ast_context_remove_ignorepat2 (struct ast_context *con, const char *ignorepat, const char *registrar)
int ast_context_remove_include (const char *context, const char *include, const char *registrar)
 Remove a context include.
int ast_context_remove_include2 (struct ast_context *con, const char *include, const char *registrar)
 Removes an include by an ast_context structure.
int ast_context_remove_switch (const char *context, const char *sw, const char *data, const char *registrar)
 Remove a switch.
int ast_context_remove_switch2 (struct ast_context *con, const char *sw, const char *data, const char *registrar)
 This function locks given context, removes switch, unlock context and return.
int ast_context_unlockmacro (const char *context)
 Unlocks the macrolock in the given context.
int ast_context_verify_includes (struct ast_context *con)
 Verifies includes in an ast_contect structure.
ast_custom_functionast_custom_function_find (const char *name)
int ast_custom_function_unregister (struct ast_custom_function *acf)
 Unregister a custom function.
int ast_destroy_timing (struct ast_timing *i)
 Deallocates memory structures associated with a timing bitmap.
enum ast_extension_states ast_devstate_to_extenstate (enum ast_device_state devstate)
 Map devstate to an extension state.
int ast_exists_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
 Determine whether an extension exists.
int ast_explicit_goto (struct ast_channel *chan, const char *context, const char *exten, int priority)
int ast_extension_close (const char *pattern, const char *data, int needmore)
int ast_extension_cmp (const char *a, const char *b)
 Determine if one extension should match before another.
int ast_extension_match (const char *pattern, const char *data)
 Determine if a given extension matches a given pattern (in NXX format).
int ast_extension_state (struct ast_channel *c, const char *context, const char *exten)
 Uses hint and devicestate callback to get the state of an extension.
static int ast_extension_state2 (struct ast_exten *e)
 Check state of extension by using hints.
const char * ast_extension_state2str (int extension_state)
 Return string representation of the state of an extension.
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_read2 (struct ast_channel *chan, const char *function, struct ast_str **str, ssize_t maxlen)
 executes a read operation on a function
int ast_func_write (struct ast_channel *chan, const char *function, const char *value)
 executes a write operation on a function
const char * ast_get_context_name (struct ast_context *con)
const char * ast_get_context_registrar (struct ast_context *c)
const char * ast_get_extension_app (struct ast_exten *e)
void * ast_get_extension_app_data (struct ast_exten *e)
const char * ast_get_extension_cidmatch (struct ast_exten *e)
ast_contextast_get_extension_context (struct ast_exten *exten)
const char * ast_get_extension_label (struct ast_exten *exten)
int ast_get_extension_matchcid (struct ast_exten *e)
const char * ast_get_extension_name (struct ast_exten *exten)
int ast_get_extension_priority (struct ast_exten *exten)
const char * ast_get_extension_registrar (struct ast_exten *e)
int ast_get_hint (char *hint, int hintsize, char *name, int namesize, struct ast_channel *c, const char *context, const char *exten)
 If an extension hint exists, return non-zero.
const char * ast_get_ignorepat_name (struct ast_ignorepat *ip)
const char * ast_get_ignorepat_registrar (struct ast_ignorepat *ip)
const char * ast_get_include_name (struct ast_include *inc)
const char * ast_get_include_registrar (struct ast_include *i)
const char * ast_get_switch_data (struct ast_sw *sw)
int ast_get_switch_eval (struct ast_sw *sw)
const char * ast_get_switch_name (struct ast_sw *sw)
const char * ast_get_switch_registrar (struct ast_sw *sw)
int ast_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority)
int ast_hashtab_compare_contexts (const void *ah_a, const void *ah_b)
 hashtable functions for contexts
unsigned int ast_hashtab_hash_contexts (const void *obj)
static struct ast_extenast_hint_extension (struct ast_channel *c, const char *context, const char *exten)
static struct ast_extenast_hint_extension_nolock (struct ast_channel *c, const char *context, const char *exten)
 Find hint for given extension in context.
int ast_ignore_pattern (const char *context, const char *pattern)
 Checks to see if a number should be ignored.
int ast_matchmore_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
 Looks to see if adding anything to this extension might match something. (exists ^ canmatch).
void ast_merge_contexts_and_delete (struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *registrar)
 Merge the temporary contexts into a global contexts list and delete from the global list the ones that are being added.
int ast_parseable_goto (struct ast_channel *chan, const char *goto_string)
int ast_pbx_init (void)
int ast_pbx_outgoing_app (const char *type, format_t format, void *data, int timeout, const char *app, const char *appdata, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel)
static int ast_pbx_outgoing_cdr_failed (void)
 Function to post an empty cdr after a spool call fails.
int ast_pbx_outgoing_exten (const char *type, format_t format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **channel)
enum ast_pbx_result ast_pbx_run (struct ast_channel *c)
 Execute the PBX in the current thread.
static void * ast_pbx_run_app (void *data)
 run the application and free the descriptor once done
enum ast_pbx_result ast_pbx_run_args (struct ast_channel *c, struct ast_pbx_args *args)
 Execute the PBX in the current thread.
enum ast_pbx_result ast_pbx_start (struct ast_channel *c)
 Create a new thread and start the PBX.
int ast_processed_calls (void)
 Retrieve the total number of calls processed through the PBX since last restart.
int ast_rdlock_context (struct ast_context *con)
 Read locks a given context.
int ast_rdlock_contexts ()
 Read locks the context list.
int ast_register_application2 (const char *app, int(*execute)(struct ast_channel *, const char *), const char *synopsis, const char *description, void *mod)
 Register an application.
int ast_register_switch (struct ast_switch *sw)
 Register an alternative dialplan switch.
static int ast_remove_hint (struct ast_exten *e)
 Remove hint from extension.
int ast_spawn_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid, int *found, int combined_find_spawn)
 Launch a new extension (i.e. new stack).
int ast_str_get_hint (struct ast_str **hint, ssize_t hintsize, struct ast_str **name, ssize_t namesize, struct ast_channel *c, const char *context, const char *exten)
 If an extension hint exists, return non-zero.
const char * ast_str_retrieve_variable (struct ast_str **str, ssize_t maxlen, struct ast_channel *c, struct varshead *headp, const char *var)
void ast_str_substitute_variables (struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, const char *templ)
void ast_str_substitute_variables_full (struct ast_str **buf, ssize_t maxlen, struct ast_channel *c, struct varshead *headp, const char *templ, size_t *used)
void ast_str_substitute_variables_varshead (struct ast_str **buf, ssize_t maxlen, struct varshead *headp, const char *templ)
static const char * ast_str_substring (struct ast_str *value, int offset, int length)
int ast_unlock_context (struct ast_context *con)
int ast_unlock_contexts ()
 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.
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 int find_hint_by_cb_id (void *obj, void *arg, int flags)
 Remove a watcher from the callback list.
static char * func_args (char *function)
 return a pointer to the arguments of the function, and terminates the function name with '\0'
static struct ast_extenget_canmatch_exten (struct match_char *node)
static unsigned get_range (char *src, int max, const char *const names[], const char *msg)
 helper function to return a range up to max (7, 12, 31 respectively). names, if supplied, is an array of names that should be mapped to numbers.
static void get_timerange (struct ast_timing *i, char *times)
 store a bitmask of valid times, one bit each 1 minute
static char * handle_debug_dialplan (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 Send ack once.
static char * handle_set_chanvar (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_set_extenpatternmatchnew (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_set_global (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_show_application (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_show_applications (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_show_chanvar (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI support for listing chanvar's variables in a parseable way.
static char * handle_show_dialplan (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_show_function (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_show_functions (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_show_globals (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI support for listing global variables in a parseable way.
static char * handle_show_hint (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 handle_show_hint: CLI support for listing registered dial plan hint
static char * handle_show_hints (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 handle_show_hints: CLI support for listing registered dial plan hints
static char * handle_show_switches (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 handle_show_switches: CLI support for listing registered dial plan switches
static int handle_statechange (void *datap)
static char * handle_unset_extenpatternmatchnew (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int hashtab_compare_exten_labels (const void *ah_a, const void *ah_b)
static int hashtab_compare_exten_numbers (const void *ah_a, const void *ah_b)
static int hashtab_compare_extens (const void *ha_a, const void *ah_b)
static unsigned int hashtab_hash_extens (const void *obj)
static unsigned int hashtab_hash_labels (const void *obj)
static unsigned int hashtab_hash_priority (const void *obj)
static int hint_cmp (void *obj, void *arg, int flags)
static int hint_hash (const void *obj, const int flags)
static int hints_data_provider_get (const struct ast_data_search *search, struct ast_data *data_root)
static int include_valid (struct ast_include *i)
static int increase_call_count (const struct ast_channel *c)
 Increase call count for channel.
static void insert_in_next_chars_alt_char_list (struct match_char **parent_ptr, struct match_char *node)
int load_pbx (void)
static int lookup_name (const char *s, const char *const names[], int max)
 Helper for get_range. return the index of the matching entry, starting from 1. If names is not supplied, try numeric values.
static void manager_dpsendack (struct mansession *s, const struct message *m)
 Send ack once.
static int manager_show_dialplan (struct mansession *s, const struct message *m)
 Manager listing of dial plan.
static int manager_show_dialplan_helper (struct mansession *s, const struct message *m, const char *actionidtext, const char *context, const char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude)
 Show dialplan extensions XXX this function is similar but not exactly the same as the CLI's show dialplan. Must check whether the difference is intentional or not.
static int matchcid (const char *cidpattern, const char *callerid)
static void new_find_extension (const char *str, struct scoreboard *score, struct match_char *tree, int length, int spec, const char *callerid, const char *label, enum ext_match_t action)
static int parse_variable_name (char *var, int *offset, int *length, int *isfunc)
 extract offset:length from variable name.
static int pbx_builtin_answer (struct ast_channel *, const char *)
static int pbx_builtin_background (struct ast_channel *, const char *)
static int pbx_builtin_busy (struct ast_channel *, const char *)
void pbx_builtin_clear_globals (void)
static int pbx_builtin_congestion (struct ast_channel *, const char *)
static int pbx_builtin_execiftime (struct ast_channel *, const char *)
const char * pbx_builtin_getvar_helper (struct ast_channel *chan, const char *name)
 Return a pointer to the value of the corresponding channel variable.
static int pbx_builtin_goto (struct ast_channel *, const char *)
static int pbx_builtin_gotoif (struct ast_channel *, const char *)
static int pbx_builtin_gotoiftime (struct ast_channel *, const char *)
static int pbx_builtin_hangup (struct ast_channel *, const char *)
static int pbx_builtin_importvar (struct ast_channel *, const char *)
static int pbx_builtin_incomplete (struct ast_channel *, const char *)
static int pbx_builtin_noop (struct ast_channel *, const char *)
static int pbx_builtin_proceeding (struct ast_channel *, const char *)
static int pbx_builtin_progress (struct ast_channel *, const char *)
void pbx_builtin_pushvar_helper (struct ast_channel *chan, const char *name, const char *value)
 Add a variable to the channel variable stack, without removing any previously set value.
int pbx_builtin_raise_exception (struct ast_channel *chan, const char *reason)
static int pbx_builtin_resetcdr (struct ast_channel *, const char *)
static int pbx_builtin_ringing (struct ast_channel *, const char *)
static int pbx_builtin_saycharacters (struct ast_channel *, const char *)
static int pbx_builtin_saydigits (struct ast_channel *, const char *)
static int pbx_builtin_saynumber (struct ast_channel *, const char *)
static int pbx_builtin_sayphonetic (struct ast_channel *, const char *)
int pbx_builtin_serialize_variables (struct ast_channel *chan, struct ast_str **buf)
 Create a human-readable string, specifying all variables and their corresponding values.
static int pbx_builtin_setamaflags (struct ast_channel *, const char *)
int pbx_builtin_setvar (struct ast_channel *chan, const char *data)
 Parse and set a single channel variable, where the name and value are separated with an '=' character.
int pbx_builtin_setvar_helper (struct ast_channel *chan, const char *name, const char *value)
 Add a variable to the channel variable stack, removing the most recently set value for the same name.
int pbx_builtin_setvar_multiple (struct ast_channel *chan, const char *vdata)
 Parse and set multiple channel variables, where the pairs are separated by the ',' character, and name and value are separated with an '=' character.
static int pbx_builtin_wait (struct ast_channel *, const char *)
static int pbx_builtin_waitexten (struct ast_channel *, const char *)
int pbx_checkcondition (const char *condition)
 Evaluate a condition.
static void pbx_destroy (struct ast_pbx *p)
int pbx_exec (struct ast_channel *c, struct ast_app *app, const char *data)
 Execute an application.
static int pbx_extension_helper (struct ast_channel *c, struct ast_context *con, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action, int *found, int combined_find_spawn)
 The return value depends on the action:.
ast_extenpbx_find_extension (struct ast_channel *chan, struct ast_context *bypass, struct pbx_find_info *q, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action)
ast_apppbx_findapp (const char *app)
 Look up an application.
static struct ast_switchpbx_findswitch (const char *sw)
static int pbx_parseable_goto (struct ast_channel *chan, const char *goto_string, int async)
void pbx_retrieve_variable (struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp)
 Retrieve the value of a builtin variable or variable from the channel variable stack.
int pbx_set_autofallthrough (int newval)
int pbx_set_extenpatternmatchnew (int newval)
void pbx_set_overrideswitch (const char *newval)
static void pbx_substitute_variables (char *passdata, int datalen, struct ast_channel *c, struct ast_exten *e)
void pbx_substitute_variables_helper (struct ast_channel *c, const char *cp1, char *cp2, int count)
void pbx_substitute_variables_helper_full (struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count, size_t *used)
void pbx_substitute_variables_varshead (struct varshead *headp, const char *cp1, char *cp2, int count)
static void * pbx_thread (void *data)
static void print_app_docs (struct ast_app *aa, int fd)
static void print_ext (struct ast_exten *e, char *buf, int buflen)
 helper function to print an extension
static 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 int testtime_write (struct ast_channel *chan, const char *cmd, char *var, const char *value)
static struct ast_extentrie_find_next_match (struct match_char *node)
static void unreference_cached_app (struct ast_app *app)
static void update_scoreboard (struct scoreboard *board, int length, int spec, struct ast_exten *exten, char last, const char *callerid, int deleted, struct match_char *node)
static void wait_for_hangup (struct ast_channel *chan, const void *data)

Variables

static int autofallthrough = 1
static struct ast_app_option background_opts [128] = { [ 's' ] = { .flag = (1 << 0) }, [ 'n' ] = { .flag = (1 << 1) }, [ 'm' ] = { .flag = (1 << 2) }, [ 'p' ] = { .flag = (1 << 3) },}
static struct pbx_builtin builtins []
 Declaration of builtin applications.
static ast_mutex_t conlock = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP }
 Lock for the ast_context list This lock MUST be recursive, or a deadlock on reload may result. See https://issues.asterisk.org/view.php?id=17643.
static struct ast_contextcontexts
static struct ast_hashtabcontexts_table = NULL
static int countcalls
static const char *const days []
static struct ast_event_subdevice_state_sub
 Subscription for device state change events.
static struct ast_taskprocessordevice_state_tps
static struct ast_custom_function exception_function
static struct ast_datastore_info exception_store_info
static int extenpatternmatchnew = 0
static struct cfextension_states extension_states []
static struct ast_threadstorage extensionstate_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_extensionstate_buf , .custom_init = NULL , }
static struct varshead globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE
static ast_rwlock_t globalslock = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RWLOCK_INITIALIZER }
static const int HASH_EXTENHINT_SIZE = 563
static struct ao2_containerhints
static struct ast_data_handler hints_data_provider
static ast_mutex_t maxcalllock = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP }
static const char *const months []
static char * overrideswitch = NULL
static struct ast_cli_entry pbx_cli []
static struct ast_data_entry pbx_data_providers []
static struct ast_app_option resetcdr_opts [128] = { [ 'w' ] = { .flag = AST_CDR_FLAG_POSTED }, [ 'a' ] = { .flag = AST_CDR_FLAG_LOCKED }, [ 'v' ] = { .flag = AST_CDR_FLAG_KEEP_VARS }, [ 'e' ] = { .flag = AST_CDR_FLAG_POST_ENABLE },}
static int stateid = 1
static struct ast_threadstorage switch_data = { .once = PTHREAD_ONCE_INIT , .key_init = __init_switch_data , .custom_init = NULL , }
static struct ast_custom_function testtime_function
static int totalcalls
static struct ast_app_option waitexten_opts [128] = { [ 'm' ] = { .flag = (1 << 0) , .arg_index = 0 + 1 }, [ 'd' ] = { .flag = (1 << 1) , .arg_index = 0 + 1 },}


Detailed Description

Core PBX routines.

Author:
Mark Spencer <markster@digium.com>

Definition in file pbx.c.


Define Documentation

#define AST_PBX_MAX_STACK   128

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

Definition at line 1419 of file pbx.c.

#define BACKGROUND_MATCHEXTEN   (1 << 2)

Definition at line 783 of file pbx.c.

Referenced by pbx_builtin_background().

#define BACKGROUND_NOANSWER   (1 << 1)

Definition at line 782 of file pbx.c.

Referenced by pbx_builtin_background().

#define BACKGROUND_PLAYBACK   (1 << 3)

Definition at line 784 of file pbx.c.

Referenced by pbx_builtin_background().

#define BACKGROUND_SKIP   (1 << 0)

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

Referenced by pbx_extension_helper().

#define NEW_MATCHER_CHK_MATCH

Referenced by new_find_extension().

#define NEW_MATCHER_RECURSE

#define SAY_STUBS

Definition at line 55 of file pbx.c.

#define STATUS_NO_CONTEXT   1

Definition at line 2533 of file pbx.c.

#define STATUS_NO_EXTENSION   2

Definition at line 2534 of file pbx.c.

#define STATUS_NO_LABEL   4

Definition at line 2536 of file pbx.c.

#define STATUS_NO_PRIORITY   3

Definition at line 2535 of file pbx.c.

#define STATUS_SUCCESS   5

Definition at line 2537 of file pbx.c.

#define SWITCH_DATA_LENGTH   256

Definition at line 773 of file pbx.c.

#define VAR_BUF_SIZE   4096

Definition at line 775 of file pbx.c.

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

#define VAR_HARDTRAN   3

Definition at line 779 of file pbx.c.

#define VAR_NORMAL   1

Definition at line 777 of file pbx.c.

#define VAR_SOFTTRAN   2

Definition at line 778 of file pbx.c.

#define WAITEXTEN_DIALTONE   (1 << 1)

Definition at line 794 of file pbx.c.

Referenced by pbx_builtin_waitexten().

#define WAITEXTEN_MOH   (1 << 0)

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

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

Referenced by ast_context_destroy().

08712 {
08713    struct ast_context *tmp, *tmpl=NULL;
08714    struct ast_exten *exten_item, *prio_item;
08715 
08716    for (tmp = list; tmp; ) {
08717       struct ast_context *next = NULL; /* next starting point */
08718          /* The following code used to skip forward to the next
08719             context with matching registrar, but this didn't
08720             make sense; individual priorities registrar'd to
08721             the matching registrar could occur in any context! */
08722       ast_debug(1, "Investigate ctx %s %s\n", tmp->name, tmp->registrar);
08723       if (con) {
08724          for (; tmp; tmpl = tmp, tmp = tmp->next) { /* skip to the matching context */
08725             ast_debug(1, "check ctx %s %s\n", tmp->name, tmp->registrar);
08726             if ( !strcasecmp(tmp->name, con->name) ) {
08727                break;   /* found it */
08728             }
08729          }
08730       }
08731 
08732       if (!tmp)   /* not found, we are done */
08733          break;
08734       ast_wrlock_context(tmp);
08735 
08736       if (registrar) {
08737          /* then search thru and remove any extens that match registrar. */
08738          struct ast_hashtab_iter *exten_iter;
08739          struct ast_hashtab_iter *prio_iter;
08740          struct ast_ignorepat *ip, *ipl = NULL, *ipn = NULL;
08741          struct ast_include *i, *pi = NULL, *ni = NULL;
08742          struct ast_sw *sw = NULL;
08743 
08744          /* remove any ignorepats whose registrar matches */
08745          for (ip = tmp->ignorepats; ip; ip = ipn) {
08746             ipn = ip->next;
08747             if (!strcmp(ip->registrar, registrar)) {
08748                if (ipl) {
08749                   ipl->next = ip->next;
08750                   ast_free(ip);
08751                   continue; /* don't change ipl */
08752                } else {
08753                   tmp->ignorepats = ip->next;
08754                   ast_free(ip);
08755                   continue; /* don't change ipl */
08756                }
08757             }
08758             ipl = ip;
08759          }
08760          /* remove any includes whose registrar matches */
08761          for (i = tmp->includes; i; i = ni) {
08762             ni = i->next;
08763             if (strcmp(i->registrar, registrar) == 0) {
08764                /* remove from list */
08765                if (pi) {
08766                   pi->next = i->next;
08767                   /* free include */
08768                   ast_free(i);
08769                   continue; /* don't change pi */
08770                } else {
08771                   tmp->includes = i->next;
08772                   /* free include */
08773                   ast_free(i);
08774                   continue; /* don't change pi */
08775                }
08776             }
08777             pi = i;
08778          }
08779          /* remove any switches whose registrar matches */
08780          AST_LIST_TRAVERSE_SAFE_BEGIN(&tmp->alts, sw, list) {
08781             if (strcmp(sw->registrar,registrar) == 0) {
08782                AST_LIST_REMOVE_CURRENT(list);
08783                ast_free(sw);
08784             }
08785          }
08786          AST_LIST_TRAVERSE_SAFE_END;
08787 
08788          if (tmp->root_table) { /* it is entirely possible that the context is EMPTY */
08789             exten_iter = ast_hashtab_start_traversal(tmp->root_table);
08790             while ((exten_item=ast_hashtab_next(exten_iter))) {
08791                int end_traversal = 1;
08792                prio_iter = ast_hashtab_start_traversal(exten_item->peer_table);
08793                while ((prio_item=ast_hashtab_next(prio_iter))) {
08794                   char extension[AST_MAX_EXTENSION];
08795                   char cidmatch[AST_MAX_EXTENSION];
08796                   if (!prio_item->registrar || strcmp(prio_item->registrar, registrar) != 0) {
08797                      continue;
08798                   }
08799                   ast_verb(3, "Remove %s/%s/%d, registrar=%s; con=%s(%p); con->root=%p\n",
08800                          tmp->name, prio_item->exten, prio_item->priority, registrar, con? con->name : "<nil>", con, con? con->root_table: NULL);
08801                   /* set matchcid to 1 to insure we get a direct match, and NULL registrar to make sure no wildcarding is done */
08802                   ast_copy_string(extension, prio_item->exten, sizeof(extension));
08803                   if (prio_item->cidmatch) {
08804                      ast_copy_string(cidmatch, prio_item->cidmatch, sizeof(cidmatch));
08805                   }
08806                   end_traversal &= ast_context_remove_extension_callerid2(tmp, extension, prio_item->priority, prio_item->cidmatch ? cidmatch : NULL, 1, NULL, 1);
08807                }
08808                /* Explanation:
08809                 * ast_context_remove_extension_callerid2 will destroy the extension that it comes across. This
08810                 * destruction includes destroying the exten's peer_table, which we are currently traversing. If
08811                 * ast_context_remove_extension_callerid2 ever should return '0' then this means we have destroyed
08812                 * the hashtable which we are traversing, and thus calling ast_hashtab_end_traversal will result
08813                 * in reading invalid memory. Thus, if we detect that we destroyed the hashtable, then we will simply
08814                 * free the iterator
08815                 */
08816                if (end_traversal) {
08817                   ast_hashtab_end_traversal(prio_iter);
08818                } else {
08819                   ast_free(prio_iter);
08820                }
08821             }
08822             ast_hashtab_end_traversal(exten_iter);
08823          }
08824 
08825          /* delete the context if it's registrar matches, is empty, has refcount of 1, */
08826          /* it's not empty, if it has includes, ignorepats, or switches that are registered from
08827             another registrar. It's not empty if there are any extensions */
08828          if (strcmp(tmp->registrar, registrar) == 0 && tmp->refcount < 2 && !tmp->root && !tmp->ignorepats && !tmp->includes && AST_LIST_EMPTY(&tmp->alts)) {
08829             ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar);
08830             ast_hashtab_remove_this_object(contexttab, tmp);
08831 
08832             next = tmp->next;
08833             if (tmpl)
08834                tmpl->next = next;
08835             else
08836                contexts = next;
08837             /* Okay, now we're safe to let it go -- in a sense, we were
08838                ready to let it go as soon as we locked it. */
08839             ast_unlock_context(tmp);
08840             __ast_internal_context_destroy(tmp);
08841          } else {
08842             ast_debug(1,"Couldn't delete ctx %s/%s; refc=%d; tmp.root=%p\n", tmp->name, tmp->registrar,
08843                     tmp->refcount, tmp->root);
08844             ast_unlock_context(tmp);
08845             next = tmp->next;
08846             tmpl = tmp;
08847          }
08848       } else if (con) {
08849          ast_verb(3, "Deleting context %s registrar=%s\n", tmp->name, tmp->registrar);
08850          ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar);
08851          ast_hashtab_remove_this_object(contexttab, tmp);
08852 
08853          next = tmp->next;
08854          if (tmpl)
08855             tmpl->next = next;
08856          else
08857             contexts = next;
08858          /* Okay, now we're safe to let it go -- in a sense, we were
08859             ready to let it go as soon as we locked it. */
08860          ast_unlock_context(tmp);
08861          __ast_internal_context_destroy(tmp);
08862       }
08863 
08864       /* if we have a specific match, we are done, otherwise continue */
08865       tmp = con ? NULL : next;
08866    }
08867 }

int __ast_custom_function_register ( struct ast_custom_function acf,
struct ast_module mod 
)

Register a custom function.

Definition at line 3414 of file pbx.c.

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

Referenced by load_pbx().

03415 {
03416    struct ast_custom_function *cur;
03417    char tmps[80];
03418 
03419    if (!acf) {
03420       return -1;
03421    }
03422 
03423    acf->mod = mod;
03424 #ifdef AST_XML_DOCS
03425    acf->docsrc = AST_STATIC_DOC;
03426 #endif
03427 
03428    if (acf_retrieve_docs(acf)) {
03429       return -1;
03430    }
03431 
03432    AST_RWLIST_WRLOCK(&acf_root);
03433 
03434    AST_RWLIST_TRAVERSE(&acf_root, cur, acflist) {
03435       if (!strcmp(acf->name, cur->name)) {
03436          ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name);
03437          AST_RWLIST_UNLOCK(&acf_root);
03438          return -1;
03439       }
03440    }
03441 
03442    /* Store in alphabetical order */
03443    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) {
03444       if (strcasecmp(acf->name, cur->name) < 0) {
03445          AST_RWLIST_INSERT_BEFORE_CURRENT(acf, acflist);
03446          break;
03447       }
03448    }
03449    AST_RWLIST_TRAVERSE_SAFE_END;
03450 
03451    if (!cur) {
03452       AST_RWLIST_INSERT_TAIL(&acf_root, acf, acflist);
03453    }
03454 
03455    AST_RWLIST_UNLOCK(&acf_root);
03456 
03457    ast_verb(2, "Registered custom function '%s'\n", term_color(tmps, acf->name, COLOR_BRCYAN, 0, sizeof(tmps)));
03458 
03459    return 0;
03460 }

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

Definition at line 10107 of file pbx.c.

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

Referenced by ast_async_goto_if_exists(), and ast_goto_if_exists().

10108 {
10109    int (*goto_func)(struct ast_channel *chan, const char *context, const char *exten, int priority);
10110 
10111    if (!chan)
10112       return -2;
10113 
10114    if (context == NULL)
10115       context = chan->context;
10116    if (exten == NULL)
10117       exten = chan->exten;
10118 
10119    goto_func = (async) ? ast_async_goto : ast_explicit_goto;
10120    if (ast_exists_extension(chan, context, exten, priority,
10121       S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL)))
10122       return goto_func(chan, context, exten, priority);
10123    else {
10124       return AST_PBX_GOTO_FAILED;
10125    }
10126 }

static void __ast_internal_context_destroy ( struct ast_context con  )  [static]

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

08665 {
08666    struct ast_include *tmpi;
08667    struct ast_sw *sw;
08668    struct ast_exten *e, *el, *en;
08669    struct ast_ignorepat *ipi;
08670    struct ast_context *tmp = con;
08671 
08672    for (tmpi = tmp->includes; tmpi; ) { /* Free includes */
08673       struct ast_include *tmpil = tmpi;
08674       tmpi = tmpi->next;
08675       ast_free(tmpil);
08676    }
08677    for (ipi = tmp->ignorepats; ipi; ) { /* Free ignorepats */
08678       struct ast_ignorepat *ipl = ipi;
08679       ipi = ipi->next;
08680       ast_free(ipl);
08681    }
08682    if (tmp->registrar)
08683       ast_free(tmp->registrar);
08684 
08685    /* destroy the hash tabs */
08686    if (tmp->root_table) {
08687       ast_hashtab_destroy(tmp->root_table, 0);
08688    }
08689    /* and destroy the pattern tree */
08690    if (tmp->pattern_tree)
08691       destroy_pattern_tree(tmp->pattern_tree);
08692 
08693    while ((sw = AST_LIST_REMOVE_HEAD(&tmp->alts, list)))
08694       ast_free(sw);
08695    for (e = tmp->root; e;) {
08696       for (en = e->peer; en;) {
08697          el = en;
08698          en = en->peer;
08699          destroy_exten(el);
08700       }
08701       el = e;
08702       e = e->next;
08703       destroy_exten(el);
08704    }
08705    tmp->root = NULL;
08706    ast_rwlock_destroy(&tmp->lock);
08707    ast_free(tmp);
08708 }

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

Definition at line 4651 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::caller, ast_channel::cdr, ast_channel::context, ast_pbx::dtimeoutms, ast_channel::exten, ast_party_caller::id, LOG_WARNING, ast_channel::name, ast_party_id::number, ast_channel::pbx, pbx_builtin_raise_exception(), ast_channel::priority, ast_pbx::rtimeoutms, S_COR, set_ext_pri(), ast_party_number::str, and ast_party_number::valid.

Referenced by ast_pbx_run_args(), and pbx_thread().

04653 {
04654    int found = 0; /* set if we find at least one match */
04655    int res = 0;
04656    int autoloopflag;
04657    int error = 0;    /* set an error conditions */
04658 
04659    /* A little initial setup here */
04660    if (c->pbx) {
04661       ast_log(LOG_WARNING, "%s already has PBX structure??\n", c->name);
04662       /* XXX and now what ? */
04663       ast_free(c->pbx);
04664    }
04665    if (!(c->pbx = ast_calloc(1, sizeof(*c->pbx))))
04666       return -1;
04667    /* Set reasonable defaults */
04668    c->pbx->rtimeoutms = 10000;
04669    c->pbx->dtimeoutms = 5000;
04670 
04671    autoloopflag = ast_test_flag(c, AST_FLAG_IN_AUTOLOOP);   /* save value to restore at the end */
04672    ast_set_flag(c, AST_FLAG_IN_AUTOLOOP);
04673 
04674    /* Start by trying whatever the channel is set to */
04675    if (!ast_exists_extension(c, c->context, c->exten, c->priority,
04676       S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
04677       /* If not successful fall back to 's' */
04678       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);
04679       /* XXX the original code used the existing priority in the call to
04680        * ast_exists_extension(), and reset it to 1 afterwards.
04681        * I believe the correct thing is to set it to 1 immediately.
04682        */
04683       set_ext_pri(c, "s", 1);
04684       if (!ast_exists_extension(c, c->context, c->exten, c->priority,
04685          S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
04686          /* JK02: And finally back to default if everything else failed */
04687          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);
04688          ast_copy_string(c->context, "default", sizeof(c->context));
04689       }
04690    }
04691    if (c->cdr) {
04692       /* allow CDR variables that have been collected after channel was created to be visible during call */
04693       ast_cdr_update(c);
04694    }
04695    for (;;) {
04696       char dst_exten[256]; /* buffer to accumulate digits */
04697       int pos = 0;      /* XXX should check bounds */
04698       int digit = 0;
04699       int invalid = 0;
04700       int timeout = 0;
04701 
04702       /* loop on priorities in this context/exten */
04703       while (!(res = ast_spawn_extension(c, c->context, c->exten, c->priority,
04704          S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL),
04705          &found, 1))) {
04706          if ((c->_softhangup & AST_SOFTHANGUP_TIMEOUT)
04707             && ast_exists_extension(c, c->context, "T", 1,
04708                S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
04709             set_ext_pri(c, "T", 0); /* 0 will become 1 with the c->priority++; at the end */
04710             /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
04711             memset(&c->whentohangup, 0, sizeof(c->whentohangup));
04712             c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT;
04713          } else if ((c->_softhangup & AST_SOFTHANGUP_TIMEOUT)
04714             && ast_exists_extension(c, c->context, "e", 1,
04715                S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
04716             pbx_builtin_raise_exception(c, "ABSOLUTETIMEOUT");
04717             /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
04718             memset(&c->whentohangup, 0, sizeof(c->whentohangup));
04719             c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT;
04720          } else if (c->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) {
04721             c->_softhangup &= ~AST_SOFTHANGUP_ASYNCGOTO;
04722             continue;
04723          } else if (ast_check_hangup(c)) {
04724             ast_debug(1, "Extension %s, priority %d returned normally even though call was hung up\n",
04725                c->exten, c->priority);
04726             error = 1;
04727             break;
04728          }
04729          c->priority++;
04730       } /* end while  - from here on we can use 'break' to go out */
04731       if (found && res) {
04732          /* Something bad happened, or a hangup has been requested. */
04733          if (strchr("0123456789ABCDEF*#", res)) {
04734             ast_debug(1, "Oooh, got something to jump out with ('%c')!\n", res);
04735             pos = 0;
04736             dst_exten[pos++] = digit = res;
04737             dst_exten[pos] = '\0';
04738          } else if (res == AST_PBX_INCOMPLETE) {
04739             ast_debug(1, "Spawn extension (%s,%s,%d) exited INCOMPLETE on '%s'\n", c->context, c->exten, c->priority, c->name);
04740             ast_verb(2, "Spawn extension (%s, %s, %d) exited INCOMPLETE on '%s'\n", c->context, c->exten, c->priority, c->name);
04741 
04742             /* Don't cycle on incomplete - this will happen if the only extension that matches is our "incomplete" extension */
04743             if (!ast_matchmore_extension(c, c->context, c->exten, 1,
04744                S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
04745                invalid = 1;
04746             } else {
04747                ast_copy_string(dst_exten, c->exten, sizeof(dst_exten));
04748                digit = 1;
04749                pos = strlen(dst_exten);
04750             }
04751          } else {
04752             ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
04753             ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
04754 
04755             if ((res == AST_PBX_ERROR)
04756                && ast_exists_extension(c, c->context, "e", 1,
04757                   S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
04758                /* if we are already on the 'e' exten, don't jump to it again */
04759                if (!strcmp(c->exten, "e")) {
04760                   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);
04761                   error = 1;
04762                } else {
04763                   pbx_builtin_raise_exception(c, "ERROR");
04764                   continue;
04765                }
04766             }
04767 
04768             if (c->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) {
04769                c->_softhangup &= ~AST_SOFTHANGUP_ASYNCGOTO;
04770                continue;
04771             } else if ((c->_softhangup & AST_SOFTHANGUP_TIMEOUT)
04772                && ast_exists_extension(c, c->context, "T", 1,
04773                   S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
04774                set_ext_pri(c, "T", 1);
04775                /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
04776                memset(&c->whentohangup, 0, sizeof(c->whentohangup));
04777                c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT;
04778                continue;
04779             } else {
04780                if (c->cdr)
04781                   ast_cdr_update(c);
04782                error = 1;
04783                break;
04784             }
04785          }
04786       }
04787       if (error)
04788          break;
04789 
04790       /*!\note
04791        * We get here on a failure of some kind:  non-existing extension or
04792        * hangup.  We have options, here.  We can either catch the failure
04793        * and continue, or we can drop out entirely. */
04794 
04795       if (invalid
04796          || !ast_exists_extension(c, c->context, c->exten, 1,
04797             S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
04798          /*!\note
04799           * If there is no match at priority 1, it is not a valid extension anymore.
04800           * Try to continue at "i" (for invalid) or "e" (for exception) or exit if
04801           * neither exist.
04802           */
04803          if (ast_exists_extension(c, c->context, "i", 1,
04804             S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
04805             ast_verb(3, "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, c->name);
04806             pbx_builtin_setvar_helper(c, "INVALID_EXTEN", c->exten);
04807             set_ext_pri(c, "i", 1);
04808          } else if (ast_exists_extension(c, c->context, "e", 1,
04809             S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
04810             pbx_builtin_raise_exception(c, "INVALID");
04811          } else {
04812             ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n",
04813                c->name, c->exten, c->context);
04814             error = 1; /* we know what to do with it */
04815             break;
04816          }
04817       } else if (c->_softhangup & AST_SOFTHANGUP_TIMEOUT) {
04818          /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */
04819          c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT;
04820       } else { /* keypress received, get more digits for a full extension */
04821          int waittime = 0;
04822          if (digit)
04823             waittime = c->pbx->dtimeoutms;
04824          else if (!autofallthrough)
04825             waittime = c->pbx->rtimeoutms;
04826          if (!waittime) {
04827             const char *status = pbx_builtin_getvar_helper(c, "DIALSTATUS");
04828             if (!status)
04829                status = "UNKNOWN";
04830             ast_verb(3, "Auto fallthrough, channel '%s' status is '%s'\n", c->name, status);
04831             if (!strcasecmp(status, "CONGESTION"))
04832                res = pbx_builtin_congestion(c, "10");
04833             else if (!strcasecmp(status, "CHANUNAVAIL"))
04834                res = pbx_builtin_congestion(c, "10");
04835             else if (!strcasecmp(status, "BUSY"))
04836                res = pbx_builtin_busy(c, "10");
04837             error = 1; /* XXX disable message */
04838             break;   /* exit from the 'for' loop */
04839          }
04840 
04841          if (collect_digits(c, waittime, dst_exten, sizeof(dst_exten), pos))
04842             break;
04843          if (res == AST_PBX_INCOMPLETE && ast_strlen_zero(&dst_exten[pos]))
04844             timeout = 1;
04845          if (!timeout
04846             && ast_exists_extension(c, c->context, dst_exten, 1,
04847                S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { /* Prepare the next cycle */
04848             set_ext_pri(c, dst_exten, 1);
04849          } else {
04850             /* No such extension */
04851             if (!timeout && !ast_strlen_zero(dst_exten)) {
04852                /* An invalid extension */
04853                if (ast_exists_extension(c, c->context, "i", 1,
04854                   S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
04855                   ast_verb(3, "Invalid extension '%s' in context '%s' on %s\n", dst_exten, c->context, c->name);
04856                   pbx_builtin_setvar_helper(c, "INVALID_EXTEN", dst_exten);
04857                   set_ext_pri(c, "i", 1);
04858                } else if (ast_exists_extension(c, c->context, "e", 1,
04859                   S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
04860                   pbx_builtin_raise_exception(c, "INVALID");
04861                } else {
04862                   ast_log(LOG_WARNING, "Invalid extension '%s', but no rule 'i' in context '%s'\n", dst_exten, c->context);
04863                   found = 1; /* XXX disable message */
04864                   break;
04865                }
04866             } else {
04867                /* A simple timeout */
04868                if (ast_exists_extension(c, c->context, "t", 1,
04869                   S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
04870                   ast_verb(3, "Timeout on %s\n", c->name);
04871                   set_ext_pri(c, "t", 1);
04872                } else if (ast_exists_extension(c, c->context, "e", 1,
04873                   S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
04874                   pbx_builtin_raise_exception(c, "RESPONSETIMEOUT");
04875                } else {
04876                   ast_log(LOG_WARNING, "Timeout, but no rule 't' in context '%s'\n", c->context);
04877                   found = 1; /* XXX disable message */
04878                   break;
04879                }
04880             }
04881          }
04882          if (c->cdr) {
04883             ast_verb(2, "CDR updated on %s\n",c->name);
04884             ast_cdr_update(c);
04885          }
04886       }
04887    }
04888 
04889    if (!found && !error) {
04890       ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name);
04891    }
04892 
04893    if (!args || !args->no_hangup_chan) {
04894       ast_softhangup(c, AST_SOFTHANGUP_APPUNLOAD);
04895    }
04896 
04897    if ((!args || !args->no_hangup_chan)
04898       && !ast_test_flag(c, AST_FLAG_BRIDGE_HANGUP_RUN)
04899       && ast_exists_extension(c, c->context, "h", 1,
04900          S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
04901       set_ext_pri(c, "h", 1);
04902       if (c->cdr && ast_opt_end_cdr_before_h_exten) {
04903          ast_cdr_end(c->cdr);
04904       }
04905       while ((res = ast_spawn_extension(c, c->context, c->exten, c->priority,
04906          S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL),
04907          &found, 1)) == 0) {
04908          c->priority++;
04909       }
04910       if (found && res) {
04911          /* Something bad happened, or a hangup has been requested. */
04912          ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
04913          ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
04914       }
04915    }
04916    ast_set2_flag(c, autoloopflag, AST_FLAG_IN_AUTOLOOP);
04917    ast_clear_flag(c, AST_FLAG_BRIDGE_HANGUP_RUN); /* from one round to the next, make sure this gets cleared */
04918    pbx_destroy(c->pbx);
04919    c->pbx = NULL;
04920 
04921    if (!args || !args->no_hangup_chan) {
04922       ast_hangup(c);
04923    }
04924 
04925    return 0;
04926 }

static void __init_extensionstate_buf ( void   )  [static]

Definition at line 807 of file pbx.c.

00810 : An extension

static void __init_switch_data ( void   )  [static]

Definition at line 806 of file pbx.c.

00810 : An extension

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

Definition at line 2308 of file pbx.c.

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

Referenced by extension_match_core().

02309 {
02310    mode &= E_MATCH_MASK;   /* only consider the relevant bits */
02311 
02312 #ifdef NEED_DEBUG_HERE
02313    ast_log(LOG_NOTICE,"match core: pat: '%s', dat: '%s', mode=%d\n", pattern, data, (int)mode);
02314 #endif
02315 
02316    if ( (mode == E_MATCH) && (pattern[0] == '_') && (!strcasecmp(pattern,data)) ) { /* note: if this test is left out, then _x. will not match _x. !!! */
02317 #ifdef NEED_DEBUG_HERE
02318       ast_log(LOG_NOTICE,"return (1) - pattern matches pattern\n");
02319 #endif
02320       return 1;
02321    }
02322 
02323    if (pattern[0] != '_') { /* not a pattern, try exact or partial match */
02324       int ld = strlen(data), lp = strlen(pattern);
02325 
02326       if (lp < ld) {    /* pattern too short, cannot match */
02327 #ifdef NEED_DEBUG_HERE
02328          ast_log(LOG_NOTICE,"return (0) - pattern too short, cannot match\n");
02329 #endif
02330          return 0;
02331       }
02332       /* depending on the mode, accept full or partial match or both */
02333       if (mode == E_MATCH) {
02334 #ifdef NEED_DEBUG_HERE
02335          ast_log(LOG_NOTICE,"return (!strcmp(%s,%s) when mode== E_MATCH)\n", pattern, data);
02336 #endif
02337          return !strcmp(pattern, data); /* 1 on match, 0 on fail */
02338       }
02339       if (ld == 0 || !strncasecmp(pattern, data, ld)) { /* partial or full match */
02340 #ifdef NEED_DEBUG_HERE
02341          ast_log(LOG_NOTICE,"return (mode(%d) == E_MATCHMORE ? lp(%d) > ld(%d) : 1)\n", mode, lp, ld);
02342 #endif
02343          return (mode == E_MATCHMORE) ? lp > ld : 1; /* XXX should consider '!' and '/' ? */
02344       } else {
02345 #ifdef NEED_DEBUG_HERE
02346          ast_log(LOG_NOTICE,"return (0) when ld(%d) > 0 && pattern(%s) != data(%s)\n", ld, pattern, data);
02347 #endif
02348          return 0;
02349       }
02350    }
02351    pattern++; /* skip leading _ */
02352    /*
02353     * XXX below we stop at '/' which is a separator for the CID info. However we should
02354     * not store '/' in the pattern at all. When we insure it, we can remove the checks.
02355     */
02356    while (*data && *pattern && *pattern != '/') {
02357       const char *end;
02358 
02359       if (*data == '-') { /* skip '-' in data (just a separator) */
02360          data++;
02361          continue;
02362       }
02363       switch (toupper(*pattern)) {
02364       case '[':   /* a range */
02365          end = strchr(pattern+1, ']'); /* XXX should deal with escapes ? */
02366          if (end == NULL) {
02367             ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n");
02368             return 0;   /* unconditional failure */
02369          }
02370          for (pattern++; pattern != end; pattern++) {
02371             if (pattern+2 < end && pattern[1] == '-') { /* this is a range */
02372                if (*data >= pattern[0] && *data <= pattern[2])
02373                   break;   /* match found */
02374                else {
02375                   pattern += 2; /* skip a total of 3 chars */
02376                   continue;
02377                }
02378             } else if (*data == pattern[0])
02379                break;   /* match found */
02380          }
02381          if (pattern == end) {
02382 #ifdef NEED_DEBUG_HERE
02383             ast_log(LOG_NOTICE,"return (0) when pattern==end\n");
02384 #endif
02385             return 0;
02386          }
02387          pattern = end; /* skip and continue */
02388          break;
02389       case 'N':
02390          if (*data < '2' || *data > '9') {
02391 #ifdef NEED_DEBUG_HERE
02392             ast_log(LOG_NOTICE,"return (0) N is matched\n");
02393 #endif
02394             return 0;
02395          }
02396          break;
02397       case 'X':
02398          if (*data < '0' || *data > '9') {
02399 #ifdef NEED_DEBUG_HERE
02400             ast_log(LOG_NOTICE,"return (0) X is matched\n");
02401 #endif
02402             return 0;
02403          }
02404          break;
02405       case 'Z':
02406          if (*data < '1' || *data > '9') {
02407 #ifdef NEED_DEBUG_HERE
02408             ast_log(LOG_NOTICE,"return (0) Z is matched\n");
02409 #endif
02410             return 0;
02411          }
02412          break;
02413       case '.':   /* Must match, even with more digits */
02414 #ifdef NEED_DEBUG_HERE
02415          ast_log(LOG_NOTICE, "return (1) when '.' is matched\n");
02416 #endif
02417          return 1;
02418       case '!':   /* Early match */
02419 #ifdef NEED_DEBUG_HERE
02420          ast_log(LOG_NOTICE, "return (2) when '!' is matched\n");
02421 #endif
02422          return 2;
02423       case ' ':
02424       case '-':   /* Ignore these in patterns */
02425          data--; /* compensate the final data++ */
02426          break;
02427       default:
02428          if (*data != *pattern) {
02429 #ifdef NEED_DEBUG_HERE
02430             ast_log(LOG_NOTICE, "return (0) when *data(%c) != *pattern(%c)\n", *data, *pattern);
02431 #endif
02432             return 0;
02433          }
02434       }
02435       data++;
02436       pattern++;
02437    }
02438    if (*data)        /* data longer than pattern, no match */ {
02439 #ifdef NEED_DEBUG_HERE
02440       ast_log(LOG_NOTICE, "return (0) when data longer than pattern\n");
02441 #endif
02442       return 0;
02443    }
02444 
02445    /*
02446     * match so far, but ran off the end of the data.
02447     * Depending on what is next, determine match or not.
02448     */
02449    if (*pattern == '\0' || *pattern == '/') {   /* exact match */
02450 #ifdef NEED_DEBUG_HERE
02451       ast_log(LOG_NOTICE, "at end, return (%d) in 'exact match'\n", (mode==E_MATCHMORE) ? 0 : 1);
02452 #endif
02453       return (mode == E_MATCHMORE) ? 0 : 1;  /* this is a failure for E_MATCHMORE */
02454    } else if (*pattern == '!')   {     /* early match */
02455 #ifdef NEED_DEBUG_HERE
02456       ast_log(LOG_NOTICE, "at end, return (2) when '!' is matched\n");
02457 #endif
02458       return 2;
02459    } else {                /* partial match */
02460 #ifdef NEED_DEBUG_HERE
02461       ast_log(LOG_NOTICE, "at end, return (%d) which deps on E_MATCH\n", (mode == E_MATCH) ? 0 : 1);
02462 #endif
02463       return (mode == E_MATCH) ? 0 : 1;   /* this is a failure for E_MATCH */
02464    }
02465 }

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

Definition at line 3151 of file pbx.c.

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

03152 {
03153    struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL);
03154    struct pbx_exception *exception = NULL;
03155    if (!ds || !ds->data)
03156       return -1;
03157    exception = ds->data;
03158    if (!strcasecmp(data, "REASON"))
03159       ast_copy_string(buf, exception->reason, buflen);
03160    else if (!strcasecmp(data, "CONTEXT"))
03161       ast_copy_string(buf, exception->context, buflen);
03162    else if (!strncasecmp(data, "EXTEN", 5))
03163       ast_copy_string(buf, exception->exten, buflen);
03164    else if (!strcasecmp(data, "PRIORITY"))
03165       snprintf(buf, buflen, "%d", exception->priority);
03166    else
03167       return -1;
03168    return 0;
03169 }

static int acf_retrieve_docs ( struct ast_custom_function acf  )  [static]

Definition at line 3369 of file pbx.c.

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

Referenced by __ast_custom_function_register().

03370 {
03371 #ifdef AST_XML_DOCS
03372    char *tmpxml;
03373 
03374    /* Let's try to find it in the Documentation XML */
03375    if (!ast_strlen_zero(acf->desc) || !ast_strlen_zero(acf->synopsis)) {
03376       return 0;
03377    }
03378 
03379    if (ast_string_field_init(acf, 128)) {
03380       return -1;
03381    }
03382 
03383    /* load synopsis */
03384    tmpxml = ast_xmldoc_build_synopsis("function", acf->name);
03385    ast_string_field_set(acf, synopsis, tmpxml);
03386    ast_free(tmpxml);
03387 
03388    /* load description */
03389    tmpxml = ast_xmldoc_build_description("function", acf->name);
03390    ast_string_field_set(acf, desc, tmpxml);
03391    ast_free(tmpxml);
03392 
03393    /* load syntax */
03394    tmpxml = ast_xmldoc_build_syntax("function", acf->name);
03395    ast_string_field_set(acf, syntax, tmpxml);
03396    ast_free(tmpxml);
03397 
03398    /* load arguments */
03399    tmpxml = ast_xmldoc_build_arguments("function", acf->name);
03400    ast_string_field_set(acf, arguments, tmpxml);
03401    ast_free(tmpxml);
03402 
03403    /* load seealso */
03404    tmpxml = ast_xmldoc_build_seealso("function", acf->name);
03405    ast_string_field_set(acf, seealso, tmpxml);
03406    ast_free(tmpxml);
03407 
03408    acf->docsrc = AST_XML_DOC;
03409 #endif
03410 
03411    return 0;
03412 }

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

Definition at line 1944 of file pbx.c.

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

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

01945 {
01946    struct match_char *m1 = NULL, *m2 = NULL, **m0;
01947    int specif;
01948    int already;
01949    int pattern = 0;
01950    char buf[256];
01951    char extenbuf[512];
01952    char *s1 = extenbuf;
01953    int l1 = strlen(e1->exten) + strlen(e1->cidmatch) + 2;
01954 
01955 
01956    ast_copy_string(extenbuf, e1->exten, sizeof(extenbuf));
01957 
01958    if (e1->matchcid &&  l1 <= sizeof(extenbuf)) {
01959       strcat(extenbuf, "/");
01960       strcat(extenbuf, e1->cidmatch);
01961    } else if (l1 > sizeof(extenbuf)) {
01962       ast_log(LOG_ERROR, "The pattern %s/%s is too big to deal with: it will be ignored! Disaster!\n", e1->exten, e1->cidmatch);
01963       return 0;
01964    }
01965 #ifdef NEED_DEBUG
01966    ast_log(LOG_DEBUG, "Adding exten %s%c%s to tree\n", s1, e1->matchcid ? '/' : ' ', e1->matchcid ? e1->cidmatch : "");
01967 #endif
01968    m1 = con->pattern_tree; /* each pattern starts over at the root of the pattern tree */
01969    m0 = &con->pattern_tree;
01970    already = 1;
01971 
01972    if ( *s1 == '_') {
01973       pattern = 1;
01974       s1++;
01975    }
01976    while (*s1) {
01977       if (pattern && *s1 == '[' && *(s1 - 1) != '\\') {
01978          char *s2 = buf;
01979          buf[0] = 0;
01980          s1++; /* get past the '[' */
01981          while (*s1 != ']' && *(s1 - 1) != '\\') {
01982             if (*s1 == '\\') {
01983                if (*(s1 + 1) == ']') {
01984                   *s2++ = ']';
01985                   s1 += 2;
01986                } else if (*(s1 + 1) == '\\') {
01987                   *s2++ = '\\';
01988                   s1 += 2;
01989                } else if (*(s1 + 1) == '-') {
01990                   *s2++ = '-';
01991                   s1 += 2;
01992                } else if (*(s1 + 1) == '[') {
01993                   *s2++ = '[';
01994                   s1 += 2;
01995                }
01996             } else if (*s1 == '-') { /* remember to add some error checking to all this! */
01997                char s3 = *(s1 - 1);
01998                char s4 = *(s1 + 1);
01999                for (s3++; s3 <= s4; s3++) {
02000                   *s2++ = s3;
02001                }
02002                s1 += 2;
02003             } else if (*s1 == '\0') {
02004                ast_log(LOG_WARNING, "A matching ']' was not found for '[' in pattern string '%s'\n", extenbuf);
02005                break;
02006             } else {
02007                *s2++ = *s1++;
02008             }
02009          }
02010          *s2 = 0; /* null terminate the exploded range */
02011          /* sort the characters */
02012 
02013          specif = strlen(buf);
02014          qsort(buf, specif, 1, compare_char);
02015          specif <<= 8;
02016          specif += buf[0];
02017       } else if (*s1 == '-') {
02018          /* Skip dashes in patterns */
02019          s1++;
02020          continue;
02021       } else {
02022          if (*s1 == '\\') {
02023             s1++;
02024             buf[0] = *s1;
02025          } else {
02026             if (pattern) {
02027                if (*s1 == 'n') { /* make sure n,x,z patterns are canonicalized to N,X,Z */
02028                   *s1 = 'N';
02029                } else if (*s1 == 'x') {
02030                   *s1 = 'X';
02031                } else if (*s1 == 'z') {
02032                   *s1 = 'Z';
02033                }
02034             }
02035             buf[0] = *s1;
02036          }
02037          buf[1] = 0;
02038          specif = 1;
02039       }
02040       m2 = 0;
02041       if (already && (m2 = already_in_tree(m1, buf, pattern)) && m2->next_char) {
02042          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...
02043                         a shorter pattern might win if the longer one doesn't match */
02044             if (m2->exten) {
02045                ast_log(LOG_WARNING, "Found duplicate exten. Had %s found %s\n", m2->exten->exten, e1->exten);
02046             }
02047             m2->exten = e1;
02048             m2->deleted = 0;
02049          }
02050          m1 = m2->next_char; /* m1 points to the node to compare against */
02051          m0 = &m2->next_char; /* m0 points to the ptr that points to m1 */
02052       } else { /* not already OR not m2 OR nor m2->next_char */
02053          if (m2) {
02054             if (findonly) {
02055                return m2;
02056             }
02057             m1 = m2; /* while m0 stays the same */
02058          } else {
02059             if (findonly) {
02060                return m1;
02061             }
02062             if (!(m1 = add_pattern_node(con, m1, buf, pattern, already,specif, m0))) { /* m1 is the node just added */
02063                return NULL;
02064             }
02065             m0 = &m1->next_char;
02066          }
02067          if (!(*(s1 + 1))) {
02068             if (m2 && m2->exten) {
02069                ast_log(LOG_WARNING, "Found duplicate exten. Had %s found %s\n", m2->exten->exten, e1->exten);
02070             }
02071             m1->deleted = 0;
02072             m1->exten = e1;
02073          }
02074 
02075          /* The 'already' variable is a mini-optimization designed to make it so that we
02076           * don't have to call already_in_tree when we know it will return false.
02077           */
02078          already = 0;
02079       }
02080       s1++; /* advance to next char */
02081    }
02082    return m1;
02083 }

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

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

Referenced by add_exten_to_pattern_tree().

01903 {
01904    struct match_char *m;
01905    
01906    if (!(m = ast_calloc(1, sizeof(*m) + strlen(pattern)))) {
01907       return NULL;
01908    }
01909 
01910    /* strcpy is safe here since we know its size and have allocated
01911     * just enough space for when we allocated m
01912     */
01913    strcpy(m->x, pattern);
01914 
01915    /* the specificity scores are the same as used in the old
01916       pattern matcher. */
01917    m->is_pattern = is_pattern;
01918    if (specificity == 1 && is_pattern && pattern[0] == 'N')
01919       m->specificity = 0x0832;
01920    else if (specificity == 1 && is_pattern && pattern[0] == 'Z')
01921       m->specificity = 0x0931;
01922    else if (specificity == 1 && is_pattern && pattern[0] == 'X')
01923       m->specificity = 0x0a30;
01924    else if (specificity == 1 && is_pattern && pattern[0] == '.')
01925       m->specificity = 0x18000;
01926    else if (specificity == 1 && is_pattern && pattern[0] == '!')
01927       m->specificity = 0x28000;
01928    else
01929       m->specificity = specificity;
01930 
01931    if (!con->pattern_tree) {
01932       insert_in_next_chars_alt_char_list(&con->pattern_tree, m);
01933    } else {
01934       if (already) { /* switch to the new regime (traversing vs appending)*/
01935          insert_in_next_chars_alt_char_list(nextcharptr, m);
01936       } else {
01937          insert_in_next_chars_alt_char_list(&current->next_char, m);
01938       }
01939    }
01940 
01941    return m;
01942 }

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

References add_pri_lockopt(), and el.

Referenced by ast_add_extension2_lockopt().

07875 {
07876    return add_pri_lockopt(con, tmp, el, e, replace, 1);
07877 }

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

07886 {
07887    struct ast_exten *ep;
07888    struct ast_exten *eh=e;
07889 
07890    for (ep = NULL; e ; ep = e, e = e->peer) {
07891       if (e->priority >= tmp->priority)
07892          break;
07893    }
07894    if (!e) {   /* go at the end, and ep is surely set because the list is not empty */
07895       ast_hashtab_insert_safe(eh->peer_table, tmp);
07896 
07897       if (tmp->label) {
07898          ast_hashtab_insert_safe(eh->peer_label_table, tmp);
07899       }
07900       ep->peer = tmp;
07901       return 0;   /* success */
07902    }
07903    if (e->priority == tmp->priority) {
07904       /* Can't have something exactly the same.  Is this a
07905          replacement?  If so, replace, otherwise, bonk. */
07906       if (!replace) {
07907          ast_log(LOG_WARNING, "Unable to register extension '%s', priority %d in '%s', already in use\n", tmp->exten, tmp->priority, con->name);
07908          if (tmp->datad) {
07909             tmp->datad(tmp->data);
07910             /* if you free this, null it out */
07911             tmp->data = NULL;
07912          }
07913 
07914          ast_free(tmp);
07915          return -1;
07916       }
07917       /* we are replacing e, so copy the link fields and then update
07918        * whoever pointed to e to point to us
07919        */
07920       tmp->next = e->next; /* not meaningful if we are not first in the peer list */
07921       tmp->peer = e->peer; /* always meaningful */
07922       if (ep)  {     /* We're in the peer list, just insert ourselves */
07923          ast_hashtab_remove_object_via_lookup(eh->peer_table,e);
07924 
07925          if (e->label) {
07926             ast_hashtab_remove_object_via_lookup(eh->peer_label_table,e);
07927          }
07928 
07929          ast_hashtab_insert_safe(eh->peer_table,tmp);
07930          if (tmp->label) {
07931             ast_hashtab_insert_safe(eh->peer_label_table,tmp);
07932          }
07933 
07934          ep->peer = tmp;
07935       } else if (el) {     /* We're the first extension. Take over e's functions */
07936          struct match_char *x = add_exten_to_pattern_tree(con, e, 1);
07937          tmp->peer_table = e->peer_table;
07938          tmp->peer_label_table = e->peer_label_table;
07939          ast_hashtab_remove_object_via_lookup(tmp->peer_table,e);
07940          ast_hashtab_insert_safe(tmp->peer_table,tmp);
07941          if (e->label) {
07942             ast_hashtab_remove_object_via_lookup(tmp->peer_label_table, e);
07943          }
07944          if (tmp->label) {
07945             ast_hashtab_insert_safe(tmp->peer_label_table, tmp);
07946          }
07947 
07948          ast_hashtab_remove_object_via_lookup(con->root_table, e);
07949          ast_hashtab_insert_safe(con->root_table, tmp);
07950          el->next = tmp;
07951          /* The pattern trie points to this exten; replace the pointer,
07952             and all will be well */
07953          if (x) { /* if the trie isn't formed yet, don't sweat this */
07954             if (x->exten) { /* this test for safety purposes */
07955                x->exten = tmp; /* replace what would become a bad pointer */
07956             } else {
07957                ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n");
07958             }
07959          }
07960       } else {       /* We're the very first extension.  */
07961          struct match_char *x = add_exten_to_pattern_tree(con, e, 1);
07962          ast_hashtab_remove_object_via_lookup(con->root_table, e);
07963          ast_hashtab_insert_safe(con->root_table, tmp);
07964          tmp->peer_table = e->peer_table;
07965          tmp->peer_label_table = e->peer_label_table;
07966          ast_hashtab_remove_object_via_lookup(tmp->peer_table, e);
07967          ast_hashtab_insert_safe(tmp->peer_table, tmp);
07968          if (e->label) {
07969             ast_hashtab_remove_object_via_lookup(tmp->peer_label_table, e);
07970          }
07971          if (tmp->label) {
07972             ast_hashtab_insert_safe(tmp->peer_label_table, tmp);
07973          }
07974 
07975          ast_hashtab_remove_object_via_lookup(con->root_table, e);
07976          ast_hashtab_insert_safe(con->root_table, tmp);
07977          con->root = tmp;
07978          /* The pattern trie points to this exten; replace the pointer,
07979             and all will be well */
07980          if (x) { /* if the trie isn't formed yet; no problem */
07981             if (x->exten) { /* this test for safety purposes */
07982                x->exten = tmp; /* replace what would become a bad pointer */
07983             } else {
07984                ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n");
07985             }
07986          }
07987       }
07988       if (tmp->priority == PRIORITY_HINT)
07989          ast_change_hint(e,tmp);
07990       /* Destroy the old one */
07991       if (e->datad)
07992          e->datad(e->data);
07993       ast_free(e);
07994    } else { /* Slip ourselves in just before e */
07995       tmp->peer = e;
07996       tmp->next = e->next; /* extension chain, or NULL if e is not the first extension */
07997       if (ep) {         /* Easy enough, we're just in the peer list */
07998          if (tmp->label) {
07999             ast_hashtab_insert_safe(eh->peer_label_table, tmp);
08000          }
08001          ast_hashtab_insert_safe(eh->peer_table, tmp);
08002          ep->peer = tmp;
08003       } else {       /* we are the first in some peer list, so link in the ext list */
08004          tmp->peer_table = e->peer_table;
08005          tmp->peer_label_table = e->peer_label_table;
08006          e->peer_table = 0;
08007          e->peer_label_table = 0;
08008          ast_hashtab_insert_safe(tmp->peer_table, tmp);
08009          if (tmp->label) {
08010             ast_hashtab_insert_safe(tmp->peer_label_table, tmp);
08011          }
08012          ast_hashtab_remove_object_via_lookup(con->root_table, e);
08013          ast_hashtab_insert_safe(con->root_table, tmp);
08014          if (el)
08015             el->next = tmp;   /* in the middle... */
08016          else
08017             con->root = tmp; /* ... or at the head */
08018          e->next = NULL;   /* e is no more at the head, so e->next must be reset */
08019       }
08020       /* And immediately return success. */
08021       if (tmp->priority == PRIORITY_HINT) {
08022          if (lockhints) {
08023             ast_add_hint(tmp);
08024          } else {
08025             ast_add_hint(tmp);
08026          }
08027       }
08028    }
08029    return 0;
08030 }

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

Definition at line 1847 of file pbx.c.

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

Referenced by add_exten_to_pattern_tree().

01848 {
01849    struct match_char *t;
01850 
01851    if (!current) {
01852       return 0;
01853    }
01854 
01855    for (t = current; t; t = t->alt_char) {
01856       if (is_pattern == t->is_pattern && !strcmp(pat, t->x)) {/* uh, we may want to sort exploded [] contents to make matching easy */
01857          return t;
01858       }
01859    }
01860 
01861    return 0;
01862 }

int ast_active_calls ( void   ) 

Retrieve the number of active calls.

Definition at line 5064 of file pbx.c.

References countcalls.

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

05065 {
05066    return countcalls;
05067 }

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

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

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

07739 {
07740    int ret = -1;
07741    struct ast_context *c = find_context_locked(context);
07742 
07743    if (c) {
07744       ret = ast_add_extension2(c, replace, extension, priority, label, callerid,
07745          application, data, datad, registrar);
07746       ast_unlock_contexts();
07747    }
07748 
07749    return ret;
07750 }

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

References ast_add_extension2_lockopt().

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

08061 {
08062    return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid, application, data, datad, registrar, 1, 1);
08063 }

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

References add_exten_to_pattern_tree(), add_pri(), ast_exten::app, ast_add_hint(), ast_calloc, ast_channel_release(), ast_copy_string(), ast_debug, ast_dummy_channel_alloc(), ast_hashtab_create(), ast_hashtab_insert_safe(), ast_hashtab_lookup(), ast_hashtab_newsize_java(), ast_hashtab_resize_java(), ast_log(), ast_strlen_zero(), ast_unlock_context(), ast_verb, ast_wrlock_context(), ast_exten::cidmatch, ast_channel::context, ast_exten::data, ast_exten::datad, el, errno, ext_cmp(), ext_strncpy(), ast_exten::exten, ast_channel::exten, hashtab_compare_exten_labels(), hashtab_compare_exten_numbers(), hashtab_compare_extens(), hashtab_hash_extens(), hashtab_hash_labels(), hashtab_hash_priority(), ast_exten::label, LOG_ERROR, ast_exten::matchcid, ast_context::name, ast_exten::next, option_debug, ast_exten::parent, ast_context::pattern_tree, pbx_substitute_variables_helper(), ast_exten::peer_label_table, ast_exten::peer_table, ast_exten::priority, PRIORITY_HINT, ast_exten::registrar, ast_context::root, ast_context::root_table, ast_exten::stuff, and VAR_BUF_SIZE.

Referenced by ast_add_extension2(), and ast_add_extension_nolock().

08074 {
08075    /*
08076     * Sort extensions (or patterns) according to the rules indicated above.
08077     * These are implemented by the function ext_cmp()).
08078     * All priorities for the same ext/pattern/cid are kept in a list,
08079     * using the 'peer' field  as a link field..
08080     */
08081    struct ast_exten *tmp, *tmp2, *e, *el = NULL;
08082    int res;
08083    int length;
08084    char *p;
08085    char expand_buf[VAR_BUF_SIZE];
08086    struct ast_exten dummy_exten = {0};
08087    char dummy_name[1024];
08088 
08089    if (ast_strlen_zero(extension)) {
08090       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",
08091             con->name);
08092       return -1;
08093    }
08094 
08095    /* If we are adding a hint evalulate in variables and global variables */
08096    if (priority == PRIORITY_HINT && strstr(application, "${") && !strstr(extension, "_")) {
08097       struct ast_channel *c = ast_dummy_channel_alloc();
08098       ast_copy_string(c->exten, extension, sizeof(c->exten));
08099       ast_copy_string(c->context, con->name, sizeof(c->context));
08100 
08101       pbx_substitute_variables_helper(c, application, expand_buf, sizeof(expand_buf));
08102       application = expand_buf;
08103       ast_channel_release(c);
08104    }
08105 
08106    length = sizeof(struct ast_exten);
08107    length += strlen(extension) + 1;
08108    length += strlen(application) + 1;
08109    if (label)
08110       length += strlen(label) + 1;
08111    if (callerid)
08112       length += strlen(callerid) + 1;
08113    else
08114       length ++;  /* just the '\0' */
08115 
08116    /* Be optimistic:  Build the extension structure first */
08117    if (!(tmp = ast_calloc(1, length)))
08118       return -1;
08119 
08120    if (ast_strlen_zero(label)) /* let's turn empty labels to a null ptr */
08121       label = 0;
08122 
08123    /* use p as dst in assignments, as the fields are const char * */
08124    p = tmp->stuff;
08125    if (label) {
08126       tmp->label = p;
08127       strcpy(p, label);
08128       p += strlen(label) + 1;
08129    }
08130    tmp->exten = p;
08131    p += ext_strncpy(p, extension, strlen(extension) + 1) + 1;
08132    tmp->priority = priority;
08133    tmp->cidmatch = p;   /* but use p for assignments below */
08134 
08135    /* Blank callerid and NULL callerid are two SEPARATE things.  Do NOT confuse the two!!! */
08136    if (callerid) {
08137       p += ext_strncpy(p, callerid, strlen(callerid) + 1) + 1;
08138       tmp->matchcid = 1;
08139    } else {
08140       *p++ = '\0';
08141       tmp->matchcid = 0;
08142    }
08143    tmp->app = p;
08144    strcpy(p, application);
08145    tmp->parent = con;
08146    tmp->data = data;
08147    tmp->datad = datad;
08148    tmp->registrar = registrar;
08149 
08150    if (lockconts) {
08151       ast_wrlock_context(con);
08152    }
08153 
08154    if (con->pattern_tree) { /* usually, on initial load, the pattern_tree isn't formed until the first find_exten; so if we are adding
08155                         an extension, and the trie exists, then we need to incrementally add this pattern to it. */
08156       ast_copy_string(dummy_name, extension, sizeof(dummy_name));
08157       dummy_exten.exten = dummy_name;
08158       dummy_exten.matchcid = 0;
08159       dummy_exten.cidmatch = 0;
08160       tmp2 = ast_hashtab_lookup(con->root_table, &dummy_exten);
08161       if (!tmp2) {
08162          /* hmmm, not in the trie; */
08163          add_exten_to_pattern_tree(con, tmp, 0);
08164          ast_hashtab_insert_safe(con->root_table, tmp); /* for the sake of completeness */
08165       }
08166    }
08167    res = 0; /* some compilers will think it is uninitialized otherwise */
08168    for (e = con->root; e; el = e, e = e->next) {   /* scan the extension list */
08169       res = ext_cmp(e->exten, tmp->exten);
08170       if (res == 0) { /* extension match, now look at cidmatch */
08171          if (!e->matchcid && !tmp->matchcid)
08172             res = 0;
08173          else if (tmp->matchcid && !e->matchcid)
08174             res = 1;
08175          else if (e->matchcid && !tmp->matchcid)
08176             res = -1;
08177          else
08178             res = ext_cmp(e->cidmatch, tmp->cidmatch);
08179       }
08180       if (res >= 0)
08181          break;
08182    }
08183    if (e && res == 0) { /* exact match, insert in the pri chain */
08184       res = add_pri(con, tmp, el, e, replace);
08185       if (lockconts) {
08186          ast_unlock_context(con);
08187       }
08188       if (res < 0) {
08189          errno = EEXIST;   /* XXX do we care ? */
08190          return 0; /* XXX should we return -1 maybe ? */
08191       }
08192    } else {
08193       /*
08194        * not an exact match, this is the first entry with this pattern,
08195        * so insert in the main list right before 'e' (if any)
08196        */
08197       tmp->next = e;
08198       if (el) {  /* there is another exten already in this context */
08199          el->next = tmp;
08200          tmp->peer_table = ast_hashtab_create(13,
08201                      hashtab_compare_exten_numbers,
08202                      ast_hashtab_resize_java,
08203                      ast_hashtab_newsize_java,
08204                      hashtab_hash_priority,
08205                      0);
08206          tmp->peer_label_table = ast_hashtab_create(7,
08207                         hashtab_compare_exten_labels,
08208                         ast_hashtab_resize_java,
08209                         ast_hashtab_newsize_java,
08210                         hashtab_hash_labels,
08211                         0);
08212          if (label) {
08213             ast_hashtab_insert_safe(tmp->peer_label_table, tmp);
08214          }
08215          ast_hashtab_insert_safe(tmp->peer_table, tmp);
08216       } else {  /* this is the first exten in this context */
08217          if (!con->root_table)
08218             con->root_table = ast_hashtab_create(27,
08219                                        hashtab_compare_extens,
08220                                        ast_hashtab_resize_java,
08221                                        ast_hashtab_newsize_java,
08222                                        hashtab_hash_extens,
08223                                        0);
08224          con->root = tmp;
08225          con->root->peer_table = ast_hashtab_create(13,
08226                         hashtab_compare_exten_numbers,
08227                         ast_hashtab_resize_java,
08228                         ast_hashtab_newsize_java,
08229                         hashtab_hash_priority,
08230                         0);
08231          con->root->peer_label_table = ast_hashtab_create(7,
08232                            hashtab_compare_exten_labels,
08233                            ast_hashtab_resize_java,
08234                            ast_hashtab_newsize_java,
08235                            hashtab_hash_labels,
08236                            0);
08237          if (label) {
08238             ast_hashtab_insert_safe(con->root->peer_label_table, tmp);
08239          }
08240          ast_hashtab_insert_safe(con->root->peer_table, tmp);
08241 
08242       }
08243       ast_hashtab_insert_safe(con->root_table, tmp);
08244       if (lockconts) {
08245          ast_unlock_context(con);
08246       }
08247       if (tmp->priority == PRIORITY_HINT) {
08248          if (lockhints) {
08249             ast_add_hint(tmp);
08250          } else {
08251             ast_add_hint(tmp);
08252          }
08253       }
08254    }
08255    if (option_debug) {
08256       if (tmp->matchcid) {
08257          ast_debug(1, "Added extension '%s' priority %d (CID match '%s') to %s (%p)\n",
08258                  tmp->exten, tmp->priority, tmp->cidmatch, con->name, con);
08259       } else {
08260          ast_debug(1, "Added extension '%s' priority %d to %s (%p)\n",
08261                  tmp->exten, tmp->priority, con->name, con);
08262       }
08263    }
08264 
08265    if (tmp->matchcid) {
08266       ast_verb(3, "Added extension '%s' priority %d (CID match '%s') to %s\n",
08267              tmp->exten, tmp->priority, tmp->cidmatch, con->name);
08268    } else {
08269       ast_verb(3, "Added extension '%s' priority %d to %s\n",
08270              tmp->exten, tmp->priority, con->name);
08271    }
08272 
08273    return 0;
08274 }

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

References ast_add_extension2_lockopt(), and find_context().

Referenced by ast_merge_contexts_and_delete().

07720 {
07721    int ret = -1;
07722    struct ast_context *c = find_context(context);
07723 
07724    if (c) {
07725       ret = ast_add_extension2_lockopt(c, replace, extension, priority, label, callerid,
07726          application, data, datad, registrar, 0, 0);
07727    }
07728 
07729    return ret;
07730 }

static int ast_add_hint ( struct ast_exten e  )  [static]

Add hint to hint list, check initial extension state.

Definition at line 4453 of file pbx.c.

References ao2_alloc, ao2_find, ao2_link, ao2_ref, ast_debug, ast_extension_state2(), ast_get_extension_app(), ast_get_extension_name(), and hints.

Referenced by ast_add_extension2_lockopt().

04454 {
04455    struct ast_hint *hint;
04456 
04457    if (!e) {
04458       return -1;
04459    }
04460 
04461    /* Search if hint exists, do nothing */   
04462    hint = ao2_find(hints, e, 0);
04463    if (hint) {
04464       ast_debug(2, "HINTS: Not re-adding existing hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e));
04465       ao2_ref(hint, -1);
04466       return -1;
04467    }
04468 
04469    ast_debug(2, "HINTS: Adding hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e));
04470 
04471    if (!(hint = ao2_alloc(sizeof(*hint), NULL))) {
04472       return -1;
04473    }
04474 
04475    /* Initialize and insert new item at the top */
04476    hint->exten = e;
04477    hint->laststate = ast_extension_state2(e);
04478 
04479    ao2_link(hints, hint);
04480 
04481    ao2_ref(hint, -1);
04482 
04483    return 0;
04484 }

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

Set the channel to next execute the specified dialplan location.

See also:
ast_async_parseable_goto, ast_async_goto_if_exists

Definition at line 7775 of file pbx.c.

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

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

07776 {
07777    int res = 0;
07778 
07779    ast_channel_lock(chan);
07780 
07781    if (chan->pbx) { /* This channel is currently in the PBX */
07782       ast_explicit_goto(chan, context, exten, priority + 1);
07783       ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO);
07784    } else {
07785       /* In order to do it when the channel doesn't really exist within
07786          the PBX, we have to make a new channel, masquerade, and start the PBX
07787          at the new location */
07788       struct ast_channel *tmpchan = ast_channel_alloc(0, chan->_state, 0, 0, chan->accountcode, chan->exten, chan->context, chan->linkedid, chan->amaflags, "AsyncGoto/%s", chan->name);
07789       if (!tmpchan) {
07790          res = -1;
07791       } else {
07792          if (chan->cdr) {
07793             ast_cdr_discard(tmpchan->cdr);
07794             tmpchan->cdr = ast_cdr_dup(chan->cdr);  /* share the love */
07795          }
07796          /* Make formats okay */
07797          tmpchan->readformat = chan->readformat;
07798          tmpchan->writeformat = chan->writeformat;
07799          /* Setup proper location */
07800          ast_explicit_goto(tmpchan,
07801             S_OR(context, chan->context), S_OR(exten, chan->exten), priority);
07802 
07803          /* Masquerade into temp channel */
07804          if (ast_channel_masquerade(tmpchan, chan)) {
07805             /* Failed to set up the masquerade.  It's probably chan_local
07806              * in the middle of optimizing itself out.  Sad. :( */
07807             ast_hangup(tmpchan);
07808             tmpchan = NULL;
07809             res = -1;
07810          } else {
07811             /* it may appear odd to unlock chan here since the masquerade is on
07812              * tmpchan, but no channel locks should be held when doing a masquerade
07813              * since a masquerade requires a lock on the channels ao2 container. */
07814             ast_channel_unlock(chan);
07815             ast_do_masquerade(tmpchan);
07816             ast_channel_lock(chan);
07817             /* Start the PBX going on our stolen channel */
07818             if (ast_pbx_start(tmpchan)) {
07819                ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name);
07820                ast_hangup(tmpchan);
07821                res = -1;
07822             }
07823          }
07824       }
07825    }
07826    ast_channel_unlock(chan);
07827    return res;
07828 }

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

Set the channel to next execute the specified dialplan location.

Definition at line 7830 of file pbx.c.

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

07831 {
07832    struct ast_channel *chan;
07833    int res = -1;
07834 
07835    if ((chan = ast_channel_get_by_name(channame))) {
07836       res = ast_async_goto(chan, context, exten, priority);
07837       chan = ast_channel_unref(chan);
07838    }
07839 
07840    return res;
07841 }

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

References __ast_goto_if_exists().

10134 {
10135    return __ast_goto_if_exists(chan, context, exten, priority, 1);
10136 }

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

References pbx_parseable_goto().

Referenced by asyncgoto_exec(), and handle_redirect().

10199 {
10200    return pbx_parseable_goto(chan, goto_string, 1);
10201 }

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

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

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

Definition at line 7366 of file pbx.c.

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

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

07367 {
07368    char *info_save, *info;
07369    int j, num_fields, last_sep = -1;
07370 
07371    /* Check for empty just in case */
07372    if (ast_strlen_zero(info_in)) {
07373       return 0;
07374    }
07375 
07376    /* make a copy just in case we were passed a static string */
07377    info_save = info = ast_strdupa(info_in);
07378 
07379    /* count the number of fields in the timespec */
07380    for (j = 0, num_fields = 1; info[j] != '\0'; j++) {
07381       if (info[j] == ',') {
07382          last_sep = j;
07383          num_fields++;
07384       }
07385    }
07386 
07387    /* save the timezone, if it is specified */
07388    if (num_fields == 5) {
07389       i->timezone = ast_strdup(info + last_sep + 1);
07390    } else {
07391       i->timezone = NULL;
07392    }
07393 
07394    /* Assume everything except time */
07395    i->monthmask = 0xfff;   /* 12 bits */
07396    i->daymask = 0x7fffffffU; /* 31 bits */
07397    i->dowmask = 0x7f; /* 7 bits */
07398    /* on each call, use strsep() to move info to the next argument */
07399    get_timerange(i, strsep(&info, "|,"));
07400    if (info)
07401       i->dowmask = get_range(strsep(&info, "|,"), 7, days, "day of week");
07402    if (info)
07403       i->daymask = get_range(strsep(&info, "|,"), 31, NULL, "day");
07404    if (info)
07405       i->monthmask = get_range(strsep(&info, "|,"), 12, months, "month");
07406    return 1;
07407 }

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

References E_CANMATCH, and pbx_extension_helper().

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

04594 {
04595    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0);
04596 }

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

Change hint for an extension.

Definition at line 4487 of file pbx.c.

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

04488 {
04489    struct ast_hint *hint;
04490 
04491    hint = ao2_find(hints, oe, 0);
04492 
04493    if (!hint) {
04494       return -1;
04495    }
04496 
04497    ao2_lock(hint);
04498    hint->exten = ne;
04499    ao2_unlock(hint);
04500    ao2_ref(hint, -1);
04501 
04502    return 0;
04503 }

int ast_check_timing ( const struct ast_timing i  ) 

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

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

Definition at line 7409 of file pbx.c.

References ast_check_timing2(), and ast_tvnow().

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

07410 {
07411    return ast_check_timing2(i, ast_tvnow());
07412 }

int ast_check_timing2 ( const struct ast_timing i,
const struct timeval  tv 
)

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

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

Definition at line 7414 of file pbx.c.

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

Referenced by ast_check_timing(), and pbx_builtin_gotoiftime().

07415 {
07416    struct ast_tm tm;
07417 
07418    ast_localtime(&tv, &tm, i->timezone);
07419 
07420    /* If it's not the right month, return */
07421    if (!(i->monthmask & (1 << tm.tm_mon)))
07422       return 0;
07423 
07424    /* If it's not that time of the month.... */
07425    /* Warning, tm_mday has range 1..31! */
07426    if (!(i->daymask & (1 << (tm.tm_mday-1))))
07427       return 0;
07428 
07429    /* If it's not the right day of the week */
07430    if (!(i->dowmask & (1 << tm.tm_wday)))
07431       return 0;
07432 
07433    /* Sanity check the hour just to be safe */
07434    if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) {
07435       ast_log(LOG_WARNING, "Insane time...\n");
07436       return 0;
07437    }
07438 
07439    /* Now the tough part, we calculate if it fits
07440       in the right time based on min/hour */
07441    if (!(i->minmask[tm.tm_hour * 2 + (tm.tm_min >= 30 ? 1 : 0)] & (1 << (tm.tm_min >= 30 ? tm.tm_min - 30 : tm.tm_min))))
07442       return 0;
07443 
07444    /* If we got this far, then we're good */
07445    return 1;
07446 }

char* ast_complete_applications ( const char *  line,
const char *  word,
int  state 
)

Command completion for the list of installed applications.

This can be called from a CLI command completion function that wants to complete from the list of available applications.

Definition at line 10203 of file pbx.c.

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

Referenced by handle_orig(), and handle_show_application().

10204 {
10205    struct ast_app *app = NULL;
10206    int which = 0;
10207    char *ret = NULL;
10208    size_t wordlen = strlen(word);
10209 
10210    AST_RWLIST_RDLOCK(&apps);
10211    AST_RWLIST_TRAVERSE(&apps, app, list) {
10212       if (!strncasecmp(word, app->name, wordlen) && ++which > state) {
10213          ret = ast_strdup(app->name);
10214          break;
10215       }
10216    }
10217    AST_RWLIST_UNLOCK(&apps);
10218 
10219    return ret;
10220 }

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

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

Referenced by handle_cli_dialplan_add_ignorepat().

07649 {
07650    int ret = -1;
07651    struct ast_context *c = find_context_locked(context);
07652 
07653    if (c) {
07654       ret = ast_context_add_ignorepat2(c, value, registrar);
07655       ast_unlock_contexts();
07656    }
07657    return ret;
07658 }

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

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

07661 {
07662    struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL;
07663    int length;
07664    char *pattern;
07665    length = sizeof(struct ast_ignorepat);
07666    length += strlen(value) + 1;
07667    if (!(ignorepat = ast_calloc(1, length)))
07668       return -1;
07669    /* The cast to char * is because we need to write the initial value.
07670     * The field is not supposed to be modified otherwise.  Also, gcc 4.2
07671     * sees the cast as dereferencing a type-punned pointer and warns about
07672     * it.  This is the workaround (we're telling gcc, yes, that's really
07673     * what we wanted to do).
07674     */
07675    pattern = (char *) ignorepat->pattern;
07676    strcpy(pattern, value);
07677    ignorepat->next = NULL;
07678    ignorepat->registrar = registrar;
07679    ast_wrlock_context(con);
07680    for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) {
07681       ignorepatl = ignorepatc;
07682       if (!strcasecmp(ignorepatc->pattern, value)) {
07683          /* Already there */
07684          ast_unlock_context(con);
07685          errno = EEXIST;
07686          return -1;
07687       }
07688    }
07689    if (ignorepatl)
07690       ignorepatl->next = ignorepat;
07691    else
07692       con->ignorepats = ignorepat;
07693    ast_unlock_context(con);
07694    return 0;
07695 
07696 }

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

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

Referenced by handle_cli_dialplan_add_include().

07196 {
07197    int ret = -1;
07198    struct ast_context *c = find_context_locked(context);
07199 
07200    if (c) {
07201       ret = ast_context_add_include2(c, include, registrar);
07202       ast_unlock_contexts();
07203    }
07204    return ret;
07205 }

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

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

Referenced by ast_context_add_include(), and context_merge_incls_swits_igps_other_registrars().

07465 {
07466    struct ast_include *new_include;
07467    char *c;
07468    struct ast_include *i, *il = NULL; /* include, include_last */
07469    int length;
07470    char *p;
07471 
07472    length = sizeof(struct ast_include);
07473    length += 2 * (strlen(value) + 1);
07474 
07475    /* allocate new include structure ... */
07476    if (!(new_include = ast_calloc(1, length)))
07477       return -1;
07478    /* Fill in this structure. Use 'p' for assignments, as the fields
07479     * in the structure are 'const char *'
07480     */
07481    p = new_include->stuff;
07482    new_include->name = p;
07483    strcpy(p, value);
07484    p += strlen(value) + 1;
07485    new_include->rname = p;
07486    strcpy(p, value);
07487    /* Strip off timing info, and process if it is there */
07488    if ( (c = strchr(p, ',')) ) {
07489       *c++ = '\0';
07490       new_include->hastime = ast_build_timing(&(new_include->timing), c);
07491    }
07492    new_include->next      = NULL;
07493    new_include->registrar = registrar;
07494 
07495    ast_wrlock_context(con);
07496 
07497    /* ... go to last include and check if context is already included too... */
07498    for (i = con->includes; i; i = i->next) {
07499       if (!strcasecmp(i->name, new_include->name)) {
07500          ast_destroy_timing(&(new_include->timing));
07501          ast_free(new_include);
07502          ast_unlock_context(con);
07503          errno = EEXIST;
07504          return -1;
07505       }
07506       il = i;
07507    }
07508 
07509    /* ... include new context into context list, unlock, return */
07510    if (il)
07511       il->next = new_include;
07512    else
07513       con->includes = new_include;
07514    ast_verb(3, "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con));
07515 
07516    ast_unlock_context(con);
07517 
07518    return 0;
07519 }

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

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

07527 {
07528    int ret = -1;
07529    struct ast_context *c = find_context_locked(context);
07530 
07531    if (c) { /* found, add switch to this context */
07532       ret = ast_context_add_switch2(c, sw, data, eval, registrar);
07533       ast_unlock_contexts();
07534    }
07535    return ret;
07536 }

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

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

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

07547 {
07548    struct ast_sw *new_sw;
07549    struct ast_sw *i;
07550    int length;
07551    char *p;
07552 
07553    length = sizeof(struct ast_sw);
07554    length += strlen(value) + 1;
07555    if (data)
07556       length += strlen(data);
07557    length++;
07558 
07559    /* allocate new sw structure ... */
07560    if (!(new_sw = ast_calloc(1, length)))
07561       return -1;
07562    /* ... fill in this structure ... */
07563    p = new_sw->stuff;
07564    new_sw->name = p;
07565    strcpy(new_sw->name, value);
07566    p += strlen(value) + 1;
07567    new_sw->data = p;
07568    if (data) {
07569       strcpy(new_sw->data, data);
07570       p += strlen(data) + 1;
07571    } else {
07572       strcpy(new_sw->data, "");
07573       p++;
07574    }
07575    new_sw->eval     = eval;
07576    new_sw->registrar = registrar;
07577 
07578    /* ... try to lock this context ... */
07579    ast_wrlock_context(con);
07580 
07581    /* ... go to last sw and check if context is already swd too... */
07582    AST_LIST_TRAVERSE(&con->alts, i, list) {
07583       if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) {
07584          ast_free(new_sw);
07585          ast_unlock_context(con);
07586          errno = EEXIST;
07587          return -1;
07588       }
07589    }
07590 
07591    /* ... sw new context into context list, unlock, return */
07592    AST_LIST_INSERT_TAIL(&con->alts, new_sw, list);
07593 
07594    ast_verb(3, "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con));
07595 
07596    ast_unlock_context(con);
07597 
07598    return 0;
07599 }

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

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

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

02513 {
02514    struct ast_context *tmp = NULL;
02515    struct fake_context item;
02516 
02517    ast_copy_string(item.name, name, sizeof(item.name));
02518 
02519    ast_rdlock_contexts();
02520    if( contexts_table ) {
02521       tmp = ast_hashtab_lookup(contexts_table,&item);
02522    } else {
02523       while ( (tmp = ast_walk_contexts(tmp)) ) {
02524          if (!name || !strcasecmp(name, tmp->name)) {
02525             break;
02526          }
02527       }
02528    }
02529    ast_unlock_contexts();
02530    return tmp;
02531 }

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

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

Referenced by build_parkinglot(), config_parse_variables(), context_merge(), load_module(), lua_register_switches(), manage_parkinglot(), park_call_full(), pbx_load_config(), pbx_load_users(), and set_config().

06849 {
06850    struct ast_context *tmp, **local_contexts;
06851    struct fake_context search;
06852    int length = sizeof(struct ast_context) + strlen(name) + 1;
06853 
06854    if (!contexts_table) {
06855       contexts_table = ast_hashtab_create(17,
06856                                  ast_hashtab_compare_contexts,
06857                                  ast_hashtab_resize_java,
06858                                  ast_hashtab_newsize_java,
06859                                  ast_hashtab_hash_contexts,
06860                                  0);
06861    }
06862 
06863    ast_copy_string(search.name, name, sizeof(search.name));
06864    if (!extcontexts) {
06865       ast_rdlock_contexts();
06866       local_contexts = &contexts;
06867       tmp = ast_hashtab_lookup(contexts_table, &search);
06868       ast_unlock_contexts();
06869       if (tmp) {
06870          tmp->refcount++;
06871          return tmp;
06872       }
06873    } else { /* local contexts just in a linked list; search there for the new context; slow, linear search, but not frequent */
06874       local_contexts = extcontexts;
06875       tmp = ast_hashtab_lookup(exttable, &search);
06876       if (tmp) {
06877          tmp->refcount++;
06878          return tmp;
06879       }
06880    }
06881 
06882    if ((tmp = ast_calloc(1, length))) {
06883       ast_rwlock_init(&tmp->lock);
06884       ast_mutex_init(&tmp->macrolock);
06885       strcpy(tmp->name, name);
06886       tmp->root = NULL;
06887       tmp->root_table = NULL;
06888       tmp->registrar = ast_strdup(registrar);
06889       tmp->includes = NULL;
06890       tmp->ignorepats = NULL;
06891       tmp->refcount = 1;
06892    } else {
06893       ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name);
06894       return NULL;
06895    }
06896 
06897    if (!extcontexts) {
06898       ast_wrlock_contexts();
06899       tmp->next = *local_contexts;
06900       *local_contexts = tmp;
06901       ast_hashtab_insert_safe(contexts_table, tmp); /*put this context into the tree */
06902       ast_unlock_contexts();
06903       ast_debug(1, "Registered context '%s'(%p) in table %p registrar: %s\n", tmp->name, tmp, contexts_table, registrar);
06904       ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar);
06905    } else {
06906       tmp->next = *local_contexts;
06907       if (exttable)
06908          ast_hashtab_insert_immediate(exttable, tmp); /*put this context into the tree */
06909 
06910       *local_contexts = tmp;
06911       ast_debug(1, "Registered context '%s'(%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar);
06912       ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar);
06913    }
06914    return tmp;
06915 }

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

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

Referenced by _macro_exec().

05445 {
05446    struct ast_context *c = NULL;
05447    int ret = -1;
05448    struct fake_context item;
05449 
05450    ast_rdlock_contexts();
05451 
05452    ast_copy_string(item.name, context, sizeof(item.name));
05453 
05454    c = ast_hashtab_lookup(contexts_table,&item);
05455    if (c)
05456       ret = 0;
05457    ast_unlock_contexts();
05458 
05459    /* if we found context, lock macrolock */
05460    if (ret == 0) {
05461       ret = ast_mutex_lock(&c->macrolock);
05462    }
05463 
05464    return ret;
05465 }

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

References ast_context_remove_extension_callerid().

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

05253 {
05254    return ast_context_remove_extension_callerid(context, extension, priority, NULL, 0, registrar);
05255 }

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

References ast_context_remove_extension_callerid2().

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

05280 {
05281    return ast_context_remove_extension_callerid2(con, extension, priority, NULL, 0, registrar, already_locked);
05282 }

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

05258 {
05259    int ret = -1; /* default error return */
05260    struct ast_context *c = find_context_locked(context);
05261 
05262    if (c) { /* ... remove extension ... */
05263       ret = ast_context_remove_extension_callerid2(c, extension, priority, callerid, matchcallerid, registrar, 1);
05264       ast_unlock_contexts();
05265    }
05266    return ret;
05267 }

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

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

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

05285 {
05286    struct ast_exten *exten, *prev_exten = NULL;
05287    struct ast_exten *peer;
05288    struct ast_exten ex, *exten2, *exten3;
05289    char dummy_name[1024];
05290    struct ast_exten *previous_peer = NULL;
05291    struct ast_exten *next_peer = NULL;
05292    int found = 0;
05293 
05294    if (!already_locked)
05295       ast_wrlock_context(con);
05296 
05297    /* Handle this is in the new world */
05298 
05299    /* FIXME For backwards compatibility, if callerid==NULL, then remove ALL
05300     * peers, not just those matching the callerid. */
05301 #ifdef NEED_DEBUG
05302    ast_verb(3,"Removing %s/%s/%d%s%s from trees, registrar=%s\n", con->name, extension, priority, matchcallerid ? "/" : "", matchcallerid ? callerid : "", registrar);
05303 #endif
05304 #ifdef CONTEXT_DEBUG
05305    check_contexts(__FILE__, __LINE__);
05306 #endif
05307    /* find this particular extension */
05308    ex.exten = dummy_name;
05309    ex.matchcid = matchcallerid && !ast_strlen_zero(callerid); /* don't say match if there's no callerid */
05310    ex.cidmatch = callerid;
05311    ast_copy_string(dummy_name, extension, sizeof(dummy_name));
05312    exten = ast_hashtab_lookup(con->root_table, &ex);
05313    if (exten) {
05314       if (priority == 0) {
05315          exten2 = ast_hashtab_remove_this_object(con->root_table, exten);
05316          if (!exten2)
05317             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);
05318          if (con->pattern_tree) {
05319             struct match_char *x = add_exten_to_pattern_tree(con, exten, 1);
05320 
05321             if (x->exten) { /* this test for safety purposes */
05322                x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */
05323                x->exten = 0; /* get rid of what will become a bad pointer */
05324             } else {
05325                ast_log(LOG_WARNING,"Trying to delete an exten from a context, but the pattern tree node returned isn't a full extension\n");
05326             }
05327          }
05328       } else {
05329          ex.priority = priority;
05330          exten2 = ast_hashtab_lookup(exten->peer_table, &ex);
05331          if (exten2) {
05332 
05333             if (exten2->label) { /* if this exten has a label, remove that, too */
05334                exten3 = ast_hashtab_remove_this_object(exten->peer_label_table,exten2);
05335                if (!exten3)
05336                   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);
05337             }
05338 
05339             exten3 = ast_hashtab_remove_this_object(exten->peer_table, exten2);
05340             if (!exten3)
05341                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);
05342             if (exten2 == exten && exten2->peer) {
05343                exten2 = ast_hashtab_remove_this_object(con->root_table, exten);
05344                ast_hashtab_insert_immediate(con->root_table, exten2->peer);
05345             }
05346             if (ast_hashtab_size(exten->peer_table) == 0) {
05347                /* well, if the last priority of an exten is to be removed,
05348                   then, the extension is removed, too! */
05349                exten3 = ast_hashtab_remove_this_object(con->root_table, exten);
05350                if (!exten3)
05351                   ast_log(LOG_ERROR,"Did not remove this exten (%s) from the context root_table (%s) (priority %d)\n", exten->exten, con->name, priority);
05352                if (con->pattern_tree) {
05353                   struct match_char *x = add_exten_to_pattern_tree(con, exten, 1);
05354                   if (x->exten) { /* this test for safety purposes */
05355                      x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */
05356                      x->exten = 0; /* get rid of what will become a bad pointer */
05357                   }
05358                }
05359             }
05360          } else {
05361             ast_log(LOG_ERROR,"Could not find priority %d of exten %s in context %s!\n",
05362                   priority, exten->exten, con->name);
05363          }
05364       }
05365    } else {
05366       /* hmmm? this exten is not in this pattern tree? */
05367       ast_log(LOG_WARNING,"Cannot find extension %s in root_table in context %s\n",
05368             extension, con->name);
05369    }
05370 #ifdef NEED_DEBUG
05371    if (con->pattern_tree) {
05372       ast_log(LOG_NOTICE,"match char tree after exten removal:\n");
05373       log_match_char_tree(con->pattern_tree, " ");
05374    }
05375 #endif
05376 
05377    /* scan the extension list to find first matching extension-registrar */
05378    for (exten = con->root; exten; prev_exten = exten, exten = exten->next) {
05379       if (!strcmp(exten->exten, extension) &&
05380          (!registrar || !strcmp(exten->registrar, registrar)) &&
05381          (!matchcallerid || (!ast_strlen_zero(callerid) && !ast_strlen_zero(exten->cidmatch) && !strcmp(exten->cidmatch, callerid)) || (ast_strlen_zero(callerid) && ast_strlen_zero(exten->cidmatch))))
05382          break;
05383    }
05384    if (!exten) {
05385       /* we can't find right extension */
05386       if (!already_locked)
05387          ast_unlock_context(con);
05388       return -1;
05389    }
05390 
05391    /* scan the priority list to remove extension with exten->priority == priority */
05392    for (peer = exten, next_peer = exten->peer ? exten->peer : exten->next;
05393        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)));
05394          peer = next_peer, next_peer = next_peer ? (next_peer->peer ? next_peer->peer : next_peer->next) : NULL) {
05395       if ((priority == 0 || peer->priority == priority) &&
05396             (!callerid || !matchcallerid || (matchcallerid && !strcmp(peer->cidmatch, callerid))) &&
05397             (!registrar || !strcmp(peer->registrar, registrar) )) {
05398          found = 1;
05399 
05400          /* we are first priority extension? */
05401          if (!previous_peer) {
05402             /*
05403              * We are first in the priority chain, so must update the extension chain.
05404              * The next node is either the next priority or the next extension
05405              */
05406             struct ast_exten *next_node = peer->peer ? peer->peer : peer->next;
05407             if (peer->peer) {
05408                /* move the peer_table and peer_label_table down to the next peer, if
05409                   it is there */
05410                peer->peer->peer_table = peer->peer_table;
05411                peer->peer->peer_label_table = peer->peer_label_table;
05412                peer->peer_table = NULL;
05413                peer->peer_label_table = NULL;
05414             }
05415             if (!prev_exten) {   /* change the root... */
05416                con->root = next_node;
05417             } else {
05418                prev_exten->next = next_node; /* unlink */
05419             }
05420             if (peer->peer)   { /* update the new head of the pri list */
05421                peer->peer->next = peer->next;
05422             }
05423          } else { /* easy, we are not first priority in extension */
05424             previous_peer->peer = peer->peer;
05425          }
05426 
05427          /* now, free whole priority extension */
05428          destroy_exten(peer);
05429       } else {
05430          previous_peer = peer;
05431       }
05432    }
05433    if (!already_locked)
05434       ast_unlock_context(con);
05435    return found ? 0 : -1;
05436 }

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

Definition at line 7605 of file pbx.c.

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

Referenced by handle_cli_dialplan_remove_ignorepat().

07606 {
07607    int ret = -1;
07608    struct ast_context *c = find_context_locked(context);
07609 
07610    if (c) {
07611       ret = ast_context_remove_ignorepat2(c, ignorepat, registrar);
07612       ast_unlock_contexts();
07613    }
07614    return ret;
07615 }

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

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

07618 {
07619    struct ast_ignorepat *ip, *ipl = NULL;
07620 
07621    ast_wrlock_context(con);
07622 
07623    for (ip = con->ignorepats; ip; ip = ip->next) {
07624       if (!strcmp(ip->pattern, ignorepat) &&
07625          (!registrar || (registrar == ip->registrar))) {
07626          if (ipl) {
07627             ipl->next = ip->next;
07628             ast_free(ip);
07629          } else {
07630             con->ignorepats = ip->next;
07631             ast_free(ip);
07632          }
07633          ast_unlock_context(con);
07634          return 0;
07635       }
07636       ipl = ip;
07637    }
07638 
07639    ast_unlock_context(con);
07640    errno = EINVAL;
07641    return -1;
07642 }

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

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

Referenced by handle_cli_dialplan_remove_include().

05144 {
05145    int ret = -1;
05146    struct ast_context *c = find_context_locked(context);
05147 
05148    if (c) {
05149       /* found, remove include from this context ... */
05150       ret = ast_context_remove_include2(c, include, registrar);
05151       ast_unlock_contexts();
05152    }
05153    return ret;
05154 }

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

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

Referenced by ast_context_remove_include().

05166 {
05167    struct ast_include *i, *pi = NULL;
05168    int ret = -1;
05169 
05170    ast_wrlock_context(con);
05171 
05172    /* find our include */
05173    for (i = con->includes; i; pi = i, i = i->next) {
05174       if (!strcmp(i->name, include) &&
05175             (!registrar || !strcmp(i->registrar, registrar))) {
05176          /* remove from list */
05177          ast_verb(3, "Removing inclusion of context '%s' in context '%s; registrar=%s'\n", include, ast_get_context_name(con), registrar);
05178          if (pi)
05179             pi->next = i->next;
05180          else
05181             con->includes = i->next;
05182          /* free include and return */
05183          ast_destroy_timing(&(i->timing));
05184          ast_free(i);
05185          ret = 0;
05186          break;
05187       }
05188    }
05189 
05190    ast_unlock_context(con);
05191 
05192    return ret;
05193 }

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

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

05201 {
05202    int ret = -1; /* default error return */
05203    struct ast_context *c = find_context_locked(context);
05204 
05205    if (c) {
05206       /* remove switch from this context ... */
05207       ret = ast_context_remove_switch2(c, sw, data, registrar);
05208       ast_unlock_contexts();
05209    }
05210    return ret;
05211 }

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

05222 {
05223    struct ast_sw *i;
05224    int ret = -1;
05225 
05226    ast_wrlock_context(con);
05227 
05228    /* walk switches */
05229    AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) {
05230       if (!strcmp(i->name, sw) && !strcmp(i->data, data) &&
05231          (!registrar || !strcmp(i->registrar, registrar))) {
05232          /* found, remove from list */
05233          ast_verb(3, "Removing switch '%s' from context '%s; registrar=%s'\n", sw, ast_get_context_name(con), registrar);
05234          AST_LIST_REMOVE_CURRENT(list);
05235          ast_free(i); /* free switch and return */
05236          ret = 0;
05237          break;
05238       }
05239    }
05240    AST_LIST_TRAVERSE_SAFE_END;
05241 
05242    ast_unlock_context(con);
05243 
05244    return ret;
05245 }

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

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

Referenced by _macro_exec().

05473 {
05474    struct ast_context *c = NULL;
05475    int ret = -1;
05476    struct fake_context item;
05477 
05478    ast_rdlock_contexts();
05479 
05480    ast_copy_string(item.name, context, sizeof(item.name));
05481 
05482    c = ast_hashtab_lookup(contexts_table,&item);
05483    if (c)
05484       ret = 0;
05485    ast_unlock_contexts();
05486 
05487    /* if we found context, unlock macrolock */
05488    if (ret == 0) {
05489       ret = ast_mutex_unlock(&c->macrolock);
05490    }
05491 
05492    return ret;
05493 }

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

10089 {
10090    struct ast_include *inc = NULL;
10091    int res = 0;
10092 
10093    while ( (inc = ast_walk_context_includes(con, inc)) ) {
10094       if (ast_context_find(inc->rname))
10095          continue;
10096 
10097       res = -1;
10098       ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n",
10099          ast_get_context_name(con), inc->rname);
10100       break;
10101    }
10102 
10103    return res;
10104 }

struct ast_custom_function* ast_custom_function_find ( const char *  name  ) 

Definition at line 3325 of file pbx.c.

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

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

03326 {
03327    struct ast_custom_function *acf = NULL;
03328 
03329    AST_RWLIST_RDLOCK(&acf_root);
03330    AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) {
03331       if (!strcmp(name, acf->name))
03332          break;
03333    }
03334    AST_RWLIST_UNLOCK(&acf_root);
03335 
03336    return acf;
03337 }

int ast_custom_function_unregister ( struct ast_custom_function acf  ) 

Unregister a custom function.

Definition at line 3339 of file pbx.c.

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

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

03340 {
03341    struct ast_custom_function *cur;
03342 
03343    if (!acf) {
03344       return -1;
03345    }
03346 
03347    AST_RWLIST_WRLOCK(&acf_root);
03348    if ((cur = AST_RWLIST_REMOVE(&acf_root, acf, acflist))) {
03349 #ifdef AST_XML_DOCS
03350       if (cur->docsrc == AST_XML_DOC) {
03351          ast_string_field_free_memory(acf);
03352       }
03353 #endif
03354       ast_verb(2, "Unregistered custom function %s\n", cur->name);
03355    }
03356    AST_RWLIST_UNLOCK(&acf_root);
03357 
03358    return cur ? 0 : -1;
03359 }

int ast_destroy_timing ( struct ast_timing i  ) 

Deallocates memory structures associated with a timing bitmap.

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

Definition at line 7448 of file pbx.c.

References ast_free, and ast_timing::timezone.

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

07449 {
07450    if (i->timezone) {
07451       ast_free(i->timezone);
07452       i->timezone = NULL;
07453    }
07454    return 0;
07455 }

enum ast_extension_states ast_devstate_to_extenstate ( enum ast_device_state  devstate  ) 

Map devstate to an extension state.

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

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

04146 {
04147    switch (devstate) {
04148    case AST_DEVICE_ONHOLD:
04149       return AST_EXTENSION_ONHOLD;
04150    case AST_DEVICE_BUSY:
04151       return AST_EXTENSION_BUSY;
04152    case AST_DEVICE_UNKNOWN:
04153       return AST_EXTENSION_NOT_INUSE;
04154    case AST_DEVICE_UNAVAILABLE:
04155    case AST_DEVICE_INVALID:
04156       return AST_EXTENSION_UNAVAILABLE;
04157    case AST_DEVICE_RINGINUSE:
04158       return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING);
04159    case AST_DEVICE_RINGING:
04160       return AST_EXTENSION_RINGING;
04161    case AST_DEVICE_INUSE:
04162       return AST_EXTENSION_INUSE;
04163    case AST_DEVICE_NOT_INUSE:
04164       return AST_EXTENSION_NOT_INUSE;
04165    case AST_DEVICE_TOTAL: /* not a device state, included for completeness */
04166       break;
04167    }
04168 
04169    return AST_EXTENSION_NOT_INUSE;
04170 }

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

References E_MATCH, and pbx_extension_helper().

Referenced by __analog_ss_thread(), __ast_goto_if_exists(), __ast_pbx_run(), _macro_exec(), acf_isexten_exec(), analog_ss_thread(), answer_call(), ast_bridge_call(), ast_pbx_outgoing_exten(), builtin_blindtransfer(), cb_events(), cli_console_dial(), conf_run(), console_dial(), console_transfer(), dahdi_handle_dtmf(), dahdi_r2_on_call_offered(), dahdi_r2_on_dnis_digit_received(), dial_exec_full(), disa_exec(), dp_lookup(), dundi_lookup_local(), findmeexec(), get_also_info(), get_destination(), get_refer_info(), gosub_exec(), handle_gosub(), handle_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(), my_handle_dtmf(), park_space_reserve(), parkandannounce_exec(), pbx_builtin_waitexten(), phone_check_exception(), pri_dchannel(), pri_ss_thread(), privacy_exec(), process_ast_dsp(), process_sdp(), readexten_exec(), register_peer_exten(), rpt_exec(), show_debug_helper(), sip_new(), sip_read(), skinny_ss(), socket_process(), vm_authenticate(), and waitstream_core().

04579 {
04580    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0);
04581 }

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

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

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

07753 {
07754    if (!chan)
07755       return -1;
07756 
07757    ast_channel_lock(chan);
07758 
07759    if (!ast_strlen_zero(context))
07760       ast_copy_string(chan->context, context, sizeof(chan->context));
07761    if (!ast_strlen_zero(exten))
07762       ast_copy_string(chan->exten, exten, sizeof(chan->exten));
07763    if (priority > -1) {
07764       chan->priority = priority;
07765       /* see flag description in channel.h for explanation */
07766       if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP))
07767          chan->priority--;
07768    }
07769 
07770    ast_channel_unlock(chan);
07771 
07772    return 0;
07773 }

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

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

02490 {
02491    if (needmore != E_MATCHMORE && needmore != E_CANMATCH)
02492       ast_log(LOG_WARNING, "invalid argument %d\n", needmore);
02493    return extension_match_core(pattern, data, needmore);
02494 }

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

References ext_cmp().

Referenced by lua_extension_cmp().

02292 {
02293    return ext_cmp(a, b);
02294 }

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

References E_MATCH, and extension_match_core().

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

02485 {
02486    return extension_match_core(pattern, data, E_MATCH);
02487 }

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

References ast_exten::app, ast_add_extension(), ast_extension_state2(), ast_free_ptr, ast_hint_extension(), ast_strdup, ast_exten::cidmatch, ast_exten::data, ast_exten::exten, ast_exten::label, ast_exten::matchcid, ast_context::name, ast_exten::parent, ast_exten::priority, and ast_exten::registrar.

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

04209 {
04210    struct ast_exten *e;
04211 
04212    if (!(e = ast_hint_extension(c, context, exten))) {  /* Do we have a hint for this extension ? */
04213       return -1;                   /* No hint, return -1 */
04214    }
04215 
04216    if (e->exten[0] == '_') {
04217       /* Create this hint on-the-fly */
04218       ast_add_extension(e->parent->name, 0, exten, e->priority, e->label,
04219          e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr,
04220          e->registrar);
04221       if (!(e = ast_hint_extension(c, context, exten))) {
04222          /* Improbable, but not impossible */
04223          return -1;
04224       }
04225    }
04226 
04227    return ast_extension_state2(e);  /* Check all devices in the hint */
04228 }

static int ast_extension_state2 ( struct ast_exten e  )  [static]

Check state of extension by using hints.

Definition at line 4173 of file pbx.c.

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

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

04174 {
04175    struct ast_str *hint = ast_str_thread_get(&extensionstate_buf, 16);
04176    char *cur, *rest;
04177    struct ast_devstate_aggregate agg;
04178 
04179    if (!e)
04180       return -1;
04181 
04182    ast_devstate_aggregate_init(&agg);
04183 
04184    ast_str_set(&hint, 0, "%s", ast_get_extension_app(e));
04185 
04186    rest = ast_str_buffer(hint);  /* One or more devices separated with a & character */
04187 
04188    while ( (cur = strsep(&rest, "&")) ) {
04189       ast_devstate_aggregate_add(&agg, ast_device_state(cur));
04190    }
04191 
04192    return ast_devstate_to_extenstate(ast_devstate_aggregate_result(&agg));
04193 }

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

References ARRAY_LEN, extension_states, and cfextension_states::text.

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

04197 {
04198    int i;
04199 
04200    for (i = 0; (i < ARRAY_LEN(extension_states)); i++) {
04201       if (extension_states[i].extension_state == extension_state)
04202          return extension_states[i].text;
04203    }
04204    return "Unknown";
04205 }

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

References ao2_find, ao2_lock, ao2_ref, ao2_unlock, ast_exten::app, ast_add_extension(), ast_calloc, ast_free_ptr, ast_hint_extension(), AST_LIST_INSERT_HEAD, AST_LIST_TRAVERSE, ast_strdup, ast_state_cb::callback, ast_hint::callbacks, ast_exten::cidmatch, ast_exten::data, ast_state_cb::data, ast_exten::exten, hints, 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(), load_module(), and skinny_register().

04306 {
04307    struct ast_hint *hint;
04308    struct ast_state_cb *cblist;
04309    struct ast_exten *e;
04310 
04311    /* If there's no context and extension:  add callback to statecbs list */
04312    if (!context && !exten) {
04313       ao2_lock(hints);
04314 
04315       AST_LIST_TRAVERSE(&statecbs, cblist, entry) {
04316          if (cblist->callback == callback) {
04317             cblist->data = data;
04318             ao2_unlock(hints);
04319             return 0;
04320          }
04321       }
04322 
04323       /* Now insert the callback */
04324       if (!(cblist = ast_calloc(1, sizeof(*cblist)))) {
04325          ao2_unlock(hints);
04326          return -1;
04327       }
04328       cblist->id = 0;
04329       cblist->callback = callback;
04330       cblist->data = data;
04331 
04332       AST_LIST_INSERT_HEAD(&statecbs, cblist, entry);
04333 
04334       ao2_unlock(hints);
04335       return 0;
04336    }
04337 
04338    if (!context || !exten)
04339       return -1;
04340 
04341    /* This callback type is for only one hint, so get the hint */
04342    e = ast_hint_extension(NULL, context, exten);
04343    if (!e) {
04344       return -1;
04345    }
04346 
04347    /* If this is a pattern, dynamically create a new extension for this
04348     * particular match.  Note that this will only happen once for each
04349     * individual extension, because the pattern will no longer match first.
04350     */
04351    if (e->exten[0] == '_') {
04352       ast_add_extension(e->parent->name, 0, exten, e->priority, e->label,
04353          e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr,
04354          e->registrar);
04355       e = ast_hint_extension(NULL, context, exten);
04356       if (!e || e->exten[0] == '_') {
04357          return -1;
04358       }
04359    }
04360 
04361    /* Find the hint in the list of hints */
04362    hint = ao2_find(hints, e, 0);
04363 
04364    if (!hint) {
04365       return -1;
04366    }
04367 
04368    /* Now insert the callback in the callback list  */
04369    if (!(cblist = ast_calloc(1, sizeof(*cblist)))) {
04370       ao2_ref(hint, -1);
04371       return -1;
04372    }
04373 
04374    cblist->id = stateid++;    /* Unique ID for this callback */
04375    cblist->callback = callback;  /* Pointer to callback routine */
04376    cblist->data = data;    /* Data for the callback */
04377 
04378    ao2_lock(hint);
04379    AST_LIST_INSERT_HEAD(&hint->callbacks, cblist, entry);
04380    ao2_unlock(hint);
04381 
04382    ao2_ref(hint, -1);
04383 
04384    return cblist->id;
04385 }

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

References ao2_callback, ao2_lock, ao2_ref, ao2_unlock, ast_free, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_state_cb::callback, ast_state_cb::entry, find_hint_by_cb_id(), hints, and ast_state_cb::id.

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

04405 {
04406    struct ast_state_cb *p_cur = NULL;
04407    int ret = -1;
04408 
04409    if (!id && !callback) {
04410       return -1;
04411    }
04412 
04413    if (!id) {  /* id == 0 is a callback without extension */
04414       ao2_lock(hints);
04415       AST_LIST_TRAVERSE_SAFE_BEGIN(&statecbs, p_cur, entry) {
04416          if (p_cur->callback == callback) {
04417             AST_LIST_REMOVE_CURRENT(entry);
04418             break;
04419          }
04420       }
04421       AST_LIST_TRAVERSE_SAFE_END;
04422       ao2_unlock(hints);
04423    } else { /* callback with extension, find the callback based on ID */
04424       struct ast_hint *hint;
04425 
04426       hint = ao2_callback(hints, 0, find_hint_by_cb_id, &id);
04427 
04428       if (hint) {
04429          ao2_lock(hint);
04430          AST_LIST_TRAVERSE_SAFE_BEGIN(&hint->callbacks, p_cur, entry) {
04431             if (p_cur->id == id) {
04432                AST_LIST_REMOVE_CURRENT(entry);
04433                ret = 0;
04434                break;
04435             }
04436          }
04437          AST_LIST_TRAVERSE_SAFE_END;
04438 
04439          ao2_unlock(hint);
04440          ao2_ref(hint, -1);
04441       }
04442    }
04443 
04444    if (p_cur) {
04445       ast_free(p_cur);
04446    }
04447 
04448    return ret;
04449 }

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

04584 {
04585    return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
04586 }

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

References E_FINDLABEL, and pbx_extension_helper().

04589 {
04590    return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
04591 }

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

executes a read operation on a function

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

Return values:
0 success
non-zero failure

Definition at line 3483 of file pbx.c.

References __ast_module_user_add(), __ast_module_user_remove(), args, ast_copy_string(), ast_custom_function_find(), ast_free, ast_log(), ast_str_buffer(), ast_str_create(), ast_str_size(), ast_strdupa, ast_module_user::chan, copy(), func_args(), LOG_ERROR, ast_custom_function::mod, ast_custom_function::read, ast_custom_function::read2, and str.

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

03484 {
03485    char *copy = ast_strdupa(function);
03486    char *args = func_args(copy);
03487    struct ast_custom_function *acfptr = ast_custom_function_find(copy);
03488    int res;
03489    struct ast_module_user *u = NULL;
03490 
03491    if (acfptr == NULL) {
03492       ast_log(LOG_ERROR, "Function %s not registered\n", copy);
03493    } else if (!acfptr->read && !acfptr->read2) {
03494       ast_log(LOG_ERROR, "Function %s cannot be read\n", copy);
03495    } else if (acfptr->read) {
03496       if (acfptr->mod) {
03497          u = __ast_module_user_add(acfptr->mod, chan);
03498       }
03499       res = acfptr->read(chan, copy, args, workspace, len);
03500       if (acfptr->mod && u) {
03501          __ast_module_user_remove(acfptr->mod, u);
03502       }
03503       return res;
03504    } else {
03505       struct ast_str *str = ast_str_create(16);
03506       if (acfptr->mod) {
03507          u = __ast_module_user_add(acfptr->mod, chan);
03508       }
03509       res = acfptr->read2(chan, copy, args, &str, 0);
03510       if (acfptr->mod && u) {
03511          __ast_module_user_remove(acfptr->mod, u);
03512       }
03513       ast_copy_string(workspace, ast_str_buffer(str), len > ast_str_size(str) ? ast_str_size(str) : len);
03514       ast_free(str);
03515       return res;
03516    }
03517    return -1;
03518 }

int ast_func_read2 ( struct ast_channel chan,
const char *  function,
struct ast_str **  str,
ssize_t  maxlen 
)

executes a read operation on a function

Parameters:
chan Channel to execute on
function Data containing the function call string (will be modified)
str A dynamic string buffer into which to place the result.
maxlen <0 if the dynamic buffer should not grow; >0 if the dynamic buffer should be limited to that number of bytes; 0 if the dynamic buffer has no upper limit
This application executes a function in read mode on a given channel.

Return values:
0 success
non-zero failure

Definition at line 3520 of file pbx.c.

References __ast_module_user_add(), __ast_module_user_remove(), args, ast_custom_function_find(), ast_log(), ast_str_buffer(), ast_str_make_space(), ast_str_reset(), ast_str_size(), ast_strdupa, ast_module_user::chan, copy(), func_args(), LOG_ERROR, maxsize, ast_custom_function::mod, ast_custom_function::read, ast_custom_function::read2, ast_custom_function::read_max, str, and VAR_BUF_SIZE.

Referenced by append_channel_vars(), and ast_str_substitute_variables_full().

03521 {
03522    char *copy = ast_strdupa(function);
03523    char *args = func_args(copy);
03524    struct ast_custom_function *acfptr = ast_custom_function_find(copy);
03525    int res;
03526    struct ast_module_user *u = NULL;
03527 
03528    if (acfptr == NULL) {
03529       ast_log(LOG_ERROR, "Function %s not registered\n", copy);
03530    } else if (!acfptr->read && !acfptr->read2) {
03531       ast_log(LOG_ERROR, "Function %s cannot be read\n", copy);
03532    } else {
03533       if (acfptr->mod) {
03534          u = __ast_module_user_add(acfptr->mod, chan);
03535       }
03536       if (acfptr->read2) {
03537          /* ast_str enabled */
03538          ast_str_reset(*str);
03539          res = acfptr->read2(chan, copy, args, str, maxlen);
03540       } else {
03541          /* Legacy function pointer, allocate buffer for result */
03542          int maxsize = ast_str_size(*str);
03543          if (maxlen > -1) {
03544             if (maxlen == 0) {
03545                if (acfptr->read_max) {
03546                   maxsize = acfptr->read_max;
03547                } else {
03548                   maxsize = VAR_BUF_SIZE;
03549                }
03550             } else {
03551                maxsize = maxlen;
03552             }
03553             ast_str_make_space(str, maxsize);
03554          }
03555          res = acfptr->read(chan, copy, args, ast_str_buffer(*str), maxsize);
03556       }
03557       if (acfptr->mod && u) {
03558          __ast_module_user_remove(acfptr->mod, u);
03559       }
03560       return res;
03561    }
03562    return -1;
03563 }

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

executes a write operation on a function

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

Return values:
0 success
non-zero failure

Definition at line 3565 of file pbx.c.

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

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

03566 {
03567    char *copy = ast_strdupa(function);
03568    char *args = func_args(copy);
03569    struct ast_custom_function *acfptr = ast_custom_function_find(copy);
03570 
03571    if (acfptr == NULL)
03572       ast_log(LOG_ERROR, "Function %s not registered\n", copy);
03573    else if (!acfptr->write)
03574       ast_log(LOG_ERROR, "Function %s cannot be written to\n", copy);
03575    else {
03576       int res;
03577       struct ast_module_user *u = NULL;
03578       if (acfptr->mod)
03579          u = __ast_module_user_add(acfptr->mod, chan);
03580       res = acfptr->write(chan, copy, args, value);
03581       if (acfptr->mod && u)
03582          __ast_module_user_remove(acfptr->mod, u);
03583       return res;
03584    }
03585 
03586    return -1;
03587 }

const char* ast_get_context_name ( struct ast_context con  ) 

Definition at line 9940 of file pbx.c.

References ast_context::name.

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

09941 {
09942    return con ? con->name : NULL;
09943 }

const char* ast_get_context_registrar ( struct ast_context c  ) 

Definition at line 9978 of file pbx.c.

References ast_context::registrar.

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

09979 {
09980    return c ? c->registrar : NULL;
09981 }

const char* ast_get_extension_app ( struct ast_exten e  ) 

Definition at line 10008 of file pbx.c.

References ast_exten::app.

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

10009 {
10010    return e ? e->app : NULL;
10011 }

void* ast_get_extension_app_data ( struct ast_exten e  ) 

Definition at line 10013 of file pbx.c.

References ast_exten::data.

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

10014 {
10015    return e ? e->data : NULL;
10016 }

const char* ast_get_extension_cidmatch ( struct ast_exten e  ) 

Definition at line 10003 of file pbx.c.

References ast_exten::cidmatch.

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

10004 {
10005    return e ? e->cidmatch : NULL;
10006 }

struct ast_context* ast_get_extension_context ( struct ast_exten exten  ) 

Definition at line 9945 of file pbx.c.

References exten.

Referenced by handle_show_hint(), handle_show_hints(), and hints_data_provider_get().

09946 {
09947    return exten ? exten->parent : NULL;
09948 }

const char* ast_get_extension_label ( struct ast_exten exten  ) 

Definition at line 9955 of file pbx.c.

References exten.

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

09956 {
09957    return exten ? exten->label : NULL;
09958 }

int ast_get_extension_matchcid ( struct ast_exten e  ) 

Definition at line 9998 of file pbx.c.

References ast_exten::matchcid.

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

09999 {
10000    return e ? e->matchcid : 0;
10001 }

const char* ast_get_extension_name ( struct ast_exten exten  ) 

Definition at line 9950 of file pbx.c.

References exten.

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

09951 {
09952    return exten ? exten->exten : NULL;
09953 }

int ast_get_extension_priority ( struct ast_exten exten  ) 

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

09971 {
09972    return exten ? exten->priority : -1;
09973 }

const char* ast_get_extension_registrar ( struct ast_exten e  ) 

Definition at line 9983 of file pbx.c.

References ast_exten::registrar.

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

09984 {
09985    return e ? e->registrar : NULL;
09986 }

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

If an extension hint exists, return non-zero.

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

Definition at line 4540 of file pbx.c.

References ast_copy_string(), ast_get_extension_app(), ast_get_extension_app_data(), and ast_hint_extension().

Referenced by action_extensionstate(), get_cid_name(), get_destination(), hint_read(), manager_state_cb(), skinny_extensionstate_cb(), and state_notify_build_xml().

04541 {
04542    struct ast_exten *e = ast_hint_extension(c, context, exten);
04543 
04544    if (e) {
04545       if (hint)
04546          ast_copy_string(hint, ast_get_extension_app(e), hintsize);
04547       if (name) {
04548          const char *tmp = ast_get_extension_app_data(e);
04549          if (tmp)
04550             ast_copy_string(name, tmp, namesize);
04551       }
04552       return -1;
04553    }
04554    return 0;
04555 }

const char* ast_get_ignorepat_name ( struct ast_ignorepat ip  ) 

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

09966 {
09967    return ip ? ip->pattern : NULL;
09968 }

const char* ast_get_ignorepat_registrar ( struct ast_ignorepat ip  ) 

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

09994 {
09995    return ip ? ip->registrar : NULL;
09996 }

const char* ast_get_include_name ( struct ast_include inc  ) 

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

09961 {
09962    return inc ? inc->name : NULL;
09963 }

const char* ast_get_include_registrar ( struct ast_include i  ) 

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

09989 {
09990    return i ? i->registrar : NULL;
09991 }

const char* ast_get_switch_data ( struct ast_sw sw  ) 

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

10024 {
10025    return sw ? sw->data : NULL;
10026 }

int ast_get_switch_eval ( struct ast_sw sw  ) 

Definition at line 10028 of file pbx.c.

References ast_sw::eval.

Referenced by context_merge_incls_swits_igps_other_registrars().

10029 {
10030    return sw->eval;
10031 }

const char* ast_get_switch_name ( struct ast_sw sw  ) 

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

10019 {
10020    return sw ? sw->name : NULL;
10021 }

const char* ast_get_switch_registrar ( struct ast_sw sw  ) 

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

10034 {
10035    return sw ? sw->registrar : NULL;
10036 }

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

References __ast_goto_if_exists().

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

10129 {
10130    return __ast_goto_if_exists(chan, context, exten, priority, 0);
10131 }

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

hashtable functions for contexts

Definition at line 1046 of file pbx.c.

References ast_context::name.

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

01047 {
01048    const struct ast_context *ac = ah_a;
01049    const struct ast_context *bc = ah_b;
01050    if (!ac || !bc) /* safety valve, but it might prevent a crash you'd rather have happen */
01051       return 1;
01052    /* assume context names are registered in a string table! */
01053    return strcmp(ac->name, bc->name);
01054 }

unsigned int ast_hashtab_hash_contexts ( const void *  obj  ) 

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

01090 {
01091    const struct ast_context *ac = obj;
01092    return ast_hashtab_hash_string(ac->name);
01093 }

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

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

04137 {
04138    struct ast_exten *e;
04139    ast_rdlock_contexts();
04140    e = ast_hint_extension_nolock(c, context, exten);
04141    ast_unlock_contexts();
04142    return e;
04143 }

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

04131 {
04132    struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */
04133    return pbx_find_extension(c, NULL, &q, context, exten, PRIORITY_HINT, NULL, "", E_MATCH);
04134 }

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

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

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

07699 {
07700    struct ast_context *con = ast_context_find(context);
07701    if (con) {
07702       struct ast_ignorepat *pat;
07703       for (pat = con->ignorepats; pat; pat = pat->next) {
07704          if (ast_extension_match(pat->pattern, pattern))
07705             return 1;
07706       }
07707    }
07708 
07709    return 0;
07710 }

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

References E_MATCHMORE, and pbx_extension_helper().

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

04599 {
04600    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0);
04601 }

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

References __ast_internal_context_destroy(), ao2_find, AO2_ITERATOR_DONTLOCK, ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_add_extension_nolock(), ast_calloc, AST_EXTENSION_REMOVED, ast_free, ast_free_ptr, ast_hashtab_destroy(), ast_hashtab_end_traversal(), ast_hashtab_next(), ast_hashtab_start_traversal(), ast_hint_extension_nolock(), AST_LIST_APPEND_LIST, AST_LIST_EMPTY, AST_LIST_HEAD_INIT_VALUE, AST_LIST_INSERT_HEAD, AST_LIST_REMOVE_HEAD, ast_rdlock_contexts(), ast_strdup, ast_tvdiff_us(), ast_tvnow(), ast_unlock_contexts(), ast_verb, ast_state_cb::callback, ast_hint::callbacks, context_merge(), contexts, contexts_table, ast_state_cb::data, E_MATCH, store_hint::exten, ast_exten::exten, ast_hint::exten, hints, ast_hint::laststate, store_hint::list, ast_context::name, ast_context::next, store_hint::next, ast_exten::parent, pbx_find_extension(), PRIORITY_HINT, and pbx_find_info::stacklen.

Referenced by lua_reload_extensions(), and pbx_load_module().

07048 {
07049    double ft;
07050    struct ast_context *tmp, *oldcontextslist;
07051    struct ast_hashtab *oldtable;
07052    struct store_hints store = AST_LIST_HEAD_INIT_VALUE;
07053    struct store_hint *this;
07054    struct ast_hint *hint;
07055    struct ast_exten *exten;
07056    int length;
07057    struct ast_state_cb *thiscb;
07058    struct ast_hashtab_iter *iter;
07059    struct ao2_iterator i;
07060 
07061    /* it is very important that this function hold the hint list lock _and_ the conlock
07062       during its operation; not only do we need to ensure that the list of contexts
07063       and extensions does not change, but also that no hint callbacks (watchers) are
07064       added or removed during the merge/delete process
07065 
07066       in addition, the locks _must_ be taken in this order, because there are already
07067       other code paths that use this order
07068    */
07069 
07070    struct timeval begintime, writelocktime, endlocktime, enddeltime;
07071 
07072    begintime = ast_tvnow();
07073    ast_rdlock_contexts();
07074    iter = ast_hashtab_start_traversal(contexts_table);
07075    while ((tmp = ast_hashtab_next(iter))) {
07076       context_merge(extcontexts, exttable, tmp, registrar);
07077    }
07078    ast_hashtab_end_traversal(iter);
07079 
07080    ao2_lock(hints);
07081    writelocktime = ast_tvnow();
07082 
07083    /* preserve all watchers for hints */
07084    i = ao2_iterator_init(hints, AO2_ITERATOR_DONTLOCK);
07085    for (hint = ao2_iterator_next(&i); hint; ao2_ref(hint, -1), hint = ao2_iterator_next(&i)) {
07086       if (!AST_LIST_EMPTY(&hint->callbacks)) {
07087          length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2 + sizeof(*this);
07088          if (!(this = ast_calloc(1, length))) {
07089             continue;
07090          }
07091          ao2_lock(hint);
07092 
07093          if (hint->exten == NULL) {
07094             ao2_unlock(hint);
07095             continue;
07096          }
07097 
07098          /* this removes all the callbacks from the hint into this. */
07099          AST_LIST_APPEND_LIST(&this->callbacks, &hint->callbacks, entry);
07100          this->laststate = hint->laststate;
07101          this->context = this->data;
07102          strcpy(this->data, hint->exten->parent->name);
07103          this->exten = this->data + strlen(this->context) + 1;
07104          strcpy(this->exten, hint->exten->exten);
07105          ao2_unlock(hint);
07106          AST_LIST_INSERT_HEAD(&store, this, list);
07107       }
07108    }
07109 
07110    /* save the old table and list */
07111    oldtable = contexts_table;
07112    oldcontextslist = contexts;
07113 
07114    /* move in the new table and list */
07115    contexts_table = exttable;
07116    contexts = *extcontexts;
07117 
07118    /* restore the watchers for hints that can be found; notify those that
07119       cannot be restored
07120    */
07121    while ((this = AST_LIST_REMOVE_HEAD(&store, list))) {
07122       struct pbx_find_info q = { .stacklen = 0 };
07123       exten = pbx_find_extension(NULL, NULL, &q, this->context, this->exten, PRIORITY_HINT, NULL, "", E_MATCH);
07124       /* If this is a pattern, dynamically create a new extension for this
07125        * particular match.  Note that this will only happen once for each
07126        * individual extension, because the pattern will no longer match first.
07127        */
07128       if (exten && exten->exten[0] == '_') {
07129          ast_add_extension_nolock(exten->parent->name, 0, this->exten, PRIORITY_HINT, NULL,
07130             0, exten->app, ast_strdup(exten->data), ast_free_ptr, exten->registrar);
07131          /* rwlocks are not recursive locks */
07132          exten = ast_hint_extension_nolock(NULL, this->context, this->exten);
07133       }
07134 
07135       /* Find the hint in the list of hints */
07136       hint = ao2_find(hints, exten, 0);
07137       if (!exten || !hint) {
07138          /* this hint has been removed, notify the watchers */
07139          while ((thiscb = AST_LIST_REMOVE_HEAD(&this->callbacks, entry))) {
07140             thiscb->callback(this->context, this->exten, AST_EXTENSION_REMOVED, thiscb->data);
07141             ast_free(thiscb);
07142          }
07143       } else {
07144          ao2_lock(hint);
07145          AST_LIST_APPEND_LIST(&hint->callbacks, &this->callbacks, entry);
07146          hint->laststate = this->laststate;
07147          ao2_unlock(hint);
07148       }
07149       ast_free(this);
07150       if (hint) {
07151          ao2_ref(hint, -1);
07152       }
07153    }
07154 
07155    ao2_unlock(hints);
07156    ast_unlock_contexts();
07157    endlocktime = ast_tvnow();
07158 
07159    /* the old list and hashtab no longer are relevant, delete them while the rest of asterisk
07160       is now freely using the new stuff instead */
07161 
07162    ast_hashtab_destroy(oldtable, NULL);
07163 
07164    for (tmp = oldcontextslist; tmp; ) {
07165       struct ast_context *next;  /* next starting point */
07166       next = tmp->next;
07167       __ast_internal_context_destroy(tmp);
07168       tmp = next;
07169    }
07170    enddeltime = ast_tvnow();
07171 
07172    ft = ast_tvdiff_us(writelocktime, begintime);
07173    ft /= 1000000.0;
07174    ast_verb(3,"Time to scan old dialplan and merge leftovers back into the new: %8.6f sec\n", ft);
07175 
07176    ft = ast_tvdiff_us(endlocktime, writelocktime);
07177    ft /= 1000000.0;
07178    ast_verb(3,"Time to restore hints and swap in new dialplan: %8.6f sec\n", ft);
07179 
07180    ft = ast_tvdiff_us(enddeltime, endlocktime);
07181    ft /= 1000000.0;
07182    ast_verb(3,"Time to delete the old dialplan: %8.6f sec\n", ft);
07183 
07184    ft = ast_tvdiff_us(enddeltime, begintime);
07185    ft /= 1000000.0;
07186    ast_verb(3,"Total time merge_contexts_delete: %8.6f sec\n", ft);
07187    return;
07188 }

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

Note:
This function will handle locking the channel as needed.

Definition at line 10193 of file pbx.c.

References pbx_parseable_goto().

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

10194 {
10195    return pbx_parseable_goto(chan, goto_string, 0);
10196 }

int ast_pbx_init ( void   ) 

Provided by pbx.c

Definition at line 10243 of file pbx.c.

References ao2_container_alloc, hint_cmp(), hint_hash(), and hints.

Referenced by main().

10244 {
10245    hints = ao2_container_alloc(HASH_EXTENHINT_SIZE, hint_hash, hint_cmp);
10246 
10247    return hints ? 0 : -1;
10248 }

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

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

Definition at line 8541 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(), async_stat::chan, errno, LOG_WARNING, and outgoing_helper::vars.

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

08542 {
08543    struct ast_channel *chan;
08544    struct app_tmp *tmp;
08545    int res = -1, cdr_res = -1;
08546    struct outgoing_helper oh;
08547 
08548    memset(&oh, 0, sizeof(oh));
08549    oh.vars = vars;
08550    oh.account = account;
08551 
08552    if (locked_channel)
08553       *locked_channel = NULL;
08554    if (ast_strlen_zero(app)) {
08555       res = -1;
08556       goto outgoing_app_cleanup;
08557    }
08558    if (synchronous) {
08559       chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh);
08560       if (chan) {
08561          ast_set_variables(chan, vars);
08562          if (account)
08563             ast_cdr_setaccount(chan, account);
08564          if (chan->_state == AST_STATE_UP) {
08565             res = 0;
08566             ast_verb(4, "Channel %s was answered.\n", chan->name);
08567             tmp = ast_calloc(1, sizeof(*tmp));
08568             if (!tmp)
08569                res = -1;
08570             else {
08571                ast_copy_string(tmp->app, app, sizeof(tmp->app));
08572                if (appdata)
08573                   ast_copy_string(tmp->data, appdata, sizeof(tmp->data));
08574                tmp->chan = chan;
08575                if (synchronous > 1) {
08576                   if (locked_channel)
08577                      ast_channel_unlock(chan);
08578                   ast_pbx_run_app(tmp);
08579                } else {
08580                   if (locked_channel)
08581                      ast_channel_lock(chan);
08582                   if (ast_pthread_create_detached(&tmp->t, NULL, ast_pbx_run_app, tmp)) {
08583                      ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno));
08584                      ast_free(tmp);
08585                      if (locked_channel)
08586                         ast_channel_unlock(chan);
08587                      ast_hangup(chan);
08588                      res = -1;
08589                   } else {
08590                      if (locked_channel)
08591                         *locked_channel = chan;
08592                   }
08593                }
08594             }
08595          } else {
08596             ast_verb(4, "Channel %s was never answered.\n", chan->name);
08597             if (chan->cdr) { /* update the cdr */
08598                /* here we update the status of the call, which sould be busy.
08599                 * if that fails then we set the status to failed */
08600                if (ast_cdr_disposition(chan->cdr, chan->hangupcause))
08601                   ast_cdr_failed(chan->cdr);
08602             }
08603             ast_hangup(chan);
08604          }
08605       }
08606 
08607       if (res < 0) { /* the call failed for some reason */
08608          if (*reason == 0) { /* if the call failed (not busy or no answer)
08609                         * update the cdr with the failed message */
08610             cdr_res = ast_pbx_outgoing_cdr_failed();
08611             if (cdr_res != 0) {
08612                res = cdr_res;
08613                goto outgoing_app_cleanup;
08614             }
08615          }
08616       }
08617 
08618    } else {
08619       struct async_stat *as;
08620       if (!(as = ast_calloc(1, sizeof(*as)))) {
08621          res = -1;
08622          goto outgoing_app_cleanup;
08623       }
08624       chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh);
08625       if (!chan) {
08626          ast_free(as);
08627          res = -1;
08628          goto outgoing_app_cleanup;
08629       }
08630       as->chan = chan;
08631       ast_copy_string(as->app, app, sizeof(as->app));
08632       if (appdata)
08633          ast_copy_string(as->appdata,  appdata, sizeof(as->appdata));
08634       as->timeout = timeout;
08635       ast_set_variables(chan, vars);
08636       if (account)
08637          ast_cdr_setaccount(chan, account);
08638       /* Start a new thread, and get something handling this channel. */
08639       if (locked_channel)
08640          ast_channel_lock(chan);
08641       if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) {
08642          ast_log(LOG_WARNING, "Failed to start async wait\n");
08643          ast_free(as);
08644          if (locked_channel)
08645             ast_channel_unlock(chan);
08646          ast_hangup(chan);
08647          res = -1;
08648          goto outgoing_app_cleanup;
08649       } else {
08650          if (locked_channel)
08651             *locked_channel = chan;
08652       }
08653       res = 0;
08654    }
08655 outgoing_app_cleanup:
08656    ast_variables_destroy(vars);
08657    return res;
08658 }

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

References ast_cdr_alloc(), ast_cdr_detach(), ast_cdr_end(), ast_cdr_failed(), ast_cdr_init(), ast_cdr_start(), ast_channel_release(), ast_dummy_channel_alloc(), and ast_channel::cdr.

Referenced by ast_pbx_outgoing_app(), and ast_pbx_outgoing_exten().

08349 {
08350    /* allocate a channel */
08351    struct ast_channel *chan = ast_dummy_channel_alloc();
08352 
08353    if (!chan)
08354       return -1;  /* failure */
08355 
08356    chan->cdr = ast_cdr_alloc();
08357    if (!chan->cdr) {
08358       /* allocation of the cdr failed */
08359       chan = ast_channel_release(chan);   /* free the channel */
08360       return -1;                /* return failure */
08361    }
08362 
08363    /* allocation of the cdr was successful */
08364    ast_cdr_init(chan->cdr, chan);  /* initialize our channel's cdr */
08365    ast_cdr_start(chan->cdr);       /* record the start and stop time */
08366    ast_cdr_end(chan->cdr);
08367    ast_cdr_failed(chan->cdr);      /* set the status to failed */
08368    ast_cdr_detach(chan->cdr);      /* post and free the record */
08369    chan->cdr = NULL;
08370    chan = ast_channel_release(chan);         /* free the channel */
08371 
08372    return 0;  /* success */
08373 }

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

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

Definition at line 8375 of file pbx.c.

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

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

08376 {
08377    struct ast_channel *chan;
08378    struct async_stat *as;
08379    int res = -1, cdr_res = -1;
08380    struct outgoing_helper oh;
08381 
08382    if (synchronous) {
08383       oh.context = context;
08384       oh.exten = exten;
08385       oh.priority = priority;
08386       oh.cid_num = cid_num;
08387       oh.cid_name = cid_name;
08388       oh.account = account;
08389       oh.vars = vars;
08390       oh.parent_channel = NULL;
08391 
08392       chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh);
08393       if (channel) {
08394          *channel = chan;
08395          if (chan)
08396             ast_channel_lock(chan);
08397       }
08398       if (chan) {
08399          if (chan->_state == AST_STATE_UP) {
08400                res = 0;
08401             ast_verb(4, "Channel %s was answered.\n", chan->name);
08402 
08403             if (synchronous > 1) {
08404                if (channel)
08405                   ast_channel_unlock(chan);
08406                if (ast_pbx_run(chan)) {
08407                   ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name);
08408                   if (channel)
08409                      *channel = NULL;
08410                   ast_hangup(chan);
08411                   chan = NULL;
08412                   res = -1;
08413                }
08414             } else {
08415                if (ast_pbx_start(chan)) {
08416                   ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name);
08417                   if (channel) {
08418                      *channel = NULL;
08419                      ast_channel_unlock(chan);
08420                   }
08421                   ast_hangup(chan);
08422                   res = -1;
08423                }
08424                chan = NULL;
08425             }
08426          } else {
08427             ast_verb(4, "Channel %s was never answered.\n", chan->name);
08428 
08429             if (chan->cdr) { /* update the cdr */
08430                /* here we update the status of the call, which sould be busy.
08431                 * if that fails then we set the status to failed */
08432                if (ast_cdr_disposition(chan->cdr, chan->hangupcause))
08433                   ast_cdr_failed(chan->cdr);
08434             }
08435 
08436             if (channel) {
08437                *channel = NULL;
08438                ast_channel_unlock(chan);
08439             }
08440             ast_hangup(chan);
08441             chan = NULL;
08442          }
08443       }
08444 
08445       if (res < 0) { /* the call failed for some reason */
08446          if (*reason == 0) { /* if the call failed (not busy or no answer)
08447                         * update the cdr with the failed message */
08448             cdr_res = ast_pbx_outgoing_cdr_failed();
08449             if (cdr_res != 0) {
08450                res = cdr_res;
08451                goto outgoing_exten_cleanup;
08452             }
08453          }
08454 
08455          /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */
08456          /* check if "failed" exists */
08457          if (ast_exists_extension(chan, context, "failed", 1, NULL)) {
08458             chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", NULL, 0, "OutgoingSpoolFailed");
08459             if (chan) {
08460                char failed_reason[4] = "";
08461                if (!ast_strlen_zero(context))
08462                   ast_copy_string(chan->context, context, sizeof(chan->context));
08463                set_ext_pri(chan, "failed", 1);
08464                ast_set_variables(chan, vars);
08465                snprintf(failed_reason, sizeof(failed_reason), "%d", *reason);
08466                pbx_builtin_setvar_helper(chan, "REASON", failed_reason);
08467                if (account)
08468                   ast_cdr_setaccount(chan, account);
08469                if (ast_pbx_run(chan)) {
08470                   ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name);
08471                   ast_hangup(chan);
08472                }
08473                chan = NULL;
08474             }
08475          }
08476       }
08477    } else {
08478       if (!(as = ast_calloc(1, sizeof(*as)))) {
08479          res = -1;
08480          goto outgoing_exten_cleanup;
08481       }
08482       chan = ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name);
08483       if (channel) {
08484          *channel = chan;
08485          if (chan)
08486             ast_channel_lock(chan);
08487       }
08488       if (!chan) {
08489          ast_free(as);
08490          res = -1;
08491          goto outgoing_exten_cleanup;
08492       }
08493       as->chan = chan;
08494       ast_copy_string(as->context, context, sizeof(as->context));
08495       set_ext_pri(as->chan,  exten, priority);
08496       as->timeout = timeout;
08497       ast_set_variables(chan, vars);
08498       if (account)
08499          ast_cdr_setaccount(chan, account);
08500       if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) {
08501          ast_log(LOG_WARNING, "Failed to start async wait\n");
08502          ast_free(as);
08503          if (channel) {
08504             *channel = NULL;
08505             ast_channel_unlock(chan);
08506          }
08507          ast_hangup(chan);
08508          res = -1;
08509          goto outgoing_exten_cleanup;
08510       }
08511       res = 0;
08512    }
08513 outgoing_exten_cleanup:
08514    ast_variables_destroy(vars);
08515    return res;
08516 }

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

References ast_pbx_run_args().

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

05060 {
05061    return ast_pbx_run_args(c, NULL);
05062 }

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

run the application and free the descriptor once done

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

08527 {
08528    struct app_tmp *tmp = data;
08529    struct ast_app *app;
08530    app = pbx_findapp(tmp->app);
08531    if (app) {
08532       ast_verb(4, "Launching %s(%s) on %s\n", tmp->app, tmp->data, tmp->chan->name);
08533       pbx_exec(tmp->chan, app, tmp->data);
08534    } else
08535       ast_log(LOG_WARNING, "No such application '%s'\n", tmp->app);
08536    ast_hangup(tmp->chan);
08537    ast_free(tmp);
08538    return NULL;
08539 }

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

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

05045 {
05046    enum ast_pbx_result res = AST_PBX_SUCCESS;
05047 
05048    if (increase_call_count(c)) {
05049       return AST_PBX_CALL_LIMIT;
05050    }
05051 
05052    res = __ast_pbx_run(c, args);
05053 
05054    decrease_call_count();
05055 
05056    return res;
05057 }

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

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

Referenced by __oh323_new(), alsa_new(), ast_async_goto(), ast_iax2_new(), ast_pbx_outgoing_exten(), bridge_call_thread(), bridge_exec(), check_goto_on_transfer(), console_new(), dahdi_new(), dial_exec_full(), generic_recall(), 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(), ss7_start_call(), unistim_new(), and usbradio_new().

05023 {
05024    pthread_t t;
05025 
05026    if (!c) {
05027       ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
05028       return AST_PBX_FAILED;
05029    }
05030 
05031    if (increase_call_count(c))
05032       return AST_PBX_CALL_LIMIT;
05033 
05034    /* Start a new thread, and get something handling this channel. */
05035    if (ast_pthread_create_detached(&t, NULL, pbx_thread, c)) {
05036       ast_log(LOG_WARNING, "Failed to create new channel thread\n");
05037       decrease_call_count();
05038       return AST_PBX_FAILED;
05039    }
05040 
05041    return AST_PBX_SUCCESS;
05042 }

int ast_processed_calls ( void   ) 

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

Definition at line 5069 of file pbx.c.

References totalcalls.

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

05070 {
05071    return totalcalls;
05072 }

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

09928 {
09929    return ast_rwlock_rdlock(&con->lock);
09930 }

int ast_rdlock_contexts ( void   ) 

Read locks the context list.

Return values:
0 on success
-1 on error

Definition at line 9909 of file pbx.c.

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

09910 {
09911    return ast_mutex_lock(&conlock);
09912 }

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

Register an application.

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

Definition at line 5496 of file pbx.c.

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

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

05497 {
05498    struct ast_app *tmp, *cur = NULL;
05499    char tmps[80];
05500    int length, res;
05501 #ifdef AST_XML_DOCS
05502    char *tmpxml;
05503 #endif
05504 
05505    AST_RWLIST_WRLOCK(&apps);
05506    AST_RWLIST_TRAVERSE(&apps, tmp, list) {
05507       if (!(res = strcasecmp(app, tmp->name))) {
05508          ast_log(LOG_WARNING, "Already have an application '%s'\n", app);
05509          AST_RWLIST_UNLOCK(&apps);
05510          return -1;
05511       } else if (res < 0)
05512          break;
05513    }
05514 
05515    length = sizeof(*tmp) + strlen(app) + 1;
05516 
05517    if (!(tmp = ast_calloc(1, length))) {
05518       AST_RWLIST_UNLOCK(&apps);
05519       return -1;
05520    }
05521 
05522    if (ast_string_field_init(tmp, 128)) {
05523       AST_RWLIST_UNLOCK(&apps);
05524       ast_free(tmp);
05525       return -1;
05526    }
05527 
05528 #ifdef AST_XML_DOCS
05529    /* Try to lookup the docs in our XML documentation database */
05530    if (ast_strlen_zero(synopsis) && ast_strlen_zero(description)) {
05531       /* load synopsis */
05532       tmpxml = ast_xmldoc_build_synopsis("application", app);
05533       ast_string_field_set(tmp, synopsis, tmpxml);
05534       ast_free(tmpxml);
05535 
05536       /* load description */
05537       tmpxml = ast_xmldoc_build_description("application", app);
05538       ast_string_field_set(tmp, description, tmpxml);
05539       ast_free(tmpxml);
05540 
05541       /* load syntax */
05542       tmpxml = ast_xmldoc_build_syntax("application", app);
05543       ast_string_field_set(tmp, syntax, tmpxml);
05544       ast_free(tmpxml);
05545 
05546       /* load arguments */
05547       tmpxml = ast_xmldoc_build_arguments("application", app);
05548       ast_string_field_set(tmp, arguments, tmpxml);
05549       ast_free(tmpxml);
05550 
05551       /* load seealso */
05552       tmpxml = ast_xmldoc_build_seealso("application", app);
05553       ast_string_field_set(tmp, seealso, tmpxml);
05554       ast_free(tmpxml);
05555       tmp->docsrc = AST_XML_DOC;
05556    } else {
05557 #endif
05558       ast_string_field_set(tmp, synopsis, synopsis);
05559       ast_string_field_set(tmp, description, description);
05560 #ifdef AST_XML_DOCS
05561       tmp->docsrc = AST_STATIC_DOC;
05562    }
05563 #endif
05564 
05565    strcpy(tmp->name, app);
05566    tmp->execute = execute;
05567    tmp->module = mod;
05568 
05569    /* Store in alphabetical order */
05570    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, cur, list) {
05571       if (strcasecmp(tmp->name, cur->name) < 0) {
05572          AST_RWLIST_INSERT_BEFORE_CURRENT(tmp, list);
05573          break;
05574       }
05575    }
05576    AST_RWLIST_TRAVERSE_SAFE_END;
05577    if (!cur)
05578       AST_RWLIST_INSERT_TAIL(&apps, tmp, list);
05579 
05580    ast_verb(2, "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps)));
05581 
05582    AST_RWLIST_UNLOCK(&apps);
05583 
05584    return 0;
05585 }

int ast_register_switch ( struct ast_switch sw  ) 

Register an alternative dialplan switch.

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

Return values:
0 success
non-zero failure

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

05592 {
05593    struct ast_switch *tmp;
05594 
05595    AST_RWLIST_WRLOCK(&switches);
05596    AST_RWLIST_TRAVERSE(&switches, tmp, list) {
05597       if (!strcasecmp(tmp->name, sw->name)) {
05598          AST_RWLIST_UNLOCK(&switches);
05599          ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name);
05600          return -1;
05601       }
05602    }
05603    AST_RWLIST_INSERT_TAIL(&switches, sw, list);
05604    AST_RWLIST_UNLOCK(&switches);
05605 
05606    return 0;
05607 }

static int ast_remove_hint ( struct ast_exten e  )  [static]

Remove hint from extension.

Definition at line 4506 of file pbx.c.

References ao2_find, ao2_lock, ao2_ref, ao2_unlink, ao2_unlock, AST_EXTENSION_DEACTIVATED, ast_free, AST_LIST_REMOVE_HEAD, ast_state_cb::callback, ast_hint::callbacks, ast_state_cb::data, ast_state_cb::entry, ast_exten::exten, ast_hint::exten, hints, ast_context::name, and ast_exten::parent.

Referenced by destroy_exten().

04507 {
04508    /* Cleanup the Notifys if hint is removed */
04509    struct ast_hint *hint;
04510    struct ast_state_cb *cblist;
04511 
04512    if (!e) {
04513       return -1;
04514    }
04515 
04516    hint = ao2_find(hints, e, 0);
04517 
04518    if (!hint) {
04519       return -1;
04520    }
04521    ao2_lock(hint);
04522 
04523    while ((cblist = AST_LIST_REMOVE_HEAD(&hint->callbacks, entry))) {
04524       /* Notify with -1 and remove all callbacks */
04525       cblist->callback(hint->exten->parent->name, hint->exten->exten,
04526          AST_EXTENSION_DEACTIVATED, cblist->data);
04527       ast_free(cblist);
04528    }
04529 
04530    hint->exten = NULL;
04531    ao2_unlink(hints, hint);
04532    ao2_unlock(hint);
04533    ao2_ref(hint, -1);
04534 
04535    return 0;
04536 }

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

04604 {
04605    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN, found, combined_find_spawn);
04606 }

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

If an extension hint exists, return non-zero.

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

Definition at line 4558 of file pbx.c.

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

Referenced by ast_str_retrieve_variable().

04559 {
04560    struct ast_exten *e = ast_hint_extension(c, context, exten);
04561 
04562    if (!e) {
04563       return 0;
04564    }
04565 
04566    if (hint) {
04567       ast_str_set(hint, hintsize, "%s", ast_get_extension_app(e));
04568    }
04569    if (name) {
04570       const char *tmp = ast_get_extension_app_data(e);
04571       if (tmp) {
04572          ast_str_set(name, namesize, "%s", tmp);
04573       }
04574    }
04575    return -1;
04576 }

const char* ast_str_retrieve_variable ( struct ast_str **  buf,
ssize_t  maxlen,
struct ast_channel chan,
struct varshead headp,
const char *  var 
)

Parameters:
buf Result will be placed in this buffer.
maxlen -1 if the buffer should not grow, 0 if the buffer may grow to any size, and >0 if the buffer should grow only to that number of bytes.
chan Channel variables from which to extract values, and channel to pass to any dialplan functions.
headp If no channel is specified, a channel list from which to extract variable values
var Variable name to retrieve.

Definition at line 2987 of file pbx.c.

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

Referenced by ast_str_substitute_variables_full(), and pbx_retrieve_variable().

02988 {
02989    const char not_found = '\0';
02990    char *tmpvar;
02991    const char *ret;
02992    const char *s; /* the result */
02993    int offset, length;
02994    int i, need_substring;
02995    struct varshead *places[2] = { headp, &globals };  /* list of places where we may look */
02996 
02997    if (c) {
02998       ast_channel_lock(c);
02999       places[0] = &c->varshead;
03000    }
03001    /*
03002     * Make a copy of var because parse_variable_name() modifies the string.
03003     * Then if called directly, we might need to run substring() on the result;
03004     * remember this for later in 'need_substring', 'offset' and 'length'
03005     */
03006    tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */
03007    need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */);
03008 
03009    /*
03010     * Look first into predefined variables, then into variable lists.
03011     * Variable 's' points to the result, according to the following rules:
03012     * s == &not_found (set at the beginning) means that we did not find a
03013     * matching variable and need to look into more places.
03014     * If s != &not_found, s is a valid result string as follows:
03015     * s = NULL if the variable does not have a value;
03016     * you typically do this when looking for an unset predefined variable.
03017     * s = workspace if the result has been assembled there;
03018     * typically done when the result is built e.g. with an snprintf(),
03019     * so we don't need to do an additional copy.
03020     * s != workspace in case we have a string, that needs to be copied
03021     * (the ast_copy_string is done once for all at the end).
03022     * Typically done when the result is already available in some string.
03023     */
03024    s = &not_found;   /* default value */
03025    if (c) { /* This group requires a valid channel */
03026       /* Names with common parts are looked up a piece at a time using strncmp. */
03027       if (!strncmp(var, "CALL", 4)) {
03028          if (!strncmp(var + 4, "ING", 3)) {
03029             if (!strcmp(var + 7, "PRES")) {        /* CALLINGPRES */
03030                ast_str_set(str, maxlen, "%d",
03031                   ast_party_id_presentation(&c->caller.id));
03032                s = ast_str_buffer(*str);
03033             } else if (!strcmp(var + 7, "ANI2")) {    /* CALLINGANI2 */
03034                ast_str_set(str, maxlen, "%d", c->caller.ani2);
03035                s = ast_str_buffer(*str);
03036             } else if (!strcmp(var + 7, "TON")) {     /* CALLINGTON */
03037                ast_str_set(str, maxlen, "%d", c->caller.id.number.plan);
03038                s = ast_str_buffer(*str);
03039             } else if (!strcmp(var + 7, "TNS")) {     /* CALLINGTNS */
03040                ast_str_set(str, maxlen, "%d", c->dialed.transit_network_select);
03041                s = ast_str_buffer(*str);
03042             }
03043          }
03044       } else if (!strcmp(var, "HINT")) {
03045          s = ast_str_get_hint(str, maxlen, NULL, 0, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL;
03046       } else if (!strcmp(var, "HINTNAME")) {
03047          s = ast_str_get_hint(NULL, 0, str, maxlen, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL;
03048       } else if (!strcmp(var, "EXTEN")) {
03049          s = c->exten;
03050       } else if (!strcmp(var, "CONTEXT")) {
03051          s = c->context;
03052       } else if (!strcmp(var, "PRIORITY")) {
03053          ast_str_set(str, maxlen, "%d", c->priority);
03054          s = ast_str_buffer(*str);
03055       } else if (!strcmp(var, "CHANNEL")) {
03056          s = c->name;
03057       } else if (!strcmp(var, "UNIQUEID")) {
03058          s = c->uniqueid;
03059       } else if (!strcmp(var, "HANGUPCAUSE")) {
03060          ast_str_set(str, maxlen, "%d", c->hangupcause);
03061          s = ast_str_buffer(*str);
03062       }
03063    }
03064    if (s == &not_found) { /* look for more */
03065       if (!strcmp(var, "EPOCH")) {
03066          ast_str_set(str, maxlen, "%u", (int) time(NULL));
03067          s = ast_str_buffer(*str);
03068       } else if (!strcmp(var, "SYSTEMNAME")) {
03069          s = ast_config_AST_SYSTEM_NAME;
03070       } else if (!strcmp(var, "ENTITYID")) {
03071          char workspace[20];
03072          ast_eid_to_str(workspace, sizeof(workspace), &ast_eid_default);
03073          s = workspace;
03074       }
03075    }
03076    /* if not found, look into chanvars or global vars */
03077    for (i = 0; s == &not_found && i < ARRAY_LEN(places); i++) {
03078       struct ast_var_t *variables;
03079       if (!places[i])
03080          continue;
03081       if (places[i] == &globals)
03082          ast_rwlock_rdlock(&globalslock);
03083       AST_LIST_TRAVERSE(places[i], variables, entries) {
03084          if (!strcasecmp(ast_var_name(variables), var)) {
03085             s = ast_var_value(variables);
03086             break;
03087          }
03088       }
03089       if (places[i] == &globals)
03090          ast_rwlock_unlock(&globalslock);
03091    }
03092    if (s == &not_found || s == NULL) {
03093       ast_debug(5, "Result of '%s' is NULL\n", var);
03094       ret = NULL;
03095    } else {
03096       ast_debug(5, "Result of '%s' is '%s'\n", var, s);
03097       if (s != ast_str_buffer(*str)) {
03098          ast_str_set(str, maxlen, "%s", s);
03099       }
03100       ret = ast_str_buffer(*str);
03101       if (need_substring) {
03102          ret = ast_str_substring(*str, offset, length);
03103          ast_debug(2, "Final result of '%s' is '%s'\n", var, ret);
03104       }
03105    }
03106 
03107    if (c) {
03108       ast_channel_unlock(c);
03109    }
03110    return ret;
03111 }

void ast_str_substitute_variables ( struct ast_str **  buf,
ssize_t  maxlen,
struct ast_channel chan,
const char *  templ 
)

Parameters:
buf Result will be placed in this buffer.
maxlen -1 if the buffer should not grow, 0 if the buffer may grow to any size, and >0 if the buffer should grow only to that number of bytes.
chan Channel variables from which to extract values, and channel to pass to any dialplan functions.
templ Variable template to expand.

Definition at line 3765 of file pbx.c.

References ast_str_substitute_variables_full().

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

03766 {
03767    size_t used;
03768    ast_str_substitute_variables_full(buf, maxlen, chan, NULL, templ, &used);
03769 }

void ast_str_substitute_variables_full ( struct ast_str **  buf,
ssize_t  maxlen,
struct ast_channel c,
struct varshead headp,
const char *  templ,
size_t *  used 
)

Parameters:
buf Result will be placed in this buffer.
maxlen -1 if the buffer should not grow, 0 if the buffer may grow to any size, and >0 if the buffer should grow only to that number of bytes.
c Channel variables from which to extract values, and channel to pass to any dialplan functions.
headp If no channel is specified, a channel list from which to extract variable values
templ Variable template to expand.
used Number of bytes read from the template.

Definition at line 3589 of file pbx.c.

References ast_channel_release(), ast_debug, ast_dummy_channel_alloc(), ast_free, ast_func_read2(), ast_log(), ast_str_append(), ast_str_append_substr(), ast_str_buffer(), ast_str_create(), ast_str_expr(), ast_str_reset(), ast_str_retrieve_variable(), ast_str_set_substr(), ast_str_strlen(), ast_str_substitute_variables_full(), ast_str_substring(), ast_strlen_zero(), len(), LOG_ERROR, LOG_WARNING, parse_variable_name(), and ast_channel::varshead.

Referenced by ast_str_substitute_variables(), ast_str_substitute_variables_full(), and ast_str_substitute_variables_varshead().

03590 {
03591    /* Substitutes variables into buf, based on string templ */
03592    char *cp4 = NULL;
03593    const char *tmp, *whereweare;
03594    int orig_size = 0;
03595    int offset, offset2, isfunction;
03596    const char *nextvar, *nextexp, *nextthing;
03597    const char *vars, *vare;
03598    char *finalvars;
03599    int pos, brackets, needsub, len;
03600    struct ast_str *substr1 = ast_str_create(16), *substr2 = NULL, *substr3 = ast_str_create(16);
03601 
03602    ast_str_reset(*buf);
03603    whereweare = tmp = templ;
03604    while (!ast_strlen_zero(whereweare)) {
03605       /* Assume we're copying the whole remaining string */
03606       pos = strlen(whereweare);
03607       nextvar = NULL;
03608       nextexp = NULL;
03609       nextthing = strchr(whereweare, '$');
03610       if (nextthing) {
03611          switch (nextthing[1]) {
03612          case '{':
03613             nextvar = nextthing;
03614             pos = nextvar - whereweare;
03615             break;
03616          case '[':
03617             nextexp = nextthing;
03618             pos = nextexp - whereweare;
03619             break;
03620          default:
03621             pos = 1;
03622          }
03623       }
03624 
03625       if (pos) {
03626          /* Copy that many bytes */
03627          ast_str_append_substr(buf, maxlen, whereweare, pos);
03628 
03629          templ += pos;
03630          whereweare += pos;
03631       }
03632 
03633       if (nextvar) {
03634          /* We have a variable.  Find the start and end, and determine
03635             if we are going to have to recursively call ourselves on the
03636             contents */
03637          vars = vare = nextvar + 2;
03638          brackets = 1;
03639          needsub = 0;
03640 
03641          /* Find the end of it */
03642          while (brackets && *vare) {
03643             if ((vare[0] == '$') && (vare[1] == '{')) {
03644                needsub++;
03645             } else if (vare[0] == '{') {
03646                brackets++;
03647             } else if (vare[0] == '}') {
03648                brackets--;
03649             } else if ((vare[0] == '$') && (vare[1] == '['))
03650                needsub++;
03651             vare++;
03652          }
03653          if (brackets)
03654             ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n");
03655          len = vare - vars - 1;
03656 
03657          /* Skip totally over variable string */
03658          whereweare += (len + 3);
03659 
03660          /* Store variable name (and truncate) */
03661          ast_str_set_substr(&substr1, 0, vars, len);
03662          ast_debug(5, "Evaluating '%s' (from '%s' len %d)\n", ast_str_buffer(substr1), vars, len);
03663 
03664          /* Substitute if necessary */
03665          if (needsub) {
03666             size_t used;
03667             if (!substr2) {
03668                substr2 = ast_str_create(16);
03669             }
03670 
03671             ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used);
03672             finalvars = ast_str_buffer(substr2);
03673          } else {
03674             finalvars = ast_str_buffer(substr1);
03675          }
03676 
03677          parse_variable_name(finalvars, &offset, &offset2, &isfunction);
03678          if (isfunction) {
03679             /* Evaluate function */
03680             if (c || !headp) {
03681                cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3);
03682             } else {
03683                struct varshead old;
03684                struct ast_channel *bogus = ast_dummy_channel_alloc();
03685                if (bogus) {
03686                   memcpy(&old, &bogus->varshead, sizeof(old));
03687                   memcpy(&bogus->varshead, headp, sizeof(bogus->varshead));
03688                   cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3);
03689                   /* Don't deallocate the varshead that was passed in */
03690                   memcpy(&bogus->varshead, &old, sizeof(bogus->varshead));
03691                   ast_channel_release(bogus);
03692                } else {
03693                   ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution.  Function results may be blank.\n");
03694                }
03695             }
03696             ast_debug(2, "Function result is '%s'\n", cp4 ? cp4 : "(null)");
03697          } else {
03698             /* Retrieve variable value */
03699             ast_str_retrieve_variable(&substr3, 0, c, headp, finalvars);
03700             cp4 = ast_str_buffer(substr3);
03701          }
03702          if (cp4) {
03703             ast_str_substring(substr3, offset, offset2);
03704             ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3));
03705          }
03706       } else if (nextexp) {
03707          /* We have an expression.  Find the start and end, and determine
03708             if we are going to have to recursively call ourselves on the
03709             contents */
03710          vars = vare = nextexp + 2;
03711          brackets = 1;
03712          needsub = 0;
03713 
03714          /* Find the end of it */
03715          while (brackets && *vare) {
03716             if ((vare[0] == '$') && (vare[1] == '[')) {
03717                needsub++;
03718                brackets++;
03719                vare++;
03720             } else if (vare[0] == '[') {
03721                brackets++;
03722             } else if (vare[0] == ']') {
03723                brackets--;
03724             } else if ((vare[0] == '$') && (vare[1] == '{')) {
03725                needsub++;
03726                vare++;
03727             }
03728             vare++;
03729          }
03730          if (brackets)
03731             ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n");
03732          len = vare - vars - 1;
03733 
03734          /* Skip totally over expression */
03735          whereweare += (len + 3);
03736 
03737          /* Store variable name (and truncate) */
03738          ast_str_set_substr(&substr1, 0, vars, len);
03739 
03740          /* Substitute if necessary */
03741          if (needsub) {
03742             size_t used;
03743             if (!substr2) {
03744                substr2 = ast_str_create(16);
03745             }
03746 
03747             ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used);
03748             finalvars = ast_str_buffer(substr2);
03749          } else {
03750             finalvars = ast_str_buffer(substr1);
03751          }
03752 
03753          if (ast_str_expr(&substr3, 0, c, finalvars)) {
03754             ast_debug(2, "Expression result is '%s'\n", ast_str_buffer(substr3));
03755          }
03756          ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3));
03757       }
03758    }
03759    *used = ast_str_strlen(*buf) - orig_size;
03760    ast_free(substr1);
03761    ast_free(substr2);
03762    ast_free(substr3);
03763 }

void ast_str_substitute_variables_varshead ( struct ast_str **  buf,
ssize_t  maxlen,
struct varshead headp,
const char *  templ 
)

Parameters:
buf Result will be placed in this buffer.
maxlen -1 if the buffer should not grow, 0 if the buffer may grow to any size, and >0 if the buffer should grow only to that number of bytes.
headp If no channel is specified, a channel list from which to extract variable values
templ Variable template to expand.

Definition at line 3771 of file pbx.c.

References ast_str_substitute_variables_full().

Referenced by add_user_extension(), build_user_routes(), phoneprov_callback(), pp_each_extension_helper(), and pp_each_user_helper().

03772 {
03773    size_t used;
03774    ast_str_substitute_variables_full(buf, maxlen, NULL, headp, templ, &used);
03775 }

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

Definition at line 2922 of file pbx.c.

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

Referenced by ast_str_retrieve_variable(), and ast_str_substitute_variables_full().

02923 {
02924    int lr;  /* length of the input string after the copy */
02925 
02926    lr = ast_str_strlen(value); /* compute length after copy, so we never go out of the workspace */
02927 
02928    /* Quick check if no need to do anything */
02929    if (offset == 0 && length >= lr) /* take the whole string */
02930       return ast_str_buffer(value);
02931 
02932    if (offset < 0)   {  /* translate negative offset into positive ones */
02933       offset = lr + offset;
02934       if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */
02935          offset = 0;
02936    }
02937 
02938    /* too large offset result in empty string so we know what to return */
02939    if (offset >= lr) {
02940       ast_str_reset(value);
02941       return ast_str_buffer(value);
02942    }
02943 
02944    if (offset > 0) {
02945       /* Go ahead and chop off the beginning */
02946       memmove(ast_str_buffer(value), ast_str_buffer(value) + offset, ast_str_strlen(value) - offset + 1);
02947       lr -= offset;
02948    }
02949 
02950    if (length >= 0 && length < lr) {   /* truncate if necessary */
02951       char *tmp = ast_str_buffer(value);
02952       tmp[length] = '\0';
02953       ast_str_update(value);
02954    } else if (length < 0) {
02955       if (lr > -length) { /* After we remove from the front and from the rear, is there anything left? */
02956          char *tmp = ast_str_buffer(value);
02957          tmp[lr + length] = '\0';
02958          ast_str_update(value);
02959       } else {
02960          ast_str_reset(value);
02961       }
02962    } else {
02963       /* Nothing to do, but update the buffer length */
02964       ast_str_update(value);
02965    }
02966 
02967    return ast_str_buffer(value);
02968 }

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

09933 {
09934    return ast_rwlock_unlock(&con->lock);
09935 }

int ast_unlock_contexts ( void   ) 

Unlocks contexts.

Return values:
0 on success
-1 on failure

Definition at line 9914 of file pbx.c.

References ast_mutex_unlock, and conlock.

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

09915 {
09916    return ast_mutex_unlock(&conlock);
09917 }

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

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

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

06828 {
06829    struct ast_app *tmp;
06830 
06831    AST_RWLIST_WRLOCK(&apps);
06832    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, tmp, list) {
06833       if (!strcasecmp(app, tmp->name)) {
06834          unreference_cached_app(tmp);
06835          AST_RWLIST_REMOVE_CURRENT(list);
06836          ast_verb(2, "Unregistered application '%s'\n", tmp->name);
06837          ast_string_field_free_memory(tmp);
06838          ast_free(tmp);
06839          break;
06840       }
06841    }
06842    AST_RWLIST_TRAVERSE_SAFE_END;
06843    AST_RWLIST_UNLOCK(&apps);
06844 
06845    return tmp ? 0 : -1;
06846 }

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

05610 {
05611    AST_RWLIST_WRLOCK(&switches);
05612    AST_RWLIST_REMOVE(&switches, sw, list);
05613    AST_RWLIST_UNLOCK(&switches);
05614 }

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

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

10048 {
10049    if (!exten)
10050       return con ? con->root : NULL;
10051    else
10052       return exten->next;
10053 }

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

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

10081 {
10082    if (!ip)
10083       return con ? con->ignorepats : NULL;
10084    else
10085       return ip->next;
10086 }

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

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

10072 {
10073    if (!inc)
10074       return con ? con->includes : NULL;
10075    else
10076       return inc->next;
10077 }

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

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

10057 {
10058    if (!sw)
10059       return con ? AST_LIST_FIRST(&con->alts) : NULL;
10060    else
10061       return AST_LIST_NEXT(sw, list);
10062 }

struct ast_context* ast_walk_contexts ( struct ast_context con  ) 

Definition at line 10041 of file pbx.c.

References contexts, and ast_context::next.

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

10042 {
10043    return con ? con->next : contexts;
10044 }

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

Definition at line 10064 of file pbx.c.

References exten, and ast_exten::priority.

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

10066 {
10067    return priority ? priority->peer : exten;
10068 }

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

09923 {
09924    return ast_rwlock_wrlock(&con->lock);
09925 }

int ast_wrlock_contexts ( void   ) 

Write locks the context list.

Return values:
0 on success
-1 on error

Definition at line 9904 of file pbx.c.

References ast_mutex_lock, and conlock.

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

09905 {
09906    return ast_mutex_lock(&conlock);
09907 }

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

Definition at line 8287 of file pbx.c.

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

Referenced by ast_pbx_outgoing_app(), and ast_pbx_outgoing_exten().

08288 {
08289    struct async_stat *as = data;
08290    struct ast_channel *chan = as->chan;
08291    int timeout = as->timeout;
08292    int res;
08293    struct ast_frame *f;
08294    struct ast_app *app;
08295 
08296    while (timeout && (chan->_state != AST_STATE_UP)) {
08297       res = ast_waitfor(chan, timeout);
08298       if (res < 1)
08299          break;
08300       if (timeout > -1)
08301          timeout = res;
08302       f = ast_read(chan);
08303       if (!f)
08304          break;
08305       if (f->frametype == AST_FRAME_CONTROL) {
08306          if ((f->subclass.integer == AST_CONTROL_BUSY)  ||
08307              (f->subclass.integer == AST_CONTROL_CONGESTION) ) {
08308             ast_frfree(f);
08309             break;
08310          }
08311       }
08312       ast_frfree(f);
08313    }
08314    if (chan->_state == AST_STATE_UP) {
08315       if (!ast_strlen_zero(as->app)) {
08316          app = pbx_findapp(as->app);
08317          if (app) {
08318             ast_verb(3, "Launching %s(%s) on %s\n", as->app, as->appdata, chan->name);
08319             pbx_exec(chan, app, as->appdata);
08320          } else
08321             ast_log(LOG_WARNING, "No such application '%s'\n", as->app);
08322       } else {
08323          if (!ast_strlen_zero(as->context))
08324             ast_copy_string(chan->context, as->context, sizeof(chan->context));
08325          if (!ast_strlen_zero(as->exten))
08326             ast_copy_string(chan->exten, as->exten, sizeof(chan->exten));
08327          if (as->priority > 0)
08328             chan->priority = as->priority;
08329          /* Run the PBX */
08330          if (ast_pbx_run(chan)) {
08331             ast_log(LOG_ERROR, "Failed to start PBX on %s\n", chan->name);
08332          } else {
08333             /* PBX will have taken care of this */
08334             chan = NULL;
08335          }
08336       }
08337    }
08338    ast_free(as);
08339    if (chan)
08340       ast_hangup(chan);
08341    return NULL;
08342 }

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

Definition at line 1585 of file pbx.c.

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

Referenced by show_debug_helper().

01586 {
01587    char extenstr[40];
01588    struct ast_str *my_prefix = ast_str_alloca(1024);
01589 
01590    extenstr[0] = '\0';
01591 
01592    if (node && node->exten)
01593       snprintf(extenstr, sizeof(extenstr), "(%p)", node->exten);
01594 
01595    if (strlen(node->x) > 1) {
01596       ast_cli(fd, "%s[%s]:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N',
01597          node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "",
01598          node->exten ? node->exten->exten : "", extenstr);
01599    } else {
01600       ast_cli(fd, "%s%s:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N',
01601          node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "",
01602          node->exten ? node->exten->exten : "", extenstr);
01603    }
01604 
01605    ast_str_set(&my_prefix, 0, "%s+       ", prefix);
01606 
01607    if (node->next_char)
01608       cli_match_char_tree(node->next_char, ast_str_buffer(my_prefix), fd);
01609 
01610    if (node->alt_char)
01611       cli_match_char_tree(node->alt_char, prefix, fd);
01612 }

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

collect digits from the channel into the buffer.

Parameters:
c,buf,buflen,pos 
waittime is in milliseconds
Return values:
0 on timeout or done.
-1 on error.

Definition at line 4624 of file pbx.c.

References ast_channel::_softhangup, ast_matchmore_extension(), AST_SOFTHANGUP_ASYNCGOTO, ast_waitfordigit(), ast_channel::caller, ast_channel::context, ast_pbx::dtimeoutms, ast_party_caller::id, ast_party_id::number, ast_channel::pbx, S_COR, ast_party_number::str, and ast_party_number::valid.

04625 {
04626    int digit;
04627 
04628    buf[pos] = '\0';  /* make sure it is properly terminated */
04629    while (ast_matchmore_extension(c, c->context, buf, 1,
04630       S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
04631       /* As long as we're willing to wait, and as long as it's not defined,
04632          keep reading digits until we can't possibly get a right answer anymore.  */
04633       digit = ast_waitfordigit(c, waittime);
04634       if (c->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) {
04635          c->_softhangup &= ~AST_SOFTHANGUP_ASYNCGOTO;
04636       } else {
04637          if (!digit) /* No entry */
04638             break;
04639          if (digit < 0) /* Error, maybe a  hangup */
04640             return -1;
04641          if (pos < buflen - 1) { /* XXX maybe error otherwise ? */
04642             buf[pos++] = digit;
04643             buf[pos] = '\0';
04644          }
04645          waittime = c->pbx->dtimeoutms;
04646       }
04647    }
04648    return 0;
04649 }

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

Definition at line 1033 of file pbx.c.

Referenced by add_exten_to_pattern_tree().

01034 {
01035    const char *ac = a;
01036    const char *bc = b;
01037    if ((*ac) < (*bc))
01038       return -1;
01039    else if ((*ac) == (*bc))
01040       return 0;
01041    else
01042       return 1;
01043 }

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

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_get_extension_name(), ast_strdup, ast_hint::exten, and hints.

Referenced by handle_show_hint().

05795 {
05796    struct ast_hint *hint;
05797    char *ret = NULL;
05798    int which = 0;
05799    int wordlen;
05800    struct ao2_iterator i;
05801 
05802    if (pos != 3)
05803       return NULL;
05804 
05805    wordlen = strlen(word);
05806 
05807    /* walk through all hints */
05808    i = ao2_iterator_init(hints, 0);
05809    for (hint = ao2_iterator_next(&i); hint; ao2_unlock(hint), ao2_ref(hint, -1), hint = ao2_iterator_next(&i)) {
05810       ao2_lock(hint);
05811       if (!strncasecmp(word, hint->exten ? ast_get_extension_name(hint->exten) : "", wordlen) && ++which > state) {
05812          ret = ast_strdup(ast_get_extension_name(hint->exten));
05813          ao2_unlock(hint);
05814          break;
05815       }
05816    }
05817    ao2_iterator_destroy(&i);
05818 
05819    return ret;
05820 }

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

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

05997 {
05998    struct ast_context *c = NULL;
05999    char *ret = NULL;
06000    int which = 0;
06001    int wordlen;
06002 
06003    /* we are do completion of [exten@]context on second position only */
06004    if (pos != 2)
06005       return NULL;
06006 
06007    ast_rdlock_contexts();
06008 
06009    wordlen = strlen(word);
06010 
06011    /* walk through all contexts and return the n-th match */
06012    while ( (c = ast_walk_contexts(c)) ) {
06013       if (!strncasecmp(word, ast_get_context_name(c), wordlen) && ++which > state) {
06014          ret = ast_strdup(ast_get_context_name(c));
06015          break;
06016       }
06017    }
06018 
06019    ast_unlock_contexts();
06020 
06021    return ret;
06022 }

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

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

06964 {
06965    struct ast_context *new = ast_hashtab_lookup(exttable, context); /* is there a match in the new set? */
06966    struct ast_exten *exten_item, *prio_item, *new_exten_item, *new_prio_item;
06967    struct ast_hashtab_iter *exten_iter;
06968    struct ast_hashtab_iter *prio_iter;
06969    int insert_count = 0;
06970    int first = 1;
06971 
06972    /* We'll traverse all the extensions/prios, and see which are not registrar'd with
06973       the current registrar, and copy them to the new context. If the new context does not
06974       exist, we'll create it "on demand". If no items are in this context to copy, then we'll
06975       only create the empty matching context if the old one meets the criteria */
06976 
06977    if (context->root_table) {
06978       exten_iter = ast_hashtab_start_traversal(context->root_table);
06979       while ((exten_item=ast_hashtab_next(exten_iter))) {
06980          if (new) {
06981             new_exten_item = ast_hashtab_lookup(new->root_table, exten_item);
06982          } else {
06983             new_exten_item = NULL;
06984          }
06985          prio_iter = ast_hashtab_start_traversal(exten_item->peer_table);
06986          while ((prio_item=ast_hashtab_next(prio_iter))) {
06987             int res1;
06988             char *dupdstr;
06989 
06990             if (new_exten_item) {
06991                new_prio_item = ast_hashtab_lookup(new_exten_item->peer_table, prio_item);
06992             } else {
06993                new_prio_item = NULL;
06994             }
06995             if (strcmp(prio_item->registrar,registrar) == 0) {
06996                continue;
06997             }
06998             /* make sure the new context exists, so we have somewhere to stick this exten/prio */
06999             if (!new) {
07000                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 */
07001             }
07002 
07003             /* copy in the includes, switches, and ignorepats */
07004             if (first) { /* but, only need to do this once */
07005                context_merge_incls_swits_igps_other_registrars(new, context, registrar);
07006                first = 0;
07007             }
07008 
07009             if (!new) {
07010                ast_log(LOG_ERROR,"Could not allocate a new context for %s in merge_and_delete! Danger!\n", context->name);
07011                return; /* no sense continuing. */
07012             }
07013             /* we will not replace existing entries in the new context with stuff from the old context.
07014                but, if this is because of some sort of registrar conflict, we ought to say something... */
07015 
07016             dupdstr = ast_strdup(prio_item->data);
07017 
07018             res1 = ast_add_extension2(new, 0, prio_item->exten, prio_item->priority, prio_item->label, 
07019                                 prio_item->matchcid ? prio_item->cidmatch : NULL, prio_item->app, dupdstr, prio_item->datad, prio_item->registrar);
07020             if (!res1 && new_exten_item && new_prio_item){
07021                ast_verb(3,"Dropping old dialplan item %s/%s/%d [%s(%s)] (registrar=%s) due to conflict with new dialplan\n",
07022                      context->name, prio_item->exten, prio_item->priority, prio_item->app, (char*)prio_item->data, prio_item->registrar);
07023             } else {
07024                /* 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,
07025                 and no double frees take place, either! */
07026                insert_count++;
07027             }
07028          }
07029          ast_hashtab_end_traversal(prio_iter);
07030       }
07031       ast_hashtab_end_traversal(exten_iter);
07032    }
07033 
07034    if (!insert_count && !new && (strcmp(context->registrar, registrar) != 0 ||
07035         (strcmp(context->registrar, registrar) == 0 && context->refcount > 1))) {
07036       /* we could have given it the registrar of the other module who incremented the refcount,
07037          but that's not available, so we give it the registrar we know about */
07038       new = ast_context_find_or_create(extcontexts, exttable, context->name, context->registrar);
07039 
07040       /* copy in the includes, switches, and ignorepats */
07041       context_merge_incls_swits_igps_other_registrars(new, context, registrar);
07042    }
07043 }

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

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

06931 {
06932    struct ast_include *i;
06933    struct ast_ignorepat *ip;
06934    struct ast_sw *sw;
06935 
06936    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);
06937    /* copy in the includes, switches, and ignorepats */
06938    /* walk through includes */
06939    for (i = NULL; (i = ast_walk_context_includes(old, i)) ; ) {
06940       if (strcmp(ast_get_include_registrar(i), registrar) == 0)
06941          continue; /* not mine */
06942       ast_context_add_include2(new, ast_get_include_name(i), ast_get_include_registrar(i));
06943    }
06944 
06945    /* walk through switches */
06946    for (sw = NULL; (sw = ast_walk_context_switches(old, sw)) ; ) {
06947       if (strcmp(ast_get_switch_registrar(sw), registrar) == 0)
06948          continue; /* not mine */
06949       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));
06950    }
06951 
06952    /* walk thru ignorepats ... */
06953    for (ip = NULL; (ip = ast_walk_context_ignorepats(old, ip)); ) {
06954       if (strcmp(ast_get_ignorepat_registrar(ip), registrar) == 0)
06955          continue; /* not mine */
06956       ast_context_add_ignorepat2(new, ast_get_ignorepat_name(ip), ast_get_ignorepat_registrar(ip));
06957    }
06958 }

static void create_match_char_tree ( struct ast_context con  )  [static]

Definition at line 2085 of file pbx.c.

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

Referenced by pbx_find_extension().

02086 {
02087    struct ast_hashtab_iter *t1;
02088    struct ast_exten *e1;
02089 #ifdef NEED_DEBUG
02090    int biggest_bucket, resizes, numobjs, numbucks;
02091 
02092    ast_log(LOG_DEBUG,"Creating Extension Trie for context %s(%p)\n", con->name, con);
02093    ast_hashtab_get_stats(con->root_table, &biggest_bucket, &resizes, &numobjs, &numbucks);
02094    ast_log(LOG_DEBUG,"This tree has %d objects in %d bucket lists, longest list=%d objects, and has resized %d times\n",
02095          numobjs, numbucks, biggest_bucket, resizes);
02096 #endif
02097    t1 = ast_hashtab_start_traversal(con->root_table);
02098    while ((e1 = ast_hashtab_next(t1))) {
02099       if (e1->exten) {
02100          add_exten_to_pattern_tree(con, e1, 0);
02101       } else {
02102          ast_log(LOG_ERROR, "Attempt to create extension with no extension name.\n");
02103       }
02104    }
02105    ast_hashtab_end_traversal(t1);
02106 }

static void decrease_call_count ( void   )  [static]

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

04981 {
04982    ast_mutex_lock(&maxcalllock);
04983    if (countcalls > 0)
04984       countcalls--;
04985    ast_mutex_unlock(&maxcalllock);
04986 }

static void destroy_exten ( struct ast_exten e  )  [static]

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

04989 {
04990    if (e->priority == PRIORITY_HINT)
04991       ast_remove_hint(e);
04992 
04993    if (e->peer_table)
04994       ast_hashtab_destroy(e->peer_table,0);
04995    if (e->peer_label_table)
04996       ast_hashtab_destroy(e->peer_label_table, 0);
04997    if (e->datad)
04998       e->datad(e->data);
04999    ast_free(e);
05000 }

static void destroy_pattern_tree ( struct match_char pattern_tree  )  [static]

Definition at line 2108 of file pbx.c.

References match_char::alt_char, ast_free, match_char::exten, and match_char::next_char.

Referenced by __ast_internal_context_destroy().

02109 {
02110    /* destroy all the alternates */
02111    if (pattern_tree->alt_char) {
02112       destroy_pattern_tree(pattern_tree->alt_char);
02113       pattern_tree->alt_char = 0;
02114    }
02115    /* destroy all the nexts */
02116    if (pattern_tree->next_char) {
02117       destroy_pattern_tree(pattern_tree->next_char);
02118       pattern_tree->next_char = 0;
02119    }
02120    pattern_tree->exten = 0; /* never hurts to make sure there's no pointers laying around */
02121    ast_free(pattern_tree);
02122 }

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

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

09796 {
09797    const char *device;
09798    struct statechange *sc;
09799 
09800    device = ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE);
09801    if (ast_strlen_zero(device)) {
09802       ast_log(LOG_ERROR, "Received invalid event that had no device IE\n");
09803       return;
09804    }
09805 
09806    if (!(sc = ast_calloc(1, sizeof(*sc) + strlen(device) + 1)))
09807       return;
09808    strcpy(sc->dev, device);
09809    if (ast_taskprocessor_push(device_state_tps, handle_statechange, sc) < 0) {
09810       ast_free(sc);
09811    }
09812 }

static void exception_store_free ( void *  data  )  [static]

Definition at line 3113 of file pbx.c.

References ast_free, and ast_string_field_free_memory.

03114 {
03115    struct pbx_exception *exception = data;
03116    ast_string_field_free_memory(exception);
03117    ast_free(exception);
03118 }

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

the full routine to compare extensions in rules.

Definition at line 2258 of file pbx.c.

References ext_cmp1().

Referenced by ast_add_extension2_lockopt(), and ast_extension_cmp().

02259 {
02260    /* make sure non-patterns come first.
02261     * If a is not a pattern, it either comes first or
02262     * we do a more complex pattern comparison.
02263     */
02264    int ret = 0;
02265 
02266    if (a[0] != '_')
02267       return (b[0] == '_') ? -1 : strcmp(a, b);
02268 
02269    /* Now we know a is a pattern; if b is not, a comes first */
02270    if (b[0] != '_')
02271       return 1;
02272 
02273    /* ok we need full pattern sorting routine.
02274     * skip past the underscores */
02275    ++a; ++b;
02276    do {
02277       unsigned char bitwise[2][32] = { { 0, } };
02278       ret = ext_cmp1(&a, bitwise[0]) - ext_cmp1(&b, bitwise[1]);
02279       if (ret == 0) {
02280          /* Are the classes different, even though they score the same? */
02281          ret = memcmp(bitwise[0], bitwise[1], 32);
02282       }
02283    } while (!ret && a && b);
02284    if (ret == 0) {
02285       return 0;
02286    } else {
02287       return (ret > 0) ? 1 : -1;
02288    }
02289 }

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

References ast_log(), and LOG_WARNING.

Referenced by ext_cmp().

02179 {
02180    int c, cmin = 0xff, count = 0;
02181    const char *end;
02182 
02183    /* load value and advance pointer */
02184    c = *(*p)++;
02185 
02186    /* always return unless we have a set of chars */
02187    switch (toupper(c)) {
02188    default: /* ordinary character */
02189       bitwise[c / 8] = 1 << (c % 8);
02190       return 0x0100 | (c & 0xff);
02191 
02192    case 'N':   /* 2..9 */
02193       bitwise[6] = 0xfc;
02194       bitwise[7] = 0x03;
02195       return 0x0800 | '2';
02196 
02197    case 'X':   /* 0..9 */
02198       bitwise[6] = 0xff;
02199       bitwise[7] = 0x03;
02200       return 0x0A00 | '0';
02201 
02202    case 'Z':   /* 1..9 */
02203       bitwise[6] = 0xfe;
02204       bitwise[7] = 0x03;
02205       return 0x0900 | '1';
02206 
02207    case '.':   /* wildcard */
02208       return 0x18000;
02209 
02210    case '!':   /* earlymatch */
02211       return 0x28000;   /* less specific than NULL */
02212 
02213    case '\0':  /* empty string */
02214       *p = NULL;
02215       return 0x30000;
02216 
02217    case '[':   /* pattern */
02218       break;
02219    }
02220    /* locate end of set */
02221    end = strchr(*p, ']');
02222 
02223    if (end == NULL) {
02224       ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n");
02225       return 0x40000;   /* XXX make this entry go last... */
02226    }
02227 
02228    for (; *p < end  ; (*p)++) {
02229       unsigned char c1, c2;   /* first-last char in range */
02230       c1 = (unsigned char)((*p)[0]);
02231       if (*p + 2 < end && (*p)[1] == '-') { /* this is a range */
02232          c2 = (unsigned char)((*p)[2]);
02233          *p += 2;    /* skip a total of 3 chars */
02234       } else {        /* individual character */
02235          c2 = c1;
02236       }
02237       if (c1 < cmin) {
02238          cmin = c1;
02239       }
02240       for (; c1 <= c2; c1++) {
02241          unsigned char mask = 1 << (c1 % 8);
02242          /*!\note If two patterns score the same, the one with the lowest
02243           * ascii values will compare as coming first. */
02244          /* Flag the character as included (used) and count it. */
02245          if (!(bitwise[ c1 / 8 ] & mask)) {
02246             bitwise[ c1 / 8 ] |= mask;
02247             count += 0x100;
02248          }
02249       }
02250    }
02251    (*p)++;
02252    return count == 0 ? 0x30000 : (count | cmin);
02253 }

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

copy a string skipping whitespace

Definition at line 7844 of file pbx.c.

Referenced by ast_add_extension2_lockopt().

07845 {
07846    int count = 0;
07847    int insquares = 0;
07848 
07849    while (*src && (count < len - 1)) {
07850       if (*src == '[') {
07851          insquares = 1;
07852       } else if (*src == ']') {
07853          insquares = 0;
07854       } else if (*src == ' ' && !insquares) {
07855          src++;
07856          continue;
07857       }
07858       *dst = *src;
07859       dst++;
07860       src++;
07861       count++;
07862    }
07863    *dst = '\0';
07864 
07865    return count;
07866 }

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

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

02472 {
02473    int i;
02474    static int prof_id = -2;   /* marker for 'unallocated' id */
02475    if (prof_id == -2) {
02476       prof_id = ast_add_profile("ext_match", 0);
02477    }
02478    ast_mark(prof_id, 1);
02479    i = _extension_match_core(pattern, data, mode);
02480    ast_mark(prof_id, 0);
02481    return i;
02482 }

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

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

05105 {
05106    struct ast_context *c = NULL;
05107    struct fake_context item;
05108 
05109    ast_copy_string(item.name, context, sizeof(item.name));
05110 
05111    c = ast_hashtab_lookup(contexts_table,&item);
05112 
05113    return c;
05114 }

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

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

Referenced by ast_add_extension(), ast_context_add_ignorepat(), ast_context_add_include(), ast_context_add_switch(), ast_context_remove_extension_callerid(), ast_context_remove_ignorepat(), ast_context_remove_include(), and ast_context_remove_switch().

05122 {
05123    struct ast_context *c = NULL;
05124    struct fake_context item;
05125 
05126    ast_copy_string(item.name, context, sizeof(item.name));
05127 
05128    ast_rdlock_contexts();
05129    c = ast_hashtab_lookup(contexts_table,&item);
05130 
05131    if (!c)
05132       ast_unlock_contexts();
05133 
05134    return c;
05135 }

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

Remove a watcher from the callback list.

Definition at line 4388 of file pbx.c.

References AST_LIST_TRAVERSE, ast_hint::callbacks, CMP_MATCH, CMP_STOP, ast_state_cb::entry, and ast_state_cb::id.

Referenced by ast_extension_state_del().

04389 {
04390    const struct ast_hint *hint = obj;
04391    int *id = arg;
04392    struct ast_state_cb *cb;
04393 
04394    AST_LIST_TRAVERSE(&hint->callbacks, cb, entry) {
04395       if (cb->id == *id) {
04396          return CMP_MATCH | CMP_STOP;
04397       }
04398    }
04399 
04400    return 0;
04401 }

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

References args, ast_log(), and LOG_WARNING.

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

03466 {
03467    char *args = strchr(function, '(');
03468 
03469    if (!args) {
03470       ast_log(LOG_WARNING, "Function '%s' doesn't contain parentheses.  Assuming null argument.\n", function);
03471    } else {
03472       char *p;
03473       *args++ = '\0';
03474       if ((p = strrchr(args, ')'))) {
03475          *p = '\0';
03476       } else {
03477          ast_log(LOG_WARNING, "Can't find trailing parenthesis for function '%s(%s'?\n", function, args);
03478       }
03479    }
03480    return args;
03481 }

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

Definition at line 1614 of file pbx.c.

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

01615 {
01616    /* find the exten at the end of the rope */
01617    struct match_char *node2 = node;
01618 
01619    for (node2 = node; node2; node2 = node2->next_char) {
01620       if (node2->exten) {
01621 #ifdef NEED_DEBUG_HERE
01622          ast_log(LOG_NOTICE,"CanMatch_exten returns exten %s(%p)\n", node2->exten->exten, node2->exten);
01623 #endif
01624          return node2->exten;
01625       }
01626    }
01627 #ifdef NEED_DEBUG_HERE
01628    ast_log(LOG_NOTICE,"CanMatch_exten returns NULL, match_char=%s\n", node->x);
01629 #endif
01630    return 0;
01631 }

static unsigned get_range ( char *  src,
int  max,
const char *const   names[],
const char *  msg 
) [static]

helper function to return a range up to max (7, 12, 31 respectively). names, if supplied, is an array of names that should be mapped to numbers.

Definition at line 7234 of file pbx.c.

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

Referenced by ast_build_timing().

07235 {
07236    int start, end; /* start and ending position */
07237    unsigned int mask = 0;
07238    char *part;
07239 
07240    /* Check for whole range */
07241    if (ast_strlen_zero(src) || !strcmp(src, "*")) {
07242       return (1 << max) - 1;
07243    }
07244 
07245    while ((part = strsep(&src, "&"))) {
07246       /* Get start and ending position */
07247       char *endpart = strchr(part, '-');
07248       if (endpart) {
07249          *endpart++ = '\0';
07250       }
07251       /* Find the start */
07252       if ((start = lookup_name(part, names, max)) < 0) {
07253          ast_log(LOG_WARNING, "Invalid %s '%s', skipping element\n", msg, part);
07254          continue;
07255       }
07256       if (endpart) { /* find end of range */
07257          if ((end = lookup_name(endpart, names, max)) < 0) {
07258             ast_log(LOG_WARNING, "Invalid end %s '%s', skipping element\n", msg, endpart);
07259             continue;
07260          }
07261       } else {
07262          end = start;
07263       }
07264       /* Fill the mask. Remember that ranges are cyclic */
07265       mask |= (1 << end);   /* initialize with last element */
07266       while (start != end) {
07267          mask |= (1 << start);
07268          if (++start >= max) {
07269             start = 0;
07270          }
07271       }
07272    }
07273    return mask;
07274 }

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

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

Definition at line 7277 of file pbx.c.

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

Referenced by ast_build_timing().

07278 {
07279    char *endpart, *part;
07280    int x;
07281    int st_h, st_m;
07282    int endh, endm;
07283    int minute_start, minute_end;
07284 
07285    /* start disabling all times, fill the fields with 0's, as they may contain garbage */
07286    memset(i->minmask, 0, sizeof(i->minmask));
07287 
07288    /* 1-minute per bit */
07289    /* Star is all times */
07290    if (ast_strlen_zero(times) || !strcmp(times, "*")) {
07291       /* 48, because each hour takes 2 integers; 30 bits each */
07292       for (x = 0; x < 48; x++) {
07293          i->minmask[x] = 0x3fffffff; /* 30 bits */
07294       }
07295       return;
07296    }
07297    /* Otherwise expect a range */
07298    while ((part = strsep(&times, "&"))) {
07299       if (!(endpart = strchr(part, '-'))) {
07300          if (sscanf(part, "%2d:%2d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) {
07301             ast_log(LOG_WARNING, "%s isn't a valid time.\n", part);
07302             continue;
07303          }
07304          i->minmask[st_h * 2 + (st_m >= 30 ? 1 : 0)] |= (1 << (st_m % 30));
07305          continue;
07306       }
07307       *endpart++ = '\0';
07308       /* why skip non digits? Mostly to skip spaces */
07309       while (*endpart && !isdigit(*endpart)) {
07310          endpart++;
07311       }
07312       if (!*endpart) {
07313          ast_log(LOG_WARNING, "Invalid time range starting with '%s-'.\n", part);
07314          continue;
07315       }
07316       if (sscanf(part, "%2d:%2d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) {
07317          ast_log(LOG_WARNING, "'%s' isn't a valid start time.\n", part);
07318          continue;
07319       }
07320       if (sscanf(endpart, "%2d:%2d", &endh, &endm) != 2 || endh < 0 || endh > 23 || endm < 0 || endm > 59) {
07321          ast_log(LOG_WARNING, "'%s' isn't a valid end time.\n", endpart);
07322          continue;
07323       }
07324       minute_start = st_h * 60 + st_m;
07325       minute_end = endh * 60 + endm;
07326       /* Go through the time and enable each appropriate bit */
07327       for (x = minute_start; x != minute_end; x = (x + 1) % (24 * 60)) {
07328          i->minmask[x / 30] |= (1 << (x % 30));
07329       }
07330       /* Do the last one */
07331       i->minmask[x / 30] |= (1 << (x % 30));
07332    }
07333    /* All done */
07334    return;
07335 }

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

Send ack once.

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

06321 {
06322    char *exten = NULL, *context = NULL;
06323    /* Variables used for different counters */
06324    struct dialplan_counters counters;
06325    const char *incstack[AST_PBX_MAX_STACK];
06326 
06327    switch (cmd) {
06328    case CLI_INIT:
06329       e->command = "dialplan debug";
06330       e->usage =
06331          "Usage: dialplan debug [context]\n"
06332          "       Show dialplan context Trie(s). Usually only useful to folks debugging the deep internals of the fast pattern matcher\n";
06333       return NULL;
06334    case CLI_GENERATE:
06335       return complete_show_dialplan_context(a->line, a->word, a->pos, a->n);
06336    }
06337 
06338    memset(&counters, 0, sizeof(counters));
06339 
06340    if (a->argc != 2 && a->argc != 3)
06341       return CLI_SHOWUSAGE;
06342 
06343    /* we obtain [exten@]context? if yes, split them ... */
06344    /* note: we ignore the exten totally here .... */
06345    if (a->argc == 3) {
06346       if (strchr(a->argv[2], '@')) {   /* split into exten & context */
06347          context = ast_strdupa(a->argv[2]);
06348          exten = strsep(&context, "@");
06349          /* change empty strings to NULL */
06350          if (ast_strlen_zero(exten))
06351             exten = NULL;
06352       } else { /* no '@' char, only context given */
06353          context = ast_strdupa(a->argv[2]);
06354       }
06355       if (ast_strlen_zero(context))
06356          context = NULL;
06357    }
06358    /* else Show complete dial plan, context and exten are NULL */
06359    show_debug_helper(a->fd, context, exten, &counters, NULL, 0, incstack);
06360 
06361    /* check for input failure and throw some error messages */
06362    if (context && !counters.context_existence) {
06363       ast_cli(a->fd, "There is no existence of '%s' context\n", context);
06364       return CLI_FAILURE;
06365    }
06366 
06367 
06368    ast_cli(a->fd,"-= %d %s. =-\n",
06369          counters.total_context, counters.total_context == 1 ? "context" : "contexts");
06370 
06371    /* everything ok */
06372    return CLI_SUCCESS;
06373 }

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

Definition at line 6691 of file pbx.c.

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

06692 {
06693    struct ast_channel *chan;
06694    const char *chan_name, *var_name, *var_value;
06695 
06696    switch (cmd) {
06697    case CLI_INIT:
06698       e->command = "dialplan set chanvar";
06699       e->usage =
06700          "Usage: dialplan set chanvar <channel> <varname> <value>\n"
06701          "       Set channel variable <varname> to <value>\n";
06702       return NULL;
06703    case CLI_GENERATE:
06704       return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
06705    }
06706 
06707    if (a->argc != e->args + 3)
06708       return CLI_SHOWUSAGE;
06709 
06710    chan_name = a->argv[e->args];
06711    var_name = a->argv[e->args + 1];
06712    var_value = a->argv[e->args + 2];
06713 
06714    if (!(chan = ast_channel_get_by_name(chan_name))) {
06715       ast_cli(a->fd, "Channel '%s' not found\n", chan_name);
06716       return CLI_FAILURE;
06717    }
06718 
06719    pbx_builtin_setvar_helper(chan, var_name, var_value);
06720 
06721    chan = ast_channel_unref(chan);
06722 
06723    ast_cli(a->fd, "\n    -- Channel variable '%s' set to '%s' for '%s'\n",  var_name, var_value, chan_name);
06724 
06725    return CLI_SUCCESS;
06726 }

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

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

06729 {
06730    int oldval = 0;
06731 
06732    switch (cmd) {
06733    case CLI_INIT:
06734       e->command = "dialplan set extenpatternmatchnew true";
06735       e->usage =
06736          "Usage: dialplan set extenpatternmatchnew true|false\n"
06737          "       Use the NEW extension pattern matching algorithm, true or false.\n";
06738       return NULL;
06739    case CLI_GENERATE:
06740       return NULL;
06741    }
06742 
06743    if (a->argc != 4)
06744       return CLI_SHOWUSAGE;
06745 
06746    oldval =  pbx_set_extenpatternmatchnew(1);
06747 
06748    if (oldval)
06749       ast_cli(a->fd, "\n    -- Still using the NEW pattern match algorithm for extension names in the dialplan.\n");
06750    else
06751       ast_cli(a->fd, "\n    -- Switched to using the NEW pattern match algorithm for extension names in the dialplan.\n");
06752 
06753    return CLI_SUCCESS;
06754 }

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

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

06670 {
06671    switch (cmd) {
06672    case CLI_INIT:
06673       e->command = "dialplan set global";
06674       e->usage =
06675          "Usage: dialplan set global <name> <value>\n"
06676          "       Set global dialplan variable <name> to <value>\n";
06677       return NULL;
06678    case CLI_GENERATE:
06679       return NULL;
06680    }
06681 
06682    if (a->argc != e->args + 2)
06683       return CLI_SHOWUSAGE;
06684 
06685    pbx_builtin_setvar_helper(NULL, a->argv[3], a->argv[4]);
06686    ast_cli(a->fd, "\n    -- Global variable '%s' set to '%s'\n", a->argv[3], a->argv[4]);
06687 
06688    return CLI_SUCCESS;
06689 }

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

Definition at line 5695 of file pbx.c.

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

05696 {
05697    struct ast_app *aa;
05698    int app, no_registered_app = 1;
05699 
05700    switch (cmd) {
05701    case CLI_INIT:
05702       e->command = "core show application";
05703       e->usage =
05704          "Usage: core show application <application> [<application> [<application> [...]]]\n"
05705          "       Describes a particular application.\n";
05706       return NULL;
05707    case CLI_GENERATE:
05708       /*
05709        * There is a possibility to show informations about more than one
05710        * application at one time. You can type 'show application Dial Echo' and
05711        * you will see informations about these two applications ...
05712        */
05713       return ast_complete_applications(a->line, a->word, a->n);
05714    }
05715 
05716    if (a->argc < 4) {
05717       return CLI_SHOWUSAGE;
05718    }
05719 
05720    AST_RWLIST_RDLOCK(&apps);
05721    AST_RWLIST_TRAVERSE(&apps, aa, list) {
05722       /* Check for each app that was supplied as an argument */
05723       for (app = 3; app < a->argc; app++) {
05724          if (strcasecmp(aa->name, a->argv[app])) {
05725             continue;
05726          }
05727 
05728          /* We found it! */
05729          no_registered_app = 0;
05730 
05731          print_app_docs(aa, a->fd);
05732       }
05733    }
05734    AST_RWLIST_UNLOCK(&apps);
05735 
05736    /* we found at least one app? no? */
05737    if (no_registered_app) {
05738       ast_cli(a->fd, "Your application(s) is (are) not registered\n");
05739       return CLI_FAILURE;
05740    }
05741 
05742    return CLI_SUCCESS;
05743 }

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

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

05910 {
05911    struct ast_app *aa;
05912    int like = 0, describing = 0;
05913    int total_match = 0;    /* Number of matches in like clause */
05914    int total_apps = 0;     /* Number of apps registered */
05915    static const char * const choices[] = { "like", "describing", NULL };
05916 
05917    switch (cmd) {
05918    case CLI_INIT:
05919       e->command = "core show applications [like|describing]";
05920       e->usage =
05921          "Usage: core show applications [{like|describing} <text>]\n"
05922          "       List applications which are currently available.\n"
05923          "       If 'like', <text> will be a substring of the app name\n"
05924          "       If 'describing', <text> will be a substring of the description\n";
05925       return NULL;
05926    case CLI_GENERATE:
05927       return (a->pos != 3) ? NULL : ast_cli_complete(a->word, choices, a->n);
05928    }
05929 
05930    AST_RWLIST_RDLOCK(&apps);
05931 
05932    if (AST_RWLIST_EMPTY(&apps)) {
05933       ast_cli(a->fd, "There are no registered applications\n");
05934       AST_RWLIST_UNLOCK(&apps);
05935       return CLI_SUCCESS;
05936    }
05937 
05938    /* core list applications like <keyword> */
05939    if ((a->argc == 5) && (!strcmp(a->argv[3], "like"))) {
05940       like = 1;
05941    } else if ((a->argc > 4) && (!strcmp(a->argv[3], "describing"))) {
05942       describing = 1;
05943    }
05944 
05945    /* core list applications describing <keyword1> [<keyword2>] [...] */
05946    if ((!like) && (!describing)) {
05947       ast_cli(a->fd, "    -= Registered Asterisk Applications =-\n");
05948    } else {
05949       ast_cli(a->fd, "    -= Matching Asterisk Applications =-\n");
05950    }
05951 
05952    AST_RWLIST_TRAVERSE(&apps, aa, list) {
05953       int printapp = 0;
05954       total_apps++;
05955       if (like) {
05956          if (strcasestr(aa->name, a->argv[4])) {
05957             printapp = 1;
05958             total_match++;
05959          }
05960       } else if (describing) {
05961          if (aa->description) {
05962             /* Match all words on command line */
05963             int i;
05964             printapp = 1;
05965             for (i = 4; i < a->argc; i++) {
05966                if (!strcasestr(aa->description, a->argv[i])) {
05967                   printapp = 0;
05968                } else {
05969                   total_match++;
05970                }
05971             }
05972          }
05973       } else {
05974          printapp = 1;
05975       }
05976 
05977       if (printapp) {
05978          ast_cli(a->fd,"  %20s: %s\n", aa->name, aa->synopsis ? aa->synopsis : "<Synopsis not available>");
05979       }
05980    }
05981    if ((!like) && (!describing)) {
05982       ast_cli(a->fd, "    -= %d Applications Registered =-\n",total_apps);
05983    } else {
05984       ast_cli(a->fd, "    -= %d Applications Matching =-\n",total_match);
05985    }
05986 
05987    AST_RWLIST_UNLOCK(&apps);
05988 
05989    return CLI_SUCCESS;
05990 }

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

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_channel_get_by_name(), ast_channel_unref, ast_cli(), ast_complete_channels(), ast_str_alloca, ast_str_buffer(), ast_str_strlen(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, pbx_builtin_serialize_variables(), ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.

06635 {
06636    struct ast_channel *chan = NULL;
06637    struct ast_str *vars = ast_str_alloca(BUFSIZ * 4); /* XXX large because we might have lots of channel vars */
06638 
06639    switch (cmd) {
06640    case CLI_INIT:
06641       e->command = "dialplan show chanvar";
06642       e->usage =
06643          "Usage: dialplan show chanvar <channel>\n"
06644          "       List current channel variables and their values\n";
06645       return NULL;
06646    case CLI_GENERATE:
06647       return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
06648    }
06649 
06650    if (a->argc != e->args + 1)
06651       return CLI_SHOWUSAGE;
06652 
06653    if (!(chan = ast_channel_get_by_name(a->argv[e->args]))) {
06654       ast_cli(a->fd, "Channel '%s' not found\n", a->argv[e->args]);
06655       return CLI_FAILURE;
06656    }
06657 
06658    pbx_builtin_serialize_variables(chan, &vars);
06659 
06660    if (ast_str_strlen(vars)) {
06661       ast_cli(a->fd, "\nVariables for channel %s:\n%s\n", a->argv[e->args], ast_str_buffer(vars));
06662    }
06663 
06664    chan = ast_channel_unref(chan);
06665 
06666    return CLI_SUCCESS;
06667 }

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

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

06254 {
06255    char *exten = NULL, *context = NULL;
06256    /* Variables used for different counters */
06257    struct dialplan_counters counters;
06258    const char *incstack[AST_PBX_MAX_STACK];
06259 
06260    switch (cmd) {
06261    case CLI_INIT:
06262       e->command = "dialplan show";
06263       e->usage =
06264          "Usage: dialplan show [[exten@]context]\n"
06265          "       Show dialplan\n";
06266       return NULL;
06267    case CLI_GENERATE:
06268       return complete_show_dialplan_context(a->line, a->word, a->pos, a->n);
06269    }
06270 
06271    memset(&counters, 0, sizeof(counters));
06272 
06273    if (a->argc != 2 && a->argc != 3)
06274       return CLI_SHOWUSAGE;
06275 
06276    /* we obtain [exten@]context? if yes, split them ... */
06277    if (a->argc == 3) {
06278       if (strchr(a->argv[2], '@')) {   /* split into exten & context */
06279          context = ast_strdupa(a->argv[2]);
06280          exten = strsep(&context, "@");
06281          /* change empty strings to NULL */
06282          if (ast_strlen_zero(exten))
06283             exten = NULL;
06284       } else { /* no '@' char, only context given */
06285          context = ast_strdupa(a->argv[2]);
06286       }
06287       if (ast_strlen_zero(context))
06288          context = NULL;
06289    }
06290    /* else Show complete dial plan, context and exten are NULL */
06291    show_dialplan_helper(a->fd, context, exten, &counters, NULL, 0, incstack);
06292 
06293    /* check for input failure and throw some error messages */
06294    if (context && !counters.context_existence) {
06295       ast_cli(a->fd, "There is no existence of '%s' context\n", context);
06296       return CLI_FAILURE;
06297    }
06298 
06299    if (exten && !counters.extension_existence) {
06300       if (context)
06301          ast_cli(a->fd, "There is no existence of %s@%s extension\n",
06302             exten, context);
06303       else
06304          ast_cli(a->fd,
06305             "There is no existence of '%s' extension in all contexts\n",
06306             exten);
06307       return CLI_FAILURE;
06308    }
06309 
06310    ast_cli(a->fd,"-= %d %s (%d %s) in %d %s. =-\n",
06311             counters.total_exten, counters.total_exten == 1 ? "extension" : "extensions",
06312             counters.total_prio, counters.total_prio == 1 ? "priority" : "priorities",
06313             counters.total_context, counters.total_context == 1 ? "context" : "contexts");
06314 
06315    /* everything ok */
06316    return CLI_SUCCESS;
06317 }

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

Definition at line 3218 of file pbx.c.

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

03219 {
03220    struct ast_custom_function *acf;
03221    /* Maximum number of characters added by terminal coloring is 22 */
03222    char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40], argtitle[40], seealsotitle[40];
03223    char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL, *seealso = NULL;
03224    char stxtitle[40], *syntax = NULL, *arguments = NULL;
03225    int syntax_size, description_size, synopsis_size, arguments_size, seealso_size;
03226    char *ret = NULL;
03227    int which = 0;
03228    int wordlen;
03229 
03230    switch (cmd) {
03231    case CLI_INIT:
03232       e->command = "core show function";
03233       e->usage =
03234          "Usage: core show function <function>\n"
03235          "       Describe a particular dialplan function.\n";
03236       return NULL;
03237    case CLI_GENERATE:
03238       wordlen = strlen(a->word);
03239       /* case-insensitive for convenience in this 'complete' function */
03240       AST_RWLIST_RDLOCK(&acf_root);
03241       AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) {
03242          if (!strncasecmp(a->word, acf->name, wordlen) && ++which > a->n) {
03243             ret = ast_strdup(acf->name);
03244             break;
03245          }
03246       }
03247       AST_RWLIST_UNLOCK(&acf_root);
03248 
03249       return ret;
03250    }
03251 
03252    if (a->argc < 4) {
03253       return CLI_SHOWUSAGE;
03254    }
03255 
03256    if (!(acf = ast_custom_function_find(a->argv[3]))) {
03257       ast_cli(a->fd, "No function by that name registered.\n");
03258       return CLI_FAILURE;
03259    }
03260 
03261    syntax_size = strlen(S_OR(acf->syntax, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
03262    if (!(syntax = ast_malloc(syntax_size))) {
03263       ast_cli(a->fd, "Memory allocation failure!\n");
03264       return CLI_FAILURE;
03265    }
03266 
03267    snprintf(info, sizeof(info), "\n  -= Info about function '%s' =- \n\n", acf->name);
03268    term_color(infotitle, info, COLOR_MAGENTA, 0, sizeof(infotitle));
03269    term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
03270    term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
03271    term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40);
03272    term_color(argtitle, "[Arguments]\n", COLOR_MAGENTA, 0, 40);
03273    term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, 40);
03274    term_color(syntax, S_OR(acf->syntax, "Not available"), COLOR_CYAN, 0, syntax_size);
03275 #ifdef AST_XML_DOCS
03276    if (acf->docsrc == AST_XML_DOC) {
03277       arguments = ast_xmldoc_printable(S_OR(acf->arguments, "Not available"), 1);
03278       synopsis = ast_xmldoc_printable(S_OR(acf->synopsis, "Not available"), 1);
03279       description = ast_xmldoc_printable(S_OR(acf->desc, "Not available"), 1);
03280       seealso = ast_xmldoc_printable(S_OR(acf->seealso, "Not available"), 1);
03281    } else
03282 #endif
03283    {
03284       synopsis_size = strlen(S_OR(acf->synopsis, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
03285       synopsis = ast_malloc(synopsis_size);
03286 
03287       description_size = strlen(S_OR(acf->desc, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
03288       description = ast_malloc(description_size);
03289 
03290       arguments_size = strlen(S_OR(acf->arguments, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
03291       arguments = ast_malloc(arguments_size);
03292 
03293       seealso_size = strlen(S_OR(acf->seealso, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
03294       seealso = ast_malloc(seealso_size);
03295 
03296       /* check allocated memory. */
03297       if (!synopsis || !description || !arguments || !seealso) {
03298          ast_free(synopsis);
03299          ast_free(description);
03300          ast_free(arguments);
03301          ast_free(seealso);
03302          ast_free(syntax);
03303          return CLI_FAILURE;
03304       }
03305 
03306       term_color(arguments, S_OR(acf->arguments, "Not available"), COLOR_CYAN, 0, arguments_size);
03307       term_color(synopsis, S_OR(acf->synopsis, "Not available"), COLOR_CYAN, 0, synopsis_size);
03308       term_color(description, S_OR(acf->desc, "Not available"), COLOR_CYAN, 0, description_size);
03309       term_color(seealso, S_OR(acf->seealso, "Not available"), COLOR_CYAN, 0, seealso_size);
03310    }
03311 
03312    ast_cli(a->fd, "%s%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n",
03313          infotitle, syntitle, synopsis, destitle, description,
03314          stxtitle, syntax, argtitle, arguments, seealsotitle, seealso);
03315 
03316    ast_free(arguments);
03317    ast_free(synopsis);
03318    ast_free(description);
03319    ast_free(seealso);
03320    ast_free(syntax);
03321 
03322    return CLI_SUCCESS;
03323 }

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

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

03177 {
03178    struct ast_custom_function *acf;
03179    int count_acf = 0;
03180    int like = 0;
03181 
03182    switch (cmd) {
03183    case CLI_INIT:
03184       e->command = "core show functions [like]";
03185       e->usage =
03186          "Usage: core show functions [like <text>]\n"
03187          "       List builtin functions, optionally only those matching a given string\n";
03188       return NULL;
03189    case CLI_GENERATE:
03190       return NULL;
03191    }
03192 
03193    if (a->argc == 5 && (!strcmp(a->argv[3], "like")) ) {
03194       like = 1;
03195    } else if (a->argc != 3) {
03196       return CLI_SHOWUSAGE;
03197    }
03198 
03199    ast_cli(a->fd, "%s Custom Functions:\n--------------------------------------------------------------------------------\n", like ? "Matching" : "Installed");
03200 
03201    AST_RWLIST_RDLOCK(&acf_root);
03202    AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) {
03203       if (!like || strstr(acf->name, a->argv[4])) {
03204          count_acf++;
03205          ast_cli(a->fd, "%-20.20s  %-35.35s  %s\n",
03206             S_OR(acf->name, ""),
03207             S_OR(acf->syntax, ""),
03208             S_OR(acf->synopsis, ""));
03209       }
03210    }
03211    AST_RWLIST_UNLOCK(&acf_root);
03212 
03213    ast_cli(a->fd, "%d %scustom functions installed.\n", count_acf, like ? "matching " : "");
03214 
03215    return CLI_SUCCESS;
03216 }

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

06577 {
06578    int i = 0;
06579    struct ast_var_t *newvariable;
06580 
06581    switch (cmd) {
06582    case CLI_INIT:
06583       e->command = "dialplan show globals";
06584       e->usage =
06585          "Usage: dialplan show globals\n"
06586          "       List current global dialplan variables and their values\n";
06587       return NULL;
06588    case CLI_GENERATE:
06589       return NULL;
06590    }
06591 
06592    ast_rwlock_rdlock(&globalslock);
06593    AST_LIST_TRAVERSE (&globals, newvariable, entries) {
06594       i++;
06595       ast_cli(a->fd, "   %s=%s\n", ast_var_name(newvariable), ast_var_value(newvariable));
06596    }
06597    ast_rwlock_unlock(&globalslock);
06598    ast_cli(a->fd, "\n    -- %d variable(s)\n", i);
06599 
06600    return CLI_SUCCESS;
06601 }

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

References ao2_container_count(), ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_extension_state2str(), ast_get_context_name(), ast_get_extension_app(), ast_get_extension_context(), ast_get_extension_name(), AST_LIST_TRAVERSE, ast_hint::callbacks, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_core_show_hint(), ast_hint::exten, ast_cli_args::fd, hints, ast_hint::laststate, ast_cli_args::line, ast_cli_args::n, ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.

05824 {
05825    struct ast_hint *hint;
05826    int watchers;
05827    int num = 0, extenlen;
05828    struct ast_state_cb *watcher;
05829    struct ao2_iterator i;
05830 
05831    switch (cmd) {
05832    case CLI_INIT:
05833       e->command = "core show hint";
05834       e->usage =
05835          "Usage: core show hint <exten>\n"
05836          "       List registered hint\n";
05837       return NULL;
05838    case CLI_GENERATE:
05839       return complete_core_show_hint(a->line, a->word, a->pos, a->n);
05840    }
05841 
05842    if (a->argc < 4)
05843       return CLI_SHOWUSAGE;
05844 
05845    if (ao2_container_count(hints) == 0) {
05846       ast_cli(a->fd, "There are no registered dialplan hints\n");
05847       return CLI_SUCCESS;
05848    }
05849    
05850    extenlen = strlen(a->argv[3]);
05851    i = ao2_iterator_init(hints, 0);
05852    for (hint = ao2_iterator_next(&i); hint; ao2_unlock(hint), ao2_ref(hint, -1), hint = ao2_iterator_next(&i)) {
05853       ao2_lock(hint);
05854       if (!strncasecmp(hint->exten ? ast_get_extension_name(hint->exten) : "", a->argv[3], extenlen)) {
05855          watchers = 0;
05856          AST_LIST_TRAVERSE(&hint->callbacks, watcher, entry) {
05857             watchers++;
05858          }
05859          ast_cli(a->fd, "   %20s@%-20.20s: %-20.20s  State:%-15.15s Watchers %2d\n",
05860             ast_get_extension_name(hint->exten),
05861             ast_get_context_name(ast_get_extension_context(hint->exten)),
05862             ast_get_extension_app(hint->exten),
05863             ast_extension_state2str(hint->laststate), watchers);
05864          num++;
05865       }
05866    }
05867    ao2_iterator_destroy(&i);
05868    if (!num)
05869       ast_cli(a->fd, "No hints matching extension %s\n", a->argv[3]);
05870    else
05871       ast_cli(a->fd, "%d hint%s matching extension %s\n", num, (num!=1 ? "s":""), a->argv[3]);
05872    return CLI_SUCCESS;
05873 }

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

References ao2_container_count(), ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, 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_hint::callbacks, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_hint::exten, ast_cli_args::fd, hints, ast_hint::laststate, and ast_cli_entry::usage.

05747 {
05748    struct ast_hint *hint;
05749    int num = 0;
05750    int watchers;
05751    struct ast_state_cb *watcher;
05752    struct ao2_iterator i;
05753 
05754    switch (cmd) {
05755    case CLI_INIT:
05756       e->command = "core show hints";
05757       e->usage =
05758          "Usage: core show hints\n"
05759          "       List registered hints\n";
05760       return NULL;
05761    case CLI_GENERATE:
05762       return NULL;
05763    }
05764 
05765    if (ao2_container_count(hints) == 0) {
05766       ast_cli(a->fd, "There are no registered dialplan hints\n");
05767       return CLI_SUCCESS;
05768    }
05769    /* ... we have hints ... */
05770    ast_cli(a->fd, "\n    -= Registered Asterisk Dial Plan Hints =-\n");
05771 
05772    i = ao2_iterator_init(hints, 0);
05773    for (hint = ao2_iterator_next(&i); hint; ao2_ref(hint, -1), hint = ao2_iterator_next(&i)) {
05774 
05775       watchers = 0;
05776       AST_LIST_TRAVERSE(&hint->callbacks, watcher, entry) {
05777          watchers++;
05778       }
05779       ast_cli(a->fd, "   %20s@%-20.20s: %-20.20s  State:%-15.15s Watchers %2d\n",
05780          ast_get_extension_name(hint->exten),
05781          ast_get_context_name(ast_get_extension_context(hint->exten)),
05782          ast_get_extension_app(hint->exten),
05783          ast_extension_state2str(hint->laststate), watchers);
05784       num++;
05785    }
05786 
05787    ao2_iterator_destroy(&i);
05788    ast_cli(a->fd, "----------------\n");
05789    ast_cli(a->fd, "- %d hints registered\n", num);
05790    return CLI_SUCCESS;
05791 }

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

05878 {
05879    struct ast_switch *sw;
05880 
05881    switch (cmd) {
05882    case CLI_INIT:
05883       e->command = "core show switches";
05884       e->usage =
05885          "Usage: core show switches\n"
05886          "       List registered switches\n";
05887       return NULL;
05888    case CLI_GENERATE:
05889       return NULL;
05890    }
05891 
05892    AST_RWLIST_RDLOCK(&switches);
05893 
05894    if (AST_RWLIST_EMPTY(&switches)) {
05895       AST_RWLIST_UNLOCK(&switches);
05896       ast_cli(a->fd, "There are no registered alternative switches\n");
05897       return CLI_SUCCESS;
05898    }
05899 
05900    ast_cli(a->fd, "\n    -= Registered Asterisk Alternative Switches =-\n");
05901    AST_RWLIST_TRAVERSE(&switches, sw, list)
05902       ast_cli(a->fd, "%s: %s\n", sw->name, sw->description);
05903 
05904    AST_RWLIST_UNLOCK(&switches);
05905 
05906    return CLI_SUCCESS;
05907 }

static int handle_statechange ( void *  datap  )  [static]

Definition at line 4230 of file pbx.c.

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_extension_state2(), ast_free, ast_get_extension_app(), AST_LIST_TRAVERSE, ast_rdlock_contexts(), ast_str_create(), ast_str_set(), ast_unlock_contexts(), ast_hint::callbacks, statechange::dev, ast_exten::exten, ast_hint::exten, hints, ast_hint::laststate, ast_context::name, ast_exten::parent, parse(), str, and strsep().

04231 {
04232    struct ast_hint *hint;
04233    struct ast_str *str;
04234    struct statechange *sc = datap;
04235    struct ao2_iterator i;
04236 
04237    if (!(str = ast_str_create(1024))) {
04238       return -1;
04239    }
04240 
04241 
04242    i = ao2_iterator_init(hints, 0);
04243    for (hint = ao2_iterator_next(&i); hint; ao2_ref(hint, -1), hint = ao2_iterator_next(&i)) {
04244       struct ast_state_cb *cblist;
04245       char *cur, *parse;
04246       int state;
04247 
04248       ast_str_set(&str, 0, "%s", ast_get_extension_app(hint->exten));
04249       parse = str->str;
04250 
04251       while ( (cur = strsep(&parse, "&")) ) {
04252          if (!strcasecmp(cur, sc->dev)) {
04253             break;
04254          }
04255       }
04256 
04257       if (!cur) {
04258          continue;
04259       }
04260 
04261       /* Get device state for this hint */
04262       state = ast_extension_state2(hint->exten);
04263 
04264       if ((state == -1) || (state == hint->laststate)) {
04265          continue;
04266       }
04267 
04268       /* Device state changed since last check - notify the watchers */
04269 
04270       ast_rdlock_contexts();
04271       ao2_lock(hints);
04272       ao2_lock(hint);
04273 
04274       if (hint->exten == NULL) {
04275          /* the extension has been destroyed */
04276          ao2_unlock(hint);
04277          ao2_unlock(hints);
04278          ast_unlock_contexts();
04279          continue;
04280       }
04281 
04282       /* For general callbacks */
04283       AST_LIST_TRAVERSE(&statecbs, cblist, entry) {
04284          cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data);
04285       }
04286 
04287       /* For extension callbacks */
04288       AST_LIST_TRAVERSE(&hint->callbacks, cblist, entry) {
04289          cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data);
04290       }
04291 
04292       hint->laststate = state;   /* record we saw the change */
04293       ao2_unlock(hint);
04294       ao2_unlock(hints);
04295       ast_unlock_contexts();
04296    }
04297    ao2_iterator_destroy(&i);
04298    ast_free(str);
04299    ast_free(sc);
04300    return 0;
04301 }

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

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

06757 {
06758    int oldval = 0;
06759 
06760    switch (cmd) {
06761    case CLI_INIT:
06762       e->command = "dialplan set extenpatternmatchnew false";
06763       e->usage =
06764          "Usage: dialplan set extenpatternmatchnew true|false\n"
06765          "       Use the NEW extension pattern matching algorithm, true or false.\n";
06766       return NULL;
06767    case CLI_GENERATE:
06768       return NULL;
06769    }
06770 
06771    if (a->argc != 4)
06772       return CLI_SHOWUSAGE;
06773 
06774    oldval =  pbx_set_extenpatternmatchnew(0);
06775 
06776    if (!oldval)
06777       ast_cli(a->fd, "\n    -- Still using the OLD pattern match algorithm for extension names in the dialplan.\n");
06778    else
06779       ast_cli(a->fd, "\n    -- Switched to using the OLD pattern match algorithm for extension names in the dialplan.\n");
06780 
06781    return CLI_SUCCESS;
06782 }

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

Definition at line 1082 of file pbx.c.

References ast_exten::label, and S_OR.

Referenced by ast_add_extension2_lockopt().

01083 {
01084    const struct ast_exten *ac = ah_a;
01085    const struct ast_exten *bc = ah_b;
01086    return strcmp(S_OR(ac->label, ""), S_OR(bc->label, ""));
01087 }

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

Definition at line 1075 of file pbx.c.

References ast_exten::priority.

Referenced by ast_add_extension2_lockopt().

01076 {
01077    const struct ast_exten *ac = ah_a;
01078    const struct ast_exten *bc = ah_b;
01079    return ac->priority != bc->priority;
01080 }

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

Definition at line 1056 of file pbx.c.

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

Referenced by ast_add_extension2_lockopt().

01057 {
01058    const struct ast_exten *ac = ah_a;
01059    const struct ast_exten *bc = ah_b;
01060    int x = strcmp(ac->exten, bc->exten);
01061    if (x) { /* if exten names are diff, then return */
01062       return x;
01063    }
01064 
01065    /* but if they are the same, do the cidmatch values match? */
01066    if (ac->matchcid && bc->matchcid) {
01067       return strcmp(ac->cidmatch,bc->cidmatch);
01068    } else if (!ac->matchcid && !bc->matchcid) {
01069       return 0; /* if there's no matchcid on either side, then this is a match */
01070    } else {
01071       return 1; /* if there's matchcid on one but not the other, they are different */
01072    }
01073 }

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

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

01096 {
01097    const struct ast_exten *ac = obj;
01098    unsigned int x = ast_hashtab_hash_string(ac->exten);
01099    unsigned int y = 0;
01100    if (ac->matchcid)
01101       y = ast_hashtab_hash_string(ac->cidmatch);
01102    return x+y;
01103 }

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

Definition at line 1111 of file pbx.c.

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

Referenced by ast_add_extension2_lockopt().

01112 {
01113    const struct ast_exten *ac = obj;
01114    return ast_hashtab_hash_string(S_OR(ac->label, ""));
01115 }

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

Definition at line 1105 of file pbx.c.

References ast_hashtab_hash_int(), and ast_exten::priority.

Referenced by ast_add_extension2_lockopt().

01106 {
01107    const struct ast_exten *ac = obj;
01108    return ast_hashtab_hash_int(ac->priority);
01109 }

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

Definition at line 10235 of file pbx.c.

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

Referenced by ast_pbx_init().

10236 {
10237    const struct ast_hint *hint = obj;
10238    const struct ast_exten *exten = arg;
10239 
10240    return (hint->exten == exten) ? CMP_MATCH | CMP_STOP : 0;
10241 }

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

Definition at line 10222 of file pbx.c.

References ast_get_extension_name(), ast_str_case_hash(), and ast_hint::exten.

Referenced by ast_pbx_init().

10223 {
10224    const struct ast_hint *hint = obj;
10225 
10226    int res = -1;
10227 
10228    if (ast_get_extension_name(hint->exten)) {
10229       res = ast_str_case_hash(ast_get_extension_name(hint->exten));
10230    }
10231 
10232    return res;
10233 }

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

Definition at line 9818 of file pbx.c.

References ao2_container_count(), ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_data_add_int(), ast_data_add_node(), ast_data_add_str(), ast_data_remove_node(), ast_data_search_match(), ast_extension_state2str(), ast_get_context_name(), ast_get_extension_app(), ast_get_extension_context(), ast_get_extension_name(), AST_LIST_TRAVERSE, ast_hint::callbacks, ast_hint::exten, hints, and ast_hint::laststate.

09820 {
09821    struct ast_data *data_hint;
09822    struct ast_hint *hint;
09823    int watchers;
09824    struct ast_state_cb *watcher;
09825    struct ao2_iterator i;
09826 
09827    if (ao2_container_count(hints) == 0) {
09828       return 0;
09829    }
09830 
09831    i = ao2_iterator_init(hints, 0);
09832    for (hint = ao2_iterator_next(&i); hint; ao2_ref(hint, -1), hint = ao2_iterator_next(&i)) {
09833       watchers = 0;
09834       AST_LIST_TRAVERSE(&hint->callbacks, watcher, entry) {
09835          watchers++;
09836       }
09837       data_hint = ast_data_add_node(data_root, "hint");
09838       if (!data_hint) {
09839          continue;
09840       }
09841       ast_data_add_str(data_hint, "extension", ast_get_extension_name(hint->exten));
09842       ast_data_add_str(data_hint, "context", ast_get_context_name(ast_get_extension_context(hint->exten)));
09843       ast_data_add_str(data_hint, "application", ast_get_extension_app(hint->exten));
09844       ast_data_add_str(data_hint, "state", ast_extension_state2str(hint->laststate));
09845       ast_data_add_int(data_hint, "watchers", watchers);
09846 
09847       if (!ast_data_search_match(search, data_hint)) {
09848          ast_data_remove_node(data_root, data_hint);
09849       }
09850    }
09851    ao2_iterator_destroy(&i);
09852 
09853    return 0;
09854 }

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

Definition at line 1451 of file pbx.c.

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

Referenced by pbx_find_extension().

01452 {
01453    if (!i->hastime)
01454       return 1;
01455 
01456    return ast_check_timing(&(i->timing));
01457 }

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

04934 {
04935    int failed = 0;
04936    double curloadavg;
04937 #if defined(HAVE_SYSINFO)
04938    long curfreemem;
04939    struct sysinfo sys_info;
04940 #endif
04941 
04942    ast_mutex_lock(&maxcalllock);
04943    if (option_maxcalls) {
04944       if (countcalls >= option_maxcalls) {
04945          ast_log(LOG_WARNING, "Maximum call limit of %d calls exceeded by '%s'!\n", option_maxcalls, c->name);
04946          failed = -1;
04947       }
04948    }
04949    if (option_maxload) {
04950       getloadavg(&curloadavg, 1);
04951       if (curloadavg >= option_maxload) {
04952          ast_log(LOG_WARNING, "Maximum loadavg limit of %f load exceeded by '%s' (currently %f)!\n", option_maxload, c->name, curloadavg);
04953          failed = -1;
04954       }
04955    }
04956 #if defined(HAVE_SYSINFO)
04957    if (option_minmemfree) {
04958       if (!sysinfo(&sys_info)) {
04959          /* make sure that the free system memory is above the configured low watermark
04960           * convert the amount of freeram from mem_units to MB */
04961          curfreemem = sys_info.freeram / sys_info.mem_unit;
04962          curfreemem /= 1024 * 1024;
04963          if (curfreemem < option_minmemfree) {
04964             ast_log(LOG_WARNING, "Available system memory (~%ldMB) is below the configured low watermark (%ldMB)\n", curfreemem, option_minmemfree);
04965             failed = -1;
04966          }
04967       }
04968    }
04969 #endif
04970 
04971    if (!failed) {
04972       countcalls++;
04973       totalcalls++;
04974    }
04975    ast_mutex_unlock(&maxcalllock);
04976 
04977    return failed;
04978 }

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

Definition at line 1868 of file pbx.c.

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

Referenced by add_pattern_node().

01869 {
01870    struct match_char *curr, *lcurr;
01871 
01872    /* insert node into the tree at "current", so the alt_char list from current is
01873       sorted in increasing value as you go to the leaves */
01874    if (!(*parent_ptr)) {
01875       *parent_ptr = node;
01876       return;
01877    }
01878 
01879    if ((*parent_ptr)->specificity > node->specificity) {
01880       /* insert at head */
01881       node->alt_char = (*parent_ptr);
01882       *parent_ptr = node;
01883       return;
01884    } 
01885 
01886    lcurr = *parent_ptr;
01887    for (curr = (*parent_ptr)->alt_char; curr; curr = curr->alt_char) {
01888       if (curr->specificity > node->specificity) {
01889          node->alt_char = curr;
01890          lcurr->alt_char = node;
01891          break;
01892       }
01893       lcurr = curr;
01894    }
01895 
01896    if (!curr) {
01897       lcurr->alt_char = node;
01898    }
01899 
01900 }

int load_pbx ( void   ) 

Provided by pbx.c

Definition at line 9865 of file pbx.c.

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

Referenced by main().

09866 {
09867    int x;
09868 
09869    /* Initialize the PBX */
09870    ast_verb(1, "Asterisk PBX Core Initializing\n");
09871    if (!(device_state_tps = ast_taskprocessor_get("pbx-core", 0))) {
09872       ast_log(LOG_WARNING, "failed to create pbx-core taskprocessor\n");
09873    }
09874 
09875    ast_verb(1, "Registering builtin applications:\n");
09876    ast_cli_register_multiple(pbx_cli, ARRAY_LEN(pbx_cli));
09877    ast_data_register_multiple_core(pbx_data_providers, ARRAY_LEN(pbx_data_providers));
09878    __ast_custom_function_register(&exception_function, NULL);
09879    __ast_custom_function_register(&testtime_function, NULL);
09880 
09881    /* Register builtin applications */
09882    for (x = 0; x < ARRAY_LEN(builtins); x++) {
09883       ast_verb(1, "[%s]\n", builtins[x].name);
09884       if (ast_register_application2(builtins[x].name, builtins[x].execute, NULL, NULL, NULL)) {
09885          ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name);
09886          return -1;
09887       }
09888    }
09889 
09890    /* Register manager application */
09891    ast_manager_register_xml("ShowDialPlan", EVENT_FLAG_CONFIG | EVENT_FLAG_REPORTING, manager_show_dialplan);
09892 
09893    if (!(device_state_sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE, device_state_cb, "pbx Device State Change", NULL,
09894          AST_EVENT_IE_END))) {
09895       return -1;
09896    }
09897 
09898    return 0;
09899 }

static int lookup_name ( const char *  s,
const char *const   names[],
int  max 
) [static]

Helper for get_range. return the index of the matching entry, starting from 1. If names is not supplied, try numeric values.

Definition at line 7211 of file pbx.c.

Referenced by get_range().

07212 {
07213    int i;
07214 
07215    if (names && *s > '9') {
07216       for (i = 0; names[i]; i++) {
07217          if (!strcasecmp(s, names[i])) {
07218             return i;
07219          }
07220       }
07221    }
07222 
07223    /* Allow months and weekdays to be specified as numbers, as well */
07224    if (sscanf(s, "%2d", &i) == 1 && i >= 1 && i <= max) {
07225       /* What the array offset would have been: "1" would be at offset 0 */
07226       return i - 1;
07227    }
07228    return -1; /* error return */
07229 }

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

Send ack once.

Definition at line 6376 of file pbx.c.

References astman_send_listack().

Referenced by manager_show_dialplan_helper().

06377 {
06378    astman_send_listack(s, m, "DialPlan list will follow", "start");
06379 }

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

Manager listing of dial plan.

Definition at line 6522 of file pbx.c.

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

Referenced by load_pbx().

06523 {
06524    const char *exten, *context;
06525    const char *id = astman_get_header(m, "ActionID");
06526    char idtext[256];
06527    int res;
06528 
06529    /* Variables used for different counters */
06530    struct dialplan_counters counters;
06531 
06532    if (!ast_strlen_zero(id))
06533       snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id);
06534    else
06535       idtext[0] = '\0';
06536 
06537    memset(&counters, 0, sizeof(counters));
06538 
06539    exten = astman_get_header(m, "Extension");
06540    context = astman_get_header(m, "Context");
06541 
06542    res = manager_show_dialplan_helper(s, m, idtext, context, exten, &counters, NULL);
06543 
06544    if (context && !counters.context_existence) {
06545       char errorbuf[BUFSIZ];
06546 
06547       snprintf(errorbuf, sizeof(errorbuf), "Did not find context %s", context);
06548       astman_send_error(s, m, errorbuf);
06549       return 0;
06550    }
06551    if (exten && !counters.extension_existence) {
06552       char errorbuf[BUFSIZ];
06553 
06554       if (context)
06555          snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s@%s", exten, context);
06556       else
06557          snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s in any context", exten);
06558       astman_send_error(s, m, errorbuf);
06559       return 0;
06560    }
06561 
06562    astman_append(s, "Event: ShowDialPlanComplete\r\n"
06563       "EventList: Complete\r\n"
06564       "ListItems: %d\r\n"
06565       "ListExtensions: %d\r\n"
06566       "ListPriorities: %d\r\n"
06567       "ListContexts: %d\r\n"
06568       "%s"
06569       "\r\n", counters.total_items, counters.total_exten, counters.total_prio, counters.total_context, idtext);
06570 
06571    /* everything ok */
06572    return 0;
06573 }

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

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

Referenced by manager_show_dialplan().

06389 {
06390    struct ast_context *c;
06391    int res = 0, old_total_exten = dpc->total_exten;
06392 
06393    if (ast_strlen_zero(exten))
06394       exten = NULL;
06395    if (ast_strlen_zero(context))
06396       context = NULL;
06397 
06398    ast_debug(3, "manager_show_dialplan: Context: -%s- Extension: -%s-\n", context, exten);
06399 
06400    /* try to lock contexts */
06401    if (ast_rdlock_contexts()) {
06402       astman_send_error(s, m, "Failed to lock contexts");
06403       ast_log(LOG_WARNING, "Failed to lock contexts list for manager: listdialplan\n");
06404       return -1;
06405    }
06406 
06407    c = NULL;      /* walk all contexts ... */
06408    while ( (c = ast_walk_contexts(c)) ) {
06409       struct ast_exten *e;
06410       struct ast_include *i;
06411       struct ast_ignorepat *ip;
06412 
06413       if (context && strcmp(ast_get_context_name(c), context) != 0)
06414          continue;   /* not the name we want */
06415 
06416       dpc->context_existence = 1;
06417 
06418       ast_debug(3, "manager_show_dialplan: Found Context: %s \n", ast_get_context_name(c));
06419 
06420       if (ast_rdlock_context(c)) {  /* failed to lock */
06421          ast_debug(3, "manager_show_dialplan: Failed to lock context\n");
06422          continue;
06423       }
06424 
06425       /* XXX note- an empty context is not printed */
06426       e = NULL;      /* walk extensions in context  */
06427       while ( (e = ast_walk_context_extensions(c, e)) ) {
06428          struct ast_exten *p;
06429 
06430          /* looking for extension? is this our extension? */
06431          if (exten && !ast_extension_match(ast_get_extension_name(e), exten)) {
06432             /* not the one we are looking for, continue */
06433             ast_debug(3, "manager_show_dialplan: Skipping extension %s\n", ast_get_extension_name(e));
06434             continue;
06435          }
06436          ast_debug(3, "manager_show_dialplan: Found Extension: %s \n", ast_get_extension_name(e));
06437 
06438          dpc->extension_existence = 1;
06439 
06440          /* may we print context info? */
06441          dpc->total_context++;
06442          dpc->total_exten++;
06443 
06444          p = NULL;      /* walk next extension peers */
06445          while ( (p = ast_walk_extension_priorities(e, p)) ) {
06446             int prio = ast_get_extension_priority(p);
06447 
06448             dpc->total_prio++;
06449             if (!dpc->total_items++)
06450                manager_dpsendack(s, m);
06451             astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
06452             astman_append(s, "Context: %s\r\nExtension: %s\r\n", ast_get_context_name(c), ast_get_extension_name(e) );
06453 
06454             /* XXX maybe make this conditional, if p != e ? */
06455             if (ast_get_extension_label(p))
06456                astman_append(s, "ExtensionLabel: %s\r\n", ast_get_extension_label(p));
06457 
06458             if (prio == PRIORITY_HINT) {
06459                astman_append(s, "Priority: hint\r\nApplication: %s\r\n", ast_get_extension_app(p));
06460             } else {
06461                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));
06462             }
06463             astman_append(s, "Registrar: %s\r\n\r\n", ast_get_extension_registrar(e));
06464          }
06465       }
06466 
06467       i = NULL;      /* walk included and write info ... */
06468       while ( (i = ast_walk_context_includes(c, i)) ) {
06469          if (exten) {
06470             /* Check all includes for the requested extension */
06471             manager_show_dialplan_helper(s, m, actionidtext, ast_get_include_name(i), exten, dpc, i);
06472          } else {
06473             if (!dpc->total_items++)
06474                manager_dpsendack(s, m);
06475             astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
06476             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));
06477             astman_append(s, "\r\n");
06478             ast_debug(3, "manager_show_dialplan: Found Included context: %s \n", ast_get_include_name(i));
06479          }
06480       }
06481 
06482       ip = NULL;  /* walk ignore patterns and write info ... */
06483       while ( (ip = ast_walk_context_ignorepats(c, ip)) ) {
06484          const char *ipname = ast_get_ignorepat_name(ip);
06485          char ignorepat[AST_MAX_EXTENSION];
06486 
06487          snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname);
06488          if (!exten || ast_extension_match(ignorepat, exten)) {
06489             if (!dpc->total_items++)
06490                manager_dpsendack(s, m);
06491             astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
06492             astman_append(s, "Context: %s\r\nIgnorePattern: %s\r\nRegistrar: %s\r\n", ast_get_context_name(c), ipname, ast_get_ignorepat_registrar(ip));
06493             astman_append(s, "\r\n");
06494          }
06495       }
06496       if (!rinclude) {
06497          struct ast_sw *sw = NULL;
06498          while ( (sw = ast_walk_context_switches(c, sw)) ) {
06499             if (!dpc->total_items++)
06500                manager_dpsendack(s, m);
06501             astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
06502             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));  
06503             astman_append(s, "\r\n");
06504             ast_debug(3, "manager_show_dialplan: Found Switch : %s \n", ast_get_switch_name(sw));
06505          }
06506       }
06507 
06508       ast_unlock_context(c);
06509    }
06510    ast_unlock_contexts();
06511 
06512    if (dpc->total_exten == old_total_exten) {
06513       ast_debug(3, "manager_show_dialplan: Found nothing new\n");
06514       /* Nothing new under the sun */
06515       return -1;
06516    } else {
06517       return res;
06518    }
06519 }

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

Definition at line 2539 of file pbx.c.

References ast_extension_match(), and ast_strlen_zero().

Referenced by pbx_find_extension().

02540 {
02541    /* If the Caller*ID pattern is empty, then we're matching NO Caller*ID, so
02542       failing to get a number should count as a match, otherwise not */
02543 
02544    if (ast_strlen_zero(callerid)) {
02545       return ast_strlen_zero(cidpattern) ? 1 : 0;
02546    }
02547 
02548    return ast_extension_match(cidpattern, callerid);
02549 }

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

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

Referenced by pbx_find_extension().

01693 {
01694    struct match_char *p; /* note minimal stack storage requirements */
01695    struct ast_exten pattern = { .label = label };
01696 #ifdef DEBUG_THIS
01697    if (tree)
01698       ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree %s action=%s\n", str, tree->x, action2str(action));
01699    else
01700       ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree NULL action=%s\n", str, action2str(action));
01701 #endif
01702    for (p = tree; p; p = p->alt_char) {
01703       if (p->is_pattern) {
01704          if (p->x[0] == 'N') {
01705             if (p->x[1] == 0 && *str >= '2' && *str <= '9' ) {
01706 #define  NEW_MATCHER_CHK_MATCH          \
01707                if (p->exten && !(*(str + 1))) { /* if a shorter pattern matches along the way, might as well report it */             \
01708                   if (action == E_MATCH || action == E_SPAWN || action == E_FINDLABEL) { /* if in CANMATCH/MATCHMORE, don't let matches get in the way */   \
01709                      update_scoreboard(score, length + 1, spec + p->specificity, p->exten, 0, callerid, p->deleted, p);                 \
01710                      if (!p->deleted) {                                                                                           \
01711                         if (action == E_FINDLABEL) {                                                                             \
01712                            if (ast_hashtab_lookup(score->exten->peer_label_table, &pattern)) {                                  \
01713                               ast_debug(4, "Found label in preferred extension\n");                                            \
01714                               return;                                                                                          \
01715                            }                                                                                                    \
01716                         } else {                                                                                                 \
01717                            ast_debug(4, "returning an exact match-- first found-- %s\n", p->exten->exten);                       \
01718                            return; /* the first match, by definition, will be the best, because of the sorted tree */           \
01719                         }                                                                                                        \
01720                      }                                                                                                            \
01721                   }                                                                                                                \
01722                }
01723                
01724 #define  NEW_MATCHER_RECURSE             \
01725                if (p->next_char && (*(str + 1) || (p->next_char->x[0] == '/' && p->next_char->x[1] == 0)                 \
01726                                                 || p->next_char->x[0] == '!')) {                                          \
01727                   if (*(str + 1) || p->next_char->x[0] == '!') {                                                         \
01728                      new_find_extension(str + 1, score, p->next_char, length + 1, spec + p->specificity, callerid, label, action); \
01729                      if (score->exten)  {                                                                             \
01730                           ast_debug(4 ,"returning an exact match-- %s\n", score->exten->exten);                         \
01731                         return; /* the first match is all we need */                                                 \
01732                      }                                                                                    \
01733                   } else {                                                                                             \
01734                      new_find_extension("/", score, p->next_char, length + 1, spec + p->specificity, callerid, label, action);    \
01735                      if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) {      \
01736                           ast_debug(4,"returning a (can/more) match--- %s\n", score->exten ? score->exten->exten :     \
01737                                         "NULL");                                                                        \
01738                         return; /* the first match is all we need */                                                 \
01739                      }                                                                                    \
01740                   }                                                                                                    \
01741                } else if (p->next_char && !*(str + 1)) {                                                                  \
01742                   score->canmatch = 1;                                                                                 \
01743                   score->canmatch_exten = get_canmatch_exten(p);                                                       \
01744                   if (action == E_CANMATCH || action == E_MATCHMORE) {                                                 \
01745                        ast_debug(4, "returning a canmatch/matchmore--- str=%s\n", str);                                  \
01746                      return;                                                                                          \
01747                   }                                                                                        \
01748                }
01749                
01750                NEW_MATCHER_CHK_MATCH;
01751                NEW_MATCHER_RECURSE;
01752             }
01753          } else if (p->x[0] == 'Z') {
01754             if (p->x[1] == 0 && *str >= '1' && *str <= '9' ) {
01755                NEW_MATCHER_CHK_MATCH;
01756                NEW_MATCHER_RECURSE;
01757             }
01758          } else if (p->x[0] == 'X') { 
01759             if (p->x[1] == 0 && *str >= '0' && *str <= '9' ) {
01760                NEW_MATCHER_CHK_MATCH;
01761                NEW_MATCHER_RECURSE;
01762             }
01763          } else if (p->x[0] == '.' && p->x[1] == 0) {
01764             /* how many chars will the . match against? */
01765             int i = 0;
01766             const char *str2 = str;
01767             while (*str2 && *str2 != '/') {
01768                str2++;
01769                i++;
01770             }
01771             if (p->exten && *str2 != '/') {
01772                update_scoreboard(score, length + i, spec + (i * p->specificity), p->exten, '.', callerid, p->deleted, p);
01773                if (score->exten) {
01774                   ast_debug(4,"return because scoreboard has a match with '/'--- %s\n", score->exten->exten);
01775                   return; /* the first match is all we need */
01776                }
01777             }
01778             if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) {
01779                new_find_extension("/", score, p->next_char, length + i, spec+(p->specificity*i), callerid, label, action);
01780                if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) {
01781                   ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set--- %s\n", score->exten ? score->exten->exten : "NULL");
01782                   return; /* the first match is all we need */
01783                }
01784             }
01785          } else if (p->x[0] == '!' && p->x[1] == 0) {
01786             /* how many chars will the . match against? */
01787             int i = 1;
01788             const char *str2 = str;
01789             while (*str2 && *str2 != '/') {
01790                str2++;
01791                i++;
01792             }
01793             if (p->exten && *str2 != '/') {
01794                update_scoreboard(score, length + 1, spec + (p->specificity * i), p->exten, '!', callerid, p->deleted, p);
01795                if (score->exten) {
01796                   ast_debug(4, "return because scoreboard has a '!' match--- %s\n", score->exten->exten);
01797                   return; /* the first match is all we need */
01798                }
01799             }
01800             if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) {
01801                new_find_extension("/", score, p->next_char, length + i, spec + (p->specificity * i), callerid, label, action);
01802                if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) {
01803                   ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set with '/' and '!'--- %s\n", score->exten ? score->exten->exten : "NULL");
01804                   return; /* the first match is all we need */
01805                }
01806             }
01807          } else if (p->x[0] == '/' && p->x[1] == 0) {
01808             /* the pattern in the tree includes the cid match! */
01809             if (p->next_char && callerid && *callerid) {
01810                new_find_extension(callerid, score, p->next_char, length + 1, spec, callerid, label, action);
01811                if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) {
01812                   ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set with '/'--- %s\n", score->exten ? score->exten->exten : "NULL");
01813                   return; /* the first match is all we need */
01814                }
01815             }
01816          } else if (strchr(p->x, *str)) {
01817             ast_debug(4, "Nothing strange about this match\n");
01818             NEW_MATCHER_CHK_MATCH;
01819             NEW_MATCHER_RECURSE;
01820          }
01821       } else if (strchr(p->x, *str)) {
01822          ast_debug(4, "Nothing strange about this match\n");
01823          NEW_MATCHER_CHK_MATCH;
01824          NEW_MATCHER_RECURSE;
01825       }
01826    }
01827    ast_debug(4, "return at end of func\n");
01828 }

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

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

02854 {
02855    int parens = 0;
02856 
02857    *offset = 0;
02858    *length = INT_MAX;
02859    *isfunc = 0;
02860    for (; *var; var++) {
02861       if (*var == '(') {
02862          (*isfunc)++;
02863          parens++;
02864       } else if (*var == ')') {
02865          parens--;
02866       } else if (*var == ':' && parens == 0) {
02867          *var++ = '\0';
02868          sscanf(var, "%30d:%30d", offset, length);
02869          return 1; /* offset:length valid */
02870       }
02871    }
02872    return 0;
02873 }

void pbx_builtin_clear_globals ( void   ) 

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

09695 {
09696    struct ast_var_t *vardata;
09697 
09698    ast_rwlock_wrlock(&globalslock);
09699    while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries)))
09700       ast_var_delete(vardata);
09701    ast_rwlock_unlock(&globalslock);
09702 }

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

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

Note:
Will lock the channel.

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

      const char *var;

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

Definition at line 9456 of file pbx.c.

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

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

09457 {
09458    struct ast_var_t *variables;
09459    const char *ret = NULL;
09460    int i;
09461    struct varshead *places[2] = { NULL, &globals };
09462 
09463    if (!name)
09464       return NULL;
09465 
09466    if (chan) {
09467       ast_channel_lock(chan);
09468       places[0] = &chan->varshead;
09469    }
09470 
09471    for (i = 0; i < 2; i++) {
09472       if (!places[i])
09473          continue;
09474       if (places[i] == &globals)
09475          ast_rwlock_rdlock(&globalslock);
09476       AST_LIST_TRAVERSE(places[i], variables, entries) {
09477          if (!strcmp(name, ast_var_name(variables))) {
09478             ret = ast_var_value(variables);
09479             break;
09480          }
09481       }
09482       if (places[i] == &globals)
09483          ast_rwlock_unlock(&globalslock);
09484       if (ret)
09485          break;
09486    }
09487 
09488    if (chan)
09489       ast_channel_unlock(chan);
09490 
09491    return ret;
09492 }

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

Definition at line 9716 of file pbx.c.

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

09717 {
09718    char *condition, *branch1, *branch2, *branch;
09719    char *stringp;
09720 
09721    if (ast_strlen_zero(data)) {
09722       ast_log(LOG_WARNING, "Ignoring, since there is no variable to check\n");
09723       return 0;
09724    }
09725 
09726    stringp = ast_strdupa(data);
09727    condition = strsep(&stringp,"?");
09728    branch1 = strsep(&stringp,":");
09729    branch2 = strsep(&stringp,"");
09730    branch = pbx_checkcondition(condition) ? branch1 : branch2;
09731 
09732    if (ast_strlen_zero(branch)) {
09733       ast_debug(1, "Not taking any branch\n");
09734       return 0;
09735    }
09736 
09737    return pbx_builtin_goto(chan, branch);
09738 }

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

Definition at line 9652 of file pbx.c.

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

09653 {
09654    char *name;
09655    char *value;
09656    char *channel;
09657    char tmp[VAR_BUF_SIZE];
09658    static int deprecation_warning = 0;
09659 
09660    if (ast_strlen_zero(data)) {
09661       ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n");
09662       return 0;
09663    }
09664    tmp[0] = 0;
09665    if (!deprecation_warning) {
09666       ast_log(LOG_WARNING, "ImportVar is deprecated.  Please use Set(varname=${IMPORT(channel,variable)}) instead.\n");
09667       deprecation_warning = 1;
09668    }
09669 
09670    value = ast_strdupa(data);
09671    name = strsep(&value,"=");
09672    channel = strsep(&value,",");
09673    if (channel && value && name) { /*! \todo XXX should do !ast_strlen_zero(..) of the args ? */
09674       struct ast_channel *chan2 = ast_channel_get_by_name(channel);
09675       if (chan2) {
09676          char *s = alloca(strlen(value) + 4);
09677          if (s) {
09678             sprintf(s, "${%s}", value);
09679             pbx_substitute_variables_helper(chan2, s, tmp, sizeof(tmp) - 1);
09680          }
09681          chan2 = ast_channel_unref(chan2);
09682       }
09683       pbx_builtin_setvar_helper(chan, name, tmp);
09684    }
09685 
09686    return(0);
09687 }

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

Definition at line 8990 of file pbx.c.

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

08991 {
08992    const char *options = data;
08993    int answer = 1;
08994 
08995    /* Some channels can receive DTMF in unanswered state; some cannot */
08996    if (!ast_strlen_zero(options) && strchr(options, 'n')) {
08997       answer = 0;
08998    }
08999 
09000    /* If the channel is hungup, stop waiting */
09001    if (ast_check_hangup(chan)) {
09002       return -1;
09003    } else if (chan->_state != AST_STATE_UP && answer) {
09004       __ast_answer(chan, 0, 1);
09005    }
09006 
09007    return AST_PBX_INCOMPLETE;
09008 }

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

Definition at line 9689 of file pbx.c.

09690 {
09691    return 0;
09692 }

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

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

Note:
Will lock the channel.

Definition at line 9494 of file pbx.c.

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

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

09495 {
09496    struct ast_var_t *newvariable;
09497    struct varshead *headp;
09498 
09499    if (name[strlen(name)-1] == ')') {
09500       char *function = ast_strdupa(name);
09501 
09502       ast_log(LOG_WARNING, "Cannot push a value onto a function\n");
09503       ast_func_write(chan, function, value);
09504       return;
09505    }
09506 
09507    if (chan) {
09508       ast_channel_lock(chan);
09509       headp = &chan->varshead;
09510    } else {
09511       ast_rwlock_wrlock(&globalslock);
09512       headp = &globals;
09513    }
09514 
09515    if (value) {
09516       if (headp == &globals)
09517          ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value);
09518       newvariable = ast_var_assign(name, value);
09519       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
09520    }
09521 
09522    if (chan)
09523       ast_channel_unlock(chan);
09524    else
09525       ast_rwlock_unlock(&globalslock);
09526 }

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

Definition at line 3125 of file pbx.c.

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

Referenced by __ast_pbx_run().

03126 {
03127    struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL);
03128    struct pbx_exception *exception = NULL;
03129 
03130    if (!ds) {
03131       ds = ast_datastore_alloc(&exception_store_info, NULL);
03132       if (!ds)
03133          return -1;
03134       if (!(exception = ast_calloc_with_stringfields(1, struct pbx_exception, 128))) {
03135          ast_datastore_free(ds);
03136          return -1;
03137       }
03138       ds->data = exception;
03139       ast_channel_datastore_add(chan, ds);
03140    } else
03141       exception = ds->data;
03142 
03143    ast_string_field_set(exception, reason, reason);
03144    ast_string_field_set(exception, context, chan->context);
03145    ast_string_field_set(exception, exten, chan->exten);
03146    exception->priority = chan->priority;
03147    set_ext_pri(chan, "e", 0);
03148    return 0;
03149 }

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

Definition at line 9777 of file pbx.c.

References ast_say_character_str(), and ast_channel::language.

09778 {
09779    int res = 0;
09780 
09781    if (data)
09782       res = ast_say_character_str(chan, data, "", chan->language);
09783    return res;
09784 }

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

Definition at line 9768 of file pbx.c.

References ast_say_digit_str(), and ast_channel::language.

09769 {
09770    int res = 0;
09771 
09772    if (data)
09773       res = ast_say_digit_str(chan, data, "", chan->language);
09774    return res;
09775 }

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

Definition at line 9740 of file pbx.c.

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

09741 {
09742    char tmp[256];
09743    char *number = tmp;
09744    char *options;
09745 
09746    if (ast_strlen_zero(data)) {
09747       ast_log(LOG_WARNING, "SayNumber requires an argument (number)\n");
09748       return -1;
09749    }
09750    ast_copy_string(tmp, data, sizeof(tmp));
09751    strsep(&number, ",");
09752    options = strsep(&number, ",");
09753    if (options) {
09754       if ( strcasecmp(options, "f") && strcasecmp(options, "m") &&
09755          strcasecmp(options, "c") && strcasecmp(options, "n") ) {
09756          ast_log(LOG_WARNING, "SayNumber gender option is either 'f', 'm', 'c' or 'n'\n");
09757          return -1;
09758       }
09759    }
09760 
09761    if (ast_say_number(chan, atoi(tmp), "", chan->language, options)) {
09762       ast_log(LOG_WARNING, "We were unable to say the number %s, is it too large?\n", tmp);
09763    }
09764 
09765    return 0;
09766 }

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

Definition at line 9786 of file pbx.c.

References ast_say_phonetic_str(), and ast_channel::language.

09787 {
09788    int res = 0;
09789 
09790    if (data)
09791       res = ast_say_phonetic_str(chan, data, "", chan->language);
09792    return res;
09793 }

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

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

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

Definition at line 9425 of file pbx.c.

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

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

09426 {
09427    struct ast_var_t *variables;
09428    const char *var, *val;
09429    int total = 0;
09430 
09431    if (!chan)
09432       return 0;
09433 
09434    ast_str_reset(*buf);
09435 
09436    ast_channel_lock(chan);
09437 
09438    AST_LIST_TRAVERSE(&chan->varshead, variables, entries) {
09439       if ((var = ast_var_name(variables)) && (val = ast_var_value(variables))
09440          /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */
09441          ) {
09442          if (ast_str_append(buf, 0, "%s=%s\n", var, val) < 0) {
09443             ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
09444             break;
09445          } else
09446             total++;
09447       } else
09448          break;
09449    }
09450 
09451    ast_channel_unlock(chan);
09452 
09453    return total;
09454 }

int pbx_builtin_setvar ( struct ast_channel chan,
const char *  data 
)

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

Note:
Will lock the channel.

Definition at line 9586 of file pbx.c.

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

Referenced by ast_compile_ael2(), and rpt_exec().

09587 {
09588    char *name, *value, *mydata;
09589 
09590    if (ast_compat_app_set) {
09591       return pbx_builtin_setvar_multiple(chan, data);
09592    }
09593 
09594    if (ast_strlen_zero(data)) {
09595       ast_log(LOG_WARNING, "Set requires one variable name/value pair.\n");
09596       return 0;
09597    }
09598 
09599    mydata = ast_strdupa(data);
09600    name = strsep(&mydata, "=");
09601    value = mydata;
09602    if (!value) {
09603       ast_log(LOG_WARNING, "Set requires an '=' to be a valid assignment.\n");
09604       return 0;
09605    }
09606 
09607    if (strchr(name, ' ')) {
09608       ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, mydata);
09609    }
09610 
09611    pbx_builtin_setvar_helper(chan, name, value);
09612 
09613    return 0;
09614 }

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

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

Note:
Will lock the channel. May also be used to set a channel dialplan function to a particular value.
See also:
ast_func_write
Returns:
-1 if the dialplan function fails to be set
Version:
1.8 changed the function to return an error code

Definition at line 9528 of file pbx.c.

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

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

09529 {
09530    struct ast_var_t *newvariable;
09531    struct varshead *headp;
09532    const char *nametail = name;
09533 
09534    if (name[strlen(name) - 1] == ')') {
09535       char *function = ast_strdupa(name);
09536 
09537       return ast_func_write(chan, function, value);
09538    }
09539 
09540    if (chan) {
09541       ast_channel_lock(chan);
09542       headp = &chan->varshead;
09543    } else {
09544       ast_rwlock_wrlock(&globalslock);
09545       headp = &globals;
09546    }
09547 
09548    /* For comparison purposes, we have to strip leading underscores */
09549    if (*nametail == '_') {
09550       nametail++;
09551       if (*nametail == '_')
09552          nametail++;
09553    }
09554 
09555    AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) {
09556       if (strcmp(ast_var_name(newvariable), nametail) == 0) {
09557          /* there is already such a variable, delete it */
09558          AST_LIST_REMOVE_CURRENT(entries);
09559          ast_var_delete(newvariable);
09560          break;
09561       }
09562    }
09563    AST_LIST_TRAVERSE_SAFE_END;
09564 
09565    if (value) {
09566       if (headp == &globals)
09567          ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value);
09568       newvariable = ast_var_assign(name, value);
09569       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
09570       manager_event(EVENT_FLAG_DIALPLAN, "VarSet",
09571          "Channel: %s\r\n"
09572          "Variable: %s\r\n"
09573          "Value: %s\r\n"
09574          "Uniqueid: %s\r\n",
09575          chan ? chan->name : "none", name, value,
09576          chan ? chan->uniqueid : "none");
09577    }
09578 
09579    if (chan)
09580       ast_channel_unlock(chan);
09581    else
09582       ast_rwlock_unlock(&globalslock);
09583    return 0;
09584 }

int pbx_builtin_setvar_multiple ( struct ast_channel chan,
const char *  data 
)

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

Note:
Will lock the channel.

Definition at line 9616 of file pbx.c.

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

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

09617 {
09618    char *data;
09619    int x;
09620    AST_DECLARE_APP_ARGS(args,
09621       AST_APP_ARG(pair)[24];
09622    );
09623    AST_DECLARE_APP_ARGS(pair,
09624       AST_APP_ARG(name);
09625       AST_APP_ARG(value);
09626    );
09627 
09628    if (ast_strlen_zero(vdata)) {
09629       ast_log(LOG_WARNING, "MSet requires at least one variable name/value pair.\n");
09630       return 0;
09631    }
09632 
09633    data = ast_strdupa(vdata);
09634    AST_STANDARD_APP_ARGS(args, data);
09635 
09636    for (x = 0; x < args.argc; x++) {
09637       AST_NONSTANDARD_APP_ARGS(pair, args.pair[x], '=');
09638       if (pair.argc == 2) {
09639          pbx_builtin_setvar_helper(chan, pair.name, pair.value);
09640          if (strchr(pair.name, ' '))
09641             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);
09642       } else if (!chan) {
09643          ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '='\n", pair.name);
09644       } else {
09645          ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '=' (in %s@%s:%d\n", pair.name, chan->exten, chan->context, chan->priority);
09646       }
09647    }
09648 
09649    return 0;
09650 }

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

References ast_strlen_zero().

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

09705 {
09706    int res;
09707    if (ast_strlen_zero(condition)) {                /* NULL or empty strings are false */
09708       return 0;
09709    } else if (sscanf(condition, "%30d", &res) == 1) { /* Numbers are evaluated for truth */
09710       return res;
09711    } else {                                         /* Strings are true */
09712       return 1;
09713    }
09714 }

static void pbx_destroy ( struct ast_pbx p  )  [static]

Definition at line 1459 of file pbx.c.

References ast_free.

01460 {
01461    ast_free(p);
01462 }

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

Execute an application.

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

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

Definition at line 1379 of file pbx.c.

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

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

01382 {
01383    int res;
01384    struct ast_module_user *u = NULL;
01385    const char *saved_c_appl;
01386    const char *saved_c_data;
01387 
01388    if (c->cdr && !ast_check_hangup(c))
01389       ast_cdr_setapp(c->cdr, app->name, data);
01390 
01391    /* save channel values */
01392    saved_c_appl= c->appl;
01393    saved_c_data= c->data;
01394 
01395    c->appl = app->name;
01396    c->data = data;
01397    ast_cel_report_event(c, AST_CEL_APP_START, NULL, NULL, NULL);
01398 
01399    if (app->module)
01400       u = __ast_module_user_add(app->module, c);
01401    if (strcasecmp(app->name, "system") && !ast_strlen_zero(data) &&
01402          strchr(data, '|') && !strchr(data, ',') && !ast_opt_dont_warn) {
01403       ast_log(LOG_WARNING, "The application delimiter is now the comma, not "
01404          "the pipe.  Did you forget to convert your dialplan?  (%s(%s))\n",
01405          app->name, (char *) data);
01406    }
01407    res = app->execute(c, S_OR(data, ""));
01408    if (app->module && u)
01409       __ast_module_user_remove(app->module, u);
01410    ast_cel_report_event(c, AST_CEL_APP_END, NULL, NULL, NULL);
01411    /* restore channel values */
01412    c->appl = saved_c_appl;
01413    c->data = saved_c_data;
01414    return res;
01415 }

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

04025 {
04026    struct ast_exten *e;
04027    struct ast_app *app;
04028    int res;
04029    struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */
04030    char passdata[EXT_DATA_SIZE];
04031 
04032    int matching_action = (action == E_MATCH || action == E_CANMATCH || action == E_MATCHMORE);
04033 
04034    ast_rdlock_contexts();
04035    if (found)
04036       *found = 0;
04037 
04038    e = pbx_find_extension(c, con, &q, context, exten, priority, label, callerid, action);
04039    if (e) {
04040       if (found)
04041          *found = 1;
04042       if (matching_action) {
04043          ast_unlock_contexts();
04044          return -1;  /* success, we found it */
04045       } else if (action == E_FINDLABEL) { /* map the label to a priority */
04046          res = e->priority;
04047          ast_unlock_contexts();
04048          return res; /* the priority we were looking for */
04049       } else { /* spawn */
04050          if (!e->cached_app)
04051             e->cached_app = pbx_findapp(e->app);
04052          app = e->cached_app;
04053          ast_unlock_contexts();
04054          if (!app) {
04055             ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority);
04056             return -1;
04057          }
04058          if (c->context != context)
04059             ast_copy_string(c->context, context, sizeof(c->context));
04060          if (c->exten != exten)
04061             ast_copy_string(c->exten, exten, sizeof(c->exten));
04062          c->priority = priority;
04063          pbx_substitute_variables(passdata, sizeof(passdata), c, e);
04064 #ifdef CHANNEL_TRACE
04065          ast_channel_trace_update(c);
04066 #endif
04067          ast_debug(1, "Launching '%s'\n", app->name);
04068          if (VERBOSITY_ATLEAST(3)) {
04069             char tmp[80], tmp2[80], tmp3[EXT_DATA_SIZE];
04070             ast_verb(3, "Executing [%s@%s:%d] %s(\"%s\", \"%s\") %s\n",
04071                exten, context, priority,
04072                term_color(tmp, app->name, COLOR_BRCYAN, 0, sizeof(tmp)),
04073                term_color(tmp2, c->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)),
04074                term_color(tmp3, passdata, COLOR_BRMAGENTA, 0, sizeof(tmp3)),
04075                "in new stack");
04076          }
04077          manager_event(EVENT_FLAG_DIALPLAN, "Newexten",
04078                "Channel: %s\r\n"
04079                "Context: %s\r\n"
04080                "Extension: %s\r\n"
04081                "Priority: %d\r\n"
04082                "Application: %s\r\n"
04083                "AppData: %s\r\n"
04084                "Uniqueid: %s\r\n",
04085                c->name, c->context, c->exten, c->priority, app->name, passdata, c->uniqueid);
04086          return pbx_exec(c, app, passdata);  /* 0 on success, -1 on failure */
04087       }
04088    } else if (q.swo) {  /* not found here, but in another switch */
04089       if (found)
04090          *found = 1;
04091       ast_unlock_contexts();
04092       if (matching_action) {
04093          return -1;
04094       } else {
04095          if (!q.swo->exec) {
04096             ast_log(LOG_WARNING, "No execution engine for switch %s\n", q.swo->name);
04097             res = -1;
04098          }
04099          return q.swo->exec(c, q.foundcontext ? q.foundcontext : context, exten, priority, callerid, q.data);
04100       }
04101    } else { /* not found anywhere, see what happened */
04102       ast_unlock_contexts();
04103       /* Using S_OR here because Solaris doesn't like NULL being passed to ast_log */
04104       switch (q.status) {
04105       case STATUS_NO_CONTEXT:
04106          if (!matching_action && !combined_find_spawn)
04107             ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", S_OR(context, ""));
04108          break;
04109       case STATUS_NO_EXTENSION:
04110          if (!matching_action && !combined_find_spawn)
04111             ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, S_OR(context, ""));
04112          break;
04113       case STATUS_NO_PRIORITY:
04114          if (!matching_action && !combined_find_spawn)
04115             ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, S_OR(context, ""));
04116          break;
04117       case STATUS_NO_LABEL:
04118          if (context && !combined_find_spawn)
04119             ast_log(LOG_NOTICE, "No such label '%s' in extension '%s' in context '%s'\n", label, exten, S_OR(context, ""));
04120          break;
04121       default:
04122          ast_debug(1, "Shouldn't happen!\n");
04123       }
04124 
04125       return (matching_action) ? 0 : -1;
04126    }
04127 }

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

References ast_context::alts, ast_autoservice_start(), ast_autoservice_stop(), ast_copy_string(), ast_hashtab_lookup(), AST_LIST_TRAVERSE, ast_log(), AST_PBX_MAX_STACK, ast_str_buffer(), ast_str_size(), ast_str_thread_get(), ast_strdupa, ast_strlen_zero(), ast_walk_context_extensions(), ast_switch::canmatch, scoreboard::canmatch_exten, contexts_table, create_match_char_tree(), ast_sw::data, pbx_find_info::data, E_CANMATCH, E_FINDLABEL, E_MATCHMORE, ast_sw::eval, ast_switch::exists, ast_exten::exten, scoreboard::exten, extenpatternmatchnew, extension_match_core(), pbx_find_info::foundcontext, include_valid(), ast_context::includes, pbx_find_info::incstack, ast_exten::label, scoreboard::last_char, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, match(), matchcid(), ast_switch::matchmore, ast_context::name, ast_sw::name, fake_context::name, new_find_extension(), ast_include::next, scoreboard::node, overrideswitch, ast_context::pattern_tree, pbx_find_extension(), pbx_findswitch(), pbx_substitute_variables_helper(), ast_exten::priority, ast_include::rname, ast_context::root_table, pbx_find_info::stacklen, pbx_find_info::status, STATUS_NO_CONTEXT, STATUS_NO_EXTENSION, STATUS_NO_LABEL, STATUS_NO_PRIORITY, STATUS_SUCCESS, 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(), ast_parking_ext_valid(), check_goto(), check_pval_item(), pbx_extension_helper(), pbx_find_extension(), and register_peer_exten().

02555 {
02556    int x, res;
02557    struct ast_context *tmp = NULL;
02558    struct ast_exten *e = NULL, *eroot = NULL;
02559    struct ast_include *i = NULL;
02560    struct ast_sw *sw = NULL;
02561    struct ast_exten pattern = {NULL, };
02562    struct scoreboard score = {0, };
02563    struct ast_str *tmpdata = NULL;
02564 
02565    pattern.label = label;
02566    pattern.priority = priority;
02567 #ifdef NEED_DEBUG_HERE
02568    ast_log(LOG_NOTICE, "Looking for cont/ext/prio/label/action = %s/%s/%d/%s/%d\n", context, exten, priority, label, (int) action);
02569 #endif
02570 
02571    /* Initialize status if appropriate */
02572    if (q->stacklen == 0) {
02573       q->status = STATUS_NO_CONTEXT;
02574       q->swo = NULL;
02575       q->data = NULL;
02576       q->foundcontext = NULL;
02577    } else if (q->stacklen >= AST_PBX_MAX_STACK) {
02578       ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n");
02579       return NULL;
02580    }
02581 
02582    /* Check first to see if we've already been checked */
02583    for (x = 0; x < q->stacklen; x++) {
02584       if (!strcasecmp(q->incstack[x], context))
02585          return NULL;
02586    }
02587 
02588    if (bypass) { /* bypass means we only look there */
02589       tmp = bypass;
02590    } else {      /* look in contexts */
02591       struct fake_context item;
02592 
02593       ast_copy_string(item.name, context, sizeof(item.name));
02594 
02595       tmp = ast_hashtab_lookup(contexts_table, &item);
02596       if (!tmp) {
02597          return NULL;
02598       }
02599    }
02600 
02601    if (q->status < STATUS_NO_EXTENSION)
02602       q->status = STATUS_NO_EXTENSION;
02603 
02604    /* Do a search for matching extension */
02605 
02606    eroot = NULL;
02607    score.total_specificity = 0;
02608    score.exten = 0;
02609    score.total_length = 0;
02610    if (!tmp->pattern_tree && tmp->root_table) {
02611       create_match_char_tree(tmp);
02612 #ifdef NEED_DEBUG
02613       ast_log(LOG_DEBUG, "Tree Created in context %s:\n", context);
02614       log_match_char_tree(tmp->pattern_tree," ");
02615 #endif
02616    }
02617 #ifdef NEED_DEBUG
02618    ast_log(LOG_NOTICE, "The Trie we are searching in:\n");
02619    log_match_char_tree(tmp->pattern_tree, "::  ");
02620 #endif
02621 
02622    do {
02623       if (!ast_strlen_zero(overrideswitch)) {
02624          char *osw = ast_strdupa(overrideswitch), *name;
02625          struct ast_switch *asw;
02626          ast_switch_f *aswf = NULL;
02627          char *datap;
02628          int eval = 0;
02629 
02630          name = strsep(&osw, "/");
02631          asw = pbx_findswitch(name);
02632 
02633          if (!asw) {
02634             ast_log(LOG_WARNING, "No such switch '%s'\n", name);
02635             break;
02636          }
02637 
02638          if (osw && strchr(osw, '$')) {
02639             eval = 1;
02640          }
02641 
02642          if (eval && !(tmpdata = ast_str_thread_get(&switch_data, 512))) {
02643             ast_log(LOG_WARNING, "Can't evaluate overrideswitch?!");
02644             break;
02645          } else if (eval) {
02646             /* Substitute variables now */
02647             pbx_substitute_variables_helper(chan, osw, ast_str_buffer(tmpdata), ast_str_size(tmpdata));
02648             datap = ast_str_buffer(tmpdata);
02649          } else {
02650             datap = osw;
02651          }
02652 
02653          /* equivalent of extension_match_core() at the switch level */
02654          if (action == E_CANMATCH)
02655             aswf = asw->canmatch;
02656          else if (action == E_MATCHMORE)
02657             aswf = asw->matchmore;
02658          else /* action == E_MATCH */
02659             aswf = asw->exists;
02660          if (!aswf) {
02661             res = 0;
02662          } else {
02663             if (chan) {
02664                ast_autoservice_start(chan);
02665             }
02666             res = aswf(chan, context, exten, priority, callerid, datap);
02667             if (chan) {
02668                ast_autoservice_stop(chan);
02669             }
02670          }
02671          if (res) {  /* Got a match */
02672             q->swo = asw;
02673             q->data = datap;
02674             q->foundcontext = context;
02675             /* XXX keep status = STATUS_NO_CONTEXT ? */
02676             return NULL;
02677          }
02678       }
02679    } while (0);
02680 
02681    if (extenpatternmatchnew) {
02682       new_find_extension(exten, &score, tmp->pattern_tree, 0, 0, callerid, label, action);
02683       eroot = score.exten;
02684 
02685       if (score.last_char == '!' && action == E_MATCHMORE) {
02686          /* We match an extension ending in '!'.
02687           * The decision in this case is final and is NULL (no match).
02688           */
02689 #ifdef NEED_DEBUG_HERE
02690          ast_log(LOG_NOTICE,"Returning MATCHMORE NULL with exclamation point.\n");
02691 #endif
02692          return NULL;
02693       }
02694 
02695       if (!eroot && (action == E_CANMATCH || action == E_MATCHMORE) && score.canmatch_exten) {
02696          q->status = STATUS_SUCCESS;
02697 #ifdef NEED_DEBUG_HERE
02698          ast_log(LOG_NOTICE,"Returning CANMATCH exten %s\n", score.canmatch_exten->exten);
02699 #endif
02700          return score.canmatch_exten;
02701       }
02702 
02703       if ((action == E_MATCHMORE || action == E_CANMATCH)  && eroot) {
02704          if (score.node) {
02705             struct ast_exten *z = trie_find_next_match(score.node);
02706             if (z) {
02707 #ifdef NEED_DEBUG_HERE
02708                ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten %s\n", z->exten);
02709 #endif
02710             } else {
02711                if (score.canmatch_exten) {
02712 #ifdef NEED_DEBUG_HERE
02713                   ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE canmatchmatch exten %s(%p)\n", score.canmatch_exten->exten, score.canmatch_exten);
02714 #endif
02715                   return score.canmatch_exten;
02716                } else {
02717 #ifdef NEED_DEBUG_HERE
02718                   ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten NULL\n");
02719 #endif
02720                }
02721             }
02722             return z;
02723          }
02724 #ifdef NEED_DEBUG_HERE
02725          ast_log(LOG_NOTICE, "Returning CANMATCH/MATCHMORE NULL (no next_match)\n");
02726 #endif
02727          return NULL;  /* according to the code, complete matches are null matches in MATCHMORE mode */
02728       }
02729 
02730       if (eroot) {
02731          /* found entry, now look for the right priority */
02732          if (q->status < STATUS_NO_PRIORITY)
02733             q->status = STATUS_NO_PRIORITY;
02734          e = NULL;
02735          if (action == E_FINDLABEL && label ) {
02736             if (q->status < STATUS_NO_LABEL)
02737                q->status = STATUS_NO_LABEL;
02738             e = ast_hashtab_lookup(eroot->peer_label_table, &pattern);
02739          } else {
02740             e = ast_hashtab_lookup(eroot->peer_table, &pattern);
02741          }
02742          if (e) { /* found a valid match */
02743             q->status = STATUS_SUCCESS;
02744             q->foundcontext = context;
02745 #ifdef NEED_DEBUG_HERE
02746             ast_log(LOG_NOTICE,"Returning complete match of exten %s\n", e->exten);
02747 #endif
02748             return e;
02749          }
02750       }
02751    } else {   /* the old/current default exten pattern match algorithm */
02752 
02753       /* scan the list trying to match extension and CID */
02754       eroot = NULL;
02755       while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) {
02756          int match = extension_match_core(eroot->exten, exten, action);
02757          /* 0 on fail, 1 on match, 2 on earlymatch */
02758 
02759          if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid)))
02760             continue;   /* keep trying */
02761          if (match == 2 && action == E_MATCHMORE) {
02762             /* We match an extension ending in '!'.
02763              * The decision in this case is final and is NULL (no match).
02764              */
02765             return NULL;
02766          }
02767          /* found entry, now look for the right priority */
02768          if (q->status < STATUS_NO_PRIORITY)
02769             q->status = STATUS_NO_PRIORITY;
02770          e = NULL;
02771          if (action == E_FINDLABEL && label ) {
02772             if (q->status < STATUS_NO_LABEL)
02773                q->status = STATUS_NO_LABEL;
02774             e = ast_hashtab_lookup(eroot->peer_label_table, &pattern);
02775          } else {
02776             e = ast_hashtab_lookup(eroot->peer_table, &pattern);
02777          }
02778          if (e) { /* found a valid match */
02779             q->status = STATUS_SUCCESS;
02780             q->foundcontext = context;
02781             return e;
02782          }
02783       }
02784    }
02785 
02786    /* Check alternative switches */
02787    AST_LIST_TRAVERSE(&tmp->alts, sw, list) {
02788       struct ast_switch *asw = pbx_findswitch(sw->name);
02789       ast_switch_f *aswf = NULL;
02790       char *datap;
02791 
02792       if (!asw) {
02793          ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name);
02794          continue;
02795       }
02796 
02797       /* Substitute variables now */
02798       if (sw->eval) {
02799          if (!(tmpdata = ast_str_thread_get(&switch_data, 512))) {
02800             ast_log(LOG_WARNING, "Can't evaluate switch?!");
02801             continue;
02802          }
02803          pbx_substitute_variables_helper(chan, sw->data, ast_str_buffer(tmpdata), ast_str_size(tmpdata));
02804       }
02805 
02806       /* equivalent of extension_match_core() at the switch level */
02807       if (action == E_CANMATCH)
02808          aswf = asw->canmatch;
02809       else if (action == E_MATCHMORE)
02810          aswf = asw->matchmore;
02811       else /* action == E_MATCH */
02812          aswf = asw->exists;
02813       datap = sw->eval ? ast_str_buffer(tmpdata) : sw->data;
02814       if (!aswf)
02815          res = 0;
02816       else {
02817          if (chan)
02818             ast_autoservice_start(chan);
02819          res = aswf(chan, context, exten, priority, callerid, datap);
02820          if (chan)
02821             ast_autoservice_stop(chan);
02822       }
02823       if (res) {  /* Got a match */
02824          q->swo = asw;
02825          q->data = datap;
02826          q->foundcontext = context;
02827          /* XXX keep status = STATUS_NO_CONTEXT ? */
02828          return NULL;
02829       }
02830    }
02831    q->incstack[q->stacklen++] = tmp->name;   /* Setup the stack */
02832    /* Now try any includes we have in this context */
02833    for (i = tmp->includes; i; i = i->next) {
02834       if (include_valid(i)) {
02835          if ((e = pbx_find_extension(chan, bypass, q, i->rname, exten, priority, label, callerid, action))) {
02836 #ifdef NEED_DEBUG_HERE
02837             ast_log(LOG_NOTICE,"Returning recursive match of %s\n", e->exten);
02838 #endif
02839             return e;
02840          }
02841          if (q->swo)
02842             return NULL;
02843       }
02844    }
02845    return NULL;
02846 }

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 1423 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_app_run_macro(), ast_bridge_call(), ast_pbx_run_app(), async_wait(), builtin_automixmonitor(), builtin_automonitor(), conf_run(), dial_exec_full(), do_magic_pickup(), dundi_exec(), exec_exec(), execif_exec(), feature_exec_app(), forward_message(), handle_exec(), handle_gosub(), iax2_exec(), lua_pbx_exec(), page_exec(), pbx_builtin_execiftime(), pbx_extension_helper(), and tryexec_exec().

01424 {
01425    struct ast_app *tmp;
01426 
01427    AST_RWLIST_RDLOCK(&apps);
01428    AST_RWLIST_TRAVERSE(&apps, tmp, list) {
01429       if (!strcasecmp(tmp->name, app))
01430          break;
01431    }
01432    AST_RWLIST_UNLOCK(&apps);
01433 
01434    return tmp;
01435 }

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

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

01438 {
01439    struct ast_switch *asw;
01440 
01441    AST_RWLIST_RDLOCK(&switches);
01442    AST_RWLIST_TRAVERSE(&switches, asw, list) {
01443       if (!strcasecmp(asw->name, sw))
01444          break;
01445    }
01446    AST_RWLIST_UNLOCK(&switches);
01447 
01448    return asw;
01449 }

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

Definition at line 10138 of file pbx.c.

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

Referenced by ast_async_parseable_goto(), and ast_parseable_goto().

10139 {
10140    char *exten, *pri, *context;
10141    char *stringp;
10142    int ipri;
10143    int mode = 0;
10144 
10145    if (ast_strlen_zero(goto_string)) {
10146       ast_log(LOG_WARNING, "Goto requires an argument ([[context,]extension,]priority)\n");
10147       return -1;
10148    }
10149    stringp = ast_strdupa(goto_string);
10150    context = strsep(&stringp, ","); /* guaranteed non-null */
10151    exten = strsep(&stringp, ",");
10152    pri = strsep(&stringp, ",");
10153    if (!exten) {  /* Only a priority in this one */
10154       pri = context;
10155       exten = NULL;
10156       context = NULL;
10157    } else if (!pri) {   /* Only an extension and priority in this one */
10158       pri = exten;
10159       exten = context;
10160       context = NULL;
10161    }
10162    if (*pri == '+') {
10163       mode = 1;
10164       pri++;
10165    } else if (*pri == '-') {
10166       mode = -1;
10167       pri++;
10168    }
10169    if (sscanf(pri, "%30d", &ipri) != 1) {
10170       ipri = ast_findlabel_extension(chan, context ? context : chan->context,
10171          exten ? exten : chan->exten, pri,
10172          S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL));
10173       if (ipri < 1) {
10174          ast_log(LOG_WARNING, "Priority '%s' must be a number > 0, or valid label\n", pri);
10175          return -1;
10176       } else
10177          mode = 0;
10178    }
10179    /* At this point we have a priority and maybe an extension and a context */
10180 
10181    if (mode)
10182       ipri = chan->priority + (ipri * mode);
10183 
10184    if (async)
10185       ast_async_goto(chan, context, exten, ipri);
10186    else
10187       ast_explicit_goto(chan, context, exten, ipri);
10188 
10189    return 0;
10190 
10191 }

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

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

Note:
See also

Definition at line 2976 of file pbx.c.

References ast_copy_string(), ast_free, ast_str_buffer(), ast_str_create(), ast_str_retrieve_variable(), and str.

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

02977 {
02978    struct ast_str *str = ast_str_create(16);
02979    const char *cret;
02980 
02981    cret = ast_str_retrieve_variable(&str, 0, c, headp, var);
02982    ast_copy_string(workspace, ast_str_buffer(str), workspacelen);
02983    *ret = cret ? workspace : NULL;
02984    ast_free(str);
02985 }

int pbx_set_autofallthrough ( int  newval  ) 

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

Definition at line 5074 of file pbx.c.

References autofallthrough.

Referenced by pbx_load_module().

05075 {
05076    int oldval = autofallthrough;
05077    autofallthrough = newval;
05078    return oldval;
05079 }

int pbx_set_extenpatternmatchnew ( int  newval  ) 

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

Definition at line 5081 of file pbx.c.

References extenpatternmatchnew.

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

05082 {
05083    int oldval = extenpatternmatchnew;
05084    extenpatternmatchnew = newval;
05085    return oldval;
05086 }

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

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

Referenced by pbx_load_module().

05089 {
05090    if (overrideswitch) {
05091       ast_free(overrideswitch);
05092    }
05093    if (!ast_strlen_zero(newval)) {
05094       overrideswitch = ast_strdup(newval);
05095    } else {
05096       overrideswitch = NULL;
05097    }
05098 }

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

Definition at line 3985 of file pbx.c.

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

Referenced by pbx_extension_helper().

03986 {
03987    const char *tmp;
03988 
03989    /* Nothing more to do */
03990    if (!e->data) {
03991       *passdata = '\0';
03992       return;
03993    }
03994 
03995    /* No variables or expressions in e->data, so why scan it? */
03996    if ((!(tmp = strchr(e->data, '$'))) || (!strstr(tmp, "${") && !strstr(tmp, "$["))) {
03997       ast_copy_string(passdata, e->data, datalen);
03998       return;
03999    }
04000 
04001    pbx_substitute_variables_helper(c, e->data, passdata, datalen - 1);
04002 }

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

Definition at line 3973 of file pbx.c.

References pbx_substitute_variables_helper_full(), and ast_channel::varshead.

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

03974 {
03975    size_t used;
03976    pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count, &used);
03977 }

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

Definition at line 3777 of file pbx.c.

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

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

03778 {
03779    /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!!  */
03780    char *cp4 = NULL;
03781    const char *tmp, *whereweare, *orig_cp2 = cp2;
03782    int length, offset, offset2, isfunction;
03783    char *workspace = NULL;
03784    char *ltmp = NULL, *var = NULL;
03785    char *nextvar, *nextexp, *nextthing;
03786    char *vars, *vare;
03787    int pos, brackets, needsub, len;
03788 
03789    *cp2 = 0; /* just in case nothing ends up there */
03790    whereweare=tmp=cp1;
03791    while (!ast_strlen_zero(whereweare) && count) {
03792       /* Assume we're copying the whole remaining string */
03793       pos = strlen(whereweare);
03794       nextvar = NULL;
03795       nextexp = NULL;
03796       nextthing = strchr(whereweare, '$');
03797       if (nextthing) {
03798          switch (nextthing[1]) {
03799          case '{':
03800             nextvar = nextthing;
03801             pos = nextvar - whereweare;
03802             break;
03803          case '[':
03804             nextexp = nextthing;
03805             pos = nextexp - whereweare;
03806             break;
03807          default:
03808             pos = 1;
03809          }
03810       }
03811 
03812       if (pos) {
03813          /* Can't copy more than 'count' bytes */
03814          if (pos > count)
03815             pos = count;
03816 
03817          /* Copy that many bytes */
03818          memcpy(cp2, whereweare, pos);
03819 
03820          count -= pos;
03821          cp2 += pos;
03822          whereweare += pos;
03823          *cp2 = 0;
03824       }
03825 
03826       if (nextvar) {
03827          /* We have a variable.  Find the start and end, and determine
03828             if we are going to have to recursively call ourselves on the
03829             contents */
03830          vars = vare = nextvar + 2;
03831          brackets = 1;
03832          needsub = 0;
03833 
03834          /* Find the end of it */
03835          while (brackets && *vare) {
03836             if ((vare[0] == '$') && (vare[1] == '{')) {
03837                needsub++;
03838             } else if (vare[0] == '{') {
03839                brackets++;
03840             } else if (vare[0] == '}') {
03841                brackets--;
03842             } else if ((vare[0] == '$') && (vare[1] == '['))
03843                needsub++;
03844             vare++;
03845          }
03846          if (brackets)
03847             ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n");
03848          len = vare - vars - 1;
03849 
03850          /* Skip totally over variable string */
03851          whereweare += (len + 3);
03852 
03853          if (!var)
03854             var = alloca(VAR_BUF_SIZE);
03855 
03856          /* Store variable name (and truncate) */
03857          ast_copy_string(var, vars, len + 1);
03858 
03859          /* Substitute if necessary */
03860          if (needsub) {
03861             size_t used;
03862             if (!ltmp)
03863                ltmp = alloca(VAR_BUF_SIZE);
03864 
03865             pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used);
03866             vars = ltmp;
03867          } else {
03868             vars = var;
03869          }
03870 
03871          if (!workspace)
03872             workspace = alloca(VAR_BUF_SIZE);
03873 
03874          workspace[0] = '\0';
03875 
03876          parse_variable_name(vars, &offset, &offset2, &isfunction);
03877          if (isfunction) {
03878             /* Evaluate function */
03879             if (c || !headp)
03880                cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
03881             else {
03882                struct varshead old;
03883                struct ast_channel *c = ast_dummy_channel_alloc();
03884                if (c) {
03885                   memcpy(&old, &c->varshead, sizeof(old));
03886                   memcpy(&c->varshead, headp, sizeof(c->varshead));
03887                   cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
03888                   /* Don't deallocate the varshead that was passed in */
03889                   memcpy(&c->varshead, &old, sizeof(c->varshead));
03890                   c = ast_channel_release(c);
03891                } else {
03892                   ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution.  Function results may be blank.\n");
03893                }
03894             }
03895             ast_debug(2, "Function result is '%s'\n", cp4 ? cp4 : "(null)");
03896          } else {
03897             /* Retrieve variable value */
03898             pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp);
03899          }
03900          if (cp4) {
03901             cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE);
03902 
03903             length = strlen(cp4);
03904             if (length > count)
03905                length = count;
03906             memcpy(cp2, cp4, length);
03907             count -= length;
03908             cp2 += length;
03909             *cp2 = 0;
03910          }
03911       } else if (nextexp) {
03912          /* We have an expression.  Find the start and end, and determine
03913             if we are going to have to recursively call ourselves on the
03914             contents */
03915          vars = vare = nextexp + 2;
03916          brackets = 1;
03917          needsub = 0;
03918 
03919          /* Find the end of it */
03920          while (brackets && *vare) {
03921             if ((vare[0] == '$') && (vare[1] == '[')) {
03922                needsub++;
03923                brackets++;
03924                vare++;
03925             } else if (vare[0] == '[') {
03926                brackets++;
03927             } else if (vare[0] == ']') {
03928                brackets--;
03929             } else if ((vare[0] == '$') && (vare[1] == '{')) {
03930                needsub++;
03931                vare++;
03932             }
03933             vare++;
03934          }
03935          if (brackets)
03936             ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n");
03937          len = vare - vars - 1;
03938 
03939          /* Skip totally over expression */
03940          whereweare += (len + 3);
03941 
03942          if (!var)
03943             var = alloca(VAR_BUF_SIZE);
03944 
03945          /* Store variable name (and truncate) */
03946          ast_copy_string(var, vars, len + 1);
03947 
03948          /* Substitute if necessary */
03949          if (needsub) {
03950             size_t used;
03951             if (!ltmp)
03952                ltmp = alloca(VAR_BUF_SIZE);
03953 
03954             pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used);
03955             vars = ltmp;
03956          } else {
03957             vars = var;
03958          }
03959 
03960          length = ast_expr(vars, cp2, count, c);
03961 
03962          if (length) {
03963             ast_debug(1, "Expression result is '%s'\n", cp2);
03964             count -= length;
03965             cp2 += length;
03966             *cp2 = 0;
03967          }
03968       }
03969    }
03970    *used = cp2 - orig_cp2;
03971 }

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

Definition at line 3979 of file pbx.c.

References pbx_substitute_variables_helper_full().

Referenced by dundi_lookup_local(), and loopback_subst().

03980 {
03981    size_t used;
03982    pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count, &used);
03983 }

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

Definition at line 5002 of file pbx.c.

References __ast_pbx_run(), and decrease_call_count().

Referenced by ast_pbx_start().

05003 {
05004    /* Oh joyeous kernel, we're a new thread, with nothing to do but
05005       answer this channel and get it going.
05006    */
05007    /* NOTE:
05008       The launcher of this function _MUST_ increment 'countcalls'
05009       before invoking the function; it will be decremented when the
05010       PBX has finished running on the channel
05011     */
05012    struct ast_channel *c = data;
05013 
05014    __ast_pbx_run(c, NULL);
05015    decrease_call_count();
05016 
05017    pthread_exit(NULL);
05018 
05019    return NULL;
05020 }

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

Definition at line 5620 of file pbx.c.

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

Referenced by handle_show_application().

05621 {
05622    /* Maximum number of characters added by terminal coloring is 22 */
05623    char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40], stxtitle[40], argtitle[40];
05624    char seealsotitle[40];
05625    char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL, *syntax = NULL, *arguments = NULL;
05626    char *seealso = NULL;
05627    int syntax_size, synopsis_size, description_size, arguments_size, seealso_size;
05628 
05629    snprintf(info, sizeof(info), "\n  -= Info about application '%s' =- \n\n", aa->name);
05630    term_color(infotitle, info, COLOR_MAGENTA, 0, sizeof(infotitle));
05631 
05632    term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
05633    term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
05634    term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40);
05635    term_color(argtitle, "[Arguments]\n", COLOR_MAGENTA, 0, 40);
05636    term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, 40);
05637 
05638 #ifdef AST_XML_DOCS
05639    if (aa->docsrc == AST_XML_DOC) {
05640       description = ast_xmldoc_printable(S_OR(aa->description, "Not available"), 1);
05641       arguments = ast_xmldoc_printable(S_OR(aa->arguments, "Not available"), 1);
05642       synopsis = ast_xmldoc_printable(S_OR(aa->synopsis, "Not available"), 1);
05643       seealso = ast_xmldoc_printable(S_OR(aa->seealso, "Not available"), 1);
05644 
05645       if (!synopsis || !description || !arguments || !seealso) {
05646          goto return_cleanup;
05647       }
05648    } else
05649 #endif
05650    {
05651       synopsis_size = strlen(S_OR(aa->synopsis, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
05652       synopsis = ast_malloc(synopsis_size);
05653 
05654       description_size = strlen(S_OR(aa->description, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
05655       description = ast_malloc(description_size);
05656 
05657       arguments_size = strlen(S_OR(aa->arguments, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
05658       arguments = ast_malloc(arguments_size);
05659 
05660       seealso_size = strlen(S_OR(aa->seealso, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
05661       seealso = ast_malloc(seealso_size);
05662 
05663       if (!synopsis || !description || !arguments || !seealso) {
05664          goto return_cleanup;
05665       }
05666 
05667       term_color(synopsis, S_OR(aa->synopsis, "Not available"), COLOR_CYAN, 0, synopsis_size);
05668       term_color(description, S_OR(aa->description, "Not available"),   COLOR_CYAN, 0, description_size);
05669       term_color(arguments, S_OR(aa->arguments, "Not available"), COLOR_CYAN, 0, arguments_size);
05670       term_color(seealso, S_OR(aa->seealso, "Not available"), COLOR_CYAN, 0, seealso_size);
05671    }
05672 
05673    /* Handle the syntax the same for both XML and raw docs */
05674    syntax_size = strlen(S_OR(aa->syntax, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
05675    if (!(syntax = ast_malloc(syntax_size))) {
05676       goto return_cleanup;
05677    }
05678    term_color(syntax, S_OR(aa->syntax, "Not available"), COLOR_CYAN, 0, syntax_size);
05679 
05680    ast_cli(fd, "%s%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n",
05681          infotitle, syntitle, synopsis, destitle, description,
05682          stxtitle, syntax, argtitle, arguments, seealsotitle, seealso);
05683 
05684 return_cleanup:
05685    ast_free(description);
05686    ast_free(arguments);
05687    ast_free(synopsis);
05688    ast_free(seealso);
05689    ast_free(syntax);
05690 }

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

helper function to print an extension

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

06036 {
06037    int prio = ast_get_extension_priority(e);
06038    if (prio == PRIORITY_HINT) {
06039       snprintf(buf, buflen, "hint: %s",
06040          ast_get_extension_app(e));
06041    } else {
06042       snprintf(buf, buflen, "%d. %s(%s)",
06043          prio, ast_get_extension_app(e),
06044          (!ast_strlen_zero(ast_get_extension_app_data(e)) ? (char *)ast_get_extension_app_data(e) : ""));
06045    }
06046 }

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

04610 {
04611    ast_channel_lock(c);
04612    ast_copy_string(c->exten, exten, sizeof(c->exten));
04613    c->priority = pri;
04614    ast_channel_unlock(c);
04615 }

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

06201 {
06202    struct ast_context *c = NULL;
06203    int res = 0, old_total_exten = dpc->total_exten;
06204 
06205    ast_cli(fd,"\n     In-mem exten Trie for Fast Extension Pattern Matching:\n\n");
06206 
06207    ast_cli(fd,"\n           Explanation: Node Contents Format = <char(s) to match>:<pattern?>:<specif>:[matched extension]\n");
06208    ast_cli(fd,    "                        Where <char(s) to match> is a set of chars, any one of which should match the current character\n");
06209    ast_cli(fd,    "                              <pattern?>: Y if this a pattern match (eg. _XZN[5-7]), N otherwise\n");
06210    ast_cli(fd,    "                              <specif>: an assigned 'exactness' number for this matching char. The lower the number, the more exact the match\n");
06211    ast_cli(fd,    "                              [matched exten]: If all chars matched to this point, which extension this matches. In form: EXTEN:<exten string>\n");
06212    ast_cli(fd,    "                        In general, you match a trie node to a string character, from left to right. All possible matching chars\n");
06213    ast_cli(fd,    "                        are in a string vertically, separated by an unbroken string of '+' characters.\n\n");
06214    ast_rdlock_contexts();
06215 
06216    /* walk all contexts ... */
06217    while ( (c = ast_walk_contexts(c)) ) {
06218       int context_info_printed = 0;
06219 
06220       if (context && strcmp(ast_get_context_name(c), context))
06221          continue;   /* skip this one, name doesn't match */
06222 
06223       dpc->context_existence = 1;
06224 
06225       if (!c->pattern_tree)
06226          ast_exists_extension(NULL, c->name, "s", 1, ""); /* do this to force the trie to built, if it is not already */
06227 
06228       ast_rdlock_context(c);
06229 
06230       dpc->total_context++;
06231       ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
06232          ast_get_context_name(c), ast_get_context_registrar(c));
06233       context_info_printed = 1;
06234 
06235       if (c->pattern_tree)
06236       {
06237          cli_match_char_tree(c->pattern_tree, " ", fd);
06238       } else {
06239          ast_cli(fd,"\n     No Pattern Trie present. Perhaps the context is empty...or there is trouble...\n\n");
06240       }
06241 
06242       ast_unlock_context(c);
06243 
06244       /* if we print something in context, make an empty line */
06245       if (context_info_printed)
06246          ast_cli(fd, "\n");
06247    }
06248    ast_unlock_contexts();
06249 
06250    return (dpc->total_exten == old_total_exten) ? -1 : res;
06251 }

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

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

Referenced by handle_show_dialplan().

06050 {
06051    struct ast_context *c = NULL;
06052    int res = 0, old_total_exten = dpc->total_exten;
06053 
06054    ast_rdlock_contexts();
06055 
06056    /* walk all contexts ... */
06057    while ( (c = ast_walk_contexts(c)) ) {
06058       struct ast_exten *e;
06059       struct ast_include *i;
06060       struct ast_ignorepat *ip;
06061       char buf[256], buf2[256];
06062       int context_info_printed = 0;
06063 
06064       if (context && strcmp(ast_get_context_name(c), context))
06065          continue;   /* skip this one, name doesn't match */
06066 
06067       dpc->context_existence = 1;
06068 
06069       ast_rdlock_context(c);
06070 
06071       /* are we looking for exten too? if yes, we print context
06072        * only if we find our extension.
06073        * Otherwise print context even if empty ?
06074        * XXX i am not sure how the rinclude is handled.
06075        * I think it ought to go inside.
06076        */
06077       if (!exten) {
06078          dpc->total_context++;
06079          ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
06080             ast_get_context_name(c), ast_get_context_registrar(c));
06081          context_info_printed = 1;
06082       }
06083 
06084       /* walk extensions ... */
06085       e = NULL;
06086       while ( (e = ast_walk_context_extensions(c, e)) ) {
06087          struct ast_exten *p;
06088 
06089          if (exten && !ast_extension_match(ast_get_extension_name(e), exten))
06090             continue;   /* skip, extension match failed */
06091 
06092          dpc->extension_existence = 1;
06093 
06094          /* may we print context info? */
06095          if (!context_info_printed) {
06096             dpc->total_context++;
06097             if (rinclude) { /* TODO Print more info about rinclude */
06098                ast_cli(fd, "[ Included context '%s' created by '%s' ]\n",
06099                   ast_get_context_name(c), ast_get_context_registrar(c));
06100             } else {
06101                ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
06102                   ast_get_context_name(c), ast_get_context_registrar(c));
06103             }
06104             context_info_printed = 1;
06105          }
06106          dpc->total_prio++;
06107 
06108          /* write extension name and first peer */
06109          if (e->matchcid)
06110             snprintf(buf, sizeof(buf), "'%s' (CID match '%s') => ", ast_get_extension_name(e), e->cidmatch);
06111          else
06112             snprintf(buf, sizeof(buf), "'%s' =>", ast_get_extension_name(e));
06113 
06114          print_ext(e, buf2, sizeof(buf2));
06115 
06116          ast_cli(fd, "  %-17s %-45s [%s]\n", buf, buf2,
06117             ast_get_extension_registrar(e));
06118 
06119          dpc->total_exten++;
06120          /* walk next extension peers */
06121          p = e;   /* skip the first one, we already got it */
06122          while ( (p = ast_walk_extension_priorities(e, p)) ) {
06123             const char *el = ast_get_extension_label(p);
06124             dpc->total_prio++;
06125             if (el)
06126                snprintf(buf, sizeof(buf), "   [%s]", el);
06127             else
06128                buf[0] = '\0';
06129             print_ext(p, buf2, sizeof(buf2));
06130 
06131             ast_cli(fd,"  %-17s %-45s [%s]\n", buf, buf2,
06132                ast_get_extension_registrar(p));
06133          }
06134       }
06135 
06136       /* walk included and write info ... */
06137       i = NULL;
06138       while ( (i = ast_walk_context_includes(c, i)) ) {
06139          snprintf(buf, sizeof(buf), "'%s'", ast_get_include_name(i));
06140          if (exten) {
06141             /* Check all includes for the requested extension */
06142             if (includecount >= AST_PBX_MAX_STACK) {
06143                ast_log(LOG_WARNING, "Maximum include depth exceeded!\n");
06144             } else {
06145                int dupe = 0;
06146                int x;
06147                for (x = 0; x < includecount; x++) {
06148                   if (!strcasecmp(includes[x], ast_get_include_name(i))) {
06149                      dupe++;
06150                      break;
06151                   }
06152                }
06153                if (!dupe) {
06154                   includes[includecount] = ast_get_include_name(i);
06155                   show_dialplan_helper(fd, ast_get_include_name(i), exten, dpc, i, includecount + 1, includes);
06156                } else {
06157                   ast_log(LOG_WARNING, "Avoiding circular include of %s within %s\n", ast_get_include_name(i), context);
06158                }
06159             }
06160          } else {
06161             ast_cli(fd, "  Include =>        %-45s [%s]\n",
06162                buf, ast_get_include_registrar(i));
06163          }
06164       }
06165 
06166       /* walk ignore patterns and write info ... */
06167       ip = NULL;
06168       while ( (ip = ast_walk_context_ignorepats(c, ip)) ) {
06169          const char *ipname = ast_get_ignorepat_name(ip);
06170          char ignorepat[AST_MAX_EXTENSION];
06171          snprintf(buf, sizeof(buf), "'%s'", ipname);
06172          snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname);
06173          if (!exten || ast_extension_match(ignorepat, exten)) {
06174             ast_cli(fd, "  Ignore pattern => %-45s [%s]\n",
06175                buf, ast_get_ignorepat_registrar(ip));
06176          }
06177       }
06178       if (!rinclude) {
06179          struct ast_sw *sw = NULL;
06180          while ( (sw = ast_walk_context_switches(c, sw)) ) {
06181             snprintf(buf, sizeof(buf), "'%s/%s'",
06182                ast_get_switch_name(sw),
06183                ast_get_switch_data(sw));
06184             ast_cli(fd, "  Alt. Switch =>    %-45s [%s]\n",
06185                buf, ast_get_switch_registrar(sw));
06186          }
06187       }
06188 
06189       ast_unlock_context(c);
06190 
06191       /* if we print something in context, make an empty line */
06192       if (context_info_printed)
06193          ast_cli(fd, "\n");
06194    }
06195    ast_unlock_contexts();
06196 
06197    return (dpc->total_exten == old_total_exten) ? -1 : res;
06198 }

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

References ast_copy_string().

Referenced by pbx_substitute_variables_helper_full().

02887 {
02888    char *ret = workspace;
02889    int lr;  /* length of the input string after the copy */
02890 
02891    ast_copy_string(workspace, value, workspace_len); /* always make a copy */
02892 
02893    lr = strlen(ret); /* compute length after copy, so we never go out of the workspace */
02894 
02895    /* Quick check if no need to do anything */
02896    if (offset == 0 && length >= lr) /* take the whole string */
02897       return ret;
02898 
02899    if (offset < 0)   {  /* translate negative offset into positive ones */
02900       offset = lr + offset;
02901       if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */
02902          offset = 0;
02903    }
02904 
02905    /* too large offset result in empty string so we know what to return */
02906    if (offset >= lr)
02907       return ret + lr;  /* the final '\0' */
02908 
02909    ret += offset;    /* move to the start position */
02910    if (length >= 0 && length < lr - offset)  /* truncate if necessary */
02911       ret[length] = '\0';
02912    else if (length < 0) {
02913       if (lr > offset - length) /* After we remove from the front and from the rear, is there anything left? */
02914          ret[lr + length - offset] = '\0';
02915       else
02916          ret[0] = '\0';
02917    }
02918 
02919    return ret;
02920 }

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

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

01634 {
01635    struct match_char *m3;
01636    struct match_char *m4;
01637    struct ast_exten *e3;
01638 
01639    if (node && node->x[0] == '.' && !node->x[1]) { /* dot and ! will ALWAYS be next match in a matchmore */
01640       return node->exten;
01641    }
01642 
01643    if (node && node->x[0] == '!' && !node->x[1]) {
01644       return node->exten;
01645    }
01646 
01647    if (!node || !node->next_char) {
01648       return NULL;
01649    }
01650 
01651    m3 = node->next_char;
01652 
01653    if (m3->exten) {
01654       return m3->exten;
01655    }
01656    for (m4 = m3->alt_char; m4; m4 = m4->alt_char) {
01657       if (m4->exten) {
01658          return m4->exten;
01659       }
01660    }
01661    for (m4 = m3; m4; m4 = m4->alt_char) {
01662       e3 = trie_find_next_match(m3);
01663       if (e3) {
01664          return e3;
01665       }
01666    }
01667 
01668    return NULL;
01669 }

static void unreference_cached_app ( struct ast_app app  )  [static]

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

06809 {
06810    struct ast_context *context = NULL;
06811    struct ast_exten *eroot = NULL, *e = NULL;
06812 
06813    ast_rdlock_contexts();
06814    while ((context = ast_walk_contexts(context))) {
06815       while ((eroot = ast_walk_context_extensions(context, eroot))) {
06816          while ((e = ast_walk_extension_priorities(eroot, e))) {
06817             if (e->cached_app == app)
06818                e->cached_app = NULL;
06819          }
06820       }
06821    }
06822    ast_unlock_contexts();
06823 
06824    return;
06825 }

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

01539 {
01540    /* if this extension is marked as deleted, then skip this -- if it never shows
01541       on the scoreboard, it will never be found, nor will halt the traversal. */
01542    if (deleted)
01543       return;
01544    board->total_specificity = spec;
01545    board->total_length = length;
01546    board->exten = exten;
01547    board->last_char = last;
01548    board->node = node;
01549 #ifdef NEED_DEBUG_HERE
01550    ast_log(LOG_NOTICE,"Scoreboarding (LONGER) %s, len=%d, score=%d\n", exten->exten, length, spec);
01551 #endif
01552 }

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

Definition at line 8876 of file pbx.c.

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

Referenced by pbx_builtin_busy(), and pbx_builtin_congestion().

08877 {
08878    int res;
08879    struct ast_frame *f;
08880    double waitsec;
08881    int waittime;
08882 
08883    if (ast_strlen_zero(data) || (sscanf(data, "%30lg", &waitsec) != 1) || (waitsec < 0))
08884       waitsec = -1;
08885    if (waitsec > -1) {
08886       waittime = waitsec * 1000.0;
08887       ast_safe_sleep(chan, waittime);
08888    } else do {
08889       res = ast_waitfor(chan, -1);
08890       if (res < 0)
08891          return;
08892       f = ast_read(chan);
08893       if (f)
08894          ast_frfree(f);
08895    } while(f);
08896 }


Variable Documentation

int autofallthrough = 1 [static]

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

Referenced by pbx_builtin_background().

struct pbx_builtin builtins[] [static]

Declaration of builtin applications.

Referenced by load_pbx().

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

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

Definition at line 1178 of file pbx.c.

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

struct ast_context* contexts [static]

Definition at line 1171 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 1172 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 1129 of file pbx.c.

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

const char* const days[] [static]

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

struct ast_taskprocessor* device_state_tps [static]

Definition at line 804 of file pbx.c.

Referenced by device_state_cb(), and load_pbx().

struct ast_custom_function exception_function [static]

Initial value:

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

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

Referenced by acf_exception_read(), and pbx_builtin_raise_exception().

int extenpatternmatchnew = 0 [static]

Definition at line 1122 of file pbx.c.

Referenced by pbx_find_extension(), and pbx_set_extenpatternmatchnew().

struct cfextension_states extension_states[] [static]

Referenced by ast_extension_state2str().

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

Definition at line 807 of file pbx.c.

Referenced by ast_extension_state2().

struct varshead globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE [static]

Definition at line 1119 of file pbx.c.

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

Definition at line 1118 of file pbx.c.

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

const int HASH_EXTENHINT_SIZE = 563 [static]

Definition at line 943 of file pbx.c.

struct ao2_container* hints [static]

Definition at line 1191 of file pbx.c.

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

struct ast_data_handler hints_data_provider [static]

Initial value:

Definition at line 9856 of file pbx.c.

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

Definition at line 1128 of file pbx.c.

Referenced by decrease_call_count(), and increase_call_count().

const char* const months[] [static]

Definition at line 7349 of file pbx.c.

Referenced by ast_build_timing().

char* overrideswitch = NULL [static]

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

Referenced by load_pbx().

struct ast_data_entry pbx_data_providers[] [static]

Initial value:

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

Definition at line 9861 of file pbx.c.

Referenced by load_pbx().

struct ast_app_option resetcdr_opts[128] = { [ 'w' ] = { .flag = AST_CDR_FLAG_POSTED }, [ 'a' ] = { .flag = AST_CDR_FLAG_LOCKED }, [ 'v' ] = { .flag = AST_CDR_FLAG_KEEP_VARS }, [ 'e' ] = { .flag = AST_CDR_FLAG_POST_ENABLE },} [static]

Definition at line 9015 of file pbx.c.

Referenced by pbx_builtin_resetcdr().

int stateid = 1 [static]

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

Referenced by pbx_find_extension().

struct ast_custom_function testtime_function [static]

Initial value:

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

Definition at line 9104 of file pbx.c.

Referenced by load_pbx().

int totalcalls [static]

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

Referenced by pbx_builtin_waitexten().


Generated on Wed Apr 6 11:30:07 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7