Fri Feb 10 06:36:55 2012

Asterisk developer's documentation


pbx.h File Reference

Core PBX routines and definitions. More...

#include "asterisk/channel.h"
#include "asterisk/sched.h"
#include "asterisk/devicestate.h"
#include "asterisk/chanvars.h"
#include "asterisk/hashtab.h"
#include "asterisk/stringfields.h"
#include "asterisk/xmldoc.h"
#include "asterisk/format.h"

Include dependency graph for pbx.h:

Go to the source code of this file.

Data Structures

struct  ast_custom_function
 Data structure associated with a custom dialplan function. More...
struct  ast_pbx
struct  ast_pbx_args
 Options for ast_pbx_run(). More...
struct  ast_switch
struct  ast_timing
struct  pbx_find_info

Defines

#define ast_custom_function_register(acf)   __ast_custom_function_register(acf, ast_module_info->self)
 Register a custom function.
#define AST_MAX_APP   32
#define AST_PBX_GOTO_FAILED   -3
#define AST_PBX_KEEP   0
#define AST_PBX_MAX_STACK   128
#define AST_PBX_REPLACE   1
#define PRIORITY_HINT   -1
#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 AST_PBX_ERROR   1
#define AST_PBX_HANGUP   -1
 Special return values from applications to the PBX.
#define AST_PBX_INCOMPLETE   12
#define AST_PBX_OK   0

Typedefs

typedef void(* ast_state_cb_destroy_type )(int id, void *data)
 Typedef for devicestate and hint callback removal indication callback.
typedef int(* ast_state_cb_type )(const char *context, const char *exten, enum ast_extension_states state, void *data)
 Typedef for devicestate and hint callbacks.
typedef int( ast_switch_f )(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
 All switch functions have the same interface, so define a type for them.

Enumerations

enum  ast_extension_states {
  AST_EXTENSION_REMOVED = -2, AST_EXTENSION_DEACTIVATED = -1, AST_EXTENSION_NOT_INUSE = 0, AST_EXTENSION_INUSE = 1 << 0,
  AST_EXTENSION_BUSY = 1 << 1, AST_EXTENSION_UNAVAILABLE = 1 << 2, AST_EXTENSION_RINGING = 1 << 3, AST_EXTENSION_ONHOLD = 1 << 4
}
 Extension states. More...
enum  ast_pbx_result { AST_PBX_SUCCESS = 0, AST_PBX_FAILED = -1, AST_PBX_CALL_LIMIT = -2 }
 The result codes when starting the PBX on a channel with ast_pbx_start. More...
enum  ext_match_t {
  E_MATCHMORE = 0x00, E_CANMATCH = 0x01, E_MATCH = 0x02, E_MATCH_MASK = 0x03,
  E_SPAWN = 0x12, E_FINDLABEL = 0x22, E_MATCHMORE = 0x00, E_CANMATCH = 0x01,
  E_MATCH = 0x02, E_MATCH_MASK = 0x03, E_SPAWN = 0x12, E_FINDLABEL = 0x22
}

Functions

int __ast_custom_function_register (struct ast_custom_function *acf, struct ast_module *mod)
 Register a custom function.
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 *.
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 *chan, 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)
 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.
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 *ignorepat, const char *registrar)
 Add an ignorepat.
int ast_context_add_ignorepat2 (struct ast_context *con, const char *ignorepat, 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 *include, 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 *sw, const char *data, int eval, const char *registrar)
 Adds a switch (first param is a ast_context).
void ast_context_destroy (struct ast_context *con, const char *registrar)
 Destroy a context (matches the specified context (or ANY context if NULL).
struct ast_contextast_context_find (const char *name)
 Find a context.
struct ast_contextast_context_find_or_create (struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *name, const char *registrar)
 Register a new context or find an existing one.
int ast_context_lockmacro (const char *macrocontext)
 locks the macrolock in the given given context
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 *macrocontext)
 Unlocks the macrolock in the given context.
int ast_context_verify_includes (struct ast_context *con)
 Verifies includes in an ast_contect structure.
struct ast_custom_functionast_custom_function_find (const char *name)
int ast_custom_function_unregister (struct ast_custom_function *acf)
 Unregister a custom function.
int ast_destroy_timing (struct ast_timing *i)
 Deallocates memory structures associated with a timing bitmap.
enum ast_extension_states ast_devstate_to_extenstate (enum ast_device_state devstate)
 Map devstate to an extension state.
int ast_exists_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
 Determine whether an extension exists.
int ast_explicit_goto (struct ast_channel *chan, const char *context, const char *exten, int priority)
int ast_extension_close (const char *pattern, const char *data, int needmore)
int ast_extension_cmp (const char *a, const char *b)
 Determine if one extension should match before another.
int ast_extension_match (const char *pattern, const char *extension)
 Determine if a given extension matches a given pattern (in NXX format).
int ast_extension_patmatch (const char *pattern, const char *data)
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.
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 change_cb, void *data)
 Registers a state change callback.
int ast_extension_state_add_destroy (const char *context, const char *exten, ast_state_cb_type change_cb, ast_state_cb_destroy_type destroy_cb, void *data)
 Registers a state change callback with destructor.
int ast_extension_state_del (int id, ast_state_cb_type change_cb)
 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
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.
int ast_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority)
int ast_ignore_pattern (const char *context, const char *pattern)
 Checks to see if a number should be ignored.
int ast_matchmore_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
 Looks to see if adding anything to this extension might match something. (exists ^ canmatch).
void ast_merge_contexts_and_delete (struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *registrar)
 Merge the temporary contexts into a global contexts list and delete from the global list the ones that are being added.
int ast_parseable_goto (struct ast_channel *chan, const char *goto_string)
int ast_pbx_outgoing_app (const char *type, struct ast_format_cap *cap, const char *addr, 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)
int ast_pbx_outgoing_exten (const char *type, struct ast_format_cap *cap, const char *addr, 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)
enum ast_pbx_result ast_pbx_run (struct ast_channel *c)
 Execute the PBX in the current thread.
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 (void)
 Read locks the context list.
int ast_register_switch (struct ast_switch *sw)
 Register an alternative dialplan switch.
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.
int ast_unlock_context (struct ast_context *con)
int ast_unlock_contexts (void)
 Unlocks contexts.
void ast_unregister_switch (struct ast_switch *sw)
 Unregister an alternative switch.
int ast_wrlock_context (struct ast_context *con)
 Write locks a given context.
int ast_wrlock_contexts (void)
 Write locks the context list.
void pbx_builtin_clear_globals (void)
const char * pbx_builtin_getvar_helper (struct ast_channel *chan, const char *name)
 Return a pointer to the value of the corresponding channel variable.
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 *data)
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.
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 *data)
 Parse and set multiple channel variables, where the pairs are separated by the ',' character, and name and value are separated with an '=' character.
int pbx_checkcondition (const char *condition)
 Evaluate a condition.
int pbx_exec (struct ast_channel *c, struct ast_app *app, const char *data)
 Execute an application.
struct ast_extenpbx_find_extension (struct ast_channel *chan, struct ast_context *bypass, struct pbx_find_info *q, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action)
struct ast_apppbx_findapp (const char *app)
 Look up an application.
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)
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 matchcid, const char *registrar)
int ast_context_remove_extension_callerid2 (struct ast_context *con, const char *extension, int priority, const char *callerid, int matchcid, const char *registrar, int already_locked)
Functions for returning values from structures

const char * ast_get_context_name (struct ast_context *con)
struct ast_contextast_get_extension_context (struct ast_exten *exten)
const char * ast_get_extension_name (struct ast_exten *exten)
const char * ast_get_ignorepat_name (struct ast_ignorepat *ip)
const char * ast_get_include_name (struct ast_include *include)
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)
Registrar info functions ...


const char * ast_get_context_registrar (struct ast_context *c)
const char * ast_get_extension_registrar (struct ast_exten *e)
const char * ast_get_ignorepat_registrar (struct ast_ignorepat *ip)
const char * ast_get_include_registrar (struct ast_include *i)
const char * ast_get_switch_registrar (struct ast_sw *sw)
Other Extension stuff


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)
const char * ast_get_extension_label (struct ast_exten *e)
int ast_get_extension_matchcid (struct ast_exten *e)
int ast_get_extension_priority (struct ast_exten *exten)
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)
Substitution routines, using dynamic string buffers


const char * ast_str_retrieve_variable (struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, 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)
Walking functions ...


struct ast_extenast_walk_context_extensions (struct ast_context *con, struct ast_exten *priority)
struct ast_ignorepatast_walk_context_ignorepats (struct ast_context *con, struct ast_ignorepat *ip)
struct ast_includeast_walk_context_includes (struct ast_context *con, struct ast_include *inc)
struct ast_swast_walk_context_switches (struct ast_context *con, struct ast_sw *sw)
struct ast_contextast_walk_contexts (struct ast_context *con)
struct ast_extenast_walk_extension_priorities (struct ast_exten *exten, struct ast_exten *priority)
Substitution routines, using static string buffers
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 cp2_size, size_t *used)
void pbx_substitute_variables_varshead (struct varshead *headp, const char *cp1, char *cp2, int count)


Detailed Description

Core PBX routines and definitions.

Definition in file pbx.h.


Define Documentation

#define ast_custom_function_register ( acf   )     __ast_custom_function_register(acf, ast_module_info->self)

Register a custom function.

Definition at line 1144 of file pbx.h.

Referenced by load_module(), and reload().

#define AST_MAX_APP   32

Max length of an application

Definition at line 39 of file pbx.h.

Referenced by destroy_station(), handle_show_function(), print_app_docs(), and sla_build_station().

#define AST_PBX_ERROR   1

Jump to the 'e' exten

Definition at line 49 of file pbx.h.

Referenced by __ast_pbx_run().

#define AST_PBX_GOTO_FAILED   -3

Definition at line 41 of file pbx.h.

Referenced by __ast_goto_if_exists(), and dial_exec_full().

#define AST_PBX_HANGUP   -1

Special return values from applications to the PBX.

Jump to the 'h' exten

Definition at line 47 of file pbx.h.

#define AST_PBX_INCOMPLETE   12

Return to PBX matching, allowing more digits for the extension

Definition at line 50 of file pbx.h.

Referenced by __ast_pbx_run(), dial_exec_full(), pbx_builtin_incomplete(), and retrydial_exec().

#define AST_PBX_KEEP   0

Definition at line 42 of file pbx.h.

#define AST_PBX_MAX_STACK   128

Definition at line 1227 of file pbx.h.

#define AST_PBX_OK   0

No errors

Definition at line 48 of file pbx.h.

#define AST_PBX_REPLACE   1

Definition at line 43 of file pbx.h.

#define PRIORITY_HINT   -1

#define STATUS_NO_CONTEXT   1

Definition at line 1222 of file pbx.h.

#define STATUS_NO_EXTENSION   2

Definition at line 1223 of file pbx.h.

#define STATUS_NO_LABEL   4

Definition at line 1225 of file pbx.h.

#define STATUS_NO_PRIORITY   3

Definition at line 1224 of file pbx.h.

#define STATUS_SUCCESS   5

Definition at line 1226 of file pbx.h.


Typedef Documentation

typedef void(* ast_state_cb_destroy_type)(int id, void *data)

Typedef for devicestate and hint callback removal indication callback.

Definition at line 82 of file pbx.h.

typedef int(* ast_state_cb_type)(const char *context, const char *exten, enum ast_extension_states state, void *data)

Typedef for devicestate and hint callbacks.

Definition at line 79 of file pbx.h.

typedef int( ast_switch_f)(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)

All switch functions have the same interface, so define a type for them.

Data structure associated with an Asterisk switch

Definition at line 114 of file pbx.h.


Enumeration Type Documentation

Extension states.

Note:
States can be combined Extension and device states in Asterisk
Enumerator:
AST_EXTENSION_REMOVED  Extension removed
AST_EXTENSION_DEACTIVATED  Extension hint removed
AST_EXTENSION_NOT_INUSE  No device INUSE or BUSY
AST_EXTENSION_INUSE  One or more devices INUSE
AST_EXTENSION_BUSY  All devices BUSY
AST_EXTENSION_UNAVAILABLE  All devices UNAVAILABLE/UNREGISTERED
AST_EXTENSION_RINGING  All devices RINGING
AST_EXTENSION_ONHOLD  All devices ONHOLD

Definition at line 60 of file pbx.h.

00060                           {
00061    AST_EXTENSION_REMOVED = -2,   /*!< Extension removed */
00062    AST_EXTENSION_DEACTIVATED = -1,  /*!< Extension hint removed */
00063    AST_EXTENSION_NOT_INUSE = 0,  /*!< No device INUSE or BUSY  */
00064    AST_EXTENSION_INUSE = 1 << 0, /*!< One or more devices INUSE */
00065    AST_EXTENSION_BUSY = 1 << 1,  /*!< All devices BUSY */
00066    AST_EXTENSION_UNAVAILABLE = 1 << 2, /*!< All devices UNAVAILABLE/UNREGISTERED */
00067    AST_EXTENSION_RINGING = 1 << 3,  /*!< All devices RINGING */
00068    AST_EXTENSION_ONHOLD = 1 << 4,   /*!< All devices ONHOLD */
00069 };

The result codes when starting the PBX on a channel with ast_pbx_start.

Note:
AST_PBX_CALL_LIMIT refers to the maxcalls call limit in asterisk.conf
See also:
ast_pbx_start
Enumerator:
AST_PBX_SUCCESS 
AST_PBX_FAILED 
AST_PBX_CALL_LIMIT 

Definition at line 289 of file pbx.h.

00289                     {
00290    AST_PBX_SUCCESS = 0,
00291    AST_PBX_FAILED = -1,
00292    AST_PBX_CALL_LIMIT = -2,
00293 };

When looking up extensions, we can have different requests identified by the 'action' argument, as follows.

Note:
that the coding is such that the low 4 bits are the third argument to extension_match_core.
Enumerator:
E_MATCHMORE 
E_CANMATCH 
E_MATCH 
E_MATCH_MASK 
E_SPAWN 
E_FINDLABEL 
E_MATCHMORE 
E_CANMATCH 
E_MATCH 
E_MATCH_MASK 
E_SPAWN 
E_FINDLABEL 

Definition at line 1213 of file pbx.h.

01213                  {
01214    E_MATCHMORE =  0x00, /* extension can match but only with more 'digits' */
01215    E_CANMATCH =   0x01, /* extension can match with or without more 'digits' */
01216    E_MATCH =   0x02, /* extension is an exact match */
01217    E_MATCH_MASK = 0x03, /* mask for the argument to extension_match_core() */
01218    E_SPAWN =   0x12, /* want to spawn an extension. Requires exact match */
01219    E_FINDLABEL =  0x22  /* returns the priority for a given label. Requires exact match */
01220 };


Function Documentation

int __ast_custom_function_register ( struct ast_custom_function acf,
struct ast_module mod 
)

Register a custom function.

Definition at line 3715 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 ast_msg_init(), and load_pbx().

03716 {
03717    struct ast_custom_function *cur;
03718    char tmps[80];
03719 
03720    if (!acf) {
03721       return -1;
03722    }
03723 
03724    acf->mod = mod;
03725 #ifdef AST_XML_DOCS
03726    acf->docsrc = AST_STATIC_DOC;
03727 #endif
03728 
03729    if (acf_retrieve_docs(acf)) {
03730       return -1;
03731    }
03732 
03733    AST_RWLIST_WRLOCK(&acf_root);
03734 
03735    AST_RWLIST_TRAVERSE(&acf_root, cur, acflist) {
03736       if (!strcmp(acf->name, cur->name)) {
03737          ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name);
03738          AST_RWLIST_UNLOCK(&acf_root);
03739          return -1;
03740       }
03741    }
03742 
03743    /* Store in alphabetical order */
03744    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) {
03745       if (strcasecmp(acf->name, cur->name) < 0) {
03746          AST_RWLIST_INSERT_BEFORE_CURRENT(acf, acflist);
03747          break;
03748       }
03749    }
03750    AST_RWLIST_TRAVERSE_SAFE_END;
03751 
03752    if (!cur) {
03753       AST_RWLIST_INSERT_TAIL(&acf_root, acf, acflist);
03754    }
03755 
03756    AST_RWLIST_UNLOCK(&acf_root);
03757 
03758    ast_verb(2, "Registered custom function '%s'\n", term_color(tmps, acf->name, COLOR_BRCYAN, 0, sizeof(tmps)));
03759 
03760    return 0;
03761 }

int ast_active_calls ( void   ) 

Retrieve the number of active calls.

Definition at line 5546 of file pbx.c.

References countcalls.

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

05547 {
05548    return countcalls;
05549 }

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

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

Referenced by ast_extension_state(), ast_extension_state_add_destroy(), handle_cli_dialplan_add_extension(), manage_parked_call(), park_add_hints(), park_call_full(), parkinglot_activate(), register_exten(), register_peer_exten(), and RegisterExtension().

08274 {
08275    int ret = -1;
08276    struct ast_context *c;
08277 
08278    c = find_context_locked(context);
08279    if (c) {
08280       ret = ast_add_extension2(c, replace, extension, priority, label, callerid,
08281          application, data, datad, registrar);
08282       ast_unlock_contexts();
08283    }
08284 
08285    return ret;
08286 }

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

Note:
For details about the arguments, check ast_add_extension()
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 8617 of file pbx.c.

References ast_add_extension2_lockopt().

Referenced by add_extensions(), ast_add_extension(), context_merge(), load_module(), lua_register_hints(), pbx_load_config(), pbx_load_users(), sla_build_station(), and sla_build_trunk().

08621 {
08622    return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid,
08623       application, data, datad, registrar, 1);
08624 }

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
Note:
Do _NOT_ hold any channel locks when calling this function.

