Tue Aug 20 16:35:08 2013

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_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_extension_states {
  AST_EXTENSION_REMOVED = -2, AST_EXTENSION_DEACTIVATED = -1, AST_EXTENSION_NOT_INUSE = 0, AST_EXTENSION_INUSE = 1 << 0,
  AST_EXTENSION_BUSY = 1 << 1, AST_EXTENSION_UNAVAILABLE = 1 << 2, AST_EXTENSION_RINGING = 1 << 3, AST_EXTENSION_ONHOLD = 1 << 4
}
 

Extension states.

More...
enum  ast_pbx_result { AST_PBX_SUCCESS = 0, AST_PBX_FAILED = -1, AST_PBX_CALL_LIMIT = -2 }
 

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

More...
enum  ext_match_t {
  E_MATCHMORE = 0x00, E_CANMATCH = 0x01, E_MATCH = 0x02, E_MATCH_MASK = 0x03,
  E_SPAWN = 0x12, E_FINDLABEL = 0x22, E_MATCHMORE = 0x00, E_CANMATCH = 0x01,
  E_MATCH = 0x02, E_MATCH_MASK = 0x03, E_SPAWN = 0x12, E_FINDLABEL = 0x22
}

Functions

int __ast_custom_function_register (struct ast_custom_function *acf, struct ast_module *mod)
 Register a custom function.
int ast_active_calls (void)
 Retrieve the number of active calls.
int ast_add_extension (const char *context, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar)
 Add and extension to an extension context.
int ast_add_extension2 (struct ast_context *con, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar)
 Add an extension to an extension context, this time with an ast_context *.
int ast_async_goto (struct ast_channel *chan, const char *context, const char *exten, int priority)
 Set the channel to next execute the specified dialplan location.
int ast_async_goto_by_name (const char *chan, const char *context, const char *exten, int priority)
 Set the channel to next execute the specified dialplan location.
int ast_async_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority)
int ast_async_parseable_goto (struct ast_channel *chan, const char *goto_string)
int ast_build_timing (struct ast_timing *i, const char *info)
 Construct a timing bitmap, for use in time-based conditionals.
int ast_canmatch_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
 Looks for a valid matching extension.
int ast_check_timing (const struct ast_timing *i)
 Evaluate a pre-constructed bitmap as to whether the current time falls within the range specified.
int ast_check_timing2 (const struct ast_timing *i, const struct timeval tv)
 Evaluate a pre-constructed bitmap as to whether a particular time falls within the range specified.
char * ast_complete_applications (const char *line, const char *word, int state)
 Command completion for the list of installed applications.
int ast_context_add_ignorepat (const char *context, const char *ignorepat, const char *registrar)
 Add an ignorepat.
int ast_context_add_ignorepat2 (struct ast_context *con, const char *ignorepat, const char *registrar)
int ast_context_add_include (const char *context, const char *include, const char *registrar)
 Add a context include.
int ast_context_add_include2 (struct ast_context *con, const char *include, const char *registrar)
 Add a context include.
int ast_context_add_switch (const char *context, const char *sw, const char *data, int eval, const char *registrar)
 Add a switch.
int ast_context_add_switch2 (struct ast_context *con, const char *sw, const char *data, int eval, const char *registrar)
 Adds a switch (first param is a ast_context).
void ast_context_destroy (struct ast_context *con, const char *registrar)
 Destroy a context (matches the specified context (or ANY context if NULL).
struct ast_contextast_context_find (const char *name)
 Find a context.
struct ast_contextast_context_find_or_create (struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *name, const char *registrar)
 Register a new context or find an existing one.
int ast_context_lockmacro (const char *macrocontext)
 locks the macrolock in the given given context
int ast_context_remove_ignorepat (const char *context, const char *ignorepat, const char *registrar)
int ast_context_remove_ignorepat2 (struct ast_context *con, const char *ignorepat, const char *registrar)
int ast_context_remove_include (const char *context, const char *include, const char *registrar)
 Remove a context include.
int ast_context_remove_include2 (struct ast_context *con, const char *include, const char *registrar)
 Removes an include by an ast_context structure.
int ast_context_remove_switch (const char *context, const char *sw, const char *data, const char *registrar)
 Remove a switch.
int ast_context_remove_switch2 (struct ast_context *con, const char *sw, const char *data, const char *registrar)
 This function locks given context, removes switch, unlock context and return.
int ast_context_unlockmacro (const char *macrocontext)
 Unlocks the macrolock in the given context.
int ast_context_verify_includes (struct ast_context *con)
 Verifies includes in an ast_contect structure.
struct ast_custom_functionast_custom_function_find (const char *name)
int ast_custom_function_unregister (struct ast_custom_function *acf)
 Unregister a custom function.
int ast_destroy_timing (struct ast_timing *i)
 Deallocates memory structures associated with a timing bitmap.
enum ast_extension_states ast_devstate_to_extenstate (enum ast_device_state devstate)
 Map devstate to an extension state.
int ast_exists_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
 Determine whether an extension exists.
int ast_explicit_goto (struct ast_channel *chan, const char *context, const char *exten, int priority)
int ast_extension_close (const char *pattern, const char *data, int needmore)
int ast_extension_cmp (const char *a, const char *b)
 Determine if one extension should match before another.
int ast_extension_match (const char *pattern, const char *extension)
 Determine if a given extension matches a given pattern (in NXX format).
int ast_extension_patmatch (const char *pattern, const char *data)
int ast_extension_state (struct ast_channel *c, const char *context, const char *exten)
 Uses hint and devicestate callback to get the state of an extension.
const char * ast_extension_state2str (int extension_state)
 Return string representation of the state of an extension.
int ast_extension_state_add (const char *context, const char *exten, ast_state_cb_type change_cb, void *data)
 Registers a state change callback.
int ast_extension_state_add_destroy (const char *context, const char *exten, ast_state_cb_type change_cb, ast_state_cb_destroy_type destroy_cb, void *data)
 Registers a state change callback with destructor.
int ast_extension_state_del (int id, ast_state_cb_type change_cb)
 Deletes a registered state change callback by ID.
int ast_findlabel_extension (struct ast_channel *c, const char *context, const char *exten, const char *label, const char *callerid)
 Find the priority of an extension that has the specified label.
int ast_findlabel_extension2 (struct ast_channel *c, struct ast_context *con, const char *exten, const char *label, const char *callerid)
 Find the priority of an extension that has the specified label.
int ast_func_read (struct ast_channel *chan, const char *function, char *workspace, size_t len)
 executes a read operation on a function
int ast_func_read2 (struct ast_channel *chan, const char *function, struct ast_str **str, ssize_t maxlen)
 executes a read operation on a function
int ast_func_write (struct ast_channel *chan, const char *function, const char *value)
 executes a write operation on a function
int ast_get_hint (char *hint, int hintsize, char *name, int namesize, struct ast_channel *c, const char *context, const char *exten)
 If an extension hint exists, return non-zero.
int ast_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority)
int ast_ignore_pattern (const char *context, const char *pattern)
 Checks to see if a number should be ignored.
int ast_matchmore_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
 Looks to see if adding anything to this extension might match something. (exists ^ canmatch).
void ast_merge_contexts_and_delete (struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *registrar)
 Merge the temporary contexts into a global contexts list and delete from the global list the ones that are being added.
int ast_parseable_goto (struct ast_channel *chan, const char *goto_string)
int ast_pbx_outgoing_app (const char *type, 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_unlock_context (struct ast_context *con)
int ast_unlock_contexts (void)
 Unlocks contexts.
void ast_unregister_switch (struct ast_switch *sw)
 Unregister an alternative switch.
int ast_wrlock_context (struct ast_context *con)
 Write locks a given context.
int ast_wrlock_contexts (void)
 Write locks the context list.
void pbx_builtin_clear_globals (void)
const char * pbx_builtin_getvar_helper (struct ast_channel *chan, const char *name)
 Return a pointer to the value of the corresponding channel variable.
void pbx_builtin_pushvar_helper (struct ast_channel *chan, const char *name, const char *value)
 Add a variable to the channel variable stack, without removing any previously set value.
int pbx_builtin_raise_exception (struct ast_channel *chan, const char *data)
int pbx_builtin_serialize_variables (struct ast_channel *chan, struct ast_str **buf)
 Create a human-readable string, specifying all variables and their corresponding values.
int pbx_builtin_setvar (struct ast_channel *chan, const char *data)
 Parse and set a single channel variable, where the name and value are separated with an '=' character.
int pbx_builtin_setvar_helper (struct ast_channel *chan, const char *name, const char *value)
 Add a variable to the channel variable stack, removing the most recently set value for the same name.
int pbx_builtin_setvar_multiple (struct ast_channel *chan, const char *data)
 Parse and set multiple channel variables, where the pairs are separated by the ',' character, and name and value are separated with an '=' character.
int pbx_checkcondition (const char *condition)
 Evaluate a condition.
int pbx_exec (struct ast_channel *c, struct ast_app *app, const char *data)
 Execute an application.
struct ast_extenpbx_find_extension (struct ast_channel *chan, struct ast_context *bypass, struct pbx_find_info *q, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action)
struct ast_apppbx_findapp (const char *app)
 Look up an application.
void pbx_retrieve_variable (struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp)
 Retrieve the value of a builtin variable or variable from the channel variable stack.
int pbx_set_autofallthrough (int newval)
int pbx_set_extenpatternmatchnew (int newval)
void pbx_set_overrideswitch (const char *newval)
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 1144 of file pbx.h.

Referenced by load_module(), and reload().

#define AST_MAX_APP   32

Max length of an application

Definition at line 39 of file pbx.h.

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

#define AST_PBX_ERROR   1

Jump to the 'e' exten

Definition at line 49 of file pbx.h.

Referenced by __ast_pbx_run().

#define AST_PBX_GOTO_FAILED   -3

Definition at line 41 of file pbx.h.

Referenced by __ast_goto_if_exists().

#define AST_PBX_HANGUP   -1

Special return values from applications to the PBX.

Jump to the 'h' exten

Definition at line 47 of file pbx.h.

#define AST_PBX_INCOMPLETE   12

Return to PBX matching, allowing more digits for the extension

Definition at line 50 of file pbx.h.

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

#define AST_PBX_KEEP   0

Definition at line 42 of file pbx.h.

#define AST_PBX_MAX_STACK   128

Definition at line 1227 of file pbx.h.

#define AST_PBX_OK   0

No errors

Definition at line 48 of file pbx.h.

#define AST_PBX_REPLACE   1

Definition at line 43 of file pbx.h.

#define PRIORITY_HINT   -1
#define STATUS_NO_CONTEXT   1

Definition at line 1222 of file pbx.h.

#define STATUS_NO_EXTENSION   2

Definition at line 1223 of file pbx.h.

#define STATUS_NO_LABEL   4

Definition at line 1225 of file pbx.h.

#define STATUS_NO_PRIORITY   3

Definition at line 1224 of file pbx.h.

#define STATUS_SUCCESS   5

Definition at line 1226 of file pbx.h.


Typedef Documentation

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

Typedef for devicestate and hint callback removal indication callback.

Definition at line 82 of file pbx.h.

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

Typedef for devicestate and hint callbacks.

Definition at line 79 of file pbx.h.

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

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

Data structure associated with an Asterisk switch

Definition at line 114 of file pbx.h.


Enumeration Type Documentation

Extension states.

Note:
States can be combined Extension and device states in Asterisk
Enumerator:
AST_EXTENSION_REMOVED 

Extension removed

AST_EXTENSION_DEACTIVATED 

Extension hint removed

AST_EXTENSION_NOT_INUSE 

No device INUSE or BUSY

AST_EXTENSION_INUSE 

One or more devices INUSE

AST_EXTENSION_BUSY 

All devices BUSY

AST_EXTENSION_UNAVAILABLE 

All devices UNAVAILABLE/UNREGISTERED

AST_EXTENSION_RINGING 

All devices RINGING

AST_EXTENSION_ONHOLD 

All devices ONHOLD

Definition at line 60 of file pbx.h.

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

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

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

Definition at line 289 of file pbx.h.

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

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

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

Definition at line 1213 of file pbx.h.

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


Function Documentation

int __ast_custom_function_register ( struct ast_custom_function acf,
struct ast_module mod 
)

Register a custom function.

Definition at line 3814 of file pbx.c.

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

Referenced by load_pbx().

03815 {
03816    struct ast_custom_function *cur;
03817    char tmps[80];
03818 
03819    if (!acf) {
03820       return -1;
03821    }
03822 
03823    acf->mod = mod;
03824 #ifdef AST_XML_DOCS
03825    acf->docsrc = AST_STATIC_DOC;
03826 #endif
03827 
03828    if (acf_retrieve_docs(acf)) {
03829       return -1;
03830    }
03831 
03832    AST_RWLIST_WRLOCK(&acf_root);
03833 
03834    AST_RWLIST_TRAVERSE(&acf_root, cur, acflist) {
03835       if (!strcmp(acf->name, cur->name)) {
03836          ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name);
03837          AST_RWLIST_UNLOCK(&acf_root);
03838          return -1;
03839       }
03840    }
03841 
03842    /* Store in alphabetical order */
03843    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) {
03844       if (strcasecmp(acf->name, cur->name) < 0) {
03845          AST_RWLIST_INSERT_BEFORE_CURRENT(acf, acflist);
03846          break;
03847       }
03848    }
03849    AST_RWLIST_TRAVERSE_SAFE_END;
03850 
03851    if (!cur) {
03852       AST_RWLIST_INSERT_TAIL(&acf_root, acf, acflist);
03853    }
03854 
03855    AST_RWLIST_UNLOCK(&acf_root);
03856 
03857    ast_verb(2, "Registered custom function '%s'\n", term_color(tmps, acf->name, COLOR_BRCYAN, 0, sizeof(tmps)));
03858 
03859    return 0;
03860 }

