Wed Jan 27 20:02:44 2016

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/frame_defs.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_custom_function_register_escalating(acf, escalation)   __ast_custom_function_register_escalating(acf, escalation, ast_module_info->self)
 Register a custom function which requires escalated privileges.
#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

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 )(char *context, char *id, 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_custom_function_escalation { AST_CFE_NONE, AST_CFE_READ, AST_CFE_WRITE, AST_CFE_BOTH }
 

Description of the ways in which a function may escalate privileges.

More...
enum  ast_ext_matchcid_types { AST_EXT_MATCHCID_OFF = 0, AST_EXT_MATCHCID_ON = 1, AST_EXT_MATCHCID_ANY = 2 }
 

extension matchcid types

More...
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_custom_function_register_escalating (struct ast_custom_function *acf, enum ast_custom_function_escalation escalation, struct ast_module *mod)
 Register a custom function which requires escalated privileges.
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, format_t format, void *data, int timeout, const char *app, const char *appdata, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel)
int ast_pbx_outgoing_exten (const char *type, format_t format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel)
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_thread_inhibit_escalations (void)
 Inhibit (in the current thread) the execution of dialplan functions which cause privilege escalations. If pbx_live_dangerously() has been called, this function has no effect.
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_live_dangerously (int new_live_dangerously)
 Enable/disable the execution of 'dangerous' functions from external protocols (AMI, etc.).
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)
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)
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)



#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
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)
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)
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)

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 1164 of file pbx.h.

Referenced by load_module(), and reload().

#define ast_custom_function_register_escalating ( acf,
escalation   )     __ast_custom_function_register_escalating(acf, escalation, ast_module_info->self)

Register a custom function which requires escalated privileges.

Examples would be SHELL() (for which a read needs permission to execute arbitrary code) or FILE() (for which write needs permission to change files on the filesystem).

Definition at line 1173 of file pbx.h.

Referenced by load_module().

#define AST_MAX_APP   32

Max length of an application

Definition at line 39 of file pbx.h.

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

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

#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 1265 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 1260 of file pbx.h.

#define STATUS_NO_EXTENSION   2

Definition at line 1261 of file pbx.h.

#define STATUS_NO_LABEL   4

Definition at line 1263 of file pbx.h.

#define STATUS_NO_PRIORITY   3

Definition at line 1262 of file pbx.h.

#define STATUS_SUCCESS   5

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

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

Typedef for devicestate and hint callbacks.

Definition at line 89 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 124 of file pbx.h.


Enumeration Type Documentation

Description of the ways in which a function may escalate privileges.

Enumerator:
AST_CFE_NONE 
AST_CFE_READ 
AST_CFE_WRITE 
AST_CFE_BOTH 

Definition at line 1154 of file pbx.h.

01154                                     {
01155    AST_CFE_NONE,
01156    AST_CFE_READ,
01157    AST_CFE_WRITE,
01158    AST_CFE_BOTH,
01159 };

extension matchcid types

Note:
matchcid in ast_exten retains 0/1, this adds 3rd state for functions to specify all
See also:
ast_context_remove_extension_callerid
Enumerator:
AST_EXT_MATCHCID_OFF 

Match only extensions with matchcid=0

AST_EXT_MATCHCID_ON 

Match only extensions with matchcid=1 AND cidmatch matches

AST_EXT_MATCHCID_ANY 

Match both - used only in functions manipulating ast_exten's

Definition at line 76 of file pbx.h.

00076                             {
00077    AST_EXT_MATCHCID_OFF = 0,  /*!< Match only extensions with matchcid=0 */
00078    AST_EXT_MATCHCID_ON = 1,   /*!< Match only extensions with matchcid=1 AND cidmatch matches */
00079    AST_EXT_MATCHCID_ANY = 2,  /*!< Match both - used only in functions manipulating ast_exten's */
00080 };

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 299 of file pbx.h.

00299                     {
00300    AST_PBX_SUCCESS = 0,
00301    AST_PBX_FAILED = -1,
00302    AST_PBX_CALL_LIMIT = -2,
00303 };

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 1251 of file pbx.h.

01251                  {
01252    E_MATCHMORE =  0x00, /* extension can match but only with more 'digits' */
01253    E_CANMATCH =   0x01, /* extension can match with or without more 'digits' */
01254    E_MATCH =   0x02, /* extension is an exact match */
01255    E_MATCH_MASK = 0x03, /* mask for the argument to extension_match_core() */
01256    E_SPAWN =   0x12, /* want to spawn an extension. Requires exact match */
01257    E_FINDLABEL =  0x22  /* returns the priority for a given label. Requires exact match */
01258 };


Function Documentation

int __ast_custom_function_register ( struct ast_custom_function acf,
struct ast_module mod 
)

Register a custom function.

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

03901 {
03902    struct ast_custom_function *cur;
03903    char tmps[80];
03904 
03905    if (!acf) {
03906       return -1;
03907    }
03908 
03909    acf->mod = mod;
03910 #ifdef AST_XML_DOCS
03911    acf->docsrc = AST_STATIC_DOC;
03912 #endif
03913 
03914    if (acf_retrieve_docs(acf)) {
03915       return -1;
03916    }
03917 
03918    AST_RWLIST_WRLOCK(&acf_root);
03919 
03920    AST_RWLIST_TRAVERSE(&acf_root, cur, acflist) {
03921       if (!strcmp(acf->name, cur->name)) {
03922          ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name);
03923          AST_RWLIST_UNLOCK(&acf_root);
03924          return -1;
03925       }
03926    }
03927 
03928    /* Store in alphabetical order */
03929    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) {
03930       if (strcasecmp(acf->name, cur->name) < 0) {
03931          AST_RWLIST_INSERT_BEFORE_CURRENT(acf, acflist);
03932          break;
03933       }
03934    }
03935    AST_RWLIST_TRAVERSE_SAFE_END;
03936 
03937    if (!cur) {
03938       AST_RWLIST_INSERT_TAIL(&acf_root, acf, acflist);
03939    }
03940 
03941    AST_RWLIST_UNLOCK(&acf_root);
03942 
03943    ast_verb(2, "Registered custom function '%s'\n", term_color(tmps, acf->name, COLOR_BRCYAN, 0, sizeof(tmps)));
03944 
03945    return 0;
03946 }

int __ast_custom_function_register_escalating ( struct ast_custom_function acf,
enum ast_custom_function_escalation  escalation,
struct ast_module mod 
)

Register a custom function which requires escalated privileges.

Examples would be SHELL() (for which a read needs permission to execute arbitrary code) or FILE() (for which write needs permission to change files on the filesystem).

Definition at line 3948 of file pbx.c.

References __ast_custom_function_register(), ast_custom_escalating_function::acf, ast_calloc, AST_CFE_BOTH, AST_CFE_NONE, AST_CFE_READ, AST_CFE_WRITE, ast_custom_function_unregister(), AST_RWLIST_INSERT_TAIL, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_custom_escalating_function::read_escalates, and ast_custom_escalating_function::write_escalates.

03949 {
03950    struct ast_custom_escalating_function *acf_escalation = NULL;
03951    int res;
03952 
03953    res = __ast_custom_function_register(acf, mod);
03954    if (res != 0) {
03955       return -1;
03956    }
03957 
03958    if (escalation == AST_CFE_NONE) {
03959       /* No escalations; no need to do anything else */
03960       return 0;
03961    }
03962 
03963    acf_escalation = ast_calloc(1, sizeof(*acf_escalation));
03964    if (!acf_escalation) {
03965       ast_custom_function_unregister(acf);
03966       return -1;
03967    }
03968 
03969    acf_escalation->acf = acf;
03970    switch (escalation) {
03971    case AST_CFE_NONE:
03972       break;
03973    case AST_CFE_READ:
03974       acf_escalation->read_escalates = 1;
03975       break;
03976    case AST_CFE_WRITE:
03977       acf_escalation->write_escalates = 1;
03978       break;
03979    case AST_CFE_BOTH:
03980       acf_escalation->read_escalates = 1;
03981       acf_escalation->write_escalates = 1;
03982       break;
03983    }
03984 
03985    AST_RWLIST_WRLOCK(&escalation_root);
03986    AST_RWLIST_INSERT_TAIL(&escalation_root, acf_escalation, list);
03987    AST_RWLIST_UNLOCK(&escalation_root);
03988 
03989    return 0;
03990 }

int ast_active_calls ( void   ) 

Retrieve the number of active calls.

Definition at line 5885 of file pbx.c.

References countcalls.

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

05886 {
05887    return countcalls;
05888 }

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

08648 {
08649    int ret = -1;
08650    struct ast_context *c;
08651 
08652    c = find_context_locked(context);
08653    if (c) {
08654       ret = ast_add_extension2(c, replace, extension, priority, label, callerid,
08655          application, data, datad, registrar);
08656       ast_unlock_contexts();
08657    }
08658 
08659    return ret;
08660 }

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

References ast_add_extension2_lockopt().

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

09010 {
09011    return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid,
09012       application, data, datad, registrar, 1);
09013 }

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

References ast_channel::_state, accountcode, ast_channel::amaflags, amaflags, ast_cdr_discard(), ast_cdr_dup(), ast_channel_alloc, ast_channel_lock, ast_channel_masquerade(), ast_channel_unlock, ast_do_masquerade(), ast_explicit_goto(), ast_hangup(), ast_log(), ast_pbx_start(), AST_SOFTHANGUP_ASYNCGOTO, ast_softhangup_nolock(), ast_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(), handle_request_bye(), handle_request_refer(), my_handle_dtmf(), pbx_parseable_goto(), process_ast_dsp(), process_sdp(), sip_read(), and socket_process().

08686 {
08687    int res = 0;
08688    struct ast_channel *tmpchan;
08689    struct {
08690       char *accountcode;
08691       char *exten;
08692       char *context;
08693       char *linkedid;
08694       char *name;
08695       struct ast_cdr *cdr;
08696       int amaflags;
08697       int state;
08698       format_t readformat;
08699       format_t writeformat;
08700    } tmpvars = { 0, };
08701 
08702    ast_channel_lock(chan);
08703    if (chan->pbx) { /* This channel is currently in the PBX */
08704       ast_explicit_goto(chan, context, exten, priority + 1);
08705       ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO);
08706       ast_channel_unlock(chan);
08707       return res;
08708    }
08709 
08710    /* In order to do it when the channel doesn't really exist within
08711     * the PBX, we have to make a new channel, masquerade, and start the PBX
08712     * at the new location */
08713    tmpvars.accountcode = ast_strdupa(chan->accountcode);
08714    tmpvars.exten = ast_strdupa(chan->exten);
08715    tmpvars.context = ast_strdupa(chan->context);
08716    tmpvars.linkedid = ast_strdupa(chan->linkedid);
08717    tmpvars.name = ast_strdupa(chan->name);
08718    tmpvars.amaflags = chan->amaflags;
08719    tmpvars.state = chan->_state;
08720    tmpvars.writeformat = chan->writeformat;
08721    tmpvars.readformat = chan->readformat;
08722    tmpvars.cdr = chan->cdr ? ast_cdr_dup(chan->cdr) : NULL;
08723 
08724    ast_channel_unlock(chan);
08725 
08726    /* Do not hold any channel locks while calling channel_alloc() since the function
08727     * locks the channel container when linking the new channel in. */
08728    if (!(tmpchan = ast_channel_alloc(0, tmpvars.state, 0, 0, tmpvars.accountcode, tmpvars.exten, tmpvars.context, tmpvars.linkedid, tmpvars.amaflags, "AsyncGoto/%s", tmpvars.name))) {
08729       ast_cdr_discard(tmpvars.cdr);
08730       return -1;
08731    }
08732 
08733    /* copy the cdr info over */
08734    if (tmpvars.cdr) {
08735       ast_cdr_discard(tmpchan->cdr);
08736       tmpchan->cdr = tmpvars.cdr;
08737       tmpvars.cdr = NULL;
08738    }
08739 
08740    /* Make formats okay */
08741    tmpchan->readformat = tmpvars.readformat;
08742    tmpchan->writeformat = tmpvars.writeformat;
08743 
08744    /* Setup proper location. Never hold another channel lock while calling this function. */
08745    ast_explicit_goto(tmpchan, S_OR(context, tmpvars.context), S_OR(exten, tmpvars.exten), priority);
08746 
08747    /* Masquerade into tmp channel */
08748    if (ast_channel_masquerade(tmpchan, chan)) {
08749       /* Failed to set up the masquerade.  It's probably chan_local
08750        * in the middle of optimizing itself out.  Sad. :( */
08751       ast_hangup(tmpchan);
08752       tmpchan = NULL;
08753       res = -1;
08754    } else {
08755       ast_do_masquerade(tmpchan);
08756       /* Start the PBX going on our stolen channel */
08757       if (ast_pbx_start(tmpchan)) {
08758          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name);
08759          ast_hangup(tmpchan);
08760          res = -1;
08761       }
08762    }
08763 
08764    return res;
08765 }

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

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

08768 {
08769    struct ast_channel *chan;
08770    int res = -1;
08771 
08772    if ((chan = ast_channel_get_by_name(channame))) {
08773       res = ast_async_goto(chan, context, exten, priority);
08774       chan = ast_channel_unref(chan);
08775    }
08776 
08777    return res;
08778 }

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

References __ast_goto_if_exists().

11126 {
11127    return __ast_goto_if_exists(chan, context, exten, priority, 1);
11128 }

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

References pbx_parseable_goto().

Referenced by asyncgoto_exec(), and handle_redirect().

11191 {
11192    return pbx_parseable_goto(chan, goto_string, 1);
11193 }

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 8268 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, and ast_timing::timezone.

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

08269 {
08270    char *info;
08271    int j, num_fields, last_sep = -1;
08272 
08273    i->timezone = NULL;
08274 
08275    /* Check for empty just in case */
08276    if (ast_strlen_zero(info_in)) {
08277       return 0;
08278    }
08279 
08280    /* make a copy just in case we were passed a static string */
08281    info = ast_strdupa(info_in);
08282 
08283    /* count the number of fields in the timespec */
08284    for (j = 0, num_fields = 1; info[j] != '\0'; j++) {
08285       if (info[j] == ',') {
08286          last_sep = j;
08287          num_fields++;
08288       }
08289    }
08290 
08291    /* save the timezone, if it is specified */
08292    if (num_fields == 5) {
08293       i->timezone = ast_strdup(info + last_sep + 1);
08294    }
08295 
08296    /* Assume everything except time */
08297    i->monthmask = 0xfff;   /* 12 bits */
08298    i->daymask = 0x7fffffffU; /* 31 bits */
08299    i->dowmask = 0x7f; /* 7 bits */
08300    /* on each call, use strsep() to move info to the next argument */
08301    get_timerange(i, strsep(&info, "|,"));
08302    if (info)
08303       i->dowmask = get_range(strsep(&info, "|,"), 7, days, "day of week");
08304    if (info)
08305       i->daymask = get_range(strsep(&info, "|,"), 31, NULL, "day");
08306    if (info)
08307       i->monthmask = get_range(strsep(&info, "|,"), 12, months, "month");
08308    return 1;
08309 }

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 5369 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(), leave_voicemail(), loopback_canmatch(), mgcp_ss(), pbx_builtin_background(), phone_check_exception(), skinny_ss(), and valid_exit().

05370 {
05371    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0);
05372 }

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

References ast_check_timing2(), and ast_tvnow().

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

08312 {
08313    return ast_check_timing2(i, ast_tvnow());
08314 }

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

