Wed Oct 28 13:33:15 2009

Asterisk developer's documentation


pbx.h File Reference

Core PBX routines and definitions. More...

#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 dependency graph for pbx.h:

Go to the source code of this file.

Data Structures

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

Defines

#define ast_custom_function_register(acf)   __ast_custom_function_register(acf, ast_module_info->self)
 Register a custom function.
#define AST_MAX_APP   32
#define AST_PBX_GOTO_FAILED   -3
#define AST_PBX_KEEP   0
#define AST_PBX_MAX_STACK   128
#define AST_PBX_REPLACE   1
#define PRIORITY_HINT   -1
#define STATUS_NO_CONTEXT   1
#define STATUS_NO_EXTENSION   2
#define STATUS_NO_LABEL   4
#define STATUS_NO_PRIORITY   3
#define STATUS_SUCCESS   5
#define AST_PBX_ERROR   1
#define AST_PBX_HANGUP   -1
 Special return values from applications to the PBX.
#define AST_PBX_INCOMPLETE   12
#define AST_PBX_OK   0

Typedefs

typedef 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.
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 callback, void *data)
 Registers a state change callback.
int ast_extension_state_del (int id, ast_state_cb_type callback)
 Deletes a registered state change callback by ID.
int ast_findlabel_extension (struct ast_channel *c, const char *context, const char *exten, const char *label, const char *callerid)
 Find the priority of an extension that has the specified label.
int ast_findlabel_extension2 (struct ast_channel *c, struct ast_context *con, const char *exten, const char *label, const char *callerid)
 Find the priority of an extension that has the specified label.
int ast_func_read (struct ast_channel *chan, const char *function, char *workspace, size_t len)
 executes a read operation on a function
int ast_func_read2 (struct ast_channel *chan, const char *function, struct ast_str **str, ssize_t maxlen)
 executes a read operation on a function
int ast_func_write (struct ast_channel *chan, const char *function, const char *value)
 executes a write operation on a function
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, int 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, int 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.
int ast_wrlock_contexts_version (void)
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.
void pbx_builtin_setvar_helper (struct ast_channel *chan, const char *name, const char *value)
 Add a variable to the channel variable stack, removing the most recently set value for the same name.
int pbx_builtin_setvar_multiple (struct ast_channel *chan, const char *data)
 Parse and set multiple channel variables, where the pairs are separated by the ',' character, and name and value are separated with an '=' character.
int pbx_checkcondition (const char *condition)
 Evaluate a condition.
int pbx_exec (struct ast_channel *c, struct ast_app *app, const char *data)
 Execute an application.
struct ast_extenpbx_find_extension (struct ast_channel *chan, struct ast_context *bypass, struct pbx_find_info *q, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action)
struct ast_apppbx_findapp (const char *app)
 Look up an application.
void pbx_retrieve_variable (struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp)
 Retrieve the value of a builtin variable or variable from the channel variable stack.
int pbx_set_autofallthrough (int newval)
int pbx_set_extenpatternmatchnew (int newval)
void pbx_set_overrideswitch (const char *newval)
int ast_context_remove_extension (const char *context, const char *extension, int priority, const char *registrar)
 Simply remove extension from context.
int ast_context_remove_extension2 (struct ast_context *con, const char *extension, int priority, const char *registrar, int already_locked)
 This functionc locks given context, search for the right extension and fires out all peer in this extensions with given priority. If priority is set to 0, all peers are removed. After that, unlock context and return.
int ast_context_remove_extension_callerid (const char *context, const char *extension, int priority, const char *callerid, int matchcid, const char *registrar)
int ast_context_remove_extension_callerid2 (struct ast_context *con, const char *extension, int priority, const char *callerid, int matchcid, const char *registrar, int already_locked)
Functions for returning values from structures

const char * ast_get_context_name (struct ast_context *con)
struct ast_contextast_get_extension_context (struct ast_exten *exten)
const char * ast_get_extension_name (struct ast_exten *exten)
const char * ast_get_ignorepat_name (struct ast_ignorepat *ip)
const char * ast_get_include_name (struct ast_include *include)
const char * ast_get_switch_data (struct ast_sw *sw)
int ast_get_switch_eval (struct ast_sw *sw)
const char * ast_get_switch_name (struct ast_sw *sw)
Registrar info functions ...


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


const char * ast_get_extension_app (struct ast_exten *e)
void * ast_get_extension_app_data (struct ast_exten *e)
const char * ast_get_extension_cidmatch (struct ast_exten *e)
const char * ast_get_extension_label (struct ast_exten *e)
int ast_get_extension_matchcid (struct ast_exten *e)
int ast_get_extension_priority (struct ast_exten *exten)
int ast_hashtab_compare_contexts (const void *ah_a, const void *ah_b)
 hashtable functions for contexts
unsigned int ast_hashtab_hash_contexts (const void *obj)
Substitution routines, using dynamic string buffers


const char * ast_str_retrieve_variable (struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, struct varshead *headp, const char *var)
void ast_str_substitute_variables (struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, const char *templ)
void ast_str_substitute_variables_full (struct ast_str **buf, ssize_t maxlen, struct ast_channel *c, struct varshead *headp, const char *templ, size_t *used)
void ast_str_substitute_variables_varshead (struct ast_str **buf, ssize_t maxlen, struct varshead *headp, const char *templ)
Walking functions ...


struct ast_extenast_walk_context_extensions (struct ast_context *con, struct ast_exten *priority)
struct ast_ignorepatast_walk_context_ignorepats (struct ast_context *con, struct ast_ignorepat *ip)
struct ast_includeast_walk_context_includes (struct ast_context *con, struct ast_include *inc)
struct ast_swast_walk_context_switches (struct ast_context *con, struct ast_sw *sw)
struct ast_contextast_walk_contexts (struct ast_context *con)
struct ast_extenast_walk_extension_priorities (struct ast_exten *exten, struct ast_exten *priority)
Substitution routines, using static string buffers
void pbx_substitute_variables_helper (struct ast_channel *c, const char *cp1, char *cp2, int count)
void pbx_substitute_variables_helper_full (struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int cp2_size, size_t *used)
void pbx_substitute_variables_varshead (struct varshead *headp, const char *cp1, char *cp2, int count)


Detailed Description

Core PBX routines and definitions.

Definition in file pbx.h.


Define Documentation

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

Register a custom function.

Definition at line 1108 of file pbx.h.

Referenced by load_module(), and reload().

#define AST_MAX_APP   32

Max length of an application

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

Referenced by __ast_pbx_run().

#define AST_PBX_GOTO_FAILED   -3

Definition at line 39 of file pbx.h.

Referenced by __ast_goto_if_exists(), and dial_exec_full().

#define AST_PBX_HANGUP   -1

Special return values from applications to the PBX.

Jump to the 'h' exten

Definition at line 45 of file pbx.h.

#define AST_PBX_INCOMPLETE   12

Return to PBX matching, allowing more digits for the extension

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

#define AST_PBX_MAX_STACK   128

Definition at line 1191 of file pbx.h.

#define AST_PBX_OK   0

No errors

Definition at line 46 of file pbx.h.

#define AST_PBX_REPLACE   1

Definition at line 41 of file pbx.h.

#define PRIORITY_HINT   -1

#define STATUS_NO_CONTEXT   1

Definition at line 1186 of file pbx.h.

#define STATUS_NO_EXTENSION   2

Definition at line 1187 of file pbx.h.

#define STATUS_NO_LABEL   4

Definition at line 1189 of file pbx.h.

#define STATUS_NO_PRIORITY   3

Definition at line 1188 of file pbx.h.

#define STATUS_SUCCESS   5

Definition at line 1190 of file pbx.h.


Typedef Documentation

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 77 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 109 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 58 of file pbx.h.

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

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

00276                     {
00277    AST_PBX_SUCCESS = 0,
00278    AST_PBX_FAILED = -1,
00279    AST_PBX_CALL_LIMIT = -2,
00280 };

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

01177                  {
01178    E_MATCHMORE =  0x00, /* extension can match but only with more 'digits' */
01179    E_CANMATCH =   0x01, /* extension can match with or without more 'digits' */
01180    E_MATCH =   0x02, /* extension is an exact match */
01181    E_MATCH_MASK = 0x03, /* mask for the argument to extension_match_core() */
01182    E_SPAWN =   0x12, /* want to spawn an extension. Requires exact match */
01183    E_FINDLABEL =  0x22  /* returns the priority for a given label. Requires exact match */
01184 };


Function Documentation

int __ast_custom_function_register ( struct ast_custom_function acf,
struct ast_module mod 
)

Register a custom function.

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

03359 {
03360    struct ast_custom_function *cur;
03361    char tmps[80];
03362 
03363    if (!acf) {
03364       return -1;
03365    }
03366 
03367    acf->mod = mod;
03368 #ifdef AST_XML_DOCS
03369    acf->docsrc = AST_STATIC_DOC;
03370 #endif
03371 
03372    if (acf_retrieve_docs(acf)) {
03373       return -1;
03374    }
03375 
03376    AST_RWLIST_WRLOCK(&acf_root);
03377 
03378    AST_RWLIST_TRAVERSE(&acf_root, cur, acflist) {
03379       if (!strcmp(acf->name, cur->name)) {
03380          ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name);
03381          AST_RWLIST_UNLOCK(&acf_root);
03382          return -1;
03383       }
03384    }
03385 
03386    /* Store in alphabetical order */
03387    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) {
03388       if (strcasecmp(acf->name, cur->name) < 0) {
03389          AST_RWLIST_INSERT_BEFORE_CURRENT(acf, acflist);
03390          break;
03391       }
03392    }
03393    AST_RWLIST_TRAVERSE_SAFE_END;
03394 
03395    if (!cur) {
03396       AST_RWLIST_INSERT_TAIL(&acf_root, acf, acflist);
03397    }
03398 
03399    AST_RWLIST_UNLOCK(&acf_root);
03400 
03401    ast_verb(2, "Registered custom function '%s'\n", term_color(tmps, acf->name, COLOR_BRCYAN, 0, sizeof(tmps)));
03402 
03403    return 0;
03404 }

int ast_active_calls ( void   ) 

Retrieve the number of active calls.

Definition at line 4934 of file pbx.c.

References countcalls.

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

04935 {
04936    return countcalls;
04937 }

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

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

Referenced by ast_extension_state_add(), handle_cli_dialplan_add_extension(), park_add_hints(), register_exten(), register_peer_exten(), and RegisterExtension().

07593 {
07594    int ret = -1;
07595    struct ast_context *c = find_context_locked(context);
07596 
07597    if (c) {
07598       ret = ast_add_extension2(c, replace, extension, priority, label, callerid,
07599          application, data, datad, registrar);
07600       ast_unlock_contexts();
07601    }
07602 
07603    return ret;
07604 }

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

References ast_add_extension2_lockopt().

Referenced by add_extensions(), ast_add_extension(), build_parkinglot(), context_merge(), load_config(), load_module(), manage_parkinglot(), park_call_full(), pbx_load_config(), pbx_load_users(), sla_build_station(), and sla_build_trunk().

07915 {
07916    return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid, application, data, datad, registrar, 1, 1);
07917 }

int ast_async_goto ( struct ast_channel chan,
const char *  context,
const char *  exten,
int  priority 
)

Set the channel to next execute the specified dialplan location.

See also:
ast_async_parseable_goto, ast_async_goto_if_exists

Definition at line 7629 of file pbx.c.

References ast_channel::_state, ast_channel::accountcode, ast_channel::amaflags, ast_cdr_discard(), ast_cdr_dup(), ast_channel_alloc, ast_channel_lock, ast_channel_masquerade(), ast_channel_unlock, ast_do_masquerade(), ast_explicit_goto(), ast_hangup(), ast_log(), ast_pbx_start(), AST_SOFTHANGUP_ASYNCGOTO, ast_softhangup_nolock(), ast_channel::cdr, ast_channel::context, ast_channel::exten, ast_channel::linkedid, LOG_WARNING, ast_channel::name, ast_channel::pbx, ast_channel::readformat, S_OR, and ast_channel::writeformat.

Referenced by __ast_goto_if_exists(), action_redirect(), ast_async_goto_by_name(), builtin_blindtransfer(), change_t38_state(), console_transfer(), dahdi_handle_dtmfup(), handle_request_bye(), handle_request_refer(), my_handle_dtmfup(), pbx_parseable_goto(), process_ast_dsp(), and socket_process().

07630 {
07631    int res = 0;
07632 
07633    ast_channel_lock(chan);
07634 
07635    if (chan->pbx) { /* This channel is currently in the PBX */
07636       ast_explicit_goto(chan, context, exten, priority + 1);
07637       ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO);
07638    } else {
07639       /* In order to do it when the channel doesn't really exist within
07640          the PBX, we have to make a new channel, masquerade, and start the PBX
07641          at the new location */
07642       struct ast_channel *tmpchan = ast_channel_alloc(0, chan->_state, 0, 0, chan->accountcode, chan->exten, chan->context, chan->linkedid, chan->amaflags, "AsyncGoto/%s", chan->name);
07643       if (!tmpchan) {
07644          res = -1;
07645       } else {
07646          if (chan->cdr) {
07647             ast_cdr_discard(tmpchan->cdr);
07648             tmpchan->cdr = ast_cdr_dup(chan->cdr);  /* share the love */
07649          }
07650          /* Make formats okay */
07651          tmpchan->readformat = chan->readformat;
07652          tmpchan->writeformat = chan->writeformat;
07653          /* Setup proper location */
07654          ast_explicit_goto(tmpchan,
07655             S_OR(context, chan->context), S_OR(exten, chan->exten), priority);
07656 
07657          /* Masquerade into temp channel */
07658          if (ast_channel_masquerade(tmpchan, chan)) {
07659             /* Failed to set up the masquerade.  It's probably chan_local
07660              * in the middle of optimizing itself out.  Sad. :( */
07661             ast_hangup(tmpchan);
07662             tmpchan = NULL;
07663             res = -1;
07664          } else {
07665             /* it may appear odd to unlock chan here since the masquerade is on
07666              * tmpchan, but no channel locks should be held when doing a masquerade
07667              * since a masquerade requires a lock on the channels ao2 container. */
07668             ast_channel_unlock(chan);
07669             ast_do_masquerade(tmpchan);
07670             ast_channel_lock(chan);
07671             /* Start the PBX going on our stolen channel */
07672             if (ast_pbx_start(tmpchan)) {
07673                ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name);
07674                ast_hangup(tmpchan);
07675                res = -1;
07676             }
07677          }
07678       }
07679    }
07680    ast_channel_unlock(chan);
07681    return res;
07682 }

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

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

07685 {
07686    struct ast_channel *chan;
07687    int res = -1;
07688 
07689    if ((chan = ast_channel_get_by_name(channame))) {
07690       res = ast_async_goto(chan, context, exten, priority);
07691       chan = ast_channel_unref(chan);
07692    }
07693 
07694    return res;
07695 }

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

References __ast_goto_if_exists().

09848 {
09849    return __ast_goto_if_exists(chan, context, exten, priority, 1);
09850 }

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

References pbx_parseable_goto().

Referenced by asyncgoto_exec(), and handle_redirect().

09911 {
09912    return pbx_parseable_goto(chan, goto_string, 1);
09913 }

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

References ast_strdup, ast_strdupa, ast_strlen_zero(), ast_timing::daymask, days, ast_timing::dowmask, get_range(), get_timerange(), ast_timing::monthmask, months, strsep(), and ast_timing::timezone.

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