int ast_active_calls ( void   ) 

Retrieve the number of active calls.

Definition at line 5631 of file pbx.c.

References countcalls.

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

05632 {
05633    return countcalls;
05634 }

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

08367 {
08368    int ret = -1;
08369    struct ast_context *c;
08370 
08371    c = find_context_locked(context);
08372    if (c) {
08373       ret = ast_add_extension2(c, replace, extension, priority, label, callerid,
08374          application, data, datad, registrar);
08375       ast_unlock_contexts();
08376    }
08377 
08378    return ret;
08379 }

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

08729 {
08730    return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid,
08731       application, data, datad, registrar, 1);
08732 }

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

08405 {
08406    int res = 0;
08407    struct ast_channel *tmpchan;
08408    struct {
08409       char *accountcode;
08410       char *exten;
08411       char *context;
08412       char *linkedid;
08413       char *name;
08414       struct ast_cdr *cdr;
08415       int amaflags;
08416       int state;
08417       format_t readformat;
08418       format_t writeformat;
08419    } tmpvars = { 0, };
08420 
08421    ast_channel_lock(chan);
08422    if (chan->pbx) { /* This channel is currently in the PBX */
08423       ast_explicit_goto(chan, context, exten, priority + 1);
08424       ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO);
08425       ast_channel_unlock(chan);
08426       return res;
08427    }
08428 
08429    /* In order to do it when the channel doesn't really exist within
08430     * the PBX, we have to make a new channel, masquerade, and start the PBX
08431     * at the new location */
08432    tmpvars.accountcode = ast_strdupa(chan->accountcode);
08433    tmpvars.exten = ast_strdupa(chan->exten);
08434    tmpvars.context = ast_strdupa(chan->context);
08435    tmpvars.linkedid = ast_strdupa(chan->linkedid);
08436    tmpvars.name = ast_strdupa(chan->name);
08437    tmpvars.amaflags = chan->amaflags;
08438    tmpvars.state = chan->_state;
08439    tmpvars.writeformat = chan->writeformat;
08440    tmpvars.readformat = chan->readformat;
08441    tmpvars.cdr = chan->cdr ? ast_cdr_dup(chan->cdr) : NULL;
08442 
08443    ast_channel_unlock(chan);
08444 
08445    /* Do not hold any channel locks while calling channel_alloc() since the function
08446     * locks the channel container when linking the new channel in. */
08447    if (!(tmpchan = ast_channel_alloc(0, tmpvars.state, 0, 0, tmpvars.accountcode, tmpvars.exten, tmpvars.context, tmpvars.linkedid, tmpvars.amaflags, "AsyncGoto/%s", tmpvars.name))) {
08448       ast_cdr_discard(tmpvars.cdr);
08449       return -1;
08450    }
08451 
08452    /* copy the cdr info over */
08453    if (tmpvars.cdr) {
08454       ast_cdr_discard(tmpchan->cdr);
08455       tmpchan->cdr = tmpvars.cdr;
08456       tmpvars.cdr = NULL;
08457    }
08458 
08459    /* Make formats okay */
08460    tmpchan->readformat = tmpvars.readformat;
08461    tmpchan->writeformat = tmpvars.writeformat;
08462 
08463    /* Setup proper location. Never hold another channel lock while calling this function. */
08464    ast_explicit_goto(tmpchan, S_OR(context, tmpvars.context), S_OR(exten, tmpvars.exten), priority);
08465 
08466    /* Masquerade into tmp channel */
08467    if (ast_channel_masquerade(tmpchan, chan)) {
08468       /* Failed to set up the masquerade.  It's probably chan_local
08469        * in the middle of optimizing itself out.  Sad. :( */
08470       ast_hangup(tmpchan);
08471       tmpchan = NULL;
08472       res = -1;
08473    } else {
08474       ast_do_masquerade(tmpchan);
08475       /* Start the PBX going on our stolen channel */
08476       if (ast_pbx_start(tmpchan)) {
08477          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name);
08478          ast_hangup(tmpchan);
08479          res = -1;
08480       }
08481    }
08482 
08483    return res;
08484 }

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

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

08487 {
08488    struct ast_channel *chan;
08489    int res = -1;
08490 
08491    if ((chan = ast_channel_get_by_name(channame))) {
08492       res = ast_async_goto(chan, context, exten, priority);
08493       chan = ast_channel_unref(chan);
08494    }
08495 
08496    return res;
08497 }

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

References __ast_goto_if_exists().

10847 {
10848    return __ast_goto_if_exists(chan, context, exten, priority, 1);
10849 }

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

References pbx_parseable_goto().

Referenced by asyncgoto_exec(), and handle_redirect().

10912 {
10913    return pbx_parseable_goto(chan, goto_string, 1);
10914 }

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

07988 {
07989    char *info;
07990    int j, num_fields, last_sep = -1;
07991 
07992    /* Check for empty just in case */
07993    if (ast_strlen_zero(info_in)) {
07994       return 0;
07995    }
07996 
07997    /* make a copy just in case we were passed a static string */
07998    info = ast_strdupa(info_in);
07999 
08000    /* count the number of fields in the timespec */
08001    for (j = 0, num_fields = 1; info[j] != '\0'; j++) {
08002       if (info[j] == ',') {
08003          last_sep = j;
08004          num_fields++;
08005       }
08006    }
08007 
08008    /* save the timezone, if it is specified */
08009    if (num_fields == 5) {
08010       i->timezone = ast_strdup(info + last_sep + 1);
08011    } else {
08012       i->timezone = NULL;
08013    }
08014 
08015    /* Assume everything except time */
08016    i->monthmask = 0xfff;   /* 12 bits */
08017    i->daymask = 0x7fffffffU; /* 31 bits */
08018    i->dowmask = 0x7f; /* 7 bits */
08019    /* on each call, use strsep() to move info to the next argument */
08020    get_timerange(i, strsep(&info, "|,"));
08021    if (info)
08022       i->dowmask = get_range(strsep(&info, "|,"), 7, days, "day of week");
08023    if (info)
08024       i->daymask = get_range(strsep(&info, "|,"), 31, NULL, "day");
08025    if (info)
08026       i->monthmask = get_range(strsep(&info, "|,"), 12, months, "month");
08027    return 1;
08028 }

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

05116 {
05117    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0);
05118 }

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

References ast_check_timing2(), and ast_tvnow().

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

08031 {
08032    return ast_check_timing2(i, ast_tvnow());
08033 }

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

08036 {
08037    struct ast_tm tm;
08038 
08039    ast_localtime(&tv, &tm, i->timezone);
08040 
08041    /* If it's not the right month, return */
08042    if (!(i->monthmask & (1 << tm.tm_mon)))
08043       return 0;
08044 
08045    /* If it's not that time of the month.... */
08046    /* Warning, tm_mday has range 1..31! */
08047    if (!(i->daymask & (1 << (tm.tm_mday-1))))
08048       return 0;
08049 
08050    /* If it's not the right day of the week */
08051    if (!(i->dowmask & (1 << tm.tm_wday)))
08052       return 0;
08053 
08054    /* Sanity check the hour just to be safe */
08055    if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) {
08056       ast_log(LOG_WARNING, "Insane time...\n");
08057       return 0;
08058    }
08059 
08060    /* Now the tough part, we calculate if it fits
08061       in the right time based on min/hour */
08062    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))))
08063       return 0;
08064 
08065    /* If we got this far, then we're good */
08066    return 1;
08067 }

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

10917 {
10918    struct ast_app *app = NULL;
10919    int which = 0;
10920    char *ret = NULL;
10921    size_t wordlen = strlen(word);
10922 
10923    AST_RWLIST_RDLOCK(&apps);
10924    AST_RWLIST_TRAVERSE(&apps, app, list) {
10925       if (!strncasecmp(word, app->name, wordlen) && ++which > state) {
10926          ret = ast_strdup(app->name);
10927          break;
10928       }
10929    }
10930    AST_RWLIST_UNLOCK(&apps);
10931 
10932    return ret;
10933 }

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

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

Referenced by handle_cli_dialplan_add_ignorepat().

08272 {
08273    int ret = -1;
08274    struct ast_context *c;
08275 
08276    c = find_context_locked(context);
08277    if (c) {
08278       ret = ast_context_add_ignorepat2(c, value, registrar);
08279       ast_unlock_contexts();
08280    }
08281    return ret;
08282 }

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

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

08285 {
08286    struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL;
08287    int length;
08288    char *pattern;
08289    length = sizeof(struct ast_ignorepat);
08290    length += strlen(value) + 1;
08291    if (!(ignorepat = ast_calloc(1, length)))
08292       return -1;
08293    /* The cast to char * is because we need to write the initial value.
08294     * The field is not supposed to be modified otherwise.  Also, gcc 4.2
08295     * sees the cast as dereferencing a type-punned pointer and warns about
08296     * it.  This is the workaround (we're telling gcc, yes, that's really
08297     * what we wanted to do).
08298     */
08299    pattern = (char *) ignorepat->pattern;
08300    strcpy(pattern, value);
08301    ignorepat->next = NULL;
08302    ignorepat->registrar = registrar;
08303    ast_wrlock_context(con);
08304    for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) {
08305       ignorepatl = ignorepatc;
08306       if (!strcasecmp(ignorepatc->pattern, value)) {
08307          /* Already there */
08308          ast_unlock_context(con);
08309          ast_free(ignorepat);
08310          errno = EEXIST;
08311          return -1;
08312       }
08313    }
08314    if (ignorepatl)
08315       ignorepatl->next = ignorepat;
08316    else
08317       con->ignorepats = ignorepat;
08318    ast_unlock_context(con);
08319    return 0;
08320 
08321 }

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

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

Referenced by handle_cli_dialplan_add_include().

07816 {
07817    int ret = -1;
07818    struct ast_context *c;
07819 
07820    c = find_context_locked(context);
07821    if (c) {
07822       ret = ast_context_add_include2(c, include, registrar);
07823       ast_unlock_contexts();
07824    }
07825    return ret;
07826 }

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

