Mon Jun 27 16:51:16 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  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 hint_id_cmp (void *obj, void *arg, int flags)
static int hints_data_provider_get (const struct ast_data_search *search, struct ast_data *data_root)
static int include_valid (struct ast_include *i)
static int increase_call_count (const struct ast_channel *c)
 Increase call count for channel.
static void insert_in_next_chars_alt_char_list (struct match_char **parent_ptr, struct match_char *node)
int load_pbx (void)
static int lookup_name (const char *s, const char *const names[], int max)
 Helper for get_range. return the index of the matching entry, starting from 1. If names is not supplied, try numeric values.
static void manager_dpsendack (struct mansession *s, const struct message *m)
 Send ack once.
static int manager_show_dialplan (struct mansession *s, const struct message *m)
 Manager listing of dial plan.
static int manager_show_dialplan_helper (struct mansession *s, const struct message *m, const char *actionidtext, const char *context, const char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude)
 Show dialplan extensions XXX this function is similar but not exactly the same as the CLI's show dialplan. Must check whether the difference is intentional or not.
static int matchcid (const char *cidpattern, const char *callerid)
static void new_find_extension (const char *str, struct scoreboard *score, struct match_char *tree, int length, int spec, const char *callerid, const char *label, enum ext_match_t action)
static int parse_variable_name (char *var, int *offset, int *length, int *isfunc)
 extract offset:length from variable name.
static int pbx_builtin_answer (struct ast_channel *, const char *)
static int pbx_builtin_background (struct ast_channel *, const char *)
static int pbx_builtin_busy (struct ast_channel *, const char *)
void pbx_builtin_clear_globals (void)
static int pbx_builtin_congestion (struct ast_channel *, const char *)
static int pbx_builtin_execiftime (struct ast_channel *, const char *)
const char * pbx_builtin_getvar_helper (struct ast_channel *chan, const char *name)
 Return a pointer to the value of the corresponding channel variable.
static int pbx_builtin_goto (struct ast_channel *, const char *)
static int pbx_builtin_gotoif (struct ast_channel *, const char *)
static int pbx_builtin_gotoiftime (struct ast_channel *, const char *)
static int pbx_builtin_hangup (struct ast_channel *, const char *)
static int pbx_builtin_importvar (struct ast_channel *, const char *)
static int pbx_builtin_incomplete (struct ast_channel *, const char *)
static int pbx_builtin_noop (struct ast_channel *, const char *)
static int pbx_builtin_proceeding (struct ast_channel *, const char *)
static int pbx_builtin_progress (struct ast_channel *, const char *)
void pbx_builtin_pushvar_helper (struct ast_channel *chan, const char *name, const char *value)
 Add a variable to the channel variable stack, without removing any previously set value.
int pbx_builtin_raise_exception (struct ast_channel *chan, const char *reason)
static int pbx_builtin_resetcdr (struct ast_channel *, const char *)
static int pbx_builtin_ringing (struct ast_channel *, const char *)
static int pbx_builtin_saycharacters (struct ast_channel *, const char *)
static int pbx_builtin_saydigits (struct ast_channel *, const char *)
static int pbx_builtin_saynumber (struct ast_channel *, const char *)
static int pbx_builtin_sayphonetic (struct ast_channel *, const char *)
int pbx_builtin_serialize_variables (struct ast_channel *chan, struct ast_str **buf)
 Create a human-readable string, specifying all variables and their corresponding values.
static int pbx_builtin_setamaflags (struct ast_channel *, const char *)
int pbx_builtin_setvar (struct ast_channel *chan, const char *data)
 Parse and set a single channel variable, where the name and value are separated with an '=' character.
int pbx_builtin_setvar_helper (struct ast_channel *chan, const char *name, const char *value)
 Add a variable to the channel variable stack, removing the most recently set value for the same name.
int pbx_builtin_setvar_multiple (struct ast_channel *chan, const char *vdata)
 Parse and set multiple channel variables, where the pairs are separated by the ',' character, and name and value are separated with an '=' character.
static int pbx_builtin_wait (struct ast_channel *, const char *)
static int pbx_builtin_waitexten (struct ast_channel *, const char *)
int pbx_checkcondition (const char *condition)
 Evaluate a condition.