08317 {
08318    struct ast_tm tm;
08319 
08320    ast_localtime(&tv, &tm, i->timezone);
08321 
08322    /* If it's not the right month, return */
08323    if (!(i->monthmask & (1 << tm.tm_mon)))
08324       return 0;
08325 
08326    /* If it's not that time of the month.... */
08327    /* Warning, tm_mday has range 1..31! */
08328    if (!(i->daymask & (1 << (tm.tm_mday-1))))
08329       return 0;
08330 
08331    /* If it's not the right day of the week */
08332    if (!(i->dowmask & (1 << tm.tm_wday)))
08333       return 0;
08334 
08335    /* Sanity check the hour just to be safe */
08336    if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) {
08337       ast_log(LOG_WARNING, "Insane time...\n");
08338       return 0;
08339    }
08340 
08341    /* Now the tough part, we calculate if it fits
08342       in the right time based on min/hour */
08343    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))))
08344       return 0;
08345 
08346    /* If we got this far, then we're good */
08347    return 1;
08348 }

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

11196 {
11197    struct ast_app *app = NULL;
11198    int which = 0;
11199    char *ret = NULL;
11200    size_t wordlen = strlen(word);
11201 
11202    AST_RWLIST_RDLOCK(&apps);
11203    AST_RWLIST_TRAVERSE(&apps, app, list) {
11204       if (!strncasecmp(word, app->name, wordlen) && ++which > state) {
11205          ret = ast_strdup(app->name);
11206          break;
11207       }
11208    }
11209    AST_RWLIST_UNLOCK(&apps);
11210 
11211    return ret;
11212 }

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

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

Referenced by handle_cli_dialplan_add_ignorepat().

08553 {
08554    int ret = -1;
08555    struct ast_context *c;
08556 
08557    c = find_context_locked(context);
08558    if (c) {
08559       ret = ast_context_add_ignorepat2(c, value, registrar);
08560       ast_unlock_contexts();
08561    }
08562    return ret;
08563 }

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

Definition at line 8565 of file pbx.c.

References ast_calloc, 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_compile_ael2(), ast_context_add_ignorepat(), context_merge_incls_swits_igps_other_registrars(), and pbx_load_config().

08566 {
08567    struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL;
08568    int length;
08569    char *pattern;
08570    length = sizeof(struct ast_ignorepat);
08571    length += strlen(value) + 1;
08572    if (!(ignorepat = ast_calloc(1, length)))
08573       return -1;
08574    /* The cast to char * is because we need to write the initial value.
08575     * The field is not supposed to be modified otherwise.  Also, gcc 4.2
08576     * sees the cast as dereferencing a type-punned pointer and warns about
08577     * it.  This is the workaround (we're telling gcc, yes, that's really
08578     * what we wanted to do).
08579     */
08580    pattern = (char *) ignorepat->pattern;
08581    strcpy(pattern, value);
08582    ignorepat->next = NULL;
08583    ignorepat->registrar = registrar;
08584    ast_wrlock_context(con);
08585    for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) {
08586       ignorepatl = ignorepatc;
08587       if (!strcasecmp(ignorepatc->pattern, value)) {
08588          /* Already there */
08589          ast_unlock_context(con);
08590          ast_free(ignorepat);
08591          errno = EEXIST;
08592          return -1;
08593       }
08594    }
08595    if (ignorepatl)
08596       ignorepatl->next = ignorepat;
08597    else
08598       con->ignorepats = ignorepat;
08599    ast_unlock_context(con);
08600    return 0;
08601 
08602 }

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

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

Referenced by handle_cli_dialplan_add_include().

08097 {
08098    int ret = -1;
08099    struct ast_context *c;
08100 
08101    c = find_context_locked(context);
08102    if (c) {
08103       ret = ast_context_add_include2(c, include, registrar);
08104       ast_unlock_contexts();
08105    }
08106    return ret;
08107 }

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

08367 {
08368    struct ast_include *new_include;
08369    char *c;
08370    struct ast_include *i, *il = NULL; /* include, include_last */
08371    int length;
08372    char *p;
08373 
08374    length = sizeof(struct ast_include);
08375    length += 2 * (strlen(value) + 1);
08376 
08377    /* allocate new include structure ... */
08378    if (!(new_include = ast_calloc(1, length)))
08379       return -1;
08380    /* Fill in this structure. Use 'p' for assignments, as the fields
08381     * in the structure are 'const char *'
08382     */
08383    p = new_include->stuff;
08384    new_include->name = p;
08385    strcpy(p, value);
08386    p += strlen(value) + 1;
08387    new_include->rname = p;
08388    strcpy(p, value);
08389    /* Strip off timing info, and process if it is there */
08390    if ( (c = strchr(p, ',')) ) {
08391       *c++ = '\0';
08392       new_include->hastime = ast_build_timing(&(new_include->timing), c);
08393    }
08394    new_include->next      = NULL;
08395    new_include->registrar = registrar;
08396 
08397    ast_wrlock_context(con);
08398 
08399    /* ... go to last include and check if context is already included too... */
08400    for (i = con->includes; i; i = i->next) {
08401       if (!strcasecmp(i->name, new_include->name)) {
08402          ast_destroy_timing(&(new_include->timing));
08403          ast_free(new_include);
08404          ast_unlock_context(con);
08405          errno = EEXIST;
08406          return -1;
08407       }
08408       il = i;
08409    }
08410 
08411    /* ... include new context into context list, unlock, return */
08412    if (il)
08413       il->next = new_include;
08414    else
08415       con->includes = new_include;
08416    ast_verb(3, "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con));
08417 
08418    ast_unlock_context(con);
08419 
08420    return 0;
08421 }

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

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

08429 {
08430    int ret = -1;
08431    struct ast_context *c;
08432 
08433    c = find_context_locked(context);
08434    if (c) { /* found, add switch to this context */
08435       ret = ast_context_add_switch2(c, sw, data, eval, registrar);
08436       ast_unlock_contexts();
08437    }
08438    return ret;
08439 }

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

08450 {
08451    struct ast_sw *new_sw;
08452    struct ast_sw *i;
08453    int length;
08454    char *p;
08455 
08456    length = sizeof(struct ast_sw);
08457    length += strlen(value) + 1;
08458    if (data)
08459       length += strlen(data);
08460    length++;
08461 
08462    /* allocate new sw structure ... */
08463    if (!(new_sw = ast_calloc(1, length)))
08464       return -1;
08465    /* ... fill in this structure ... */
08466    p = new_sw->stuff;
08467    new_sw->name = p;
08468    strcpy(new_sw->name, value);
08469    p += strlen(value) + 1;
08470    new_sw->data = p;
08471    if (data) {
08472       strcpy(new_sw->data, data);
08473       p += strlen(data) + 1;
08474    } else {
08475       strcpy(new_sw->data, "");
08476       p++;
08477    }
08478    new_sw->eval     = eval;
08479    new_sw->registrar = registrar;
08480 
08481    /* ... try to lock this context ... */
08482    ast_wrlock_context(con);
08483 
08484    /* ... go to last sw and check if context is already swd too... */
08485    AST_LIST_TRAVERSE(&con->alts, i, list) {
08486       if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) {
08487          ast_free(new_sw);
08488          ast_unlock_context(con);
08489          errno = EEXIST;
08490          return -1;
08491       }
08492    }
08493 
08494    /* ... sw new context into context list, unlock, return */
08495    AST_LIST_INSERT_TAIL(&con->alts, new_sw, list);
08496 
08497    ast_verb(3, "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con));
08498 
08499    ast_unlock_context(con);
08500 
08501    return 0;
08502 }

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 9829 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(), features_shutdown(), 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 2925 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(), isexten_function_read(), manage_parkinglot(), parked_call_exec(), register_exten(), register_peer_exten(), remove_dead_dialplan_useage(), unload_module(), and unregister_exten().

02926 {
02927    struct ast_context *tmp;
02928    struct fake_context item;
02929 
02930    if (!name) {
02931       return NULL;
02932    }
02933    ast_rdlock_contexts();
02934    if (contexts_table) {
02935       ast_copy_string(item.name, name, sizeof(item.name));
02936       tmp = ast_hashtab_lookup(contexts_table, &item);
02937    } else {
02938       tmp = NULL;
02939       while ((tmp = ast_walk_contexts(tmp))) {
02940          if (!strcasecmp(name, tmp->name)) {
02941             break;
02942          }
02943       }
02944    }
02945    ast_unlock_contexts();
02946    return tmp;
02947 }

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

07681 {
07682    struct ast_context *tmp, **local_contexts;
07683    struct fake_context search;
07684    int length = sizeof(struct ast_context) + strlen(name) + 1;
07685 
07686    if (!contexts_table) {
07687       /* Protect creation of contexts_table from reentrancy. */
07688       ast_wrlock_contexts();
07689       if (!contexts_table) {
07690          contexts_table = ast_hashtab_create(17,
07691             ast_hashtab_compare_contexts,
07692             ast_hashtab_resize_java,
07693             ast_hashtab_newsize_java,
07694             ast_hashtab_hash_contexts,
07695             0);
07696       }
07697       ast_unlock_contexts();
07698    }
07699 
07700    ast_copy_string(search.name, name, sizeof(search.name));
07701    if (!extcontexts) {
07702       ast_rdlock_contexts();
07703       local_contexts = &contexts;
07704       tmp = ast_hashtab_lookup(contexts_table, &search);
07705       ast_unlock_contexts();
07706       if (tmp) {
07707          tmp->refcount++;
07708          return tmp;
07709       }
07710    } else { /* local contexts just in a linked list; search there for the new context; slow, linear search, but not frequent */
07711       local_contexts = extcontexts;
07712       tmp = ast_hashtab_lookup(exttable, &search);
07713       if (tmp) {
07714          tmp->refcount++;
07715          return tmp;
07716       }
07717    }
07718 
07719    if ((tmp = ast_calloc(1, length))) {
07720       ast_rwlock_init(&tmp->lock);
07721       ast_mutex_init(&tmp->macrolock);
07722       strcpy(tmp->name, name);
07723       tmp->root = NULL;
07724       tmp->root_table = NULL;
07725       tmp->registrar = ast_strdup(registrar);
07726       tmp->includes = NULL;
07727       tmp->ignorepats = NULL;
07728       tmp->refcount = 1;
07729    } else {
07730       ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name);
07731       return NULL;
07732    }
07733 
07734    if (!extcontexts) {
07735       ast_wrlock_contexts();
07736       tmp->next = *local_contexts;
07737       *local_contexts = tmp;
07738       ast_hashtab_insert_safe(contexts_table, tmp); /*put this context into the tree */
07739       ast_unlock_contexts();
07740       ast_debug(1, "Registered context '%s'(%p) in table %p registrar: %s\n", tmp->name, tmp, contexts_table, registrar);
07741       ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar);
07742    } else {
07743       tmp->next = *local_contexts;
07744       if (exttable)
07745          ast_hashtab_insert_immediate(exttable, tmp); /*put this context into the tree */
07746 
07747       *local_contexts = tmp;
07748       ast_debug(1, "Registered context '%s'(%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar);
07749       ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar);
07750    }
07751    return tmp;
07752 }

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

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

Referenced by _macro_exec().

06261 {
06262    struct ast_context *c;
06263    int ret = -1;
06264 
06265    c = find_context_locked(context);
06266    if (c) {
06267       ast_unlock_contexts();
06268 
06269       /* if we found context, lock macrolock */
06270       ret = ast_mutex_lock(&c->macrolock);
06271    }
06272 
06273    return ret;
06274 }

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

References ast_context_remove_extension_callerid(), and AST_EXT_MATCHCID_ANY.

Referenced by register_peer_exten(), remove_exten_if_exist(), sla_station_destructor(), sla_trunk_destructor(), unregister_exten(), and UnregisterExtension().

06069 {
06070    return ast_context_remove_extension_callerid(context, extension, priority, NULL, AST_EXT_MATCHCID_ANY, registrar);
06071 }

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

References ast_context_remove_extension_callerid2(), and AST_EXT_MATCHCID_ANY.

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

06099 {
06100    return ast_context_remove_extension_callerid2(con, extension, priority, NULL, AST_EXT_MATCHCID_ANY, registrar, already_locked);
06101 }

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

06074 {
06075    int ret = -1; /* default error return */
06076    struct ast_context *c;
06077 
06078    c = find_context_locked(context);
06079    if (c) { /* ... remove extension ... */
06080       ret = ast_context_remove_extension_callerid2(c, extension, priority, callerid,
06081          matchcallerid, registrar, 0);
06082       ast_unlock_contexts();
06083    }
06084 
06085    return ret;
06086 }

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