08086 {
08087    struct ast_include *new_include;
08088    char *c;
08089    struct ast_include *i, *il = NULL; /* include, include_last */
08090    int length;
08091    char *p;
08092 
08093    length = sizeof(struct ast_include);
08094    length += 2 * (strlen(value) + 1);
08095 
08096    /* allocate new include structure ... */
08097    if (!(new_include = ast_calloc(1, length)))
08098       return -1;
08099    /* Fill in this structure. Use 'p' for assignments, as the fields
08100     * in the structure are 'const char *'
08101     */
08102    p = new_include->stuff;
08103    new_include->name = p;
08104    strcpy(p, value);
08105    p += strlen(value) + 1;
08106    new_include->rname = p;
08107    strcpy(p, value);
08108    /* Strip off timing info, and process if it is there */
08109    if ( (c = strchr(p, ',')) ) {
08110       *c++ = '\0';
08111       new_include->hastime = ast_build_timing(&(new_include->timing), c);
08112    }
08113    new_include->next      = NULL;
08114    new_include->registrar = registrar;
08115 
08116    ast_wrlock_context(con);
08117 
08118    /* ... go to last include and check if context is already included too... */
08119    for (i = con->includes; i; i = i->next) {
08120       if (!strcasecmp(i->name, new_include->name)) {
08121          ast_destroy_timing(&(new_include->timing));
08122          ast_free(new_include);
08123          ast_unlock_context(con);
08124          errno = EEXIST;
08125          return -1;
08126       }
08127       il = i;
08128    }
08129 
08130    /* ... include new context into context list, unlock, return */
08131    if (il)
08132       il->next = new_include;
08133    else
08134       con->includes = new_include;
08135    ast_verb(3, "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con));
08136 
08137    ast_unlock_context(con);
08138 
08139    return 0;
08140 }

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

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

08148 {
08149    int ret = -1;
08150    struct ast_context *c;
08151 
08152    c = find_context_locked(context);
08153    if (c) { /* found, add switch to this context */
08154       ret = ast_context_add_switch2(c, sw, data, eval, registrar);
08155       ast_unlock_contexts();
08156    }
08157    return ret;
08158 }

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

08169 {
08170    struct ast_sw *new_sw;
08171    struct ast_sw *i;
08172    int length;
08173    char *p;
08174 
08175    length = sizeof(struct ast_sw);
08176    length += strlen(value) + 1;
08177    if (data)
08178       length += strlen(data);
08179    length++;
08180 
08181    /* allocate new sw structure ... */
08182    if (!(new_sw = ast_calloc(1, length)))
08183       return -1;
08184    /* ... fill in this structure ... */
08185    p = new_sw->stuff;
08186    new_sw->name = p;
08187    strcpy(new_sw->name, value);
08188    p += strlen(value) + 1;
08189    new_sw->data = p;
08190    if (data) {
08191       strcpy(new_sw->data, data);
08192       p += strlen(data) + 1;
08193    } else {
08194       strcpy(new_sw->data, "");
08195       p++;
08196    }
08197    new_sw->eval     = eval;
08198    new_sw->registrar = registrar;
08199 
08200    /* ... try to lock this context ... */
08201    ast_wrlock_context(con);
08202 
08203    /* ... go to last sw and check if context is already swd too... */
08204    AST_LIST_TRAVERSE(&con->alts, i, list) {
08205       if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) {
08206          ast_free(new_sw);
08207          ast_unlock_context(con);
08208          errno = EEXIST;
08209          return -1;
08210       }
08211    }
08212 
08213    /* ... sw new context into context list, unlock, return */
08214    AST_LIST_INSERT_TAIL(&con->alts, new_sw, list);
08215 
08216    ast_verb(3, "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con));
08217 
08218    ast_unlock_context(con);
08219 
08220    return 0;
08221 }

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

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

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

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

Find a context.

Parameters:
name name of the context to find

Will search for the context with the given name.

Returns:
the ast_context on success, NULL on failure.

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

02897 {
02898    struct ast_context *tmp;
02899    struct fake_context item;
02900 
02901    if (!name) {
02902       return NULL;
02903    }
02904    ast_rdlock_contexts();
02905    if (contexts_table) {
02906       ast_copy_string(item.name, name, sizeof(item.name));
02907       tmp = ast_hashtab_lookup(contexts_table, &item);
02908    } else {
02909       tmp = NULL;
02910       while ((tmp = ast_walk_contexts(tmp))) {
02911          if (!strcasecmp(name, tmp->name)) {
02912             break;
02913          }
02914       }
02915    }
02916    ast_unlock_contexts();
02917    return tmp;
02918 }

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

07415 {
07416    struct ast_context *tmp, **local_contexts;
07417    struct fake_context search;
07418    int length = sizeof(struct ast_context) + strlen(name) + 1;
07419 
07420    if (!contexts_table) {
07421       /* Protect creation of contexts_table from reentrancy. */
07422       ast_wrlock_contexts();
07423       if (!contexts_table) {
07424          contexts_table = ast_hashtab_create(17,
07425             ast_hashtab_compare_contexts,
07426             ast_hashtab_resize_java,
07427             ast_hashtab_newsize_java,
07428             ast_hashtab_hash_contexts,
07429             0);
07430       }
07431       ast_unlock_contexts();
07432    }
07433 
07434    ast_copy_string(search.name, name, sizeof(search.name));
07435    if (!extcontexts) {
07436       ast_rdlock_contexts();
07437       local_contexts = &contexts;
07438       tmp = ast_hashtab_lookup(contexts_table, &search);
07439       ast_unlock_contexts();
07440       if (tmp) {
07441          tmp->refcount++;
07442          return tmp;
07443       }
07444    } else { /* local contexts just in a linked list; search there for the new context; slow, linear search, but not frequent */
07445       local_contexts = extcontexts;
07446       tmp = ast_hashtab_lookup(exttable, &search);
07447       if (tmp) {
07448          tmp->refcount++;
07449          return tmp;
07450       }
07451    }
07452 
07453    if ((tmp = ast_calloc(1, length))) {
07454       ast_rwlock_init(&tmp->lock);
07455       ast_mutex_init(&tmp->macrolock);
07456       strcpy(tmp->name, name);
07457       tmp->root = NULL;
07458       tmp->root_table = NULL;
07459       tmp->registrar = ast_strdup(registrar);
07460       tmp->includes = NULL;
07461       tmp->ignorepats = NULL;
07462       tmp->refcount = 1;
07463    } else {
07464       ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name);
07465       return NULL;
07466    }
07467 
07468    if (!extcontexts) {
07469       ast_wrlock_contexts();
07470       tmp->next = *local_contexts;
07471       *local_contexts = tmp;
07472       ast_hashtab_insert_safe(contexts_table, tmp); /*put this context into the tree */
07473       ast_unlock_contexts();
07474       ast_debug(1, "Registered context '%s'(%p) in table %p registrar: %s\n", tmp->name, tmp, contexts_table, registrar);
07475       ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar);
07476    } else {
07477       tmp->next = *local_contexts;
07478       if (exttable)
07479          ast_hashtab_insert_immediate(exttable, tmp); /*put this context into the tree */
07480 
07481       *local_contexts = tmp;
07482       ast_debug(1, "Registered context '%s'(%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar);
07483       ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar);
07484    }
07485    return tmp;
07486 }

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

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

Referenced by _macro_exec().

06010 {
06011    struct ast_context *c;
06012    int ret = -1;
06013 
06014    c = find_context_locked(context);
06015    if (c) {
06016       ast_unlock_contexts();
06017 
06018       /* if we found context, lock macrolock */
06019       ret = ast_mutex_lock(&c->macrolock);
06020    }
06021 
06022    return ret;
06023 }

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

References ast_context_remove_extension_callerid().

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

05815 {
05816    return ast_context_remove_extension_callerid(context, extension, priority, NULL, 0, registrar);
05817 }

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

References ast_context_remove_extension_callerid2().

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

05845 {
05846    return ast_context_remove_extension_callerid2(con, extension, priority, NULL, 0, registrar, already_locked);
05847 }

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

05820 {
05821    int ret = -1; /* default error return */
05822    struct ast_context *c;
05823 
05824    c = find_context_locked(context);
05825    if (c) { /* ... remove extension ... */
05826       ret = ast_context_remove_extension_callerid2(c, extension, priority, callerid,
05827          matchcallerid, registrar, 0);
05828       ast_unlock_contexts();
05829    }
05830 
05831    return ret;
05832 }

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

05850 {
05851    struct ast_exten *exten, *prev_exten = NULL;
05852    struct ast_exten *peer;
05853    struct ast_exten ex, *exten2, *exten3;
05854    char dummy_name[1024];
05855    struct ast_exten *previous_peer = NULL;
05856    struct ast_exten *next_peer = NULL;
05857    int found = 0;
05858 
05859    if (!already_locked)
05860       ast_wrlock_context(con);
05861 
05862    /* Handle this is in the new world */
05863 
05864    /* FIXME For backwards compatibility, if callerid==NULL, then remove ALL
05865     * peers, not just those matching the callerid. */
05866 #ifdef NEED_DEBUG
05867    ast_verb(3,"Removing %s/%s/%d%s%s from trees, registrar=%s\n", con->name, extension, priority, matchcallerid ? "/" : "", matchcallerid ? callerid : "", registrar);
05868 #endif
05869 #ifdef CONTEXT_DEBUG
05870    check_contexts(__FILE__, __LINE__);
05871 #endif
05872    /* find this particular extension */
05873    ex.exten = dummy_name;
05874    ex.matchcid = matchcallerid && !ast_strlen_zero(callerid); /* don't say match if there's no callerid */
05875    ex.cidmatch = callerid;
05876    ast_copy_string(dummy_name, extension, sizeof(dummy_name));
05877    exten = ast_hashtab_lookup(con->root_table, &ex);
05878    if (exten) {
05879       if (priority == 0) {
05880          exten2 = ast_hashtab_remove_this_object(con->root_table, exten);
05881          if (!exten2)
05882             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);
05883          if (con->pattern_tree) {
05884             struct match_char *x = add_exten_to_pattern_tree(con, exten, 1);
05885 
05886             if (x->exten) { /* this test for safety purposes */
05887                x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */
05888                x->exten = 0; /* get rid of what will become a bad pointer */
05889             } else {
05890                ast_log(LOG_WARNING,"Trying to delete an exten from a context, but the pattern tree node returned isn't a full extension\n");
05891             }
05892          }
05893       } else {
05894          ex.priority = priority;
05895          exten2 = ast_hashtab_lookup(exten->peer_table, &ex);
05896          if (exten2) {
05897 
05898             if (exten2->label) { /* if this exten has a label, remove that, too */
05899                exten3 = ast_hashtab_remove_this_object(exten->peer_label_table,exten2);
05900                if (!exten3)
05901                   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);
05902             }
05903 
05904             exten3 = ast_hashtab_remove_this_object(exten->peer_table, exten2);
05905             if (!exten3)
05906                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);
05907             if (exten2 == exten && exten2->peer) {
05908                exten2 = ast_hashtab_remove_this_object(con->root_table, exten);
05909                ast_hashtab_insert_immediate(con->root_table, exten2->peer);
05910             }
05911             if (ast_hashtab_size(exten->peer_table) == 0) {
05912                /* well, if the last priority of an exten is to be removed,
05913                   then, the extension is removed, too! */
05914                exten3 = ast_hashtab_remove_this_object(con->root_table, exten);
05915                if (!exten3)
05916                   ast_log(LOG_ERROR,"Did not remove this exten (%s) from the context root_table (%s) (priority %d)\n", exten->exten, con->name, priority);
05917                if (con->pattern_tree) {
05918                   struct match_char *x = add_exten_to_pattern_tree(con, exten, 1);
05919                   if (x->exten) { /* this test for safety purposes */
05920                      x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */
05921                      x->exten = 0; /* get rid of what will become a bad pointer */
05922                   }
05923                }
05924             }
05925          } else {
05926             ast_log(LOG_ERROR,"Could not find priority %d of exten %s in context %s!\n",
05927                   priority, exten->exten, con->name);
05928          }
05929       }
05930    } else {
05931       /* hmmm? this exten is not in this pattern tree? */
05932       ast_log(LOG_WARNING,"Cannot find extension %s in root_table in context %s\n",
05933             extension, con->name);
05934    }
05935 #ifdef NEED_DEBUG
05936    if (con->pattern_tree) {
05937       ast_log(LOG_NOTICE,"match char tree after exten removal:\n");
05938       log_match_char_tree(con->pattern_tree, " ");
05939    }
05940 #endif
05941 
05942    /* scan the extension list to find first matching extension-registrar */
05943    for (exten = con->root; exten; prev_exten = exten, exten = exten->next) {
05944       if (!strcmp(exten->exten, extension) &&
05945          (!registrar || !strcmp(exten->registrar, registrar)) &&
05946          (!matchcallerid || (!ast_strlen_zero(callerid) && !ast_strlen_zero(exten->cidmatch) && !strcmp(exten->cidmatch, callerid)) || (ast_strlen_zero(callerid) && ast_strlen_zero(exten->cidmatch))))
05947          break;
05948    }
05949    if (!exten) {
05950       /* we can't find right extension */
05951       if (!already_locked)
05952          ast_unlock_context(con);
05953       return -1;
05954    }
05955 
05956    /* scan the priority list to remove extension with exten->priority == priority */
05957    for (peer = exten, next_peer = exten->peer ? exten->peer : exten->next;
05958        peer && !strcmp(peer->exten, extension) && (!matchcallerid || (!ast_strlen_zero(callerid) && !ast_strlen_zero(peer->cidmatch) && !strcmp(peer->cidmatch,callerid)) || (ast_strlen_zero(callerid) && ast_strlen_zero(peer->cidmatch)));
05959          peer = next_peer, next_peer = next_peer ? (next_peer->peer ? next_peer->peer : next_peer->next) : NULL) {
05960       if ((priority == 0 || peer->priority == priority) &&
05961             (!callerid || !matchcallerid || (matchcallerid && !strcmp(peer->cidmatch, callerid))) &&
05962             (!registrar || !strcmp(peer->registrar, registrar) )) {
05963          found = 1;
05964 
05965          /* we are first priority extension? */
05966          if (!previous_peer) {
05967             /*
05968              * We are first in the priority chain, so must update the extension chain.
05969              * The next node is either the next priority or the next extension
05970              */
05971             struct ast_exten *next_node = peer->peer ? peer->peer : peer->next;
05972             if (peer->peer) {
05973                /* move the peer_table and peer_label_table down to the next peer, if
05974                   it is there */
05975                peer->peer->peer_table = peer->peer_table;
05976                peer->peer->peer_label_table = peer->peer_label_table;
05977                peer->peer_table = NULL;
05978                peer->peer_label_table = NULL;
05979             }
05980             if (!prev_exten) {   /* change the root... */
05981                con->root = next_node;
05982             } else {
05983                prev_exten->next = next_node; /* unlink */
05984             }
05985             if (peer->peer)   { /* update the new head of the pri list */
05986                peer->peer->next = peer->next;
05987             }
05988          } else { /* easy, we are not first priority in extension */
05989             previous_peer->peer = peer->peer;
05990          }
05991 
05992          /* now, free whole priority extension */
05993          destroy_exten(peer);
05994       } else {
05995          previous_peer = peer;
05996       }
05997    }
05998    if (!already_locked)
05999       ast_unlock_context(con);
06000    return found ? 0 : -1;
06001 }

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