static void pbx_destroy (struct ast_pbx *p)
int pbx_exec (struct ast_channel *c, struct ast_app *app, const char *data)
 Execute an application.
static int pbx_extension_helper (struct ast_channel *c, struct ast_context *con, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action, int *found, int combined_find_spawn)
 The return value depends on the action:.
ast_extenpbx_find_extension (struct ast_channel *chan, struct ast_context *bypass, struct pbx_find_info *q, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action)
ast_apppbx_findapp (const char *app)
 Look up an application.
static struct ast_switchpbx_findswitch (const char *sw)
static int pbx_parseable_goto (struct ast_channel *chan, const char *goto_string, int async)
void pbx_retrieve_variable (struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp)
 Retrieve the value of a builtin variable or variable from the channel variable stack.
int pbx_set_autofallthrough (int newval)
int pbx_set_extenpatternmatchnew (int newval)
void pbx_set_overrideswitch (const char *newval)
static void pbx_substitute_variables (char *passdata, int datalen, struct ast_channel *c, struct ast_exten *e)
void pbx_substitute_variables_helper (struct ast_channel *c, const char *cp1, char *cp2, int count)
void pbx_substitute_variables_helper_full (struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count, size_t *used)
void pbx_substitute_variables_varshead (struct varshead *headp, const char *cp1, char *cp2, int count)
static void * pbx_thread (void *data)
static void print_app_docs (struct ast_app *aa, int fd)
static void print_ext (struct ast_exten *e, char *buf, int buflen)
 helper function to print an extension
static void set_ext_pri (struct ast_channel *c, const char *exten, int pri)
static int show_debug_helper (int fd, const char *context, const char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude, int includecount, const char *includes[])
static int show_dialplan_helper (int fd, const char *context, const char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude, int includecount, const char *includes[])
static int statecbs_cmp (void *obj, void *arg, int flags)
static char * substring (const char *value, int offset, int length, char *workspace, size_t workspace_len)
 takes a substring. It is ok to call with value == workspace.
static int testtime_write (struct ast_channel *chan, const char *cmd, char *var, const char *value)
static struct ast_extentrie_find_next_match (struct match_char *node)
static void unreference_cached_app (struct ast_app *app)
static void update_scoreboard (struct scoreboard *board, int length, int spec, struct ast_exten *exten, char last, const char *callerid, int deleted, struct match_char *node)
static void wait_for_hangup (struct ast_channel *chan, const void *data)

Variables

static int autofallthrough = 1
static struct ast_app_option background_opts [128] = { [ 's' ] = { .flag = (1 << 0) }, [ 'n' ] = { .flag = (1 << 1) }, [ 'm' ] = { .flag = (1 << 2) }, [ 'p' ] = { .flag = (1 << 3) },}
static struct pbx_builtin builtins []
 Declaration of builtin applications.
static ast_mutex_t conlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 }
 Lock for the ast_context list 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 = { PTHREAD_RWLOCK_INITIALIZER , NULL, 1 }
static const int HASH_EXTENHINT_SIZE = 563
static struct ao2_containerhints
static struct ast_data_handler hints_data_provider
static ast_mutex_t maxcalllock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 }
static const char *const months []
static char * overrideswitch = NULL
static struct ast_cli_entry pbx_cli []
static struct ast_data_entry pbx_data_providers []
static struct ast_app_option resetcdr_opts [128] = { [ 'w' ] = { .flag = AST_CDR_FLAG_POSTED }, [ 'a' ] = { .flag = AST_CDR_FLAG_LOCKED }, [ 'v' ] = { .flag = AST_CDR_FLAG_KEEP_VARS }, [ 'e' ] = { .flag = AST_CDR_FLAG_POST_ENABLE },}
static struct ao2_containerstatecbs
static int stateid = 1
static struct ast_threadstorage switch_data = { .once = PTHREAD_ONCE_INIT , .key_init = __init_switch_data , .custom_init = NULL , }
static struct ast_custom_function testtime_function
static int totalcalls
static struct ast_app_option waitexten_opts [128] = { [ 'm' ] = { .flag = (1 << 0) , .arg_index = 0 + 1 }, [ 'd' ] = { .flag = (1 << 1) , .arg_index = 0 + 1 },}