Definition at line 8311 of file pbx.c.

References ast_channel::_state, accountcode, ast_channel::amaflags, amaflags, ast_cdr_discard(), ast_cdr_dup(), ast_channel_accountcode(), ast_channel_alloc, ast_channel_linkedid(), ast_channel_lock, ast_channel_masquerade(), ast_channel_name(), ast_channel_unlock, ast_do_masquerade(), ast_explicit_goto(), ast_format_copy(), ast_hangup(), ast_log(), ast_pbx_start(), AST_SOFTHANGUP_ASYNCGOTO, ast_softhangup_nolock(), ast_strdupa, ast_channel::cdr, ast_channel::context, ast_channel::exten, LOG_WARNING, 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(), fax_detect_framehook(), handle_request_bye(), handle_request_refer(), my_handle_dtmf(), pbx_parseable_goto(), process_ast_dsp(), process_sdp(), sip_read(), and socket_process().

08312 {
08313    int res = 0;
08314    struct ast_channel *tmpchan;
08315    struct {
08316       char *accountcode;
08317       char *exten;
08318       char *context;
08319       char *linkedid;
08320       char *name;
08321       struct ast_cdr *cdr;
08322       int amaflags;
08323       int state;
08324       struct ast_format readformat;
08325       struct ast_format writeformat;
08326    } tmpvars = { 0, };
08327 
08328    ast_channel_lock(chan);
08329    if (chan->pbx) { /* This channel is currently in the PBX */
08330       ast_explicit_goto(chan, context, exten, priority + 1);
08331       ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO);
08332       ast_channel_unlock(chan);
08333       return res;
08334    }
08335 
08336    /* In order to do it when the channel doesn't really exist within
08337     * the PBX, we have to make a new channel, masquerade, and start the PBX
08338     * at the new location */
08339    tmpvars.accountcode = ast_strdupa(ast_channel_accountcode(chan));
08340    tmpvars.exten = ast_strdupa(chan->exten);
08341    tmpvars.context = ast_strdupa(chan->context);
08342    tmpvars.linkedid = ast_strdupa(ast_channel_linkedid(chan));
08343    tmpvars.name = ast_strdupa(ast_channel_name(chan));
08344    tmpvars.amaflags = chan->amaflags;
08345    tmpvars.state = chan->_state;
08346    ast_format_copy(&tmpvars.writeformat, &chan->writeformat);
08347    ast_format_copy(&tmpvars.readformat, &chan->readformat);
08348    tmpvars.cdr = chan->cdr ? ast_cdr_dup(chan->cdr) : NULL;
08349 
08350    ast_channel_unlock(chan);
08351 
08352    /* Do not hold any channel locks while calling channel_alloc() since the function
08353     * locks the channel container when linking the new channel in. */
08354    if (!(tmpchan = ast_channel_alloc(0, tmpvars.state, 0, 0, tmpvars.accountcode, tmpvars.exten, tmpvars.context, tmpvars.linkedid, tmpvars.amaflags, "AsyncGoto/%s", tmpvars.name))) {
08355       ast_cdr_discard(tmpvars.cdr);
08356       return -1;
08357    }
08358 
08359    /* copy the cdr info over */
08360    if (tmpvars.cdr) {
08361       ast_cdr_discard(tmpchan->cdr);
08362       tmpchan->cdr = tmpvars.cdr;
08363       tmpvars.cdr = NULL;
08364    }
08365 
08366    /* Make formats okay */
08367    ast_format_copy(&tmpchan->readformat, &tmpvars.readformat);
08368    ast_format_copy(&tmpchan->writeformat, &tmpvars.writeformat);
08369 
08370    /* Setup proper location. Never hold another channel lock while calling this function. */
08371    ast_explicit_goto(tmpchan, S_OR(context, tmpvars.context), S_OR(exten, tmpvars.exten), priority);
08372 
08373    /* Masquerade into tmp channel */
08374    if (ast_channel_masquerade(tmpchan, chan)) {
08375       /* Failed to set up the masquerade.  It's probably chan_local
08376        * in the middle of optimizing itself out.  Sad. :( */
08377       ast_hangup(tmpchan);
08378       tmpchan = NULL;
08379       res = -1;
08380    } else {
08381       ast_do_masquerade(tmpchan);
08382       /* Start the PBX going on our stolen channel */
08383       if (ast_pbx_start(tmpchan)) {
08384          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmpchan));
08385          ast_hangup(tmpchan);
08386          res = -1;
08387       }
08388    }
08389 
08390    return res;
08391 }

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

Set the channel to next execute the specified dialplan location.

Definition at line 8393 of file pbx.c.

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

08394 {
08395    struct ast_channel *chan;
08396    int res = -1;
08397 
08398    if ((chan = ast_channel_get_by_name(channame))) {
08399       res = ast_async_goto(chan, context, exten, priority);
08400       chan = ast_channel_unref(chan);
08401    }
08402 
08403    return res;
08404 }

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

References __ast_goto_if_exists().

10709 {
10710    return __ast_goto_if_exists(chan, context, exten, priority, 1);
10711 }

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

References pbx_parseable_goto().

Referenced by asyncgoto_exec(), and handle_redirect().

10774 {
10775    return pbx_parseable_goto(chan, goto_string, 1);
10776 }

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

07896 {
07897    char *info;
07898    int j, num_fields, last_sep = -1;
07899 
07900    /* Check for empty just in case */
07901    if (ast_strlen_zero(info_in)) {
07902       return 0;
07903    }
07904 
07905    /* make a copy just in case we were passed a static string */
07906    info = ast_strdupa(info_in);
07907 
07908    /* count the number of fields in the timespec */
07909    for (j = 0, num_fields = 1; info[j] != '\0'; j++) {
07910       if (info[j] == ',') {
07911          last_sep = j;
07912          num_fields++;
07913       }
07914    }
07915 
07916    /* save the timezone, if it is specified */
07917    if (num_fields == 5) {
07918       i->timezone = ast_strdup(info + last_sep + 1);
07919    } else {
07920       i->timezone = NULL;
07921    }
07922 
07923    /* Assume everything except time */
07924    i->monthmask = 0xfff;   /* 12 bits */
07925    i->daymask = 0x7fffffffU; /* 31 bits */
07926    i->dowmask = 0x7f; /* 7 bits */
07927    /* on each call, use strsep() to move info to the next argument */
07928    get_timerange(i, strsep(&info, "|,"));
07929    if (info)
07930       i->dowmask = get_range(strsep(&info, "|,"), 7, days, "day of week");
07931    if (info)
07932       i->daymask = get_range(strsep(&info, "|,"), 31, NULL, "day");
07933    if (info)
07934       i->monthmask = get_range(strsep(&info, "|,"), 12, months, "month");
07935    return 1;
07936 }

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

05042 {
05043    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0);
05044 }

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

References ast_check_timing2(), and ast_tvnow().

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

07939 {
07940    return ast_check_timing2(i, ast_tvnow());
07941 }

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

07944 {
07945    struct ast_tm tm;
07946 
07947    ast_localtime(&tv, &tm, i->timezone);
07948 
07949    /* If it's not the right month, return */
07950    if (!(i->monthmask & (1 << tm.tm_mon)))
07951       return 0;
07952 
07953    /* If it's not that time of the month.... */
07954    /* Warning, tm_mday has range 1..31! */
07955    if (!(i->daymask & (1 << (tm.tm_mday-1))))
07956       return 0;
07957 
07958    /* If it's not the right day of the week */
07959    if (!(i->dowmask & (1 << tm.tm_wday)))
07960       return 0;
07961 
07962    /* Sanity check the hour just to be safe */
07963    if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) {
07964       ast_log(LOG_WARNING, "Insane time...\n");
07965       return 0;
07966    }
07967 
07968    /* Now the tough part, we calculate if it fits
07969       in the right time based on min/hour */
07970    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))))
07971       return 0;
07972 
07973    /* If we got this far, then we're good */
07974    return 1;
07975 }

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

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

Referenced by handle_orig(), and handle_show_application().

10779 {
10780    struct ast_app *app = NULL;
10781    int which = 0;
10782    char *ret = NULL;
10783    size_t wordlen = strlen(word);
10784 
10785    AST_RWLIST_RDLOCK(&apps);
10786    AST_RWLIST_TRAVERSE(&apps, app, list) {
10787       if (!strncasecmp(word, app->name, wordlen) && ++which > state) {
10788          ret = ast_strdup(app->name);
10789          break;
10790       }
10791    }
10792    AST_RWLIST_UNLOCK(&apps);
10793 
10794    return ret;
10795 }

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

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

Referenced by handle_cli_dialplan_add_ignorepat().

08180 {
08181    int ret = -1;
08182    struct ast_context *c;
08183 
08184    c = find_context_locked(context);
08185    if (c) {
08186       ret = ast_context_add_ignorepat2(c, value, registrar);
08187       ast_unlock_contexts();
08188    }
08189    return ret;
08190 }

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

Definition at line 8192 of file pbx.c.

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

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

08193 {
08194    struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL;
08195    int length;
08196    char *pattern;
08197    length = sizeof(struct ast_ignorepat);
08198    length += strlen(value) + 1;
08199    if (!(ignorepat = ast_calloc(1, length)))
08200       return -1;
08201    /* The cast to char * is because we need to write the initial value.
08202     * The field is not supposed to be modified otherwise.  Also, gcc 4.2
08203     * sees the cast as dereferencing a type-punned pointer and warns about
08204     * it.  This is the workaround (we're telling gcc, yes, that's really
08205     * what we wanted to do).
08206     */
08207    pattern = (char *) ignorepat->pattern;
08208    strcpy(pattern, value);
08209    ignorepat->next = NULL;
08210    ignorepat->registrar = registrar;
08211    ast_wrlock_context(con);
08212    for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) {
08213       ignorepatl = ignorepatc;
08214       if (!strcasecmp(ignorepatc->pattern, value)) {
08215          /* Already there */
08216          ast_unlock_context(con);
08217          errno = EEXIST;
08218          return -1;
08219       }
08220    }
08221    if (ignorepatl)
08222       ignorepatl->next = ignorepat;
08223    else
08224       con->ignorepats = ignorepat;
08225    ast_unlock_context(con);
08226    return 0;
08227 
08228 }

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

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

Referenced by handle_cli_dialplan_add_include().

07724 {
07725    int ret = -1;
07726    struct ast_context *c;
07727 
07728    c = find_context_locked(context);
07729    if (c) {
07730       ret = ast_context_add_include2(c, include, registrar);
07731       ast_unlock_contexts();
07732    }
07733    return ret;
07734 }

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

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

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

07994 {
07995    struct ast_include *new_include;
07996    char *c;
07997    struct ast_include *i, *il = NULL; /* include, include_last */
07998    int length;
07999    char *p;
08000 
08001    length = sizeof(struct ast_include);
08002    length += 2 * (strlen(value) + 1);
08003 
08004    /* allocate new include structure ... */
08005    if (!(new_include = ast_calloc(1, length)))
08006       return -1;
08007    /* Fill in this structure. Use 'p' for assignments, as the fields
08008     * in the structure are 'const char *'
08009     */
08010    p = new_include->stuff;
08011    new_include->name = p;
08012    strcpy(p, value);
08013    p += strlen(value) + 1;
08014    new_include->rname = p;
08015    strcpy(p, value);
08016    /* Strip off timing info, and process if it is there */
08017    if ( (c = strchr(p, ',')) ) {
08018       *c++ = '\0';
08019       new_include->hastime = ast_build_timing(&(new_include->timing), c);
08020    }
08021    new_include->next      = NULL;
08022    new_include->registrar = registrar;
08023 
08024    ast_wrlock_context(con);
08025 
08026    /* ... go to last include and check if context is already included too... */
08027    for (i = con->includes; i; i = i->next) {
08028       if (!strcasecmp(i->name, new_include->name)) {
08029          ast_destroy_timing(&(new_include->timing));
08030          ast_free(new_include);
08031          ast_unlock_context(con);
08032          errno = EEXIST;
08033          return -1;
08034       }
08035       il = i;
08036    }
08037 
08038    /* ... include new context into context list, unlock, return */
08039    if (il)
08040       il->next = new_include;
08041    else
08042       con->includes = new_include;
08043    ast_verb(3, "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con));
08044 
08045    ast_unlock_context(con);
08046 
08047    return 0;
08048 }

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

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

08056 {
08057    int ret = -1;
08058    struct ast_context *c;
08059 
08060    c = find_context_locked(context);
08061    if (c) { /* found, add switch to this context */
08062       ret = ast_context_add_switch2(c, sw, data, eval, registrar);
08063       ast_unlock_contexts();
08064    }
08065    return ret;
08066 }

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

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

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

08077 {
08078    struct ast_sw *new_sw;
08079    struct ast_sw *i;
08080    int length;
08081    char *p;
08082 
08083    length = sizeof(struct ast_sw);
08084    length += strlen(value) + 1;
08085    if (data)
08086       length += strlen(data);
08087    length++;
08088 
08089    /* allocate new sw structure ... */
08090    if (!(new_sw = ast_calloc(1, length)))
08091       return -1;
08092    /* ... fill in this structure ... */
08093    p = new_sw->stuff;
08094    new_sw->name = p;
08095    strcpy(new_sw->name, value);
08096    p += strlen(value) + 1;
08097    new_sw->data = p;
08098    if (data) {
08099       strcpy(new_sw->data, data);
08100       p += strlen(data) + 1;
08101    } else {
08102       strcpy(new_sw->data, "");
08103       p++;
08104    }
08105    new_sw->eval     = eval;
08106    new_sw->registrar = registrar;
08107 
08108    /* ... try to lock this context ... */
08109    ast_wrlock_context(con);
08110 
08111    /* ... go to last sw and check if context is already swd too... */
08112    AST_LIST_TRAVERSE(&con->alts, i, list) {
08113       if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) {
08114          ast_free(new_sw);
08115          ast_unlock_context(con);
08116          errno = EEXIST;
08117          return -1;
08118       }
08119    }
08120 
08121    /* ... sw new context into context list, unlock, return */
08122    AST_LIST_INSERT_TAIL(&con->alts, new_sw, list);
08123 
08124    ast_verb(3, "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con));
08125 
08126    ast_unlock_context(con);
08127 
08128    return 0;
08129 }

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

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

Referenced by __unload_module(), ast_features_reload(), cleanup_stale_contexts(), remove_dead_dialplan_useage(), sla_destroy(), and unload_module().

struct ast_context* ast_context_find ( const char *  name  )  [read]

Find a context.

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

Returns:
the ast_context on success, NULL on failure.

Definition at line 2777 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_features_reload(), ast_ignore_pattern(), cleanup_stale_contexts(), handle_cli_dialplan_add_extension(), isexten_function_read(), manage_parkinglot(), parked_call_exec(), register_exten(), register_peer_exten(), remove_dead_dialplan_useage(), unload_module(), and unregister_exten().

02778 {
02779    struct ast_context *tmp;
02780    struct fake_context item;
02781 
02782    if (!name) {
02783       return NULL;
02784    }
02785    ast_rdlock_contexts();
02786    if (contexts_table) {
02787       ast_copy_string(item.name, name, sizeof(item.name));
02788       tmp = ast_hashtab_lookup(contexts_table, &item);
02789    } else {
02790       tmp = NULL;
02791       while ((tmp = ast_walk_contexts(tmp))) {
02792          if (!strcasecmp(name, tmp->name)) {
02793             break;
02794          }
02795       }
02796    }
02797    ast_unlock_contexts();
02798    return tmp;
02799 }

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

Register a new context or find an existing one.

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

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

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

Definition at line 7324 of file pbx.c.

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

Referenced by ast_compile_ael2(), config_parse_variables(), context_merge(), handle_cli_dialplan_add_extension(), load_module(), lua_register_hints(), lua_register_switches(), manage_parked_call(), parkinglot_activate(), pbx_load_config(), pbx_load_users(), reload_config(), set_config(), sla_build_station(), and sla_build_trunk().

07325 {
07326    struct ast_context *tmp, **local_contexts;
07327    struct fake_context search;
07328    int length = sizeof(struct ast_context) + strlen(name) + 1;
07329 
07330    if (!contexts_table) {
07331       /* Protect creation of contexts_table from reentrancy. */
07332       ast_wrlock_contexts();
07333       if (!contexts_table) {
07334          contexts_table = ast_hashtab_create(17,
07335             ast_hashtab_compare_contexts,
07336             ast_hashtab_resize_java,
07337             ast_hashtab_newsize_java,
07338             ast_hashtab_hash_contexts,
07339             0);
07340       }
07341       ast_unlock_contexts();
07342    }
07343 
07344    ast_copy_string(search.name, name, sizeof(search.name));
07345    if (!extcontexts) {
07346       ast_rdlock_contexts();
07347       local_contexts = &contexts;
07348       tmp = ast_hashtab_lookup(contexts_table, &search);
07349       ast_unlock_contexts();
07350       if (tmp) {
07351          tmp->refcount++;
07352          return tmp;
07353       }
07354    } else { /* local contexts just in a linked list; search there for the new context; slow, linear search, but not frequent */
07355       local_contexts = extcontexts;
07356       tmp = ast_hashtab_lookup(exttable, &search);
07357       if (tmp) {
07358          tmp->refcount++;
07359          return tmp;
07360       }
07361    }
07362 
07363    if ((tmp = ast_calloc(1, length))) {
07364       ast_rwlock_init(&tmp->lock);
07365       ast_mutex_init(&tmp->macrolock);
07366       strcpy(tmp->name, name);
07367       tmp->root = NULL;
07368       tmp->root_table = NULL;
07369       tmp->registrar = ast_strdup(registrar);
07370       tmp->includes = NULL;
07371       tmp->ignorepats = NULL;
07372       tmp->refcount = 1;
07373    } else {
07374       ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name);
07375       return NULL;
07376    }
07377 
07378    if (!extcontexts) {
07379       ast_wrlock_contexts();
07380       tmp->next = *local_contexts;
07381       *local_contexts = tmp;
07382       ast_hashtab_insert_safe(contexts_table, tmp); /*put this context into the tree */
07383       ast_unlock_contexts();
07384       ast_debug(1, "Registered context '%s'(%p) in table %p registrar: %s\n", tmp->name, tmp, contexts_table, registrar);
07385       ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar);
07386    } else {
07387       tmp->next = *local_contexts;
07388       if (exttable)
07389          ast_hashtab_insert_immediate(exttable, tmp); /*put this context into the tree */
07390 
07391       *local_contexts = tmp;
07392       ast_debug(1, "Registered context '%s'(%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar);
07393       ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar);
07394    }
07395    return tmp;
07396 }