Definition at line 8227 of file pbx.c.

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

Referenced by handle_cli_dialplan_remove_ignorepat().

08228 {
08229    int ret = -1;
08230    struct ast_context *c;
08231 
08232    c = find_context_locked(context);
08233    if (c) {
08234       ret = ast_context_remove_ignorepat2(c, ignorepat, registrar);
08235       ast_unlock_contexts();
08236    }
08237    return ret;
08238 }

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

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

08241 {
08242    struct ast_ignorepat *ip, *ipl = NULL;
08243 
08244    ast_wrlock_context(con);
08245 
08246    for (ip = con->ignorepats; ip; ip = ip->next) {
08247       if (!strcmp(ip->pattern, ignorepat) &&
08248          (!registrar || (registrar == ip->registrar))) {
08249          if (ipl) {
08250             ipl->next = ip->next;
08251             ast_free(ip);
08252          } else {
08253             con->ignorepats = ip->next;
08254             ast_free(ip);
08255          }
08256          ast_unlock_context(con);
08257          return 0;
08258       }
08259       ipl = ip;
08260    }
08261 
08262    ast_unlock_context(con);
08263    errno = EINVAL;
08264    return -1;
08265 }

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

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

Referenced by handle_cli_dialplan_remove_include().

05708 {
05709    int ret = -1;
05710    struct ast_context *c;
05711 
05712    c = find_context_locked(context);
05713    if (c) {
05714       /* found, remove include from this context ... */
05715       ret = ast_context_remove_include2(c, include, registrar);
05716       ast_unlock_contexts();
05717    }
05718    return ret;
05719 }

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

05731 {
05732    struct ast_include *i, *pi = NULL;
05733    int ret = -1;
05734 
05735    ast_wrlock_context(con);
05736 
05737    /* find our include */
05738    for (i = con->includes; i; pi = i, i = i->next) {
05739       if (!strcmp(i->name, include) &&
05740             (!registrar || !strcmp(i->registrar, registrar))) {
05741          /* remove from list */
05742          ast_verb(3, "Removing inclusion of context '%s' in context '%s; registrar=%s'\n", include, ast_get_context_name(con), registrar);
05743          if (pi)
05744             pi->next = i->next;
05745          else
05746             con->includes = i->next;
05747          /* free include and return */
05748          ast_destroy_timing(&(i->timing));
05749          ast_free(i);
05750          ret = 0;
05751          break;
05752       }
05753    }
05754 
05755    ast_unlock_context(con);
05756 
05757    return ret;
05758 }

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

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

05766 {
05767    int ret = -1; /* default error return */
05768    struct ast_context *c;
05769 
05770    c = find_context_locked(context);
05771    if (c) {
05772       /* remove switch from this context ... */
05773       ret = ast_context_remove_switch2(c, sw, data, registrar);
05774       ast_unlock_contexts();
05775    }
05776    return ret;
05777 }

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

05788 {
05789    struct ast_sw *i;
05790    int ret = -1;
05791 
05792    ast_wrlock_context(con);
05793 
05794    /* walk switches */
05795    AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) {
05796       if (!strcmp(i->name, sw) && !strcmp(i->data, data) &&
05797          (!registrar || !strcmp(i->registrar, registrar))) {
05798          /* found, remove from list */
05799          ast_verb(3, "Removing switch '%s' from context '%s; registrar=%s'\n", sw, ast_get_context_name(con), registrar);
05800          AST_LIST_REMOVE_CURRENT(list);
05801          ast_free(i); /* free switch and return */
05802          ret = 0;
05803          break;
05804       }
05805    }
05806    AST_LIST_TRAVERSE_SAFE_END;
05807 
05808    ast_unlock_context(con);
05809 
05810    return ret;
05811 }

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

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

Referenced by _macro_exec().

06031 {
06032    struct ast_context *c;
06033    int ret = -1;
06034 
06035    c = find_context_locked(context);
06036    if (c) {
06037       ast_unlock_contexts();
06038 
06039       /* if we found context, unlock macrolock */
06040       ret = ast_mutex_unlock(&c->macrolock);
06041    }
06042 
06043    return ret;
06044 }

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

10802 {
10803    struct ast_include *inc = NULL;
10804    int res = 0;
10805 
10806    while ( (inc = ast_walk_context_includes(con, inc)) ) {
10807       if (ast_context_find(inc->rname))
10808          continue;
10809 
10810       res = -1;
10811       ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n",
10812          ast_get_context_name(con), inc->rname);
10813       break;
10814    }
10815 
10816    return res;
10817 }

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

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

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

03740 {
03741    struct ast_custom_function *cur;
03742 
03743    if (!acf) {
03744       return -1;
03745    }
03746 
03747    AST_RWLIST_WRLOCK(&acf_root);
03748    if ((cur = AST_RWLIST_REMOVE(&acf_root, acf, acflist))) {
03749 #ifdef AST_XML_DOCS
03750       if (cur->docsrc == AST_XML_DOC) {
03751          ast_string_field_free_memory(acf);
03752       }
03753 #endif
03754       ast_verb(2, "Unregistered custom function %s\n", cur->name);
03755    }
03756    AST_RWLIST_UNLOCK(&acf_root);
03757 
03758    return cur ? 0 : -1;
03759 }

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

08070 {
08071    if (i->timezone) {
08072       ast_free(i->timezone);
08073       i->timezone = NULL;
08074    }
08075    return 0;
08076 }

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

04549 {
04550    switch (devstate) {
04551    case AST_DEVICE_ONHOLD:
04552       return AST_EXTENSION_ONHOLD;
04553    case AST_DEVICE_BUSY:
04554       return AST_EXTENSION_BUSY;
04555    case AST_DEVICE_UNKNOWN:
04556       return AST_EXTENSION_NOT_INUSE;
04557    case AST_DEVICE_UNAVAILABLE:
04558    case AST_DEVICE_INVALID:
04559       return AST_EXTENSION_UNAVAILABLE;
04560    case AST_DEVICE_RINGINUSE:
04561       return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING);
04562    case AST_DEVICE_RINGING:
04563       return AST_EXTENSION_RINGING;
04564    case AST_DEVICE_INUSE:
04565       return AST_EXTENSION_INUSE;
04566    case AST_DEVICE_NOT_INUSE:
04567       return AST_EXTENSION_NOT_INUSE;
04568    case AST_DEVICE_TOTAL: /* not a device state, included for completeness */
04569       break;
04570    }
04571 
04572    return AST_EXTENSION_NOT_INUSE;
04573 }

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

05101 {
05102    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0);
05103 }

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

08382 {
08383    if (!chan)
08384       return -1;
08385 
08386    ast_channel_lock(chan);
08387 
08388    if (!ast_strlen_zero(context))
08389       ast_copy_string(chan->context, context, sizeof(chan->context));
08390    if (!ast_strlen_zero(exten))
08391       ast_copy_string(chan->exten, exten, sizeof(chan->exten));
08392    if (priority > -1) {
08393       chan->priority = priority;
08394       /* see flag description in channel.h for explanation */
08395       if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP))
08396          chan->priority--;
08397    }
08398 
08399    ast_channel_unlock(chan);
08400 
08401    return 0;
08402 }

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

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

02874 {
02875    if (needmore != E_MATCHMORE && needmore != E_CANMATCH)
02876       ast_log(LOG_WARNING, "invalid argument %d\n", needmore);
02877    return extension_match_core(pattern, data, needmore);
02878 }

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

References ext_cmp().

Referenced by lua_extension_cmp().

02639 {
02640    int cmp;
02641 
02642    cmp = ext_cmp(a, b);
02643    if (cmp < 0) {
02644       return -1;
02645    }
02646    if (cmp > 0) {
02647       return 1;
02648    }
02649    return 0;
02650 }

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

02869 {
02870    return extension_match_core(pattern, data, E_MATCH);
02871 }

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

04619 {
04620    struct ast_exten *e;
04621 
04622    if (!(e = ast_hint_extension(c, context, exten))) {  /* Do we have a hint for this extension ? */
04623       return -1;                   /* No hint, return -1 */
04624    }
04625 
04626    if (e->exten[0] == '_') {
04627       /* Create this hint on-the-fly */
04628       ast_add_extension(e->parent->name, 0, exten, e->priority, e->label,
04629          e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr,
04630          e->registrar);
04631       if (!(e = ast_hint_extension(c, context, exten))) {
04632          /* Improbable, but not impossible */
04633          return -1;
04634       }
04635    }
04636 
04637    return ast_extension_state2(e);  /* Check all devices in the hint */
04638 }

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

04607 {
04608    int i;
04609 
04610    for (i = 0; (i < ARRAY_LEN(extension_states)); i++) {
04611       if (extension_states[i].extension_state == extension_state)
04612          return extension_states[i].text;
04613    }
04614    return "Unknown";
04615 }

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

References ast_extension_state_add_destroy().

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

04841 {
04842    return ast_extension_state_add_destroy(context, exten, change_cb, NULL, data);
04843 }

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

04754 {
04755    struct ast_hint *hint;
04756    struct ast_state_cb *state_cb;
04757    struct ast_exten *e;
04758    int id;
04759 
04760    /* If there's no context and extension:  add callback to statecbs list */
04761    if (!context && !exten) {
04762       /* Prevent multiple adds from adding the same change_cb at the same time. */
04763       ao2_lock(statecbs);
04764 
04765       /* Remove any existing change_cb. */
04766       ao2_find(statecbs, change_cb, OBJ_UNLINK | OBJ_NODATA);
04767 
04768       /* Now insert the change_cb */
04769       if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) {
04770          ao2_unlock(statecbs);
04771          return -1;
04772       }
04773       state_cb->id = 0;
04774       state_cb->change_cb = change_cb;
04775       state_cb->destroy_cb = destroy_cb;
04776       state_cb->data = data;
04777       ao2_link(statecbs, state_cb);
04778 
04779       ao2_ref(state_cb, -1);
04780       ao2_unlock(statecbs);
04781       return 0;
04782    }
04783 
04784    if (!context || !exten)
04785       return -1;
04786 
04787    /* This callback type is for only one hint, so get the hint */
04788    e = ast_hint_extension(NULL, context, exten);
04789    if (!e) {
04790       return -1;
04791    }
04792 
04793    /* If this is a pattern, dynamically create a new extension for this
04794     * particular match.  Note that this will only happen once for each
04795     * individual extension, because the pattern will no longer match first.
04796     */
04797    if (e->exten[0] == '_') {
04798       ast_add_extension(e->parent->name, 0, exten, e->priority, e->label,
04799          e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr,
04800          e->registrar);
04801       e = ast_hint_extension(NULL, context, exten);
04802       if (!e || e->exten[0] == '_') {
04803          return -1;
04804       }
04805    }
04806 
04807    /* Find the hint in the hints container */
04808    ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */
04809    hint = ao2_find(hints, e, 0);
04810    if (!hint) {
04811       ao2_unlock(hints);
04812       return -1;
04813    }
04814 
04815    /* Now insert the callback in the callback list  */
04816    if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) {
04817       ao2_ref(hint, -1);
04818       ao2_unlock(hints);
04819       return -1;
04820    }
04821    do {
04822       id = stateid++;      /* Unique ID for this callback */
04823       /* Do not allow id to ever be -1 or 0. */
04824    } while (id == -1 || id == 0);
04825    state_cb->id = id;
04826    state_cb->change_cb = change_cb; /* Pointer to callback routine */
04827    state_cb->destroy_cb = destroy_cb;
04828    state_cb->data = data;     /* Data for the callback */
04829    ao2_link(hint->callbacks, state_cb);
04830 
04831    ao2_ref(state_cb, -1);
04832    ao2_ref(hint, -1);
04833    ao2_unlock(hints);
04834 
04835    return id;
04836 }

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

04862 {
04863    struct ast_state_cb *p_cur;
04864    int ret = -1;
04865 
04866    if (!id) {  /* id == 0 is a callback without extension */
04867       if (!change_cb) {
04868          return ret;
04869       }
04870       p_cur = ao2_find(statecbs, change_cb, OBJ_UNLINK);
04871       if (p_cur) {
04872          ret = 0;
04873          ao2_ref(p_cur, -1);
04874       }
04875    } else { /* callback with extension, find the callback based on ID */
04876       struct ast_hint *hint;
04877 
04878       ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */
04879       hint = ao2_callback(hints, 0, find_hint_by_cb_id, &id);
04880       if (hint) {
04881          p_cur = ao2_find(hint->callbacks, &id, OBJ_UNLINK);
04882          if (p_cur) {
04883             ret = 0;
04884             ao2_ref(p_cur, -1);
04885          }
04886          ao2_ref(hint, -1);
04887       }
04888       ao2_unlock(hints);
04889    }
04890 
04891    return ret;
04892 }

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

