Wed Aug 7 17:16:08 2019

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

03947 {
03948    struct ast_custom_function *cur;
03949    char tmps[80];
03950 
03951    if (!acf) {
03952       return -1;
03953    }
03954 
03955    acf->mod = mod;
03956 #ifdef AST_XML_DOCS
03957    acf->docsrc = AST_STATIC_DOC;
03958 #endif
03959 
03960    if (acf_retrieve_docs(acf)) {
03961       return -1;
03962    }
03963 
03964    AST_RWLIST_WRLOCK(&acf_root);
03965 
03966    AST_RWLIST_TRAVERSE(&acf_root, cur, acflist) {
03967       if (!strcmp(acf->name, cur->name)) {
03968          ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name);
03969          AST_RWLIST_UNLOCK(&acf_root);
03970          return -1;
03971       }
03972    }
03973 
03974    /* Store in alphabetical order */
03975    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) {
03976       if (strcasecmp(acf->name, cur->name) < 0) {
03977          AST_RWLIST_INSERT_BEFORE_CURRENT(acf, acflist);
03978          break;
03979       }
03980    }
03981    AST_RWLIST_TRAVERSE_SAFE_END;
03982 
03983    if (!cur) {
03984       AST_RWLIST_INSERT_TAIL(&acf_root, acf, acflist);
03985    }
03986 
03987    AST_RWLIST_UNLOCK(&acf_root);
03988 
03989    ast_verb(2, "Registered custom function '%s'\n", term_color(tmps, acf->name, COLOR_BRCYAN, 0, sizeof(tmps)));
03990 
03991    return 0;
03992 }

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

03995 {
03996    struct ast_custom_escalating_function *acf_escalation = NULL;
03997    int res;
03998 
03999    res = __ast_custom_function_register(acf, mod);
04000    if (res != 0) {
04001       return -1;
04002    }
04003 
04004    if (escalation == AST_CFE_NONE) {
04005       /* No escalations; no need to do anything else */
04006       return 0;
04007    }
04008 
04009    acf_escalation = ast_calloc(1, sizeof(*acf_escalation));
04010    if (!acf_escalation) {
04011       ast_custom_function_unregister(acf);
04012       return -1;
04013    }
04014 
04015    acf_escalation->acf = acf;
04016    switch (escalation) {
04017    case AST_CFE_NONE:
04018       break;
04019    case AST_CFE_READ:
04020       acf_escalation->read_escalates = 1;
04021       break;
04022    case AST_CFE_WRITE:
04023       acf_escalation->write_escalates = 1;
04024       break;
04025    case AST_CFE_BOTH:
04026       acf_escalation->read_escalates = 1;
04027       acf_escalation->write_escalates = 1;
04028       break;
04029    }
04030 
04031    AST_RWLIST_WRLOCK(&escalation_root);
04032    AST_RWLIST_INSERT_TAIL(&escalation_root, acf_escalation, list);
04033    AST_RWLIST_UNLOCK(&escalation_root);
04034 
04035    return 0;
04036 }

int ast_active_calls ( void   ) 

Retrieve the number of active calls.

Definition at line 5931 of file pbx.c.

References countcalls.

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

05932 {
05933    return countcalls;
05934 }

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

08694 {
08695    int ret = -1;
08696    struct ast_context *c;
08697 
08698    c = find_context_locked(context);
08699    if (c) {
08700       ret = ast_add_extension2(c, replace, extension, priority, label, callerid,
08701          application, data, datad, registrar);
08702       ast_unlock_contexts();
08703    }
08704 
08705    return ret;
08706 }

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

09056 {
09057    return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid,
09058       application, data, datad, registrar, 1);
09059 }

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

08732 {
08733    int res = 0;
08734    struct ast_channel *tmpchan;
08735    struct {
08736       char *accountcode;
08737       char *exten;
08738       char *context;
08739       char *linkedid;
08740       char *name;
08741       struct ast_cdr *cdr;
08742       int amaflags;
08743       int state;
08744       format_t readformat;
08745       format_t writeformat;
08746    } tmpvars = { 0, };
08747 
08748    ast_channel_lock(chan);
08749    if (chan->pbx) { /* This channel is currently in the PBX */
08750       ast_explicit_goto(chan, context, exten, priority + 1);
08751       ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO);
08752       ast_channel_unlock(chan);
08753       return res;
08754    }
08755 
08756    /* In order to do it when the channel doesn't really exist within
08757     * the PBX, we have to make a new channel, masquerade, and start the PBX
08758     * at the new location */
08759    tmpvars.accountcode = ast_strdupa(chan->accountcode);
08760    tmpvars.exten = ast_strdupa(chan->exten);
08761    tmpvars.context = ast_strdupa(chan->context);
08762    tmpvars.linkedid = ast_strdupa(chan->linkedid);
08763    tmpvars.name = ast_strdupa(chan->name);
08764    tmpvars.amaflags = chan->amaflags;
08765    tmpvars.state = chan->_state;
08766    tmpvars.writeformat = chan->writeformat;
08767    tmpvars.readformat = chan->readformat;
08768    tmpvars.cdr = chan->cdr ? ast_cdr_dup(chan->cdr) : NULL;
08769 
08770    ast_channel_unlock(chan);
08771 
08772    /* Do not hold any channel locks while calling channel_alloc() since the function
08773     * locks the channel container when linking the new channel in. */
08774    if (!(tmpchan = ast_channel_alloc(0, tmpvars.state, 0, 0, tmpvars.accountcode, tmpvars.exten, tmpvars.context, tmpvars.linkedid, tmpvars.amaflags, "AsyncGoto/%s", tmpvars.name))) {
08775       ast_cdr_discard(tmpvars.cdr);
08776       return -1;
08777    }
08778 
08779    /* copy the cdr info over */
08780    if (tmpvars.cdr) {
08781       ast_cdr_discard(tmpchan->cdr);
08782       tmpchan->cdr = tmpvars.cdr;
08783       tmpvars.cdr = NULL;
08784    }
08785 
08786    /* Make formats okay */
08787    tmpchan->readformat = tmpvars.readformat;
08788    tmpchan->writeformat = tmpvars.writeformat;
08789 
08790    /* Setup proper location. Never hold another channel lock while calling this function. */
08791    ast_explicit_goto(tmpchan, S_OR(context, tmpvars.context), S_OR(exten, tmpvars.exten), priority);
08792 
08793    /* Masquerade into tmp channel */
08794    if (ast_channel_masquerade(tmpchan, chan)) {
08795       /* Failed to set up the masquerade.  It's probably chan_local
08796        * in the middle of optimizing itself out.  Sad. :( */
08797       ast_hangup(tmpchan);
08798       tmpchan = NULL;
08799       res = -1;
08800    } else {
08801       ast_do_masquerade(tmpchan);
08802       /* Start the PBX going on our stolen channel */
08803       if (ast_pbx_start(tmpchan)) {
08804          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name);
08805          ast_hangup(tmpchan);
08806          res = -1;
08807       }
08808    }
08809 
08810    return res;
08811 }

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

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

08814 {
08815    struct ast_channel *chan;
08816    int res = -1;
08817 
08818    if ((chan = ast_channel_get_by_name(channame))) {
08819       res = ast_async_goto(chan, context, exten, priority);
08820       chan = ast_channel_unref(chan);
08821    }
08822 
08823    return res;
08824 }

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

References __ast_goto_if_exists().

11267 {
11268    return __ast_goto_if_exists(chan, context, exten, priority, 1);
11269 }

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

References pbx_parseable_goto().

Referenced by asyncgoto_exec(), and handle_redirect().

11332 {
11333    return pbx_parseable_goto(chan, goto_string, 1);
11334 }

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

08315 {
08316    char *info;
08317    int j, num_fields, last_sep = -1;
08318 
08319    i->timezone = NULL;
08320 
08321    /* Check for empty just in case */
08322    if (ast_strlen_zero(info_in)) {
08323       return 0;
08324    }
08325 
08326    /* make a copy just in case we were passed a static string */
08327    info = ast_strdupa(info_in);
08328 
08329    /* count the number of fields in the timespec */
08330    for (j = 0, num_fields = 1; info[j] != '\0'; j++) {
08331       if (info[j] == ',') {
08332          last_sep = j;
08333          num_fields++;
08334       }
08335    }
08336 
08337    /* save the timezone, if it is specified */
08338    if (num_fields == 5) {
08339       i->timezone = ast_strdup(info + last_sep + 1);
08340    }
08341 
08342    /* Assume everything except time */
08343    i->monthmask = 0xfff;   /* 12 bits */
08344    i->daymask = 0x7fffffffU; /* 31 bits */
08345    i->dowmask = 0x7f; /* 7 bits */
08346    /* on each call, use strsep() to move info to the next argument */
08347    get_timerange(i, strsep(&info, "|,"));
08348    if (info)
08349       i->dowmask = get_range(strsep(&info, "|,"), 7, days, "day of week");
08350    if (info)
08351       i->daymask = get_range(strsep(&info, "|,"), 31, NULL, "day");
08352    if (info)
08353       i->monthmask = get_range(strsep(&info, "|,"), 12, months, "month");
08354    return 1;
08355 }

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

05416 {
05417    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0);
05418 }

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

References ast_check_timing2(), and ast_tvnow().

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

08358 {
08359    return ast_check_timing2(i, ast_tvnow());
08360 }

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

08363 {
08364    struct ast_tm tm;
08365 
08366    ast_localtime(&tv, &tm, i->timezone);
08367 
08368    /* If it's not the right month, return */
08369    if (!(i->monthmask & (1 << tm.tm_mon)))
08370       return 0;
08371 
08372    /* If it's not that time of the month.... */
08373    /* Warning, tm_mday has range 1..31! */
08374    if (!(i->daymask & (1 << (tm.tm_mday-1))))
08375       return 0;
08376 
08377    /* If it's not the right day of the week */
08378    if (!(i->dowmask & (1 << tm.tm_wday)))
08379       return 0;
08380 
08381    /* Sanity check the hour just to be safe */
08382    if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) {
08383       ast_log(LOG_WARNING, "Insane time...\n");
08384       return 0;
08385    }
08386 
08387    /* Now the tough part, we calculate if it fits
08388       in the right time based on min/hour */
08389    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))))
08390       return 0;
08391 
08392    /* If we got this far, then we're good */
08393    return 1;
08394 }

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

11337 {
11338    struct ast_app *app = NULL;
11339    int which = 0;
11340    char *ret = NULL;
11341    size_t wordlen = strlen(word);
11342 
11343    AST_RWLIST_RDLOCK(&apps);
11344    AST_RWLIST_TRAVERSE(&apps, app, list) {
11345       if (!strncasecmp(word, app->name, wordlen) && ++which > state) {
11346          ret = ast_strdup(app->name);
11347          break;
11348       }
11349    }
11350    AST_RWLIST_UNLOCK(&apps);
11351 
11352    return ret;
11353 }

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

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

Referenced by handle_cli_dialplan_add_ignorepat().

08599 {
08600    int ret = -1;
08601    struct ast_context *c;
08602 
08603    c = find_context_locked(context);
08604    if (c) {
08605       ret = ast_context_add_ignorepat2(c, value, registrar);
08606       ast_unlock_contexts();
08607    }
08608    return ret;
08609 }

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

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