06104 {
06105    struct ast_exten *exten, *prev_exten = NULL;
06106    struct ast_exten *peer;
06107    struct ast_exten ex, *exten2, *exten3;
06108    char dummy_name[1024];
06109    struct ast_exten *previous_peer = NULL;
06110    struct ast_exten *next_peer = NULL;
06111    int found = 0;
06112 
06113    if (!already_locked)
06114       ast_wrlock_context(con);
06115 
06116 #ifdef NEED_DEBUG
06117    ast_verb(3,"Removing %s/%s/%d%s%s from trees, registrar=%s\n", con->name, extension, priority, matchcallerid ? "/" : "", matchcallerid ? callerid : "", registrar);
06118 #endif
06119 #ifdef CONTEXT_DEBUG
06120    check_contexts(__FILE__, __LINE__);
06121 #endif
06122    /* find this particular extension */
06123    ex.exten = dummy_name;
06124    ex.matchcid = matchcallerid;
06125    ex.cidmatch = callerid;
06126    ast_copy_string(dummy_name, extension, sizeof(dummy_name));
06127    exten = ast_hashtab_lookup(con->root_table, &ex);
06128    if (exten) {
06129       if (priority == 0) {
06130          exten2 = ast_hashtab_remove_this_object(con->root_table, exten);
06131          if (!exten2)
06132             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);
06133          if (con->pattern_tree) {
06134             struct match_char *x = add_exten_to_pattern_tree(con, exten, 1);
06135 
06136             if (x->exten) { /* this test for safety purposes */
06137                x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */
06138                x->exten = 0; /* get rid of what will become a bad pointer */
06139             } else {
06140                ast_log(LOG_WARNING,"Trying to delete an exten from a context, but the pattern tree node returned isn't a full extension\n");
06141             }
06142          }
06143       } else {
06144          ex.priority = priority;
06145          exten2 = ast_hashtab_lookup(exten->peer_table, &ex);
06146          if (exten2) {
06147             if (exten2->label) { /* if this exten has a label, remove that, too */
06148                exten3 = ast_hashtab_remove_this_object(exten->peer_label_table,exten2);
06149                if (!exten3)
06150                   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);
06151             }
06152 
06153             exten3 = ast_hashtab_remove_this_object(exten->peer_table, exten2);
06154             if (!exten3)
06155                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);
06156             if (exten2 == exten && exten2->peer) {
06157                exten2 = ast_hashtab_remove_this_object(con->root_table, exten);
06158                ast_hashtab_insert_immediate(con->root_table, exten2->peer);
06159             }
06160             if (ast_hashtab_size(exten->peer_table) == 0) {
06161                /* well, if the last priority of an exten is to be removed,
06162                   then, the extension is removed, too! */
06163                exten3 = ast_hashtab_remove_this_object(con->root_table, exten);
06164                if (!exten3)
06165                   ast_log(LOG_ERROR,"Did not remove this exten (%s) from the context root_table (%s) (priority %d)\n", exten->exten, con->name, priority);
06166                if (con->pattern_tree) {
06167                   struct match_char *x = add_exten_to_pattern_tree(con, exten, 1);
06168                   if (x->exten) { /* this test for safety purposes */
06169                      x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */
06170                      x->exten = 0; /* get rid of what will become a bad pointer */
06171                   }
06172                }
06173             }
06174          } else {
06175             ast_log(LOG_ERROR,"Could not find priority %d of exten %s in context %s!\n",
06176                   priority, exten->exten, con->name);
06177          }
06178       }
06179    } else {
06180       /* hmmm? this exten is not in this pattern tree? */
06181       ast_log(LOG_WARNING,"Cannot find extension %s in root_table in context %s\n",
06182             extension, con->name);
06183    }
06184 #ifdef NEED_DEBUG
06185    if (con->pattern_tree) {
06186       ast_log(LOG_NOTICE,"match char tree after exten removal:\n");
06187       log_match_char_tree(con->pattern_tree, " ");
06188    }
06189 #endif
06190 
06191    /* scan the extension list to find first matching extension-registrar */
06192    for (exten = con->root; exten; prev_exten = exten, exten = exten->next) {
06193       if (!strcmp(exten->exten, extension) &&
06194          (!registrar || !strcmp(exten->registrar, registrar)) &&
06195          (!matchcallerid || (!ast_strlen_zero(callerid) && !ast_strlen_zero(exten->cidmatch) && !strcmp(exten->cidmatch, callerid)) || (ast_strlen_zero(callerid) && ast_strlen_zero(exten->cidmatch))))
06196          break;
06197    }
06198    if (!exten) {
06199       /* we can't find right extension */
06200       if (!already_locked)
06201          ast_unlock_context(con);
06202       return -1;
06203    }
06204 
06205    /* scan the priority list to remove extension with exten->priority == priority */
06206    for (peer = exten, next_peer = exten->peer ? exten->peer : exten->next;
06207        peer && !strcmp(peer->exten, extension) &&
06208          (!callerid || (!matchcallerid && !peer->matchcid) || (matchcallerid && peer->matchcid && !strcmp(peer->cidmatch, callerid))) ;
06209          peer = next_peer, next_peer = next_peer ? (next_peer->peer ? next_peer->peer : next_peer->next) : NULL) {
06210 
06211       if ((priority == 0 || peer->priority == priority) &&
06212             (!registrar || !strcmp(peer->registrar, registrar) )) {
06213          found = 1;
06214 
06215          /* we are first priority extension? */
06216          if (!previous_peer) {
06217             /*
06218              * We are first in the priority chain, so must update the extension chain.
06219              * The next node is either the next priority or the next extension
06220              */
06221             struct ast_exten *next_node = peer->peer ? peer->peer : peer->next;
06222             if (peer->peer) {
06223                /* move the peer_table and peer_label_table down to the next peer, if
06224                   it is there */
06225                peer->peer->peer_table = peer->peer_table;
06226                peer->peer->peer_label_table = peer->peer_label_table;
06227                peer->peer_table = NULL;
06228                peer->peer_label_table = NULL;
06229             }
06230             if (!prev_exten) {   /* change the root... */
06231                con->root = next_node;
06232             } else {
06233                prev_exten->next = next_node; /* unlink */
06234             }
06235             if (peer->peer)   { /* update the new head of the pri list */
06236                peer->peer->next = peer->next;
06237             }
06238          } else { /* easy, we are not first priority in extension */
06239             previous_peer->peer = peer->peer;
06240          }
06241 
06242 
06243          /* now, free whole priority extension */
06244          destroy_exten(peer);
06245       } else {
06246          previous_peer = peer;
06247       }
06248    }
06249    if (!already_locked)
06250       ast_unlock_context(con);
06251    return found ? 0 : -1;
06252 }

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

Definition at line 8508 of file pbx.c.

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

Referenced by handle_cli_dialplan_remove_ignorepat().

08509 {
08510    int ret = -1;
08511    struct ast_context *c;
08512 
08513    c = find_context_locked(context);
08514    if (c) {
08515       ret = ast_context_remove_ignorepat2(c, ignorepat, registrar);
08516       ast_unlock_contexts();
08517    }
08518    return ret;
08519 }

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

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

08522 {
08523    struct ast_ignorepat *ip, *ipl = NULL;
08524 
08525    ast_wrlock_context(con);
08526 
08527    for (ip = con->ignorepats; ip; ip = ip->next) {
08528       if (!strcmp(ip->pattern, ignorepat) &&
08529          (!registrar || (registrar == ip->registrar))) {
08530          if (ipl) {
08531             ipl->next = ip->next;
08532             ast_free(ip);
08533          } else {
08534             con->ignorepats = ip->next;
08535             ast_free(ip);
08536          }
08537          ast_unlock_context(con);
08538          return 0;
08539       }
08540       ipl = ip;
08541    }
08542 
08543    ast_unlock_context(con);
08544    errno = EINVAL;
08545    return -1;
08546 }

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

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

Referenced by handle_cli_dialplan_remove_include().

05962 {
05963    int ret = -1;
05964    struct ast_context *c;
05965 
05966    c = find_context_locked(context);
05967    if (c) {
05968       /* found, remove include from this context ... */
05969       ret = ast_context_remove_include2(c, include, registrar);
05970       ast_unlock_contexts();
05971    }
05972    return ret;
05973 }

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

05985 {
05986    struct ast_include *i, *pi = NULL;
05987    int ret = -1;
05988 
05989    ast_wrlock_context(con);
05990 
05991    /* find our include */
05992    for (i = con->includes; i; pi = i, i = i->next) {
05993       if (!strcmp(i->name, include) &&
05994             (!registrar || !strcmp(i->registrar, registrar))) {
05995          /* remove from list */
05996          ast_verb(3, "Removing inclusion of context '%s' in context '%s; registrar=%s'\n", include, ast_get_context_name(con), registrar);
05997          if (pi)
05998             pi->next = i->next;
05999          else
06000             con->includes = i->next;
06001          /* free include and return */
06002          ast_destroy_timing(&(i->timing));
06003          ast_free(i);
06004          ret = 0;
06005          break;
06006       }
06007    }
06008 
06009    ast_unlock_context(con);
06010 
06011    return ret;
06012 }

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

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

06020 {
06021    int ret = -1; /* default error return */
06022    struct ast_context *c;
06023 
06024    c = find_context_locked(context);
06025    if (c) {
06026       /* remove switch from this context ... */
06027       ret = ast_context_remove_switch2(c, sw, data, registrar);
06028       ast_unlock_contexts();
06029    }
06030    return ret;
06031 }

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

06042 {
06043    struct ast_sw *i;
06044    int ret = -1;
06045 
06046    ast_wrlock_context(con);
06047 
06048    /* walk switches */
06049    AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) {
06050       if (!strcmp(i->name, sw) && !strcmp(i->data, data) &&
06051          (!registrar || !strcmp(i->registrar, registrar))) {
06052          /* found, remove from list */
06053          ast_verb(3, "Removing switch '%s' from context '%s; registrar=%s'\n", sw, ast_get_context_name(con), registrar);
06054          AST_LIST_REMOVE_CURRENT(list);
06055          ast_free(i); /* free switch and return */
06056          ret = 0;
06057          break;
06058       }
06059    }
06060    AST_LIST_TRAVERSE_SAFE_END;
06061 
06062    ast_unlock_context(con);
06063 
06064    return ret;
06065 }

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

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

Referenced by _macro_exec().

06282 {
06283    struct ast_context *c;
06284    int ret = -1;
06285 
06286    c = find_context_locked(context);
06287    if (c) {
06288       ast_unlock_contexts();
06289 
06290       /* if we found context, unlock macrolock */
06291       ret = ast_mutex_unlock(&c->macrolock);
06292    }
06293 
06294    return ret;
06295 }

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

11081 {
11082    struct ast_include *inc = NULL;
11083    int res = 0;
11084 
11085    while ( (inc = ast_walk_context_includes(con, inc)) ) {
11086       if (ast_context_find(inc->rname))
11087          continue;
11088 
11089       res = -1;
11090       ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n",
11091          ast_get_context_name(con), inc->rname);
11092       break;
11093    }
11094 
11095    return res;
11096 }

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

References ast_custom_escalating_function::acf, ast_free, AST_RWLIST_REMOVE, AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_string_field_free_memory, ast_verb, AST_XML_DOC, ast_custom_function::docsrc, and ast_custom_function::name.

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

03769 {
03770    struct ast_custom_function *cur;
03771    struct ast_custom_escalating_function *cur_escalation;
03772 
03773    if (!acf) {
03774       return -1;
03775    }
03776 
03777    AST_RWLIST_WRLOCK(&acf_root);
03778    if ((cur = AST_RWLIST_REMOVE(&acf_root, acf, acflist))) {
03779 #ifdef AST_XML_DOCS
03780       if (cur->docsrc == AST_XML_DOC) {
03781          ast_string_field_free_memory(acf);
03782       }
03783 #endif
03784       ast_verb(2, "Unregistered custom function %s\n", cur->name);
03785    }
03786    AST_RWLIST_UNLOCK(&acf_root);
03787 
03788    /* Remove from the escalation list */
03789    AST_RWLIST_WRLOCK(&escalation_root);
03790    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&escalation_root, cur_escalation, list) {
03791       if (cur_escalation->acf == acf) {
03792          AST_RWLIST_REMOVE_CURRENT(list);
03793          ast_free(cur_escalation);
03794          break;
03795       }
03796    }
03797    AST_RWLIST_TRAVERSE_SAFE_END;
03798    AST_RWLIST_UNLOCK(&escalation_root);
03799 
03800    return cur ? 0 : -1;
03801 }

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

08351 {
08352    if (i->timezone) {
08353       ast_free(i->timezone);
08354       i->timezone = NULL;
08355    }
08356    return 0;
08357 }

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

04799 {
04800    switch (devstate) {
04801    case AST_DEVICE_ONHOLD:
04802       return AST_EXTENSION_ONHOLD;
04803    case AST_DEVICE_BUSY:
04804       return AST_EXTENSION_BUSY;
04805    case AST_DEVICE_UNKNOWN:
04806       return AST_EXTENSION_NOT_INUSE;
04807    case AST_DEVICE_UNAVAILABLE:
04808    case AST_DEVICE_INVALID:
04809       return AST_EXTENSION_UNAVAILABLE;
04810    case AST_DEVICE_RINGINUSE:
04811       return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING);
04812    case AST_DEVICE_RINGING:
04813       return AST_EXTENSION_RINGING;
04814    case AST_DEVICE_INUSE:
04815       return AST_EXTENSION_INUSE;
04816    case AST_DEVICE_NOT_INUSE:
04817       return AST_EXTENSION_NOT_INUSE;
04818    case AST_DEVICE_TOTAL: /* not a device state, included for completeness */
04819       break;
04820    }
04821 
04822    return AST_EXTENSION_NOT_INUSE;
04823 }

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

References E_MATCH, and pbx_extension_helper().

Referenced by __analog_ss_thread(), __ast_goto_if_exists(), __ast_pbx_run(), _macro_exec(), acf_isexten_exec(), analog_ss_thread(), answer_call(), ast_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(), findmeexec(), get_also_info(), get_destination(), get_refer_info(), gosub_exec(), handle_gosub(), handle_stimulus_message(), isexten_function_read(), leave_voicemail(), local_alloc(), local_call(), local_devicestate(), 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(), show_debug_helper(), sip_new(), sip_read(), skinny_ss(), socket_process(), try_calling(), vm_authenticate(), and waitstream_core().

05355 {
05356    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0);
05357 }

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 8662 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(), and pbx_parseable_goto().

08663 {
08664    if (!chan)
08665       return -1;
08666 
08667    ast_channel_lock(chan);
08668 
08669    if (!ast_strlen_zero(context))
08670       ast_copy_string(chan->context, context, sizeof(chan->context));
08671    if (!ast_strlen_zero(exten))
08672       ast_copy_string(chan->exten, exten, sizeof(chan->exten));
08673    if (priority > -1) {
08674       chan->priority = priority;
08675       /* see flag description in channel.h for explanation */
08676       if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP))
08677          chan->priority--;
08678    }
08679 
08680    ast_channel_unlock(chan);
08681 
08682    return 0;
08683 }

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

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

02903 {
02904    if (needmore != E_MATCHMORE && needmore != E_CANMATCH)
02905       ast_log(LOG_WARNING, "invalid argument %d\n", needmore);
02906    return extension_match_core(pattern, data, needmore);
02907 }

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

References ext_cmp().

Referenced by lua_extension_cmp().

02668 {
02669    int cmp;
02670 
02671    cmp = ext_cmp(a, b);
02672    if (cmp < 0) {
02673       return -1;
02674    }
02675    if (cmp > 0) {
02676       return 1;
02677    }
02678    return 0;
02679 }

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

02898 {
02899    return extension_match_core(pattern, data, E_MATCH);
02900 }

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

04869 {
04870    struct ast_exten *e;
04871 
04872    if (!(e = ast_hint_extension(c, context, exten))) {  /* Do we have a hint for this extension ? */
04873       return -1;                   /* No hint, return -1 */
04874    }
04875 
04876    if (e->exten[0] == '_') {
04877       /* Create this hint on-the-fly */
04878       ast_add_extension(e->parent->name, 0, exten, e->priority, e->label,
04879          e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr,
04880          e->registrar);
04881       if (!(e = ast_hint_extension(c, context, exten))) {
04882          /* Improbable, but not impossible */
04883          return -1;
04884       }
04885    }
04886 
04887    return ast_extension_state2(e);  /* Check all devices in the hint */
04888 }

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

References ARRAY_LEN, extension_states, and cfextension_states::text.

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

04857 {
04858    int i;
04859 
04860    for (i = 0; (i < ARRAY_LEN(extension_states)); i++) {
04861       if (extension_states[i].extension_state == extension_state)
04862          return extension_states[i].text;
04863    }
04864    return "Unknown";
04865 }

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

References ast_extension_state_add_destroy().

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

05091 {
05092    return ast_extension_state_add_destroy(context, exten, change_cb, NULL, data);
05093 }

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

05004 {
05005    struct ast_hint *hint;
05006    struct ast_state_cb *state_cb;
05007    struct ast_exten *e;
05008    int id;
05009 
05010    /* If there's no context and extension:  add callback to statecbs list */
05011    if (!context && !exten) {
05012       /* Prevent multiple adds from adding the same change_cb at the same time. */
05013       ao2_lock(statecbs);
05014 
05015       /* Remove any existing change_cb. */
05016       ao2_find(statecbs, change_cb, OBJ_UNLINK | OBJ_NODATA);
05017 
05018       /* Now insert the change_cb */
05019       if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) {
05020          ao2_unlock(statecbs);
05021          return -1;
05022       }
05023       state_cb->id = 0;
05024       state_cb->change_cb = change_cb;
05025       state_cb->destroy_cb = destroy_cb;
05026       state_cb->data = data;
05027       ao2_link(statecbs, state_cb);
05028 
05029       ao2_ref(state_cb, -1);
05030       ao2_unlock(statecbs);
05031       return 0;
05032    }
05033 
05034    if (!context || !exten)
05035       return -1;
05036 
05037    /* This callback type is for only one hint, so get the hint */
05038    e = ast_hint_extension(NULL, context, exten);
05039    if (!e) {
05040       return -1;
05041    }
05042 
05043    /* If this is a pattern, dynamically create a new extension for this
05044     * particular match.  Note that this will only happen once for each
05045     * individual extension, because the pattern will no longer match first.
05046     */
05047    if (e->exten[0] == '_') {
05048       ast_add_extension(e->parent->name, 0, exten, e->priority, e->label,
05049          e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr,
05050          e->registrar);
05051       e = ast_hint_extension(NULL, context, exten);
05052       if (!e || e->exten[0] == '_') {
05053          return -1;
05054       }
05055    }
05056 
05057    /* Find the hint in the hints container */
05058    ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */
05059    hint = ao2_find(hints, e, 0);
05060    if (!hint) {
05061       ao2_unlock(hints);
05062       return -1;
05063    }
05064 
05065    /* Now insert the callback in the callback list  */
05066    if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) {
05067       ao2_ref(hint, -1);
05068       ao2_unlock(hints);
05069       return -1;
05070    }
05071    do {
05072       id = stateid++;      /* Unique ID for this callback */
05073       /* Do not allow id to ever be -1 or 0. */
05074    } while (id == -1 || id == 0);
05075    state_cb->id = id;
05076    state_cb->change_cb = change_cb; /* Pointer to callback routine */
05077    state_cb->destroy_cb = destroy_cb;
05078    state_cb->data = data;     /* Data for the callback */
05079    ao2_link(hint->callbacks, state_cb);
05080 
05081    ao2_ref(state_cb, -1);
05082    ao2_ref(hint, -1);
05083    ao2_unlock(hints);
05084 
05085    return id;
05086 }

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