int ast_context_lockmacro ( const char *  context  ) 

locks the macrolock in the given given context

Parameters:
macrocontext name of the macro-context to lock
Locks the given macro-context to ensure only one thread (call) can execute it at a time

Return values:
0 on success
-1 on failure
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 5924 of file pbx.c.

References ast_mutex_lock, ast_unlock_contexts(), find_context_locked(), and ast_context::macrolock.

Referenced by _macro_exec().

05925 {
05926    struct ast_context *c;
05927    int ret = -1;
05928 
05929    c = find_context_locked(context);
05930    if (c) {
05931       ast_unlock_contexts();
05932 
05933       /* if we found context, lock macrolock */
05934       ret = ast_mutex_lock(&c->macrolock);
05935    }
05936 
05937    return ret;
05938 }

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
Note:
This function will lock conlock.

Definition at line 5729 of file pbx.c.

References ast_context_remove_extension_callerid().

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

05730 {
05731    return ast_context_remove_extension_callerid(context, extension, priority, NULL, 0, registrar);
05732 }

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

References ast_context_remove_extension_callerid2().

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

05760 {
05761    return ast_context_remove_extension_callerid2(con, extension, priority, NULL, 0, registrar, already_locked);
05762 }

int ast_context_remove_extension_callerid ( const char *  context,
const char *  extension,
int  priority,
const char *  callerid,
int  matchcid,
const char *  registrar 
)

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

05735 {
05736    int ret = -1; /* default error return */
05737    struct ast_context *c;
05738 
05739    c = find_context_locked(context);
05740    if (c) { /* ... remove extension ... */
05741       ret = ast_context_remove_extension_callerid2(c, extension, priority, callerid,
05742          matchcallerid, registrar, 0);
05743       ast_unlock_contexts();
05744    }
05745 
05746    return ret;
05747 }

int ast_context_remove_extension_callerid2 ( struct ast_context con,
const char *  extension,
int  priority,
const char *  callerid,
int  matchcid,
const char *  registrar,
int  already_locked 
)

Definition at line 5764 of file pbx.c.

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

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

05765 {
05766    struct ast_exten *exten, *prev_exten = NULL;
05767    struct ast_exten *peer;
05768    struct ast_exten ex, *exten2, *exten3;
05769    char dummy_name[1024];
05770    struct ast_exten *previous_peer = NULL;
05771    struct ast_exten *next_peer = NULL;
05772    int found = 0;
05773 
05774    if (!already_locked)
05775       ast_wrlock_context(con);
05776 
05777    /* Handle this is in the new world */
05778 
05779    /* FIXME For backwards compatibility, if callerid==NULL, then remove ALL
05780     * peers, not just those matching the callerid. */
05781 #ifdef NEED_DEBUG
05782    ast_verb(3,"Removing %s/%s/%d%s%s from trees, registrar=%s\n", con->name, extension, priority, matchcallerid ? "/" : "", matchcallerid ? callerid : "", registrar);
05783 #endif
05784 #ifdef CONTEXT_DEBUG
05785    check_contexts(__FILE__, __LINE__);
05786 #endif
05787    /* find this particular extension */
05788    ex.exten = dummy_name;
05789    ex.matchcid = matchcallerid && !ast_strlen_zero(callerid); /* don't say match if there's no callerid */
05790    ex.cidmatch = callerid;
05791    ast_copy_string(dummy_name, extension, sizeof(dummy_name));
05792    exten = ast_hashtab_lookup(con->root_table, &ex);
05793    if (exten) {
05794       if (priority == 0) {
05795          exten2 = ast_hashtab_remove_this_object(con->root_table, exten);
05796          if (!exten2)
05797             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);
05798          if (con->pattern_tree) {
05799             struct match_char *x = add_exten_to_pattern_tree(con, exten, 1);
05800 
05801             if (x->exten) { /* this test for safety purposes */
05802                x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */
05803                x->exten = 0; /* get rid of what will become a bad pointer */
05804             } else {
05805                ast_log(LOG_WARNING,"Trying to delete an exten from a context, but the pattern tree node returned isn't a full extension\n");
05806             }
05807          }
05808       } else {
05809          ex.priority = priority;
05810          exten2 = ast_hashtab_lookup(exten->peer_table, &ex);
05811          if (exten2) {
05812 
05813             if (exten2->label) { /* if this exten has a label, remove that, too */
05814                exten3 = ast_hashtab_remove_this_object(exten->peer_label_table,exten2);
05815                if (!exten3)
05816                   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);
05817             }
05818 
05819             exten3 = ast_hashtab_remove_this_object(exten->peer_table, exten2);
05820             if (!exten3)
05821                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);
05822             if (exten2 == exten && exten2->peer) {
05823                exten2 = ast_hashtab_remove_this_object(con->root_table, exten);
05824                ast_hashtab_insert_immediate(con->root_table, exten2->peer);
05825             }
05826             if (ast_hashtab_size(exten->peer_table) == 0) {
05827                /* well, if the last priority of an exten is to be removed,
05828                   then, the extension is removed, too! */
05829                exten3 = ast_hashtab_remove_this_object(con->root_table, exten);
05830                if (!exten3)
05831                   ast_log(LOG_ERROR,"Did not remove this exten (%s) from the context root_table (%s) (priority %d)\n", exten->exten, con->name, priority);
05832                if (con->pattern_tree) {
05833                   struct match_char *x = add_exten_to_pattern_tree(con, exten, 1);
05834                   if (x->exten) { /* this test for safety purposes */
05835                      x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */
05836                      x->exten = 0; /* get rid of what will become a bad pointer */
05837                   }
05838                }
05839             }
05840          } else {
05841             ast_log(LOG_ERROR,"Could not find priority %d of exten %s in context %s!\n",
05842                   priority, exten->exten, con->name);
05843          }
05844       }
05845    } else {
05846       /* hmmm? this exten is not in this pattern tree? */
05847       ast_log(LOG_WARNING,"Cannot find extension %s in root_table in context %s\n",
05848             extension, con->name);
05849    }
05850 #ifdef NEED_DEBUG
05851    if (con->pattern_tree) {
05852       ast_log(LOG_NOTICE,"match char tree after exten removal:\n");
05853       log_match_char_tree(con->pattern_tree, " ");
05854    }
05855 #endif
05856 
05857    /* scan the extension list to find first matching extension-registrar */
05858    for (exten = con->root; exten; prev_exten = exten, exten = exten->next) {
05859       if (!strcmp(exten->exten, extension) &&
05860          (!registrar || !strcmp(exten->registrar, registrar)) &&
05861          (!matchcallerid || (!ast_strlen_zero(callerid) && !ast_strlen_zero(exten->cidmatch) && !strcmp(exten->cidmatch, callerid)) || (ast_strlen_zero(callerid) && ast_strlen_zero(exten->cidmatch))))
05862          break;
05863    }
05864    if (!exten) {
05865       /* we can't find right extension */
05866       if (!already_locked)
05867          ast_unlock_context(con);
05868       return -1;
05869    }
05870 
05871    /* scan the priority list to remove extension with exten->priority == priority */
05872    for (peer = exten, next_peer = exten->peer ? exten->peer : exten->next;
05873        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)));
05874          peer = next_peer, next_peer = next_peer ? (next_peer->peer ? next_peer->peer : next_peer->next) : NULL) {
05875       if ((priority == 0 || peer->priority == priority) &&
05876             (!callerid || !matchcallerid || (matchcallerid && !strcmp(peer->cidmatch, callerid))) &&
05877             (!registrar || !strcmp(peer->registrar, registrar) )) {
05878          found = 1;
05879 
05880          /* we are first priority extension? */
05881          if (!previous_peer) {
05882             /*
05883              * We are first in the priority chain, so must update the extension chain.
05884              * The next node is either the next priority or the next extension
05885              */
05886             struct ast_exten *next_node = peer->peer ? peer->peer : peer->next;
05887             if (peer->peer) {
05888                /* move the peer_table and peer_label_table down to the next peer, if
05889                   it is there */
05890                peer->peer->peer_table = peer->peer_table;
05891                peer->peer->peer_label_table = peer->peer_label_table;
05892                peer->peer_table = NULL;
05893                peer->peer_label_table = NULL;
05894             }
05895             if (!prev_exten) {   /* change the root... */
05896                con->root = next_node;
05897             } else {
05898                prev_exten->next = next_node; /* unlink */
05899             }
05900             if (peer->peer)   { /* update the new head of the pri list */
05901                peer->peer->next = peer->next;
05902             }
05903          } else { /* easy, we are not first priority in extension */
05904             previous_peer->peer = peer->peer;
05905          }
05906 
05907          /* now, free whole priority extension */
05908          destroy_exten(peer);
05909       } else {
05910          previous_peer = peer;
05911       }
05912    }
05913    if (!already_locked)
05914       ast_unlock_context(con);
05915    return found ? 0 : -1;
05916 }

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

Definition at line 8135 of file pbx.c.

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

Referenced by handle_cli_dialplan_remove_ignorepat().

08136 {
08137    int ret = -1;
08138    struct ast_context *c;
08139 
08140    c = find_context_locked(context);
08141    if (c) {
08142       ret = ast_context_remove_ignorepat2(c, ignorepat, registrar);
08143       ast_unlock_contexts();
08144    }
08145    return ret;
08146 }

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

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

08149 {
08150    struct ast_ignorepat *ip, *ipl = NULL;
08151 
08152    ast_wrlock_context(con);
08153 
08154    for (ip = con->ignorepats; ip; ip = ip->next) {
08155       if (!strcmp(ip->pattern, ignorepat) &&
08156          (!registrar || (registrar == ip->registrar))) {
08157          if (ipl) {
08158             ipl->next = ip->next;
08159             ast_free(ip);
08160          } else {
08161             con->ignorepats = ip->next;
08162             ast_free(ip);
08163          }
08164          ast_unlock_context(con);
08165          return 0;
08166       }
08167       ipl = ip;
08168    }
08169 
08170    ast_unlock_context(con);
08171    errno = EINVAL;
08172    return -1;
08173 }

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

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

Referenced by handle_cli_dialplan_remove_include().

05623 {
05624    int ret = -1;
05625    struct ast_context *c;
05626 
05627    c = find_context_locked(context);
05628    if (c) {
05629       /* found, remove include from this context ... */
05630       ret = ast_context_remove_include2(c, include, registrar);
05631       ast_unlock_contexts();
05632    }
05633    return ret;
05634 }

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

Removes an include by an ast_context structure.

Note:
See ast_context_add_include2 for information on arguments
Return values:
0 on success
-1 on success
Removes an include by an ast_context structure.

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

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

05646 {
05647    struct ast_include *i, *pi = NULL;
05648    int ret = -1;
05649 
05650    ast_wrlock_context(con);
05651 
05652    /* find our include */
05653    for (i = con->includes; i; pi = i, i = i->next) {
05654       if (!strcmp(i->name, include) &&
05655             (!registrar || !strcmp(i->registrar, registrar))) {
05656          /* remove from list */
05657          ast_verb(3, "Removing inclusion of context '%s' in context '%s; registrar=%s'\n", include, ast_get_context_name(con), registrar);
05658          if (pi)
05659             pi->next = i->next;
05660          else
05661             con->includes = i->next;
05662          /* free include and return */
05663          ast_destroy_timing(&(i->timing));
05664          ast_free(i);
05665          ret = 0;
05666          break;
05667       }
05668    }
05669 
05670    ast_unlock_context(con);
05671 
05672    return ret;
05673 }

int ast_context_remove_switch ( const char *  context,
const char *  sw,
const char *  data,
const char *  registrar 
)

Remove a switch.

Removes a switch with the given parameters

Return values:
0 on success
-1 on failure
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 5680 of file pbx.c.

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

05681 {
05682    int ret = -1; /* default error return */
05683    struct ast_context *c;
05684 
05685    c = find_context_locked(context);
05686    if (c) {
05687       /* remove switch from this context ... */
05688       ret = ast_context_remove_switch2(c, sw, data, registrar);
05689       ast_unlock_contexts();
05690    }
05691    return ret;
05692 }

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

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

Referenced by ast_context_remove_switch().

05703 {
05704    struct ast_sw *i;
05705    int ret = -1;
05706 
05707    ast_wrlock_context(con);
05708 
05709    /* walk switches */
05710    AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) {
05711       if (!strcmp(i->name, sw) && !strcmp(i->data, data) &&
05712          (!registrar || !strcmp(i->registrar, registrar))) {
05713          /* found, remove from list */
05714          ast_verb(3, "Removing switch '%s' from context '%s; registrar=%s'\n", sw, ast_get_context_name(con), registrar);
05715          AST_LIST_REMOVE_CURRENT(list);
05716          ast_free(i); /* free switch and return */
05717          ret = 0;
05718          break;
05719       }
05720    }
05721    AST_LIST_TRAVERSE_SAFE_END;
05722 
05723    ast_unlock_context(con);
05724 
05725    return ret;
05726 }

int ast_context_unlockmacro ( const char *  context  ) 

Unlocks the macrolock in the given context.

Parameters:
macrocontext name of the macro-context to unlock
Unlocks the given macro-context so that another thread (call) can execute it

Return values:
0 on success
-1 on failure
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 5945 of file pbx.c.

References ast_mutex_unlock, ast_unlock_contexts(), find_context_locked(), and ast_context::macrolock.

Referenced by _macro_exec().

05946 {
05947    struct ast_context *c;
05948    int ret = -1;
05949 
05950    c = find_context_locked(context);
05951    if (c) {
05952       ast_unlock_contexts();
05953 
05954       /* if we found context, unlock macrolock */
05955       ret = ast_mutex_unlock(&c->macrolock);
05956    }
05957 
05958    return ret;
05959 }

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

10664 {
10665    struct ast_include *inc = NULL;
10666    int res = 0;
10667 
10668    while ( (inc = ast_walk_context_includes(con, inc)) ) {
10669       if (ast_context_find(inc->rname))
10670          continue;
10671 
10672       res = -1;
10673       ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n",
10674          ast_get_context_name(con), inc->rname);
10675       break;
10676    }
10677 
10678    return res;
10679 }

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

int ast_custom_function_unregister ( struct ast_custom_function acf  ) 

Unregister a custom function.

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

03641 {
03642    struct ast_custom_function *cur;
03643 
03644    if (!acf) {
03645       return -1;
03646    }
03647 
03648    AST_RWLIST_WRLOCK(&acf_root);
03649    if ((cur = AST_RWLIST_REMOVE(&acf_root, acf, acflist))) {
03650 #ifdef AST_XML_DOCS
03651       if (cur->docsrc == AST_XML_DOC) {
03652          ast_string_field_free_memory(acf);
03653       }
03654 #endif
03655       ast_verb(2, "Unregistered custom function %s\n", cur->name);
03656    }
03657    AST_RWLIST_UNLOCK(&acf_root);
03658 
03659    return cur ? 0 : -1;
03660 }

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

07978 {
07979    if (i->timezone) {
07980       ast_free(i->timezone);
07981       i->timezone = NULL;
07982    }
07983    return 0;
07984 }

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 4449 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_state3().

04450 {
04451    switch (devstate) {
04452    case AST_DEVICE_ONHOLD:
04453       return AST_EXTENSION_ONHOLD;
04454    case AST_DEVICE_BUSY:
04455       return AST_EXTENSION_BUSY;
04456    case AST_DEVICE_UNKNOWN:
04457       return AST_EXTENSION_NOT_INUSE;
04458    case AST_DEVICE_UNAVAILABLE:
04459    case AST_DEVICE_INVALID:
04460       return AST_EXTENSION_UNAVAILABLE;
04461    case AST_DEVICE_RINGINUSE:
04462       return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING);
04463    case AST_DEVICE_RINGING:
04464       return AST_EXTENSION_RINGING;
04465    case AST_DEVICE_INUSE:
04466       return AST_EXTENSION_INUSE;
04467    case AST_DEVICE_NOT_INUSE:
04468       return AST_EXTENSION_NOT_INUSE;
04469    case AST_DEVICE_TOTAL: /* not a device state, included for completeness */
04470       break;
04471    }
04472 
04473    return AST_EXTENSION_NOT_INUSE;
04474 }

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 5026 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(), action_originate(), analog_ss_thread(), answer_call(), ast_app_dtget(), ast_bridge_call(), ast_pbx_outgoing_exten(), cb_events(), cli_console_dial(), conf_run(), console_dial(), console_transfer(), dahdi_handle_dtmf(), dial_exec_full(), disa_exec(), dp_lookup(), dundi_lookup_local(), fax_detect_framehook(), findmeexec(), get_also_info(), get_destination(), get_refer_info(), gosub_exec(), handle_gosub(), handle_link_data(), handle_link_phone_dtmf(), 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(), parkandannounce_exec(), pbx_builtin_waitexten(), phone_check_exception(), privacy_exec(), process_ast_dsp(), process_sdp(), readexten_exec(), register_peer_exten(), rpt_exec(), setsubstate(), show_debug_helper(), sip_new(), sip_read(), skinny_ss(), socket_process(), try_calling(), vm_authenticate(), and waitstream_core().