07225 {
07226    char *info_save, *info;
07227    int j, num_fields, last_sep = -1;
07228 
07229    /* Check for empty just in case */
07230    if (ast_strlen_zero(info_in)) {
07231       return 0;
07232    }
07233 
07234    /* make a copy just in case we were passed a static string */
07235    info_save = info = ast_strdupa(info_in);
07236 
07237    /* count the number of fields in the timespec */
07238    for (j = 0, num_fields = 1; info[j] != '\0'; j++) {
07239       if (info[j] == ',') {
07240          last_sep = j;
07241          num_fields++;
07242       }
07243    }
07244 
07245    /* save the timezone, if it is specified */
07246    if (num_fields == 5) {
07247       i->timezone = ast_strdup(info + last_sep + 1);
07248    } else {
07249       i->timezone = NULL;
07250    }
07251 
07252    /* Assume everything except time */
07253    i->monthmask = 0xfff;   /* 12 bits */
07254    i->daymask = 0x7fffffffU; /* 31 bits */
07255    i->dowmask = 0x7f; /* 7 bits */
07256    /* on each call, use strsep() to move info to the next argument */
07257    get_timerange(i, strsep(&info, "|,"));
07258    if (info)
07259       i->dowmask = get_range(strsep(&info, "|,"), 7, days, "day of week");
07260    if (info)
07261       i->daymask = get_range(strsep(&info, "|,"), 31, NULL, "day");
07262    if (info)
07263       i->monthmask = get_range(strsep(&info, "|,"), 12, months, "month");
07264    return 1;
07265 }

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

References E_CANMATCH, and pbx_extension_helper().

Referenced by __analog_ss_thread(), analog_ss_thread(), background_detect_exec(), cb_events(), do_immediate_setup(), dp_lookup(), dundi_lookup_local(), get_also_info(), get_destination(), handle_link_data(), handle_link_phone_dtmf(), leave_voicemail(), local_dtmf_helper(), loopback_canmatch(), mgcp_ss(), phone_check_exception(), skinny_ss(), and valid_exit().

04496 {
04497    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0);
04498 }

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

References ast_localtime(), ast_log(), ast_tvnow(), 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 iftime(), include_valid(), pbx_builtin_execiftime(), and pbx_builtin_gotoiftime().

07268 {
07269    struct ast_tm tm;
07270    struct timeval now = ast_tvnow();
07271 
07272    ast_localtime(&now, &tm, i->timezone);
07273 
07274    /* If it's not the right month, return */
07275    if (!(i->monthmask & (1 << tm.tm_mon)))
07276       return 0;
07277 
07278    /* If it's not that time of the month.... */
07279    /* Warning, tm_mday has range 1..31! */
07280    if (!(i->daymask & (1 << (tm.tm_mday-1))))
07281       return 0;
07282 
07283    /* If it's not the right day of the week */
07284    if (!(i->dowmask & (1 << tm.tm_wday)))
07285       return 0;
07286 
07287    /* Sanity check the hour just to be safe */
07288    if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) {
07289       ast_log(LOG_WARNING, "Insane time...\n");
07290       return 0;
07291    }
07292 
07293    /* Now the tough part, we calculate if it fits
07294       in the right time based on min/hour */
07295    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))))
07296       return 0;
07297 
07298    /* If we got this far, then we're good */
07299    return 1;
07300 }

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

09916 {
09917    struct ast_app *app = NULL;
09918    int which = 0;
09919    char *ret = NULL;
09920    size_t wordlen = strlen(word);
09921 
09922    AST_RWLIST_RDLOCK(&apps);
09923    AST_RWLIST_TRAVERSE(&apps, app, list) {
09924       if (!strncasecmp(word, app->name, wordlen) && ++which > state) {
09925          ret = ast_strdup(app->name);
09926          break;
09927       }
09928    }
09929    AST_RWLIST_UNLOCK(&apps);
09930 
09931    return ret;
09932 }

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

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

Referenced by handle_cli_dialplan_add_ignorepat().

07503 {
07504    int ret = -1;
07505    struct ast_context *c = find_context_locked(context);
07506 
07507    if (c) {
07508       ret = ast_context_add_ignorepat2(c, value, registrar);
07509       ast_unlock_contexts();
07510    }
07511    return ret;
07512 }

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

Definition at line 7514 of file pbx.c.

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

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

07515 {
07516    struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL;
07517    int length;
07518    char *pattern;
07519    length = sizeof(struct ast_ignorepat);
07520    length += strlen(value) + 1;
07521    if (!(ignorepat = ast_calloc(1, length)))
07522       return -1;
07523    /* The cast to char * is because we need to write the initial value.
07524     * The field is not supposed to be modified otherwise.  Also, gcc 4.2
07525     * sees the cast as dereferencing a type-punned pointer and warns about
07526     * it.  This is the workaround (we're telling gcc, yes, that's really
07527     * what we wanted to do).
07528     */
07529    pattern = (char *) ignorepat->pattern;
07530    strcpy(pattern, value);
07531    ignorepat->next = NULL;
07532    ignorepat->registrar = registrar;
07533    ast_wrlock_context(con);
07534    for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) {
07535       ignorepatl = ignorepatc;
07536       if (!strcasecmp(ignorepatc->pattern, value)) {
07537          /* Already there */
07538          ast_unlock_context(con);
07539          errno = EEXIST;
07540          return -1;
07541       }
07542    }
07543    if (ignorepatl)
07544       ignorepatl->next = ignorepat;
07545    else
07546       con->ignorepats = ignorepat;
07547    ast_unlock_context(con);
07548    return 0;
07549 
07550 }

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

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

Referenced by handle_cli_dialplan_add_include().

07054 {
07055    int ret = -1;
07056    struct ast_context *c = find_context_locked(context);
07057 
07058    if (c) {
07059       ret = ast_context_add_include2(c, include, registrar);
07060       ast_unlock_contexts();
07061    }
07062    return ret;
07063 }

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

07319 {
07320    struct ast_include *new_include;
07321    char *c;
07322    struct ast_include *i, *il = NULL; /* include, include_last */
07323    int length;
07324    char *p;
07325 
07326    length = sizeof(struct ast_include);
07327    length += 2 * (strlen(value) + 1);
07328 
07329    /* allocate new include structure ... */
07330    if (!(new_include = ast_calloc(1, length)))
07331       return -1;
07332    /* Fill in this structure. Use 'p' for assignments, as the fields
07333     * in the structure are 'const char *'
07334     */
07335    p = new_include->stuff;
07336    new_include->name = p;
07337    strcpy(p, value);
07338    p += strlen(value) + 1;
07339    new_include->rname = p;
07340    strcpy(p, value);
07341    /* Strip off timing info, and process if it is there */
07342    if ( (c = strchr(p, ',')) ) {
07343       *c++ = '\0';
07344       new_include->hastime = ast_build_timing(&(new_include->timing), c);
07345    }
07346    new_include->next      = NULL;
07347    new_include->registrar = registrar;
07348 
07349    ast_wrlock_context(con);
07350 
07351    /* ... go to last include and check if context is already included too... */
07352    for (i = con->includes; i; i = i->next) {
07353       if (!strcasecmp(i->name, new_include->name)) {
07354          ast_destroy_timing(&(new_include->timing));
07355          ast_free(new_include);
07356          ast_unlock_context(con);
07357          errno = EEXIST;
07358          return -1;
07359       }
07360       il = i;
07361    }
07362 
07363    /* ... include new context into context list, unlock, return */
07364    if (il)
07365       il->next = new_include;
07366    else
07367       con->includes = new_include;
07368    ast_verb(3, "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con));
07369 
07370    ast_unlock_context(con);
07371 
07372    return 0;
07373 }

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

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

07381 {
07382    int ret = -1;
07383    struct ast_context *c = find_context_locked(context);
07384 
07385    if (c) { /* found, add switch to this context */
07386       ret = ast_context_add_switch2(c, sw, data, eval, registrar);
07387       ast_unlock_contexts();
07388    }
07389    return ret;
07390 }

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

07401 {
07402    struct ast_sw *new_sw;
07403    struct ast_sw *i;
07404    int length;
07405    char *p;
07406 
07407    length = sizeof(struct ast_sw);
07408    length += strlen(value) + 1;
07409    if (data)
07410       length += strlen(data);
07411    length++;
07412 
07413    /* allocate new sw structure ... */
07414    if (!(new_sw = ast_calloc(1, length)))
07415       return -1;
07416    /* ... fill in this structure ... */
07417    p = new_sw->stuff;
07418    new_sw->name = p;
07419    strcpy(new_sw->name, value);
07420    p += strlen(value) + 1;
07421    new_sw->data = p;
07422    if (data) {
07423       strcpy(new_sw->data, data);
07424       p += strlen(data) + 1;
07425    } else {
07426       strcpy(new_sw->data, "");
07427       p++;
07428    }
07429    new_sw->eval     = eval;
07430    new_sw->registrar = registrar;
07431 
07432    /* ... try to lock this context ... */
07433    ast_wrlock_context(con);
07434 
07435    /* ... go to last sw and check if context is already swd too... */
07436    AST_LIST_TRAVERSE(&con->alts, i, list) {
07437       if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) {
07438          ast_free(new_sw);
07439          ast_unlock_context(con);
07440          errno = EEXIST;
07441          return -1;
07442       }
07443    }
07444 
07445    /* ... sw new context into context list, unlock, return */
07446    AST_LIST_INSERT_TAIL(&con->alts, new_sw, list);
07447 
07448    ast_verb(3, "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con));
07449 
07450    ast_unlock_context(con);
07451 
07452    return 0;
07453 }

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

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

Referenced by __unload_module(), cleanup_stale_contexts(), parkinglot_destroy(), sla_destroy(), and unload_module().

struct ast_context* ast_context_find ( const char *  name  )  [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 2454 of file pbx.c.

References ast_copy_string(), ast_hashtab_lookup(), ast_rdlock_contexts(), ast_unlock_contexts(), ast_walk_contexts(), contexts_table, ast_context::name, and fake_context::name.

Referenced by __unload_module(), _macro_exec(), ast_context_verify_includes(), ast_ignore_pattern(), cleanup_stale_contexts(), isexten_function_read(), load_config(), manage_parkinglot(), park_exec_full(), parkinglot_destroy(), register_exten(), register_peer_exten(), unload_module(), and unregister_exten().

02455 {
02456    struct ast_context *tmp = NULL;
02457    struct fake_context item;
02458 
02459    ast_copy_string(item.name, name, sizeof(item.name));
02460 
02461    ast_rdlock_contexts();
02462    if( contexts_table ) {
02463       tmp = ast_hashtab_lookup(contexts_table,&item);
02464    } else {
02465       while ( (tmp = ast_walk_contexts(tmp)) ) {
02466          if (!name || !strcasecmp(name, tmp->name)) {
02467             break;
02468          }
02469       }
02470    }
02471    ast_unlock_contexts();
02472    return tmp;
02473 }

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 6710 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(), build_parkinglot(), config_parse_variables(), context_merge(), load_config(), load_module(), lua_register_switches(), manage_parkinglot(), park_call_full(), pbx_load_config(), pbx_load_users(), reload_config(), set_config(), sla_build_station(), and sla_build_trunk().

06711 {
06712    struct ast_context *tmp, **local_contexts;
06713    struct fake_context search;
06714    int length = sizeof(struct ast_context) + strlen(name) + 1;
06715 
06716    if (!contexts_table) {
06717       contexts_table = ast_hashtab_create(17,
06718                                  ast_hashtab_compare_contexts,
06719                                  ast_hashtab_resize_java,
06720                                  ast_hashtab_newsize_java,
06721                                  ast_hashtab_hash_contexts,
06722                                  0);
06723    }
06724 
06725    ast_copy_string(search.name, name, sizeof(search.name));
06726    if (!extcontexts) {
06727       ast_rdlock_contexts();
06728       local_contexts = &contexts;
06729       tmp = ast_hashtab_lookup(contexts_table, &search);
06730       ast_unlock_contexts();
06731       if (tmp) {
06732          tmp->refcount++;
06733          return tmp;
06734       }
06735    } else { /* local contexts just in a linked list; search there for the new context; slow, linear search, but not frequent */
06736       local_contexts = extcontexts;
06737       tmp = ast_hashtab_lookup(exttable, &search);
06738       if (tmp) {
06739          tmp->refcount++;
06740          return tmp;
06741       }
06742    }
06743 
06744    if ((tmp = ast_calloc(1, length))) {
06745       ast_rwlock_init(&tmp->lock);
06746       ast_mutex_init(&tmp->macrolock);
06747       strcpy(tmp->name, name);
06748       tmp->root = NULL;
06749       tmp->root_table = NULL;
06750       tmp->registrar = ast_strdup(registrar);
06751       tmp->includes = NULL;
06752       tmp->ignorepats = NULL;
06753       tmp->refcount = 1;
06754    } else {
06755       ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name);
06756       return NULL;
06757    }
06758 
06759    if (!extcontexts) {
06760       ast_wrlock_contexts();
06761       tmp->next = *local_contexts;
06762       *local_contexts = tmp;
06763       ast_hashtab_insert_safe(contexts_table, tmp); /*put this context into the tree */
06764       ast_unlock_contexts();
06765       ast_debug(1, "Registered context '%s'(%p) in table %p registrar: %s\n", tmp->name, tmp, contexts_table, registrar);
06766       ast_verb(3, "Registered extension context '%s' (%p) in table %p; registrar: %s\n", tmp->name, tmp, contexts_table, registrar);
06767    } else {
06768       tmp->next = *local_contexts;
06769       if (exttable)
06770          ast_hashtab_insert_immediate(exttable, tmp); /*put this context into the tree */
06771 
06772       *local_contexts = tmp;
06773       ast_debug(1, "Registered context '%s'(%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar);
06774       ast_verb(3, "Registered extension context '%s' (%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar);
06775    }
06776    return tmp;
06777 }

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

References ast_copy_string(), ast_hashtab_lookup(), ast_mutex_lock(), ast_rdlock_contexts(), ast_unlock_contexts(), contexts_table, ast_context::macrolock, and fake_context::name.

Referenced by _macro_exec().

05315 {
05316    struct ast_context *c = NULL;
05317    int ret = -1;
05318    struct fake_context item;
05319 
05320    ast_rdlock_contexts();
05321 
05322    ast_copy_string(item.name, context, sizeof(item.name));
05323 
05324    c = ast_hashtab_lookup(contexts_table,&item);
05325    if (c)
05326       ret = 0;
05327    ast_unlock_contexts();
05328 
05329    /* if we found context, lock macrolock */
05330    if (ret == 0) {
05331       ret = ast_mutex_lock(&c->macrolock);
05332    }
05333 
05334    return ret;
05335 }

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)
callerid NULL to remove all; non-NULL to match a single record per priority
matchcid non-zero to match callerid element (if non-NULL); 0 to match default case
registrar registrar of the extension
This function removes an extension from a given context.

Return values:
0 on success
-1 on failure

Definition at line 5122 of file pbx.c.

References ast_context_remove_extension_callerid().

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

05123 {
05124    return ast_context_remove_extension_callerid(context, extension, priority, NULL, 0, registrar);
05125 }

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

References ast_context_remove_extension_callerid2().

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

05150 {
05151    return ast_context_remove_extension_callerid2(con, extension, priority, NULL, 0, registrar, already_locked);
05152 }

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

05128 {
05129    int ret = -1; /* default error return */
05130    struct ast_context *c = find_context_locked(context);
05131 
05132    if (c) { /* ... remove extension ... */
05133       ret = ast_context_remove_extension_callerid2(c, extension, priority, callerid, matchcallerid, registrar, 1);
05134       ast_unlock_contexts();
05135    }
05136    return ret;
05137 }

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

05155 {
05156    struct ast_exten *exten, *prev_exten = NULL;
05157    struct ast_exten *peer;
05158    struct ast_exten ex, *exten2, *exten3;
05159    char dummy_name[1024];
05160    struct ast_exten *previous_peer = NULL;
05161    struct ast_exten *next_peer = NULL;
05162    int found = 0;
05163 
05164    if (!already_locked)
05165       ast_wrlock_context(con);
05166 
05167    /* Handle this is in the new world */
05168 
05169    /* FIXME For backwards compatibility, if callerid==NULL, then remove ALL
05170     * peers, not just those matching the callerid. */
05171 #ifdef NEED_DEBUG
05172    ast_verb(3,"Removing %s/%s/%d%s%s from trees, registrar=%s\n", con->name, extension, priority, matchcallerid ? "/" : "", matchcallerid ? callerid : "", registrar);
05173 #endif
05174 #ifdef CONTEXT_DEBUG
05175    check_contexts(__FILE__, __LINE__);
05176 #endif
05177    /* find this particular extension */
05178    ex.exten = dummy_name;
05179    ex.matchcid = matchcallerid && !ast_strlen_zero(callerid); /* don't say match if there's no callerid */
05180    ex.cidmatch = callerid;
05181    ast_copy_string(dummy_name, extension, sizeof(dummy_name));
05182    exten = ast_hashtab_lookup(con->root_table, &ex);
05183    if (exten) {
05184       if (priority == 0) {
05185          exten2 = ast_hashtab_remove_this_object(con->root_table, exten);
05186          if (!exten2)
05187             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);
05188          if (con->pattern_tree) {
05189             struct match_char *x = add_exten_to_pattern_tree(con, exten, 1);
05190 
05191             if (x->exten) { /* this test for safety purposes */
05192                x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */
05193                x->exten = 0; /* get rid of what will become a bad pointer */
05194             } else {
05195                ast_log(LOG_WARNING,"Trying to delete an exten from a context, but the pattern tree node returned isn't a full extension\n");
05196             }
05197          }
05198       } else {
05199          ex.priority = priority;
05200          exten2 = ast_hashtab_lookup(exten->peer_table, &ex);
05201          if (exten2) {
05202 
05203             if (exten2->label) { /* if this exten has a label, remove that, too */
05204                exten3 = ast_hashtab_remove_this_object(exten->peer_label_table,exten2);
05205                if (!exten3)
05206                   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);
05207             }
05208 
05209             exten3 = ast_hashtab_remove_this_object(exten->peer_table, exten2);
05210             if (!exten3)
05211                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);
05212             if (exten2 == exten && exten2->peer) {
05213                exten2 = ast_hashtab_remove_this_object(con->root_table, exten);
05214                ast_hashtab_insert_immediate(con->root_table, exten2->peer);
05215             }
05216             if (ast_hashtab_size(exten->peer_table) == 0) {
05217                /* well, if the last priority of an exten is to be removed,
05218                   then, the extension is removed, too! */
05219                exten3 = ast_hashtab_remove_this_object(con->root_table, exten);
05220                if (!exten3)
05221                   ast_log(LOG_ERROR,"Did not remove this exten (%s) from the context root_table (%s) (priority %d)\n", exten->exten, con->name, priority);
05222                if (con->pattern_tree) {
05223                   struct match_char *x = add_exten_to_pattern_tree(con, exten, 1);
05224                   if (x->exten) { /* this test for safety purposes */
05225                      x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */
05226                      x->exten = 0; /* get rid of what will become a bad pointer */
05227                   }
05228                }
05229             }
05230          } else {
05231             ast_log(LOG_ERROR,"Could not find priority %d of exten %s in context %s!\n",
05232                   priority, exten->exten, con->name);
05233          }
05234       }
05235    } else {
05236       /* hmmm? this exten is not in this pattern tree? */
05237       ast_log(LOG_WARNING,"Cannot find extension %s in root_table in context %s\n",
05238             extension, con->name);
05239    }
05240 #ifdef NEED_DEBUG
05241    if (con->pattern_tree) {
05242       ast_log(LOG_NOTICE,"match char tree after exten removal:\n");
05243       log_match_char_tree(con->pattern_tree, " ");
05244    }
05245 #endif
05246 
05247    /* scan the extension list to find first matching extension-registrar */
05248    for (exten = con->root; exten; prev_exten = exten, exten = exten->next) {
05249       if (!strcmp(exten->exten, extension) &&
05250          (!registrar || !strcmp(exten->registrar, registrar)) &&
05251          (!matchcallerid || (!ast_strlen_zero(callerid) && !ast_strlen_zero(exten->cidmatch) && !strcmp(exten->cidmatch, callerid)) || (ast_strlen_zero(callerid) && ast_strlen_zero(exten->cidmatch))))
05252          break;
05253    }
05254    if (!exten) {
05255       /* we can't find right extension */
05256       if (!already_locked)
05257          ast_unlock_context(con);
05258       return -1;
05259    }
05260 
05261    /* scan the priority list to remove extension with exten->priority == priority */
05262    for (peer = exten, next_peer = exten->peer ? exten->peer : exten->next;
05263        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)));
05264          peer = next_peer, next_peer = next_peer ? (next_peer->peer ? next_peer->peer : next_peer->next) : NULL) {
05265       if ((priority == 0 || peer->priority == priority) &&
05266             (!callerid || !matchcallerid || (matchcallerid && !strcmp(peer->cidmatch, callerid))) &&
05267             (!registrar || !strcmp(peer->registrar, registrar) )) {
05268          found = 1;
05269 
05270          /* we are first priority extension? */
05271          if (!previous_peer) {
05272             /*
05273              * We are first in the priority chain, so must update the extension chain.
05274              * The next node is either the next priority or the next extension
05275              */
05276             struct ast_exten *next_node = peer->peer ? peer->peer : peer->next;
05277             if (peer->peer) {
05278                /* move the peer_table and peer_label_table down to the next peer, if
05279                   it is there */
05280                peer->peer->peer_table = peer->peer_table;
05281                peer->peer->peer_label_table = peer->peer_label_table;
05282                peer->peer_table = NULL;
05283                peer->peer_label_table = NULL;
05284             }
05285             if (!prev_exten) {   /* change the root... */
05286                con->root = next_node;
05287             } else {
05288                prev_exten->next = next_node; /* unlink */
05289             }
05290             if (peer->peer)   { /* update the new head of the pri list */
05291                peer->peer->next = peer->next;
05292             }
05293          } else { /* easy, we are not first priority in extension */
05294             previous_peer->peer = peer->peer;
05295          }
05296 
05297          /* now, free whole priority extension */
05298          destroy_exten(peer);
05299       } else {
05300          previous_peer = peer;
05301       }
05302    }
05303    if (!already_locked)
05304       ast_unlock_context(con);
05305    return found ? 0 : -1;
05306 }

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