08612 {
08613    struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL;
08614    int length;
08615    char *pattern;
08616    length = sizeof(struct ast_ignorepat);
08617    length += strlen(value) + 1;
08618    if (!(ignorepat = ast_calloc(1, length)))
08619       return -1;
08620    /* The cast to char * is because we need to write the initial value.
08621     * The field is not supposed to be modified otherwise.  Also, gcc 4.2
08622     * sees the cast as dereferencing a type-punned pointer and warns about
08623     * it.  This is the workaround (we're telling gcc, yes, that's really
08624     * what we wanted to do).
08625     */
08626    pattern = (char *) ignorepat->pattern;
08627    strcpy(pattern, value);
08628    ignorepat->next = NULL;
08629    ignorepat->registrar = registrar;
08630    ast_wrlock_context(con);
08631    for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) {
08632       ignorepatl = ignorepatc;
08633       if (!strcasecmp(ignorepatc->pattern, value)) {
08634          /* Already there */
08635          ast_unlock_context(con);
08636          ast_free(ignorepat);
08637          errno = EEXIST;
08638          return -1;
08639       }
08640    }
08641    if (ignorepatl)
08642       ignorepatl->next = ignorepat;
08643    else
08644       con->ignorepats = ignorepat;
08645    ast_unlock_context(con);
08646    return 0;
08647 
08648 }

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

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

Referenced by handle_cli_dialplan_add_include().

08143 {
08144    int ret = -1;
08145    struct ast_context *c;
08146 
08147    c = find_context_locked(context);
08148    if (c) {
08149       ret = ast_context_add_include2(c, include, registrar);
08150       ast_unlock_contexts();
08151    }
08152    return ret;
08153 }

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

08413 {
08414    struct ast_include *new_include;
08415    char *c;
08416    struct ast_include *i, *il = NULL; /* include, include_last */
08417    int length;
08418    char *p;
08419 
08420    length = sizeof(struct ast_include);
08421    length += 2 * (strlen(value) + 1);
08422 
08423    /* allocate new include structure ... */
08424    if (!(new_include = ast_calloc(1, length)))
08425       return -1;
08426    /* Fill in this structure. Use 'p' for assignments, as the fields
08427     * in the structure are 'const char *'
08428     */
08429    p = new_include->stuff;
08430    new_include->name = p;
08431    strcpy(p, value);
08432    p += strlen(value) + 1;
08433    new_include->rname = p;
08434    strcpy(p, value);
08435    /* Strip off timing info, and process if it is there */
08436    if ( (c = strchr(p, ',')) ) {
08437       *c++ = '\0';
08438       new_include->hastime = ast_build_timing(&(new_include->timing), c);
08439    }
08440    new_include->next      = NULL;
08441    new_include->registrar = registrar;
08442 
08443    ast_wrlock_context(con);
08444 
08445    /* ... go to last include and check if context is already included too... */
08446    for (i = con->includes; i; i = i->next) {
08447       if (!strcasecmp(i->name, new_include->name)) {
08448          ast_destroy_timing(&(new_include->timing));
08449          ast_free(new_include);
08450          ast_unlock_context(con);
08451          errno = EEXIST;
08452          return -1;
08453       }
08454       il = i;
08455    }
08456 
08457    /* ... include new context into context list, unlock, return */
08458    if (il)
08459       il->next = new_include;
08460    else
08461       con->includes = new_include;
08462    ast_verb(3, "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con));
08463 
08464    ast_unlock_context(con);
08465 
08466    return 0;
08467 }

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

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

08475 {
08476    int ret = -1;
08477    struct ast_context *c;
08478 
08479    c = find_context_locked(context);
08480    if (c) { /* found, add switch to this context */
08481       ret = ast_context_add_switch2(c, sw, data, eval, registrar);
08482       ast_unlock_contexts();
08483    }
08484    return ret;
08485 }

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

08496 {
08497    struct ast_sw *new_sw;
08498    struct ast_sw *i;
08499    int length;
08500    char *p;
08501 
08502    length = sizeof(struct ast_sw);
08503    length += strlen(value) + 1;
08504    if (data)
08505       length += strlen(data);
08506    length++;
08507 
08508    /* allocate new sw structure ... */
08509    if (!(new_sw = ast_calloc(1, length)))
08510       return -1;
08511    /* ... fill in this structure ... */
08512    p = new_sw->stuff;
08513    new_sw->name = p;
08514    strcpy(new_sw->name, value);
08515    p += strlen(value) + 1;
08516    new_sw->data = p;
08517    if (data) {
08518       strcpy(new_sw->data, data);
08519       p += strlen(data) + 1;
08520    } else {
08521       strcpy(new_sw->data, "");
08522       p++;
08523    }
08524    new_sw->eval     = eval;
08525    new_sw->registrar = registrar;
08526 
08527    /* ... try to lock this context ... */
08528    ast_wrlock_context(con);
08529 
08530    /* ... go to last sw and check if context is already swd too... */
08531    AST_LIST_TRAVERSE(&con->alts, i, list) {
08532       if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) {
08533          ast_free(new_sw);
08534          ast_unlock_context(con);
08535          errno = EEXIST;
08536          return -1;
08537       }
08538    }
08539 
08540    /* ... sw new context into context list, unlock, return */
08541    AST_LIST_INSERT_TAIL(&con->alts, new_sw, list);
08542 
08543    ast_verb(3, "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con));
08544 
08545    ast_unlock_context(con);
08546 
08547    return 0;
08548 }

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 9875 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 2971 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().

02972 {
02973    struct ast_context *tmp;
02974    struct fake_context item;
02975 
02976    if (!name) {
02977       return NULL;
02978    }
02979    ast_rdlock_contexts();
02980    if (contexts_table) {
02981       ast_copy_string(item.name, name, sizeof(item.name));
02982       tmp = ast_hashtab_lookup(contexts_table, &item);
02983    } else {
02984       tmp = NULL;
02985       while ((tmp = ast_walk_contexts(tmp))) {
02986          if (!strcasecmp(name, tmp->name)) {
02987             break;
02988          }
02989       }
02990    }
02991    ast_unlock_contexts();
02992    return tmp;
02993 }

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

07727 {
07728    struct ast_context *tmp, **local_contexts;
07729    struct fake_context search;
07730    int length = sizeof(struct ast_context) + strlen(name) + 1;
07731 
07732    if (!contexts_table) {
07733       /* Protect creation of contexts_table from reentrancy. */
07734       ast_wrlock_contexts();
07735       if (!contexts_table) {
07736          contexts_table = ast_hashtab_create(17,
07737             ast_hashtab_compare_contexts,
07738             ast_hashtab_resize_java,
07739             ast_hashtab_newsize_java,
07740             ast_hashtab_hash_contexts,
07741             0);
07742       }
07743       ast_unlock_contexts();
07744    }
07745 
07746    ast_copy_string(search.name, name, sizeof(search.name));
07747    if (!extcontexts) {
07748       ast_rdlock_contexts();
07749       local_contexts = &contexts;
07750       tmp = ast_hashtab_lookup(contexts_table, &search);
07751       ast_unlock_contexts();
07752       if (tmp) {
07753          tmp->refcount++;
07754          return tmp;
07755       }
07756    } else { /* local contexts just in a linked list; search there for the new context; slow, linear search, but not frequent */
07757       local_contexts = extcontexts;
07758       tmp = ast_hashtab_lookup(exttable, &search);
07759       if (tmp) {
07760          tmp->refcount++;
07761          return tmp;
07762       }
07763    }
07764 
07765    if ((tmp = ast_calloc(1, length))) {
07766       ast_rwlock_init(&tmp->lock);
07767       ast_mutex_init(&tmp->macrolock);
07768       strcpy(tmp->name, name);
07769       tmp->root = NULL;
07770       tmp->root_table = NULL;
07771       tmp->registrar = ast_strdup(registrar);
07772       tmp->includes = NULL;
07773       tmp->ignorepats = NULL;
07774       tmp->refcount = 1;
07775    } else {
07776       ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name);
07777       return NULL;
07778    }
07779 
07780    if (!extcontexts) {
07781       ast_wrlock_contexts();
07782       tmp->next = *local_contexts;
07783       *local_contexts = tmp;
07784       ast_hashtab_insert_safe(contexts_table, tmp); /*put this context into the tree */
07785       ast_unlock_contexts();
07786       ast_debug(1, "Registered context '%s'(%p) in table %p registrar: %s\n", tmp->name, tmp, contexts_table, registrar);
07787       ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar);
07788    } else {
07789       tmp->next = *local_contexts;
07790       if (exttable)
07791          ast_hashtab_insert_immediate(exttable, tmp); /*put this context into the tree */
07792 
07793       *local_contexts = tmp;
07794       ast_debug(1, "Registered context '%s'(%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar);
07795       ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar);
07796    }
07797    return tmp;
07798 }

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

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

Referenced by _macro_exec().

06307 {
06308    struct ast_context *c;
06309    int ret = -1;
06310 
06311    c = find_context_locked(context);
06312    if (c) {
06313       ast_unlock_contexts();
06314 
06315       /* if we found context, lock macrolock */
06316       ret = ast_mutex_lock(&c->macrolock);
06317    }
06318 
06319    return ret;
06320 }

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

06115 {
06116    return ast_context_remove_extension_callerid(context, extension, priority, NULL, AST_EXT_MATCHCID_ANY, registrar);
06117 }

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

06145 {
06146    return ast_context_remove_extension_callerid2(con, extension, priority, NULL, AST_EXT_MATCHCID_ANY, registrar, already_locked);
06147 }

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

06120 {
06121    int ret = -1; /* default error return */
06122    struct ast_context *c;
06123 
06124    c = find_context_locked(context);
06125    if (c) { /* ... remove extension ... */
06126       ret = ast_context_remove_extension_callerid2(c, extension, priority, callerid,
06127          matchcallerid, registrar, 0);
06128       ast_unlock_contexts();
06129    }
06130 
06131    return ret;
06132 }

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