Detailed Description

Core PBX routines.

Author:
Mark Spencer <markster@digium.com>

Definition in file pbx.c.


Define Documentation

#define AST_PBX_MAX_STACK   128

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

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

#define STATUS_NO_EXTENSION   2

Definition at line 2533 of file pbx.c.

#define STATUS_NO_LABEL   4

Definition at line 2535 of file pbx.c.

#define STATUS_NO_PRIORITY   3

Definition at line 2534 of file pbx.c.

#define STATUS_SUCCESS   5

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

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

int __ast_custom_function_register ( struct ast_custom_function acf,
struct ast_module mod 
)

Register a custom function.

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

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

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

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

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

static void __ast_internal_context_destroy ( struct ast_context con  )  [static]

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

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

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

Definition at line 4654 of file pbx.c.

References ast_channel::_softhangup, ast_calloc, ast_cdr_update(), ast_channel_clear_softhangup(), 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().

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

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

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

Referenced by extension_match_core().

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

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

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

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

static int acf_retrieve_docs ( struct ast_custom_function acf  )  [static]

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

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

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

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

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

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

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

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

References add_pri_lockopt(), and el.

Referenced by ast_add_extension2_lockopt().

07878 {
07879    return add_pri_lockopt(con, tmp, el, e, replace, 1);
07880 }

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

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

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

Definition at line 1846 of file pbx.c.

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

Referenced by add_exten_to_pattern_tree().

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

int ast_active_calls ( void   ) 

Retrieve the number of active calls.

Definition at line 5067 of file pbx.c.

References countcalls.

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

05068 {
05069    return countcalls;
05070 }

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

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

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

08064 {
08065    return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid, application, data, datad, registrar, 1, 1);
08066 }

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

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

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

References ast_add_extension2_lockopt(), and find_context().

Referenced by ast_merge_contexts_and_delete().

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

static int ast_add_hint ( struct ast_exten e  )  [static]

Add hint to hint list, check initial extension state.

Definition at line 4452 of file pbx.c.

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

Referenced by ast_add_extension2_lockopt().

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

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

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

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

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

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

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

References __ast_goto_if_exists().

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

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

References pbx_parseable_goto().

Referenced by asyncgoto_exec(), and handle_redirect().

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

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

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

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

04597 {
04598    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0);
04599 }

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

Change hint for an extension.

Definition at line 4489 of file pbx.c.

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

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

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

References ast_check_timing2(), and ast_tvnow().

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

07413 {
07414    return ast_check_timing2(i, ast_tvnow());
07415 }

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

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

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

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

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

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

Referenced by handle_cli_dialplan_add_ignorepat().

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

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

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

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

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

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

Referenced by handle_cli_dialplan_add_include().

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

References ast_context_remove_extension_callerid().

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

05256 {
05257    return ast_context_remove_extension_callerid(context, extension, priority, NULL, 0, registrar);
05258 }

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

References ast_context_remove_extension_callerid2().

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

05283 {
05284    return ast_context_remove_extension_callerid2(con, extension, priority, NULL, 0, registrar, already_locked);
05285 }

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

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

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

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

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

Definition at line 7608 of file pbx.c.

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

Referenced by handle_cli_dialplan_remove_ignorepat().

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

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

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

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

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

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

Referenced by handle_cli_dialplan_remove_include().

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

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

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

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

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

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

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

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

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

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

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

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

struct ast_custom_function* ast_custom_function_find ( const char *  name  ) 

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

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

int ast_custom_function_unregister ( struct ast_custom_function acf  ) 

Unregister a custom function.

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

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

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

07452 {
07453    if (i->timezone) {
07454       ast_free(i->timezone);
07455       i->timezone = NULL;
07456    }
07457    return 0;
07458 }

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

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

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

References E_MATCH, and pbx_extension_helper().