Definition at line 7459 of file pbx.c.

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

Referenced by handle_cli_dialplan_remove_ignorepat().

07460 {
07461    int ret = -1;
07462    struct ast_context *c = find_context_locked(context);
07463 
07464    if (c) {
07465       ret = ast_context_remove_ignorepat2(c, ignorepat, registrar);
07466       ast_unlock_contexts();
07467    }
07468    return ret;
07469 }

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

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

07472 {
07473    struct ast_ignorepat *ip, *ipl = NULL;
07474 
07475    ast_wrlock_context(con);
07476 
07477    for (ip = con->ignorepats; ip; ip = ip->next) {
07478       if (!strcmp(ip->pattern, ignorepat) &&
07479          (!registrar || (registrar == ip->registrar))) {
07480          if (ipl) {
07481             ipl->next = ip->next;
07482             ast_free(ip);
07483          } else {
07484             con->ignorepats = ip->next;
07485             ast_free(ip);
07486          }
07487          ast_unlock_context(con);
07488          return 0;
07489       }
07490       ipl = ip;
07491    }
07492 
07493    ast_unlock_context(con);
07494    errno = EINVAL;
07495    return -1;
07496 }

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

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

Referenced by handle_cli_dialplan_remove_include().

05014 {
05015    int ret = -1;
05016    struct ast_context *c = find_context_locked(context);
05017 
05018    if (c) {
05019       /* found, remove include from this context ... */
05020       ret = ast_context_remove_include2(c, include, registrar);
05021       ast_unlock_contexts();
05022    }
05023    return ret;
05024 }

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

05036 {
05037    struct ast_include *i, *pi = NULL;
05038    int ret = -1;
05039 
05040    ast_wrlock_context(con);
05041 
05042    /* find our include */
05043    for (i = con->includes; i; pi = i, i = i->next) {
05044       if (!strcmp(i->name, include) &&
05045             (!registrar || !strcmp(i->registrar, registrar))) {
05046          /* remove from list */
05047          ast_verb(3, "Removing inclusion of context '%s' in context '%s; registrar=%s'\n", include, ast_get_context_name(con), registrar);
05048          if (pi)
05049             pi->next = i->next;
05050          else
05051             con->includes = i->next;
05052          /* free include and return */
05053          ast_destroy_timing(&(i->timing));
05054          ast_free(i);
05055          ret = 0;
05056          break;
05057       }
05058    }
05059 
05060    ast_unlock_context(con);
05061 
05062    return ret;
05063 }

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

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

05071 {
05072    int ret = -1; /* default error return */
05073    struct ast_context *c = find_context_locked(context);
05074 
05075    if (c) {
05076       /* remove switch from this context ... */
05077       ret = ast_context_remove_switch2(c, sw, data, registrar);
05078       ast_unlock_contexts();
05079    }
05080    return ret;
05081 }

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

05092 {
05093    struct ast_sw *i;
05094    int ret = -1;
05095 
05096    ast_wrlock_context(con);
05097 
05098    /* walk switches */
05099    AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) {
05100       if (!strcmp(i->name, sw) && !strcmp(i->data, data) &&
05101          (!registrar || !strcmp(i->registrar, registrar))) {
05102          /* found, remove from list */
05103          ast_verb(3, "Removing switch '%s' from context '%s; registrar=%s'\n", sw, ast_get_context_name(con), registrar);
05104          AST_LIST_REMOVE_CURRENT(list);
05105          ast_free(i); /* free switch and return */
05106          ret = 0;
05107          break;
05108       }
05109    }
05110    AST_LIST_TRAVERSE_SAFE_END;
05111 
05112    ast_unlock_context(con);
05113 
05114    return ret;
05115 }

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

References ast_copy_string(), ast_hashtab_lookup(), ast_mutex_unlock(), ast_rdlock_contexts(), ast_unlock_contexts(), contexts_table, ast_context::macrolock, and fake_context::name.

Referenced by _macro_exec().

05343 {
05344    struct ast_context *c = NULL;
05345    int ret = -1;
05346    struct fake_context item;
05347 
05348    ast_rdlock_contexts();
05349 
05350    ast_copy_string(item.name, context, sizeof(item.name));
05351 
05352    c = ast_hashtab_lookup(contexts_table,&item);
05353    if (c)
05354       ret = 0;
05355    ast_unlock_contexts();
05356 
05357    /* if we found context, unlock macrolock */
05358    if (ret == 0) {
05359       ret = ast_mutex_unlock(&c->macrolock);
05360    }
05361 
05362    return ret;
05363 }

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

09804 {
09805    struct ast_include *inc = NULL;
09806    int res = 0;
09807 
09808    while ( (inc = ast_walk_context_includes(con, inc)) ) {
09809       if (ast_context_find(inc->rname))
09810          continue;
09811 
09812       res = -1;
09813       ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n",
09814          ast_get_context_name(con), inc->rname);
09815       break;
09816    }
09817 
09818    return res;
09819 }

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 3283 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 load_module(), reload(), and unload_module().

03284 {
03285    struct ast_custom_function *cur;
03286 
03287    if (!acf) {
03288       return -1;
03289    }
03290 
03291    AST_RWLIST_WRLOCK(&acf_root);
03292    if ((cur = AST_RWLIST_REMOVE(&acf_root, acf, acflist))) {
03293 #ifdef AST_XML_DOCS
03294       if (cur->docsrc == AST_XML_DOC) {
03295          ast_string_field_free_memory(acf);
03296       }
03297 #endif
03298       ast_verb(2, "Unregistered custom function %s\n", cur->name);
03299    }
03300    AST_RWLIST_UNLOCK(&acf_root);
03301 
03302    return cur ? 0 : -1;
03303 }

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

07303 {
07304    if (i->timezone) {
07305       ast_free(i->timezone);
07306       i->timezone = NULL;
07307    }
07308    return 0;
07309 }

enum ast_extension_states ast_devstate_to_extenstate ( enum ast_device_state  devstate  ) 

Map devstate to an extension state.

Parameters:
[in] device state
Returns:
the extension state mapping.

Definition at line 4086 of file pbx.c.

References AST_DEVICE_BUSY, AST_DEVICE_INUSE, AST_DEVICE_INVALID, AST_DEVICE_NOT_INUSE, AST_DEVICE_ONHOLD, AST_DEVICE_RINGING, AST_DEVICE_RINGINUSE, AST_DEVICE_TOTAL, AST_DEVICE_UNAVAILABLE, AST_DEVICE_UNKNOWN, AST_EXTENSION_BUSY, AST_EXTENSION_INUSE, AST_EXTENSION_NOT_INUSE, AST_EXTENSION_ONHOLD, AST_EXTENSION_RINGING, and AST_EXTENSION_UNAVAILABLE.

Referenced by ast_extension_state2().

04087 {
04088    switch (devstate) {
04089    case AST_DEVICE_ONHOLD:
04090       return AST_EXTENSION_ONHOLD;
04091    case AST_DEVICE_BUSY:
04092       return AST_EXTENSION_BUSY;
04093    case AST_DEVICE_UNAVAILABLE:
04094    case AST_DEVICE_UNKNOWN:
04095    case AST_DEVICE_INVALID:
04096       return AST_EXTENSION_UNAVAILABLE;
04097    case AST_DEVICE_RINGINUSE:
04098       return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING);
04099    case AST_DEVICE_RINGING:
04100       return AST_EXTENSION_RINGING;
04101    case AST_DEVICE_INUSE:
04102       return AST_EXTENSION_INUSE;
04103    case AST_DEVICE_NOT_INUSE:
04104       return AST_EXTENSION_NOT_INUSE;
04105    case AST_DEVICE_TOTAL: /* not a device state, included for completeness */
04106       break;
04107    }
04108 
04109    return AST_EXTENSION_NOT_INUSE;
04110 }

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 4480 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(), builtin_atxfer(), builtin_blindtransfer(), cb_events(), change_t38_state(), cli_console_dial(), conf_run(), console_dial(), console_transfer(), dahdi_handle_dtmfup(), dial_exec_full(), disa_exec(), dp_lookup(), dundi_lookup_local(), get_also_info(), get_destination(), get_refer_info(), gosub_exec(), handle_gosub(), handle_link_data(), handle_link_phone_dtmf(), handle_stimulus_message(), isexten_function_read(), leave_voicemail(), local_alloc(), local_call(), local_devicestate(), local_dtmf_helper(), loopback_exists(), metermaidstate(), mgcp_ss(), minivm_greet_exec(), misdn_overlap_dial_task(), my_handle_dtmfup(), park_space_reserve(), parkandannounce_exec(), pbx_builtin_waitexten(), phone_check_exception(), privacy_exec(), process_ast_dsp(), readexten_exec(), register_peer_exten(), rpt_exec(), show_debug_helper(), skinny_ss(), socket_process(), and waitstream_core().