06150 {
06151    struct ast_exten *exten, *prev_exten = NULL;
06152    struct ast_exten *peer;
06153    struct ast_exten ex, *exten2, *exten3;
06154    char dummy_name[1024];
06155    struct ast_exten *previous_peer = NULL;
06156    struct ast_exten *next_peer = NULL;
06157    int found = 0;
06158 
06159    if (!already_locked)
06160       ast_wrlock_context(con);
06161 
06162 #ifdef NEED_DEBUG
06163    ast_verb(3,"Removing %s/%s/%d%s%s from trees, registrar=%s\n", con->name, extension, priority, matchcallerid ? "/" : "", matchcallerid ? callerid : "", registrar);
06164 #endif
06165 #ifdef CONTEXT_DEBUG
06166    check_contexts(__FILE__, __LINE__);
06167 #endif
06168    /* find this particular extension */
06169    ex.exten = dummy_name;
06170    ex.matchcid = matchcallerid;
06171    ex.cidmatch = callerid;
06172    ast_copy_string(dummy_name, extension, sizeof(dummy_name));
06173    exten = ast_hashtab_lookup(con->root_table, &ex);
06174    if (exten) {
06175       if (priority == 0) {
06176          exten2 = ast_hashtab_remove_this_object(con->root_table, exten);
06177          if (!exten2)
06178             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);
06179          if (con->pattern_tree) {
06180             struct match_char *x = add_exten_to_pattern_tree(con, exten, 1);
06181 
06182             if (x->exten) { /* this test for safety purposes */
06183                x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */
06184                x->exten = 0; /* get rid of what will become a bad pointer */
06185             } else {
06186                ast_log(LOG_WARNING,"Trying to delete an exten from a context, but the pattern tree node returned isn't a full extension\n");
06187             }
06188          }
06189       } else {
06190          ex.priority = priority;
06191          exten2 = ast_hashtab_lookup(exten->peer_table, &ex);
06192          if (exten2) {
06193             if (exten2->label) { /* if this exten has a label, remove that, too */
06194                exten3 = ast_hashtab_remove_this_object(exten->peer_label_table,exten2);
06195                if (!exten3)
06196                   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);
06197             }
06198 
06199             exten3 = ast_hashtab_remove_this_object(exten->peer_table, exten2);
06200             if (!exten3)
06201                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);
06202             if (exten2 == exten && exten2->peer) {
06203                exten2 = ast_hashtab_remove_this_object(con->root_table, exten);
06204                ast_hashtab_insert_immediate(con->root_table, exten2->peer);
06205             }
06206             if (ast_hashtab_size(exten->peer_table) == 0) {
06207                /* well, if the last priority of an exten is to be removed,
06208                   then, the extension is removed, too! */
06209                exten3 = ast_hashtab_remove_this_object(con->root_table, exten);
06210                if (!exten3)
06211                   ast_log(LOG_ERROR,"Did not remove this exten (%s) from the context root_table (%s) (priority %d)\n", exten->exten, con->name, priority);
06212                if (con->pattern_tree) {
06213                   struct match_char *x = add_exten_to_pattern_tree(con, exten, 1);
06214                   if (x->exten) { /* this test for safety purposes */
06215                      x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */
06216                      x->exten = 0; /* get rid of what will become a bad pointer */
06217                   }
06218                }
06219             }
06220          } else {
06221             ast_log(LOG_ERROR,"Could not find priority %d of exten %s in context %s!\n",
06222                   priority, exten->exten, con->name);
06223          }
06224       }
06225    } else {
06226       /* hmmm? this exten is not in this pattern tree? */
06227       ast_log(LOG_WARNING,"Cannot find extension %s in root_table in context %s\n",
06228             extension, con->name);
06229    }
06230 #ifdef NEED_DEBUG
06231    if (con->pattern_tree) {
06232       ast_log(LOG_NOTICE,"match char tree after exten removal:\n");
06233       log_match_char_tree(con->pattern_tree, " ");
06234    }
06235 #endif
06236 
06237    /* scan the extension list to find first matching extension-registrar */
06238    for (exten = con->root; exten; prev_exten = exten, exten = exten->next) {
06239       if (!strcmp(exten->exten, extension) &&
06240          (!registrar || !strcmp(exten->registrar, registrar)) &&
06241          (!matchcallerid || (!ast_strlen_zero(callerid) && !ast_strlen_zero(exten->cidmatch) && !strcmp(exten->cidmatch, callerid)) || (ast_strlen_zero(callerid) && ast_strlen_zero(exten->cidmatch))))
06242          break;
06243    }
06244    if (!exten) {
06245       /* we can't find right extension */
06246       if (!already_locked)
06247          ast_unlock_context(con);
06248       return -1;
06249    }
06250 
06251    /* scan the priority list to remove extension with exten->priority == priority */
06252    for (peer = exten, next_peer = exten->peer ? exten->peer : exten->next;
06253        peer && !strcmp(peer->exten, extension) &&
06254          (!callerid || (!matchcallerid && !peer->matchcid) || (matchcallerid && peer->matchcid && !strcmp(peer->cidmatch, callerid))) ;
06255          peer = next_peer, next_peer = next_peer ? (next_peer->peer ? next_peer->peer : next_peer->next) : NULL) {
06256 
06257       if ((priority == 0 || peer->priority == priority) &&
06258             (!registrar || !strcmp(peer->registrar, registrar) )) {
06259          found = 1;
06260 
06261          /* we are first priority extension? */
06262          if (!previous_peer) {
06263             /*
06264              * We are first in the priority chain, so must update the extension chain.
06265              * The next node is either the next priority or the next extension
06266              */
06267             struct ast_exten *next_node = peer->peer ? peer->peer : peer->next;
06268             if (peer->peer) {
06269                /* move the peer_table and peer_label_table down to the next peer, if
06270                   it is there */
06271                peer->peer->peer_table = peer->peer_table;
06272                peer->peer->peer_label_table = peer->peer_label_table;
06273                peer->peer_table = NULL;
06274                peer->peer_label_table = NULL;
06275             }
06276             if (!prev_exten) {   /* change the root... */
06277                con->root = next_node;
06278             } else {
06279                prev_exten->next = next_node; /* unlink */
06280             }
06281             if (peer->peer)   { /* update the new head of the pri list */
06282                peer->peer->next = peer->next;
06283             }
06284          } else { /* easy, we are not first priority in extension */
06285             previous_peer->peer = peer->peer;
06286          }
06287 
06288 
06289          /* now, free whole priority extension */
06290          destroy_exten(peer);
06291       } else {
06292          previous_peer = peer;
06293       }
06294    }
06295    if (!already_locked)
06296       ast_unlock_context(con);
06297    return found ? 0 : -1;
06298 }

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

Definition at line 8554 of file pbx.c.

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

Referenced by handle_cli_dialplan_remove_ignorepat().

08555 {
08556    int ret = -1;
08557    struct ast_context *c;
08558 
08559    c = find_context_locked(context);
08560    if (c) {
08561       ret = ast_context_remove_ignorepat2(c, ignorepat, registrar);
08562       ast_unlock_contexts();
08563    }
08564    return ret;
08565 }

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

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

08568 {
08569    struct ast_ignorepat *ip, *ipl = NULL;
08570 
08571    ast_wrlock_context(con);
08572 
08573    for (ip = con->ignorepats; ip; ip = ip->next) {
08574       if (!strcmp(ip->pattern, ignorepat) &&
08575          (!registrar || (registrar == ip->registrar))) {
08576          if (ipl) {
08577             ipl->next = ip->next;
08578             ast_free(ip);
08579          } else {
08580             con->ignorepats = ip->next;
08581             ast_free(ip);
08582          }
08583          ast_unlock_context(con);
08584          return 0;
08585       }
08586       ipl = ip;
08587    }
08588 
08589    ast_unlock_context(con);
08590    errno = EINVAL;
08591    return -1;
08592 }

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

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

Referenced by handle_cli_dialplan_remove_include().

06008 {
06009    int ret = -1;
06010    struct ast_context *c;
06011 
06012    c = find_context_locked(context);
06013    if (c) {
06014       /* found, remove include from this context ... */
06015       ret = ast_context_remove_include2(c, include, registrar);
06016       ast_unlock_contexts();
06017    }
06018    return ret;
06019 }

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

06031 {
06032    struct ast_include *i, *pi = NULL;
06033    int ret = -1;
06034 
06035    ast_wrlock_context(con);
06036 
06037    /* find our include */
06038    for (i = con->includes; i; pi = i, i = i->next) {
06039       if (!strcmp(i->name, include) &&
06040             (!registrar || !strcmp(i->registrar, registrar))) {
06041          /* remove from list */
06042          ast_verb(3, "Removing inclusion of context '%s' in context '%s; registrar=%s'\n", include, ast_get_context_name(con), registrar);
06043          if (pi)
06044             pi->next = i->next;
06045          else
06046             con->includes = i->next;
06047          /* free include and return */
06048          ast_destroy_timing(&(i->timing));
06049          ast_free(i);
06050          ret = 0;
06051          break;
06052       }
06053    }
06054 
06055    ast_unlock_context(con);
06056 
06057    return ret;
06058 }

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

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

06066 {
06067    int ret = -1; /* default error return */
06068    struct ast_context *c;
06069 
06070    c = find_context_locked(context);
06071    if (c) {
06072       /* remove switch from this context ... */
06073       ret = ast_context_remove_switch2(c, sw, data, registrar);
06074       ast_unlock_contexts();
06075    }
06076    return ret;
06077 }

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

06088 {
06089    struct ast_sw *i;
06090    int ret = -1;
06091 
06092    ast_wrlock_context(con);
06093 
06094    /* walk switches */
06095    AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) {
06096       if (!strcmp(i->name, sw) && !strcmp(i->data, data) &&
06097          (!registrar || !strcmp(i->registrar, registrar))) {
06098          /* found, remove from list */
06099          ast_verb(3, "Removing switch '%s' from context '%s; registrar=%s'\n", sw, ast_get_context_name(con), registrar);
06100          AST_LIST_REMOVE_CURRENT(list);
06101          ast_free(i); /* free switch and return */
06102          ret = 0;
06103          break;
06104       }
06105    }
06106    AST_LIST_TRAVERSE_SAFE_END;
06107 
06108    ast_unlock_context(con);
06109 
06110    return ret;
06111 }

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

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

Referenced by _macro_exec().

06328 {
06329    struct ast_context *c;
06330    int ret = -1;
06331 
06332    c = find_context_locked(context);
06333    if (c) {
06334       ast_unlock_contexts();
06335 
06336       /* if we found context, unlock macrolock */
06337       ret = ast_mutex_unlock(&c->macrolock);
06338    }
06339 
06340    return ret;
06341 }

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

11222 {
11223    struct ast_include *inc = NULL;
11224    int res = 0;
11225 
11226    while ( (inc = ast_walk_context_includes(con, inc)) ) {
11227       if (ast_context_find(inc->rname))
11228          continue;
11229 
11230       res = -1;
11231       ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n",
11232          ast_get_context_name(con), inc->rname);
11233       break;
11234    }
11235 
11236    return res;
11237 }

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

03815 {
03816    struct ast_custom_function *cur;
03817    struct ast_custom_escalating_function *cur_escalation;
03818 
03819    if (!acf) {
03820       return -1;
03821    }
03822 
03823    AST_RWLIST_WRLOCK(&acf_root);
03824    if ((cur = AST_RWLIST_REMOVE(&acf_root, acf, acflist))) {
03825 #ifdef AST_XML_DOCS
03826       if (cur->docsrc == AST_XML_DOC) {
03827          ast_string_field_free_memory(acf);
03828       }
03829 #endif
03830       ast_verb(2, "Unregistered custom function %s\n", cur->name);
03831    }
03832    AST_RWLIST_UNLOCK(&acf_root);
03833 
03834    /* Remove from the escalation list */
03835    AST_RWLIST_WRLOCK(&escalation_root);
03836    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&escalation_root, cur_escalation, list) {
03837       if (cur_escalation->acf == acf) {
03838          AST_RWLIST_REMOVE_CURRENT(list);
03839          ast_free(cur_escalation);
03840          break;
03841       }
03842    }
03843    AST_RWLIST_TRAVERSE_SAFE_END;
03844    AST_RWLIST_UNLOCK(&escalation_root);
03845 
03846    return cur ? 0 : -1;
03847 }

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

08397 {
08398    if (i->timezone) {
08399       ast_free(i->timezone);
08400       i->timezone = NULL;
08401    }
08402    return 0;
08403 }

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

04845 {
04846    switch (devstate) {
04847    case AST_DEVICE_ONHOLD:
04848       return AST_EXTENSION_ONHOLD;
04849    case AST_DEVICE_BUSY:
04850       return AST_EXTENSION_BUSY;
04851    case AST_DEVICE_UNKNOWN:
04852       return AST_EXTENSION_NOT_INUSE;
04853    case AST_DEVICE_UNAVAILABLE:
04854    case AST_DEVICE_INVALID:
04855       return AST_EXTENSION_UNAVAILABLE;
04856    case AST_DEVICE_RINGINUSE:
04857       return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING);
04858    case AST_DEVICE_RINGING:
04859       return AST_EXTENSION_RINGING;
04860    case AST_DEVICE_INUSE:
04861       return AST_EXTENSION_INUSE;
04862    case AST_DEVICE_NOT_INUSE:
04863       return AST_EXTENSION_NOT_INUSE;
04864    case AST_DEVICE_TOTAL: /* not a device state, included for completeness */
04865       break;
04866    }
04867 
04868    return AST_EXTENSION_NOT_INUSE;
04869 }

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