Referenced by __analog_ss_thread(), __ast_goto_if_exists(), __ast_pbx_run(), _macro_exec(), acf_isexten_exec(), analog_ss_thread(), answer_call(), ast_bridge_call(), ast_pbx_outgoing_exten(), cb_events(), cli_console_dial(), conf_run(), console_dial(), console_transfer(), dahdi_handle_dtmf(), dahdi_r2_on_call_offered(), dahdi_r2_on_dnis_digit_received(), dial_exec_full(), disa_exec(), dp_lookup(), dundi_lookup_local(), findmeexec(), get_also_info(), get_destination(), get_refer_info(), gosub_exec(), handle_gosub(), handle_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().

04582 {
04583    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0);
04584 }

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

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

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

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

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

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

References ext_cmp().

Referenced by lua_extension_cmp().

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

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

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

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

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

static int ast_extension_state2 ( struct ast_exten e  )  [static]

Check state of extension by using hints.

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

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

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

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

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

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

References ao2_callback, ao2_find, ao2_lock, ao2_ref, ao2_unlock, find_hint_by_cb_id(), hints, OBJ_UNLINK, and statecbs.

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

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

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

04587 {
04588    return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
04589 }

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

References E_FINDLABEL, and pbx_extension_helper().

04592 {
04593    return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
04594 }

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

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

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

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

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

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

const char* ast_get_context_name ( struct ast_context con  ) 

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

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

const char* ast_get_context_registrar ( struct ast_context c  ) 

Definition at line 9977 of file pbx.c.

References ast_context::registrar.

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

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

const char* ast_get_extension_app ( struct ast_exten e  ) 

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

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

void* ast_get_extension_app_data ( struct ast_exten e  ) 

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

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

const char* ast_get_extension_cidmatch ( struct ast_exten e  ) 

Definition at line 10002 of file pbx.c.

References ast_exten::cidmatch.

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

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

struct ast_context* ast_get_extension_context ( struct ast_exten exten  ) 

Definition at line 9944 of file pbx.c.

References exten.

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

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

const char* ast_get_extension_label ( struct ast_exten exten  ) 

Definition at line 9954 of file pbx.c.

References exten.

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

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

int ast_get_extension_matchcid ( struct ast_exten e  ) 

Definition at line 9997 of file pbx.c.

References ast_exten::matchcid.

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

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

const char* ast_get_extension_name ( struct ast_exten exten  ) 

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

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

int ast_get_extension_priority ( struct ast_exten exten  ) 

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

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

const char* ast_get_extension_registrar ( struct ast_exten e  ) 

Definition at line 9982 of file pbx.c.

References ast_exten::registrar.

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

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

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

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

const char* ast_get_ignorepat_name ( struct ast_ignorepat ip  ) 

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

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

const char* ast_get_ignorepat_registrar ( struct ast_ignorepat ip  ) 

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

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

const char* ast_get_include_name ( struct ast_include inc  ) 

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

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

const char* ast_get_include_registrar ( struct ast_include i  ) 

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

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

const char* ast_get_switch_data ( struct ast_sw sw  ) 

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

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

int ast_get_switch_eval ( struct ast_sw sw  ) 

Definition at line 10027 of file pbx.c.

References ast_sw::eval.

Referenced by context_merge_incls_swits_igps_other_registrars().

10028 {
10029    return sw->eval;
10030 }

const char* ast_get_switch_name ( struct ast_sw sw  ) 

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

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

const char* ast_get_switch_registrar ( struct ast_sw sw  ) 

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

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

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

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

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

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

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

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

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

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

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

04602 {
04603    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0);
04604 }

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

References __ast_internal_context_destroy(), ao2_callback, ao2_container_count(), ao2_find, AO2_ITERATOR_DONTLOCK, ao2_iterator_init(), ao2_iterator_next, ao2_link, ao2_lock, ao2_ref, ao2_unlock, ast_add_extension_nolock(), ast_calloc, AST_EXTENSION_REMOVED, ast_free, ast_free_ptr, ast_hashtab_destroy(), ast_hashtab_end_traversal(), ast_hashtab_next(), ast_hashtab_start_traversal(), ast_hint_extension_nolock(), AST_LIST_HEAD_INIT_VALUE, AST_LIST_INSERT_HEAD, AST_LIST_INSERT_TAIL, 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::laststate, store_hint::list, ast_context::name, ast_context::next, store_hint::next, OBJ_UNLINK, ast_exten::parent, pbx_find_extension(), PRIORITY_HINT, and pbx_find_info::stacklen.