05027 {
05028    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0);
05029 }

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

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

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

08289 {
08290    if (!chan)
08291       return -1;
08292 
08293    ast_channel_lock(chan);
08294 
08295    if (!ast_strlen_zero(context))
08296       ast_copy_string(chan->context, context, sizeof(chan->context));
08297    if (!ast_strlen_zero(exten))
08298       ast_copy_string(chan->exten, exten, sizeof(chan->exten));
08299    if (priority > -1) {
08300       chan->priority = priority;
08301       /* see flag description in channel.h for explanation */
08302       if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP))
08303          chan->priority--;
08304    }
08305 
08306    ast_channel_unlock(chan);
08307 
08308    return 0;
08309 }

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

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

02755 {
02756    if (needmore != E_MATCHMORE && needmore != E_CANMATCH)
02757       ast_log(LOG_WARNING, "invalid argument %d\n", needmore);
02758    return extension_match_core(pattern, data, needmore);
02759 }

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

References ext_cmp().

Referenced by lua_extension_cmp().

02557 {
02558    return ext_cmp(a, b);
02559 }

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

References E_MATCH, and extension_match_core().

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

02750 {
02751    return extension_match_core(pattern, data, E_MATCH);
02752 }

int ast_extension_patmatch ( const char *  pattern,
const char *  data 
)

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

04520 {
04521    struct ast_exten *e;
04522 
04523    if (!(e = ast_hint_extension(c, context, exten))) {  /* Do we have a hint for this extension ? */
04524       return -1;                   /* No hint, return -1 */
04525    }
04526 
04527    if (e->exten[0] == '_') {
04528       /* Create this hint on-the-fly */
04529       ast_add_extension(e->parent->name, 0, exten, e->priority, e->label,
04530          e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr,
04531          e->registrar);
04532       if (!(e = ast_hint_extension(c, context, exten))) {
04533          /* Improbable, but not impossible */
04534          return -1;
04535       }
04536    }
04537 
04538    return ast_extension_state2(e);  /* Check all devices in the hint */
04539 }

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

04508 {
04509    int i;
04510 
04511    for (i = 0; (i < ARRAY_LEN(extension_states)); i++) {
04512       if (extension_states[i].extension_state == extension_state)
04513          return extension_states[i].text;
04514    }
04515    return "Unknown";
04516 }

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

Registers a state change callback.

Parameters:
context which context to look in
exten which extension to get state
change_cb callback to call if state changed
data to pass to callback
Note:
The change_cb is called if the state of an extension is changed.
Return values:
-1 on failure
ID on success

Definition at line 4752 of file pbx.c.

References ast_extension_state_add_destroy().

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

04754 {
04755    return ast_extension_state_add_destroy(context, exten, change_cb, NULL, data);
04756 }

int ast_extension_state_add_destroy ( const char *  context,
const char *  exten,
ast_state_cb_type  change_cb,
ast_state_cb_destroy_type  destroy_cb,
void *  data 
)

Registers a state change callback with destructor.

Since:
1.8.9

10.1.0

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

The destroy_cb is called when the registration is deleted so the registerer can release any associated resources.

Return values:
-1 on failure
ID on success

Definition at line 4665 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_state_cb::change_cb, ast_exten::cidmatch, ast_exten::data, ast_state_cb::data, ast_state_cb::destroy_cb, destroy_state_cb(), ast_exten::exten, hints, ast_state_cb::id, ast_exten::label, ast_exten::matchcid, ast_context::name, OBJ_NODATA, OBJ_UNLINK, ast_exten::parent, ast_exten::priority, ast_exten::registrar, statecbs, and stateid.

Referenced by ast_extension_state_add(), and handle_request_subscribe().

04667 {
04668    struct ast_hint *hint;
04669    struct ast_state_cb *state_cb;
04670    struct ast_exten *e;
04671    int id;
04672 
04673    /* If there's no context and extension:  add callback to statecbs list */
04674    if (!context && !exten) {
04675       /* Prevent multiple adds from adding the same change_cb at the same time. */
04676       ao2_lock(statecbs);
04677 
04678       /* Remove any existing change_cb. */
04679       ao2_find(statecbs, change_cb, OBJ_UNLINK | OBJ_NODATA);
04680 
04681       /* Now insert the change_cb */
04682       if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) {
04683          ao2_unlock(statecbs);
04684          return -1;
04685       }
04686       state_cb->id = 0;
04687       state_cb->change_cb = change_cb;
04688       state_cb->destroy_cb = destroy_cb;
04689       state_cb->data = data;
04690       ao2_link(statecbs, state_cb);
04691 
04692       ao2_ref(state_cb, -1);
04693       ao2_unlock(statecbs);
04694       return 0;
04695    }
04696 
04697    if (!context || !exten)
04698       return -1;
04699 
04700    /* This callback type is for only one hint, so get the hint */
04701    e = ast_hint_extension(NULL, context, exten);
04702    if (!e) {
04703       return -1;
04704    }
04705 
04706    /* If this is a pattern, dynamically create a new extension for this
04707     * particular match.  Note that this will only happen once for each
04708     * individual extension, because the pattern will no longer match first.
04709     */
04710    if (e->exten[0] == '_') {
04711       ast_add_extension(e->parent->name, 0, exten, e->priority, e->label,
04712          e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr,
04713          e->registrar);
04714       e = ast_hint_extension(NULL, context, exten);
04715       if (!e || e->exten[0] == '_') {
04716          return -1;
04717       }
04718    }
04719 
04720    /* Find the hint in the hints container */
04721    ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */
04722    hint = ao2_find(hints, e, 0);
04723    if (!hint) {
04724       ao2_unlock(hints);
04725       return -1;
04726    }
04727 
04728    /* Now insert the callback in the callback list  */
04729    if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) {
04730       ao2_ref(hint, -1);
04731       ao2_unlock(hints);
04732       return -1;
04733    }
04734    do {
04735       id = stateid++;      /* Unique ID for this callback */
04736       /* Do not allow id to ever be -1 or 0. */
04737    } while (id == -1 || id == 0);
04738    state_cb->id = id;
04739    state_cb->change_cb = change_cb; /* Pointer to callback routine */
04740    state_cb->destroy_cb = destroy_cb;
04741    state_cb->data = data;     /* Data for the callback */
04742    ao2_link(hint->callbacks, state_cb);
04743 
04744    ao2_ref(state_cb, -1);
04745    ao2_ref(hint, -1);
04746    ao2_unlock(hints);
04747 
04748    return id;
04749 }

int ast_extension_state_del ( int  id,
ast_state_cb_type  change_cb 
)

Deletes a registered state change callback by ID.

Parameters:
id of the registered state callback to delete
change_cb callback to call if state changed (Used if id == 0 (global))
Return values:
0 success
-1 failure

Definition at line 4774 of file pbx.c.

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

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

04775 {
04776    struct ast_state_cb *p_cur;
04777    int ret = -1;
04778 
04779    if (!id) {  /* id == 0 is a callback without extension */
04780       if (!change_cb) {
04781          return ret;
04782       }
04783       p_cur = ao2_find(statecbs, change_cb, OBJ_UNLINK);
04784       if (p_cur) {
04785          ret = 0;
04786          ao2_ref(p_cur, -1);
04787       }
04788    } else { /* callback with extension, find the callback based on ID */
04789       struct ast_hint *hint;
04790 
04791       ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */
04792       hint = ao2_callback(hints, 0, find_hint_by_cb_id, &id);
04793       if (hint) {
04794          p_cur = ao2_find(hint->callbacks, &id, OBJ_UNLINK);
04795          if (p_cur) {
04796             ret = 0;
04797             ao2_ref(p_cur, -1);
04798          }
04799          ao2_ref(hint, -1);
04800       }
04801       ao2_unlock(hints);
04802    }
04803 
04804    return ret;
04805 }

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

05032 {
05033    return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
05034 }

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

References E_FINDLABEL, and pbx_extension_helper().

Referenced by pbx_load_config().

05037 {
05038    return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
05039 }

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

03785 {
03786    char *copy = ast_strdupa(function);
03787    char *args = func_args(copy);
03788    struct ast_custom_function *acfptr = ast_custom_function_find(copy);
03789    int res;
03790    struct ast_module_user *u = NULL;
03791 
03792    if (acfptr == NULL) {
03793       ast_log(LOG_ERROR, "Function %s not registered\n", copy);
03794    } else if (!acfptr->read && !acfptr->read2) {
03795       ast_log(LOG_ERROR, "Function %s cannot be read\n", copy);
03796    } else if (acfptr->read) {
03797       if (acfptr->mod) {
03798          u = __ast_module_user_add(acfptr->mod, chan);
03799       }
03800       res = acfptr->read(chan, copy, args, workspace, len);
03801       if (acfptr->mod && u) {
03802          __ast_module_user_remove(acfptr->mod, u);
03803       }
03804       return res;
03805    } else {
03806       struct ast_str *str = ast_str_create(16);
03807       if (acfptr->mod) {
03808          u = __ast_module_user_add(acfptr->mod, chan);
03809       }
03810       res = acfptr->read2(chan, copy, args, &str, 0);
03811       if (acfptr->mod && u) {
03812          __ast_module_user_remove(acfptr->mod, u);
03813       }
03814       ast_copy_string(workspace, ast_str_buffer(str), len > ast_str_size(str) ? ast_str_size(str) : len);
03815       ast_free(str);
03816       return res;
03817    }
03818    return -1;
03819 }

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 3821 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, copy(), func_args(), LOG_ERROR, maxsize, ast_custom_function::mod, ast_custom_function::read, ast_custom_function::read2, ast_custom_function::read_max, and VAR_BUF_SIZE.

Referenced by append_channel_vars(), and ast_str_substitute_variables_full().

03822 {
03823    char *copy = ast_strdupa(function);
03824    char *args = func_args(copy);
03825    struct ast_custom_function *acfptr = ast_custom_function_find(copy);
03826    int res;
03827    struct ast_module_user *u = NULL;
03828 
03829    if (acfptr == NULL) {
03830       ast_log(LOG_ERROR, "Function %s not registered\n", copy);
03831    } else if (!acfptr->read && !acfptr->read2) {
03832       ast_log(LOG_ERROR, "Function %s cannot be read\n", copy);
03833    } else {
03834       if (acfptr->mod) {
03835          u = __ast_module_user_add(acfptr->mod, chan);
03836       }
03837       ast_str_reset(*str);
03838       if (acfptr->read2) {
03839          /* ast_str enabled */
03840          res = acfptr->read2(chan, copy, args, str, maxlen);
03841       } else {
03842          /* Legacy function pointer, allocate buffer for result */
03843          int maxsize = ast_str_size(*str);
03844          if (maxlen > -1) {
03845             if (maxlen == 0) {
03846                if (acfptr->read_max) {
03847                   maxsize = acfptr->read_max;
03848                } else {
03849                   maxsize = VAR_BUF_SIZE;
03850                }
03851             } else {
03852                maxsize = maxlen;
03853             }
03854             ast_str_make_space(str, maxsize);
03855          }
03856          res = acfptr->read(chan, copy, args, ast_str_buffer(*str), maxsize);
03857       }
03858       if (acfptr->mod && u) {
03859          __ast_module_user_remove(acfptr->mod, u);
03860       }
03861       return res;
03862    }
03863    return -1;
03864 }

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

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

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

03867 {
03868    char *copy = ast_strdupa(function);
03869    char *args = func_args(copy);
03870    struct ast_custom_function *acfptr = ast_custom_function_find(copy);
03871 
03872    if (acfptr == NULL)
03873       ast_log(LOG_ERROR, "Function %s not registered\n", copy);
03874    else if (!acfptr->write)
03875       ast_log(LOG_ERROR, "Function %s cannot be written to\n", copy);
03876    else {
03877       int res;
03878       struct ast_module_user *u = NULL;
03879       if (acfptr->mod)
03880          u = __ast_module_user_add(acfptr->mod, chan);
03881       res = acfptr->write(chan, copy, args, value);
03882       if (acfptr->mod && u)
03883          __ast_module_user_remove(acfptr->mod, u);
03884       return res;
03885    }
03886 
03887    return -1;
03888 }

const char* ast_get_context_name ( struct ast_context con  ) 

const char* ast_get_context_registrar ( struct ast_context c  ) 

Definition at line 10553 of file pbx.c.

References ast_context::registrar.

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

10554 {
10555    return c ? c->registrar : NULL;
10556 }

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  ) 

Definition at line 10578 of file pbx.c.

References ast_exten::cidmatch.

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

10579 {
10580    return e ? e->cidmatch : NULL;
10581 }

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

Definition at line 10520 of file pbx.c.

References ast_exten::parent.

Referenced by ast_add_hint(), ast_change_hint(), ast_remove_hint(), destroy_hint(), handle_show_hint(), handle_show_hints(), handle_statechange(), and hints_data_provider_get().

10521 {
10522    return exten ? exten->parent : NULL;
10523 }

const char* ast_get_extension_label ( struct ast_exten e  ) 

Definition at line 10530 of file pbx.c.

References ast_exten::label.

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

10531 {
10532    return exten ? exten->label : NULL;
10533 }

int ast_get_extension_matchcid ( struct ast_exten e  ) 

Definition at line 10573 of file pbx.c.

References ast_exten::matchcid.

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

10574 {
10575    return e ? e->matchcid : 0;
10576 }

const char* ast_get_extension_name ( struct ast_exten exten  ) 

int ast_get_extension_priority ( struct ast_exten exten  ) 

Definition at line 10545 of file pbx.c.

References ast_exten::priority.

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

10546 {
10547    return exten ? exten->priority : -1;
10548 }

const char* ast_get_extension_registrar ( struct ast_exten e  ) 

Definition at line 10558 of file pbx.c.

References ast_exten::registrar.

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

10559 {
10560    return e ? e->registrar : NULL;
10561 }

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

04989 {
04990    struct ast_exten *e = ast_hint_extension(c, context, exten);
04991 
04992    if (e) {
04993       if (hint)
04994          ast_copy_string(hint, ast_get_extension_app(e), hintsize);
04995       if (name) {
04996          const char *tmp = ast_get_extension_app_data(e);
04997          if (tmp)
04998             ast_copy_string(name, tmp, namesize);
04999       }
05000       return -1;
05001    }
05002    return 0;
05003 }

const char* ast_get_ignorepat_name ( struct ast_ignorepat ip  ) 

const char* ast_get_ignorepat_registrar ( struct ast_ignorepat ip  ) 

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

10569 {
10570    return ip ? ip->registrar : NULL;
10571 }

const char* ast_get_include_name ( struct ast_include include  ) 

const char* ast_get_include_registrar ( struct ast_include i  ) 

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

10564 {
10565    return i ? i->registrar : NULL;
10566 }

const char* ast_get_switch_data ( struct ast_sw sw  ) 

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

10599 {
10600    return sw ? sw->data : NULL;
10601 }

int ast_get_switch_eval ( struct ast_sw sw  ) 

Definition at line 10603 of file pbx.c.

References ast_sw::eval.

Referenced by context_merge_incls_swits_igps_other_registrars().

10604 {
10605    return sw->eval;
10606 }

const char* ast_get_switch_name ( struct ast_sw sw  ) 

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

10594 {
10595    return sw ? sw->name : NULL;
10596 }

const char* ast_get_switch_registrar ( struct ast_sw sw  ) 

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

10609 {
10610    return sw ? sw->registrar : NULL;
10611 }

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

10704 {
10705    return __ast_goto_if_exists(chan, context, exten, priority, 0);
10706 }

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

hashtable functions for contexts

Definition at line 1186 of file pbx.c.

References ast_context::name.

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

01187 {
01188    const struct ast_context *ac = ah_a;
01189    const struct ast_context *bc = ah_b;
01190    if (!ac || !bc) /* safety valve, but it might prevent a crash you'd rather have happen */
01191       return 1;
01192    /* assume context names are registered in a string table! */
01193    return strcmp(ac->name, bc->name);
01194 }

unsigned int ast_hashtab_hash_contexts ( const void *  obj  ) 

Definition at line 1229 of file pbx.c.

References ast_hashtab_hash_string(), and ast_context::name.

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

01230 {
01231    const struct ast_context *ac = obj;
01232    return ast_hashtab_hash_string(ac->name);
01233 }

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 8230 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(), mgcp_ss(), and skinny_ss().

08231 {
08232    struct ast_context *con = ast_context_find(context);
08233 
08234    if (con) {
08235       struct ast_ignorepat *pat;
08236 
08237       for (pat = con->ignorepats; pat; pat = pat->next) {
08238          if (ast_extension_match(pat->pattern, pattern))
08239             return 1;
08240       }
08241    }
08242 
08243    return 0;
08244 }

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

References E_MATCHMORE, and pbx_extension_helper().

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

05047 {
05048    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0);
05049 }

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