05401 {
05402    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0);
05403 }

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

08709 {
08710    if (!chan)
08711       return -1;
08712 
08713    ast_channel_lock(chan);
08714 
08715    if (!ast_strlen_zero(context))
08716       ast_copy_string(chan->context, context, sizeof(chan->context));
08717    if (!ast_strlen_zero(exten))
08718       ast_copy_string(chan->exten, exten, sizeof(chan->exten));
08719    if (priority > -1) {
08720       chan->priority = priority;
08721       /* see flag description in channel.h for explanation */
08722       if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP))
08723          chan->priority--;
08724    }
08725 
08726    ast_channel_unlock(chan);
08727 
08728    return 0;
08729 }

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

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

02949 {
02950    if (needmore != E_MATCHMORE && needmore != E_CANMATCH)
02951       ast_log(LOG_WARNING, "invalid argument %d\n", needmore);
02952    return extension_match_core(pattern, data, needmore);
02953 }

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

References ext_cmp().

Referenced by lua_extension_cmp().

02714 {
02715    int cmp;
02716 
02717    cmp = ext_cmp(a, b);
02718    if (cmp < 0) {
02719       return -1;
02720    }
02721    if (cmp > 0) {
02722       return 1;
02723    }
02724    return 0;
02725 }

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

02944 {
02945    return extension_match_core(pattern, data, E_MATCH);
02946 }

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

04915 {
04916    struct ast_exten *e;
04917 
04918    if (!(e = ast_hint_extension(c, context, exten))) {  /* Do we have a hint for this extension ? */
04919       return -1;                   /* No hint, return -1 */
04920    }
04921 
04922    if (e->exten[0] == '_') {
04923       /* Create this hint on-the-fly */
04924       ast_add_extension(e->parent->name, 0, exten, e->priority, e->label,
04925          e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr,
04926          e->registrar);
04927       if (!(e = ast_hint_extension(c, context, exten))) {
04928          /* Improbable, but not impossible */
04929          return -1;
04930       }
04931    }
04932 
04933    return ast_extension_state2(e);  /* Check all devices in the hint */
04934 }

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

04903 {
04904    int i;
04905 
04906    for (i = 0; (i < ARRAY_LEN(extension_states)); i++) {
04907       if (extension_states[i].extension_state == extension_state)
04908          return extension_states[i].text;
04909    }
04910    return "Unknown";
04911 }

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

References ast_extension_state_add_destroy().

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

05137 {
05138    return ast_extension_state_add_destroy(context, exten, change_cb, NULL, data);
05139 }

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

05050 {
05051    struct ast_hint *hint;
05052    struct ast_state_cb *state_cb;
05053    struct ast_exten *e;
05054    int id;
05055 
05056    /* If there's no context and extension:  add callback to statecbs list */
05057    if (!context && !exten) {
05058       /* Prevent multiple adds from adding the same change_cb at the same time. */
05059       ao2_lock(statecbs);
05060 
05061       /* Remove any existing change_cb. */
05062       ao2_find(statecbs, change_cb, OBJ_UNLINK | OBJ_NODATA);
05063 
05064       /* Now insert the change_cb */
05065       if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) {
05066          ao2_unlock(statecbs);
05067          return -1;
05068       }
05069       state_cb->id = 0;
05070       state_cb->change_cb = change_cb;
05071       state_cb->destroy_cb = destroy_cb;
05072       state_cb->data = data;
05073       ao2_link(statecbs, state_cb);
05074 
05075       ao2_ref(state_cb, -1);
05076       ao2_unlock(statecbs);
05077       return 0;
05078    }
05079 
05080    if (!context || !exten)
05081       return -1;
05082 
05083    /* This callback type is for only one hint, so get the hint */
05084    e = ast_hint_extension(NULL, context, exten);
05085    if (!e) {
05086       return -1;
05087    }
05088 
05089    /* If this is a pattern, dynamically create a new extension for this
05090     * particular match.  Note that this will only happen once for each
05091     * individual extension, because the pattern will no longer match first.
05092     */
05093    if (e->exten[0] == '_') {
05094       ast_add_extension(e->parent->name, 0, exten, e->priority, e->label,
05095          e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr,
05096          e->registrar);
05097       e = ast_hint_extension(NULL, context, exten);
05098       if (!e || e->exten[0] == '_') {
05099          return -1;
05100       }
05101    }
05102 
05103    /* Find the hint in the hints container */
05104    ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */
05105    hint = ao2_find(hints, e, 0);
05106    if (!hint) {
05107       ao2_unlock(hints);
05108       return -1;
05109    }
05110 
05111    /* Now insert the callback in the callback list  */
05112    if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) {
05113       ao2_ref(hint, -1);
05114       ao2_unlock(hints);
05115       return -1;
05116    }
05117    do {
05118       id = stateid++;      /* Unique ID for this callback */
05119       /* Do not allow id to ever be -1 or 0. */
05120    } while (id == -1 || id == 0);
05121    state_cb->id = id;
05122    state_cb->change_cb = change_cb; /* Pointer to callback routine */
05123    state_cb->destroy_cb = destroy_cb;
05124    state_cb->data = data;     /* Data for the callback */
05125    ao2_link(hint->callbacks, state_cb);
05126 
05127    ao2_ref(state_cb, -1);
05128    ao2_ref(hint, -1);
05129    ao2_unlock(hints);
05130 
05131    return id;
05132 }

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

05158 {
05159    struct ast_state_cb *p_cur;
05160    int ret = -1;
05161 
05162    if (!id) {  /* id == 0 is a callback without extension */
05163       if (!change_cb) {
05164          return ret;
05165       }
05166       p_cur = ao2_find(statecbs, change_cb, OBJ_UNLINK);
05167       if (p_cur) {
05168          ret = 0;
05169          ao2_ref(p_cur, -1);
05170       }
05171    } else { /* callback with extension, find the callback based on ID */
05172       struct ast_hint *hint;
05173 
05174       ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */
05175       hint = ao2_callback(hints, 0, find_hint_by_cb_id, &id);
05176       if (hint) {
05177          p_cur = ao2_find(hint->callbacks, &id, OBJ_UNLINK);
05178          if (p_cur) {
05179             ret = 0;
05180             ao2_ref(p_cur, -1);
05181          }
05182          ao2_ref(hint, -1);
05183       }
05184       ao2_unlock(hints);
05185    }
05186 
05187    return ret;
05188 }

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

05406 {
05407    return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
05408 }

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

References E_FINDLABEL, and pbx_extension_helper().

Referenced by pbx_load_config().

05411 {
05412    return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
05413 }

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

04178 {
04179    char *copy = ast_strdupa(function);
04180    char *args = func_args(copy);
04181    struct ast_custom_function *acfptr = ast_custom_function_find(copy);
04182    int res;
04183    struct ast_module_user *u = NULL;
04184 
04185    if (acfptr == NULL) {
04186       ast_log(LOG_ERROR, "Function %s not registered\n", copy);
04187    } else if (!acfptr->read && !acfptr->read2) {
04188       ast_log(LOG_ERROR, "Function %s cannot be read\n", copy);
04189    } else if (!is_read_allowed(acfptr)) {
04190       ast_log(LOG_ERROR, "Dangerous function %s read blocked\n", copy);
04191    } else if (acfptr->read) {
04192       if (acfptr->mod) {
04193          u = __ast_module_user_add(acfptr->mod, chan);
04194       }
04195       res = acfptr->read(chan, copy, args, workspace, len);
04196       if (acfptr->mod && u) {
04197          __ast_module_user_remove(acfptr->mod, u);
04198       }
04199       return res;
04200    } else {
04201       struct ast_str *str = ast_str_create(16);
04202       if (acfptr->mod) {
04203          u = __ast_module_user_add(acfptr->mod, chan);
04204       }
04205       res = acfptr->read2(chan, copy, args, &str, 0);
04206       if (acfptr->mod && u) {
04207          __ast_module_user_remove(acfptr->mod, u);
04208       }
04209       ast_copy_string(workspace, ast_str_buffer(str), len > ast_str_size(str) ? ast_str_size(str) : len);
04210       ast_free(str);
04211       return res;
04212    }
04213    return -1;
04214 }

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

04217 {
04218    char *copy = ast_strdupa(function);
04219    char *args = func_args(copy);
04220    struct ast_custom_function *acfptr = ast_custom_function_find(copy);
04221    int res;
04222    struct ast_module_user *u = NULL;
04223 
04224    if (acfptr == NULL) {
04225       ast_log(LOG_ERROR, "Function %s not registered\n", copy);
04226    } else if (!acfptr->read && !acfptr->read2) {
04227       ast_log(LOG_ERROR, "Function %s cannot be read\n", copy);
04228    } else if (!is_read_allowed(acfptr)) {
04229       ast_log(LOG_ERROR, "Dangerous function %s read blocked\n", copy);
04230    } else {
04231       if (acfptr->mod) {
04232          u = __ast_module_user_add(acfptr->mod, chan);
04233       }
04234       ast_str_reset(*str);
04235       if (acfptr->read2) {
04236          /* ast_str enabled */
04237          res = acfptr->read2(chan, copy, args, str, maxlen);
04238       } else {
04239          /* Legacy function pointer, allocate buffer for result */
04240          int maxsize = ast_str_size(*str);
04241          if (maxlen > -1) {
04242             if (maxlen == 0) {
04243                if (acfptr->read_max) {
04244                   maxsize = acfptr->read_max;
04245                } else {
04246                   maxsize = VAR_BUF_SIZE;
04247                }
04248             } else {
04249                maxsize = maxlen;
04250             }
04251             ast_str_make_space(str, maxsize);
04252          }
04253          res = acfptr->read(chan, copy, args, ast_str_buffer(*str), maxsize);
04254       }
04255       if (acfptr->mod && u) {
04256          __ast_module_user_remove(acfptr->mod, u);
04257       }
04258       return res;
04259    }
04260    return -1;
04261 }

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

04264 {
04265    char *copy = ast_strdupa(function);
04266    char *args = func_args(copy);
04267    struct ast_custom_function *acfptr = ast_custom_function_find(copy);
04268 
04269    if (acfptr == NULL) {
04270       ast_log(LOG_ERROR, "Function %s not registered\n", copy);
04271    } else if (!acfptr->write) {
04272       ast_log(LOG_ERROR, "Function %s cannot be written to\n", copy);
04273    } else if (!is_write_allowed(acfptr)) {
04274       ast_log(LOG_ERROR, "Dangerous function %s write blocked\n", copy);
04275    } else {
04276       int res;
04277       struct ast_module_user *u = NULL;
04278       if (acfptr->mod)
04279          u = __ast_module_user_add(acfptr->mod, chan);
04280       res = acfptr->write(chan, copy, args, value);
04281       if (acfptr->mod && u)
04282          __ast_module_user_remove(acfptr->mod, u);
04283       return res;
04284    }
04285 
04286    return -1;
04287 }

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

Definition at line 11111 of file pbx.c.

References ast_context::registrar.

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

11112 {
11113    return c ? c->registrar : NULL;
11114 }

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