04481 {
04482    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0);
04483 }

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

07607 {
07608    if (!chan)
07609       return -1;
07610 
07611    ast_channel_lock(chan);
07612 
07613    if (!ast_strlen_zero(context))
07614       ast_copy_string(chan->context, context, sizeof(chan->context));
07615    if (!ast_strlen_zero(exten))
07616       ast_copy_string(chan->exten, exten, sizeof(chan->exten));
07617    if (priority > -1) {
07618       chan->priority = priority;
07619       /* see flag description in channel.h for explanation */
07620       if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP))
07621          chan->priority--;
07622    }
07623 
07624    ast_channel_unlock(chan);
07625 
07626    return 0;
07627 }

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

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

02432 {
02433    if (needmore != E_MATCHMORE && needmore != E_CANMATCH)
02434       ast_log(LOG_WARNING, "invalid argument %d\n", needmore);
02435    return extension_match_core(pattern, data, needmore);
02436 }

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

References ext_cmp().

Referenced by lua_extension_cmp().

02234 {
02235    return ext_cmp(a, b);
02236 }

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

02427 {
02428    return extension_match_core(pattern, data, E_MATCH);
02429 }

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

References ast_extension_state2(), and ast_hint_extension().

Referenced by action_extensionstate(), extstate_read(), and handle_request_subscribe().

04149 {
04150    struct ast_exten *e;
04151 
04152    if (!(e = ast_hint_extension(c, context, exten))) {  /* Do we have a hint for this extension ? */
04153       return -1;                   /* No hint, return -1 */
04154    }
04155 
04156    return ast_extension_state2(e);  /* Check all devices in the hint */
04157 }

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

04137 {
04138    int i;
04139 
04140    for (i = 0; (i < ARRAY_LEN(extension_states)); i++) {
04141       if (extension_states[i].extension_state == extension_state)
04142          return extension_states[i].text;
04143    }
04144    return "Unknown";
04145 }

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

Registers a state change callback.

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

Return values:
-1 on failure
ID on success

Definition at line 4212 of file pbx.c.

References ast_exten::app, ast_add_extension(), ast_calloc, ast_free_ptr, ast_hint_extension(), AST_LIST_INSERT_HEAD, AST_LIST_TRAVERSE, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_strdup, ast_state_cb::callback, ast_hint::callbacks, ast_exten::cidmatch, ast_exten::data, ast_state_cb::data, ast_hint::exten, ast_exten::exten, ast_state_cb::id, ast_exten::label, ast_context::name, ast_exten::parent, ast_exten::priority, ast_exten::registrar, and stateid.

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

04214 {
04215    struct ast_hint *hint;
04216    struct ast_state_cb *cblist;
04217    struct ast_exten *e;
04218 
04219    /* If there's no context and extension:  add callback to statecbs list */
04220    if (!context && !exten) {
04221       AST_RWLIST_WRLOCK(&hints);
04222 
04223       AST_LIST_TRAVERSE(&statecbs, cblist, entry) {
04224          if (cblist->callback == callback) {
04225             cblist->data = data;
04226             AST_RWLIST_UNLOCK(&hints);
04227             return 0;
04228          }
04229       }
04230 
04231       /* Now insert the callback */
04232       if (!(cblist = ast_calloc(1, sizeof(*cblist)))) {
04233          AST_RWLIST_UNLOCK(&hints);
04234          return -1;
04235       }
04236       cblist->id = 0;
04237       cblist->callback = callback;
04238       cblist->data = data;
04239 
04240       AST_LIST_INSERT_HEAD(&statecbs, cblist, entry);
04241 
04242       AST_RWLIST_UNLOCK(&hints);
04243 
04244       return 0;
04245    }
04246 
04247    if (!context || !exten)
04248       return -1;
04249 
04250    /* This callback type is for only one hint, so get the hint */
04251    e = ast_hint_extension(NULL, context, exten);
04252    if (!e) {
04253       return -1;
04254    }
04255 
04256    /* If this is a pattern, dynamically create a new extension for this
04257     * particular match.  Note that this will only happen once for each
04258     * individual extension, because the pattern will no longer match first.
04259     */
04260    if (e->exten[0] == '_') {
04261       ast_add_extension(e->parent->name, 0, exten, e->priority, e->label,
04262          e->cidmatch, e->app, ast_strdup(e->data), ast_free_ptr,
04263          e->registrar);
04264       e = ast_hint_extension(NULL, context, exten);
04265       if (!e || e->exten[0] == '_') {
04266          return -1;
04267       }
04268    }
04269 
04270    /* Find the hint in the list of hints */
04271    AST_RWLIST_WRLOCK(&hints);
04272 
04273    AST_RWLIST_TRAVERSE(&hints, hint, list) {
04274       if (hint->exten == e)
04275          break;
04276    }
04277 
04278    if (!hint) {
04279       /* We have no hint, sorry */
04280       AST_RWLIST_UNLOCK(&hints);
04281       return -1;
04282    }
04283 
04284    /* Now insert the callback in the callback list  */
04285    if (!(cblist = ast_calloc(1, sizeof(*cblist)))) {
04286       AST_RWLIST_UNLOCK(&hints);
04287       return -1;
04288    }
04289 
04290    cblist->id = stateid++;    /* Unique ID for this callback */
04291    cblist->callback = callback;  /* Pointer to callback routine */
04292    cblist->data = data;    /* Data for the callback */
04293 
04294    AST_LIST_INSERT_HEAD(&hint->callbacks, cblist, entry);
04295 
04296    AST_RWLIST_UNLOCK(&hints);
04297 
04298    return cblist->id;
04299 }

int ast_extension_state_del ( int  id,
ast_state_cb_type  callback 
)

Deletes a registered state change callback by ID.

Parameters:
id of the callback to delete
callback callback
Removes the callback from list of callbacks

Return values:
0 success
-1 failure

Definition at line 4302 of file pbx.c.

References ast_free, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_state_cb::callback, ast_hint::callbacks, and ast_state_cb::id.

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

04303 {
04304    struct ast_state_cb *p_cur = NULL;
04305    int ret = -1;
04306 
04307    if (!id && !callback)
04308       return -1;
04309 
04310    AST_RWLIST_WRLOCK(&hints);
04311 
04312    if (!id) {  /* id == 0 is a callback without extension */
04313       AST_LIST_TRAVERSE_SAFE_BEGIN(&statecbs, p_cur, entry) {
04314          if (p_cur->callback == callback) {
04315             AST_LIST_REMOVE_CURRENT(entry);
04316             break;
04317          }
04318       }
04319       AST_LIST_TRAVERSE_SAFE_END;
04320    } else { /* callback with extension, find the callback based on ID */
04321       struct ast_hint *hint;
04322       AST_RWLIST_TRAVERSE(&hints, hint, list) {
04323          AST_LIST_TRAVERSE_SAFE_BEGIN(&hint->callbacks, p_cur, entry) {
04324             if (p_cur->id == id) {
04325                AST_LIST_REMOVE_CURRENT(entry);
04326                break;
04327             }
04328          }
04329          AST_LIST_TRAVERSE_SAFE_END;
04330 
04331          if (p_cur)
04332             break;
04333       }
04334    }
04335 
04336    if (p_cur) {
04337       ast_free(p_cur);
04338    }
04339 
04340    AST_RWLIST_UNLOCK(&hints);
04341 
04342    return ret;
04343 }

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

04486 {
04487    return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
04488 }

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

References E_FINDLABEL, and pbx_extension_helper().

Referenced by pbx_load_config().

04491 {
04492    return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
04493 }

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

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

03428 {
03429    char *copy = ast_strdupa(function);
03430    char *args = func_args(copy);
03431    struct ast_custom_function *acfptr = ast_custom_function_find(copy);
03432    int res;
03433    struct ast_module_user *u = NULL;
03434 
03435    if (acfptr == NULL) {
03436       ast_log(LOG_ERROR, "Function %s not registered\n", copy);
03437    } else if (!acfptr->read && !acfptr->read2) {
03438       ast_log(LOG_ERROR, "Function %s cannot be read\n", copy);
03439    } else if (acfptr->read) {
03440       if (acfptr->mod) {
03441          u = __ast_module_user_add(acfptr->mod, chan);
03442       }
03443       res = acfptr->read(chan, copy, args, workspace, len);
03444       if (acfptr->mod && u) {
03445          __ast_module_user_remove(acfptr->mod, u);
03446       }
03447       return res;
03448    } else {
03449       struct ast_str *str = ast_str_create(16);
03450       if (acfptr->mod) {
03451          u = __ast_module_user_add(acfptr->mod, chan);
03452       }
03453       res = acfptr->read2(chan, copy, args, &str, 0);
03454       if (acfptr->mod && u) {
03455          __ast_module_user_remove(acfptr->mod, u);
03456       }
03457       ast_copy_string(workspace, ast_str_buffer(str), len > ast_str_size(str) ? ast_str_size(str) : len);
03458       ast_free(str);
03459       return res;
03460    }
03461    return -1;
03462 }

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

References __ast_module_user_add(), __ast_module_user_remove(), 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 ast_str_substitute_variables_full().

03465 {
03466    char *copy = ast_strdupa(function);
03467    char *args = func_args(copy);
03468    struct ast_custom_function *acfptr = ast_custom_function_find(copy);
03469    int res;
03470    struct ast_module_user *u = NULL;
03471 
03472    if (acfptr == NULL) {
03473       ast_log(LOG_ERROR, "Function %s not registered\n", copy);
03474    } else if (!acfptr->read && !acfptr->read2) {
03475       ast_log(LOG_ERROR, "Function %s cannot be read\n", copy);
03476    } else {
03477       if (acfptr->mod) {
03478          u = __ast_module_user_add(acfptr->mod, chan);
03479       }
03480       if (acfptr->read2) {
03481          /* ast_str enabled */
03482          ast_str_reset(*str);
03483          res = acfptr->read2(chan, copy, args, str, maxlen);
03484       } else {
03485          /* Legacy function pointer, allocate buffer for result */
03486          int maxsize = ast_str_size(*str);
03487          if (maxlen > -1) {
03488             if (maxlen == 0) {
03489                if (acfptr->read_max) {
03490                   maxsize = acfptr->read_max;
03491                } else {
03492                   maxsize = VAR_BUF_SIZE;
03493                }
03494             } else {
03495                maxsize = maxlen;
03496             }
03497             ast_str_make_space(str, maxsize);
03498          }
03499          res = acfptr->read(chan, copy, args, ast_str_buffer(*str), maxsize);
03500       }
03501       if (acfptr->mod && u) {
03502          __ast_module_user_remove(acfptr->mod, u);
03503       }
03504       return res;
03505    }
03506    return -1;
03507 }

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

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

03510 {
03511    char *copy = ast_strdupa(function);
03512    char *args = func_args(copy);
03513    struct ast_custom_function *acfptr = ast_custom_function_find(copy);
03514 
03515    if (acfptr == NULL)
03516       ast_log(LOG_ERROR, "Function %s not registered\n", copy);
03517    else if (!acfptr->write)
03518       ast_log(LOG_ERROR, "Function %s cannot be written to\n", copy);
03519    else {
03520       int res;
03521       struct ast_module_user *u = NULL;
03522       if (acfptr->mod)
03523          u = __ast_module_user_add(acfptr->mod, chan);
03524       res = acfptr->write(chan, copy, args, value);
03525       if (acfptr->mod && u)
03526          __ast_module_user_remove(acfptr->mod, u);
03527       return res;
03528    }
03529 
03530    return -1;
03531 }

const char* ast_get_context_name ( struct ast_context con  ) 

const char* ast_get_context_registrar ( struct ast_context c  ) 

Definition at line 9693 of file pbx.c.

References ast_context::registrar.

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

09694 {
09695    return c ? c->registrar : NULL;
09696 }

const char* ast_get_extension_app ( struct ast_exten e  ) 

void* ast_get_extension_app_data ( struct ast_exten e  ) 

Definition at line 9728 of file pbx.c.

References ast_exten::data.

Referenced by _macro_exec(), ast_get_hint(), ast_str_get_hint(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and print_ext().

09729 {
09730    return e ? e->data : NULL;
09731 }

const char* ast_get_extension_cidmatch ( struct ast_exten e  ) 

Definition at line 9718 of file pbx.c.

References ast_exten::cidmatch.

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

09719 {
09720    return e ? e->cidmatch : NULL;
09721 }

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

Definition at line 9660 of file pbx.c.

References ast_exten::parent.

Referenced by handle_show_hint(), and handle_show_hints().

09661 {
09662    return exten ? exten->parent : NULL;
09663 }

const char* ast_get_extension_label ( struct ast_exten e  ) 

Definition at line 9670 of file pbx.c.

References ast_exten::label.

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

09671 {
09672    return exten ? exten->label : NULL;
09673 }

int ast_get_extension_matchcid ( struct ast_exten e  ) 

Definition at line 9713 of file pbx.c.

References ast_exten::matchcid.

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

09714 {
09715    return e ? e->matchcid : 0;
09716 }

const char* ast_get_extension_name ( struct ast_exten exten  ) 

int ast_get_extension_priority ( struct ast_exten exten  ) 

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

09686 {
09687    return exten ? exten->priority : -1;
09688 }

const char* ast_get_extension_registrar ( struct ast_exten e  ) 

Definition at line 9698 of file pbx.c.

References ast_exten::registrar.

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

09699 {
09700    return e ? e->registrar : NULL;
09701 }

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

04443 {
04444    struct ast_exten *e = ast_hint_extension(c, context, exten);
04445 
04446    if (e) {
04447       if (hint)
04448          ast_copy_string(hint, ast_get_extension_app(e), hintsize);
04449       if (name) {
04450          const char *tmp = ast_get_extension_app_data(e);
04451          if (tmp)
04452             ast_copy_string(name, tmp, namesize);
04453       }
04454       return -1;
04455    }
04456    return 0;
04457 }

const char* ast_get_ignorepat_name ( struct ast_ignorepat ip  ) 

const char* ast_get_ignorepat_registrar ( struct ast_ignorepat ip  ) 

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

09709 {
09710    return ip ? ip->registrar : NULL;
09711 }

const char* ast_get_include_name ( struct ast_include include  ) 

const char* ast_get_include_registrar ( struct ast_include i  ) 

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

09704 {
09705    return i ? i->registrar : NULL;
09706 }

const char* ast_get_switch_data ( struct ast_sw sw  ) 

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

09739 {
09740    return sw ? sw->data : NULL;
09741 }

int ast_get_switch_eval ( struct ast_sw sw  ) 

Definition at line 9743 of file pbx.c.

References ast_sw::eval.

Referenced by context_merge_incls_swits_igps_other_registrars().

09744 {
09745    return sw->eval;
09746 }

const char* ast_get_switch_name ( struct ast_sw sw  ) 

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

09734 {
09735    return sw ? sw->name : NULL;
09736 }

const char* ast_get_switch_registrar ( struct ast_sw sw  ) 

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

09749 {
09750    return sw ? sw->registrar : NULL;
09751 }

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

References __ast_goto_if_exists().

Referenced by background_detect_exec(), channel_spy(), common_exec(), conf_run(), dial_exec_full(), goto_exten(), onedigit_goto(), priority_jump(), select_entry(), and valid_exit().

09843 {
09844    return __ast_goto_if_exists(chan, context, exten, priority, 0);
09845 }

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

hashtable functions for contexts

Definition at line 1013 of file pbx.c.

References ast_context::name.

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

01014 {
01015    const struct ast_context *ac = ah_a;
01016    const struct ast_context *bc = ah_b;
01017    if (!ac || !bc) /* safety valve, but it might prevent a crash you'd rather have happen */
01018       return 1;
01019    /* assume context names are registered in a string table! */
01020    return strcmp(ac->name, bc->name);
01021 }

unsigned int ast_hashtab_hash_contexts ( const void *  obj  ) 

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

01057 {
01058    const struct ast_context *ac = obj;
01059    return ast_hashtab_hash_string(ac->name);
01060 }

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

07553 {
07554    struct ast_context *con = ast_context_find(context);
07555    if (con) {
07556       struct ast_ignorepat *pat;
07557       for (pat = con->ignorepats; pat; pat = pat->next) {
07558          if (ast_extension_match(pat->pattern, pattern))
07559             return 1;
07560       }
07561    }
07562 
07563    return 0;
07564 }

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

References E_MATCHMORE, and pbx_extension_helper().

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

04501 {
04502    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0);
04503 }

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