References __ast_internal_context_destroy(), ao2_callback, ao2_container_count(), ao2_find, ao2_iterator_destroy(), AO2_ITERATOR_DONTLOCK, ao2_iterator_init(), ao2_iterator_next, ao2_link, ao2_lock, ao2_ref, ao2_unlock, ast_exten::app, ast_add_extension_nolock(), ast_calloc, AST_EXTENSION_REMOVED, ast_free, ast_free_ptr, ast_hashtab_destroy(), ast_hashtab_end_traversal(), ast_hashtab_next(), ast_hashtab_start_traversal(), ast_hint_extension_nolock(), AST_LIST_HEAD_NOLOCK_INIT_VALUE, AST_LIST_INSERT_HEAD, AST_LIST_INSERT_TAIL, AST_LIST_REMOVE_HEAD, ast_mutex_lock, ast_mutex_unlock, ast_strdup, ast_tvdiff_us(), ast_tvnow(), ast_unlock_contexts(), ast_verb, ast_wrlock_contexts(), store_hint::callbacks, ast_hint::callbacks, ast_state_cb::change_cb, store_hint::context, context_merge(), context_merge_lock, contexts, contexts_table, ast_state_cb::data, ast_exten::data, store_hint::data, E_MATCH, store_hint::exten, ast_exten::exten, ast_hint::exten, hints, ast_hint::laststate, store_hint::laststate, ast_context::name, ast_context::next, ast_sw::next, OBJ_UNLINK, ast_exten::parent, pbx_find_extension(), PRIORITY_HINT, ast_exten::registrar, and pbx_find_info::stacklen.

Referenced by lua_reload_extensions(), and pbx_load_module().

07529 {
07530    double ft;
07531    struct ast_context *tmp;
07532    struct ast_context *oldcontextslist;
07533    struct ast_hashtab *oldtable;
07534    struct store_hints hints_stored = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
07535    struct store_hints hints_removed = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
07536    struct store_hint *saved_hint;
07537    struct ast_hint *hint;
07538    struct ast_exten *exten;
07539    int length;
07540    struct ast_state_cb *thiscb;
07541    struct ast_hashtab_iter *iter;
07542    struct ao2_iterator i;
07543    struct timeval begintime;
07544    struct timeval writelocktime;
07545    struct timeval endlocktime;
07546    struct timeval enddeltime;
07547 
07548    /*
07549     * It is very important that this function hold the hints
07550     * container lock _and_ the conlock during its operation; not
07551     * only do we need to ensure that the list of contexts and
07552     * extensions does not change, but also that no hint callbacks
07553     * (watchers) are added or removed during the merge/delete
07554     * process
07555     *
07556     * In addition, the locks _must_ be taken in this order, because
07557     * there are already other code paths that use this order
07558     */
07559 
07560    begintime = ast_tvnow();
07561    ast_mutex_lock(&context_merge_lock);/* Serialize ast_merge_contexts_and_delete */
07562    ast_wrlock_contexts();
07563    iter = ast_hashtab_start_traversal(contexts_table);
07564    while ((tmp = ast_hashtab_next(iter))) {
07565       context_merge(extcontexts, exttable, tmp, registrar);
07566    }
07567    ast_hashtab_end_traversal(iter);
07568 
07569    ao2_lock(hints);
07570    writelocktime = ast_tvnow();
07571 
07572    /* preserve all watchers for hints */
07573    i = ao2_iterator_init(hints, AO2_ITERATOR_DONTLOCK);
07574    for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
07575       if (ao2_container_count(hint->callbacks)) {
07576          ao2_lock(hint);
07577          if (!hint->exten) {
07578             /* The extension has already been destroyed. (Should never happen here) */
07579             ao2_unlock(hint);
07580             continue;
07581          }
07582 
07583          length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2
07584             + sizeof(*saved_hint);
07585          if (!(saved_hint = ast_calloc(1, length))) {
07586             ao2_unlock(hint);
07587             continue;
07588          }
07589 
07590          /* This removes all the callbacks from the hint into saved_hint. */
07591          while ((thiscb = ao2_callback(hint->callbacks, OBJ_UNLINK, NULL, NULL))) {
07592             AST_LIST_INSERT_TAIL(&saved_hint->callbacks, thiscb, entry);
07593             /*
07594              * We intentionally do not unref thiscb to account for the
07595              * non-ao2 reference in saved_hint->callbacks
07596              */
07597          }
07598 
07599          saved_hint->laststate = hint->laststate;
07600          saved_hint->context = saved_hint->data;
07601          strcpy(saved_hint->data, hint->exten->parent->name);
07602          saved_hint->exten = saved_hint->data + strlen(saved_hint->context) + 1;
07603          strcpy(saved_hint->exten, hint->exten->exten);
07604          ao2_unlock(hint);
07605          AST_LIST_INSERT_HEAD(&hints_stored, saved_hint, list);
07606       }
07607    }
07608    ao2_iterator_destroy(&i);
07609 
07610    /* save the old table and list */
07611    oldtable = contexts_table;
07612    oldcontextslist = contexts;
07613 
07614    /* move in the new table and list */
07615    contexts_table = exttable;
07616    contexts = *extcontexts;
07617 
07618    /*
07619     * Restore the watchers for hints that can be found; notify
07620     * those that cannot be restored.
07621     */
07622    while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_stored, list))) {
07623       struct pbx_find_info q = { .stacklen = 0 };
07624 
07625       exten = pbx_find_extension(NULL, NULL, &q, saved_hint->context, saved_hint->exten,
07626          PRIORITY_HINT, NULL, "", E_MATCH);
07627       /*
07628        * If this is a pattern, dynamically create a new extension for this
07629        * particular match.  Note that this will only happen once for each
07630        * individual extension, because the pattern will no longer match first.
07631        */
07632       if (exten && exten->exten[0] == '_') {
07633          ast_add_extension_nolock(exten->parent->name, 0, saved_hint->exten,
07634             PRIORITY_HINT, NULL, 0, exten->app, ast_strdup(exten->data), ast_free_ptr,
07635             exten->registrar);
07636          /* rwlocks are not recursive locks */
07637          exten = ast_hint_extension_nolock(NULL, saved_hint->context,
07638             saved_hint->exten);
07639       }
07640 
07641       /* Find the hint in the hints container */
07642       hint = exten ? ao2_find(hints, exten, 0) : NULL;
07643       if (!hint) {
07644          /*
07645           * Notify watchers of this removed hint later when we aren't
07646           * encumberd by so many locks.
07647           */
07648          AST_LIST_INSERT_HEAD(&hints_removed, saved_hint, list);
07649       } else {
07650          ao2_lock(hint);
07651          while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) {
07652             ao2_link(hint->callbacks, thiscb);
07653             /* Ref that we added when putting into saved_hint->callbacks */
07654             ao2_ref(thiscb, -1);
07655          }
07656          hint->laststate = saved_hint->laststate;
07657          ao2_unlock(hint);
07658          ao2_ref(hint, -1);
07659          ast_free(saved_hint);
07660       }
07661    }
07662 
07663    ao2_unlock(hints);
07664    ast_unlock_contexts();
07665 
07666    /*
07667     * Notify watchers of all removed hints with the same lock
07668     * environment as handle_statechange().
07669     */
07670    while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_removed, list))) {
07671       /* this hint has been removed, notify the watchers */
07672       while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) {
07673          thiscb->change_cb(saved_hint->context, saved_hint->exten,
07674             AST_EXTENSION_REMOVED, thiscb->data);
07675          /* Ref that we added when putting into saved_hint->callbacks */
07676          ao2_ref(thiscb, -1);
07677       }
07678       ast_free(saved_hint);
07679    }
07680 
07681    ast_mutex_unlock(&context_merge_lock);
07682    endlocktime = ast_tvnow();
07683 
07684    /*
07685     * The old list and hashtab no longer are relevant, delete them
07686     * while the rest of asterisk is now freely using the new stuff
07687     * instead.
07688     */
07689 
07690    ast_hashtab_destroy(oldtable, NULL);
07691 
07692    for (tmp = oldcontextslist; tmp; ) {
07693       struct ast_context *next;  /* next starting point */
07694 
07695       next = tmp->next;
07696       __ast_internal_context_destroy(tmp);
07697       tmp = next;
07698    }
07699    enddeltime = ast_tvnow();
07700 
07701    ft = ast_tvdiff_us(writelocktime, begintime);
07702    ft /= 1000000.0;
07703    ast_verb(3,"Time to scan old dialplan and merge leftovers back into the new: %8.6f sec\n", ft);
07704 
07705    ft = ast_tvdiff_us(endlocktime, writelocktime);
07706    ft /= 1000000.0;
07707    ast_verb(3,"Time to restore hints and swap in new dialplan: %8.6f sec\n", ft);
07708 
07709    ft = ast_tvdiff_us(enddeltime, endlocktime);
07710    ft /= 1000000.0;
07711    ast_verb(3,"Time to delete the old dialplan: %8.6f sec\n", ft);
07712 
07713    ft = ast_tvdiff_us(enddeltime, begintime);
07714    ft /= 1000000.0;
07715    ast_verb(3,"Total time merge_contexts_delete: %8.6f sec\n", ft);
07716 }

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

10769 {
10770    return pbx_parseable_goto(chan, goto_string, 0);
10771 }

int ast_pbx_outgoing_app ( const char *  type,
struct ast_format_cap cap,
const char *  addr,
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 9107 of file pbx.c.

References __ast_request_and_dial(), ast_channel::_state, outgoing_helper::account, async_stat::app, async_stat::appdata, ast_calloc, ast_cdr_disposition(), ast_cdr_failed(), ast_cdr_setaccount(), ast_channel_lock, ast_channel_name(), 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_string_field_free_memory, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), ast_variables_destroy(), ast_verb, async_wait(), ast_channel::cdr, async_stat::chan, app_tmp::chan, errno, ast_channel::hangupcause, LOG_WARNING, async_stat::p, app_tmp::t, async_stat::timeout, and outgoing_helper::vars.

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

09108 {
09109    struct ast_channel *chan;
09110    struct app_tmp *tmp;
09111    int res = -1, cdr_res = -1;
09112    struct outgoing_helper oh;
09113 
09114    memset(&oh, 0, sizeof(oh));
09115    oh.vars = vars;
09116    oh.account = account;
09117 
09118    if (locked_channel)
09119       *locked_channel = NULL;
09120    if (ast_strlen_zero(app)) {
09121       res = -1;
09122       goto outgoing_app_cleanup;
09123    }
09124    if (synchronous) {
09125       chan = __ast_request_and_dial(type, cap, NULL, addr, timeout, reason, cid_num, cid_name, &oh);
09126       if (chan) {
09127          ast_set_variables(chan, vars);
09128          if (account)
09129             ast_cdr_setaccount(chan, account);
09130          if (chan->_state == AST_STATE_UP) {
09131             res = 0;
09132             ast_verb(4, "Channel %s was answered.\n", ast_channel_name(chan));
09133             tmp = ast_calloc(1, sizeof(*tmp));
09134             if (!tmp || ast_string_field_init(tmp, 252)) {
09135                if (tmp) {
09136                   ast_free(tmp);
09137                }
09138                res = -1;
09139             } else {
09140                ast_string_field_set(tmp, app, app);
09141                ast_string_field_set(tmp, data, appdata);
09142                tmp->chan = chan;
09143                if (synchronous > 1) {
09144                   if (locked_channel)
09145                      ast_channel_unlock(chan);
09146                   ast_pbx_run_app(tmp);
09147                } else {
09148                   if (locked_channel)
09149                      ast_channel_lock(chan);
09150                   if (ast_pthread_create_detached(&tmp->t, NULL, ast_pbx_run_app, tmp)) {
09151                      ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", ast_channel_name(chan), strerror(errno));
09152                      ast_string_field_free_memory(tmp);
09153                      ast_free(tmp);
09154                      if (locked_channel)
09155                         ast_channel_unlock(chan);
09156                      ast_hangup(chan);
09157                      res = -1;
09158                   } else {
09159                      if (locked_channel)
09160                         *locked_channel = chan;
09161                   }
09162                }
09163             }
09164          } else {
09165             ast_verb(4, "Channel %s was never answered.\n", ast_channel_name(chan));
09166             if (chan->cdr) { /* update the cdr */
09167                /* here we update the status of the call, which sould be busy.
09168                 * if that fails then we set the status to failed */
09169                if (ast_cdr_disposition(chan->cdr, chan->hangupcause))
09170                   ast_cdr_failed(chan->cdr);
09171             }
09172             ast_hangup(chan);
09173          }
09174       }
09175 
09176       if (res < 0) { /* the call failed for some reason */
09177          if (*reason == 0) { /* if the call failed (not busy or no answer)
09178                         * update the cdr with the failed message */
09179             cdr_res = ast_pbx_outgoing_cdr_failed();
09180             if (cdr_res != 0) {
09181                res = cdr_res;
09182                goto outgoing_app_cleanup;
09183             }
09184          }
09185       }
09186 
09187    } else {
09188       struct async_stat *as;
09189       if (!(as = ast_calloc(1, sizeof(*as)))) {
09190          res = -1;
09191          goto outgoing_app_cleanup;
09192       }
09193       chan = __ast_request_and_dial(type, cap, NULL, addr, timeout, reason, cid_num, cid_name, &oh);
09194       if (!chan) {
09195          ast_free(as);
09196          res = -1;
09197          goto outgoing_app_cleanup;
09198       }
09199       as->chan = chan;
09200       ast_copy_string(as->app, app, sizeof(as->app));
09201       if (appdata)
09202          ast_copy_string(as->appdata,  appdata, sizeof(as->appdata));
09203       as->timeout = timeout;
09204       ast_set_variables(chan, vars);
09205       if (account)
09206          ast_cdr_setaccount(chan, account);
09207       /* Start a new thread, and get something handling this channel. */
09208       if (locked_channel)
09209          ast_channel_lock(chan);
09210       if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) {
09211          ast_log(LOG_WARNING, "Failed to start async wait\n");
09212          ast_free(as);
09213          if (locked_channel)
09214             ast_channel_unlock(chan);
09215          ast_hangup(chan);
09216          res = -1;
09217          goto outgoing_app_cleanup;
09218       } else {
09219          if (locked_channel)
09220             *locked_channel = chan;
09221       }
09222       res = 0;
09223    }
09224 outgoing_app_cleanup:
09225    ast_variables_destroy(vars);
09226    return res;
09227 }

int ast_pbx_outgoing_exten ( const char *  type,
struct ast_format_cap cap,
const char *  addr,
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 8938 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_name(), ast_channel_unlock, ast_copy_string(), ast_exists_extension(), ast_free, ast_hangup(), ast_log(), ast_pbx_outgoing_cdr_failed(), ast_pbx_run(), ast_pbx_start(), ast_pthread_create_detached, ast_request_and_dial(), ast_set_variables(), AST_STATE_DOWN, AST_STATE_UP, ast_strlen_zero(), ast_variables_destroy(), ast_verb, async_wait(), ast_channel::cdr, async_stat::chan, outgoing_helper::cid_name, outgoing_helper::cid_num, async_stat::context, ast_channel::context, outgoing_helper::context, outgoing_helper::exten, ast_channel::hangupcause, LOG_ERROR, LOG_WARNING, async_stat::p, outgoing_helper::parent_channel, pbx_builtin_setvar_helper(), outgoing_helper::priority, set_ext_pri(), async_stat::timeout, and outgoing_helper::vars.

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

08939 {
08940    struct ast_channel *chan;
08941    struct async_stat *as;
08942    int res = -1, cdr_res = -1;
08943    struct outgoing_helper oh;
08944 
08945    if (synchronous) {
08946       oh.context = context;
08947       oh.exten = exten;
08948       oh.priority = priority;
08949       oh.cid_num = cid_num;
08950       oh.cid_name = cid_name;
08951       oh.account = account;
08952       oh.vars = vars;
08953       oh.parent_channel = NULL;
08954 
08955       chan = __ast_request_and_dial(type, cap, NULL, addr, timeout, reason, cid_num, cid_name, &oh);
08956       if (channel) {
08957          *channel = chan;
08958          if (chan)
08959             ast_channel_lock(chan);
08960       }
08961       if (chan) {
08962          if (chan->_state == AST_STATE_UP) {
08963                res = 0;
08964             ast_verb(4, "Channel %s was answered.\n", ast_channel_name(chan));
08965 
08966             if (synchronous > 1) {
08967                if (channel)
08968                   ast_channel_unlock(chan);
08969                if (ast_pbx_run(chan)) {
08970                   ast_log(LOG_ERROR, "Unable to run PBX on %s\n", ast_channel_name(chan));
08971                   if (channel)
08972                      *channel = NULL;
08973                   ast_hangup(chan);
08974                   chan = NULL;
08975                   res = -1;
08976                }
08977             } else {
08978                if (ast_pbx_start(chan)) {
08979                   ast_log(LOG_ERROR, "Unable to start PBX on %s\n", ast_channel_name(chan));
08980                   if (channel) {
08981                      *channel = NULL;
08982                      ast_channel_unlock(chan);
08983                   }
08984                   ast_hangup(chan);
08985                   res = -1;
08986                }
08987                chan = NULL;
08988             }
08989          } else {
08990             ast_verb(4, "Channel %s was never answered.\n", ast_channel_name(chan));
08991 
08992             if (chan->cdr) { /* update the cdr */
08993                /* here we update the status of the call, which sould be busy.
08994                 * if that fails then we set the status to failed */
08995                if (ast_cdr_disposition(chan->cdr, chan->hangupcause))
08996                   ast_cdr_failed(chan->cdr);
08997             }
08998 
08999             if (channel) {
09000                *channel = NULL;
09001                ast_channel_unlock(chan);
09002             }
09003             ast_hangup(chan);
09004             chan = NULL;
09005          }
09006       }
09007 
09008       if (res < 0) { /* the call failed for some reason */
09009          if (*reason == 0) { /* if the call failed (not busy or no answer)
09010                         * update the cdr with the failed message */
09011             cdr_res = ast_pbx_outgoing_cdr_failed();
09012             if (cdr_res != 0) {
09013                res = cdr_res;
09014                goto outgoing_exten_cleanup;
09015             }
09016          }
09017 
09018          /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */
09019          /* check if "failed" exists */
09020          if (ast_exists_extension(chan, context, "failed", 1, NULL)) {
09021             chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", NULL, 0, "OutgoingSpoolFailed");
09022             if (chan) {
09023                char failed_reason[4] = "";
09024                if (!ast_strlen_zero(context))
09025                   ast_copy_string(chan->context, context, sizeof(chan->context));
09026                set_ext_pri(chan, "failed", 1);
09027                ast_set_variables(chan, vars);
09028                snprintf(failed_reason, sizeof(failed_reason), "%d", *reason);
09029                pbx_builtin_setvar_helper(chan, "REASON", failed_reason);
09030                if (account)
09031                   ast_cdr_setaccount(chan, account);
09032                if (ast_pbx_run(chan)) {
09033                   ast_log(LOG_ERROR, "Unable to run PBX on %s\n", ast_channel_name(chan));
09034                   ast_hangup(chan);
09035                }
09036                chan = NULL;
09037             }
09038          }
09039       }
09040    } else {
09041       if (!(as = ast_calloc(1, sizeof(*as)))) {
09042          res = -1;
09043          goto outgoing_exten_cleanup;
09044       }
09045       chan = ast_request_and_dial(type, cap, NULL, addr, timeout, reason, cid_num, cid_name);
09046       if (channel) {
09047          *channel = chan;
09048          if (chan)
09049             ast_channel_lock(chan);
09050       }
09051       if (!chan) {
09052          ast_free(as);
09053          res = -1;
09054          goto outgoing_exten_cleanup;
09055       }
09056       as->chan = chan;
09057       ast_copy_string(as->context, context, sizeof(as->context));
09058       set_ext_pri(as->chan,  exten, priority);
09059       as->timeout = timeout;
09060       ast_set_variables(chan, vars);
09061       if (account)
09062          ast_cdr_setaccount(chan, account);
09063       if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) {
09064          ast_log(LOG_WARNING, "Failed to start async wait\n");
09065          ast_free(as);
09066          if (channel) {
09067             *channel = NULL;
09068             ast_channel_unlock(chan);
09069          }
09070          ast_hangup(chan);
09071          res = -1;
09072          goto outgoing_exten_cleanup;
09073       }
09074       res = 0;
09075    }
09076 outgoing_exten_cleanup:
09077    ast_variables_destroy(vars);
09078    return res;
09079 }

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