References ast_exten::cidmatch.

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

11137 {
11138    return e ? e->cidmatch : NULL;
11139 }

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

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

11079 {
11080    return exten ? exten->parent : NULL;
11081 }

const char* ast_get_extension_label ( struct ast_exten e  ) 

Definition at line 11088 of file pbx.c.

References ast_exten::label.

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

11089 {
11090    return exten ? exten->label : NULL;
11091 }

int ast_get_extension_matchcid ( struct ast_exten e  ) 

Definition at line 11131 of file pbx.c.

References ast_exten::matchcid.

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

11132 {
11133    return e ? e->matchcid : 0;
11134 }

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

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

11104 {
11105    return exten ? exten->priority : -1;
11106 }

const char* ast_get_extension_registrar ( struct ast_exten e  ) 

Definition at line 11116 of file pbx.c.

References ast_exten::registrar.

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

11117 {
11118    return e ? e->registrar : NULL;
11119 }

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

05363 {
05364    struct ast_exten *e = ast_hint_extension(c, context, exten);
05365 
05366    if (e) {
05367       if (hint)
05368          ast_copy_string(hint, ast_get_extension_app(e), hintsize);
05369       if (name) {
05370          const char *tmp = ast_get_extension_app_data(e);
05371          if (tmp)
05372             ast_copy_string(name, tmp, namesize);
05373       }
05374       return -1;
05375    }
05376    return 0;
05377 }

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

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

11127 {
11128    return ip ? ip->registrar : NULL;
11129 }

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

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

11122 {
11123    return i ? i->registrar : NULL;
11124 }

const char* ast_get_switch_data ( struct ast_sw sw  ) 

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

11157 {
11158    return sw ? sw->data : NULL;
11159 }

int ast_get_switch_eval ( struct ast_sw sw  ) 

Definition at line 11161 of file pbx.c.

References ast_sw::eval.

Referenced by context_merge_incls_swits_igps_other_registrars().

11162 {
11163    return sw->eval;
11164 }

const char* ast_get_switch_name ( struct ast_sw sw  ) 

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

11152 {
11153    return sw ? sw->name : NULL;
11154 }

const char* ast_get_switch_registrar ( struct ast_sw sw  ) 

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

11167 {
11168    return sw ? sw->registrar : NULL;
11169 }

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

11262 {
11263    return __ast_goto_if_exists(chan, context, exten, priority, 0);
11264 }

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

hashtable functions for contexts

Definition at line 1136 of file pbx.c.

References ast_context::name.

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

01137 {
01138    const struct ast_context *ac = ah_a;
01139    const struct ast_context *bc = ah_b;
01140    if (!ac || !bc) /* safety valve, but it might prevent a crash you'd rather have happen */
01141       return 1;
01142    /* assume context names are registered in a string table! */
01143    return strcmp(ac->name, bc->name);
01144 }

unsigned int ast_hashtab_hash_contexts ( const void *  obj  ) 

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

01189 {
01190    const struct ast_context *ac = obj;
01191    return ast_hashtab_hash_string(ac->name);
01192 }

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

08651 {
08652    struct ast_context *con = ast_context_find(context);
08653 
08654    if (con) {
08655       struct ast_ignorepat *pat;
08656 
08657       for (pat = con->ignorepats; pat; pat = pat->next) {
08658          if (ast_extension_match(pat->pattern, pattern))
08659             return 1;
08660       }
08661    }
08662 
08663    return 0;
08664 }

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

05421 {
05422    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0);
05423 }

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

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

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

11327 {
11328    return pbx_parseable_goto(chan, goto_string, 0);
11329 }

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

09545 {
09546    struct ast_channel *chan;
09547    struct app_tmp *tmp;
09548    int res = -1, cdr_res = -1;
09549    struct outgoing_helper oh;
09550 
09551    memset(&oh, 0, sizeof(oh));
09552    oh.vars = vars;
09553    oh.account = account;
09554 
09555    if (locked_channel)
09556       *locked_channel = NULL;
09557    if (ast_strlen_zero(app)) {
09558       res = -1;
09559       goto outgoing_app_cleanup;
09560    }
09561    if (synchronous) {
09562       chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh);
09563       if (chan) {
09564          ast_set_variables(chan, vars);
09565          if (account)
09566             ast_cdr_setaccount(chan, account);
09567          if (chan->_state == AST_STATE_UP) {
09568             res = 0;
09569             ast_verb(4, "Channel %s was answered.\n", chan->name);
09570             tmp = ast_calloc(1, sizeof(*tmp));
09571             if (!tmp || ast_string_field_init(tmp, 252)) {
09572                if (tmp) {
09573                   ast_free(tmp);
09574                }
09575                res = -1;
09576             } else {
09577                ast_string_field_set(tmp, app, app);
09578                ast_string_field_set(tmp, data, appdata);
09579                tmp->chan = chan;
09580                if (synchronous > 1) {
09581                   if (locked_channel)
09582                      ast_channel_unlock(chan);
09583                   ast_pbx_run_app(tmp);
09584                } else {
09585                   if (locked_channel)
09586                      ast_channel_lock(chan);
09587                   if (ast_pthread_create_detached(&tmp->t, NULL, ast_pbx_run_app, tmp)) {
09588                      ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno));
09589                      ast_string_field_free_memory(tmp);
09590                      ast_free(tmp);
09591                      if (locked_channel)
09592                         ast_channel_unlock(chan);
09593                      ast_hangup(chan);
09594                      res = -1;
09595                   } else {
09596                      if (locked_channel)
09597                         *locked_channel = chan;
09598                   }
09599                }
09600             }
09601          } else {
09602             ast_verb(4, "Channel %s was never answered.\n", chan->name);
09603             if (chan->cdr) { /* update the cdr */
09604                /* here we update the status of the call, which sould be busy.
09605                 * if that fails then we set the status to failed */
09606                if (ast_cdr_disposition(chan->cdr, chan->hangupcause))
09607                   ast_cdr_failed(chan->cdr);
09608             }
09609             ast_hangup(chan);
09610          }
09611       }
09612 
09613       if (res < 0) { /* the call failed for some reason */
09614          if (*reason == 0) { /* if the call failed (not busy or no answer)
09615                         * update the cdr with the failed message */
09616             cdr_res = ast_pbx_outgoing_cdr_failed();
09617             if (cdr_res != 0) {
09618                res = cdr_res;
09619                goto outgoing_app_cleanup;
09620             }
09621          }
09622       }
09623 
09624    } else {
09625       struct async_stat *as;
09626       if (!(as = ast_calloc(1, sizeof(*as)))) {
09627          res = -1;
09628          goto outgoing_app_cleanup;
09629       }
09630       chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh);
09631       if (!chan) {
09632          ast_free(as);
09633          res = -1;
09634          goto outgoing_app_cleanup;
09635       }
09636       as->chan = chan;
09637       ast_copy_string(as->app, app, sizeof(as->app));
09638       if (appdata)
09639          ast_copy_string(as->appdata,  appdata, sizeof(as->appdata));
09640       as->timeout = timeout;
09641       ast_set_variables(chan, vars);
09642       if (account)
09643          ast_cdr_setaccount(chan, account);
09644       /* Start a new thread, and get something handling this channel. */
09645       if (locked_channel)
09646          ast_channel_lock(chan);
09647       if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) {
09648          ast_log(LOG_WARNING, "Failed to start async wait\n");
09649          ast_free(as);
09650          if (locked_channel)
09651             ast_channel_unlock(chan);
09652          ast_hangup(chan);
09653          res = -1;
09654          goto outgoing_app_cleanup;
09655       } else {
09656          if (locked_channel)
09657             *locked_channel = chan;
09658       }
09659       res = 0;
09660    }
09661 outgoing_app_cleanup:
09662    ast_variables_destroy(vars);
09663    return res;
09664 }

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

09376 {
09377    struct ast_channel *chan;
09378    struct async_stat *as;
09379    int res = -1, cdr_res = -1;
09380    struct outgoing_helper oh;
09381 
09382    if (synchronous) {
09383       oh.context = context;
09384       oh.exten = exten;
09385       oh.priority = priority;
09386       oh.cid_num = cid_num;
09387       oh.cid_name = cid_name;
09388       oh.account = account;
09389       oh.vars = vars;
09390       oh.parent_channel = NULL;
09391 
09392       chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh);
09393       if (channel) {
09394          *channel = chan;
09395          if (chan)
09396             ast_channel_lock(chan);
09397       }
09398       if (chan) {
09399          if (chan->_state == AST_STATE_UP) {
09400                res = 0;
09401             ast_verb(4, "Channel %s was answered.\n", chan->name);
09402 
09403             if (synchronous > 1) {
09404                if (channel)
09405                   ast_channel_unlock(chan);
09406                if (ast_pbx_run(chan)) {
09407                   ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name);
09408                   if (channel)
09409                      *channel = NULL;
09410                   ast_hangup(chan);
09411                   chan = NULL;
09412                   res = -1;
09413                }
09414             } else {
09415                if (ast_pbx_start(chan)) {
09416                   ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name);
09417                   if (channel) {
09418                      *channel = NULL;
09419                      ast_channel_unlock(chan);
09420                   }
09421                   ast_hangup(chan);
09422                   res = -1;
09423                }
09424                chan = NULL;
09425             }
09426          } else {
09427             ast_verb(4, "Channel %s was never answered.\n", chan->name);
09428 
09429             if (chan->cdr) { /* update the cdr */
09430                /* here we update the status of the call, which sould be busy.
09431                 * if that fails then we set the status to failed */
09432                if (ast_cdr_disposition(chan->cdr, chan->hangupcause))
09433                   ast_cdr_failed(chan->cdr);
09434             }
09435 
09436             if (channel) {
09437                *channel = NULL;
09438                ast_channel_unlock(chan);
09439             }
09440             ast_hangup(chan);
09441             chan = NULL;
09442          }
09443       }
09444 
09445       if (res < 0) { /* the call failed for some reason */
09446          if (*reason == 0) { /* if the call failed (not busy or no answer)
09447                         * update the cdr with the failed message */
09448             cdr_res = ast_pbx_outgoing_cdr_failed();
09449             if (cdr_res != 0) {
09450                res = cdr_res;
09451                goto outgoing_exten_cleanup;
09452             }
09453          }
09454 
09455          /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */
09456          /* check if "failed" exists */
09457          if (ast_exists_extension(chan, context, "failed", 1, NULL)) {
09458             chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", NULL, 0, "OutgoingSpoolFailed");
09459             if (chan) {
09460                char failed_reason[4] = "";
09461                if (!ast_strlen_zero(context))
09462                   ast_copy_string(chan->context, context, sizeof(chan->context));
09463                set_ext_pri(chan, "failed", 1);
09464                ast_set_variables(chan, vars);
09465                snprintf(failed_reason, sizeof(failed_reason), "%d", *reason);
09466                pbx_builtin_setvar_helper(chan, "REASON", failed_reason);
09467                if (account)
09468                   ast_cdr_setaccount(chan, account);
09469                if (ast_pbx_run(chan)) {
09470                   ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name);
09471                   ast_hangup(chan);
09472                }
09473                chan = NULL;
09474             }
09475          }
09476       }
09477    } else {
09478       if (!(as = ast_calloc(1, sizeof(*as)))) {
09479          res = -1;
09480          goto outgoing_exten_cleanup;
09481       }
09482       chan = ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name);
09483       if (channel) {
09484          *channel = chan;
09485          if (chan)
09486             ast_channel_lock(chan);
09487       }
09488       if (!chan) {
09489          ast_free(as);
09490          res = -1;
09491          goto outgoing_exten_cleanup;
09492       }
09493       as->chan = chan;
09494       ast_copy_string(as->context, context, sizeof(as->context));
09495       set_ext_pri(as->chan,  exten, priority);
09496       as->timeout = timeout;
09497       ast_set_variables(chan, vars);
09498       if (account)
09499          ast_cdr_setaccount(chan, account);
09500       if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) {
09501          ast_log(LOG_WARNING, "Failed to start async wait\n");
09502          ast_free(as);
09503          if (channel) {
09504             *channel = NULL;
09505             ast_channel_unlock(chan);
09506          }
09507          ast_hangup(chan);
09508          res = -1;
09509          goto outgoing_exten_cleanup;
09510       }
09511       res = 0;
09512    }
09513 outgoing_exten_cleanup:
09514    ast_variables_destroy(vars);
09515    return res;
09516 }

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