05106 {
05107    return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
05108 }

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

References E_FINDLABEL, and pbx_extension_helper().

Referenced by pbx_load_config().

05111 {
05112    return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
05113 }

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

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

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

03884 {
03885    char *copy = ast_strdupa(function);
03886    char *args = func_args(copy);
03887    struct ast_custom_function *acfptr = ast_custom_function_find(copy);
03888    int res;
03889    struct ast_module_user *u = NULL;
03890 
03891    if (acfptr == NULL) {
03892       ast_log(LOG_ERROR, "Function %s not registered\n", copy);
03893    } else if (!acfptr->read && !acfptr->read2) {
03894       ast_log(LOG_ERROR, "Function %s cannot be read\n", copy);
03895    } else if (acfptr->read) {
03896       if (acfptr->mod) {
03897          u = __ast_module_user_add(acfptr->mod, chan);
03898       }
03899       res = acfptr->read(chan, copy, args, workspace, len);
03900       if (acfptr->mod && u) {
03901          __ast_module_user_remove(acfptr->mod, u);
03902       }
03903       return res;
03904    } else {
03905       struct ast_str *str = ast_str_create(16);
03906       if (acfptr->mod) {
03907          u = __ast_module_user_add(acfptr->mod, chan);
03908       }
03909       res = acfptr->read2(chan, copy, args, &str, 0);
03910       if (acfptr->mod && u) {
03911          __ast_module_user_remove(acfptr->mod, u);
03912       }
03913       ast_copy_string(workspace, ast_str_buffer(str), len > ast_str_size(str) ? ast_str_size(str) : len);
03914       ast_free(str);
03915       return res;
03916    }
03917    return -1;
03918 }

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

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

Referenced by append_channel_vars(), and ast_str_substitute_variables_full().

03921 {
03922    char *copy = ast_strdupa(function);
03923    char *args = func_args(copy);
03924    struct ast_custom_function *acfptr = ast_custom_function_find(copy);
03925    int res;
03926    struct ast_module_user *u = NULL;
03927 
03928    if (acfptr == NULL) {
03929       ast_log(LOG_ERROR, "Function %s not registered\n", copy);
03930    } else if (!acfptr->read && !acfptr->read2) {
03931       ast_log(LOG_ERROR, "Function %s cannot be read\n", copy);
03932    } else {
03933       if (acfptr->mod) {
03934          u = __ast_module_user_add(acfptr->mod, chan);
03935       }
03936       ast_str_reset(*str);
03937       if (acfptr->read2) {
03938          /* ast_str enabled */
03939          res = acfptr->read2(chan, copy, args, str, maxlen);
03940       } else {
03941          /* Legacy function pointer, allocate buffer for result */
03942          int maxsize = ast_str_size(*str);
03943          if (maxlen > -1) {
03944             if (maxlen == 0) {
03945                if (acfptr->read_max) {
03946                   maxsize = acfptr->read_max;
03947                } else {
03948                   maxsize = VAR_BUF_SIZE;
03949                }
03950             } else {
03951                maxsize = maxlen;
03952             }
03953             ast_str_make_space(str, maxsize);
03954          }
03955          res = acfptr->read(chan, copy, args, ast_str_buffer(*str), maxsize);
03956       }
03957       if (acfptr->mod && u) {
03958          __ast_module_user_remove(acfptr->mod, u);
03959       }
03960       return res;
03961    }
03962    return -1;
03963 }

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

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

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

03966 {
03967    char *copy = ast_strdupa(function);
03968    char *args = func_args(copy);
03969    struct ast_custom_function *acfptr = ast_custom_function_find(copy);
03970 
03971    if (acfptr == NULL)
03972       ast_log(LOG_ERROR, "Function %s not registered\n", copy);
03973    else if (!acfptr->write)
03974       ast_log(LOG_ERROR, "Function %s cannot be written to\n", copy);
03975    else {
03976       int res;
03977       struct ast_module_user *u = NULL;
03978       if (acfptr->mod)
03979          u = __ast_module_user_add(acfptr->mod, chan);
03980       res = acfptr->write(chan, copy, args, value);
03981       if (acfptr->mod && u)
03982          __ast_module_user_remove(acfptr->mod, u);
03983       return res;
03984    }
03985 
03986    return -1;
03987 }

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

Definition at line 10691 of file pbx.c.

References ast_context::registrar.

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

10692 {
10693    return c ? c->registrar : NULL;
10694 }

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

References ast_exten::cidmatch.

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

10717 {
10718    return e ? e->cidmatch : NULL;
10719 }

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

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

10659 {
10660    return exten ? exten->parent : NULL;
10661 }

const char* ast_get_extension_label ( struct ast_exten e  ) 

Definition at line 10668 of file pbx.c.

References ast_exten::label.

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

10669 {
10670    return exten ? exten->label : NULL;
10671 }

int ast_get_extension_matchcid ( struct ast_exten e  ) 

Definition at line 10711 of file pbx.c.

References ast_exten::matchcid.

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

10712 {
10713    return e ? e->matchcid : 0;
10714 }

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

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

10684 {
10685    return exten ? exten->priority : -1;
10686 }

const char* ast_get_extension_registrar ( struct ast_exten e  ) 

Definition at line 10696 of file pbx.c.

References ast_exten::registrar.

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

10697 {
10698    return e ? e->registrar : NULL;
10699 }

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

05063 {
05064    struct ast_exten *e = ast_hint_extension(c, context, exten);
05065 
05066    if (e) {
05067       if (hint)
05068          ast_copy_string(hint, ast_get_extension_app(e), hintsize);
05069       if (name) {
05070          const char *tmp = ast_get_extension_app_data(e);
05071          if (tmp)
05072             ast_copy_string(name, tmp, namesize);
05073       }
05074       return -1;
05075    }
05076    return 0;
05077 }

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

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

10707 {
10708    return ip ? ip->registrar : NULL;
10709 }

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

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

10702 {
10703    return i ? i->registrar : NULL;
10704 }

const char* ast_get_switch_data ( struct ast_sw sw  ) 

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

10737 {
10738    return sw ? sw->data : NULL;
10739 }

int ast_get_switch_eval ( struct ast_sw sw  ) 

Definition at line 10741 of file pbx.c.

References ast_sw::eval.

Referenced by context_merge_incls_swits_igps_other_registrars().

10742 {
10743    return sw->eval;
10744 }

const char* ast_get_switch_name ( struct ast_sw sw  ) 

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

10732 {
10733    return sw ? sw->name : NULL;
10734 }

const char* ast_get_switch_registrar ( struct ast_sw sw  ) 

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

10747 {
10748    return sw ? sw->registrar : NULL;
10749 }

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

10842 {
10843    return __ast_goto_if_exists(chan, context, exten, priority, 0);
10844 }

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

hashtable functions for contexts

Definition at line 1081 of file pbx.c.

References ast_context::name.

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

01082 {
01083    const struct ast_context *ac = ah_a;
01084    const struct ast_context *bc = ah_b;
01085    if (!ac || !bc) /* safety valve, but it might prevent a crash you'd rather have happen */
01086       return 1;
01087    /* assume context names are registered in a string table! */
01088    return strcmp(ac->name, bc->name);
01089 }

unsigned int ast_hashtab_hash_contexts ( const void *  obj  ) 

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

01125 {
01126    const struct ast_context *ac = obj;
01127    return ast_hashtab_hash_string(ac->name);
01128 }

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

08324 {
08325    struct ast_context *con = ast_context_find(context);
08326 
08327    if (con) {
08328       struct ast_ignorepat *pat;
08329 
08330       for (pat = con->ignorepats; pat; pat = pat->next) {
08331          if (ast_extension_match(pat->pattern, pattern))
08332             return 1;
08333       }
08334    }
08335 
08336    return 0;
08337 }

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

05121 {
05122    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0);
05123 }

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

07621 {
07622    double ft;
07623    struct ast_context *tmp;
07624    struct ast_context *oldcontextslist;
07625    struct ast_hashtab *oldtable;
07626    struct store_hints hints_stored = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
07627    struct store_hints hints_removed = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
07628    struct store_hint *saved_hint;
07629    struct ast_hint *hint;
07630    struct ast_exten *exten;
07631    int length;
07632    struct ast_state_cb *thiscb;
07633    struct ast_hashtab_iter *iter;
07634    struct ao2_iterator i;
07635    struct timeval begintime;
07636    struct timeval writelocktime;
07637    struct timeval endlocktime;
07638    struct timeval enddeltime;
07639 
07640    /*
07641     * It is very important that this function hold the hints
07642     * container lock _and_ the conlock during its operation; not
07643     * only do we need to ensure that the list of contexts and
07644     * extensions does not change, but also that no hint callbacks
07645     * (watchers) are added or removed during the merge/delete
07646     * process
07647     *
07648     * In addition, the locks _must_ be taken in this order, because
07649     * there are already other code paths that use this order
07650     */
07651 
07652    begintime = ast_tvnow();
07653    ast_mutex_lock(&context_merge_lock);/* Serialize ast_merge_contexts_and_delete */
07654    ast_wrlock_contexts();
07655    iter = ast_hashtab_start_traversal(contexts_table);
07656    while ((tmp = ast_hashtab_next(iter))) {
07657       context_merge(extcontexts, exttable, tmp, registrar);
07658    }
07659    ast_hashtab_end_traversal(iter);
07660 
07661    ao2_lock(hints);
07662    writelocktime = ast_tvnow();
07663 
07664    /* preserve all watchers for hints */
07665    i = ao2_iterator_init(hints, AO2_ITERATOR_DONTLOCK);
07666    for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
07667       if (ao2_container_count(hint->callbacks)) {
07668          ao2_lock(hint);
07669          if (!hint->exten) {
07670             /* The extension has already been destroyed. (Should never happen here) */
07671             ao2_unlock(hint);
07672             continue;
07673          }
07674 
07675          length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2
07676             + sizeof(*saved_hint);
07677          if (!(saved_hint = ast_calloc(1, length))) {
07678             ao2_unlock(hint);
07679             continue;
07680          }
07681 
07682          /* This removes all the callbacks from the hint into saved_hint. */
07683          while ((thiscb = ao2_callback(hint->callbacks, OBJ_UNLINK, NULL, NULL))) {
07684             AST_LIST_INSERT_TAIL(&saved_hint->callbacks, thiscb, entry);
07685             /*
07686              * We intentionally do not unref thiscb to account for the
07687              * non-ao2 reference in saved_hint->callbacks
07688              */
07689          }
07690 
07691          saved_hint->laststate = hint->laststate;
07692          saved_hint->context = saved_hint->data;
07693          strcpy(saved_hint->data, hint->exten->parent->name);
07694          saved_hint->exten = saved_hint->data + strlen(saved_hint->context) + 1;
07695          strcpy(saved_hint->exten, hint->exten->exten);
07696          ao2_unlock(hint);
07697          AST_LIST_INSERT_HEAD(&hints_stored, saved_hint, list);
07698       }
07699    }
07700    ao2_iterator_destroy(&i);
07701 
07702    /* save the old table and list */
07703    oldtable = contexts_table;
07704    oldcontextslist = contexts;
07705 
07706    /* move in the new table and list */
07707    contexts_table = exttable;
07708    contexts = *extcontexts;
07709 
07710    /*
07711     * Restore the watchers for hints that can be found; notify
07712     * those that cannot be restored.
07713     */
07714    while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_stored, list))) {
07715       struct pbx_find_info q = { .stacklen = 0 };
07716 
07717       exten = pbx_find_extension(NULL, NULL, &q, saved_hint->context, saved_hint->exten,
07718          PRIORITY_HINT, NULL, "", E_MATCH);
07719       /*
07720        * If this is a pattern, dynamically create a new extension for this
07721        * particular match.  Note that this will only happen once for each
07722        * individual extension, because the pattern will no longer match first.
07723        */
07724       if (exten && exten->exten[0] == '_') {
07725          ast_add_extension_nolock(exten->parent->name, 0, saved_hint->exten,
07726             PRIORITY_HINT, NULL, 0, exten->app, ast_strdup(exten->data), ast_free_ptr,
07727             exten->registrar);
07728          /* rwlocks are not recursive locks */
07729          exten = ast_hint_extension_nolock(NULL, saved_hint->context,
07730             saved_hint->exten);
07731       }
07732 
07733       /* Find the hint in the hints container */
07734       hint = exten ? ao2_find(hints, exten, 0) : NULL;
07735       if (!hint) {
07736          /*
07737           * Notify watchers of this removed hint later when we aren't
07738           * encumberd by so many locks.
07739           */
07740          AST_LIST_INSERT_HEAD(&hints_removed, saved_hint, list);
07741       } else {
07742          ao2_lock(hint);
07743          while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) {
07744             ao2_link(hint->callbacks, thiscb);
07745             /* Ref that we added when putting into saved_hint->callbacks */
07746             ao2_ref(thiscb, -1);
07747          }
07748          hint->laststate = saved_hint->laststate;
07749          ao2_unlock(hint);
07750          ao2_ref(hint, -1);
07751          ast_free(saved_hint);
07752       }
07753    }
07754 
07755    ao2_unlock(hints);
07756    ast_unlock_contexts();
07757 
07758    /*
07759     * Notify watchers of all removed hints with the same lock
07760     * environment as handle_statechange().
07761     */
07762    while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_removed, list))) {
07763       /* this hint has been removed, notify the watchers */
07764       while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) {
07765          thiscb->change_cb(saved_hint->context, saved_hint->exten,
07766             AST_EXTENSION_REMOVED, thiscb->data);
07767          /* Ref that we added when putting into saved_hint->callbacks */
07768          ao2_ref(thiscb, -1);
07769       }
07770       ast_free(saved_hint);
07771    }
07772 
07773    ast_mutex_unlock(&context_merge_lock);
07774    endlocktime = ast_tvnow();
07775 
07776    /*
07777     * The old list and hashtab no longer are relevant, delete them
07778     * while the rest of asterisk is now freely using the new stuff
07779     * instead.
07780     */
07781 
07782    ast_hashtab_destroy(oldtable, NULL);
07783 
07784    for (tmp = oldcontextslist; tmp; ) {
07785       struct ast_context *next;  /* next starting point */
07786 
07787       next = tmp->next;
07788       __ast_internal_context_destroy(tmp);
07789       tmp = next;
07790    }
07791    enddeltime = ast_tvnow();
07792 
07793    ft = ast_tvdiff_us(writelocktime, begintime);
07794    ft /= 1000000.0;
07795    ast_verb(3,"Time to scan old dialplan and merge leftovers back into the new: %8.6f sec\n", ft);
07796 
07797    ft = ast_tvdiff_us(endlocktime, writelocktime);
07798    ft /= 1000000.0;
07799    ast_verb(3,"Time to restore hints and swap in new dialplan: %8.6f sec\n", ft);
07800 
07801    ft = ast_tvdiff_us(enddeltime, endlocktime);
07802    ft /= 1000000.0;
07803    ast_verb(3,"Time to delete the old dialplan: %8.6f sec\n", ft);
07804 
07805    ft = ast_tvdiff_us(enddeltime, begintime);
07806    ft /= 1000000.0;
07807    ast_verb(3,"Total time merge_contexts_delete: %8.6f sec\n", ft);
07808 }

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