References ast_pbx_run_args().

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

05542 {
05543    return ast_pbx_run_args(c, NULL);
05544 }

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

References __ast_pbx_run(), ast_log(), AST_OPT_FLAG_FULLY_BOOTED, ast_options, AST_PBX_CALL_LIMIT, AST_PBX_FAILED, AST_PBX_SUCCESS, ast_test_flag, decrease_call_count(), increase_call_count(), and LOG_WARNING.

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

05522 {
05523    enum ast_pbx_result res = AST_PBX_SUCCESS;
05524 
05525    if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) {
05526       ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n");
05527       return AST_PBX_FAILED;
05528    }
05529 
05530    if (increase_call_count(c)) {
05531       return AST_PBX_CALL_LIMIT;
05532    }
05533 
05534    res = __ast_pbx_run(c, args);
05535 
05536    decrease_call_count();
05537 
05538    return res;
05539 }

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

References ast_log(), AST_OPT_FLAG_FULLY_BOOTED, ast_options, AST_PBX_CALL_LIMIT, AST_PBX_FAILED, AST_PBX_SUCCESS, ast_pthread_create_detached, ast_test_flag, 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_parked_call(), mgcp_new(), nbs_new(), oss_new(), pbx_start_chan(), phone_new(), rpt_call(), skinny_new(), unistim_new(), and usbradio_new().

05495 {
05496    pthread_t t;
05497 
05498    if (!c) {
05499       ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
05500       return AST_PBX_FAILED;
05501    }
05502 
05503    if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) {
05504       ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n");
05505       return AST_PBX_FAILED;
05506    }
05507 
05508    if (increase_call_count(c))
05509       return AST_PBX_CALL_LIMIT;
05510 
05511    /* Start a new thread, and get something handling this channel. */
05512    if (ast_pthread_create_detached(&t, NULL, pbx_thread, c)) {
05513       ast_log(LOG_WARNING, "Failed to create new channel thread\n");
05514       decrease_call_count();
05515       return AST_PBX_FAILED;
05516    }
05517 
05518    return AST_PBX_SUCCESS;
05519 }

int ast_processed_calls ( void   ) 

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

Definition at line 5551 of file pbx.c.

References totalcalls.

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

05552 {
05553    return totalcalls;
05554 }

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

10503 {
10504    return ast_rwlock_rdlock(&con->lock);
10505 }

int ast_rdlock_contexts ( void   ) 

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

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

Referenced by load_module().

06058 {
06059    struct ast_switch *tmp;
06060 
06061    AST_RWLIST_WRLOCK(&switches);
06062    AST_RWLIST_TRAVERSE(&switches, tmp, list) {
06063       if (!strcasecmp(tmp->name, sw->name)) {
06064          AST_RWLIST_UNLOCK(&switches);
06065          ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name);
06066          return -1;
06067       }
06068    }
06069    AST_RWLIST_INSERT_TAIL(&switches, sw, list);
06070    AST_RWLIST_UNLOCK(&switches);
06071 
06072    return 0;
06073 }

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

05052 {
05053    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN, found, combined_find_spawn);
05054 }

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

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

Referenced by ast_str_retrieve_variable().

05007 {
05008    struct ast_exten *e = ast_hint_extension(c, context, exten);
05009 
05010    if (!e) {
05011       return 0;
05012    }
05013 
05014    if (hint) {
05015       ast_str_set(hint, hintsize, "%s", ast_get_extension_app(e));
05016    }
05017    if (name) {
05018       const char *tmp = ast_get_extension_app_data(e);
05019       if (tmp) {
05020          ast_str_set(name, namesize, "%s", tmp);
05021       }
05022    }
05023    return -1;
05024 }

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

References ast_party_caller::ani2, ARRAY_LEN, ast_channel_lock, ast_channel_name(), ast_channel_uniqueid(), ast_channel_unlock, ast_config_AST_AGI_DIR, ast_config_AST_CONFIG_DIR, ast_config_AST_DATA_DIR, ast_config_AST_DB, ast_config_AST_KEY_DIR, ast_config_AST_LOG_DIR, ast_config_AST_MODULE_DIR, ast_config_AST_RUN_DIR, ast_config_AST_SPOOL_DIR, ast_config_AST_SYSTEM_NAME, ast_config_AST_VAR_DIR, 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_var_t::entries, ast_channel::exten, globals, globalslock, ast_channel::hangupcause, ast_party_caller::id, ast_party_id::number, parse_variable_name(), ast_party_number::plan, ast_channel::priority, ast_party_dialed::transit_network_select, and ast_channel::varshead.

Referenced by ast_str_substitute_variables_full(), and pbx_retrieve_variable().

03252 {
03253    const char not_found = '\0';
03254    char *tmpvar;
03255    const char *ret;
03256    const char *s; /* the result */
03257    int offset, length;
03258    int i, need_substring;
03259    struct varshead *places[2] = { headp, &globals };  /* list of places where we may look */
03260 
03261    if (c) {
03262       ast_channel_lock(c);
03263       places[0] = &c->varshead;
03264    }
03265    /*
03266     * Make a copy of var because parse_variable_name() modifies the string.
03267     * Then if called directly, we might need to run substring() on the result;
03268     * remember this for later in 'need_substring', 'offset' and 'length'
03269     */
03270    tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */
03271    need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */);
03272 
03273    /*
03274     * Look first into predefined variables, then into variable lists.
03275     * Variable 's' points to the result, according to the following rules:
03276     * s == &not_found (set at the beginning) means that we did not find a
03277     * matching variable and need to look into more places.
03278     * If s != &not_found, s is a valid result string as follows:
03279     * s = NULL if the variable does not have a value;
03280     * you typically do this when looking for an unset predefined variable.
03281     * s = workspace if the result has been assembled there;
03282     * typically done when the result is built e.g. with an snprintf(),
03283     * so we don't need to do an additional copy.
03284     * s != workspace in case we have a string, that needs to be copied
03285     * (the ast_copy_string is done once for all at the end).
03286     * Typically done when the result is already available in some string.
03287     */
03288    s = &not_found;   /* default value */
03289    if (c) { /* This group requires a valid channel */
03290       /* Names with common parts are looked up a piece at a time using strncmp. */
03291       if (!strncmp(var, "CALL", 4)) {
03292          if (!strncmp(var + 4, "ING", 3)) {
03293             if (!strcmp(var + 7, "PRES")) {        /* CALLINGPRES */
03294                ast_str_set(str, maxlen, "%d",
03295                   ast_party_id_presentation(&c->caller.id));
03296                s = ast_str_buffer(*str);
03297             } else if (!strcmp(var + 7, "ANI2")) {    /* CALLINGANI2 */
03298                ast_str_set(str, maxlen, "%d", c->caller.ani2);
03299                s = ast_str_buffer(*str);
03300             } else if (!strcmp(var + 7, "TON")) {     /* CALLINGTON */
03301                ast_str_set(str, maxlen, "%d", c->caller.id.number.plan);
03302                s = ast_str_buffer(*str);
03303             } else if (!strcmp(var + 7, "TNS")) {     /* CALLINGTNS */
03304                ast_str_set(str, maxlen, "%d", c->dialed.transit_network_select);
03305                s = ast_str_buffer(*str);
03306             }
03307          }
03308       } else if (!strcmp(var, "HINT")) {
03309          s = ast_str_get_hint(str, maxlen, NULL, 0, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL;
03310       } else if (!strcmp(var, "HINTNAME")) {
03311          s = ast_str_get_hint(NULL, 0, str, maxlen, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL;
03312       } else if (!strcmp(var, "EXTEN")) {
03313          s = c->exten;
03314       } else if (!strcmp(var, "CONTEXT")) {
03315          s = c->context;
03316       } else if (!strcmp(var, "PRIORITY")) {
03317          ast_str_set(str, maxlen, "%d", c->priority);
03318          s = ast_str_buffer(*str);
03319       } else if (!strcmp(var, "CHANNEL")) {
03320          s = ast_channel_name(c);
03321       } else if (!strcmp(var, "UNIQUEID")) {
03322          s = ast_channel_uniqueid(c);
03323       } else if (!strcmp(var, "HANGUPCAUSE")) {
03324          ast_str_set(str, maxlen, "%d", c->hangupcause);
03325          s = ast_str_buffer(*str);
03326       }
03327    }
03328    if (s == &not_found) { /* look for more */
03329       if (!strcmp(var, "EPOCH")) {
03330          ast_str_set(str, maxlen, "%u", (int) time(NULL));
03331          s = ast_str_buffer(*str);
03332       } else if (!strcmp(var, "SYSTEMNAME")) {
03333          s = ast_config_AST_SYSTEM_NAME;
03334       } else if (!strcmp(var, "ASTETCDIR")) {
03335          s = ast_config_AST_CONFIG_DIR;
03336       } else if (!strcmp(var, "ASTMODDIR")) {
03337          s = ast_config_AST_MODULE_DIR;
03338       } else if (!strcmp(var, "ASTVARLIBDIR")) {
03339          s = ast_config_AST_VAR_DIR;
03340       } else if (!strcmp(var, "ASTDBDIR")) {
03341          s = ast_config_AST_DB;
03342       } else if (!strcmp(var, "ASTKEYDIR")) {
03343          s = ast_config_AST_KEY_DIR;
03344       } else if (!strcmp(var, "ASTDATADIR")) {
03345          s = ast_config_AST_DATA_DIR;
03346       } else if (!strcmp(var, "ASTAGIDIR")) {
03347          s = ast_config_AST_AGI_DIR;
03348       } else if (!strcmp(var, "ASTSPOOLDIR")) {
03349          s = ast_config_AST_SPOOL_DIR;
03350       } else if (!strcmp(var, "ASTRUNDIR")) {
03351          s = ast_config_AST_RUN_DIR;
03352       } else if (!strcmp(var, "ASTLOGDIR")) {
03353          s = ast_config_AST_LOG_DIR;
03354       } else if (!strcmp(var, "ENTITYID")) {
03355          char workspace[20];
03356          ast_eid_to_str(workspace, sizeof(workspace), &ast_eid_default);
03357          s = workspace;
03358       }
03359    }
03360    /* if not found, look into chanvars or global vars */
03361    for (i = 0; s == &not_found && i < ARRAY_LEN(places); i++) {
03362       struct ast_var_t *variables;
03363       if (!places[i])
03364          continue;
03365       if (places[i] == &globals)
03366          ast_rwlock_rdlock(&globalslock);
03367       AST_LIST_TRAVERSE(places[i], variables, entries) {
03368          if (!strcasecmp(ast_var_name(variables), var)) {
03369             s = ast_var_value(variables);
03370             break;
03371          }
03372       }
03373       if (places[i] == &globals)
03374          ast_rwlock_unlock(&globalslock);
03375    }
03376    if (s == &not_found || s == NULL) {
03377       ast_debug(5, "Result of '%s' is NULL\n", var);
03378       ret = NULL;
03379    } else {
03380       ast_debug(5, "Result of '%s' is '%s'\n", var, s);
03381       if (s != ast_str_buffer(*str)) {
03382          ast_str_set(str, maxlen, "%s", s);
03383       }
03384       ret = ast_str_buffer(*str);
03385       if (need_substring) {
03386          ret = ast_str_substring(*str, offset, length);
03387          ast_debug(2, "Final result of '%s' is '%s'\n", var, ret);
03388       }
03389    }
03390 
03391    if (c) {
03392       ast_channel_unlock(c);
03393    }
03394    return ret;
03395 }

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

References ast_str_substitute_variables_full().

Referenced by _macro_exec(), acf_odbc_read(), acf_odbc_write(), cli_odbc_read(), cli_odbc_write(), config_curl(), custom_log(), cut_internal(), destroy_curl(), do_notify(), 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(), strreplace(), syslog_log(), tryexec_exec(), unshift_push(), update2_curl(), and update_curl().

04070 {
04071    size_t used;
04072    ast_str_substitute_variables_full(buf, maxlen, chan, NULL, templ, &used);
04073 }

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

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

03891 {
03892    /* Substitutes variables into buf, based on string templ */
03893    char *cp4 = NULL;
03894    const char *whereweare;
03895    int orig_size = 0;
03896    int offset, offset2, isfunction;
03897    const char *nextvar, *nextexp, *nextthing;
03898    const char *vars, *vare;
03899    char *finalvars;
03900    int pos, brackets, needsub, len;
03901    struct ast_str *substr1 = ast_str_create(16), *substr2 = NULL, *substr3 = ast_str_create(16);
03902 
03903    ast_str_reset(*buf);
03904    whereweare = templ;
03905    while (!ast_strlen_zero(whereweare)) {
03906       /* reset our buffer */
03907       ast_str_reset(substr3);
03908 
03909       /* Assume we're copying the whole remaining string */
03910       pos = strlen(whereweare);
03911       nextvar = NULL;
03912       nextexp = NULL;
03913       nextthing = strchr(whereweare, '$');
03914       if (nextthing) {
03915          switch (nextthing[1]) {
03916          case '{':
03917             nextvar = nextthing;
03918             pos = nextvar - whereweare;
03919             break;
03920          case '[':
03921             nextexp = nextthing;
03922             pos = nextexp - whereweare;
03923             break;
03924          default:
03925             pos = 1;
03926          }
03927       }
03928 
03929       if (pos) {
03930          /* Copy that many bytes */
03931          ast_str_append_substr(buf, maxlen, whereweare, pos);
03932 
03933          templ += pos;
03934          whereweare += pos;
03935       }
03936 
03937       if (nextvar) {
03938          /* We have a variable.  Find the start and end, and determine
03939             if we are going to have to recursively call ourselves on the
03940             contents */
03941          vars = vare = nextvar + 2;
03942          brackets = 1;
03943          needsub = 0;
03944 
03945          /* Find the end of it */
03946          while (brackets && *vare) {
03947             if ((vare[0] == '$') && (vare[1] == '{')) {
03948                needsub++;
03949             } else if (vare[0] == '{') {
03950                brackets++;
03951             } else if (vare[0] == '}') {
03952                brackets--;
03953             } else if ((vare[0] == '$') && (vare[1] == '['))
03954                needsub++;
03955             vare++;
03956          }
03957          if (brackets)
03958             ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n");
03959          len = vare - vars - 1;
03960 
03961          /* Skip totally over variable string */
03962          whereweare += (len + 3);
03963 
03964          /* Store variable name (and truncate) */
03965          ast_str_set_substr(&substr1, 0, vars, len);
03966          ast_debug(5, "Evaluating '%s' (from '%s' len %d)\n", ast_str_buffer(substr1), vars, len);
03967 
03968          /* Substitute if necessary */
03969          if (needsub) {
03970             size_t used;
03971             if (!substr2) {
03972                substr2 = ast_str_create(16);
03973             }
03974 
03975             ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used);
03976             finalvars = ast_str_buffer(substr2);
03977          } else {
03978             finalvars = ast_str_buffer(substr1);
03979          }
03980 
03981          parse_variable_name(finalvars, &offset, &offset2, &isfunction);
03982          if (isfunction) {
03983             /* Evaluate function */
03984             if (c || !headp) {
03985                cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3);
03986             } else {
03987                struct varshead old;
03988                struct ast_channel *bogus = ast_dummy_channel_alloc();
03989                if (bogus) {
03990                   memcpy(&old, &bogus->varshead, sizeof(old));
03991                   memcpy(&bogus->varshead, headp, sizeof(bogus->varshead));
03992                   cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3);
03993                   /* Don't deallocate the varshead that was passed in */
03994                   memcpy(&bogus->varshead, &old, sizeof(bogus->varshead));
03995                   ast_channel_unref(bogus);
03996                } else {
03997                   ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution.  Function results may be blank.\n");
03998                }
03999             }
04000             ast_debug(2, "Function result is '%s'\n", cp4 ? cp4 : "(null)");
04001          } else {
04002             /* Retrieve variable value */
04003             ast_str_retrieve_variable(&substr3, 0, c, headp, finalvars);
04004             cp4 = ast_str_buffer(substr3);
04005          }
04006          if (cp4) {
04007             ast_str_substring(substr3, offset, offset2);
04008             ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3));
04009          }
04010       } else if (nextexp) {
04011          /* We have an expression.  Find the start and end, and determine
04012             if we are going to have to recursively call ourselves on the
04013             contents */
04014          vars = vare = nextexp + 2;
04015          brackets = 1;
04016          needsub = 0;
04017 
04018          /* Find the end of it */
04019          while (brackets && *vare) {
04020             if ((vare[0] == '$') && (vare[1] == '[')) {
04021                needsub++;
04022                brackets++;
04023                vare++;
04024             } else if (vare[0] == '[') {
04025                brackets++;
04026             } else if (vare[0] == ']') {
04027                brackets--;
04028             } else if ((vare[0] == '$') && (vare[1] == '{')) {
04029                needsub++;
04030                vare++;
04031             }
04032             vare++;
04033          }
04034          if (brackets)
04035             ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n");
04036          len = vare - vars - 1;
04037 
04038          /* Skip totally over expression */
04039          whereweare += (len + 3);
04040 
04041          /* Store variable name (and truncate) */
04042          ast_str_set_substr(&substr1, 0, vars, len);
04043 
04044          /* Substitute if necessary */
04045          if (needsub) {
04046             size_t used;
04047             if (!substr2) {
04048                substr2 = ast_str_create(16);
04049             }
04050 
04051             ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used);
04052             finalvars = ast_str_buffer(substr2);
04053          } else {
04054             finalvars = ast_str_buffer(substr1);
04055          }
04056 
04057          if (ast_str_expr(&substr3, 0, c, finalvars)) {
04058             ast_debug(2, "Expression result is '%s'\n", ast_str_buffer(substr3));
04059          }
04060          ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3));
04061       }
04062    }
04063    *used = ast_str_strlen(*buf) - orig_size;
04064    ast_free(substr1);
04065    ast_free(substr2);
04066    ast_free(substr3);
04067 }

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