References __ast_internal_context_destroy(), 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_APPEND_LIST, AST_LIST_EMPTY, AST_LIST_HEAD_INIT_VALUE, AST_LIST_INSERT_HEAD, AST_LIST_REMOVE_HEAD, ast_log(), ast_rdlock_contexts(), AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_strdup, ast_tvdiff_us(), ast_tvnow(), ast_unlock_contexts(), ast_verb, ast_wrlock_contexts(), ast_wrlock_contexts_version(), ast_state_cb::callback, ast_hint::callbacks, context_merge(), contexts, contexts_table, ast_state_cb::data, ast_exten::data, E_MATCH, ast_exten::exten, ast_hint::exten, ast_hint::laststate, LOG_WARNING, ast_context::name, ast_context::next, ast_sw::next, ast_exten::parent, pbx_find_extension(), PRIORITY_HINT, ast_context::registrar, and pbx_find_info::stacklen.

Referenced by lua_reload_extensions(), and pbx_load_module().

06910 {
06911    double ft;
06912    struct ast_context *tmp, *oldcontextslist;
06913    struct ast_hashtab *oldtable;
06914    struct store_hints store = AST_LIST_HEAD_INIT_VALUE;
06915    struct store_hint *this;
06916    struct ast_hint *hint;
06917    struct ast_exten *exten;
06918    int length;
06919    struct ast_state_cb *thiscb;
06920    struct ast_hashtab_iter *iter;
06921 
06922    /* it is very important that this function hold the hint list lock _and_ the conlock
06923       during its operation; not only do we need to ensure that the list of contexts
06924       and extensions does not change, but also that no hint callbacks (watchers) are
06925       added or removed during the merge/delete process
06926 
06927       in addition, the locks _must_ be taken in this order, because there are already
06928       other code paths that use this order
06929    */
06930 
06931    struct timeval begintime, writelocktime, endlocktime, enddeltime;
06932    int wrlock_ver;
06933 
06934    begintime = ast_tvnow();
06935    ast_rdlock_contexts();
06936    iter = ast_hashtab_start_traversal(contexts_table);
06937    while ((tmp = ast_hashtab_next(iter))) {
06938       context_merge(extcontexts, exttable, tmp, registrar);
06939    }
06940    ast_hashtab_end_traversal(iter);
06941    wrlock_ver = ast_wrlock_contexts_version();
06942 
06943    ast_unlock_contexts(); /* this feels real retarded, but you must do
06944                        what you must do If this isn't done, the following 
06945                         wrlock is a guraranteed deadlock */
06946    ast_wrlock_contexts();
06947    if (ast_wrlock_contexts_version() > wrlock_ver+1) {
06948       ast_log(LOG_WARNING,"==================!!!!!!!!!!!!!!!Something changed the contexts in the middle of merging contexts!\n");
06949    }
06950 
06951    AST_RWLIST_WRLOCK(&hints);
06952    writelocktime = ast_tvnow();
06953 
06954    /* preserve all watchers for hints associated with this registrar */
06955    AST_RWLIST_TRAVERSE(&hints, hint, list) {
06956       if (!AST_LIST_EMPTY(&hint->callbacks) && !strcmp(registrar, hint->exten->parent->registrar)) {
06957          length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2 + sizeof(*this);
06958          if (!(this = ast_calloc(1, length)))
06959             continue;
06960          AST_LIST_APPEND_LIST(&this->callbacks, &hint->callbacks, entry);
06961          this->laststate = hint->laststate;
06962          this->context = this->data;
06963          strcpy(this->data, hint->exten->parent->name);
06964          this->exten = this->data + strlen(this->context) + 1;
06965          strcpy(this->exten, hint->exten->exten);
06966          AST_LIST_INSERT_HEAD(&store, this, list);
06967       }
06968    }
06969 
06970    /* save the old table and list */
06971    oldtable = contexts_table;
06972    oldcontextslist = contexts;
06973 
06974    /* move in the new table and list */
06975    contexts_table = exttable;
06976    contexts = *extcontexts;
06977 
06978    /* restore the watchers for hints that can be found; notify those that
06979       cannot be restored
06980    */
06981    while ((this = AST_LIST_REMOVE_HEAD(&store, list))) {
06982       struct pbx_find_info q = { .stacklen = 0 };
06983       exten = pbx_find_extension(NULL, NULL, &q, this->context, this->exten, PRIORITY_HINT, NULL, "", E_MATCH);
06984       /* If this is a pattern, dynamically create a new extension for this
06985        * particular match.  Note that this will only happen once for each
06986        * individual extension, because the pattern will no longer match first.
06987        */
06988       if (exten && exten->exten[0] == '_') {
06989          ast_add_extension_nolock(exten->parent->name, 0, this->exten, PRIORITY_HINT, NULL,
06990             0, exten->app, ast_strdup(exten->data), ast_free_ptr, registrar);
06991          /* rwlocks are not recursive locks */
06992          exten = ast_hint_extension_nolock(NULL, this->context, this->exten);
06993       }
06994 
06995       /* Find the hint in the list of hints */
06996       AST_RWLIST_TRAVERSE(&hints, hint, list) {
06997          if (hint->exten == exten)
06998             break;
06999       }
07000       if (!exten || !hint) {
07001          /* this hint has been removed, notify the watchers */
07002          while ((thiscb = AST_LIST_REMOVE_HEAD(&this->callbacks, entry))) {
07003             thiscb->callback(this->context, this->exten, AST_EXTENSION_REMOVED, thiscb->data);
07004             ast_free(thiscb);
07005          }
07006       } else {
07007          AST_LIST_APPEND_LIST(&hint->callbacks, &this->callbacks, entry);
07008          hint->laststate = this->laststate;
07009       }
07010       ast_free(this);
07011    }
07012 
07013    AST_RWLIST_UNLOCK(&hints);
07014    ast_unlock_contexts();
07015    endlocktime = ast_tvnow();
07016 
07017    /* the old list and hashtab no longer are relevant, delete them while the rest of asterisk
07018       is now freely using the new stuff instead */
07019 
07020    ast_hashtab_destroy(oldtable, NULL);
07021 
07022    for (tmp = oldcontextslist; tmp; ) {
07023       struct ast_context *next;  /* next starting point */
07024       next = tmp->next;
07025       __ast_internal_context_destroy(tmp);
07026       tmp = next;
07027    }
07028    enddeltime = ast_tvnow();
07029 
07030    ft = ast_tvdiff_us(writelocktime, begintime);
07031    ft /= 1000000.0;
07032    ast_verb(3,"Time to scan old dialplan and merge leftovers back into the new: %8.6f sec\n", ft);
07033 
07034    ft = ast_tvdiff_us(endlocktime, writelocktime);
07035    ft /= 1000000.0;
07036    ast_verb(3,"Time to restore hints and swap in new dialplan: %8.6f sec\n", ft);
07037 
07038    ft = ast_tvdiff_us(enddeltime, endlocktime);
07039    ft /= 1000000.0;
07040    ast_verb(3,"Time to delete the old dialplan: %8.6f sec\n", ft);
07041 
07042    ft = ast_tvdiff_us(enddeltime, begintime);
07043    ft /= 1000000.0;
07044    ast_verb(3,"Total time merge_contexts_delete: %8.6f sec\n", ft);
07045    return;
07046 }

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

09906 {
09907    return pbx_parseable_goto(chan, goto_string, 0);
09908 }

int ast_pbx_outgoing_app ( const char *  type,
int  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 8393 of file pbx.c.

References __ast_request_and_dial(), ast_channel::_state, outgoing_helper::account, async_stat::app, app_tmp::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_strlen_zero(), ast_variables_destroy(), ast_verb, async_wait(), ast_channel::cdr, async_stat::chan, app_tmp::chan, app_tmp::data, errno, ast_channel::hangupcause, LOG_WARNING, ast_channel::name, 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().

08394 {
08395    struct ast_channel *chan;
08396    struct app_tmp *tmp;
08397    int res = -1, cdr_res = -1;
08398    struct outgoing_helper oh;
08399 
08400    memset(&oh, 0, sizeof(oh));
08401    oh.vars = vars;
08402    oh.account = account;
08403 
08404    if (locked_channel)
08405       *locked_channel = NULL;
08406    if (ast_strlen_zero(app)) {
08407       res = -1;
08408       goto outgoing_app_cleanup;
08409    }
08410    if (synchronous) {
08411       chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh);
08412       if (chan) {
08413          ast_set_variables(chan, vars);
08414          if (account)
08415             ast_cdr_setaccount(chan, account);
08416          if (chan->_state == AST_STATE_UP) {
08417             res = 0;
08418             ast_verb(4, "Channel %s was answered.\n", chan->name);
08419             tmp = ast_calloc(1, sizeof(*tmp));
08420             if (!tmp)
08421                res = -1;
08422             else {
08423                ast_copy_string(tmp->app, app, sizeof(tmp->app));
08424                if (appdata)
08425                   ast_copy_string(tmp->data, appdata, sizeof(tmp->data));
08426                tmp->chan = chan;
08427                if (synchronous > 1) {
08428                   if (locked_channel)
08429                      ast_channel_unlock(chan);
08430                   ast_pbx_run_app(tmp);
08431                } else {
08432                   if (locked_channel)
08433                      ast_channel_lock(chan);
08434                   if (ast_pthread_create_detached(&tmp->t, NULL, ast_pbx_run_app, tmp)) {
08435                      ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno));
08436                      ast_free(tmp);
08437                      if (locked_channel)
08438                         ast_channel_unlock(chan);
08439                      ast_hangup(chan);
08440                      res = -1;
08441                   } else {
08442                      if (locked_channel)
08443                         *locked_channel = chan;
08444                   }
08445                }
08446             }
08447          } else {
08448             ast_verb(4, "Channel %s was never answered.\n", chan->name);
08449             if (chan->cdr) { /* update the cdr */
08450                /* here we update the status of the call, which sould be busy.
08451                 * if that fails then we set the status to failed */
08452                if (ast_cdr_disposition(chan->cdr, chan->hangupcause))
08453                   ast_cdr_failed(chan->cdr);
08454             }
08455             ast_hangup(chan);
08456          }
08457       }
08458 
08459       if (res < 0) { /* the call failed for some reason */
08460          if (*reason == 0) { /* if the call failed (not busy or no answer)
08461                         * update the cdr with the failed message */
08462             cdr_res = ast_pbx_outgoing_cdr_failed();
08463             if (cdr_res != 0) {
08464                res = cdr_res;
08465                goto outgoing_app_cleanup;
08466             }
08467          }
08468       }
08469 
08470    } else {
08471       struct async_stat *as;
08472       if (!(as = ast_calloc(1, sizeof(*as)))) {
08473          res = -1;
08474          goto outgoing_app_cleanup;
08475       }
08476       chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh);
08477       if (!chan) {
08478          ast_free(as);
08479          res = -1;
08480          goto outgoing_app_cleanup;
08481       }
08482       as->chan = chan;
08483       ast_copy_string(as->app, app, sizeof(as->app));
08484       if (appdata)
08485          ast_copy_string(as->appdata,  appdata, sizeof(as->appdata));
08486       as->timeout = timeout;
08487       ast_set_variables(chan, vars);
08488       if (account)
08489          ast_cdr_setaccount(chan, account);
08490       /* Start a new thread, and get something handling this channel. */
08491       if (locked_channel)
08492          ast_channel_lock(chan);
08493       if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) {
08494          ast_log(LOG_WARNING, "Failed to start async wait\n");
08495          ast_free(as);
08496          if (locked_channel)
08497             ast_channel_unlock(chan);
08498          ast_hangup(chan);
08499          res = -1;
08500          goto outgoing_app_cleanup;
08501       } else {
08502          if (locked_channel)
08503             *locked_channel = chan;
08504       }
08505       res = 0;
08506    }
08507 outgoing_app_cleanup:
08508    ast_variables_destroy(vars);
08509    return res;
08510 }