05927 {
05928    return ast_pbx_run_args(c, NULL);
05929 }

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

05907 {
05908    enum ast_pbx_result res = AST_PBX_SUCCESS;
05909 
05910    if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) {
05911       ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n");
05912       return AST_PBX_FAILED;
05913    }
05914 
05915    if (increase_call_count(c)) {
05916       return AST_PBX_CALL_LIMIT;
05917    }
05918 
05919    res = __ast_pbx_run(c, args);
05920 
05921    decrease_call_count();
05922 
05923    return res;
05924 }

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

05880 {
05881    pthread_t t;
05882 
05883    if (!c) {
05884       ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
05885       return AST_PBX_FAILED;
05886    }
05887 
05888    if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) {
05889       ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n");
05890       return AST_PBX_FAILED;
05891    }
05892 
05893    if (increase_call_count(c))
05894       return AST_PBX_CALL_LIMIT;
05895 
05896    /* Start a new thread, and get something handling this channel. */
05897    if (ast_pthread_create_detached(&t, NULL, pbx_thread, c)) {
05898       ast_log(LOG_WARNING, "Failed to create new channel thread\n");
05899       decrease_call_count();
05900       return AST_PBX_FAILED;
05901    }
05902 
05903    return AST_PBX_SUCCESS;
05904 }

int ast_processed_calls ( void   ) 

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

Definition at line 5936 of file pbx.c.

References totalcalls.

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

05937 {
05938    return totalcalls;
05939 }

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

11061 {
11062    return ast_rwlock_rdlock(&con->lock);
11063 }

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

06440 {
06441    struct ast_switch *tmp;
06442 
06443    AST_RWLIST_WRLOCK(&switches);
06444    AST_RWLIST_TRAVERSE(&switches, tmp, list) {
06445       if (!strcasecmp(tmp->name, sw->name)) {
06446          AST_RWLIST_UNLOCK(&switches);
06447          ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name);
06448          return -1;
06449       }
06450    }
06451    AST_RWLIST_INSERT_TAIL(&switches, sw, list);
06452    AST_RWLIST_UNLOCK(&switches);
06453 
06454    return 0;
06455 }

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

05426 {
05427    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN, found, combined_find_spawn);
05428 }

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

05381 {
05382    struct ast_exten *e = ast_hint_extension(c, context, exten);
05383 
05384    if (!e) {
05385       return 0;
05386    }
05387 
05388    if (hint) {
05389       ast_str_set(hint, hintsize, "%s", ast_get_extension_app(e));
05390    }
05391    if (name) {
05392       const char *tmp = ast_get_extension_app_data(e);
05393       if (tmp) {
05394          ast_str_set(name, namesize, "%s", tmp);
05395       }
05396    }
05397    return -1;
05398 }

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

03446 {
03447    const char not_found = '\0';
03448    char *tmpvar;
03449    const char *ret;
03450    const char *s; /* the result */
03451    int offset, length;
03452    int i, need_substring;
03453    struct varshead *places[2] = { headp, &globals };  /* list of places where we may look */
03454    char workspace[20];
03455 
03456    if (c) {
03457       ast_channel_lock(c);
03458       places[0] = &c->varshead;
03459    }
03460    /*
03461     * Make a copy of var because parse_variable_name() modifies the string.
03462     * Then if called directly, we might need to run substring() on the result;
03463     * remember this for later in 'need_substring', 'offset' and 'length'
03464     */
03465    tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */
03466    need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */);
03467 
03468    /*
03469     * Look first into predefined variables, then into variable lists.
03470     * Variable 's' points to the result, according to the following rules:
03471     * s == &not_found (set at the beginning) means that we did not find a
03472     * matching variable and need to look into more places.
03473     * If s != &not_found, s is a valid result string as follows:
03474     * s = NULL if the variable does not have a value;
03475     * you typically do this when looking for an unset predefined variable.
03476     * s = workspace if the result has been assembled there;
03477     * typically done when the result is built e.g. with an snprintf(),
03478     * so we don't need to do an additional copy.
03479     * s != workspace in case we have a string, that needs to be copied
03480     * (the ast_copy_string is done once for all at the end).
03481     * Typically done when the result is already available in some string.
03482     */
03483    s = &not_found;   /* default value */
03484    if (c) { /* This group requires a valid channel */
03485       /* Names with common parts are looked up a piece at a time using strncmp. */
03486       if (!strncmp(var, "CALL", 4)) {
03487          if (!strncmp(var + 4, "ING", 3)) {
03488             if (!strcmp(var + 7, "PRES")) {        /* CALLINGPRES */
03489                ast_str_set(str, maxlen, "%d",
03490                   ast_party_id_presentation(&c->caller.id));
03491                s = ast_str_buffer(*str);
03492             } else if (!strcmp(var + 7, "ANI2")) {    /* CALLINGANI2 */
03493                ast_str_set(str, maxlen, "%d", c->caller.ani2);
03494                s = ast_str_buffer(*str);
03495             } else if (!strcmp(var + 7, "TON")) {     /* CALLINGTON */
03496                ast_str_set(str, maxlen, "%d", c->caller.id.number.plan);
03497                s = ast_str_buffer(*str);
03498             } else if (!strcmp(var + 7, "TNS")) {     /* CALLINGTNS */
03499                ast_str_set(str, maxlen, "%d", c->dialed.transit_network_select);
03500                s = ast_str_buffer(*str);
03501             }
03502          }
03503       } else if (!strcmp(var, "HINT")) {
03504          s = ast_str_get_hint(str, maxlen, NULL, 0, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL;
03505       } else if (!strcmp(var, "HINTNAME")) {
03506          s = ast_str_get_hint(NULL, 0, str, maxlen, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL;
03507       } else if (!strcmp(var, "EXTEN")) {
03508          s = c->exten;
03509       } else if (!strcmp(var, "CONTEXT")) {
03510          s = c->context;
03511       } else if (!strcmp(var, "PRIORITY")) {
03512          ast_str_set(str, maxlen, "%d", c->priority);
03513          s = ast_str_buffer(*str);
03514       } else if (!strcmp(var, "CHANNEL")) {
03515          s = c->name;
03516       } else if (!strcmp(var, "UNIQUEID")) {
03517          s = c->uniqueid;
03518       } else if (!strcmp(var, "HANGUPCAUSE")) {
03519          ast_str_set(str, maxlen, "%d", c->hangupcause);
03520          s = ast_str_buffer(*str);
03521       }
03522    }
03523    if (s == &not_found) { /* look for more */
03524       if (!strcmp(var, "EPOCH")) {
03525          ast_str_set(str, maxlen, "%d", (int) time(NULL));
03526          s = ast_str_buffer(*str);
03527       } else if (!strcmp(var, "SYSTEMNAME")) {
03528          s = ast_config_AST_SYSTEM_NAME;
03529       } else if (!strcmp(var, "ENTITYID")) {
03530          ast_eid_to_str(workspace, sizeof(workspace), &ast_eid_default);
03531          s = workspace;
03532       }
03533    }
03534    /* if not found, look into chanvars or global vars */
03535    for (i = 0; s == &not_found && i < ARRAY_LEN(places); i++) {
03536       struct ast_var_t *variables;
03537       if (!places[i])
03538          continue;
03539       if (places[i] == &globals)
03540          ast_rwlock_rdlock(&globalslock);
03541       AST_LIST_TRAVERSE(places[i], variables, entries) {
03542          if (!strcasecmp(ast_var_name(variables), var)) {
03543             s = ast_var_value(variables);
03544             break;
03545          }
03546       }
03547       if (places[i] == &globals)
03548          ast_rwlock_unlock(&globalslock);
03549    }
03550    if (s == &not_found || s == NULL) {
03551       ast_debug(5, "Result of '%s' is NULL\n", var);
03552       ret = NULL;
03553    } else {
03554       ast_debug(5, "Result of '%s' is '%s'\n", var, s);
03555       if (s != ast_str_buffer(*str)) {
03556          ast_str_set(str, maxlen, "%s", s);
03557       }
03558       ret = ast_str_buffer(*str);
03559       if (need_substring) {
03560          ret = ast_str_substring(*str, offset, length);
03561          ast_debug(2, "Final result of '%s' is '%s'\n", var, ret);
03562       }
03563    }
03564 
03565    if (c) {
03566       ast_channel_unlock(c);
03567    }
03568    return ret;
03569 }

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

04469 {
04470    size_t used;
04471    ast_str_substitute_variables_full(buf, maxlen, chan, NULL, templ, &used);
04472 }

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

04290 {
04291    /* Substitutes variables into buf, based on string templ */
04292    char *cp4 = NULL;
04293    const char *tmp, *whereweare;
04294    int orig_size = 0;
04295    int offset, offset2, isfunction;
04296    const char *nextvar, *nextexp, *nextthing;
04297    const char *vars, *vare;
04298    char *finalvars;
04299    int pos, brackets, needsub, len;
04300    struct ast_str *substr1 = ast_str_create(16), *substr2 = NULL, *substr3 = ast_str_create(16);
04301 
04302    ast_str_reset(*buf);
04303    whereweare = tmp = templ;
04304    while (!ast_strlen_zero(whereweare)) {
04305       /* reset our buffer */
04306       ast_str_reset(substr3);
04307 
04308       /* Assume we're copying the whole remaining string */
04309       pos = strlen(whereweare);
04310       nextvar = NULL;
04311       nextexp = NULL;
04312       nextthing = strchr(whereweare, '$');
04313       if (nextthing) {
04314          switch (nextthing[1]) {
04315          case '{':
04316             nextvar = nextthing;
04317             pos = nextvar - whereweare;
04318             break;
04319          case '[':
04320             nextexp = nextthing;
04321             pos = nextexp - whereweare;
04322             break;
04323          default:
04324             pos = 1;
04325          }
04326       }
04327 
04328       if (pos) {
04329          /* Copy that many bytes */
04330          ast_str_append_substr(buf, maxlen, whereweare, pos);
04331 
04332          templ += pos;
04333          whereweare += pos;
04334       }
04335 
04336       if (nextvar) {
04337          /* We have a variable.  Find the start and end, and determine
04338             if we are going to have to recursively call ourselves on the
04339             contents */
04340          vars = vare = nextvar + 2;
04341          brackets = 1;
04342          needsub = 0;
04343 
04344          /* Find the end of it */
04345          while (brackets && *vare) {
04346             if ((vare[0] == '$') && (vare[1] == '{')) {
04347                needsub++;
04348             } else if (vare[0] == '{') {
04349                brackets++;
04350             } else if (vare[0] == '}') {
04351                brackets--;
04352             } else if ((vare[0] == '$') && (vare[1] == '['))
04353                needsub++;
04354             vare++;
04355          }
04356          if (brackets)
04357             ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n");
04358          len = vare - vars - 1;
04359 
04360          /* Skip totally over variable string */
04361          whereweare += (len + 3);
04362 
04363          /* Store variable name (and truncate) */
04364          ast_str_set_substr(&substr1, 0, vars, len);
04365          ast_debug(5, "Evaluating '%s' (from '%s' len %d)\n", ast_str_buffer(substr1), vars, len);
04366 
04367          /* Substitute if necessary */
04368          if (needsub) {
04369             size_t used;
04370             if (!substr2) {
04371                substr2 = ast_str_create(16);
04372             }
04373 
04374             ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used);
04375             finalvars = ast_str_buffer(substr2);
04376          } else {
04377             finalvars = ast_str_buffer(substr1);
04378          }
04379 
04380          parse_variable_name(finalvars, &offset, &offset2, &isfunction);
04381          if (isfunction) {
04382             /* Evaluate function */
04383             if (c || !headp) {
04384                cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3);
04385             } else {
04386                struct varshead old;
04387                struct ast_channel *bogus = ast_dummy_channel_alloc();
04388                if (bogus) {
04389                   memcpy(&old, &bogus->varshead, sizeof(old));
04390                   memcpy(&bogus->varshead, headp, sizeof(bogus->varshead));
04391                   cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3);
04392                   /* Don't deallocate the varshead that was passed in */
04393                   memcpy(&bogus->varshead, &old, sizeof(bogus->varshead));
04394                   ast_channel_unref(bogus);
04395                } else {
04396                   ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution.  Function results may be blank.\n");
04397                }
04398             }
04399             ast_debug(2, "Function %s result is '%s'\n", finalvars, cp4 ? cp4 : "(null)");
04400          } else {
04401             /* Retrieve variable value */
04402             ast_str_retrieve_variable(&substr3, 0, c, headp, finalvars);
04403             cp4 = ast_str_buffer(substr3);
04404          }
04405          if (cp4) {
04406             ast_str_substring(substr3, offset, offset2);
04407             ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3));
04408          }
04409       } else if (nextexp) {
04410          /* We have an expression.  Find the start and end, and determine
04411             if we are going to have to recursively call ourselves on the
04412             contents */
04413          vars = vare = nextexp + 2;
04414          brackets = 1;
04415          needsub = 0;
04416 
04417          /* Find the end of it */
04418          while (brackets && *vare) {
04419             if ((vare[0] == '$') && (vare[1] == '[')) {
04420                needsub++;
04421                brackets++;
04422                vare++;
04423             } else if (vare[0] == '[') {
04424                brackets++;
04425             } else if (vare[0] == ']') {
04426                brackets--;
04427             } else if ((vare[0] == '$') && (vare[1] == '{')) {
04428                needsub++;
04429                vare++;
04430             }
04431             vare++;
04432          }
04433          if (brackets)
04434             ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n");
04435          len = vare - vars - 1;
04436 
04437          /* Skip totally over expression */
04438          whereweare += (len + 3);
04439 
04440          /* Store variable name (and truncate) */
04441          ast_str_set_substr(&substr1, 0, vars, len);
04442 
04443          /* Substitute if necessary */
04444          if (needsub) {
04445             size_t used;
04446             if (!substr2) {
04447                substr2 = ast_str_create(16);
04448             }
04449 
04450             ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used);
04451             finalvars = ast_str_buffer(substr2);
04452          } else {
04453             finalvars = ast_str_buffer(substr1);
04454          }
04455 
04456          if (ast_str_expr(&substr3, 0, c, finalvars)) {
04457             ast_debug(2, "Expression result is '%s'\n", ast_str_buffer(substr3));
04458          }
04459          ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3));
04460       }
04461    }
04462    *used = ast_str_strlen(*buf) - orig_size;
04463    ast_free(substr1);
04464    ast_free(substr2);
04465    ast_free(substr3);
04466 }

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