05112 {
05113    struct ast_state_cb *p_cur;
05114    int ret = -1;
05115 
05116    if (!id) {  /* id == 0 is a callback without extension */
05117       if (!change_cb) {
05118          return ret;
05119       }
05120       p_cur = ao2_find(statecbs, change_cb, OBJ_UNLINK);
05121       if (p_cur) {
05122          ret = 0;
05123          ao2_ref(p_cur, -1);
05124       }
05125    } else { /* callback with extension, find the callback based on ID */
05126       struct ast_hint *hint;
05127 
05128       ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */
05129       hint = ao2_callback(hints, 0, find_hint_by_cb_id, &id);
05130       if (hint) {
05131          p_cur = ao2_find(hint->callbacks, &id, OBJ_UNLINK);
05132          if (p_cur) {
05133             ret = 0;
05134             ao2_ref(p_cur, -1);
05135          }
05136          ao2_ref(hint, -1);
05137       }
05138       ao2_unlock(hints);
05139    }
05140 
05141    return ret;
05142 }

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

05360 {
05361    return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
05362 }

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

References E_FINDLABEL, and pbx_extension_helper().

Referenced by pbx_load_config().

05365 {
05366    return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
05367 }

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

04132 {
04133    char *copy = ast_strdupa(function);
04134    char *args = func_args(copy);
04135    struct ast_custom_function *acfptr = ast_custom_function_find(copy);
04136    int res;
04137    struct ast_module_user *u = NULL;
04138 
04139    if (acfptr == NULL) {
04140       ast_log(LOG_ERROR, "Function %s not registered\n", copy);
04141    } else if (!acfptr->read && !acfptr->read2) {
04142       ast_log(LOG_ERROR, "Function %s cannot be read\n", copy);
04143    } else if (!is_read_allowed(acfptr)) {
04144       ast_log(LOG_ERROR, "Dangerous function %s read blocked\n", copy);
04145    } else if (acfptr->read) {
04146       if (acfptr->mod) {
04147          u = __ast_module_user_add(acfptr->mod, chan);
04148       }
04149       res = acfptr->read(chan, copy, args, workspace, len);
04150       if (acfptr->mod && u) {
04151          __ast_module_user_remove(acfptr->mod, u);
04152       }
04153       return res;
04154    } else {
04155       struct ast_str *str = ast_str_create(16);
04156       if (acfptr->mod) {
04157          u = __ast_module_user_add(acfptr->mod, chan);
04158       }
04159       res = acfptr->read2(chan, copy, args, &str, 0);
04160       if (acfptr->mod && u) {
04161          __ast_module_user_remove(acfptr->mod, u);
04162       }
04163       ast_copy_string(workspace, ast_str_buffer(str), len > ast_str_size(str) ? ast_str_size(str) : len);
04164       ast_free(str);
04165       return res;
04166    }
04167    return -1;
04168 }

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

04171 {
04172    char *copy = ast_strdupa(function);
04173    char *args = func_args(copy);
04174    struct ast_custom_function *acfptr = ast_custom_function_find(copy);
04175    int res;
04176    struct ast_module_user *u = NULL;
04177 
04178    if (acfptr == NULL) {
04179       ast_log(LOG_ERROR, "Function %s not registered\n", copy);
04180    } else if (!acfptr->read && !acfptr->read2) {
04181       ast_log(LOG_ERROR, "Function %s cannot be read\n", copy);
04182    } else if (!is_read_allowed(acfptr)) {
04183       ast_log(LOG_ERROR, "Dangerous function %s read blocked\n", copy);
04184    } else {
04185       if (acfptr->mod) {
04186          u = __ast_module_user_add(acfptr->mod, chan);
04187       }
04188       ast_str_reset(*str);
04189       if (acfptr->read2) {
04190          /* ast_str enabled */
04191          res = acfptr->read2(chan, copy, args, str, maxlen);
04192       } else {
04193          /* Legacy function pointer, allocate buffer for result */
04194          int maxsize = ast_str_size(*str);
04195          if (maxlen > -1) {
04196             if (maxlen == 0) {
04197                if (acfptr->read_max) {
04198                   maxsize = acfptr->read_max;
04199                } else {
04200                   maxsize = VAR_BUF_SIZE;
04201                }
04202             } else {
04203                maxsize = maxlen;
04204             }
04205             ast_str_make_space(str, maxsize);
04206          }
04207          res = acfptr->read(chan, copy, args, ast_str_buffer(*str), maxsize);
04208       }
04209       if (acfptr->mod && u) {
04210          __ast_module_user_remove(acfptr->mod, u);
04211       }
04212       return res;
04213    }
04214    return -1;
04215 }

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 4217 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(), is_write_allowed(), LOG_ERROR, ast_custom_function::mod, and ast_custom_function::write.

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

04218 {
04219    char *copy = ast_strdupa(function);
04220    char *args = func_args(copy);
04221    struct ast_custom_function *acfptr = ast_custom_function_find(copy);
04222 
04223    if (acfptr == NULL) {
04224       ast_log(LOG_ERROR, "Function %s not registered\n", copy);
04225    } else if (!acfptr->write) {
04226       ast_log(LOG_ERROR, "Function %s cannot be written to\n", copy);
04227    } else if (!is_write_allowed(acfptr)) {
04228       ast_log(LOG_ERROR, "Dangerous function %s write blocked\n", copy);
04229    } else {
04230       int res;
04231       struct ast_module_user *u = NULL;
04232       if (acfptr->mod)
04233          u = __ast_module_user_add(acfptr->mod, chan);
04234       res = acfptr->write(chan, copy, args, value);
04235       if (acfptr->mod && u)
04236          __ast_module_user_remove(acfptr->mod, u);
04237       return res;
04238    }
04239 
04240    return -1;
04241 }

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

Definition at line 10970 of file pbx.c.

References ast_context::registrar.

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

10971 {
10972    return c ? c->registrar : NULL;
10973 }

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

References ast_exten::cidmatch.

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

10996 {
10997    return e ? e->cidmatch : NULL;
10998 }

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

Definition at line 10937 of file pbx.c.

References ast_exten::parent.

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

10938 {
10939    return exten ? exten->parent : NULL;
10940 }

const char* ast_get_extension_label ( struct ast_exten e  ) 

Definition at line 10947 of file pbx.c.

References ast_exten::label.

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

10948 {
10949    return exten ? exten->label : NULL;
10950 }

int ast_get_extension_matchcid ( struct ast_exten e  ) 

Definition at line 10990 of file pbx.c.

References ast_exten::matchcid.

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

10991 {
10992    return e ? e->matchcid : 0;
10993 }

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

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

10963 {
10964    return exten ? exten->priority : -1;
10965 }

const char* ast_get_extension_registrar ( struct ast_exten e  ) 

Definition at line 10975 of file pbx.c.

References ast_exten::registrar.

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

10976 {
10977    return e ? e->registrar : NULL;
10978 }

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

05317 {
05318    struct ast_exten *e = ast_hint_extension(c, context, exten);
05319 
05320    if (e) {
05321       if (hint)
05322          ast_copy_string(hint, ast_get_extension_app(e), hintsize);
05323       if (name) {
05324          const char *tmp = ast_get_extension_app_data(e);
05325          if (tmp)
05326             ast_copy_string(name, tmp, namesize);
05327       }
05328       return -1;
05329    }
05330    return 0;
05331 }

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

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

10986 {
10987    return ip ? ip->registrar : NULL;
10988 }

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

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

10981 {
10982    return i ? i->registrar : NULL;
10983 }

const char* ast_get_switch_data ( struct ast_sw sw  ) 

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

11016 {
11017    return sw ? sw->data : NULL;
11018 }

int ast_get_switch_eval ( struct ast_sw sw  ) 

Definition at line 11020 of file pbx.c.

References ast_sw::eval.

Referenced by context_merge_incls_swits_igps_other_registrars().

11021 {
11022    return sw->eval;
11023 }

const char* ast_get_switch_name ( struct ast_sw sw  ) 

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

11011 {
11012    return sw ? sw->name : NULL;
11013 }

const char* ast_get_switch_registrar ( struct ast_sw sw  ) 

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

11026 {
11027    return sw ? sw->registrar : NULL;
11028 }

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 11120 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(), select_entry(), valid_exit(), vm_execmain(), and vmauthenticate().

11121 {
11122    return __ast_goto_if_exists(chan, context, exten, priority, 0);
11123 }

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

hashtable functions for contexts

Definition at line 1092 of file pbx.c.

References ast_context::name.

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

01093 {
01094    const struct ast_context *ac = ah_a;
01095    const struct ast_context *bc = ah_b;
01096    if (!ac || !bc) /* safety valve, but it might prevent a crash you'd rather have happen */
01097       return 1;
01098    /* assume context names are registered in a string table! */
01099    return strcmp(ac->name, bc->name);
01100 }

unsigned int ast_hashtab_hash_contexts ( const void *  obj  ) 

Definition at line 1144 of file pbx.c.

References ast_hashtab_hash_string(), and ast_context::name.

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

01145 {
01146    const struct ast_context *ac = obj;
01147    return ast_hashtab_hash_string(ac->name);
01148 }

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

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

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

08605 {
08606    struct ast_context *con = ast_context_find(context);
08607 
08608    if (con) {
08609       struct ast_ignorepat *pat;
08610 
08611       for (pat = con->ignorepats; pat; pat = pat->next) {
08612          if (ast_extension_match(pat->pattern, pattern))
08613             return 1;
08614       }
08615    }
08616 
08617    return 0;
08618 }

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 5374 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(), loopback_matchmore(), mgcp_ss(), pbx_builtin_background(), readexten_exec(), and skinny_ss().

05375 {
05376    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0);
05377 }

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

07892 {
07893    double ft;
07894    struct ast_context *tmp;
07895    struct ast_context *oldcontextslist;
07896    struct ast_hashtab *oldtable;
07897    struct store_hints hints_stored = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
07898    struct store_hints hints_removed = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
07899    struct store_hint *saved_hint;
07900    struct ast_hint *hint;
07901    struct ast_exten *exten;
07902    int length;
07903    struct ast_state_cb *thiscb;
07904    struct ast_hashtab_iter *iter;
07905    struct ao2_iterator i;
07906    struct timeval begintime;
07907    struct timeval writelocktime;
07908    struct timeval endlocktime;
07909    struct timeval enddeltime;
07910 
07911    /*
07912     * It is very important that this function hold the hints
07913     * container lock _and_ the conlock during its operation; not
07914     * only do we need to ensure that the list of contexts and
07915     * extensions does not change, but also that no hint callbacks
07916     * (watchers) are added or removed during the merge/delete
07917     * process
07918     *
07919     * In addition, the locks _must_ be taken in this order, because
07920     * there are already other code paths that use this order
07921     */
07922 
07923    begintime = ast_tvnow();
07924    ast_mutex_lock(&context_merge_lock);/* Serialize ast_merge_contexts_and_delete */
07925    ast_wrlock_contexts();
07926 
07927    if (!contexts_table) {
07928       /* Well, that's odd. There are no contexts. */
07929       contexts_table = exttable;
07930       contexts = *extcontexts;
07931       ast_unlock_contexts();
07932       ast_mutex_unlock(&context_merge_lock);
07933       return;
07934    }
07935 
07936    iter = ast_hashtab_start_traversal(contexts_table);
07937    while ((tmp = ast_hashtab_next(iter))) {
07938       context_merge(extcontexts, exttable, tmp, registrar);
07939    }
07940    ast_hashtab_end_traversal(iter);
07941 
07942    ao2_lock(hints);
07943    writelocktime = ast_tvnow();
07944 
07945    /* preserve all watchers for hints */
07946    i = ao2_iterator_init(hints, AO2_ITERATOR_DONTLOCK);
07947    for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
07948       if (ao2_container_count(hint->callbacks)) {
07949          ao2_lock(hint);
07950          if (!hint->exten) {
07951             /* The extension has already been destroyed. (Should never happen here) */
07952             ao2_unlock(hint);
07953             continue;
07954          }
07955 
07956          length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2
07957             + sizeof(*saved_hint);
07958          if (!(saved_hint = ast_calloc(1, length))) {
07959             ao2_unlock(hint);
07960             continue;
07961          }
07962 
07963          /* This removes all the callbacks from the hint into saved_hint. */
07964          while ((thiscb = ao2_callback(hint->callbacks, OBJ_UNLINK, NULL, NULL))) {
07965             AST_LIST_INSERT_TAIL(&saved_hint->callbacks, thiscb, entry);
07966             /*
07967              * We intentionally do not unref thiscb to account for the
07968              * non-ao2 reference in saved_hint->callbacks
07969              */
07970          }
07971 
07972          saved_hint->laststate = hint->laststate;
07973          saved_hint->context = saved_hint->data;
07974          strcpy(saved_hint->data, hint->exten->parent->name);
07975          saved_hint->exten = saved_hint->data + strlen(saved_hint->context) + 1;
07976          strcpy(saved_hint->exten, hint->exten->exten);
07977          ao2_unlock(hint);
07978          AST_LIST_INSERT_HEAD(&hints_stored, saved_hint, list);
07979       }
07980    }
07981    ao2_iterator_destroy(&i);
07982 
07983    /* save the old table and list */
07984    oldtable = contexts_table;
07985    oldcontextslist = contexts;
07986 
07987    /* move in the new table and list */
07988    contexts_table = exttable;
07989    contexts = *extcontexts;
07990 
07991    /*
07992     * Restore the watchers for hints that can be found; notify
07993     * those that cannot be restored.
07994     */
07995    while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_stored, list))) {
07996       struct pbx_find_info q = { .stacklen = 0 };
07997 
07998       exten = pbx_find_extension(NULL, NULL, &q, saved_hint->context, saved_hint->exten,
07999          PRIORITY_HINT, NULL, "", E_MATCH);
08000       /*
08001        * If this is a pattern, dynamically create a new extension for this
08002        * particular match.  Note that this will only happen once for each
08003        * individual extension, because the pattern will no longer match first.
08004        */
08005       if (exten && exten->exten[0] == '_') {
08006          ast_add_extension_nolock(exten->parent->name, 0, saved_hint->exten,
08007             PRIORITY_HINT, NULL, 0, exten->app, ast_strdup(exten->data), ast_free_ptr,
08008             exten->registrar);
08009          /* rwlocks are not recursive locks */
08010          exten = ast_hint_extension_nolock(NULL, saved_hint->context,
08011             saved_hint->exten);
08012       }
08013 
08014       /* Find the hint in the hints container */
08015       hint = exten ? ao2_find(hints, exten, 0) : NULL;
08016       if (!hint) {
08017          /*
08018           * Notify watchers of this removed hint later when we aren't
08019           * encumberd by so many locks.
08020           */
08021          AST_LIST_INSERT_HEAD(&hints_removed, saved_hint, list);
08022       } else {
08023          ao2_lock(hint);
08024          while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) {
08025             ao2_link(hint->callbacks, thiscb);
08026             /* Ref that we added when putting into saved_hint->callbacks */
08027             ao2_ref(thiscb, -1);
08028          }
08029          hint->laststate = saved_hint->laststate;
08030          ao2_unlock(hint);
08031          ao2_ref(hint, -1);
08032          ast_free(saved_hint);
08033       }
08034    }
08035 
08036    ao2_unlock(hints);
08037    ast_unlock_contexts();
08038 
08039    /*
08040     * Notify watchers of all removed hints with the same lock
08041     * environment as handle_statechange().
08042     */
08043    while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_removed, list))) {
08044       /* this hint has been removed, notify the watchers */
08045       while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) {
08046          thiscb->change_cb(saved_hint->context, saved_hint->exten,
08047             AST_EXTENSION_REMOVED, thiscb->data);
08048          /* Ref that we added when putting into saved_hint->callbacks */
08049          ao2_ref(thiscb, -1);
08050       }
08051       ast_free(saved_hint);
08052    }
08053 
08054    ast_mutex_unlock(&context_merge_lock);
08055    endlocktime = ast_tvnow();
08056 
08057    /*
08058     * The old list and hashtab no longer are relevant, delete them
08059     * while the rest of asterisk is now freely using the new stuff
08060     * instead.
08061     */
08062 
08063    ast_hashtab_destroy(oldtable, NULL);
08064 
08065    for (tmp = oldcontextslist; tmp; ) {
08066       struct ast_context *next;  /* next starting point */
08067 
08068       next = tmp->next;
08069       __ast_internal_context_destroy(tmp);
08070       tmp = next;
08071    }
08072    enddeltime = ast_tvnow();
08073 
08074    ft = ast_tvdiff_us(writelocktime, begintime);
08075    ft /= 1000000.0;
08076    ast_verb(3,"Time to scan old dialplan and merge leftovers back into the new: %8.6f sec\n", ft);
08077 
08078    ft = ast_tvdiff_us(endlocktime, writelocktime);
08079    ft /= 1000000.0;
08080    ast_verb(3,"Time to restore hints and swap in new dialplan: %8.6f sec\n", ft);
08081 
08082    ft = ast_tvdiff_us(enddeltime, endlocktime);
08083    ft /= 1000000.0;
08084    ast_verb(3,"Time to delete the old dialplan: %8.6f sec\n", ft);
08085 
08086    ft = ast_tvdiff_us(enddeltime, begintime);
08087    ft /= 1000000.0;
08088    ast_verb(3,"Total time merge_contexts_delete: %8.6f sec\n", ft);
08089 }

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