Referenced by lua_reload_extensions(), and pbx_load_module().

07043 {
07044    double ft;
07045    struct ast_context *tmp, *oldcontextslist;
07046    struct ast_hashtab *oldtable;
07047    struct store_hints store = AST_LIST_HEAD_INIT_VALUE;
07048    struct store_hint *this;
07049    struct ast_hint *hint;
07050    struct ast_exten *exten;
07051    int length;
07052    struct ast_state_cb *thiscb;
07053    struct ast_hashtab_iter *iter;
07054    struct ao2_iterator i;
07055 
07056    /* it is very important that this function hold the hint list lock _and_ the conlock
07057       during its operation; not only do we need to ensure that the list of contexts
07058       and extensions does not change, but also that no hint callbacks (watchers) are
07059       added or removed during the merge/delete process
07060 
07061       in addition, the locks _must_ be taken in this order, because there are already
07062       other code paths that use this order
07063    */
07064 
07065    struct timeval begintime, writelocktime, endlocktime, enddeltime;
07066 
07067    begintime = ast_tvnow();
07068    ast_rdlock_contexts();
07069    iter = ast_hashtab_start_traversal(contexts_table);
07070    while ((tmp = ast_hashtab_next(iter))) {
07071       context_merge(extcontexts, exttable, tmp, registrar);
07072    }
07073    ast_hashtab_end_traversal(iter);
07074 
07075    ao2_lock(hints);
07076    writelocktime = ast_tvnow();
07077 
07078    /* preserve all watchers for hints */
07079    i = ao2_iterator_init(hints, AO2_ITERATOR_DONTLOCK);
07080    for (hint = ao2_iterator_next(&i); hint; ao2_ref(hint, -1), hint = ao2_iterator_next(&i)) {
07081       if (ao2_container_count(hint->callbacks)) {
07082 
07083          length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2 + sizeof(*this);
07084          if (!(this = ast_calloc(1, length))) {
07085             continue;
07086          }
07087          ao2_lock(hint);
07088 
07089          if (hint->exten == NULL) {
07090             ao2_unlock(hint);
07091             continue;
07092          }
07093 
07094          /* this removes all the callbacks from the hint into 'this'. */
07095          while ((thiscb = ao2_callback(hint->callbacks, OBJ_UNLINK, NULL, NULL))) {
07096             AST_LIST_INSERT_TAIL(&this->callbacks, thiscb, entry);
07097             /* We intentionally do not unref thiscb to account for the non-ao2 reference in this->callbacks */
07098          }
07099 
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             ao2_ref(thiscb, -1);  /* Ref that we added when putting into this->callbacks */
07142          }
07143       } else {
07144          ao2_lock(hint);
07145          while ((thiscb = AST_LIST_REMOVE_HEAD(&this->callbacks, entry))) {
07146             ao2_link(hint->callbacks, thiscb);
07147             ao2_ref(thiscb, -1);  /* Ref that we added when putting into this->callbacks */
07148          }
07149          hint->laststate = this->laststate;
07150          ao2_unlock(hint);
07151       }
07152       ast_free(this);
07153       if (hint) {
07154          ao2_ref(hint, -1);
07155       }
07156    }
07157 
07158    ao2_unlock(hints);
07159    ast_unlock_contexts();
07160    endlocktime = ast_tvnow();
07161 
07162    /* the old list and hashtab no longer are relevant, delete them while the rest of asterisk
07163       is now freely using the new stuff instead */
07164 
07165    ast_hashtab_destroy(oldtable, NULL);
07166 
07167    for (tmp = oldcontextslist; tmp; ) {
07168       struct ast_context *next;  /* next starting point */
07169       next = tmp->next;
07170       __ast_internal_context_destroy(tmp);
07171       tmp = next;
07172    }
07173    enddeltime = ast_tvnow();
07174 
07175    ft = ast_tvdiff_us(writelocktime, begintime);
07176    ft /= 1000000.0;
07177    ast_verb(3,"Time to scan old dialplan and merge leftovers back into the new: %8.6f sec\n", ft);
07178 
07179    ft = ast_tvdiff_us(endlocktime, writelocktime);
07180    ft /= 1000000.0;
07181    ast_verb(3,"Time to restore hints and swap in new dialplan: %8.6f sec\n", ft);
07182 
07183    ft = ast_tvdiff_us(enddeltime, endlocktime);
07184    ft /= 1000000.0;
07185    ast_verb(3,"Time to delete the old dialplan: %8.6f sec\n", ft);
07186 
07187    ft = ast_tvdiff_us(enddeltime, begintime);
07188    ft /= 1000000.0;
07189    ast_verb(3,"Total time merge_contexts_delete: %8.6f sec\n", ft);
07190    return;
07191 }

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

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