10907 {
10908    return pbx_parseable_goto(chan, goto_string, 0);
10909 }

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

09218 {
09219    struct ast_channel *chan;
09220    struct app_tmp *tmp;
09221    int res = -1, cdr_res = -1;
09222    struct outgoing_helper oh;
09223 
09224    memset(&oh, 0, sizeof(oh));
09225    oh.vars = vars;
09226    oh.account = account;
09227 
09228    if (locked_channel)
09229       *locked_channel = NULL;
09230    if (ast_strlen_zero(app)) {
09231       res = -1;
09232       goto outgoing_app_cleanup;
09233    }
09234    if (synchronous) {
09235       chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh);
09236       if (chan) {
09237          ast_set_variables(chan, vars);
09238          if (account)
09239             ast_cdr_setaccount(chan, account);
09240          if (chan->_state == AST_STATE_UP) {
09241             res = 0;
09242             ast_verb(4, "Channel %s was answered.\n", chan->name);
09243             tmp = ast_calloc(1, sizeof(*tmp));
09244             if (!tmp || ast_string_field_init(tmp, 252)) {
09245                if (tmp) {
09246                   ast_free(tmp);
09247                }
09248                res = -1;
09249             } else {
09250                ast_string_field_set(tmp, app, app);
09251                ast_string_field_set(tmp, data, appdata);
09252                tmp->chan = chan;
09253                if (synchronous > 1) {
09254                   if (locked_channel)
09255                      ast_channel_unlock(chan);
09256                   ast_pbx_run_app(tmp);
09257                } else {
09258                   if (locked_channel)
09259                      ast_channel_lock(chan);
09260                   if (ast_pthread_create_detached(&tmp->t, NULL, ast_pbx_run_app, tmp)) {
09261                      ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno));
09262                      ast_string_field_free_memory(tmp);
09263                      ast_free(tmp);
09264                      if (locked_channel)
09265                         ast_channel_unlock(chan);
09266                      ast_hangup(chan);
09267                      res = -1;
09268                   } else {
09269                      if (locked_channel)
09270                         *locked_channel = chan;
09271                   }
09272                }
09273             }
09274          } else {
09275             ast_verb(4, "Channel %s was never answered.\n", chan->name);
09276             if (chan->cdr) { /* update the cdr */
09277                /* here we update the status of the call, which sould be busy.
09278                 * if that fails then we set the status to failed */
09279                if (ast_cdr_disposition(chan->cdr, chan->hangupcause))
09280                   ast_cdr_failed(chan->cdr);
09281             }
09282             ast_hangup(chan);
09283          }
09284       }
09285 
09286       if (res < 0) { /* the call failed for some reason */
09287          if (*reason == 0) { /* if the call failed (not busy or no answer)
09288                         * update the cdr with the failed message */
09289             cdr_res = ast_pbx_outgoing_cdr_failed();
09290             if (cdr_res != 0) {
09291                res = cdr_res;
09292                goto outgoing_app_cleanup;
09293             }
09294          }
09295       }
09296 
09297    } else {
09298       struct async_stat *as;
09299       if (!(as = ast_calloc(1, sizeof(*as)))) {
09300          res = -1;
09301          goto outgoing_app_cleanup;
09302       }
09303       chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh);
09304       if (!chan) {
09305          ast_free(as);
09306          res = -1;
09307          goto outgoing_app_cleanup;
09308       }
09309       as->chan = chan;
09310       ast_copy_string(as->app, app, sizeof(as->app));
09311       if (appdata)
09312          ast_copy_string(as->appdata,  appdata, sizeof(as->appdata));
09313       as->timeout = timeout;
09314       ast_set_variables(chan, vars);
09315       if (account)
09316          ast_cdr_setaccount(chan, account);
09317       /* Start a new thread, and get something handling this channel. */
09318       if (locked_channel)
09319          ast_channel_lock(chan);
09320       if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) {
09321          ast_log(LOG_WARNING, "Failed to start async wait\n");
09322          ast_free(as);
09323          if (locked_channel)
09324             ast_channel_unlock(chan);
09325          ast_hangup(chan);
09326          res = -1;
09327          goto outgoing_app_cleanup;
09328       } else {
09329          if (locked_channel)
09330             *locked_channel = chan;
09331       }
09332       res = 0;
09333    }
09334 outgoing_app_cleanup:
09335    ast_variables_destroy(vars);
09336    return res;
09337 }

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

09049 {
09050    struct ast_channel *chan;
09051    struct async_stat *as;
09052    int res = -1, cdr_res = -1;
09053    struct outgoing_helper oh;
09054 
09055    if (synchronous) {
09056       oh.context = context;
09057       oh.exten = exten;
09058       oh.priority = priority;
09059       oh.cid_num = cid_num;
09060       oh.cid_name = cid_name;
09061       oh.account = account;
09062       oh.vars = vars;
09063       oh.parent_channel = NULL;
09064 
09065       chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh);
09066       if (channel) {
09067          *channel = chan;
09068          if (chan)
09069             ast_channel_lock(chan);
09070       }
09071       if (chan) {
09072          if (chan->_state == AST_STATE_UP) {
09073                res = 0;
09074             ast_verb(4, "Channel %s was answered.\n", chan->name);
09075 
09076             if (synchronous > 1) {
09077                if (channel)
09078                   ast_channel_unlock(chan);
09079                if (ast_pbx_run(chan)) {
09080                   ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name);
09081                   if (channel)
09082                      *channel = NULL;
09083                   ast_hangup(chan);
09084                   chan = NULL;
09085                   res = -1;
09086                }
09087             } else {
09088                if (ast_pbx_start(chan)) {
09089                   ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name);
09090                   if (channel) {
09091                      *channel = NULL;
09092                      ast_channel_unlock(chan);
09093                   }
09094                   ast_hangup(chan);
09095                   res = -1;
09096                }
09097                chan = NULL;
09098             }
09099          } else {
09100             ast_verb(4, "Channel %s was never answered.\n", chan->name);
09101 
09102             if (chan->cdr) { /* update the cdr */
09103                /* here we update the status of the call, which sould be busy.
09104                 * if that fails then we set the status to failed */
09105                if (ast_cdr_disposition(chan->cdr, chan->hangupcause))
09106                   ast_cdr_failed(chan->cdr);
09107             }
09108 
09109             if (channel) {
09110                *channel = NULL;
09111                ast_channel_unlock(chan);
09112             }
09113             ast_hangup(chan);
09114             chan = NULL;
09115          }
09116       }
09117 
09118       if (res < 0) { /* the call failed for some reason */
09119          if (*reason == 0) { /* if the call failed (not busy or no answer)
09120                         * update the cdr with the failed message */
09121             cdr_res = ast_pbx_outgoing_cdr_failed();
09122             if (cdr_res != 0) {
09123                res = cdr_res;
09124                goto outgoing_exten_cleanup;
09125             }
09126          }
09127 
09128          /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */
09129          /* check if "failed" exists */
09130          if (ast_exists_extension(chan, context, "failed", 1, NULL)) {
09131             chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", NULL, 0, "OutgoingSpoolFailed");
09132             if (chan) {
09133                char failed_reason[4] = "";
09134                if (!ast_strlen_zero(context))
09135                   ast_copy_string(chan->context, context, sizeof(chan->context));
09136                set_ext_pri(chan, "failed", 1);
09137                ast_set_variables(chan, vars);
09138                snprintf(failed_reason, sizeof(failed_reason), "%d", *reason);
09139                pbx_builtin_setvar_helper(chan, "REASON", failed_reason);
09140                if (account)
09141                   ast_cdr_setaccount(chan, account);
09142                if (ast_pbx_run(chan)) {
09143                   ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name);
09144                   ast_hangup(chan);
09145                }
09146                chan = NULL;
09147             }
09148          }
09149       }
09150    } else {
09151       if (!(as = ast_calloc(1, sizeof(*as)))) {
09152          res = -1;
09153          goto outgoing_exten_cleanup;
09154       }
09155       chan = ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name);
09156       if (channel) {
09157          *channel = chan;
09158          if (chan)
09159             ast_channel_lock(chan);
09160       }
09161       if (!chan) {
09162          ast_free(as);
09163          res = -1;
09164          goto outgoing_exten_cleanup;
09165       }
09166       as->chan = chan;
09167       ast_copy_string(as->context, context, sizeof(as->context));
09168       set_ext_pri(as->chan,  exten, priority);
09169       as->timeout = timeout;
09170       ast_set_variables(chan, vars);
09171       if (account)
09172          ast_cdr_setaccount(chan, account);
09173       if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) {
09174          ast_log(LOG_WARNING, "Failed to start async wait\n");
09175          ast_free(as);
09176          if (channel) {
09177             *channel = NULL;
09178             ast_channel_unlock(chan);
09179          }
09180          ast_hangup(chan);
09181          res = -1;
09182          goto outgoing_exten_cleanup;
09183       }
09184       res = 0;
09185    }
09186 outgoing_exten_cleanup:
09187    ast_variables_destroy(vars);
09188    return res;
09189 }

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

05627 {
05628    return ast_pbx_run_args(c, NULL);
05629 }

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

05607 {
05608    enum ast_pbx_result res = AST_PBX_SUCCESS;
05609 
05610    if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) {
05611       ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n");
05612       return AST_PBX_FAILED;
05613    }
05614 
05615    if (increase_call_count(c)) {
05616       return AST_PBX_CALL_LIMIT;
05617    }
05618 
05619    res = __ast_pbx_run(c, args);
05620 
05621    decrease_call_count();
05622 
05623    return res;
05624 }

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

05580 {
05581    pthread_t t;
05582 
05583    if (!c) {
05584       ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
05585       return AST_PBX_FAILED;
05586    }
05587 
05588    if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) {
05589       ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n");
05590       return AST_PBX_FAILED;
05591    }
05592 
05593    if (increase_call_count(c))
05594       return AST_PBX_CALL_LIMIT;
05595 
05596    /* Start a new thread, and get something handling this channel. */
05597    if (ast_pthread_create_detached(&t, NULL, pbx_thread, c)) {
05598       ast_log(LOG_WARNING, "Failed to create new channel thread\n");
05599       decrease_call_count();
05600       return AST_PBX_FAILED;
05601    }
05602 
05603    return AST_PBX_SUCCESS;
05604 }

int ast_processed_calls ( void   ) 

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