11186 {
11187    return pbx_parseable_goto(chan, goto_string, 0);
11188 }

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

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

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

09499 {
09500    struct ast_channel *chan;
09501    struct app_tmp *tmp;
09502    int res = -1, cdr_res = -1;
09503    struct outgoing_helper oh;
09504 
09505    memset(&oh, 0, sizeof(oh));
09506    oh.vars = vars;
09507    oh.account = account;
09508 
09509    if (locked_channel)
09510       *locked_channel = NULL;
09511    if (ast_strlen_zero(app)) {
09512       res = -1;
09513       goto outgoing_app_cleanup;
09514    }
09515    if (synchronous) {
09516       chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh);
09517       if (chan) {
09518          ast_set_variables(chan, vars);
09519          if (account)
09520             ast_cdr_setaccount(chan, account);
09521          if (chan->_state == AST_STATE_UP) {
09522             res = 0;
09523             ast_verb(4, "Channel %s was answered.\n", chan->name);
09524             tmp = ast_calloc(1, sizeof(*tmp));
09525             if (!tmp || ast_string_field_init(tmp, 252)) {
09526                if (tmp) {
09527                   ast_free(tmp);
09528                }
09529                res = -1;
09530             } else {
09531                ast_string_field_set(tmp, app, app);
09532                ast_string_field_set(tmp, data, appdata);
09533                tmp->chan = chan;
09534                if (synchronous > 1) {
09535                   if (locked_channel)
09536                      ast_channel_unlock(chan);
09537                   ast_pbx_run_app(tmp);
09538                } else {
09539                   if (locked_channel)
09540                      ast_channel_lock(chan);
09541                   if (ast_pthread_create_detached(&tmp->t, NULL, ast_pbx_run_app, tmp)) {
09542                      ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno));
09543                      ast_string_field_free_memory(tmp);
09544                      ast_free(tmp);
09545                      if (locked_channel)
09546                         ast_channel_unlock(chan);
09547                      ast_hangup(chan);
09548                      res = -1;
09549                   } else {
09550                      if (locked_channel)
09551                         *locked_channel = chan;
09552                   }
09553                }
09554             }
09555          } else {
09556             ast_verb(4, "Channel %s was never answered.\n", chan->name);
09557             if (chan->cdr) { /* update the cdr */
09558                /* here we update the status of the call, which sould be busy.
09559                 * if that fails then we set the status to failed */
09560                if (ast_cdr_disposition(chan->cdr, chan->hangupcause))
09561                   ast_cdr_failed(chan->cdr);
09562             }
09563             ast_hangup(chan);
09564          }
09565       }
09566 
09567       if (res < 0) { /* the call failed for some reason */
09568          if (*reason == 0) { /* if the call failed (not busy or no answer)
09569                         * update the cdr with the failed message */
09570             cdr_res = ast_pbx_outgoing_cdr_failed();
09571             if (cdr_res != 0) {
09572                res = cdr_res;
09573                goto outgoing_app_cleanup;
09574             }
09575          }
09576       }
09577 
09578    } else {
09579       struct async_stat *as;
09580       if (!(as = ast_calloc(1, sizeof(*as)))) {
09581          res = -1;
09582          goto outgoing_app_cleanup;
09583       }
09584       chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh);
09585       if (!chan) {
09586          ast_free(as);
09587          res = -1;
09588          goto outgoing_app_cleanup;
09589       }
09590       as->chan = chan;
09591       ast_copy_string(as->app, app, sizeof(as->app));
09592       if (appdata)
09593          ast_copy_string(as->appdata,  appdata, sizeof(as->appdata));
09594       as->timeout = timeout;
09595       ast_set_variables(chan, vars);
09596       if (account)
09597          ast_cdr_setaccount(chan, account);
09598       /* Start a new thread, and get something handling this channel. */
09599       if (locked_channel)
09600          ast_channel_lock(chan);
09601       if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) {
09602          ast_log(LOG_WARNING, "Failed to start async wait\n");
09603          ast_free(as);
09604          if (locked_channel)
09605             ast_channel_unlock(chan);
09606          ast_hangup(chan);
09607          res = -1;
09608          goto outgoing_app_cleanup;
09609       } else {
09610          if (locked_channel)
09611             *locked_channel = chan;
09612       }
09613       res = 0;
09614    }
09615 outgoing_app_cleanup:
09616    ast_variables_destroy(vars);
09617    return res;
09618 }

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

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

Definition at line 9329 of file pbx.c.

References __ast_request_and_dial(), ast_channel::_state, outgoing_helper::account, ast_calloc, ast_cdr_disposition(), ast_cdr_failed(), ast_cdr_setaccount(), ast_channel_alloc, ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_exists_extension(), ast_free, ast_hangup(), ast_log(), ast_pbx_outgoing_cdr_failed(), ast_pbx_run(), ast_pbx_start(), ast_pthread_create_detached, ast_request_and_dial(), ast_set_variables(), AST_STATE_DOWN, AST_STATE_UP, ast_strlen_zero(), ast_variables_destroy(), ast_verb, async_wait(), ast_channel::cdr, async_stat::chan, outgoing_helper::cid_name, outgoing_helper::cid_num, async_stat::context, ast_channel::context, outgoing_helper::context, outgoing_helper::exten, ast_channel::hangupcause, LOG_ERROR, LOG_WARNING, 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().

09330 {
09331    struct ast_channel *chan;
09332    struct async_stat *as;
09333    int res = -1, cdr_res = -1;
09334    struct outgoing_helper oh;
09335 
09336    if (synchronous) {
09337       oh.context = context;
09338       oh.exten = exten;
09339       oh.priority = priority;
09340       oh.cid_num = cid_num;
09341       oh.cid_name = cid_name;
09342       oh.account = account;
09343       oh.vars = vars;
09344       oh.parent_channel = NULL;
09345 
09346       chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh);
09347       if (channel) {
09348          *channel = chan;
09349          if (chan)
09350             ast_channel_lock(chan);
09351       }
09352       if (chan) {
09353          if (chan->_state == AST_STATE_UP) {
09354                res = 0;
09355             ast_verb(4, "Channel %s was answered.\n", chan->name);
09356 
09357             if (synchronous > 1) {
09358                if (channel)
09359                   ast_channel_unlock(chan);
09360                if (ast_pbx_run(chan)) {
09361                   ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name);
09362                   if (channel)
09363                      *channel = NULL;
09364                   ast_hangup(chan);
09365                   chan = NULL;
09366                   res = -1;
09367                }
09368             } else {
09369                if (ast_pbx_start(chan)) {
09370                   ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name);
09371                   if (channel) {
09372                      *channel = NULL;
09373                      ast_channel_unlock(chan);
09374                   }
09375                   ast_hangup(chan);
09376                   res = -1;
09377                }
09378                chan = NULL;
09379             }
09380          } else {
09381             ast_verb(4, "Channel %s was never answered.\n", chan->name);
09382 
09383             if (chan->cdr) { /* update the cdr */
09384                /* here we update the status of the call, which sould be busy.
09385                 * if that fails then we set the status to failed */
09386                if (ast_cdr_disposition(chan->cdr, chan->hangupcause))
09387                   ast_cdr_failed(chan->cdr);
09388             }
09389 
09390             if (channel) {
09391                *channel = NULL;
09392                ast_channel_unlock(chan);
09393             }
09394             ast_hangup(chan);
09395             chan = NULL;
09396          }
09397       }
09398 
09399       if (res < 0) { /* the call failed for some reason */
09400          if (*reason == 0) { /* if the call failed (not busy or no answer)
09401                         * update the cdr with the failed message */
09402             cdr_res = ast_pbx_outgoing_cdr_failed();
09403             if (cdr_res != 0) {
09404                res = cdr_res;
09405                goto outgoing_exten_cleanup;
09406             }
09407          }
09408 
09409          /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */
09410          /* check if "failed" exists */
09411          if (ast_exists_extension(chan, context, "failed", 1, NULL)) {
09412             chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", NULL, 0, "OutgoingSpoolFailed");
09413             if (chan) {
09414                char failed_reason[4] = "";
09415                if (!ast_strlen_zero(context))
09416                   ast_copy_string(chan->context, context, sizeof(chan->context));
09417                set_ext_pri(chan, "failed", 1);
09418                ast_set_variables(chan, vars);
09419                snprintf(failed_reason, sizeof(failed_reason), "%d", *reason);
09420                pbx_builtin_setvar_helper(chan, "REASON", failed_reason);
09421                if (account)
09422                   ast_cdr_setaccount(chan, account);
09423                if (ast_pbx_run(chan)) {
09424                   ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name);
09425                   ast_hangup(chan);
09426                }
09427                chan = NULL;
09428             }
09429          }
09430       }
09431    } else {
09432       if (!(as = ast_calloc(1, sizeof(*as)))) {
09433          res = -1;
09434          goto outgoing_exten_cleanup;
09435       }
09436       chan = ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name);
09437       if (channel) {
09438          *channel = chan;
09439          if (chan)
09440             ast_channel_lock(chan);
09441       }
09442       if (!chan) {
09443          ast_free(as);
09444          res = -1;
09445          goto outgoing_exten_cleanup;
09446       }
09447       as->chan = chan;
09448       ast_copy_string(as->context, context, sizeof(as->context));
09449       set_ext_pri(as->chan,  exten, priority);
09450       as->timeout = timeout;
09451       ast_set_variables(chan, vars);
09452       if (account)
09453          ast_cdr_setaccount(chan, account);
09454       if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) {
09455          ast_log(LOG_WARNING, "Failed to start async wait\n");
09456          ast_free(as);
09457          if (channel) {
09458             *channel = NULL;
09459             ast_channel_unlock(chan);
09460          }
09461          ast_hangup(chan);
09462          res = -1;
09463          goto outgoing_exten_cleanup;
09464       }
09465       res = 0;
09466    }
09467 outgoing_exten_cleanup:
09468    ast_variables_destroy(vars);
09469    return res;
09470 }

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

05881 {
05882    return ast_pbx_run_args(c, NULL);
05883 }

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 5860 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 ast_pbx_run(), dial_exec_full(), handle_gosub(), and try_calling().

05861 {
05862    enum ast_pbx_result res = AST_PBX_SUCCESS;
05863 
05864    if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) {
05865       ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n");
05866       return AST_PBX_FAILED;
05867    }
05868 
05869    if (increase_call_count(c)) {
05870       return AST_PBX_CALL_LIMIT;
05871    }
05872 
05873    res = __ast_pbx_run(c, args);
05874 
05875    decrease_call_count();
05876 
05877    return res;
05878 }

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 5833 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(), skinny_new(), and unistim_new().

05834 {
05835    pthread_t t;
05836 
05837    if (!c) {
05838       ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
05839       return AST_PBX_FAILED;
05840    }
05841 
05842    if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) {
05843       ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n");
05844       return AST_PBX_FAILED;
05845    }
05846 
05847    if (increase_call_count(c))
05848       return AST_PBX_CALL_LIMIT;
05849 
05850    /* Start a new thread, and get something handling this channel. */
05851    if (ast_pthread_create_detached(&t, NULL, pbx_thread, c)) {
05852       ast_log(LOG_WARNING, "Failed to create new channel thread\n");
05853       decrease_call_count();
05854       return AST_PBX_FAILED;
05855    }
05856 
05857    return AST_PBX_SUCCESS;
05858 }

int ast_processed_calls ( void   ) 

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

Definition at line 5890 of file pbx.c.

References totalcalls.

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

05891 {
05892    return totalcalls;
05893 }

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

10920 {
10921    return ast_rwlock_rdlock(&con->lock);
10922 }

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

06394 {
06395    struct ast_switch *tmp;
06396 
06397    AST_RWLIST_WRLOCK(&switches);
06398    AST_RWLIST_TRAVERSE(&switches, tmp, list) {
06399       if (!strcasecmp(tmp->name, sw->name)) {
06400          AST_RWLIST_UNLOCK(&switches);
06401          ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name);
06402          return -1;
06403       }
06404    }
06405    AST_RWLIST_INSERT_TAIL(&switches, sw, list);
06406    AST_RWLIST_UNLOCK(&switches);
06407 
06408    return 0;
06409 }

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

References E_SPAWN, and pbx_extension_helper().

Referenced by __ast_pbx_run(), _macro_exec(), ast_bridge_call(), dial_exec_full(), gosub_run(), and loopback_exec().

05380 {
05381    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN, found, combined_find_spawn);
05382 }

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

05335 {
05336    struct ast_exten *e = ast_hint_extension(c, context, exten);
05337 
05338    if (!e) {
05339       return 0;
05340    }
05341 
05342    if (hint) {
05343       ast_str_set(hint, hintsize, "%s", ast_get_extension_app(e));
05344    }
05345    if (name) {
05346       const char *tmp = ast_get_extension_app_data(e);
05347       if (tmp) {
05348          ast_str_set(name, namesize, "%s", tmp);
05349       }
05350    }
05351    return -1;
05352 }

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