04076 {
04077    size_t used;
04078    ast_str_substitute_variables_full(buf, maxlen, NULL, headp, templ, &used);
04079 }

int ast_unlock_context ( struct ast_context con  ) 

int ast_unlock_contexts ( void   ) 

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

References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

Referenced by __unload_module(), and unload_module().

06076 {
06077    AST_RWLIST_WRLOCK(&switches);
06078    AST_RWLIST_REMOVE(&switches, sw, list);
06079    AST_RWLIST_UNLOCK(&switches);
06080 }

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

Definition at line 10621 of file pbx.c.

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

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

10623 {
10624    if (!exten)
10625       return con ? con->root : NULL;
10626    else
10627       return exten->next;
10628 }

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

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

10656 {
10657    if (!ip)
10658       return con ? con->ignorepats : NULL;
10659    else
10660       return ip->next;
10661 }

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

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

Definition at line 10630 of file pbx.c.

References ast_context::alts, AST_LIST_FIRST, and AST_LIST_NEXT.

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

10632 {
10633    if (!sw)
10634       return con ? AST_LIST_FIRST(&con->alts) : NULL;
10635    else
10636       return AST_LIST_NEXT(sw, list);
10637 }

struct ast_context* ast_walk_contexts ( struct ast_context con  )  [read]

struct ast_exten* ast_walk_extension_priorities ( struct ast_exten exten,
struct ast_exten priority 
) [read]

Definition at line 10639 of file pbx.c.

References ast_exten::peer.

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

10641 {
10642    return priority ? priority->peer : exten;
10643 }

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

10498 {
10499    return ast_rwlock_wrlock(&con->lock);
10500 }

int ast_wrlock_contexts ( void   ) 

Write locks the context list.

Return values:
0 on success
-1 on error

Definition at line 10479 of file pbx.c.

References ast_mutex_lock, and conlock.

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

10480 {
10481    return ast_mutex_lock(&conlock);
10482 }

void pbx_builtin_clear_globals ( void   ) 

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

10274 {
10275    struct ast_var_t *vardata;
10276 
10277    ast_rwlock_wrlock(&globalslock);
10278    while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries)))
10279       ast_var_delete(vardata);
10280    ast_rwlock_unlock(&globalslock);
10281 }

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

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

Referenced by __ast_pbx_run(), _macro_exec(), _while_exec(), 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(), create_dynamic_parkinglot(), crement_function_read(), dahdi_hangup(), dial_exec_full(), do_forward(), dundi_exec(), dundi_helper(), feature_check(), feature_interpret(), find_by_mark(), find_conf_realtime(), 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(), manager_mixmonitor(), 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(), setsubstate(), sip_addheader(), sla_trunk_exec(), speech_background(), try_calling(), try_suggested_sip_codec(), update_bridge_vars(), and wait_for_answer().

10036 {
10037    struct ast_var_t *variables;
10038    const char *ret = NULL;
10039    int i;
10040    struct varshead *places[2] = { NULL, &globals };
10041 
10042    if (!name)
10043       return NULL;
10044 
10045    if (chan) {
10046       ast_channel_lock(chan);
10047       places[0] = &chan->varshead;
10048    }
10049 
10050    for (i = 0; i < 2; i++) {
10051       if (!places[i])
10052          continue;
10053       if (places[i] == &globals)
10054          ast_rwlock_rdlock(&globalslock);
10055       AST_LIST_TRAVERSE(places[i], variables, entries) {
10056          if (!strcmp(name, ast_var_name(variables))) {
10057             ret = ast_var_value(variables);
10058             break;
10059          }
10060       }
10061       if (places[i] == &globals)
10062          ast_rwlock_unlock(&globalslock);
10063       if (ret)
10064          break;
10065    }
10066 
10067    if (chan)
10068       ast_channel_unlock(chan);
10069 
10070    return ret;
10071 }

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 10073 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, LOG_WARNING, and ast_channel::varshead.

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

10074 {
10075    struct ast_var_t *newvariable;
10076    struct varshead *headp;
10077 
10078    if (name[strlen(name)-1] == ')') {
10079       char *function = ast_strdupa(name);
10080 
10081       ast_log(LOG_WARNING, "Cannot push a value onto a function\n");
10082       ast_func_write(chan, function, value);
10083       return;
10084    }
10085 
10086    if (chan) {
10087       ast_channel_lock(chan);
10088       headp = &chan->varshead;
10089    } else {
10090       ast_rwlock_wrlock(&globalslock);
10091       headp = &globals;
10092    }
10093 
10094    if (value) {
10095       if (headp == &globals)
10096          ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value);
10097       newvariable = ast_var_assign(name, value);
10098       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
10099    }
10100 
10101    if (chan)
10102       ast_channel_unlock(chan);
10103    else
10104       ast_rwlock_unlock(&globalslock);
10105 }

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

Definition at line 3446 of file pbx.c.

References raise_exception().

03447 {
03448    /* Priority will become 1, next time through the AUTOLOOP */
03449    return raise_exception(chan, reason, 0);
03450 }

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

10005 {
10006    struct ast_var_t *variables;
10007    const char *var, *val;
10008    int total = 0;
10009 
10010    if (!chan)
10011       return 0;
10012 
10013    ast_str_reset(*buf);
10014 
10015    ast_channel_lock(chan);
10016 
10017    AST_LIST_TRAVERSE(&chan->varshead, variables, entries) {
10018       if ((var = ast_var_name(variables)) && (val = ast_var_value(variables))
10019          /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */
10020          ) {
10021          if (ast_str_append(buf, 0, "%s=%s\n", var, val) < 0) {
10022             ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
10023             break;
10024          } else
10025             total++;
10026       } else
10027          break;
10028    }
10029 
10030    ast_channel_unlock(chan);
10031 
10032    return total;
10033 }

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

10166 {
10167    char *name, *value, *mydata;
10168 
10169    if (ast_compat_app_set) {
10170       return pbx_builtin_setvar_multiple(chan, data);
10171    }
10172 
10173    if (ast_strlen_zero(data)) {
10174       ast_log(LOG_WARNING, "Set requires one variable name/value pair.\n");
10175       return 0;
10176    }
10177 
10178    mydata = ast_strdupa(data);
10179    name = strsep(&mydata, "=");
10180    value = mydata;
10181    if (!value) {
10182       ast_log(LOG_WARNING, "Set requires an '=' to be a valid assignment.\n");
10183       return 0;
10184    }
10185 
10186    if (strchr(name, ' ')) {
10187       ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, mydata);
10188    }
10189 
10190    pbx_builtin_setvar_helper(chan, name, value);
10191 
10192    return 0;
10193 }

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

References ast_channel_lock, ast_channel_name(), ast_channel_uniqueid(), 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, and ast_channel::varshead.

Referenced by __analog_ss_thread(), __ast_pbx_run(), __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_eivr_setvariable(), ast_iax2_new(), ast_monitor_start(), ast_monitor_stop(), ast_pbx_outgoing_exten(), ast_pickup_call(), 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(), calendar_write_exec(), cb_events(), cccancel_exec(), 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(), disa_exec(), do_notify(), do_waiting(), end_bridge_callback(), export_aoc_vars(), export_ch(), fax_detect_framehook(), 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(), launch_monitor_thread(), leave_queue(), leave_voicemail(), local_hangup(), lua_set_variable(), lua_set_variable_value(), macro_fixup(), manage_parked_call(), mgcp_new(), minivm_accmess_exec(), minivm_delete_exec(), minivm_greet_exec(), minivm_notify_exec(), minivm_record_exec(), misdn_call(), mixmonitor_exec(), msg_send_exec(), my_handle_dtmf(), originate_exec(), ospauth_exec(), ospfinished_exec(), osplookup_exec(), ospnext_exec(), parked_call_exec(), 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(), privacy_exec(), process_ast_dsp(), process_sdp(), read_exec(), readexten_exec(), readfile_exec(), realtimefield_read(), 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(), setsubstate(), shift_pop(), 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().

10108 {
10109    struct ast_var_t *newvariable;
10110    struct varshead *headp;
10111    const char *nametail = name;
10112 
10113    if (name[strlen(name) - 1] == ')') {
10114       char *function = ast_strdupa(name);
10115 
10116       return ast_func_write(chan, function, value);
10117    }
10118 
10119    if (chan) {
10120       ast_channel_lock(chan);
10121       headp = &chan->varshead;
10122    } else {
10123       ast_rwlock_wrlock(&globalslock);
10124       headp = &globals;
10125    }
10126 
10127    /* For comparison purposes, we have to strip leading underscores */
10128    if (*nametail == '_') {
10129       nametail++;
10130       if (*nametail == '_')
10131          nametail++;
10132    }
10133 
10134    AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) {
10135       if (strcmp(ast_var_name(newvariable), nametail) == 0) {
10136          /* there is already such a variable, delete it */
10137          AST_LIST_REMOVE_CURRENT(entries);
10138          ast_var_delete(newvariable);
10139          break;
10140       }
10141    }
10142    AST_LIST_TRAVERSE_SAFE_END;
10143 
10144    if (value) {
10145       if (headp == &globals)
10146          ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value);
10147       newvariable = ast_var_assign(name, value);
10148       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
10149       manager_event(EVENT_FLAG_DIALPLAN, "VarSet",
10150          "Channel: %s\r\n"
10151          "Variable: %s\r\n"
10152          "Value: %s\r\n"
10153          "Uniqueid: %s\r\n",
10154          chan ? ast_channel_name(chan) : "none", name, value,
10155          chan ? ast_channel_uniqueid(chan) : "none");
10156    }
10157 
10158    if (chan)
10159       ast_channel_unlock(chan);
10160    else
10161       ast_rwlock_unlock(&globalslock);
10162    return 0;
10163 }

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 10195 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, pbx_builtin_setvar_helper(), ast_channel::priority, and value.

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

10196 {
10197    char *data;
10198    int x;
10199    AST_DECLARE_APP_ARGS(args,
10200       AST_APP_ARG(pair)[24];
10201    );
10202    AST_DECLARE_APP_ARGS(pair,
10203       AST_APP_ARG(name);
10204       AST_APP_ARG(value);
10205    );
10206 
10207    if (ast_strlen_zero(vdata)) {
10208       ast_log(LOG_WARNING, "MSet requires at least one variable name/value pair.\n");
10209       return 0;
10210    }
10211 
10212    data = ast_strdupa(vdata);
10213    AST_STANDARD_APP_ARGS(args, data);
10214 
10215    for (x = 0; x < args.argc; x++) {
10216       AST_NONSTANDARD_APP_ARGS(pair, args.pair[x], '=');
10217       if (pair.argc == 2) {
10218          pbx_builtin_setvar_helper(chan, pair.name, pair.value);
10219          if (strchr(pair.name, ' '))
10220             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);
10221       } else if (!chan) {
10222          ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '='\n", pair.name);
10223       } else {
10224          ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '=' (in %s@%s:%d\n", pair.name, chan->exten, chan->context, chan->priority);
10225       }
10226    }
10227 
10228    return 0;
10229 }

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

10284 {
10285    int res;
10286    if (ast_strlen_zero(condition)) {                /* NULL or empty strings are false */
10287       return 0;
10288    } else if (sscanf(condition, "%30d", &res) == 1) { /* Numbers are evaluated for truth */
10289       return res;
10290    } else {                                         /* Strings are true */
10291       return 1;
10292    }
10293 }

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

References __ast_module_user_add(), __ast_module_user_remove(), 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, ast_app::execute, LOG_WARNING, ast_app::module, ast_app::name, and S_OR.

Referenced by aelsub_exec(), 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(), realtime_exec(), record_thread(), try_calling(), and tryexec_exec().

01526 {
01527    int res;
01528    struct ast_module_user *u = NULL;
01529    const char *saved_c_appl;
01530    const char *saved_c_data;
01531 
01532    if (c->cdr && !ast_check_hangup(c))
01533       ast_cdr_setapp(c->cdr, app->name, data);
01534 
01535    /* save channel values */
01536    saved_c_appl= c->appl;
01537    saved_c_data= c->data;
01538 
01539    c->appl = app->name;
01540    c->data = data;
01541    ast_cel_report_event(c, AST_CEL_APP_START, NULL, NULL, NULL);
01542 
01543    if (app->module)
01544       u = __ast_module_user_add(app->module, c);
01545    if (strcasecmp(app->name, "system") && !ast_strlen_zero(data) &&
01546          strchr(data, '|') && !strchr(data, ',') && !ast_opt_dont_warn) {
01547       ast_log(LOG_WARNING, "The application delimiter is now the comma, not "
01548          "the pipe.  Did you forget to convert your dialplan?  (%s(%s))\n",
01549          app->name, (char *) data);
01550    }
01551    res = app->execute(c, S_OR(data, ""));
01552    if (app->module && u)
01553       __ast_module_user_remove(app->module, u);
01554    ast_cel_report_event(c, AST_CEL_APP_END, NULL, NULL, NULL);
01555    /* restore channel values */
01556    c->appl = saved_c_appl;
01557    c->data = saved_c_data;
01558    return res;
01559 }

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

Definition at line 2819 of file pbx.c.

References ast_context::alts, ast_autoservice_start(), ast_autoservice_stop(), ast_debug, 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, 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(), find_context(), pbx_find_info::foundcontext, include_valid(), ast_context::includes, pbx_find_info::incstack, ast_exten::label, scoreboard::last_char, LOG_NOTICE, LOG_WARNING, match(), matchcid(), ast_switch::matchmore, ast_context::name, ast_sw::name, new_find_extension(), ast_include::next, scoreboard::node, overrideswitch, ast_context::pattern_tree, pbx_find_extension(), pbx_findswitch(), pbx_substitute_variables_helper(), ast_exten::priority, ast_include::rname, ast_context::root_table, pbx_find_info::stacklen, pbx_find_info::status, STATUS_NO_CONTEXT, STATUS_NO_EXTENSION, STATUS_NO_LABEL, STATUS_NO_PRIORITY, STATUS_SUCCESS, 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(), check_goto(), check_pval_item(), get_parking_exten(), pbx_extension_helper(), pbx_find_extension(), register_peer_exten(), and remove_exten_if_exist().