int ast_pbx_outgoing_exten ( const char *  type,
int  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 8227 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, ast_channel::name, 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().

08228 {
08229    struct ast_channel *chan;
08230    struct async_stat *as;
08231    int res = -1, cdr_res = -1;
08232    struct outgoing_helper oh;
08233 
08234    if (synchronous) {
08235       oh.context = context;
08236       oh.exten = exten;
08237       oh.priority = priority;
08238       oh.cid_num = cid_num;
08239       oh.cid_name = cid_name;
08240       oh.account = account;
08241       oh.vars = vars;
08242       oh.parent_channel = NULL;
08243 
08244       chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh);
08245       if (channel) {
08246          *channel = chan;
08247          if (chan)
08248             ast_channel_lock(chan);
08249       }
08250       if (chan) {
08251          if (chan->_state == AST_STATE_UP) {
08252                res = 0;
08253             ast_verb(4, "Channel %s was answered.\n", chan->name);
08254 
08255             if (synchronous > 1) {
08256                if (channel)
08257                   ast_channel_unlock(chan);
08258                if (ast_pbx_run(chan)) {
08259                   ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name);
08260                   if (channel)
08261                      *channel = NULL;
08262                   ast_hangup(chan);
08263                   chan = NULL;
08264                   res = -1;
08265                }
08266             } else {
08267                if (ast_pbx_start(chan)) {
08268                   ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name);
08269                   if (channel) {
08270                      *channel = NULL;
08271                      ast_channel_unlock(chan);
08272                   }
08273                   ast_hangup(chan);
08274                   res = -1;
08275                }
08276                chan = NULL;
08277             }
08278          } else {
08279             ast_verb(4, "Channel %s was never answered.\n", chan->name);
08280 
08281             if (chan->cdr) { /* update the cdr */
08282                /* here we update the status of the call, which sould be busy.
08283                 * if that fails then we set the status to failed */
08284                if (ast_cdr_disposition(chan->cdr, chan->hangupcause))
08285                   ast_cdr_failed(chan->cdr);
08286             }
08287 
08288             if (channel) {
08289                *channel = NULL;
08290                ast_channel_unlock(chan);
08291             }
08292             ast_hangup(chan);
08293             chan = NULL;
08294          }
08295       }
08296 
08297       if (res < 0) { /* the call failed for some reason */
08298          if (*reason == 0) { /* if the call failed (not busy or no answer)
08299                         * update the cdr with the failed message */
08300             cdr_res = ast_pbx_outgoing_cdr_failed();
08301             if (cdr_res != 0) {
08302                res = cdr_res;
08303                goto outgoing_exten_cleanup;
08304             }
08305          }
08306 
08307          /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */
08308          /* check if "failed" exists */
08309          if (ast_exists_extension(chan, context, "failed", 1, NULL)) {
08310             chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", NULL, 0, "OutgoingSpoolFailed");
08311             if (chan) {
08312                char failed_reason[4] = "";
08313                if (!ast_strlen_zero(context))
08314                   ast_copy_string(chan->context, context, sizeof(chan->context));
08315                set_ext_pri(chan, "failed", 1);
08316                ast_set_variables(chan, vars);
08317                snprintf(failed_reason, sizeof(failed_reason), "%d", *reason);
08318                pbx_builtin_setvar_helper(chan, "REASON", failed_reason);
08319                if (account)
08320                   ast_cdr_setaccount(chan, account);
08321                if (ast_pbx_run(chan)) {
08322                   ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name);
08323                   ast_hangup(chan);
08324                }
08325                chan = NULL;
08326             }
08327          }
08328       }
08329    } else {
08330       if (!(as = ast_calloc(1, sizeof(*as)))) {
08331          res = -1;
08332          goto outgoing_exten_cleanup;
08333       }
08334       chan = ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name);
08335       if (channel) {
08336          *channel = chan;
08337          if (chan)
08338             ast_channel_lock(chan);
08339       }
08340       if (!chan) {
08341          ast_free(as);
08342          res = -1;
08343          goto outgoing_exten_cleanup;
08344       }
08345       as->chan = chan;
08346       ast_copy_string(as->context, context, sizeof(as->context));
08347       set_ext_pri(as->chan,  exten, priority);
08348       as->timeout = timeout;
08349       ast_set_variables(chan, vars);
08350       if (account)
08351          ast_cdr_setaccount(chan, account);
08352       if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) {
08353          ast_log(LOG_WARNING, "Failed to start async wait\n");
08354          ast_free(as);
08355          if (channel) {
08356             *channel = NULL;
08357             ast_channel_unlock(chan);
08358          }
08359          ast_hangup(chan);
08360          res = -1;
08361          goto outgoing_exten_cleanup;
08362       }
08363       res = 0;
08364    }
08365 outgoing_exten_cleanup:
08366    ast_variables_destroy(vars);
08367    return res;
08368 }

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

04930 {
04931    return ast_pbx_run_args(c, NULL);
04932 }

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

References __ast_pbx_run(), AST_PBX_CALL_LIMIT, AST_PBX_SUCCESS, decrease_call_count(), and increase_call_count().

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

04915 {
04916    enum ast_pbx_result res = AST_PBX_SUCCESS;
04917 
04918    if (increase_call_count(c)) {
04919       return AST_PBX_CALL_LIMIT;
04920    }
04921 
04922    res = __ast_pbx_run(c, args);
04923 
04924    decrease_call_count();
04925 
04926    return res;
04927 }

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

References ast_log(), AST_PBX_CALL_LIMIT, AST_PBX_FAILED, AST_PBX_SUCCESS, ast_pthread_create_detached, decrease_call_count(), increase_call_count(), LOG_WARNING, and pbx_thread().

Referenced by __oh323_new(), alsa_new(), ast_async_goto(), ast_iax2_new(), ast_pbx_outgoing_exten(), bridge_call_thread(), bridge_exec(), check_goto_on_transfer(), console_new(), dahdi_new(), dial_exec_full(), gtalk_new(), gtalk_newcall(), handle_request_invite(), jingle_new(), jingle_newcall(), local_call(), manage_parkinglot(), mgcp_new(), nbs_new(), oss_new(), pbx_start_chan(), phone_new(), rpt_call(), sip_new(), skinny_new(), unistim_new(), and usbradio_new().

04893 {
04894    pthread_t t;
04895 
04896    if (!c) {
04897       ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
04898       return AST_PBX_FAILED;
04899    }
04900 
04901    if (increase_call_count(c))
04902       return AST_PBX_CALL_LIMIT;
04903 
04904    /* Start a new thread, and get something handling this channel. */
04905    if (ast_pthread_create_detached(&t, NULL, pbx_thread, c)) {
04906       ast_log(LOG_WARNING, "Failed to create new channel thread\n");
04907       decrease_call_count();
04908       return AST_PBX_FAILED;
04909    }
04910 
04911    return AST_PBX_SUCCESS;
04912 }

int ast_processed_calls ( void   ) 

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

Definition at line 4939 of file pbx.c.

References totalcalls.

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

04940 {
04941    return totalcalls;
04942 }

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

09643 {
09644    return ast_rwlock_rdlock(&con->lock);
09645 }

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

05462 {
05463    struct ast_switch *tmp;
05464 
05465    AST_RWLIST_WRLOCK(&switches);
05466    AST_RWLIST_TRAVERSE(&switches, tmp, list) {
05467       if (!strcasecmp(tmp->name, sw->name)) {
05468          AST_RWLIST_UNLOCK(&switches);
05469          ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name);
05470          return -1;
05471       }
05472    }
05473    AST_RWLIST_INSERT_TAIL(&switches, sw, list);
05474    AST_RWLIST_UNLOCK(&switches);
05475 
05476    return 0;
05477 }

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

04506 {
04507    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN, found, combined_find_spawn);
04508 }

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

04461 {
04462    struct ast_exten *e = ast_hint_extension(c, context, exten);
04463 
04464    if (!e) {
04465       return 0;
04466    }
04467 
04468    if (hint) {
04469       ast_str_set(hint, hintsize, "%s", ast_get_extension_app(e));
04470    }
04471    if (name) {
04472       const char *tmp = ast_get_extension_app_data(e);
04473       if (tmp) {
04474          ast_str_set(name, namesize, "%s", tmp);
04475       }
04476    }
04477    return -1;
04478 }

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

References 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_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::cid, ast_callerid::cid_ani2, ast_callerid::cid_pres, ast_callerid::cid_tns, ast_callerid::cid_ton, ast_channel::context, ast_var_t::entries, ast_channel::exten, globals, globalslock, ast_channel::hangupcause, ast_channel::name, parse_variable_name(), ast_channel::priority, s, ast_channel::uniqueid, and ast_channel::varshead.

Referenced by ast_str_substitute_variables_full(), and pbx_retrieve_variable().

02930 {
02931    const char not_found = '\0';
02932    char *tmpvar;
02933    const char *ret;
02934    const char *s; /* the result */
02935    int offset, length;
02936    int i, need_substring;
02937    struct varshead *places[2] = { headp, &globals };  /* list of places where we may look */
02938 
02939    if (c) {
02940       ast_channel_lock(c);
02941       places[0] = &c->varshead;
02942    }
02943    /*
02944     * Make a copy of var because parse_variable_name() modifies the string.
02945     * Then if called directly, we might need to run substring() on the result;
02946     * remember this for later in 'need_substring', 'offset' and 'length'
02947     */
02948    tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */
02949    need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */);
02950 
02951    /*
02952     * Look first into predefined variables, then into variable lists.
02953     * Variable 's' points to the result, according to the following rules:
02954     * s == &not_found (set at the beginning) means that we did not find a
02955     * matching variable and need to look into more places.
02956     * If s != &not_found, s is a valid result string as follows:
02957     * s = NULL if the variable does not have a value;
02958     * you typically do this when looking for an unset predefined variable.
02959     * s = workspace if the result has been assembled there;
02960     * typically done when the result is built e.g. with an snprintf(),
02961     * so we don't need to do an additional copy.
02962     * s != workspace in case we have a string, that needs to be copied
02963     * (the ast_copy_string is done once for all at the end).
02964     * Typically done when the result is already available in some string.
02965     */
02966    s = &not_found;   /* default value */
02967    if (c) { /* This group requires a valid channel */
02968       /* Names with common parts are looked up a piece at a time using strncmp. */
02969       if (!strncmp(var, "CALL", 4)) {
02970          if (!strncmp(var + 4, "ING", 3)) {
02971             if (!strcmp(var + 7, "PRES")) {        /* CALLINGPRES */
02972                ast_str_set(str, maxlen, "%d", c->cid.cid_pres);
02973                s = ast_str_buffer(*str);
02974             } else if (!strcmp(var + 7, "ANI2")) {    /* CALLINGANI2 */
02975                ast_str_set(str, maxlen, "%d", c->cid.cid_ani2);
02976                s = ast_str_buffer(*str);
02977             } else if (!strcmp(var + 7, "TON")) {     /* CALLINGTON */
02978                ast_str_set(str, maxlen, "%d", c->cid.cid_ton);
02979                s = ast_str_buffer(*str);
02980             } else if (!strcmp(var + 7, "TNS")) {     /* CALLINGTNS */
02981                ast_str_set(str, maxlen, "%d", c->cid.cid_tns);
02982                s = ast_str_buffer(*str);
02983             }
02984          }
02985       } else if (!strcmp(var, "HINT")) {
02986          s = ast_str_get_hint(str, maxlen, NULL, 0, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL;
02987       } else if (!strcmp(var, "HINTNAME")) {
02988          s = ast_str_get_hint(NULL, 0, str, maxlen, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL;
02989       } else if (!strcmp(var, "EXTEN")) {
02990          s = c->exten;
02991       } else if (!strcmp(var, "CONTEXT")) {
02992          s = c->context;
02993       } else if (!strcmp(var, "PRIORITY")) {
02994          ast_str_set(str, maxlen, "%d", c->priority);
02995          s = ast_str_buffer(*str);
02996       } else if (!strcmp(var, "CHANNEL")) {
02997          s = c->name;
02998       } else if (!strcmp(var, "UNIQUEID")) {
02999          s = c->uniqueid;
03000       } else if (!strcmp(var, "HANGUPCAUSE")) {
03001          ast_str_set(str, maxlen, "%d", c->hangupcause);
03002          s = ast_str_buffer(*str);
03003       }
03004    }
03005    if (s == &not_found) { /* look for more */
03006       if (!strcmp(var, "EPOCH")) {
03007          ast_str_set(str, maxlen, "%u", (int) time(NULL));
03008          s = ast_str_buffer(*str);
03009       } else if (!strcmp(var, "SYSTEMNAME")) {
03010          s = ast_config_AST_SYSTEM_NAME;
03011       } else if (!strcmp(var, "ENTITYID")) {
03012          char workspace[20];
03013          ast_eid_to_str(workspace, sizeof(workspace), &ast_eid_default);
03014          s = workspace;
03015       }
03016    }
03017    /* if not found, look into chanvars or global vars */
03018    for (i = 0; s == &not_found && i < ARRAY_LEN(places); i++) {
03019       struct ast_var_t *variables;
03020       if (!places[i])
03021          continue;
03022       if (places[i] == &globals)
03023          ast_rwlock_rdlock(&globalslock);
03024       AST_LIST_TRAVERSE(places[i], variables, entries) {
03025          if (!strcasecmp(ast_var_name(variables), var)) {
03026             s = ast_var_value(variables);
03027             break;
03028          }
03029       }
03030       if (places[i] == &globals)
03031          ast_rwlock_unlock(&globalslock);
03032    }
03033    if (s == &not_found || s == NULL) {
03034       ast_debug(5, "Result of '%s' is NULL\n", var);
03035       ret = NULL;
03036    } else {
03037       ast_debug(5, "Result of '%s' is '%s'\n", var, s);
03038       if (s != ast_str_buffer(*str)) {
03039          ast_str_set(str, maxlen, "%s", s);
03040       }
03041       ret = ast_str_buffer(*str);
03042       if (need_substring) {
03043          ret = ast_str_substring(*str, offset, length);
03044          ast_debug(2, "Final result of '%s' is '%s'\n", var, ret);
03045       }
03046    }
03047 
03048    if (c) {
03049       ast_channel_unlock(c);
03050    }
03051    return ret;
03052 }

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 3709 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_fieldqty_helper(), handle_getvariablefull(), import_helper(), make_email_file(), realtime_curl(), realtime_multi_curl(), require_curl(), sendmail(), sendpage(), store_curl(), syslog_log(), tryexec_exec(), update2_curl(), and update_curl().

03710 {
03711    size_t used;
03712    ast_str_substitute_variables_full(buf, maxlen, chan, NULL, templ, &used);
03713 }

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

References ast_channel_release(), ast_debug, ast_dummy_channel_alloc(), ast_free, ast_func_read2(), ast_log(), ast_str_append(), ast_str_append_substr(), ast_str_buffer(), ast_str_create(), ast_str_expr(), ast_str_reset(), ast_str_retrieve_variable(), ast_str_set_substr(), ast_str_strlen(), ast_str_substitute_variables_full(), ast_str_substring(), ast_strlen_zero(), len(), LOG_ERROR, LOG_WARNING, parse_variable_name(), and ast_channel::varshead.

Referenced by ast_str_substitute_variables(), ast_str_substitute_variables_full(), and ast_str_substitute_variables_varshead().

03534 {
03535    /* Substitutes variables into buf, based on string templ */
03536    char *cp4 = NULL;
03537    const char *tmp, *whereweare;
03538    int orig_size = 0;
03539    int offset, offset2, isfunction;
03540    const char *nextvar, *nextexp, *nextthing;
03541    const char *vars, *vare;
03542    char *finalvars;
03543    int pos, brackets, needsub, len;
03544    struct ast_str *substr1 = ast_str_create(16), *substr2 = NULL, *substr3 = ast_str_create(16);
03545 
03546    ast_str_reset(*buf);
03547    whereweare = tmp = templ;
03548    while (!ast_strlen_zero(whereweare)) {
03549       /* Assume we're copying the whole remaining string */
03550       pos = strlen(whereweare);
03551       nextvar = NULL;
03552       nextexp = NULL;
03553       nextthing = strchr(whereweare, '$');
03554       if (nextthing) {
03555          switch (nextthing[1]) {
03556          case '{':
03557             nextvar = nextthing;
03558             pos = nextvar - whereweare;
03559             break;
03560          case '[':
03561             nextexp = nextthing;
03562             pos = nextexp - whereweare;
03563             break;
03564          default:
03565             pos = 1;
03566          }
03567       }
03568 
03569       if (pos) {
03570          /* Copy that many bytes */
03571          ast_str_append_substr(buf, maxlen, whereweare, pos);
03572 
03573          templ += pos;
03574          whereweare += pos;
03575       }
03576 
03577       if (nextvar) {
03578          /* We have a variable.  Find the start and end, and determine
03579             if we are going to have to recursively call ourselves on the
03580             contents */
03581          vars = vare = nextvar + 2;
03582          brackets = 1;
03583          needsub = 0;
03584 
03585          /* Find the end of it */
03586          while (brackets && *vare) {
03587             if ((vare[0] == '$') && (vare[1] == '{')) {
03588                needsub++;
03589             } else if (vare[0] == '{') {
03590                brackets++;
03591             } else if (vare[0] == '}') {
03592                brackets--;
03593             } else if ((vare[0] == '$') && (vare[1] == '['))
03594                needsub++;
03595             vare++;
03596          }
03597          if (brackets)
03598             ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n");
03599          len = vare - vars - 1;
03600 
03601          /* Skip totally over variable string */
03602          whereweare += (len + 3);
03603 
03604          /* Store variable name (and truncate) */
03605          ast_str_set_substr(&substr1, 0, vars, len);
03606          ast_debug(5, "Evaluating '%s' (from '%s' len %d)\n", ast_str_buffer(substr1), vars, len);
03607 
03608          /* Substitute if necessary */
03609          if (needsub) {
03610             size_t used;
03611             if (!substr2) {
03612                substr2 = ast_str_create(16);
03613             }
03614 
03615             ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used);
03616             finalvars = ast_str_buffer(substr2);
03617          } else {
03618             finalvars = ast_str_buffer(substr1);
03619          }
03620 
03621          parse_variable_name(finalvars, &offset, &offset2, &isfunction);
03622          if (isfunction) {
03623             /* Evaluate function */
03624             if (c || !headp) {
03625                cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3);
03626             } else {
03627                struct varshead old;
03628                struct ast_channel *bogus = ast_dummy_channel_alloc();
03629                if (bogus) {
03630                   memcpy(&old, &bogus->varshead, sizeof(old));
03631                   memcpy(&bogus->varshead, headp, sizeof(bogus->varshead));
03632                   cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3);
03633                   /* Don't deallocate the varshead that was passed in */
03634                   memcpy(&bogus->varshead, &old, sizeof(bogus->varshead));
03635                   ast_channel_release(bogus);
03636                } else {
03637                   ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution.  Function results may be blank.\n");
03638                }
03639             }
03640             ast_debug(2, "Function result is '%s'\n", cp4 ? cp4 : "(null)");
03641          } else {
03642             /* Retrieve variable value */
03643             ast_str_retrieve_variable(&substr3, 0, c, headp, finalvars);
03644             cp4 = ast_str_buffer(substr3);
03645          }
03646          if (cp4) {
03647             ast_str_substring(substr3, offset, offset2);
03648             ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3));
03649          }
03650       } else if (nextexp) {
03651          /* We have an expression.  Find the start and end, and determine
03652             if we are going to have to recursively call ourselves on the
03653             contents */
03654          vars = vare = nextexp + 2;
03655          brackets = 1;
03656          needsub = 0;
03657 
03658          /* Find the end of it */
03659          while (brackets && *vare) {
03660             if ((vare[0] == '$') && (vare[1] == '[')) {
03661                needsub++;
03662                brackets++;
03663                vare++;
03664             } else if (vare[0] == '[') {
03665                brackets++;
03666             } else if (vare[0] == ']') {
03667                brackets--;
03668             } else if ((vare[0] == '$') && (vare[1] == '{')) {
03669                needsub++;
03670                vare++;
03671             }
03672             vare++;
03673          }
03674          if (brackets)
03675             ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n");
03676          len = vare - vars - 1;
03677 
03678          /* Skip totally over expression */
03679          whereweare += (len + 3);
03680 
03681          /* Store variable name (and truncate) */
03682          ast_str_set_substr(&substr1, 0, vars, len);
03683 
03684          /* Substitute if necessary */
03685          if (needsub) {
03686             size_t used;
03687             if (!substr2) {
03688                substr2 = ast_str_create(16);
03689             }
03690 
03691             ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used);
03692             finalvars = ast_str_buffer(substr2);
03693          } else {
03694             finalvars = ast_str_buffer(substr1);
03695          }
03696 
03697          if (ast_str_expr(&substr3, 0, c, finalvars)) {
03698             ast_debug(2, "Expression result is '%s'\n", ast_str_buffer(substr3));
03699          }
03700          ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3));
03701       }
03702    }
03703    *used = ast_str_strlen(*buf) - orig_size;
03704    ast_free(substr1);
03705    ast_free(substr2);
03706    ast_free(substr3);
03707 }

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