Definition at line 5636 of file pbx.c.

References totalcalls.

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

05637 {
05638    return totalcalls;
05639 }

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

10641 {
10642    return ast_rwlock_rdlock(&con->lock);
10643 }

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

06143 {
06144    struct ast_switch *tmp;
06145 
06146    AST_RWLIST_WRLOCK(&switches);
06147    AST_RWLIST_TRAVERSE(&switches, tmp, list) {
06148       if (!strcasecmp(tmp->name, sw->name)) {
06149          AST_RWLIST_UNLOCK(&switches);
06150          ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name);
06151          return -1;
06152       }
06153    }
06154    AST_RWLIST_INSERT_TAIL(&switches, sw, list);
06155    AST_RWLIST_UNLOCK(&switches);
06156 
06157    return 0;
06158 }

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

References E_SPAWN, and pbx_extension_helper().

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

05126 {
05127    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN, found, combined_find_spawn);
05128 }

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

05081 {
05082    struct ast_exten *e = ast_hint_extension(c, context, exten);
05083 
05084    if (!e) {
05085       return 0;
05086    }
05087 
05088    if (hint) {
05089       ast_str_set(hint, hintsize, "%s", ast_get_extension_app(e));
05090    }
05091    if (name) {
05092       const char *tmp = ast_get_extension_app_data(e);
05093       if (tmp) {
05094          ast_str_set(name, namesize, "%s", tmp);
05095       }
05096    }
05097    return -1;
05098 }

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

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

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

04169 {
04170    size_t used;
04171    ast_str_substitute_variables_full(buf, maxlen, chan, NULL, templ, &used);
04172 }

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

03990 {
03991    /* Substitutes variables into buf, based on string templ */
03992    char *cp4 = NULL;
03993    const char *tmp, *whereweare;
03994    int orig_size = 0;
03995    int offset, offset2, isfunction;
03996    const char *nextvar, *nextexp, *nextthing;
03997    const char *vars, *vare;
03998    char *finalvars;
03999    int pos, brackets, needsub, len;
04000    struct ast_str *substr1 = ast_str_create(16), *substr2 = NULL, *substr3 = ast_str_create(16);
04001 
04002    ast_str_reset(*buf);
04003    whereweare = tmp = templ;
04004    while (!ast_strlen_zero(whereweare)) {
04005       /* reset our buffer */
04006       ast_str_reset(substr3);
04007 
04008       /* Assume we're copying the whole remaining string */
04009       pos = strlen(whereweare);
04010       nextvar = NULL;
04011       nextexp = NULL;
04012       nextthing = strchr(whereweare, '$');
04013       if (nextthing) {
04014          switch (nextthing[1]) {
04015          case '{':
04016             nextvar = nextthing;
04017             pos = nextvar - whereweare;
04018             break;
04019          case '[':
04020             nextexp = nextthing;
04021             pos = nextexp - whereweare;
04022             break;
04023          default:
04024             pos = 1;
04025          }
04026       }
04027 
04028       if (pos) {
04029          /* Copy that many bytes */
04030          ast_str_append_substr(buf, maxlen, whereweare, pos);
04031 
04032          templ += pos;
04033          whereweare += pos;
04034       }
04035 
04036       if (nextvar) {
04037          /* We have a variable.  Find the start and end, and determine
04038             if we are going to have to recursively call ourselves on the
04039             contents */
04040          vars = vare = nextvar + 2;
04041          brackets = 1;
04042          needsub = 0;
04043 
04044          /* Find the end of it */
04045          while (brackets && *vare) {
04046             if ((vare[0] == '$') && (vare[1] == '{')) {
04047                needsub++;
04048             } else if (vare[0] == '{') {
04049                brackets++;
04050             } else if (vare[0] == '}') {
04051                brackets--;
04052             } else if ((vare[0] == '$') && (vare[1] == '['))
04053                needsub++;
04054             vare++;
04055          }
04056          if (brackets)
04057             ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n");
04058          len = vare - vars - 1;
04059 
04060          /* Skip totally over variable string */
04061          whereweare += (len + 3);
04062 
04063          /* Store variable name (and truncate) */
04064          ast_str_set_substr(&substr1, 0, vars, len);
04065          ast_debug(5, "Evaluating '%s' (from '%s' len %d)\n", ast_str_buffer(substr1), vars, len);
04066 
04067          /* Substitute if necessary */
04068          if (needsub) {
04069             size_t used;
04070             if (!substr2) {
04071                substr2 = ast_str_create(16);
04072             }
04073 
04074             ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used);
04075             finalvars = ast_str_buffer(substr2);
04076          } else {
04077             finalvars = ast_str_buffer(substr1);
04078          }
04079 
04080          parse_variable_name(finalvars, &offset, &offset2, &isfunction);
04081          if (isfunction) {
04082             /* Evaluate function */
04083             if (c || !headp) {
04084                cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3);
04085             } else {
04086                struct varshead old;
04087                struct ast_channel *bogus = ast_dummy_channel_alloc();
04088                if (bogus) {
04089                   memcpy(&old, &bogus->varshead, sizeof(old));
04090                   memcpy(&bogus->varshead, headp, sizeof(bogus->varshead));
04091                   cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3);
04092                   /* Don't deallocate the varshead that was passed in */
04093                   memcpy(&bogus->varshead, &old, sizeof(bogus->varshead));
04094                   ast_channel_unref(bogus);
04095                } else {
04096                   ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution.  Function results may be blank.\n");
04097                }
04098             }
04099             ast_debug(2, "Function result is '%s'\n", cp4 ? cp4 : "(null)");
04100          } else {
04101             /* Retrieve variable value */
04102             ast_str_retrieve_variable(&substr3, 0, c, headp, finalvars);
04103             cp4 = ast_str_buffer(substr3);
04104          }
04105          if (cp4) {
04106             ast_str_substring(substr3, offset, offset2);
04107             ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3));
04108          }
04109       } else if (nextexp) {
04110          /* We have an expression.  Find the start and end, and determine
04111             if we are going to have to recursively call ourselves on the
04112             contents */
04113          vars = vare = nextexp + 2;
04114          brackets = 1;
04115          needsub = 0;
04116 
04117          /* Find the end of it */
04118          while (brackets && *vare) {
04119             if ((vare[0] == '$') && (vare[1] == '[')) {
04120                needsub++;
04121                brackets++;
04122                vare++;
04123             } else if (vare[0] == '[') {
04124                brackets++;
04125             } else if (vare[0] == ']') {
04126                brackets--;
04127             } else if ((vare[0] == '$') && (vare[1] == '{')) {
04128                needsub++;
04129                vare++;
04130             }
04131             vare++;
04132          }
04133          if (brackets)
04134             ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n");
04135          len = vare - vars - 1;
04136 
04137          /* Skip totally over expression */
04138          whereweare += (len + 3);
04139 
04140          /* Store variable name (and truncate) */
04141          ast_str_set_substr(&substr1, 0, vars, len);
04142 
04143          /* Substitute if necessary */
04144          if (needsub) {
04145             size_t used;
04146             if (!substr2) {
04147                substr2 = ast_str_create(16);
04148             }
04149 
04150             ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used);
04151             finalvars = ast_str_buffer(substr2);
04152          } else {
04153             finalvars = ast_str_buffer(substr1);
04154          }
04155 
04156          if (ast_str_expr(&substr3, 0, c, finalvars)) {
04157             ast_debug(2, "Expression result is '%s'\n", ast_str_buffer(substr3));
04158          }
04159          ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3));
04160       }
04161    }
04162    *used = ast_str_strlen(*buf) - orig_size;
04163    ast_free(substr1);
04164    ast_free(substr2);
04165    ast_free(substr3);
04166 }

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

04175 {
04176    size_t used;
04177    ast_str_substitute_variables_full(buf, maxlen, NULL, headp, templ, &used);
04178 }

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

References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

Referenced by __unload_module(), and unload_module().

06161 {
06162    AST_RWLIST_WRLOCK(&switches);
06163    AST_RWLIST_REMOVE(&switches, sw, list);
06164    AST_RWLIST_UNLOCK(&switches);
06165 }

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

10794 {
10795    if (!ip)
10796       return con ? con->ignorepats : NULL;
10797    else
10798       return ip->next;
10799 }

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

10770 {
10771    if (!sw)
10772       return con ? AST_LIST_FIRST(&con->alts) : NULL;
10773    else
10774       return AST_LIST_NEXT(sw, list);
10775 }

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

10779 {
10780    return priority ? priority->peer : exten;
10781 }

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

10636 {
10637    return ast_rwlock_wrlock(&con->lock);
10638 }

int ast_wrlock_contexts ( void   ) 

Write locks the context list.

Return values:
0 on success
-1 on error

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

10618 {
10619    return ast_mutex_lock(&conlock);
10620 }

void pbx_builtin_clear_globals ( void   ) 

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

10385 {
10386    struct ast_var_t *vardata;
10387 
10388    ast_rwlock_wrlock(&globalslock);
10389    while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries)))
10390       ast_var_delete(vardata);
10391    ast_rwlock_unlock(&globalslock);
10392 }

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

10149 {
10150    struct ast_var_t *variables;
10151    const char *ret = NULL;
10152    int i;
10153    struct varshead *places[2] = { NULL, &globals };
10154 
10155    if (!name)
10156       return NULL;
10157 
10158    if (chan) {
10159       ast_channel_lock(chan);
10160       places[0] = &chan->varshead;
10161    }
10162 
10163    for (i = 0; i < 2; i++) {
10164       if (!places[i])
10165          continue;
10166       if (places[i] == &globals)
10167          ast_rwlock_rdlock(&globalslock);
10168       AST_LIST_TRAVERSE(places[i], variables, entries) {
10169          if (!strcmp(name, ast_var_name(variables))) {
10170             ret = ast_var_value(variables);
10171             break;
10172          }
10173       }
10174       if (places[i] == &globals)
10175          ast_rwlock_unlock(&globalslock);
10176       if (ret)
10177          break;
10178    }
10179 
10180    if (chan)
10181       ast_channel_unlock(chan);
10182 
10183    return ret;
10184 }

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

10187 {
10188    struct ast_var_t *newvariable;
10189    struct varshead *headp;
10190 
10191    if (name[strlen(name)-1] == ')') {
10192       char *function = ast_strdupa(name);
10193 
10194       ast_log(LOG_WARNING, "Cannot push a value onto a function\n");
10195       ast_func_write(chan, function, value);
10196       return;
10197    }
10198 
10199    if (chan) {
10200       ast_channel_lock(chan);
10201       headp = &chan->varshead;
10202    } else {
10203       ast_rwlock_wrlock(&globalslock);
10204       headp = &globals;
10205    }
10206 
10207    if (value) {
10208       if (headp == &globals)
10209          ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value);
10210       newvariable = ast_var_assign(name, value);
10211       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
10212    }
10213 
10214    if (chan)
10215       ast_channel_unlock(chan);
10216    else
10217       ast_rwlock_unlock(&globalslock);
10218 }

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

Definition at line 3545 of file pbx.c.

References raise_exception().

03546 {
03547    /* Priority will become 1, next time through the AUTOLOOP */
03548    return raise_exception(chan, reason, 0);
03549 }

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

10118 {
10119    struct ast_var_t *variables;
10120    const char *var, *val;
10121    int total = 0;
10122 
10123    if (!chan)
10124       return 0;
10125 
10126    ast_str_reset(*buf);
10127 
10128    ast_channel_lock(chan);
10129 
10130    AST_LIST_TRAVERSE(&chan->varshead, variables, entries) {
10131       if ((var = ast_var_name(variables)) && (val = ast_var_value(variables))
10132          /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */
10133          ) {
10134          if (ast_str_append(buf, 0, "%s=%s\n", var, val) < 0) {
10135             ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
10136             break;
10137          } else
10138             total++;
10139       } else
10140          break;
10141    }
10142 
10143    ast_channel_unlock(chan);
10144 
10145    return total;
10146 }

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

10279 {
10280    char *name, *value, *mydata;
10281 
10282    if (ast_compat_app_set) {
10283       return pbx_builtin_setvar_multiple(chan, data);
10284    }
10285 
10286    if (ast_strlen_zero(data)) {
10287       ast_log(LOG_WARNING, "Set requires one variable name/value pair.\n");
10288       return 0;
10289    }
10290 
10291    mydata = ast_strdupa(data);
10292    name = strsep(&mydata, "=");
10293    value = mydata;
10294    if (!value) {
10295       ast_log(LOG_WARNING, "Set requires an '=' to be a valid assignment.\n");
10296       return 0;
10297    }
10298 
10299    if (strchr(name, ' ')) {
10300       ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, mydata);
10301    }
10302 
10303    pbx_builtin_setvar_helper(chan, name, value);
10304 
10305    return 0;
10306 }

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 10220 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(), 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(), parked_call_exec(), parse_moved_contact(), pbx_builtin_background(), pbx_builtin_gotoiftime(), pbx_builtin_importvar(), pbx_builtin_setvar(), pbx_builtin_setvar_multiple(), pbx_load_config(), phase_e_handler(), play_message_datetime(), playback_exec(), pqm_exec(), prep_email_sub_vars(), privacy_exec(), process_ast_dsp(), process_sdp(), read_exec(), readexten_exec(), readfile_exec(), realtimefield_read(), receivefax_exec(), record_exec(), reload_module(), return_exec(), rollback_exec(), rotate_file(), 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().