References ast_party_caller::ani2, ARRAY_LEN, ast_channel_lock, ast_channel_unlock, ast_config_AST_SYSTEM_NAME, ast_debug, ast_eid_default, ast_eid_to_str(), AST_LIST_TRAVERSE, ast_party_id_presentation(), ast_rwlock_rdlock, ast_rwlock_unlock, ast_str_buffer(), ast_str_get_hint(), ast_str_set(), ast_str_substring(), ast_strdupa, ast_var_name(), ast_var_value(), ast_channel::caller, ast_channel::context, ast_channel::dialed, ast_channel::exten, globals, globalslock, ast_channel::hangupcause, ast_party_caller::id, ast_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().

03400 {
03401    const char not_found = '\0';
03402    char *tmpvar;
03403    const char *ret;
03404    const char *s; /* the result */
03405    int offset, length;
03406    int i, need_substring;
03407    struct varshead *places[2] = { headp, &globals };  /* list of places where we may look */
03408    char workspace[20];
03409 
03410    if (c) {
03411       ast_channel_lock(c);
03412       places[0] = &c->varshead;
03413    }
03414    /*
03415     * Make a copy of var because parse_variable_name() modifies the string.
03416     * Then if called directly, we might need to run substring() on the result;
03417     * remember this for later in 'need_substring', 'offset' and 'length'
03418     */
03419    tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */
03420    need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */);
03421 
03422    /*
03423     * Look first into predefined variables, then into variable lists.
03424     * Variable 's' points to the result, according to the following rules:
03425     * s == &not_found (set at the beginning) means that we did not find a
03426     * matching variable and need to look into more places.
03427     * If s != &not_found, s is a valid result string as follows:
03428     * s = NULL if the variable does not have a value;
03429     * you typically do this when looking for an unset predefined variable.
03430     * s = workspace if the result has been assembled there;
03431     * typically done when the result is built e.g. with an snprintf(),
03432     * so we don't need to do an additional copy.
03433     * s != workspace in case we have a string, that needs to be copied
03434     * (the ast_copy_string is done once for all at the end).
03435     * Typically done when the result is already available in some string.
03436     */
03437    s = &not_found;   /* default value */
03438    if (c) { /* This group requires a valid channel */
03439       /* Names with common parts are looked up a piece at a time using strncmp. */
03440       if (!strncmp(var, "CALL", 4)) {
03441          if (!strncmp(var + 4, "ING", 3)) {
03442             if (!strcmp(var + 7, "PRES")) {        /* CALLINGPRES */
03443                ast_str_set(str, maxlen, "%d",
03444                   ast_party_id_presentation(&c->caller.id));
03445                s = ast_str_buffer(*str);
03446             } else if (!strcmp(var + 7, "ANI2")) {    /* CALLINGANI2 */
03447                ast_str_set(str, maxlen, "%d", c->caller.ani2);
03448                s = ast_str_buffer(*str);
03449             } else if (!strcmp(var + 7, "TON")) {     /* CALLINGTON */
03450                ast_str_set(str, maxlen, "%d", c->caller.id.number.plan);
03451                s = ast_str_buffer(*str);
03452             } else if (!strcmp(var + 7, "TNS")) {     /* CALLINGTNS */
03453                ast_str_set(str, maxlen, "%d", c->dialed.transit_network_select);
03454                s = ast_str_buffer(*str);
03455             }
03456          }
03457       } else if (!strcmp(var, "HINT")) {
03458          s = ast_str_get_hint(str, maxlen, NULL, 0, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL;
03459       } else if (!strcmp(var, "HINTNAME")) {
03460          s = ast_str_get_hint(NULL, 0, str, maxlen, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL;
03461       } else if (!strcmp(var, "EXTEN")) {
03462          s = c->exten;
03463       } else if (!strcmp(var, "CONTEXT")) {
03464          s = c->context;
03465       } else if (!strcmp(var, "PRIORITY")) {
03466          ast_str_set(str, maxlen, "%d", c->priority);
03467          s = ast_str_buffer(*str);
03468       } else if (!strcmp(var, "CHANNEL")) {
03469          s = c->name;
03470       } else if (!strcmp(var, "UNIQUEID")) {
03471          s = c->uniqueid;
03472       } else if (!strcmp(var, "HANGUPCAUSE")) {
03473          ast_str_set(str, maxlen, "%d", c->hangupcause);
03474          s = ast_str_buffer(*str);
03475       }
03476    }
03477    if (s == &not_found) { /* look for more */
03478       if (!strcmp(var, "EPOCH")) {
03479          ast_str_set(str, maxlen, "%d", (int) time(NULL));
03480          s = ast_str_buffer(*str);
03481       } else if (!strcmp(var, "SYSTEMNAME")) {
03482          s = ast_config_AST_SYSTEM_NAME;
03483       } else if (!strcmp(var, "ENTITYID")) {
03484          ast_eid_to_str(workspace, sizeof(workspace), &ast_eid_default);
03485          s = workspace;
03486       }
03487    }
03488    /* if not found, look into chanvars or global vars */
03489    for (i = 0; s == &not_found && i < ARRAY_LEN(places); i++) {
03490       struct ast_var_t *variables;
03491       if (!places[i])
03492          continue;
03493       if (places[i] == &globals)
03494          ast_rwlock_rdlock(&globalslock);
03495       AST_LIST_TRAVERSE(places[i], variables, entries) {
03496          if (!strcasecmp(ast_var_name(variables), var)) {
03497             s = ast_var_value(variables);
03498             break;
03499          }
03500       }
03501       if (places[i] == &globals)
03502          ast_rwlock_unlock(&globalslock);
03503    }
03504    if (s == &not_found || s == NULL) {
03505       ast_debug(5, "Result of '%s' is NULL\n", var);
03506       ret = NULL;
03507    } else {
03508       ast_debug(5, "Result of '%s' is '%s'\n", var, s);
03509       if (s != ast_str_buffer(*str)) {
03510          ast_str_set(str, maxlen, "%s", s);
03511       }
03512       ret = ast_str_buffer(*str);
03513       if (need_substring) {
03514          ret = ast_str_substring(*str, offset, length);
03515          ast_debug(2, "Final result of '%s' is '%s'\n", var, ret);
03516       }
03517    }
03518 
03519    if (c) {
03520       ast_channel_unlock(c);
03521    }
03522    return ret;
03523 }

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 4422 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(), exec_exec(), func_mchan_read(), function_eval2(), function_fieldnum_helper(), function_fieldqty_helper(), handle_getvariablefull(), import_helper(), listfilter(), make_email_file(), realtime_curl(), realtime_multi_curl(), replace(), require_curl(), sendmail(), sendpage(), shift_pop(), store_curl(), syslog_log(), tryexec_exec(), unshift_push(), update2_curl(), and update_curl().

04423 {
04424    size_t used;
04425    ast_str_substitute_variables_full(buf, maxlen, chan, NULL, templ, &used);
04426 }

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

04244 {
04245    /* Substitutes variables into buf, based on string templ */
04246    char *cp4 = NULL;
04247    const char *tmp, *whereweare;
04248    int orig_size = 0;
04249    int offset, offset2, isfunction;
04250    const char *nextvar, *nextexp, *nextthing;
04251    const char *vars, *vare;
04252    char *finalvars;
04253    int pos, brackets, needsub, len;
04254    struct ast_str *substr1 = ast_str_create(16), *substr2 = NULL, *substr3 = ast_str_create(16);
04255 
04256    ast_str_reset(*buf);
04257    whereweare = tmp = templ;
04258    while (!ast_strlen_zero(whereweare)) {
04259       /* reset our buffer */
04260       ast_str_reset(substr3);
04261 
04262       /* Assume we're copying the whole remaining string */
04263       pos = strlen(whereweare);
04264       nextvar = NULL;
04265       nextexp = NULL;
04266       nextthing = strchr(whereweare, '$');
04267       if (nextthing) {
04268          switch (nextthing[1]) {
04269          case '{':
04270             nextvar = nextthing;
04271             pos = nextvar - whereweare;
04272             break;
04273          case '[':
04274             nextexp = nextthing;
04275             pos = nextexp - whereweare;
04276             break;
04277          default:
04278             pos = 1;
04279          }
04280       }
04281 
04282       if (pos) {
04283          /* Copy that many bytes */
04284          ast_str_append_substr(buf, maxlen, whereweare, pos);
04285 
04286          templ += pos;
04287          whereweare += pos;
04288       }
04289 
04290       if (nextvar) {
04291          /* We have a variable.  Find the start and end, and determine
04292             if we are going to have to recursively call ourselves on the
04293             contents */
04294          vars = vare = nextvar + 2;
04295          brackets = 1;
04296          needsub = 0;
04297 
04298          /* Find the end of it */
04299          while (brackets && *vare) {
04300             if ((vare[0] == '$') && (vare[1] == '{')) {
04301                needsub++;
04302             } else if (vare[0] == '{') {
04303                brackets++;
04304             } else if (vare[0] == '}') {
04305                brackets--;
04306             } else if ((vare[0] == '$') && (vare[1] == '['))
04307                needsub++;
04308             vare++;
04309          }
04310          if (brackets)
04311             ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n");
04312          len = vare - vars - 1;
04313 
04314          /* Skip totally over variable string */
04315          whereweare += (len + 3);
04316 
04317          /* Store variable name (and truncate) */
04318          ast_str_set_substr(&substr1, 0, vars, len);
04319          ast_debug(5, "Evaluating '%s' (from '%s' len %d)\n", ast_str_buffer(substr1), vars, len);
04320 
04321          /* Substitute if necessary */
04322          if (needsub) {
04323             size_t used;
04324             if (!substr2) {
04325                substr2 = ast_str_create(16);
04326             }
04327 
04328             ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used);
04329             finalvars = ast_str_buffer(substr2);
04330          } else {
04331             finalvars = ast_str_buffer(substr1);
04332          }
04333 
04334          parse_variable_name(finalvars, &offset, &offset2, &isfunction);
04335          if (isfunction) {
04336             /* Evaluate function */
04337             if (c || !headp) {
04338                cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3);
04339             } else {
04340                struct varshead old;
04341                struct ast_channel *bogus = ast_dummy_channel_alloc();
04342                if (bogus) {
04343                   memcpy(&old, &bogus->varshead, sizeof(old));
04344                   memcpy(&bogus->varshead, headp, sizeof(bogus->varshead));
04345                   cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3);
04346                   /* Don't deallocate the varshead that was passed in */
04347                   memcpy(&bogus->varshead, &old, sizeof(bogus->varshead));
04348                   ast_channel_unref(bogus);
04349                } else {
04350                   ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution.  Function results may be blank.\n");
04351                }
04352             }
04353             ast_debug(2, "Function %s result is '%s'\n", finalvars, cp4 ? cp4 : "(null)");
04354          } else {
04355             /* Retrieve variable value */
04356             ast_str_retrieve_variable(&substr3, 0, c, headp, finalvars);
04357             cp4 = ast_str_buffer(substr3);
04358          }
04359          if (cp4) {
04360             ast_str_substring(substr3, offset, offset2);
04361             ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3));
04362          }
04363       } else if (nextexp) {
04364          /* We have an expression.  Find the start and end, and determine
04365             if we are going to have to recursively call ourselves on the
04366             contents */
04367          vars = vare = nextexp + 2;
04368          brackets = 1;
04369          needsub = 0;
04370 
04371          /* Find the end of it */
04372          while (brackets && *vare) {
04373             if ((vare[0] == '$') && (vare[1] == '[')) {
04374                needsub++;
04375                brackets++;
04376                vare++;
04377             } else if (vare[0] == '[') {
04378                brackets++;
04379             } else if (vare[0] == ']') {
04380                brackets--;
04381             } else if ((vare[0] == '$') && (vare[1] == '{')) {
04382                needsub++;
04383                vare++;
04384             }
04385             vare++;
04386          }
04387          if (brackets)
04388             ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n");
04389          len = vare - vars - 1;
04390 
04391          /* Skip totally over expression */
04392          whereweare += (len + 3);
04393 
04394          /* Store variable name (and truncate) */
04395          ast_str_set_substr(&substr1, 0, vars, len);
04396 
04397          /* Substitute if necessary */
04398          if (needsub) {
04399             size_t used;
04400             if (!substr2) {
04401                substr2 = ast_str_create(16);
04402             }
04403 
04404             ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used);
04405             finalvars = ast_str_buffer(substr2);
04406          } else {
04407             finalvars = ast_str_buffer(substr1);
04408          }
04409 
04410          if (ast_str_expr(&substr3, 0, c, finalvars)) {
04411             ast_debug(2, "Expression result is '%s'\n", ast_str_buffer(substr3));
04412          }
04413          ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3));
04414       }
04415    }
04416    *used = ast_str_strlen(*buf) - orig_size;
04417    ast_free(substr1);
04418    ast_free(substr2);
04419    ast_free(substr3);
04420 }

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

04429 {
04430    size_t used;
04431    ast_str_substitute_variables_full(buf, maxlen, NULL, headp, templ, &used);
04432 }

int ast_thread_inhibit_escalations ( void   ) 

Inhibit (in the current thread) the execution of dialplan functions which cause privilege escalations. If pbx_live_dangerously() has been called, this function has no effect.

Returns:
0 if successfuly marked current thread.
Non-zero if marking current thread failed.

Definition at line 4026 of file pbx.c.

References ast_log(), ast_threadstorage_get(), LOG_ERROR, and thread_inhibit_escalations_tl.

Referenced by handle_tcptls_connection().

04027 {
04028    int *thread_inhibit_escalations;
04029 
04030    thread_inhibit_escalations = ast_threadstorage_get(
04031       &thread_inhibit_escalations_tl, sizeof(*thread_inhibit_escalations));
04032 
04033    if (thread_inhibit_escalations == NULL) {
04034       ast_log(LOG_ERROR, "Error inhibiting privilege escalations for current thread\n");
04035       return -1;
04036    }
04037 
04038    *thread_inhibit_escalations = 1;
04039    return 0;
04040 }

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

References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

Referenced by __unload_module(), and unload_module().

06412 {
06413    AST_RWLIST_WRLOCK(&switches);
06414    AST_RWLIST_REMOVE(&switches, sw, list);
06415    AST_RWLIST_UNLOCK(&switches);
06416 }

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

Definition at line 11071 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(), context_used(), handle_cli_dialplan_save(), lookup_c_ip(), manager_show_dialplan_helper(), and show_dialplan_helper().

11073 {
11074    if (!ip)
11075       return con ? con->ignorepats : NULL;
11076    else
11077       return ip->next;
11078 }

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

References ast_context::alts, AST_LIST_FIRST, and AST_LIST_NEXT.

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

11049 {
11050    if (!sw)
11051       return con ? AST_LIST_FIRST(&con->alts) : NULL;
11052    else
11053       return AST_LIST_NEXT(sw, list);
11054 }

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

11058 {
11059    return priority ? priority->peer : exten;
11060 }

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

10915 {
10916    return ast_rwlock_wrlock(&con->lock);
10917 }

int ast_wrlock_contexts ( void   ) 

Write locks the context list.

Return values:
0 on success
-1 on error

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

10897 {
10898    return ast_mutex_lock(&conlock);
10899 }

void pbx_builtin_clear_globals ( void   ) 

Definition at line 10663 of file pbx.c.

References AST_LIST_REMOVE_HEAD, ast_rwlock_unlock, ast_rwlock_wrlock, ast_var_delete(), globals, and globalslock.

Referenced by handle_cli_dialplan_reload(), pbx_shutdown(), and reload().