03716 {
03717    size_t used;
03718    ast_str_substitute_variables_full(buf, maxlen, NULL, headp, templ, &used);
03719 }

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

References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

Referenced by __unload_module(), and unload_module().

05480 {
05481    AST_RWLIST_WRLOCK(&switches);
05482    AST_RWLIST_REMOVE(&switches, sw, list);
05483    AST_RWLIST_UNLOCK(&switches);
05484 }

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

Definition at line 9761 of file pbx.c.

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

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

09763 {
09764    if (!exten)
09765       return con ? con->root : NULL;
09766    else
09767       return exten->next;
09768 }

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

Definition at line 9794 of file pbx.c.

References ast_context::ignorepats, and ast_ignorepat::next.

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

09796 {
09797    if (!ip)
09798       return con ? con->ignorepats : NULL;
09799    else
09800       return ip->next;
09801 }

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

References ast_context::alts, AST_LIST_FIRST, and AST_LIST_NEXT.

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

09772 {
09773    if (!sw)
09774       return con ? AST_LIST_FIRST(&con->alts) : NULL;
09775    else
09776       return AST_LIST_NEXT(sw, list);
09777 }

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

09781 {
09782    return priority ? priority->peer : exten;
09783 }

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

09638 {
09639    return ast_rwlock_wrlock(&con->lock);
09640 }

int ast_wrlock_contexts ( void   ) 

Write locks the context list.

Return values:
0 on success
-1 on error

Definition at line 9616 of file pbx.c.

References ast_atomic_fetchadd_int(), ast_rwlock_wrlock(), conlock, and conlock_wrlock_version.

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

09617 {
09618    int res = ast_rwlock_wrlock(&conlock);
09619    if (!res)
09620       ast_atomic_fetchadd_int(&conlock_wrlock_version, 1);
09621    return res;
09622 }

int ast_wrlock_contexts_version ( void   ) 

Definition at line 9608 of file pbx.c.

References conlock_wrlock_version.

Referenced by ast_merge_contexts_and_delete().

09609 {
09610    return conlock_wrlock_version;
09611 }

void pbx_builtin_clear_globals ( void   ) 

Definition at line 9453 of file pbx.c.

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

Referenced by handle_cli_dialplan_reload(), and reload().

09454 {
09455    struct ast_var_t *vardata;
09456 
09457    ast_rwlock_wrlock(&globalslock);
09458    while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries)))
09459       ast_var_delete(vardata);
09460    ast_rwlock_unlock(&globalslock);
09461 }

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 9223 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(), array(), array_insert(), array_remove(), ast_bridge_call(), ast_bridge_timelimit(), ast_call_forward(), ast_channel_connected_line_macro(), ast_eivr_getvariable(), ast_hangup(), ast_monitor_stop(), bridge_play_sounds(), builtin_atxfer(), builtin_automixmonitor(), builtin_automonitor(), check_goto_on_transfer(), common_exec(), conf_run(), confbridge_exec(), crement_function_read(), dahdi_call(), dahdi_hangup(), dial_exec_full(), do_forward(), dundi_exec(), dundi_helper(), feature_interpret(), find_by_mark(), find_conf_realtime(), findparkinglotname(), func_channel_read(), get_also_info(), get_index(), get_refer_info(), global_read(), hash_read(), iax2_exec(), import_ch(), leave_voicemail(), listfilter(), local_attended_transfer(), local_hangup(), local_read(), login_exec(), macro_fixup(), minivm_delete_exec(), minivm_notify_exec(), misdn_answer(), misdn_hangup(), morsecode_exec(), notify_new_message(), oh323_call(), oh323_hangup(), park_call_full(), park_space_reserve(), queue_exec(), real_ctx(), retrydial_exec(), ring_entry(), run_agi(), 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().

09224 {
09225    struct ast_var_t *variables;
09226    const char *ret = NULL;
09227    int i;
09228    struct varshead *places[2] = { NULL, &globals };
09229 
09230    if (!name)
09231       return NULL;
09232 
09233    if (chan) {
09234       ast_channel_lock(chan);
09235       places[0] = &chan->varshead;
09236    }
09237 
09238    for (i = 0; i < 2; i++) {
09239       if (!places[i])
09240          continue;
09241       if (places[i] == &globals)
09242          ast_rwlock_rdlock(&globalslock);
09243       AST_LIST_TRAVERSE(places[i], variables, entries) {
09244          if (!strcmp(name, ast_var_name(variables))) {
09245             ret = ast_var_value(variables);
09246             break;
09247          }
09248       }
09249       if (places[i] == &globals)
09250          ast_rwlock_unlock(&globalslock);
09251       if (ret)
09252          break;
09253    }
09254 
09255    if (chan)
09256       ast_channel_unlock(chan);
09257 
09258    return ret;
09259 }

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

09262 {
09263    struct ast_var_t *newvariable;
09264    struct varshead *headp;
09265 
09266    if (name[strlen(name)-1] == ')') {
09267       char *function = ast_strdupa(name);
09268 
09269       ast_log(LOG_WARNING, "Cannot push a value onto a function\n");
09270       ast_func_write(chan, function, value);
09271       return;
09272    }
09273 
09274    if (chan) {
09275       ast_channel_lock(chan);
09276       headp = &chan->varshead;
09277    } else {
09278       ast_rwlock_wrlock(&globalslock);
09279       headp = &globals;
09280    }
09281 
09282    if (value) {
09283       if (headp == &globals)
09284          ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value);
09285       newvariable = ast_var_assign(name, value);
09286       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
09287    }
09288 
09289    if (chan)
09290       ast_channel_unlock(chan);
09291    else
09292       ast_rwlock_unlock(&globalslock);
09293 }

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

Definition at line 3066 of file pbx.c.

References ast_calloc, ast_channel_datastore_add(), ast_channel_datastore_find(), ast_datastore_alloc, ast_datastore_free(), ast_free, ast_string_field_init, ast_string_field_set, ast_channel::context, ast_datastore::data, exception_store_info, ast_channel::exten, ast_channel::priority, pbx_exception::priority, and set_ext_pri().

Referenced by __ast_pbx_run().

03067 {
03068    struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL);
03069    struct pbx_exception *exception = NULL;
03070 
03071    if (!ds) {
03072       ds = ast_datastore_alloc(&exception_store_info, NULL);
03073       if (!ds)
03074          return -1;
03075       exception = ast_calloc(1, sizeof(struct pbx_exception));
03076       if (!exception) {
03077          ast_datastore_free(ds);
03078          return -1;
03079       }
03080       if (ast_string_field_init(exception, 128)) {
03081          ast_free(exception);
03082          ast_datastore_free(ds);
03083          return -1;
03084       }
03085       ds->data = exception;
03086       ast_channel_datastore_add(chan, ds);
03087    } else
03088       exception = ds->data;
03089 
03090    ast_string_field_set(exception, reason, reason);
03091    ast_string_field_set(exception, context, chan->context);
03092    ast_string_field_set(exception, exten, chan->exten);
03093    exception->priority = chan->priority;
03094    set_ext_pri(chan, "e", 0);
03095    return 0;
03096 }

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

References ast_channel_lock, ast_channel_unlock, AST_LIST_TRAVERSE, ast_log(), ast_str_append(), ast_str_reset(), ast_var_name(), ast_var_value(), ast_var_t::entries, LOG_ERROR, total, var, and ast_channel::varshead.

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

09193 {
09194    struct ast_var_t *variables;
09195    const char *var, *val;
09196    int total = 0;
09197 
09198    if (!chan)
09199       return 0;
09200 
09201    ast_str_reset(*buf);
09202 
09203    ast_channel_lock(chan);
09204 
09205    AST_LIST_TRAVERSE(&chan->varshead, variables, entries) {
09206       if ((var = ast_var_name(variables)) && (val = ast_var_value(variables))
09207          /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */
09208          ) {
09209          if (ast_str_append(buf, 0, "%s=%s\n", var, val) < 0) {
09210             ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
09211             break;
09212          } else
09213             total++;
09214       } else
09215          break;
09216    }
09217 
09218    ast_channel_unlock(chan);
09219 
09220    return total;
09221 }

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

References ast_compat_app_set, ast_log(), ast_strdupa, ast_strlen_zero(), LOG_WARNING, pbx_builtin_setvar_helper(), pbx_builtin_setvar_multiple(), strsep(), and value.

Referenced by ast_compile_ael2(), and rpt_exec().

09353 {
09354    char *name, *value, *mydata;
09355 
09356    if (ast_compat_app_set) {
09357       return pbx_builtin_setvar_multiple(chan, data);
09358    }
09359 
09360    if (ast_strlen_zero(data)) {
09361       ast_log(LOG_WARNING, "Set requires one variable name/value pair.\n");
09362       return 0;
09363    }
09364 
09365    mydata = ast_strdupa(data);
09366    name = strsep(&mydata, "=");
09367    value = mydata;
09368    if (strchr(name, ' '))
09369       ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, mydata);
09370 
09371    pbx_builtin_setvar_helper(chan, name, value);
09372    return(0);
09373 }

void 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

Definition at line 9295 of file pbx.c.

References ast_channel_lock, ast_channel_unlock, ast_func_write(), AST_LIST_INSERT_HEAD, AST_LIST_REMOVE, AST_LIST_TRAVERSE, ast_rwlock_unlock(), ast_rwlock_wrlock(), ast_strdupa, ast_var_assign(), ast_var_delete(), ast_var_name(), ast_verb, EVENT_FLAG_DIALPLAN, globals, globalslock, manager_event, ast_channel::name, ast_channel::uniqueid, and ast_channel::varshead.

Referenced by __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(), array_insert(), array_remove(), ast_bridge_call(), ast_cel_fabricate_channel_from_event(), ast_eivr_setvariable(), ast_iax2_new(), ast_monitor_start(), ast_pbx_outgoing_exten(), ast_rtp_instance_set_stats_vars(), ast_set_variables(), asyncgoto_exec(), background_detect_exec(), bridge_exec(), bridge_play_sounds(), builtin_atxfer(), builtin_automixmonitor(), builtin_automonitor(), builtin_blindtransfer(), cb_events(), chanavail_exec(), change_t38_state(), channel_spy(), commit_exec(), conf_run(), controlplayback_exec(), count_exec(), crement_function_read(), dahdi_handle_dtmfup(), 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(), get_rdnis(), get_refer_info(), global_write(), gosub_release_frame(), handle_request_bye(), handle_request_refer(), handle_response(), handle_set_chanvar(), handle_set_global(), handle_setvariable(), hash_read(), hash_write(), isAnsweringMachine(), leave_queue(), leave_voicemail(), local_hangup(), lua_set_variable(), lua_set_variable_value(), macro_fixup(), manage_parkinglot(), mgcp_new(), minivm_accmess_exec(), minivm_delete_exec(), minivm_greet_exec(), minivm_notify_exec(), minivm_record_exec(), misdn_call(), mixmonitor_exec(), my_handle_dtmfup(), originate_exec(), ospauth_exec(), ospfinished_exec(), osplookup_exec(), ospnext_exec(), park_exec_full(), parse_moved_contact(), pbx_builtin_background(), 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(), read_exec(), readexten_exec(), readfile_exec(), realtimefield_read(), record_exec(), return_exec(), rollback_exec(), rotate_file(), rpt_exec(), rqm_exec(), sendimage_exec(), sendtext_exec(), sendurl_exec(), set(), set_queue_result(), sip_addheader(), sip_hangup(), sip_new(), skinny_new(), sla_calc_trunk_timeouts(), sla_station_exec(), sla_trunk_exec(), socket_process(), speech_create(), start_monitor_exec(), system_exec_helper(), transfer_exec(), transmit(), tryexec_exec(), update_bridge_vars(), update_qe_rule(), upqm_exec(), vm_box_exists(), vm_exec(), vmauthenticate(), waituntil_exec(), and zapateller_exec().