int ast_pbx_init ( void   ) 

Provided by pbx.c

Definition at line 10250 of file pbx.c.

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

Referenced by main().

10251 {
10252    hints = ao2_container_alloc(HASH_EXTENHINT_SIZE, hint_hash, hint_cmp);
10253    statecbs = ao2_container_alloc(HASH_EXTENHINT_SIZE, NULL, statecbs_cmp);
10254 
10255    return (hints && statecbs) ? 0 : -1;
10256 }

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

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

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

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

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

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

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

05063 {
05064    return ast_pbx_run_args(c, NULL);
05065 }

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

run the application and free the descriptor once done

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

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

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

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

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 5025 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(), unistim_new(), and usbradio_new().

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

int ast_processed_calls ( void   ) 

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

Definition at line 5072 of file pbx.c.

References totalcalls.

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

05073 {
05074    return totalcalls;
05075 }

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

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

int ast_rdlock_contexts ( void   ) 

Read locks the context list.

Return values:
0 on success
-1 on error

Definition at line 9908 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(), manager_show_dialplan_helper(), pbx_extension_helper(), show_debug_helper(), show_dialplan_helper(), and unreference_cached_app().

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

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

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

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

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

static int ast_remove_hint ( struct ast_exten e  )  [static]

Remove hint from extension.

Definition at line 4508 of file pbx.c.

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

Referenced by destroy_exten().

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

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

04607 {
04608    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN, found, combined_find_spawn);
04609 }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

int ast_unlock_contexts ( void   ) 

Unlocks contexts.

Return values:
0 on success
-1 on failure

Definition at line 9913 of file pbx.c.

References ast_mutex_unlock, and conlock.

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

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

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

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

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

05613 {
05614    AST_RWLIST_WRLOCK(&switches);
05615    AST_RWLIST_REMOVE(&switches, sw, list);
05616    AST_RWLIST_UNLOCK(&switches);
05617 }

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

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

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

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

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

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

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

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

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

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

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

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

struct ast_context* ast_walk_contexts ( struct ast_context con  ) 

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

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

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

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

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

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

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

int ast_wrlock_contexts ( void   ) 

Write locks the context list.

Return values:
0 on success
-1 on error

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

static void create_match_char_tree ( struct ast_context con  )  [static]

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

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

static void decrease_call_count ( void   )  [static]

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

04984 {
04985    ast_mutex_lock(&maxcalllock);
04986    if (countcalls > 0)
04987       countcalls--;
04988    ast_mutex_unlock(&maxcalllock);
04989 }

static void destroy_exten ( struct ast_exten e  )  [static]

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

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

static void destroy_pattern_tree ( struct match_char pattern_tree  )  [static]

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

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

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

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

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

static void exception_store_free ( void *  data  )  [static]

Definition at line 3112 of file pbx.c.

References ast_free, and ast_string_field_free_memory.

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

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

the full routine to compare extensions in rules.

Definition at line 2257 of file pbx.c.

References ext_cmp1().

Referenced by ast_add_extension2_lockopt(), and ast_extension_cmp().

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

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

References ast_log(), and LOG_WARNING.

Referenced by ext_cmp().

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

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

copy a string skipping whitespace

Definition at line 7847 of file pbx.c.

Referenced by ast_add_extension2_lockopt().

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

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

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

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

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

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

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

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

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

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

Remove a watcher from the callback list.

Definition at line 4390 of file pbx.c.

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

Referenced by ast_extension_state_del().