10664 {
10665    struct ast_var_t *vardata;
10666 
10667    ast_rwlock_wrlock(&globalslock);
10668    while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries)))
10669       ast_var_delete(vardata);
10670    ast_rwlock_unlock(&globalslock);
10671 }

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 10429 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(), confbridge_exec(), 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(), gosub_run(), handle_gosub(), hash_read(), iax2_call(), iax2_exec(), import_ch(), leave_voicemail(), local_attended_transfer(), local_hangup(), local_read(), login_exec(), macro_fixup(), meetme_menu_admin_extended(), minivm_delete_exec(), minivm_notify_exec(), misdn_answer(), misdn_hangup(), morsecode_exec(), notify_new_message(), oh323_call(), oh323_hangup(), park_call_exec(), 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(), sip_addheader(), sla_trunk_exec(), speech_background(), try_calling(), try_suggested_sip_codec(), update_bridge_vars(), and wait_for_answer().

10430 {
10431    struct ast_var_t *variables;
10432    const char *ret = NULL;
10433    int i;
10434    struct varshead *places[2] = { NULL, &globals };
10435 
10436    if (!name)
10437       return NULL;
10438 
10439    if (chan) {
10440       ast_channel_lock(chan);
10441       places[0] = &chan->varshead;
10442    }
10443 
10444    for (i = 0; i < 2; i++) {
10445       if (!places[i])
10446          continue;
10447       if (places[i] == &globals)
10448          ast_rwlock_rdlock(&globalslock);
10449       AST_LIST_TRAVERSE(places[i], variables, entries) {
10450          if (!strcmp(name, ast_var_name(variables))) {
10451             ret = ast_var_value(variables);
10452             break;
10453          }
10454       }
10455       if (places[i] == &globals)
10456          ast_rwlock_unlock(&globalslock);
10457       if (ret)
10458          break;
10459    }
10460 
10461    if (chan)
10462       ast_channel_unlock(chan);
10463 
10464    return ret;
10465 }

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

10468 {
10469    struct ast_var_t *newvariable;
10470    struct varshead *headp;
10471 
10472    if (name[strlen(name)-1] == ')') {
10473       char *function = ast_strdupa(name);
10474 
10475       ast_log(LOG_WARNING, "Cannot push a value onto a function\n");
10476       ast_func_write(chan, function, value);
10477       return;
10478    }
10479 
10480    if (chan) {
10481       ast_channel_lock(chan);
10482       headp = &chan->varshead;
10483    } else {
10484       ast_rwlock_wrlock(&globalslock);
10485       headp = &globals;
10486    }
10487 
10488    if (value && (newvariable = ast_var_assign(name, value))) {
10489       if (headp == &globals)
10490          ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value);
10491       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
10492    }
10493 
10494    if (chan)
10495       ast_channel_unlock(chan);
10496    else
10497       ast_rwlock_unlock(&globalslock);
10498 }

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

Definition at line 3574 of file pbx.c.

References raise_exception().

03575 {
03576    /* Priority will become 1, next time through the AUTOLOOP */
03577    return raise_exception(chan, reason, 0);
03578 }

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 10398 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(), LOG_ERROR, total, var, and ast_channel::varshead.

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

10399 {
10400    struct ast_var_t *variables;
10401    const char *var, *val;
10402    int total = 0;
10403 
10404    if (!chan)
10405       return 0;
10406 
10407    ast_str_reset(*buf);
10408 
10409    ast_channel_lock(chan);
10410 
10411    AST_LIST_TRAVERSE(&chan->varshead, variables, entries) {
10412       if ((var = ast_var_name(variables)) && (val = ast_var_value(variables))
10413          /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */
10414          ) {
10415          if (ast_str_append(buf, 0, "%s=%s\n", var, val) < 0) {
10416             ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
10417             break;
10418          } else
10419             total++;
10420       } else
10421          break;
10422    }
10423 
10424    ast_channel_unlock(chan);
10425 
10426    return total;
10427 }

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 10557 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(), and value.

Referenced by ast_compile_ael2().

10558 {
10559    char *name, *value, *mydata;
10560 
10561    if (ast_compat_app_set) {
10562       return pbx_builtin_setvar_multiple(chan, data);
10563    }
10564 
10565    if (ast_strlen_zero(data)) {
10566       ast_log(LOG_WARNING, "Set requires one variable name/value pair.\n");
10567       return 0;
10568    }
10569 
10570    mydata = ast_strdupa(data);
10571    name = strsep(&mydata, "=");
10572    value = mydata;
10573    if (!value) {
10574       ast_log(LOG_WARNING, "Set requires an '=' to be a valid assignment.\n");
10575       return 0;
10576    }
10577 
10578    if (strchr(name, ' ')) {
10579       ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, mydata);
10580    }
10581 
10582    pbx_builtin_setvar_helper(chan, name, value);
10583 
10584    return 0;
10585 }

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

References ast_channel_lock, ast_channel_unlock, ast_func_write(), AST_LIST_INSERT_HEAD, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_rwlock_unlock, ast_rwlock_wrlock, ast_strdupa, ast_var_assign(), ast_var_delete(), ast_var_name(), ast_verb, EVENT_FLAG_DIALPLAN, globals, globalslock, manager_event, 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(), 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_waiting(), end_bridge_callback(), export_aoc_vars(), export_ch(), feature_exec_app(), feature_request_and_dial(), frame_set_var(), func_mchan_write(), function_db_delete(), function_db_exists(), function_db_read(), function_realtime_store(), generic_recall(), get_rdnis(), get_refer_info(), global_write(), gosub_release_frame(), gosub_run(), handle_gosub(), handle_incoming(), handle_request_bye(), handle_request_refer(), handle_set_chanvar(), handle_set_global(), handle_setvariable(), hash_read(), hash_write(), isAnsweringMachine(), leave_queue(), leave_voicemail(), local_hangup(), lua_set_variable(), lua_set_variable_value(), macro_fixup(), manage_parked_call(), mgcp_new(), minivm_accmess_exec(), minivm_delete_exec(), minivm_greet_exec(), minivm_notify_exec(), minivm_record_exec(), misdn_call(), mixmonitor_exec(), my_handle_dtmf(), originate_exec(), ospauth_exec(), ospfinished_exec(), osplookup_exec(), ospnext_exec(), park_call_full(), 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(), ring_entry(), rollback_exec(), rotate_file(), rqm_exec(), sendfax_exec(), sendimage_exec(), sendtext_exec(), sendurl_exec(), set(), set_channel_variables(), set_queue_result(), 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().

10501 {
10502    struct ast_var_t *newvariable;
10503    struct varshead *headp;
10504    const char *nametail = name;
10505 
10506    if (name[strlen(name) - 1] == ')') {
10507       char *function = ast_strdupa(name);
10508 
10509       return ast_func_write(chan, function, value);
10510    }
10511 
10512    if (chan) {
10513       ast_channel_lock(chan);
10514       headp = &chan->varshead;
10515    } else {
10516       ast_rwlock_wrlock(&globalslock);
10517       headp = &globals;
10518    }
10519 
10520    /* For comparison purposes, we have to strip leading underscores */
10521    if (*nametail == '_') {
10522       nametail++;
10523       if (*nametail == '_')
10524          nametail++;
10525    }
10526 
10527    AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) {
10528       if (strcmp(ast_var_name(newvariable), nametail) == 0) {
10529          /* there is already such a variable, delete it */
10530          AST_LIST_REMOVE_CURRENT(entries);
10531          ast_var_delete(newvariable);
10532          break;
10533       }
10534    }
10535    AST_LIST_TRAVERSE_SAFE_END;
10536 
10537    if (value && (newvariable = ast_var_assign(name, value))) {
10538       if (headp == &globals)
10539          ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value);
10540       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
10541       manager_event(EVENT_FLAG_DIALPLAN, "VarSet",
10542          "Channel: %s\r\n"
10543          "Variable: %s\r\n"
10544          "Value: %s\r\n"
10545          "Uniqueid: %s\r\n",
10546          chan ? chan->name : "none", name, value,
10547          chan ? chan->uniqueid : "none");
10548    }
10549 
10550    if (chan)
10551       ast_channel_unlock(chan);
10552    else
10553       ast_rwlock_unlock(&globalslock);
10554    return 0;
10555 }

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

10588 {
10589    char *data;
10590    int x;
10591    AST_DECLARE_APP_ARGS(args,
10592       AST_APP_ARG(pair)[24];
10593    );
10594    AST_DECLARE_APP_ARGS(pair,
10595       AST_APP_ARG(name);
10596       AST_APP_ARG(value);
10597    );
10598 
10599    if (ast_strlen_zero(vdata)) {
10600       ast_log(LOG_WARNING, "MSet requires at least one variable name/value pair.\n");
10601       return 0;
10602    }
10603 
10604    data = ast_strdupa(vdata);
10605    AST_STANDARD_APP_ARGS(args, data);
10606 
10607    for (x = 0; x < args.argc; x++) {
10608       AST_NONSTANDARD_APP_ARGS(pair, args.pair[x], '=');
10609       if (pair.argc == 2) {
10610          pbx_builtin_setvar_helper(chan, pair.name, pair.value);
10611          if (strchr(pair.name, ' '))
10612             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);
10613       } else if (!chan) {
10614          ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '='\n", pair.name);
10615       } else {
10616          ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '=' (in %s@%s:%d\n", pair.name, chan->exten, chan->context, chan->priority);
10617       }
10618    }
10619 
10620    return 0;
10621 }

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

10674 {
10675    int res;
10676    if (ast_strlen_zero(condition)) {                /* NULL or empty strings are false */
10677       return 0;
10678    } else if (sscanf(condition, "%30d", &res) == 1) { /* Numbers are evaluated for truth */
10679       return res;
10680    } else {                                         /* Strings are true */
10681       return 1;
10682    }
10683 }

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 1451 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_exec_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(), iax2_exec(), lua_pbx_exec(), page_exec(), pbx_builtin_execiftime(), pbx_extension_helper(), realtime_exec(), try_calling(), and tryexec_exec().

01454 {
01455    int res;
01456    struct ast_module_user *u = NULL;
01457    const char *saved_c_appl;
01458    const char *saved_c_data;
01459 
01460    if (c->cdr && !ast_check_hangup(c))
01461       ast_cdr_setapp(c->cdr, app->name, data);
01462 
01463    /* save channel values */
01464    saved_c_appl= c->appl;
01465    saved_c_data= c->data;
01466 
01467    c->appl = app->name;
01468    c->data = data;
01469    ast_cel_report_event(c, AST_CEL_APP_START, NULL, NULL, NULL);
01470 
01471    if (app->module)
01472       u = __ast_module_user_add(app->module, c);
01473    if (strcasecmp(app->name, "system") && !ast_strlen_zero(data) &&
01474          strchr(data, '|') && !strchr(data, ',') && !ast_opt_dont_warn) {
01475       ast_log(LOG_WARNING, "The application delimiter is now the comma, not "
01476          "the pipe.  Did you forget to convert your dialplan?  (%s(%s))\n",
01477          app->name, (char *) data);
01478    }
01479    res = app->execute(c, S_OR(data, ""));
01480    if (app->module && u)
01481       __ast_module_user_remove(app->module, u);
01482    ast_cel_report_event(c, AST_CEL_APP_END, NULL, NULL, NULL);
01483    /* restore channel values */
01484    c->appl = saved_c_appl;
01485    c->data = saved_c_data;
01486    return res;
01487 }

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

References ast_context::alts, ast_autoservice_start(), ast_autoservice_stop(), 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_DEBUG, 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, 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().