04475 {
04476    size_t used;
04477    ast_str_substitute_variables_full(buf, maxlen, NULL, headp, templ, &used);
04478 }

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

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

Referenced by handle_tcptls_connection().

04073 {
04074    int *thread_inhibit_escalations;
04075 
04076    thread_inhibit_escalations = ast_threadstorage_get(
04077       &thread_inhibit_escalations_tl, sizeof(*thread_inhibit_escalations));
04078 
04079    if (thread_inhibit_escalations == NULL) {
04080       ast_log(LOG_ERROR, "Error inhibiting privilege escalations for current thread\n");
04081       return -1;
04082    }
04083 
04084    *thread_inhibit_escalations = 1;
04085    return 0;
04086 }

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

References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

Referenced by __unload_module(), and unload_module().

06458 {
06459    AST_RWLIST_WRLOCK(&switches);
06460    AST_RWLIST_REMOVE(&switches, sw, list);
06461    AST_RWLIST_UNLOCK(&switches);
06462 }

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

11214 {
11215    if (!ip)
11216       return con ? con->ignorepats : NULL;
11217    else
11218       return ip->next;
11219 }

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

11190 {
11191    if (!sw)
11192       return con ? AST_LIST_FIRST(&con->alts) : NULL;
11193    else
11194       return AST_LIST_NEXT(sw, list);
11195 }

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

11199 {
11200    return priority ? priority->peer : exten;
11201 }

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

11056 {
11057    return ast_rwlock_wrlock(&con->lock);
11058 }

int ast_wrlock_contexts ( void   ) 

Write locks the context list.

Return values:
0 on success
-1 on error

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

11038 {
11039    return ast_mutex_lock(&conlock);
11040 }

void pbx_builtin_clear_globals ( void   ) 

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

10710 {
10711    struct ast_var_t *vardata;
10712 
10713    ast_rwlock_wrlock(&globalslock);
10714    while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries)))
10715       ast_var_delete(vardata);
10716    ast_rwlock_unlock(&globalslock);
10717 }

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

10476 {
10477    struct ast_var_t *variables;
10478    const char *ret = NULL;
10479    int i;
10480    struct varshead *places[2] = { NULL, &globals };
10481 
10482    if (!name)
10483       return NULL;
10484 
10485    if (chan) {
10486       ast_channel_lock(chan);
10487       places[0] = &chan->varshead;
10488    }
10489 
10490    for (i = 0; i < 2; i++) {
10491       if (!places[i])
10492          continue;
10493       if (places[i] == &globals)
10494          ast_rwlock_rdlock(&globalslock);
10495       AST_LIST_TRAVERSE(places[i], variables, entries) {
10496          if (!strcmp(name, ast_var_name(variables))) {
10497             ret = ast_var_value(variables);
10498             break;
10499          }
10500       }
10501       if (places[i] == &globals)
10502          ast_rwlock_unlock(&globalslock);
10503       if (ret)
10504          break;
10505    }
10506 
10507    if (chan)
10508       ast_channel_unlock(chan);
10509 
10510    return ret;
10511 }

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

10514 {
10515    struct ast_var_t *newvariable;
10516    struct varshead *headp;
10517 
10518    if (name[strlen(name)-1] == ')') {
10519       char *function = ast_strdupa(name);
10520 
10521       ast_log(LOG_WARNING, "Cannot push a value onto a function\n");
10522       ast_func_write(chan, function, value);
10523       return;
10524    }
10525 
10526    if (chan) {
10527       ast_channel_lock(chan);
10528       headp = &chan->varshead;
10529    } else {
10530       ast_rwlock_wrlock(&globalslock);
10531       headp = &globals;
10532    }
10533 
10534    if (value && (newvariable = ast_var_assign(name, value))) {
10535       if (headp == &globals)
10536          ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value);
10537       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
10538    }
10539 
10540    if (chan)
10541       ast_channel_unlock(chan);
10542    else
10543       ast_rwlock_unlock(&globalslock);
10544 }

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

Definition at line 3620 of file pbx.c.

References raise_exception().

03621 {
03622    /* Priority will become 1, next time through the AUTOLOOP */
03623    return raise_exception(chan, reason, 0);
03624 }

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

10445 {
10446    struct ast_var_t *variables;
10447    const char *var, *val;
10448    int total = 0;
10449 
10450    if (!chan)
10451       return 0;
10452 
10453    ast_str_reset(*buf);
10454 
10455    ast_channel_lock(chan);
10456 
10457    AST_LIST_TRAVERSE(&chan->varshead, variables, entries) {
10458       if ((var = ast_var_name(variables)) && (val = ast_var_value(variables))
10459          /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */
10460          ) {
10461          if (ast_str_append(buf, 0, "%s=%s\n", var, val) < 0) {
10462             ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
10463             break;
10464          } else
10465             total++;
10466       } else
10467          break;
10468    }
10469 
10470    ast_channel_unlock(chan);
10471 
10472    return total;
10473 }

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

10604 {
10605    char *name, *value, *mydata;
10606 
10607    if (ast_compat_app_set) {
10608       return pbx_builtin_setvar_multiple(chan, data);
10609    }
10610 
10611    if (ast_strlen_zero(data)) {
10612       ast_log(LOG_WARNING, "Set requires one variable name/value pair.\n");
10613       return 0;
10614    }
10615 
10616    mydata = ast_strdupa(data);
10617    name = strsep(&mydata, "=");
10618    value = mydata;
10619    if (!value) {
10620       ast_log(LOG_WARNING, "Set requires an '=' to be a valid assignment.\n");
10621       return 0;
10622    }
10623 
10624    if (strchr(name, ' ')) {
10625       ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, mydata);
10626    }
10627 
10628    pbx_builtin_setvar_helper(chan, name, value);
10629 
10630    return 0;
10631 }

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 10546 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_saydate(), pbx_builtin_saytime(), 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().

10547 {
10548    struct ast_var_t *newvariable;
10549    struct varshead *headp;
10550    const char *nametail = name;
10551 
10552    if (name[strlen(name) - 1] == ')') {
10553       char *function = ast_strdupa(name);
10554 
10555       return ast_func_write(chan, function, value);
10556    }
10557 
10558    if (chan) {
10559       ast_channel_lock(chan);
10560       headp = &chan->varshead;
10561    } else {
10562       ast_rwlock_wrlock(&globalslock);
10563       headp = &globals;
10564    }
10565 
10566    /* For comparison purposes, we have to strip leading underscores */
10567    if (*nametail == '_') {
10568       nametail++;
10569       if (*nametail == '_')
10570          nametail++;
10571    }
10572 
10573    AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) {
10574       if (strcmp(ast_var_name(newvariable), nametail) == 0) {
10575          /* there is already such a variable, delete it */
10576          AST_LIST_REMOVE_CURRENT(entries);
10577          ast_var_delete(newvariable);
10578          break;
10579       }
10580    }
10581    AST_LIST_TRAVERSE_SAFE_END;
10582 
10583    if (value && (newvariable = ast_var_assign(name, value))) {
10584       if (headp == &globals)
10585          ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value);
10586       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
10587       manager_event(EVENT_FLAG_DIALPLAN, "VarSet",
10588          "Channel: %s\r\n"
10589          "Variable: %s\r\n"
10590          "Value: %s\r\n"
10591          "Uniqueid: %s\r\n",
10592          chan ? chan->name : "none", name, value,
10593          chan ? chan->uniqueid : "none");
10594    }
10595 
10596    if (chan)
10597       ast_channel_unlock(chan);
10598    else
10599       ast_rwlock_unlock(&globalslock);
10600    return 0;
10601 }

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