04391 {
04392    struct ast_state_cb *state_cb;
04393    const struct ast_hint *hint = obj;
04394    int *id = arg;
04395 
04396    if ((state_cb = ao2_find(hint->callbacks, id, 0))) {
04397       ao2_ref(state_cb, -1);
04398       return CMP_MATCH | CMP_STOP;
04399    }
04400 
04401    return 0;
04402 }

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

References args, ast_log(), and LOG_WARNING.

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

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

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

Definition at line 1613 of file pbx.c.

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

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

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

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

Referenced by ast_build_timing().

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

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

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

Referenced by ast_build_timing().

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

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

Send ack once.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

static int handle_statechange ( void *  datap  )  [static]

Definition at line 4229 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_str_create(), ast_str_set(), ast_hint::callbacks, statechange::dev, ast_exten::exten, ast_hint::exten, hints, ast_hint::laststate, ast_context::name, ast_exten::parent, parse(), statecbs, str, and strsep().

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

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

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

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

Referenced by ast_pbx_init().

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

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

Definition at line 10221 of file pbx.c.

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

Referenced by ast_pbx_init().

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

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

Definition at line 4443 of file pbx.c.

References CMP_MATCH, CMP_STOP, and ast_state_cb::id.

Referenced by ast_add_hint().

04444 {
04445    const struct ast_state_cb *cb = obj;
04446    int *id = arg;
04447 
04448    return (cb->id == *id) ? CMP_MATCH | CMP_STOP : 0;
04449 }

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

Definition at line 9821 of file pbx.c.

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

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

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

Definition at line 1450 of file pbx.c.

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

Referenced by pbx_find_extension().

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

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

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

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

Definition at line 1867 of file pbx.c.

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

Referenced by add_pattern_node().

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

int load_pbx ( void   ) 

Provided by pbx.c

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

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

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

Referenced by get_range().

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

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

Send ack once.

Definition at line 6371 of file pbx.c.

References astman_send_listack().

Referenced by manager_show_dialplan_helper().

06372 {
06373    astman_send_listack(s, m, "DialPlan list will follow", "start");
06374 }

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

Manager listing of dial plan.

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

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

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

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

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

Definition at line 2538 of file pbx.c.

References ast_extension_match(), and ast_strlen_zero().

Referenced by pbx_find_extension().

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

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

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

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

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

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

void pbx_builtin_clear_globals ( void   ) 

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

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

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 9459 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(), sip_addheader(), sla_trunk_exec(), speech_background(), try_suggested_sip_codec(), and update_bridge_vars().

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

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

Definition at line 9719 of file pbx.c.

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

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

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

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

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

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

Definition at line 8993 of file pbx.c.

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

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

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

Definition at line 9692 of file pbx.c.

09693 {
09694    return 0;
09695 }

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

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

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

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

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

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

Definition at line 9780 of file pbx.c.

References ast_say_character_str(), and ast_channel::language.

09781 {
09782    int res = 0;
09783 
09784    if (data)
09785       res = ast_say_character_str(chan, data, "", chan->language);
09786    return res;
09787 }

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

Definition at line 9771 of file pbx.c.

References ast_say_digit_str(), and ast_channel::language.

09772 {
09773    int res = 0;
09774 
09775    if (data)
09776       res = ast_say_digit_str(chan, data, "", chan->language);
09777    return res;
09778 }

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

Definition at line 9743 of file pbx.c.

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

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

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

Definition at line 9789 of file pbx.c.

References ast_say_phonetic_str(), and ast_channel::language.

09790 {
09791    int res = 0;
09792 
09793    if (data)
09794       res = ast_say_phonetic_str(chan, data, "", chan->language);
09795    return res;
09796 }

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

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

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

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

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 9531 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(), generic_recall(), get_rdnis(), get_refer_info(), global_write(), gosub_release_frame(), handle_incoming(), handle_request_bye(), handle_request_refer(), handle_set_chanvar(), handle_set_global(), handle_setvariable(), hash_read(), hash_write(), isAnsweringMachine(), leave_queue(), leave_voicemail(), local_hangup(), lua_set_variable(), lua_set_variable_value(), macro_fixup(), manage_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(), sip_addheader(), sip_hangup(), sip_new(), sip_read(), skinny_new(), sla_calc_trunk_timeouts(), sla_station_exec(), sla_trunk_exec(), socket_process(), speech_create(), start_monitor_exec(), system_exec_helper(), testtime_write(), transfer_exec(), transmit(), tryexec_exec(), unshift_push(), update_bridge_vars(), update_qe_rule(), upqm_exec(), vm_box_exists(), vm_exec(), vmauthenticate(), waituntil_exec(), and zapateller_exec().

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

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

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

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

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