02823 {
02824    int x, res;
02825    struct ast_context *tmp = NULL;
02826    struct ast_exten *e = NULL, *eroot = NULL;
02827    struct ast_include *i = NULL;
02828    struct ast_sw *sw = NULL;
02829    struct ast_exten pattern = {NULL, };
02830    struct scoreboard score = {0, };
02831    struct ast_str *tmpdata = NULL;
02832 
02833    pattern.label = label;
02834    pattern.priority = priority;
02835 #ifdef NEED_DEBUG_HERE
02836    ast_log(LOG_NOTICE, "Looking for cont/ext/prio/label/action = %s/%s/%d/%s/%d\n", context, exten, priority, label, (int) action);
02837 #endif
02838 
02839    /* Initialize status if appropriate */
02840    if (q->stacklen == 0) {
02841       q->status = STATUS_NO_CONTEXT;
02842       q->swo = NULL;
02843       q->data = NULL;
02844       q->foundcontext = NULL;
02845    } else if (q->stacklen >= AST_PBX_MAX_STACK) {
02846       ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n");
02847       return NULL;
02848    }
02849 
02850    /* Check first to see if we've already been checked */
02851    for (x = 0; x < q->stacklen; x++) {
02852       if (!strcasecmp(q->incstack[x], context))
02853          return NULL;
02854    }
02855 
02856    if (bypass) { /* bypass means we only look there */
02857       tmp = bypass;
02858    } else {      /* look in contexts */
02859       tmp = find_context(context);
02860       if (!tmp) {
02861          return NULL;
02862       }
02863    }
02864 
02865    if (q->status < STATUS_NO_EXTENSION)
02866       q->status = STATUS_NO_EXTENSION;
02867 
02868    /* Do a search for matching extension */
02869 
02870    eroot = NULL;
02871    score.total_specificity = 0;
02872    score.exten = 0;
02873    score.total_length = 0;
02874    if (!tmp->pattern_tree && tmp->root_table) {
02875       create_match_char_tree(tmp);
02876 #ifdef NEED_DEBUG
02877       ast_debug(1, "Tree Created in context %s:\n", context);
02878       log_match_char_tree(tmp->pattern_tree," ");
02879 #endif
02880    }
02881 #ifdef NEED_DEBUG
02882    ast_log(LOG_NOTICE, "The Trie we are searching in:\n");
02883    log_match_char_tree(tmp->pattern_tree, "::  ");
02884 #endif
02885 
02886    do {
02887       if (!ast_strlen_zero(overrideswitch)) {
02888          char *osw = ast_strdupa(overrideswitch), *name;
02889          struct ast_switch *asw;
02890          ast_switch_f *aswf = NULL;
02891          char *datap;
02892          int eval = 0;
02893 
02894          name = strsep(&osw, "/");
02895          asw = pbx_findswitch(name);
02896 
02897          if (!asw) {
02898             ast_log(LOG_WARNING, "No such switch '%s'\n", name);
02899             break;
02900          }
02901 
02902          if (osw && strchr(osw, '$')) {
02903             eval = 1;
02904          }
02905 
02906          if (eval && !(tmpdata = ast_str_thread_get(&switch_data, 512))) {
02907             ast_log(LOG_WARNING, "Can't evaluate overrideswitch?!");
02908             break;
02909          } else if (eval) {
02910             /* Substitute variables now */
02911             pbx_substitute_variables_helper(chan, osw, ast_str_buffer(tmpdata), ast_str_size(tmpdata));
02912             datap = ast_str_buffer(tmpdata);
02913          } else {
02914             datap = osw;
02915          }
02916 
02917          /* equivalent of extension_match_core() at the switch level */
02918          if (action == E_CANMATCH)
02919             aswf = asw->canmatch;
02920          else if (action == E_MATCHMORE)
02921             aswf = asw->matchmore;
02922          else /* action == E_MATCH */
02923             aswf = asw->exists;
02924          if (!aswf) {
02925             res = 0;
02926          } else {
02927             if (chan) {
02928                ast_autoservice_start(chan);
02929             }
02930             res = aswf(chan, context, exten, priority, callerid, datap);
02931             if (chan) {
02932                ast_autoservice_stop(chan);
02933             }
02934          }
02935          if (res) {  /* Got a match */
02936             q->swo = asw;
02937             q->data = datap;
02938             q->foundcontext = context;
02939             /* XXX keep status = STATUS_NO_CONTEXT ? */
02940             return NULL;
02941          }
02942       }
02943    } while (0);
02944 
02945    if (extenpatternmatchnew) {
02946       new_find_extension(exten, &score, tmp->pattern_tree, 0, 0, callerid, label, action);
02947       eroot = score.exten;
02948 
02949       if (score.last_char == '!' && action == E_MATCHMORE) {
02950          /* We match an extension ending in '!'.
02951           * The decision in this case is final and is NULL (no match).
02952           */
02953 #ifdef NEED_DEBUG_HERE
02954          ast_log(LOG_NOTICE,"Returning MATCHMORE NULL with exclamation point.\n");
02955 #endif
02956          return NULL;
02957       }
02958 
02959       if (!eroot && (action == E_CANMATCH || action == E_MATCHMORE) && score.canmatch_exten) {
02960          q->status = STATUS_SUCCESS;
02961 #ifdef NEED_DEBUG_HERE
02962          ast_log(LOG_NOTICE,"Returning CANMATCH exten %s\n", score.canmatch_exten->exten);
02963 #endif
02964          return score.canmatch_exten;
02965       }
02966 
02967       if ((action == E_MATCHMORE || action == E_CANMATCH)  && eroot) {
02968          if (score.node) {
02969             struct ast_exten *z = trie_find_next_match(score.node);
02970             if (z) {
02971 #ifdef NEED_DEBUG_HERE
02972                ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten %s\n", z->exten);
02973 #endif
02974             } else {
02975                if (score.canmatch_exten) {
02976 #ifdef NEED_DEBUG_HERE
02977                   ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE canmatchmatch exten %s(%p)\n", score.canmatch_exten->exten, score.canmatch_exten);
02978 #endif
02979                   return score.canmatch_exten;
02980                } else {
02981 #ifdef NEED_DEBUG_HERE
02982                   ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten NULL\n");
02983 #endif
02984                }
02985             }
02986             return z;
02987          }
02988 #ifdef NEED_DEBUG_HERE
02989          ast_log(LOG_NOTICE, "Returning CANMATCH/MATCHMORE NULL (no next_match)\n");
02990 #endif
02991          return NULL;  /* according to the code, complete matches are null matches in MATCHMORE mode */
02992       }
02993 
02994       if (eroot) {
02995          /* found entry, now look for the right priority */
02996          if (q->status < STATUS_NO_PRIORITY)
02997             q->status = STATUS_NO_PRIORITY;
02998          e = NULL;
02999          if (action == E_FINDLABEL && label ) {
03000             if (q->status < STATUS_NO_LABEL)
03001                q->status = STATUS_NO_LABEL;
03002             e = ast_hashtab_lookup(eroot->peer_label_table, &pattern);
03003          } else {
03004             e = ast_hashtab_lookup(eroot->peer_table, &pattern);
03005          }
03006          if (e) { /* found a valid match */
03007             q->status = STATUS_SUCCESS;
03008             q->foundcontext = context;
03009 #ifdef NEED_DEBUG_HERE
03010             ast_log(LOG_NOTICE,"Returning complete match of exten %s\n", e->exten);
03011 #endif
03012             return e;
03013          }
03014       }
03015    } else {   /* the old/current default exten pattern match algorithm */
03016 
03017       /* scan the list trying to match extension and CID */
03018       eroot = NULL;
03019       while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) {
03020          int match = extension_match_core(eroot->exten, exten, action);
03021          /* 0 on fail, 1 on match, 2 on earlymatch */
03022 
03023          if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid)))
03024             continue;   /* keep trying */
03025          if (match == 2 && action == E_MATCHMORE) {
03026             /* We match an extension ending in '!'.
03027              * The decision in this case is final and is NULL (no match).
03028              */
03029             return NULL;
03030          }
03031          /* found entry, now look for the right priority */
03032          if (q->status < STATUS_NO_PRIORITY)
03033             q->status = STATUS_NO_PRIORITY;
03034          e = NULL;
03035          if (action == E_FINDLABEL && label ) {
03036             if (q->status < STATUS_NO_LABEL)
03037                q->status = STATUS_NO_LABEL;
03038             e = ast_hashtab_lookup(eroot->peer_label_table, &pattern);
03039          } else {
03040             e = ast_hashtab_lookup(eroot->peer_table, &pattern);
03041          }
03042          if (e) { /* found a valid match */
03043             q->status = STATUS_SUCCESS;
03044             q->foundcontext = context;
03045             return e;
03046          }
03047       }
03048    }
03049 
03050    /* Check alternative switches */
03051    AST_LIST_TRAVERSE(&tmp->alts, sw, list) {
03052       struct ast_switch *asw = pbx_findswitch(sw->name);
03053       ast_switch_f *aswf = NULL;
03054       char *datap;
03055 
03056       if (!asw) {
03057          ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name);
03058          continue;
03059       }
03060 
03061       /* Substitute variables now */
03062       if (sw->eval) {
03063          if (!(tmpdata = ast_str_thread_get(&switch_data, 512))) {
03064             ast_log(LOG_WARNING, "Can't evaluate switch?!");
03065             continue;
03066          }
03067          pbx_substitute_variables_helper(chan, sw->data, ast_str_buffer(tmpdata), ast_str_size(tmpdata));
03068       }
03069 
03070       /* equivalent of extension_match_core() at the switch level */
03071       if (action == E_CANMATCH)
03072          aswf = asw->canmatch;
03073       else if (action == E_MATCHMORE)
03074          aswf = asw->matchmore;
03075       else /* action == E_MATCH */
03076          aswf = asw->exists;
03077       datap = sw->eval ? ast_str_buffer(tmpdata) : sw->data;
03078       if (!aswf)
03079          res = 0;
03080       else {
03081          if (chan)
03082             ast_autoservice_start(chan);
03083          res = aswf(chan, context, exten, priority, callerid, datap);
03084          if (chan)
03085             ast_autoservice_stop(chan);
03086       }
03087       if (res) {  /* Got a match */
03088          q->swo = asw;
03089          q->data = datap;
03090          q->foundcontext = context;
03091          /* XXX keep status = STATUS_NO_CONTEXT ? */
03092          return NULL;
03093       }
03094    }
03095    q->incstack[q->stacklen++] = tmp->name;   /* Setup the stack */
03096    /* Now try any includes we have in this context */
03097    for (i = tmp->includes; i; i = i->next) {
03098       if (include_valid(i)) {
03099          if ((e = pbx_find_extension(chan, bypass, q, i->rname, exten, priority, label, callerid, action))) {
03100 #ifdef NEED_DEBUG_HERE
03101             ast_log(LOG_NOTICE,"Returning recursive match of %s\n", e->exten);
03102 #endif
03103             return e;
03104          }
03105          if (q->swo)
03106             return NULL;
03107       }
03108    }
03109    return NULL;
03110 }

struct ast_app* pbx_findapp ( const char *  app  )  [read]

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

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

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

01568 {
01569    struct ast_app *tmp;
01570 
01571    AST_RWLIST_RDLOCK(&apps);
01572    AST_RWLIST_TRAVERSE(&apps, tmp, list) {
01573       if (!strcasecmp(tmp->name, app))
01574          break;
01575    }
01576    AST_RWLIST_UNLOCK(&apps);
01577 
01578    return tmp;
01579 }

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:
Will lock the channel.
Retrieve the value of a builtin variable or variable from the channel variable stack.

Note:
See also

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

03241 {
03242    struct ast_str *str = ast_str_create(16);
03243    const char *cret;
03244 
03245    cret = ast_str_retrieve_variable(&str, 0, c, headp, var);
03246    ast_copy_string(workspace, ast_str_buffer(str), workspacelen);
03247    *ret = cret ? workspace : NULL;
03248    ast_free(str);
03249 }

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

References autofallthrough.

Referenced by pbx_load_module().

05557 {
05558    int oldval = autofallthrough;
05559    autofallthrough = newval;
05560    return oldval;
05561 }

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

References extenpatternmatchnew.

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

05564 {
05565    int oldval = extenpatternmatchnew;
05566    extenpatternmatchnew = newval;
05567    return oldval;
05568 }

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

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

Referenced by pbx_load_module().

05571 {
05572    if (overrideswitch) {
05573       ast_free(overrideswitch);
05574    }
05575    if (!ast_strlen_zero(newval)) {
05576       overrideswitch = ast_strdup(newval);
05577    } else {
05578       overrideswitch = NULL;
05579    }
05580 }

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  cp2_size,
size_t *  used 
)

Definition at line 4081 of file pbx.c.

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

04082 {
04083    /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!!  */
04084    char *cp4 = NULL;
04085    const char *whereweare, *orig_cp2 = cp2;
04086    int length, offset, offset2, isfunction;
04087    char *workspace = NULL;
04088    char *ltmp = NULL, *var = NULL;
04089    char *nextvar, *nextexp, *nextthing;
04090    char *vars, *vare;
04091    int pos, brackets, needsub, len;
04092 
04093    *cp2 = 0; /* just in case nothing ends up there */
04094    whereweare = cp1;
04095    while (!ast_strlen_zero(whereweare) && count) {
04096       /* Assume we're copying the whole remaining string */
04097       pos = strlen(whereweare);
04098       nextvar = NULL;
04099       nextexp = NULL;
04100       nextthing = strchr(whereweare, '$');
04101       if (nextthing) {
04102          switch (nextthing[1]) {
04103          case '{':
04104             nextvar = nextthing;
04105             pos = nextvar - whereweare;
04106             break;
04107          case '[':
04108             nextexp = nextthing;
04109             pos = nextexp - whereweare;
04110             break;
04111          default:
04112             pos = 1;
04113          }
04114       }
04115 
04116       if (pos) {
04117          /* Can't copy more than 'count' bytes */
04118          if (pos > count)
04119             pos = count;
04120 
04121          /* Copy that many bytes */
04122          memcpy(cp2, whereweare, pos);
04123 
04124          count -= pos;
04125          cp2 += pos;
04126          whereweare += pos;
04127          *cp2 = 0;
04128       }
04129 
04130       if (nextvar) {
04131          /* We have a variable.  Find the start and end, and determine
04132             if we are going to have to recursively call ourselves on the
04133             contents */
04134          vars = vare = nextvar + 2;
04135          brackets = 1;
04136          needsub = 0;
04137 
04138          /* Find the end of it */
04139          while (brackets && *vare) {
04140             if ((vare[0] == '$') && (vare[1] == '{')) {
04141                needsub++;
04142             } else if (vare[0] == '{') {
04143                brackets++;
04144             } else if (vare[0] == '}') {
04145                brackets--;
04146             } else if ((vare[0] == '$') && (vare[1] == '['))
04147                needsub++;
04148             vare++;
04149          }
04150          if (brackets)
04151             ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n");
04152          len = vare - vars - 1;
04153 
04154          /* Skip totally over variable string */
04155          whereweare += (len + 3);
04156 
04157          if (!var)
04158             var = alloca(VAR_BUF_SIZE);
04159 
04160          /* Store variable name (and truncate) */
04161          ast_copy_string(var, vars, len + 1);
04162 
04163          /* Substitute if necessary */
04164          if (needsub) {
04165             size_t used;
04166             if (!ltmp)
04167                ltmp = alloca(VAR_BUF_SIZE);
04168 
04169             pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used);
04170             vars = ltmp;
04171          } else {
04172             vars = var;
04173          }
04174 
04175          if (!workspace)
04176             workspace = alloca(VAR_BUF_SIZE);
04177 
04178          workspace[0] = '\0';
04179 
04180          parse_variable_name(vars, &offset, &offset2, &isfunction);
04181          if (isfunction) {
04182             /* Evaluate function */
04183             if (c || !headp)
04184                cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
04185             else {
04186                struct varshead old;
04187                struct ast_channel *c = ast_dummy_channel_alloc();
04188                if (c) {
04189                   memcpy(&old, &c->varshead, sizeof(old));
04190                   memcpy(&c->varshead, headp, sizeof(c->varshead));
04191                   cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
04192                   /* Don't deallocate the varshead that was passed in */
04193                   memcpy(&c->varshead, &old, sizeof(c->varshead));
04194                   c = ast_channel_unref(c);
04195                } else {
04196                   ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution.  Function results may be blank.\n");
04197                }
04198             }
04199             ast_debug(2, "Function result is '%s'\n", cp4 ? cp4 : "(null)");
04200          } else {
04201             /* Retrieve variable value */
04202             pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp);
04203          }
04204          if (cp4) {
04205             cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE);
04206 
04207             length = strlen(cp4);
04208             if (length > count)
04209                length = count;
04210             memcpy(cp2, cp4, length);
04211             count -= length;
04212             cp2 += length;
04213             *cp2 = 0;
04214          }
04215       } else if (nextexp) {
04216          /* We have an expression.  Find the start and end, and determine
04217             if we are going to have to recursively call ourselves on the
04218             contents */
04219          vars = vare = nextexp + 2;
04220          brackets = 1;
04221          needsub = 0;
04222 
04223          /* Find the end of it */
04224          while (brackets && *vare) {
04225             if ((vare[0] == '$') && (vare[1] == '[')) {
04226                needsub++;
04227                brackets++;
04228                vare++;
04229             } else if (vare[0] == '[') {
04230                brackets++;
04231             } else if (vare[0] == ']') {
04232                brackets--;
04233             } else if ((vare[0] == '$') && (vare[1] == '{')) {
04234                needsub++;
04235                vare++;
04236             }
04237             vare++;
04238          }
04239          if (brackets)
04240             ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n");
04241          len = vare - vars - 1;
04242 
04243          /* Skip totally over expression */
04244          whereweare += (len + 3);
04245 
04246          if (!var)
04247             var = alloca(VAR_BUF_SIZE);
04248 
04249          /* Store variable name (and truncate) */
04250          ast_copy_string(var, vars, len + 1);
04251 
04252          /* Substitute if necessary */
04253          if (needsub) {
04254             size_t used;
04255             if (!ltmp)
04256                ltmp = alloca(VAR_BUF_SIZE);
04257 
04258             pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used);
04259             vars = ltmp;
04260          } else {
04261             vars = var;
04262          }
04263 
04264          length = ast_expr(vars, cp2, count, c);
04265 
04266          if (length) {
04267             ast_debug(1, "Expression result is '%s'\n", cp2);
04268             count -= length;
04269             cp2 += length;
04270             *cp2 = 0;
04271          }
04272       }
04273    }
04274    *used = cp2 - orig_cp2;
04275 }

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

Definition at line 4283 of file pbx.c.

References pbx_substitute_variables_helper_full().

Referenced by do_say(), dundi_lookup_local(), get_mapping_weight(), and loopback_subst().

04284 {
04285    size_t used;
04286    pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count, &used);
04287 }


Generated on Fri Feb 10 06:36:56 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6