10634 {
10635    char *data;
10636    int x;
10637    AST_DECLARE_APP_ARGS(args,
10638       AST_APP_ARG(pair)[24];
10639    );
10640    AST_DECLARE_APP_ARGS(pair,
10641       AST_APP_ARG(name);
10642       AST_APP_ARG(value);
10643    );
10644 
10645    if (ast_strlen_zero(vdata)) {
10646       ast_log(LOG_WARNING, "MSet requires at least one variable name/value pair.\n");
10647       return 0;
10648    }
10649 
10650    data = ast_strdupa(vdata);
10651    AST_STANDARD_APP_ARGS(args, data);
10652 
10653    for (x = 0; x < args.argc; x++) {
10654       AST_NONSTANDARD_APP_ARGS(pair, args.pair[x], '=');
10655       if (pair.argc == 2) {
10656          pbx_builtin_setvar_helper(chan, pair.name, pair.value);
10657          if (strchr(pair.name, ' '))
10658             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);
10659       } else if (!chan) {
10660          ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '='\n", pair.name);
10661       } else {
10662          ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '=' (in %s@%s:%d\n", pair.name, chan->exten, chan->context, chan->priority);
10663       }
10664    }
10665 
10666    return 0;
10667 }

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

10720 {
10721    int res;
10722    if (ast_strlen_zero(condition)) {                /* NULL or empty strings are false */
10723       return 0;
10724    } else if (sscanf(condition, "%30d", &res) == 1) { /* Numbers are evaluated for truth */
10725       return res;
10726    } else {                                         /* Strings are true */
10727       return 1;
10728    }
10729 }

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

01500 {
01501    int res;
01502    struct ast_module_user *u = NULL;
01503    const char *saved_c_appl;
01504    const char *saved_c_data;
01505 
01506    if (c->cdr && !ast_check_hangup(c))
01507       ast_cdr_setapp(c->cdr, app->name, data);
01508 
01509    /* save channel values */
01510    saved_c_appl= c->appl;
01511    saved_c_data= c->data;
01512 
01513    c->appl = app->name;
01514    c->data = data;
01515    ast_cel_report_event(c, AST_CEL_APP_START, NULL, NULL, NULL);
01516 
01517    if (app->module)
01518       u = __ast_module_user_add(app->module, c);
01519    if (strcasecmp(app->name, "system") && !ast_strlen_zero(data) &&
01520          strchr(data, '|') && !strchr(data, ',') && !ast_opt_dont_warn) {
01521       ast_log(LOG_WARNING, "The application delimiter is now the comma, not "
01522          "the pipe.  Did you forget to convert your dialplan?  (%s(%s))\n",
01523          app->name, (char *) data);
01524    }
01525    res = app->execute(c, S_OR(data, ""));
01526    if (app->module && u)
01527       __ast_module_user_remove(app->module, u);
01528    ast_cel_report_event(c, AST_CEL_APP_END, NULL, NULL, NULL);
01529    /* restore channel values */
01530    c->appl = saved_c_appl;
01531    c->data = saved_c_data;
01532    return res;
01533 }

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

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

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

01538 {
01539    struct ast_app *tmp;
01540 
01541    AST_RWLIST_RDLOCK(&apps);
01542    AST_RWLIST_TRAVERSE(&apps, tmp, list) {
01543       if (!strcasecmp(tmp->name, app))
01544          break;
01545    }
01546    AST_RWLIST_UNLOCK(&apps);
01547 
01548    return tmp;
01549 }

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

References ast_log(), LOG_NOTICE, and LOG_WARNING.

Referenced by ast_readconfig().

04060 {
04061    if (new_live_dangerously && !live_dangerously) {
04062       ast_log(LOG_WARNING, "Privilege escalation protection disabled!\n"
04063          "See https://wiki.asterisk.org/wiki/x/1gKfAQ for more details.\n");
04064    }
04065 
04066    if (!new_live_dangerously && live_dangerously) {
04067       ast_log(LOG_NOTICE, "Privilege escalation protection enabled.\n");
04068    }
04069    live_dangerously = new_live_dangerously;
04070 }

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

03435 {
03436    struct ast_str *str = ast_str_create(16);
03437    const char *cret;
03438 
03439    cret = ast_str_retrieve_variable(&str, 0, c, headp, var);
03440    ast_copy_string(workspace, ast_str_buffer(str), workspacelen);
03441    *ret = cret ? workspace : NULL;
03442    ast_free(str);
03443 }

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

References autofallthrough.

Referenced by pbx_load_module().

05942 {
05943    int oldval = autofallthrough;
05944    autofallthrough = newval;
05945    return oldval;
05946 }

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

References extenpatternmatchnew.

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

05949 {
05950    int oldval = extenpatternmatchnew;
05951    extenpatternmatchnew = newval;
05952    return oldval;
05953 }

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

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

Referenced by pbx_load_module().

05956 {
05957    if (overrideswitch) {
05958       ast_free(overrideswitch);
05959    }
05960    if (!ast_strlen_zero(newval)) {
05961       overrideswitch = ast_strdup(newval);
05962    } else {
05963       overrideswitch = NULL;
05964    }
05965 }

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

04481 {
04482    /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!!  */
04483    char *cp4 = NULL;
04484    const char *tmp, *whereweare, *orig_cp2 = cp2;
04485    int length, offset, offset2, isfunction;
04486    char *workspace = NULL;
04487    char *ltmp = NULL, *var = NULL;
04488    char *nextvar, *nextexp, *nextthing;
04489    char *vars, *vare;
04490    int pos, brackets, needsub, len;
04491 
04492    *cp2 = 0; /* just in case nothing ends up there */
04493    whereweare=tmp=cp1;
04494    while (!ast_strlen_zero(whereweare) && count) {
04495       /* Assume we're copying the whole remaining string */
04496       pos = strlen(whereweare);
04497       nextvar = NULL;
04498       nextexp = NULL;
04499       nextthing = strchr(whereweare, '$');
04500       if (nextthing) {
04501          switch (nextthing[1]) {
04502          case '{':
04503             nextvar = nextthing;
04504             pos = nextvar - whereweare;
04505             break;
04506          case '[':
04507             nextexp = nextthing;
04508             pos = nextexp - whereweare;
04509             break;
04510          default:
04511             pos = 1;
04512          }
04513       }
04514 
04515       if (pos) {
04516          /* Can't copy more than 'count' bytes */
04517          if (pos > count)
04518             pos = count;
04519 
04520          /* Copy that many bytes */
04521          memcpy(cp2, whereweare, pos);
04522 
04523          count -= pos;
04524          cp2 += pos;
04525          whereweare += pos;
04526          *cp2 = 0;
04527       }
04528 
04529       if (nextvar) {
04530          /* We have a variable.  Find the start and end, and determine
04531             if we are going to have to recursively call ourselves on the
04532             contents */
04533          vars = vare = nextvar + 2;
04534          brackets = 1;
04535          needsub = 0;
04536 
04537          /* Find the end of it */
04538          while (brackets && *vare) {
04539             if ((vare[0] == '$') && (vare[1] == '{')) {
04540                needsub++;
04541             } else if (vare[0] == '{') {
04542                brackets++;
04543             } else if (vare[0] == '}') {
04544                brackets--;
04545             } else if ((vare[0] == '$') && (vare[1] == '['))
04546                needsub++;
04547             vare++;
04548          }
04549          if (brackets)
04550             ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n");
04551          len = vare - vars - 1;
04552 
04553          /* Skip totally over variable string */
04554          whereweare += (len + 3);
04555 
04556          if (!var)
04557             var = ast_alloca(VAR_BUF_SIZE);
04558 
04559          /* Store variable name (and truncate) */
04560          ast_copy_string(var, vars, len + 1);
04561 
04562          /* Substitute if necessary */
04563          if (needsub) {
04564             size_t used;
04565             if (!ltmp)
04566                ltmp = ast_alloca(VAR_BUF_SIZE);
04567 
04568             pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used);
04569             vars = ltmp;
04570          } else {
04571             vars = var;
04572          }
04573 
04574          if (!workspace)
04575             workspace = ast_alloca(VAR_BUF_SIZE);
04576 
04577          workspace[0] = '\0';
04578 
04579          parse_variable_name(vars, &offset, &offset2, &isfunction);
04580          if (isfunction) {
04581             /* Evaluate function */
04582             if (c || !headp)
04583                cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
04584             else {
04585                struct varshead old;
04586                struct ast_channel *c = ast_dummy_channel_alloc();
04587                if (c) {
04588                   memcpy(&old, &c->varshead, sizeof(old));
04589                   memcpy(&c->varshead, headp, sizeof(c->varshead));
04590                   cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
04591                   /* Don't deallocate the varshead that was passed in */
04592                   memcpy(&c->varshead, &old, sizeof(c->varshead));
04593                   c = ast_channel_unref(c);
04594                } else {
04595                   ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution.  Function results may be blank.\n");
04596                }
04597             }
04598             ast_debug(2, "Function %s result is '%s'\n", vars, cp4 ? cp4 : "(null)");
04599          } else {
04600             /* Retrieve variable value */
04601             pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp);
04602          }
04603          if (cp4) {
04604             cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE);
04605 
04606             length = strlen(cp4);
04607             if (length > count)
04608                length = count;
04609             memcpy(cp2, cp4, length);
04610             count -= length;
04611             cp2 += length;
04612             *cp2 = 0;
04613          }
04614       } else if (nextexp) {
04615          /* We have an expression.  Find the start and end, and determine
04616             if we are going to have to recursively call ourselves on the
04617             contents */
04618          vars = vare = nextexp + 2;
04619          brackets = 1;
04620          needsub = 0;
04621 
04622          /* Find the end of it */
04623          while (brackets && *vare) {
04624             if ((vare[0] == '$') && (vare[1] == '[')) {
04625                needsub++;
04626                brackets++;
04627                vare++;
04628             } else if (vare[0] == '[') {
04629                brackets++;
04630             } else if (vare[0] == ']') {
04631                brackets--;
04632             } else if ((vare[0] == '$') && (vare[1] == '{')) {
04633                needsub++;
04634                vare++;
04635             }
04636             vare++;
04637          }
04638          if (brackets)
04639             ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n");
04640          len = vare - vars - 1;
04641 
04642          /* Skip totally over expression */
04643          whereweare += (len + 3);
04644 
04645          if (!var)
04646             var = ast_alloca(VAR_BUF_SIZE);
04647 
04648          /* Store variable name (and truncate) */
04649          ast_copy_string(var, vars, len + 1);
04650 
04651          /* Substitute if necessary */
04652          if (needsub) {
04653             size_t used;
04654             if (!ltmp)
04655                ltmp = ast_alloca(VAR_BUF_SIZE);
04656 
04657             pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used);
04658             vars = ltmp;
04659          } else {
04660             vars = var;
04661          }
04662 
04663          length = ast_expr(vars, cp2, count, c);
04664 
04665          if (length) {
04666             ast_debug(1, "Expression result is '%s'\n", cp2);
04667             count -= length;
04668             cp2 += length;
04669             *cp2 = 0;
04670          }
04671       }
04672    }
04673    *used = cp2 - orig_cp2;
04674 }

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

Definition at line 4682 of file pbx.c.

References pbx_substitute_variables_helper_full().

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

04683 {
04684    size_t used;
04685    pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count, &used);
04686 }


Generated on 7 Aug 2019 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1