static void pbx_destroy ( struct ast_pbx p  )  [static]

Definition at line 1458 of file pbx.c.

References ast_free.

01459 {
01460    ast_free(p);
01461 }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

References autofallthrough.

Referenced by pbx_load_module().

05078 {
05079    int oldval = autofallthrough;
05080    autofallthrough = newval;
05081    return oldval;
05082 }

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

References extenpatternmatchnew.

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

05085 {
05086    int oldval = extenpatternmatchnew;
05087    extenpatternmatchnew = newval;
05088    return oldval;
05089 }

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

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

Referenced by pbx_load_module().

05092 {
05093    if (overrideswitch) {
05094       ast_free(overrideswitch);
05095    }
05096    if (!ast_strlen_zero(newval)) {
05097       overrideswitch = ast_strdup(newval);
05098    } else {
05099       overrideswitch = NULL;
05100    }
05101 }

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

Definition at line 3984 of file pbx.c.

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

Referenced by pbx_extension_helper().

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

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

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

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

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

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

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

Definition at line 3978 of file pbx.c.

References pbx_substitute_variables_helper_full().

Referenced by dundi_lookup_local(), and loopback_subst().

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

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

Definition at line 5005 of file pbx.c.

References __ast_pbx_run(), and decrease_call_count().

Referenced by ast_pbx_start().

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

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

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

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

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

helper function to print an extension

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

06031 {
06032    int prio = ast_get_extension_priority(e);
06033    if (prio == PRIORITY_HINT) {
06034       snprintf(buf, buflen, "hint: %s",
06035          ast_get_extension_app(e));
06036    } else {
06037       snprintf(buf, buflen, "%d. %s(%s)",
06038          prio, ast_get_extension_app(e),
06039          (!ast_strlen_zero(ast_get_extension_app_data(e)) ? (char *)ast_get_extension_app_data(e) : ""));
06040    }
06041 }

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

04613 {
04614    ast_channel_lock(c);
04615    ast_copy_string(c->exten, exten, sizeof(c->exten));
04616    c->priority = pri;
04617    ast_channel_unlock(c);
04618 }

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

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

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

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

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

Definition at line 10242 of file pbx.c.

References ast_state_cb::callback, CMP_MATCH, and CMP_STOP.

Referenced by ast_pbx_init().

10243 {
10244    const struct ast_state_cb *state_cb = obj;
10245    const struct ast_state_cb *callback = arg;
10246 
10247    return (state_cb == callback) ? CMP_MATCH | CMP_STOP : 0;
10248 }

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

References ast_copy_string().

Referenced by pbx_substitute_variables_helper_full().

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

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

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

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

static void unreference_cached_app ( struct ast_app app  )  [static]

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

06804 {
06805    struct ast_context *context = NULL;
06806    struct ast_exten *eroot = NULL, *e = NULL;
06807 
06808    ast_rdlock_contexts();
06809    while ((context = ast_walk_contexts(context))) {
06810       while ((eroot = ast_walk_context_extensions(context, eroot))) {
06811          while ((e = ast_walk_extension_priorities(eroot, e))) {
06812             if (e->cached_app == app)
06813                e->cached_app = NULL;
06814          }
06815       }
06816    }
06817    ast_unlock_contexts();
06818 
06819    return;
06820 }

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

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

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

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

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


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 = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [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 7340 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 3170 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 3119 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 = { PTHREAD_RWLOCK_INITIALIZER , NULL, 1 } [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 9855 of file pbx.c.

ast_mutex_t maxcalllock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [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 7352 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 6782 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 9860 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 9018 of file pbx.c.

Referenced by pbx_builtin_resetcdr().

struct ao2_container* statecbs [static]

Definition at line 1193 of file pbx.c.

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

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 9107 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 Mon Jun 27 16:51:17 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7