02971 {
02972    int x, res;
02973    struct ast_context *tmp = NULL;
02974    struct ast_exten *e = NULL, *eroot = NULL;
02975    struct ast_include *i = NULL;
02976    struct ast_sw *sw = NULL;
02977    struct ast_exten pattern = {NULL, };
02978    struct scoreboard score = {0, };
02979    struct ast_str *tmpdata = NULL;
02980 
02981    pattern.label = label;
02982    pattern.priority = priority;
02983 #ifdef NEED_DEBUG_HERE
02984    ast_log(LOG_NOTICE, "Looking for cont/ext/prio/label/action = %s/%s/%d/%s/%d\n", context, exten, priority, label, (int) action);
02985 #endif
02986 
02987    /* Initialize status if appropriate */
02988    if (q->stacklen == 0) {
02989       q->status = STATUS_NO_CONTEXT;
02990       q->swo = NULL;
02991       q->data = NULL;
02992       q->foundcontext = NULL;
02993    } else if (q->stacklen >= AST_PBX_MAX_STACK) {
02994       ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n");
02995       return NULL;
02996    }
02997 
02998    /* Check first to see if we've already been checked */
02999    for (x = 0; x < q->stacklen; x++) {
03000       if (!strcasecmp(q->incstack[x], context))
03001          return NULL;
03002    }
03003 
03004    if (bypass) { /* bypass means we only look there */
03005       tmp = bypass;
03006    } else {      /* look in contexts */
03007       tmp = find_context(context);
03008       if (!tmp) {
03009          return NULL;
03010       }
03011    }
03012 
03013    if (q->status < STATUS_NO_EXTENSION)
03014       q->status = STATUS_NO_EXTENSION;
03015 
03016    /* Do a search for matching extension */
03017 
03018    eroot = NULL;
03019    score.total_specificity = 0;
03020    score.exten = 0;
03021    score.total_length = 0;
03022    if (!tmp->pattern_tree && tmp->root_table) {
03023       create_match_char_tree(tmp);
03024 #ifdef NEED_DEBUG
03025       ast_log(LOG_DEBUG, "Tree Created in context %s:\n", context);
03026       log_match_char_tree(tmp->pattern_tree," ");
03027 #endif
03028    }
03029 #ifdef NEED_DEBUG
03030    ast_log(LOG_NOTICE, "The Trie we are searching in:\n");
03031    log_match_char_tree(tmp->pattern_tree, "::  ");
03032 #endif
03033 
03034    do {
03035       if (!ast_strlen_zero(overrideswitch)) {
03036          char *osw = ast_strdupa(overrideswitch), *name;
03037          struct ast_switch *asw;
03038          ast_switch_f *aswf = NULL;
03039          char *datap;
03040          int eval = 0;
03041 
03042          name = strsep(&osw, "/");
03043          asw = pbx_findswitch(name);
03044 
03045          if (!asw) {
03046             ast_log(LOG_WARNING, "No such switch '%s'\n", name);
03047             break;
03048          }
03049 
03050          if (osw && strchr(osw, '$')) {
03051             eval = 1;
03052          }
03053 
03054          if (eval && !(tmpdata = ast_str_thread_get(&switch_data, 512))) {
03055             ast_log(LOG_WARNING, "Can't evaluate overrideswitch?!\n");
03056             break;
03057          } else if (eval) {
03058             /* Substitute variables now */
03059             pbx_substitute_variables_helper(chan, osw, ast_str_buffer(tmpdata), ast_str_size(tmpdata));
03060             datap = ast_str_buffer(tmpdata);
03061          } else {
03062             datap = osw;
03063          }
03064 
03065          /* equivalent of extension_match_core() at the switch level */
03066          if (action == E_CANMATCH)
03067             aswf = asw->canmatch;
03068          else if (action == E_MATCHMORE)
03069             aswf = asw->matchmore;
03070          else /* action == E_MATCH */
03071             aswf = asw->exists;
03072          if (!aswf) {
03073             res = 0;
03074          } else {
03075             if (chan) {
03076                ast_autoservice_start(chan);
03077             }
03078             res = aswf(chan, context, exten, priority, callerid, datap);
03079             if (chan) {
03080                ast_autoservice_stop(chan);
03081             }
03082          }
03083          if (res) {  /* Got a match */
03084             q->swo = asw;
03085             q->data = datap;
03086             q->foundcontext = context;
03087             /* XXX keep status = STATUS_NO_CONTEXT ? */
03088             return NULL;
03089          }
03090       }
03091    } while (0);
03092 
03093    if (extenpatternmatchnew) {
03094       new_find_extension(exten, &score, tmp->pattern_tree, 0, 0, callerid, label, action);
03095       eroot = score.exten;
03096 
03097       if (score.last_char == '!' && action == E_MATCHMORE) {
03098          /* We match an extension ending in '!'.
03099           * The decision in this case is final and is NULL (no match).
03100           */
03101 #ifdef NEED_DEBUG_HERE
03102          ast_log(LOG_NOTICE,"Returning MATCHMORE NULL with exclamation point.\n");
03103 #endif
03104          return NULL;
03105       }
03106 
03107       if (!eroot && (action == E_CANMATCH || action == E_MATCHMORE) && score.canmatch_exten) {
03108          q->status = STATUS_SUCCESS;
03109 #ifdef NEED_DEBUG_HERE
03110          ast_log(LOG_NOTICE,"Returning CANMATCH exten %s\n", score.canmatch_exten->exten);
03111 #endif
03112          return score.canmatch_exten;
03113       }
03114 
03115       if ((action == E_MATCHMORE || action == E_CANMATCH)  && eroot) {
03116          if (score.node) {
03117             struct ast_exten *z = trie_find_next_match(score.node);
03118             if (z) {
03119 #ifdef NEED_DEBUG_HERE
03120                ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten %s\n", z->exten);
03121 #endif
03122             } else {
03123                if (score.canmatch_exten) {
03124 #ifdef NEED_DEBUG_HERE
03125                   ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE canmatchmatch exten %s(%p)\n", score.canmatch_exten->exten, score.canmatch_exten);
03126 #endif
03127                   return score.canmatch_exten;
03128                } else {
03129 #ifdef NEED_DEBUG_HERE
03130                   ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten NULL\n");
03131 #endif
03132                }
03133             }
03134             return z;
03135          }
03136 #ifdef NEED_DEBUG_HERE
03137          ast_log(LOG_NOTICE, "Returning CANMATCH/MATCHMORE NULL (no next_match)\n");
03138 #endif
03139          return NULL;  /* according to the code, complete matches are null matches in MATCHMORE mode */
03140       }
03141 
03142       if (eroot) {
03143          /* found entry, now look for the right priority */
03144          if (q->status < STATUS_NO_PRIORITY)
03145             q->status = STATUS_NO_PRIORITY;
03146          e = NULL;
03147          if (action == E_FINDLABEL && label ) {
03148             if (q->status < STATUS_NO_LABEL)
03149                q->status = STATUS_NO_LABEL;
03150             e = ast_hashtab_lookup(eroot->peer_label_table, &pattern);
03151          } else {
03152             e = ast_hashtab_lookup(eroot->peer_table, &pattern);
03153          }
03154          if (e) { /* found a valid match */
03155             q->status = STATUS_SUCCESS;
03156             q->foundcontext = context;
03157 #ifdef NEED_DEBUG_HERE
03158             ast_log(LOG_NOTICE,"Returning complete match of exten %s\n", e->exten);
03159 #endif
03160             return e;
03161          }
03162       }
03163    } else {   /* the old/current default exten pattern match algorithm */
03164 
03165       /* scan the list trying to match extension and CID */
03166       eroot = NULL;
03167       while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) {
03168          int match = extension_match_core(eroot->exten, exten, action);
03169          /* 0 on fail, 1 on match, 2 on earlymatch */
03170 
03171          if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid)))
03172             continue;   /* keep trying */
03173          if (match == 2 && action == E_MATCHMORE) {
03174             /* We match an extension ending in '!'.
03175              * The decision in this case is final and is NULL (no match).
03176              */
03177             return NULL;
03178          }
03179          /* found entry, now look for the right priority */
03180          if (q->status < STATUS_NO_PRIORITY)
03181             q->status = STATUS_NO_PRIORITY;
03182          e = NULL;
03183          if (action == E_FINDLABEL && label ) {
03184             if (q->status < STATUS_NO_LABEL)
03185                q->status = STATUS_NO_LABEL;
03186             e = ast_hashtab_lookup(eroot->peer_label_table, &pattern);
03187          } else {
03188             e = ast_hashtab_lookup(eroot->peer_table, &pattern);
03189          }
03190          if (e) { /* found a valid match */
03191             q->status = STATUS_SUCCESS;
03192             q->foundcontext = context;
03193             return e;
03194          }
03195       }
03196    }
03197 
03198    /* Check alternative switches */
03199    AST_LIST_TRAVERSE(&tmp->alts, sw, list) {
03200       struct ast_switch *asw = pbx_findswitch(sw->name);
03201       ast_switch_f *aswf = NULL;
03202       char *datap;
03203 
03204       if (!asw) {
03205          ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name);
03206          continue;
03207       }
03208 
03209       /* Substitute variables now */
03210       if (sw->eval) {
03211          if (!(tmpdata = ast_str_thread_get(&switch_data, 512))) {
03212             ast_log(LOG_WARNING, "Can't evaluate switch?!\n");
03213             continue;
03214          }
03215          pbx_substitute_variables_helper(chan, sw->data, ast_str_buffer(tmpdata), ast_str_size(tmpdata));
03216       }
03217 
03218       /* equivalent of extension_match_core() at the switch level */
03219       if (action == E_CANMATCH)
03220          aswf = asw->canmatch;
03221       else if (action == E_MATCHMORE)
03222          aswf = asw->matchmore;
03223       else /* action == E_MATCH */
03224          aswf = asw->exists;
03225       datap = sw->eval ? ast_str_buffer(tmpdata) : sw->data;
03226       if (!aswf)
03227          res = 0;
03228       else {
03229          if (chan)
03230             ast_autoservice_start(chan);
03231          res = aswf(chan, context, exten, priority, callerid, datap);
03232          if (chan)
03233             ast_autoservice_stop(chan);
03234       }
03235       if (res) {  /* Got a match */
03236          q->swo = asw;
03237          q->data = datap;
03238          q->foundcontext = context;
03239          /* XXX keep status = STATUS_NO_CONTEXT ? */
03240          return NULL;
03241       }
03242    }
03243    q->incstack[q->stacklen++] = tmp->name;   /* Setup the stack */
03244    /* Now try any includes we have in this context */
03245    for (i = tmp->includes; i; i = i->next) {
03246       if (include_valid(i)) {
03247          if ((e = pbx_find_extension(chan, bypass, q, i->rname, exten, priority, label, callerid, action))) {
03248 #ifdef NEED_DEBUG_HERE
03249             ast_log(LOG_NOTICE,"Returning recursive match of %s\n", e->exten);
03250 #endif
03251             return e;
03252          }
03253          if (q->swo)
03254             return NULL;
03255       }
03256    }
03257    return NULL;
03258 }

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 1491 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_exec_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(), iax2_exec(), lua_pbx_exec(), page_exec(), pbx_builtin_execiftime(), pbx_extension_helper(), realtime_exec(), try_calling(), and tryexec_exec().

01492 {
01493    struct ast_app *tmp;
01494 
01495    AST_RWLIST_RDLOCK(&apps);
01496    AST_RWLIST_TRAVERSE(&apps, tmp, list) {
01497       if (!strcasecmp(tmp->name, app))
01498          break;
01499    }
01500    AST_RWLIST_UNLOCK(&apps);
01501 
01502    return tmp;
01503 }

void pbx_live_dangerously ( int  new_live_dangerously  ) 

Enable/disable the execution of 'dangerous' functions from external protocols (AMI, etc.).

These dialplan functions (such as SHELL) provide an opportunity for privilege escalation. They are okay to invoke from the dialplan, but external protocols with permission controls should not normally invoke them.

This function can globally enable/disable the execution of dangerous functions from external protocols.

Parameters:
new_live_dangerously If true, enable the execution of escalating functions from external protocols.

Definition at line 4013 of file pbx.c.

References ast_log(), LOG_NOTICE, and LOG_WARNING.

Referenced by ast_readconfig().

04014 {
04015    if (new_live_dangerously && !live_dangerously) {
04016       ast_log(LOG_WARNING, "Privilege escalation protection disabled!\n"
04017          "See https://wiki.asterisk.org/wiki/x/1gKfAQ for more details.\n");
04018    }
04019 
04020    if (!new_live_dangerously && live_dangerously) {
04021       ast_log(LOG_NOTICE, "Privilege escalation protection enabled.\n");
04022    }
04023    live_dangerously = new_live_dangerously;
04024 }

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

03389 {
03390    struct ast_str *str = ast_str_create(16);
03391    const char *cret;
03392 
03393    cret = ast_str_retrieve_variable(&str, 0, c, headp, var);
03394    ast_copy_string(workspace, ast_str_buffer(str), workspacelen);
03395    *ret = cret ? workspace : NULL;
03396    ast_free(str);
03397 }

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

References autofallthrough.

Referenced by pbx_load_module().

05896 {
05897    int oldval = autofallthrough;
05898    autofallthrough = newval;
05899    return oldval;
05900 }

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

References extenpatternmatchnew.

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

05903 {
05904    int oldval = extenpatternmatchnew;
05905    extenpatternmatchnew = newval;
05906    return oldval;
05907 }

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

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

Referenced by pbx_load_module().

05910 {
05911    if (overrideswitch) {
05912       ast_free(overrideswitch);
05913    }
05914    if (!ast_strlen_zero(newval)) {
05915       overrideswitch = ast_strdup(newval);
05916    } else {
05917       overrideswitch = NULL;
05918    }
05919 }

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

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

04435 {
04436    /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!!  */
04437    char *cp4 = NULL;
04438    const char *tmp, *whereweare, *orig_cp2 = cp2;
04439    int length, offset, offset2, isfunction;
04440    char *workspace = NULL;
04441    char *ltmp = NULL, *var = NULL;
04442    char *nextvar, *nextexp, *nextthing;
04443    char *vars, *vare;
04444    int pos, brackets, needsub, len;
04445 
04446    *cp2 = 0; /* just in case nothing ends up there */
04447    whereweare=tmp=cp1;
04448    while (!ast_strlen_zero(whereweare) && count) {
04449       /* Assume we're copying the whole remaining string */
04450       pos = strlen(whereweare);
04451       nextvar = NULL;
04452       nextexp = NULL;
04453       nextthing = strchr(whereweare, '$');
04454       if (nextthing) {
04455          switch (nextthing[1]) {
04456          case '{':
04457             nextvar = nextthing;
04458             pos = nextvar - whereweare;
04459             break;
04460          case '[':
04461             nextexp = nextthing;
04462             pos = nextexp - whereweare;
04463             break;
04464          default:
04465             pos = 1;
04466          }
04467       }
04468 
04469       if (pos) {
04470          /* Can't copy more than 'count' bytes */
04471          if (pos > count)
04472             pos = count;
04473 
04474          /* Copy that many bytes */
04475          memcpy(cp2, whereweare, pos);
04476 
04477          count -= pos;
04478          cp2 += pos;
04479          whereweare += pos;
04480          *cp2 = 0;
04481       }
04482 
04483       if (nextvar) {
04484          /* We have a variable.  Find the start and end, and determine
04485             if we are going to have to recursively call ourselves on the
04486             contents */
04487          vars = vare = nextvar + 2;
04488          brackets = 1;
04489          needsub = 0;
04490 
04491          /* Find the end of it */
04492          while (brackets && *vare) {
04493             if ((vare[0] == '$') && (vare[1] == '{')) {
04494                needsub++;
04495             } else if (vare[0] == '{') {
04496                brackets++;
04497             } else if (vare[0] == '}') {
04498                brackets--;
04499             } else if ((vare[0] == '$') && (vare[1] == '['))
04500                needsub++;
04501             vare++;
04502          }
04503          if (brackets)
04504             ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n");
04505          len = vare - vars - 1;
04506 
04507          /* Skip totally over variable string */
04508          whereweare += (len + 3);
04509 
04510          if (!var)
04511             var = ast_alloca(VAR_BUF_SIZE);
04512 
04513          /* Store variable name (and truncate) */
04514          ast_copy_string(var, vars, len + 1);
04515 
04516          /* Substitute if necessary */
04517          if (needsub) {
04518             size_t used;
04519             if (!ltmp)
04520                ltmp = ast_alloca(VAR_BUF_SIZE);
04521 
04522             pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used);
04523             vars = ltmp;
04524          } else {
04525             vars = var;
04526          }
04527 
04528          if (!workspace)
04529             workspace = ast_alloca(VAR_BUF_SIZE);
04530 
04531          workspace[0] = '\0';
04532 
04533          parse_variable_name(vars, &offset, &offset2, &isfunction);
04534          if (isfunction) {
04535             /* Evaluate function */
04536             if (c || !headp)
04537                cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
04538             else {
04539                struct varshead old;
04540                struct ast_channel *c = ast_dummy_channel_alloc();
04541                if (c) {
04542                   memcpy(&old, &c->varshead, sizeof(old));
04543                   memcpy(&c->varshead, headp, sizeof(c->varshead));
04544                   cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
04545                   /* Don't deallocate the varshead that was passed in */
04546                   memcpy(&c->varshead, &old, sizeof(c->varshead));
04547                   c = ast_channel_unref(c);
04548                } else {
04549                   ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution.  Function results may be blank.\n");
04550                }
04551             }
04552             ast_debug(2, "Function %s result is '%s'\n", vars, cp4 ? cp4 : "(null)");
04553          } else {
04554             /* Retrieve variable value */
04555             pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp);
04556          }
04557          if (cp4) {
04558             cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE);
04559 
04560             length = strlen(cp4);
04561             if (length > count)
04562                length = count;
04563             memcpy(cp2, cp4, length);
04564             count -= length;
04565             cp2 += length;
04566             *cp2 = 0;
04567          }
04568       } else if (nextexp) {
04569          /* We have an expression.  Find the start and end, and determine
04570             if we are going to have to recursively call ourselves on the
04571             contents */
04572          vars = vare = nextexp + 2;
04573          brackets = 1;
04574          needsub = 0;
04575 
04576          /* Find the end of it */
04577          while (brackets && *vare) {
04578             if ((vare[0] == '$') && (vare[1] == '[')) {
04579                needsub++;
04580                brackets++;
04581                vare++;
04582             } else if (vare[0] == '[') {
04583                brackets++;
04584             } else if (vare[0] == ']') {
04585                brackets--;
04586             } else if ((vare[0] == '$') && (vare[1] == '{')) {
04587                needsub++;
04588                vare++;
04589             }
04590             vare++;
04591          }
04592          if (brackets)
04593             ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n");
04594          len = vare - vars - 1;
04595 
04596          /* Skip totally over expression */
04597          whereweare += (len + 3);
04598 
04599          if (!var)
04600             var = ast_alloca(VAR_BUF_SIZE);
04601 
04602          /* Store variable name (and truncate) */
04603          ast_copy_string(var, vars, len + 1);
04604 
04605          /* Substitute if necessary */
04606          if (needsub) {
04607             size_t used;
04608             if (!ltmp)
04609                ltmp = ast_alloca(VAR_BUF_SIZE);
04610 
04611             pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used);
04612             vars = ltmp;
04613          } else {
04614             vars = var;
04615          }
04616 
04617          length = ast_expr(vars, cp2, count, c);
04618 
04619          if (length) {
04620             ast_debug(1, "Expression result is '%s'\n", cp2);
04621             count -= length;
04622             cp2 += length;
04623             *cp2 = 0;
04624          }
04625       }
04626    }
04627    *used = cp2 - orig_cp2;
04628 }

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

Definition at line 4636 of file pbx.c.

References pbx_substitute_variables_helper_full().

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

04637 {
04638    size_t used;
04639    pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count, &used);
04640 }


Generated on 27 Jan 2016 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1