09296 {
09297    struct ast_var_t *newvariable;
09298    struct varshead *headp;
09299    const char *nametail = name;
09300 
09301    if (name[strlen(name) - 1] == ')') {
09302       char *function = ast_strdupa(name);
09303 
09304       ast_func_write(chan, function, value);
09305       return;
09306    }
09307 
09308    if (chan) {
09309       ast_channel_lock(chan);
09310       headp = &chan->varshead;
09311    } else {
09312       ast_rwlock_wrlock(&globalslock);
09313       headp = &globals;
09314    }
09315 
09316    /* For comparison purposes, we have to strip leading underscores */
09317    if (*nametail == '_') {
09318       nametail++;
09319       if (*nametail == '_')
09320          nametail++;
09321    }
09322 
09323    AST_LIST_TRAVERSE (headp, newvariable, entries) {
09324       if (strcasecmp(ast_var_name(newvariable), nametail) == 0) {
09325          /* there is already such a variable, delete it */
09326          AST_LIST_REMOVE(headp, newvariable, entries);
09327          ast_var_delete(newvariable);
09328          break;
09329       }
09330    }
09331 
09332    if (value) {
09333       if (headp == &globals)
09334          ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value);
09335       newvariable = ast_var_assign(name, value);
09336       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
09337       manager_event(EVENT_FLAG_DIALPLAN, "VarSet",
09338          "Channel: %s\r\n"
09339          "Variable: %s\r\n"
09340          "Value: %s\r\n"
09341          "Uniqueid: %s\r\n",
09342          chan ? chan->name : "none", name, value,
09343          chan ? chan->uniqueid : "none");
09344    }
09345 
09346    if (chan)
09347       ast_channel_unlock(chan);
09348    else
09349       ast_rwlock_unlock(&globalslock);
09350 }

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

References AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), AST_NONSTANDARD_APP_ARGS, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_channel::context, ast_channel::exten, LOG_WARNING, ast_channel::name, pbx_builtin_setvar_helper(), ast_channel::priority, and value.

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

09376 {
09377    char *data;
09378    int x;
09379    AST_DECLARE_APP_ARGS(args,
09380       AST_APP_ARG(pair)[24];
09381    );
09382    AST_DECLARE_APP_ARGS(pair,
09383       AST_APP_ARG(name);
09384       AST_APP_ARG(value);
09385    );
09386 
09387    if (ast_strlen_zero(vdata)) {
09388       ast_log(LOG_WARNING, "MSet requires at least one variable name/value pair.\n");
09389       return 0;
09390    }
09391 
09392    data = ast_strdupa(vdata);
09393    AST_STANDARD_APP_ARGS(args, data);
09394 
09395    for (x = 0; x < args.argc; x++) {
09396       AST_NONSTANDARD_APP_ARGS(pair, args.pair[x], '=');
09397       if (pair.argc == 2) {
09398          pbx_builtin_setvar_helper(chan, pair.name, pair.value);
09399          if (strchr(pair.name, ' '))
09400             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);
09401       } else if (!chan) {
09402          ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '='\n", pair.name);
09403       } else {
09404          ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '=' (in %s@%s:%d\n", pair.name, chan->exten, chan->context, chan->priority);
09405       }
09406    }
09407 
09408    return 0;
09409 }

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

References ast_strlen_zero().

Referenced by _macro_exec(), _while_exec(), acf_if(), execif_exec(), gosubif_exec(), macroif_exec(), and pbx_builtin_gotoif().

09464 {
09465    int res;
09466    if (ast_strlen_zero(condition)) {                /* NULL or empty strings are false */
09467       return 0;
09468    } else if (sscanf(condition, "%30d", &res) == 1) { /* Numbers are evaluated for truth */
09469       return res;
09470    } else {                                         /* Strings are true */
09471       return 1;
09472    }
09473 }

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

01344 {
01345    int res;
01346    struct ast_module_user *u = NULL;
01347    const char *saved_c_appl;
01348    const char *saved_c_data;
01349 
01350    if (c->cdr && !ast_check_hangup(c))
01351       ast_cdr_setapp(c->cdr, app->name, data);
01352 
01353    /* save channel values */
01354    saved_c_appl= c->appl;
01355    saved_c_data= c->data;
01356 
01357    c->appl = app->name;
01358    c->data = data;
01359    ast_cel_report_event(c, AST_CEL_APP_START, NULL, NULL, NULL);
01360 
01361    if (app->module)
01362       u = __ast_module_user_add(app->module, c);
01363    if (strcasecmp(app->name, "system") && !ast_strlen_zero(data) &&
01364          strchr(data, '|') && !strchr(data, ',') && !ast_opt_dont_warn) {
01365       ast_log(LOG_WARNING, "The application delimiter is now the comma, not "
01366          "the pipe.  Did you forget to convert your dialplan?  (%s(%s))\n",
01367          app->name, (char *) data);
01368    }
01369    res = app->execute(c, S_OR(data, ""));
01370    if (app->module && u)
01371       __ast_module_user_remove(app->module, u);
01372    ast_cel_report_event(c, AST_CEL_APP_END, NULL, NULL, NULL);
01373    /* restore channel values */
01374    c->appl = saved_c_appl;
01375    c->data = saved_c_data;
01376    return res;
01377 }

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

References ast_context::alts, ast_autoservice_start(), ast_autoservice_stop(), ast_copy_string(), ast_hashtab_lookup(), AST_LIST_TRAVERSE, ast_log(), AST_PBX_MAX_STACK, ast_str_buffer(), ast_str_size(), ast_str_thread_get(), ast_strdupa, ast_strlen_zero(), ast_walk_context_extensions(), ast_switch::canmatch, scoreboard::canmatch_exten, contexts_table, create_match_char_tree(), ast_sw::data, pbx_find_info::data, E_CANMATCH, E_FINDLABEL, E_MATCHMORE, ast_sw::eval, ast_switch::exists, ast_exten::exten, scoreboard::exten, extenpatternmatchnew, extension_match_core(), pbx_find_info::foundcontext, include_valid(), ast_context::includes, pbx_find_info::incstack, ast_exten::label, scoreboard::last_char, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, match(), matchcid(), ast_switch::matchmore, ast_context::name, ast_sw::name, fake_context::name, new_find_extension(), ast_include::next, scoreboard::node, overrideswitch, ast_context::pattern_tree, pbx_find_extension(), pbx_findswitch(), pbx_substitute_variables_helper(), ast_exten::priority, ast_include::rname, ast_context::root_table, pbx_find_info::stacklen, pbx_find_info::status, STATUS_NO_CONTEXT, STATUS_NO_EXTENSION, STATUS_NO_LABEL, STATUS_NO_PRIORITY, STATUS_SUCCESS, strsep(), switch_data, pbx_find_info::swo, scoreboard::total_length, scoreboard::total_specificity, and trie_find_next_match().

Referenced by ast_hint_extension_nolock(), ast_merge_contexts_and_delete(), check_goto(), check_pval_item(), pbx_extension_helper(), pbx_find_extension(), and register_peer_exten().

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

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

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

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

01386 {
01387    struct ast_app *tmp;
01388 
01389    AST_RWLIST_RDLOCK(&apps);
01390    AST_RWLIST_TRAVERSE(&apps, tmp, list) {
01391       if (!strcasecmp(tmp->name, app))
01392          break;
01393    }
01394    AST_RWLIST_UNLOCK(&apps);
01395 
01396    return tmp;
01397 }

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

02919 {
02920    struct ast_str *str = ast_str_create(16);
02921    const char *cret;
02922 
02923    cret = ast_str_retrieve_variable(&str, 0, c, headp, var);
02924    ast_copy_string(workspace, ast_str_buffer(str), workspacelen);
02925    *ret = cret ? workspace : NULL;
02926    ast_free(str);
02927 }

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

References autofallthrough.

Referenced by pbx_load_module().

04945 {
04946    int oldval = autofallthrough;
04947    autofallthrough = newval;
04948    return oldval;
04949 }

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

References extenpatternmatchnew.

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

04952 {
04953    int oldval = extenpatternmatchnew;
04954    extenpatternmatchnew = newval;
04955    return oldval;
04956 }

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

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

Referenced by pbx_load_module().

04959 {
04960    if (overrideswitch) {
04961       ast_free(overrideswitch);
04962    }
04963    if (!ast_strlen_zero(newval)) {
04964       overrideswitch = ast_strdup(newval);
04965    } else {
04966       overrideswitch = NULL;
04967    }
04968 }

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

References ast_channel_release(), ast_copy_string(), ast_debug, ast_dummy_channel_alloc(), ast_expr(), ast_func_read(), ast_log(), ast_strlen_zero(), len(), LOG_ERROR, LOG_WARNING, parse_variable_name(), pbx_retrieve_variable(), pbx_substitute_variables_helper_full(), substring(), var, VAR_BUF_SIZE, and ast_channel::varshead.

Referenced by pbx_substitute_variables_helper(), pbx_substitute_variables_helper_full(), and pbx_substitute_variables_varshead().

03722 {
03723    /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!!  */
03724    char *cp4 = NULL;
03725    const char *tmp, *whereweare, *orig_cp2 = cp2;
03726    int length, offset, offset2, isfunction;
03727    char *workspace = NULL;
03728    char *ltmp = NULL, *var = NULL;
03729    char *nextvar, *nextexp, *nextthing;
03730    char *vars, *vare;
03731    int pos, brackets, needsub, len;
03732 
03733    *cp2 = 0; /* just in case nothing ends up there */
03734    whereweare=tmp=cp1;
03735    while (!ast_strlen_zero(whereweare) && count) {
03736       /* Assume we're copying the whole remaining string */
03737       pos = strlen(whereweare);
03738       nextvar = NULL;
03739       nextexp = NULL;
03740       nextthing = strchr(whereweare, '$');
03741       if (nextthing) {
03742          switch (nextthing[1]) {
03743          case '{':
03744             nextvar = nextthing;
03745             pos = nextvar - whereweare;
03746             break;
03747          case '[':
03748             nextexp = nextthing;
03749             pos = nextexp - whereweare;
03750             break;
03751          default:
03752             pos = 1;
03753          }
03754       }
03755 
03756       if (pos) {
03757          /* Can't copy more than 'count' bytes */
03758          if (pos > count)
03759             pos = count;
03760 
03761          /* Copy that many bytes */
03762          memcpy(cp2, whereweare, pos);
03763 
03764          count -= pos;
03765          cp2 += pos;
03766          whereweare += pos;
03767          *cp2 = 0;
03768       }
03769 
03770       if (nextvar) {
03771          /* We have a variable.  Find the start and end, and determine
03772             if we are going to have to recursively call ourselves on the
03773             contents */
03774          vars = vare = nextvar + 2;
03775          brackets = 1;
03776          needsub = 0;
03777 
03778          /* Find the end of it */
03779          while (brackets && *vare) {
03780             if ((vare[0] == '$') && (vare[1] == '{')) {
03781                needsub++;
03782             } else if (vare[0] == '{') {
03783                brackets++;
03784             } else if (vare[0] == '}') {
03785                brackets--;
03786             } else if ((vare[0] == '$') && (vare[1] == '['))
03787                needsub++;
03788             vare++;
03789          }
03790          if (brackets)
03791             ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n");
03792          len = vare - vars - 1;
03793 
03794          /* Skip totally over variable string */
03795          whereweare += (len + 3);
03796 
03797          if (!var)
03798             var = alloca(VAR_BUF_SIZE);
03799 
03800          /* Store variable name (and truncate) */
03801          ast_copy_string(var, vars, len + 1);
03802 
03803          /* Substitute if necessary */
03804          if (needsub) {
03805             size_t used;
03806             if (!ltmp)
03807                ltmp = alloca(VAR_BUF_SIZE);
03808 
03809             pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used);
03810             vars = ltmp;
03811          } else {
03812             vars = var;
03813          }
03814 
03815          if (!workspace)
03816             workspace = alloca(VAR_BUF_SIZE);
03817 
03818          workspace[0] = '\0';
03819 
03820          parse_variable_name(vars, &offset, &offset2, &isfunction);
03821          if (isfunction) {
03822             /* Evaluate function */
03823             if (c || !headp)
03824                cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
03825             else {
03826                struct varshead old;
03827                struct ast_channel *c = ast_dummy_channel_alloc();
03828                if (c) {
03829                   memcpy(&old, &c->varshead, sizeof(old));
03830                   memcpy(&c->varshead, headp, sizeof(c->varshead));
03831                   cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
03832                   /* Don't deallocate the varshead that was passed in */
03833                   memcpy(&c->varshead, &old, sizeof(c->varshead));
03834                   c = ast_channel_release(c);
03835                } else {
03836                   ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution.  Function results may be blank.\n");
03837                }
03838             }
03839             ast_debug(2, "Function result is '%s'\n", cp4 ? cp4 : "(null)");
03840          } else {
03841             /* Retrieve variable value */
03842             pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp);
03843          }
03844          if (cp4) {
03845             cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE);
03846 
03847             length = strlen(cp4);
03848             if (length > count)
03849                length = count;
03850             memcpy(cp2, cp4, length);
03851             count -= length;
03852             cp2 += length;
03853             *cp2 = 0;
03854          }
03855       } else if (nextexp) {
03856          /* We have an expression.  Find the start and end, and determine
03857             if we are going to have to recursively call ourselves on the
03858             contents */
03859          vars = vare = nextexp + 2;
03860          brackets = 1;
03861          needsub = 0;
03862 
03863          /* Find the end of it */
03864          while (brackets && *vare) {
03865             if ((vare[0] == '$') && (vare[1] == '[')) {
03866                needsub++;
03867                brackets++;
03868                vare++;
03869             } else if (vare[0] == '[') {
03870                brackets++;
03871             } else if (vare[0] == ']') {
03872                brackets--;
03873             } else if ((vare[0] == '$') && (vare[1] == '{')) {
03874                needsub++;
03875                vare++;
03876             }
03877             vare++;
03878          }
03879          if (brackets)
03880             ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n");
03881          len = vare - vars - 1;
03882 
03883          /* Skip totally over expression */
03884          whereweare += (len + 3);
03885 
03886          if (!var)
03887             var = alloca(VAR_BUF_SIZE);
03888 
03889          /* Store variable name (and truncate) */
03890          ast_copy_string(var, vars, len + 1);
03891 
03892          /* Substitute if necessary */
03893          if (needsub) {
03894             size_t used;
03895             if (!ltmp)
03896                ltmp = alloca(VAR_BUF_SIZE);
03897 
03898             pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used);
03899             vars = ltmp;
03900          } else {
03901             vars = var;
03902          }
03903 
03904          length = ast_expr(vars, cp2, count, c);
03905 
03906          if (length) {
03907             ast_debug(1, "Expression result is '%s'\n", cp2);
03908             count -= length;
03909             cp2 += length;
03910             *cp2 = 0;
03911          }
03912       }
03913    }
03914    *used = cp2 - orig_cp2;
03915 }

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

Definition at line 3923 of file pbx.c.

References pbx_substitute_variables_helper_full().

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

03924 {
03925    size_t used;
03926    pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count, &used);
03927 }


Generated on Wed Oct 28 13:33:16 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6