10221 {
10222    struct ast_var_t *newvariable;
10223    struct varshead *headp;
10224    const char *nametail = name;
10225 
10226    if (name[strlen(name) - 1] == ')') {
10227       char *function = ast_strdupa(name);
10228 
10229       return ast_func_write(chan, function, value);
10230    }
10231 
10232    if (chan) {
10233       ast_channel_lock(chan);
10234       headp = &chan->varshead;
10235    } else {
10236       ast_rwlock_wrlock(&globalslock);
10237       headp = &globals;
10238    }
10239 
10240    /* For comparison purposes, we have to strip leading underscores */
10241    if (*nametail == '_') {
10242       nametail++;
10243       if (*nametail == '_')
10244          nametail++;
10245    }
10246 
10247    AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) {
10248       if (strcmp(ast_var_name(newvariable), nametail) == 0) {
10249          /* there is already such a variable, delete it */
10250          AST_LIST_REMOVE_CURRENT(entries);
10251          ast_var_delete(newvariable);
10252          break;
10253       }
10254    }
10255    AST_LIST_TRAVERSE_SAFE_END;
10256 
10257    if (value) {
10258       if (headp == &globals)
10259          ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value);
10260       newvariable = ast_var_assign(name, value);
10261       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
10262       manager_event(EVENT_FLAG_DIALPLAN, "VarSet",
10263          "Channel: %s\r\n"
10264          "Variable: %s\r\n"
10265          "Value: %s\r\n"
10266          "Uniqueid: %s\r\n",
10267          chan ? chan->name : "none", name, value,
10268          chan ? chan->uniqueid : "none");
10269    }
10270 
10271    if (chan)
10272       ast_channel_unlock(chan);
10273    else
10274       ast_rwlock_unlock(&globalslock);
10275    return 0;
10276 }

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

10309 {
10310    char *data;
10311    int x;
10312    AST_DECLARE_APP_ARGS(args,
10313       AST_APP_ARG(pair)[24];
10314    );
10315    AST_DECLARE_APP_ARGS(pair,
10316       AST_APP_ARG(name);
10317       AST_APP_ARG(value);
10318    );
10319 
10320    if (ast_strlen_zero(vdata)) {
10321       ast_log(LOG_WARNING, "MSet requires at least one variable name/value pair.\n");
10322       return 0;
10323    }
10324 
10325    data = ast_strdupa(vdata);
10326    AST_STANDARD_APP_ARGS(args, data);
10327 
10328    for (x = 0; x < args.argc; x++) {
10329       AST_NONSTANDARD_APP_ARGS(pair, args.pair[x], '=');
10330       if (pair.argc == 2) {
10331          pbx_builtin_setvar_helper(chan, pair.name, pair.value);
10332          if (strchr(pair.name, ' '))
10333             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);
10334       } else if (!chan) {
10335          ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '='\n", pair.name);
10336       } else {
10337          ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '=' (in %s@%s:%d\n", pair.name, chan->exten, chan->context, chan->priority);
10338       }
10339    }
10340 
10341    return 0;
10342 }

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

10395 {
10396    int res;
10397    if (ast_strlen_zero(condition)) {                /* NULL or empty strings are false */
10398       return 0;
10399    } else if (sscanf(condition, "%30d", &res) == 1) { /* Numbers are evaluated for truth */
10400       return res;
10401    } else {                                         /* Strings are true */
10402       return 1;
10403    }
10404 }

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

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

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

01421 {
01422    int res;
01423    struct ast_module_user *u = NULL;
01424    const char *saved_c_appl;
01425    const char *saved_c_data;
01426 
01427    if (c->cdr && !ast_check_hangup(c))
01428       ast_cdr_setapp(c->cdr, app->name, data);
01429 
01430    /* save channel values */
01431    saved_c_appl= c->appl;
01432    saved_c_data= c->data;
01433 
01434    c->appl = app->name;
01435    c->data = data;
01436    ast_cel_report_event(c, AST_CEL_APP_START, NULL, NULL, NULL);
01437 
01438    if (app->module)
01439       u = __ast_module_user_add(app->module, c);
01440    if (strcasecmp(app->name, "system") && !ast_strlen_zero(data) &&
01441          strchr(data, '|') && !strchr(data, ',') && !ast_opt_dont_warn) {
01442       ast_log(LOG_WARNING, "The application delimiter is now the comma, not "
01443          "the pipe.  Did you forget to convert your dialplan?  (%s(%s))\n",
01444          app->name, (char *) data);
01445    }
01446    res = app->execute(c, S_OR(data, ""));
01447    if (app->module && u)
01448       __ast_module_user_remove(app->module, u);
01449    ast_cel_report_event(c, AST_CEL_APP_END, NULL, NULL, NULL);
01450    /* restore channel values */
01451    c->appl = saved_c_appl;
01452    c->data = saved_c_data;
01453    return res;
01454 }

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

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

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

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

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

01463 {
01464    struct ast_app *tmp;
01465 
01466    AST_RWLIST_RDLOCK(&apps);
01467    AST_RWLIST_TRAVERSE(&apps, tmp, list) {
01468       if (!strcasecmp(tmp->name, app))
01469          break;
01470    }
01471    AST_RWLIST_UNLOCK(&apps);
01472 
01473    return tmp;
01474 }

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

03360 {
03361    struct ast_str *str = ast_str_create(16);
03362    const char *cret;
03363 
03364    cret = ast_str_retrieve_variable(&str, 0, c, headp, var);
03365    ast_copy_string(workspace, ast_str_buffer(str), workspacelen);
03366    *ret = cret ? workspace : NULL;
03367    ast_free(str);
03368 }

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

References autofallthrough.

Referenced by pbx_load_module().

05642 {
05643    int oldval = autofallthrough;
05644    autofallthrough = newval;
05645    return oldval;
05646 }

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

References extenpatternmatchnew.

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

05649 {
05650    int oldval = extenpatternmatchnew;
05651    extenpatternmatchnew = newval;
05652    return oldval;
05653 }

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

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

Referenced by pbx_load_module().

05656 {
05657    if (overrideswitch) {
05658       ast_free(overrideswitch);
05659    }
05660    if (!ast_strlen_zero(newval)) {
05661       overrideswitch = ast_strdup(newval);
05662    } else {
05663       overrideswitch = NULL;
05664    }
05665 }

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

04181 {
04182    /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!!  */
04183    char *cp4 = NULL;
04184    const char *tmp, *whereweare, *orig_cp2 = cp2;
04185    int length, offset, offset2, isfunction;
04186    char *workspace = NULL;
04187    char *ltmp = NULL, *var = NULL;
04188    char *nextvar, *nextexp, *nextthing;
04189    char *vars, *vare;
04190    int pos, brackets, needsub, len;
04191 
04192    *cp2 = 0; /* just in case nothing ends up there */
04193    whereweare=tmp=cp1;
04194    while (!ast_strlen_zero(whereweare) && count) {
04195       /* Assume we're copying the whole remaining string */
04196       pos = strlen(whereweare);
04197       nextvar = NULL;
04198       nextexp = NULL;
04199       nextthing = strchr(whereweare, '$');
04200       if (nextthing) {
04201          switch (nextthing[1]) {
04202          case '{':
04203             nextvar = nextthing;
04204             pos = nextvar - whereweare;
04205             break;
04206          case '[':
04207             nextexp = nextthing;
04208             pos = nextexp - whereweare;
04209             break;
04210          default:
04211             pos = 1;
04212          }
04213       }
04214 
04215       if (pos) {
04216          /* Can't copy more than 'count' bytes */
04217          if (pos > count)
04218             pos = count;
04219 
04220          /* Copy that many bytes */
04221          memcpy(cp2, whereweare, pos);
04222 
04223          count -= pos;
04224          cp2 += pos;
04225          whereweare += pos;
04226          *cp2 = 0;
04227       }
04228 
04229       if (nextvar) {
04230          /* We have a variable.  Find the start and end, and determine
04231             if we are going to have to recursively call ourselves on the
04232             contents */
04233          vars = vare = nextvar + 2;
04234          brackets = 1;
04235          needsub = 0;
04236 
04237          /* Find the end of it */
04238          while (brackets && *vare) {
04239             if ((vare[0] == '$') && (vare[1] == '{')) {
04240                needsub++;
04241             } else if (vare[0] == '{') {
04242                brackets++;
04243             } else if (vare[0] == '}') {
04244                brackets--;
04245             } else if ((vare[0] == '$') && (vare[1] == '['))
04246                needsub++;
04247             vare++;
04248          }
04249          if (brackets)
04250             ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n");
04251          len = vare - vars - 1;
04252 
04253          /* Skip totally over variable string */
04254          whereweare += (len + 3);
04255 
04256          if (!var)
04257             var = ast_alloca(VAR_BUF_SIZE);
04258 
04259          /* Store variable name (and truncate) */
04260          ast_copy_string(var, vars, len + 1);
04261 
04262          /* Substitute if necessary */
04263          if (needsub) {
04264             size_t used;
04265             if (!ltmp)
04266                ltmp = ast_alloca(VAR_BUF_SIZE);
04267 
04268             pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used);
04269             vars = ltmp;
04270          } else {
04271             vars = var;
04272          }
04273 
04274          if (!workspace)
04275             workspace = ast_alloca(VAR_BUF_SIZE);
04276 
04277          workspace[0] = '\0';
04278 
04279          parse_variable_name(vars, &offset, &offset2, &isfunction);
04280          if (isfunction) {
04281             /* Evaluate function */
04282             if (c || !headp)
04283                cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
04284             else {
04285                struct varshead old;
04286                struct ast_channel *c = ast_dummy_channel_alloc();
04287                if (c) {
04288                   memcpy(&old, &c->varshead, sizeof(old));
04289                   memcpy(&c->varshead, headp, sizeof(c->varshead));
04290                   cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
04291                   /* Don't deallocate the varshead that was passed in */
04292                   memcpy(&c->varshead, &old, sizeof(c->varshead));
04293                   c = ast_channel_unref(c);
04294                } else {
04295                   ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution.  Function results may be blank.\n");
04296                }
04297             }
04298             ast_debug(2, "Function result is '%s'\n", cp4 ? cp4 : "(null)");
04299          } else {
04300             /* Retrieve variable value */
04301             pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp);
04302          }
04303          if (cp4) {
04304             cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE);
04305 
04306             length = strlen(cp4);
04307             if (length > count)
04308                length = count;
04309             memcpy(cp2, cp4, length);
04310             count -= length;
04311             cp2 += length;
04312             *cp2 = 0;
04313          }
04314       } else if (nextexp) {
04315          /* We have an expression.  Find the start and end, and determine
04316             if we are going to have to recursively call ourselves on the
04317             contents */
04318          vars = vare = nextexp + 2;
04319          brackets = 1;
04320          needsub = 0;
04321 
04322          /* Find the end of it */
04323          while (brackets && *vare) {
04324             if ((vare[0] == '$') && (vare[1] == '[')) {
04325                needsub++;
04326                brackets++;
04327                vare++;
04328             } else if (vare[0] == '[') {
04329                brackets++;
04330             } else if (vare[0] == ']') {
04331                brackets--;
04332             } else if ((vare[0] == '$') && (vare[1] == '{')) {
04333                needsub++;
04334                vare++;
04335             }
04336             vare++;
04337          }
04338          if (brackets)
04339             ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n");
04340          len = vare - vars - 1;
04341 
04342          /* Skip totally over expression */
04343          whereweare += (len + 3);
04344 
04345          if (!var)
04346             var = ast_alloca(VAR_BUF_SIZE);
04347 
04348          /* Store variable name (and truncate) */
04349          ast_copy_string(var, vars, len + 1);
04350 
04351          /* Substitute if necessary */
04352          if (needsub) {
04353             size_t used;
04354             if (!ltmp)
04355                ltmp = ast_alloca(VAR_BUF_SIZE);
04356 
04357             pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used);
04358             vars = ltmp;
04359          } else {
04360             vars = var;
04361          }
04362 
04363          length = ast_expr(vars, cp2, count, c);
04364 
04365          if (length) {
04366             ast_debug(1, "Expression result is '%s'\n", cp2);
04367             count -= length;
04368             cp2 += length;
04369             *cp2 = 0;
04370          }
04371       }
04372    }
04373    *used = cp2 - orig_cp2;
04374 }

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

Definition at line 4382 of file pbx.c.

References pbx_substitute_variables_helper_full().

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

04383 {
04384    size_t used;
04385    pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count, &used);
04386 }


Generated on 20 Aug 2013 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1