Mon Jun 27 16:51:17 2011

Asterisk developer's documentation


pbx.h File Reference

Core PBX routines and definitions. More...

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

Go to the source code of this file.

Data Structures

struct  ast_custom_function
 Data structure associated with a custom dialplan function. More...
struct  ast_pbx
struct  ast_pbx_args
 Options for ast_pbx_run(). More...
struct  ast_switch
struct  ast_timing
struct  pbx_find_info
#define AST_PBX_ERROR   1
#define AST_PBX_HANGUP   -1
 Special return values from applications to the PBX.
#define AST_PBX_INCOMPLETE   12
#define AST_PBX_OK   0
int ast_context_remove_extension (const char *context, const char *extension, int priority, const char *registrar)
 Simply remove extension from context.
int ast_context_remove_extension2 (struct ast_context *con, const char *extension, int priority, const char *registrar, int already_locked)
 This functionc locks given context, search for the right extension and fires out all peer in this extensions with given priority. If priority is set to 0, all peers are removed. After that, unlock context and return.
int ast_context_remove_extension_callerid (const char *context, const char *extension, int priority, const char *callerid, int matchcid, const char *registrar)
int ast_context_remove_extension_callerid2 (struct ast_context *con, const char *extension, int priority, const char *callerid, int matchcid, const char *registrar, int already_locked)
Functions for returning values from structures

const char * ast_get_context_name (struct ast_context *con)
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 ...

ast_extenast_walk_context_extensions (struct ast_context *con, struct ast_exten *priority)
ast_ignorepatast_walk_context_ignorepats (struct ast_context *con, struct ast_ignorepat *ip)
ast_includeast_walk_context_includes (struct ast_context *con, struct ast_include *inc)
ast_swast_walk_context_switches (struct ast_context *con, struct ast_sw *sw)
ast_contextast_walk_contexts (struct ast_context *con)
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)

Defines

#define ast_custom_function_register(acf)   __ast_custom_function_register(acf, ast_module_info->self)
 Register a custom function.
#define AST_MAX_APP   32
#define AST_PBX_GOTO_FAILED   -3
#define AST_PBX_KEEP   0
#define AST_PBX_MAX_STACK   128
#define AST_PBX_REPLACE   1
#define PRIORITY_HINT   -1
#define STATUS_NO_CONTEXT   1
#define STATUS_NO_EXTENSION   2
#define STATUS_NO_LABEL   4
#define STATUS_NO_PRIORITY   3
#define STATUS_SUCCESS   5

Typedefs

typedef 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
}

Functions

int __ast_custom_function_register (struct ast_custom_function *acf, struct ast_module *mod)
 Register a custom function.
int ast_active_calls (void)
 Retrieve the number of active calls.
int ast_add_extension (const char *context, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar)
 Add and extension to an extension context.
int ast_add_extension2 (struct ast_context *con, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar)
 Add an extension to an extension context, this time with an ast_context *.
int ast_async_goto (struct ast_channel *chan, const char *context, const char *exten, int priority)
 Set the channel to next execute the specified dialplan location.
int ast_async_goto_by_name (const char *chan, const char *context, const char *exten, int priority)
 Set the channel to next execute the specified dialplan location.
int ast_async_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority)
int ast_async_parseable_goto (struct ast_channel *chan, const char *goto_string)
int ast_build_timing (struct ast_timing *i, const char *info)
 Construct a timing bitmap, for use in time-based conditionals.
int ast_canmatch_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
 Looks for a valid matching extension.
int ast_check_timing (const struct ast_timing *i)
 Evaluate a pre-constructed bitmap as to whether the current time falls within the range specified.
int ast_check_timing2 (const struct ast_timing *i, const struct timeval tv)
 Evaluate a pre-constructed bitmap as to whether a particular time falls within the range specified.
char * ast_complete_applications (const char *line, const char *word, int state)
 Command completion for the list of installed applications.
int ast_context_add_ignorepat (const char *context, const char *ignorepat, const char *registrar)
 Add an ignorepat.
int ast_context_add_ignorepat2 (struct ast_context *con, const char *ignorepat, const char *registrar)
int ast_context_add_include (const char *context, const char *include, const char *registrar)
 Add a context include.
int ast_context_add_include2 (struct ast_context *con, const char *include, const char *registrar)
 Add a context include.
int ast_context_add_switch (const char *context, const char *sw, const char *data, int eval, const char *registrar)
 Add a switch.
int ast_context_add_switch2 (struct ast_context *con, const char *sw, const char *data, int eval, const char *registrar)
 Adds a switch (first param is a ast_context).
void ast_context_destroy (struct ast_context *con, const char *registrar)
 Destroy a context (matches the specified context (or ANY context if NULL).
ast_contextast_context_find (const char *name)
 Find a context.
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.
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, format_t format, void *data, int timeout, const char *app, const char *appdata, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel)
int ast_pbx_outgoing_exten (const char *type, format_t format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel)
enum ast_pbx_result ast_pbx_run (struct ast_channel *c)
 Execute the PBX in the current thread.
enum ast_pbx_result ast_pbx_run_args (struct ast_channel *c, struct ast_pbx_args *args)
 Execute the PBX in the current thread.
enum ast_pbx_result ast_pbx_start (struct ast_channel *c)
 Create a new thread and start the PBX.
int ast_processed_calls (void)
 Retrieve the total number of calls processed through the PBX since last restart.
int ast_rdlock_context (struct ast_context *con)
 Read locks a given context.
int ast_rdlock_contexts (void)
 Read locks the context list.
int ast_register_switch (struct ast_switch *sw)
 Register an alternative dialplan switch.
int ast_spawn_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid, int *found, int combined_find_spawn)
 Launch a new extension (i.e. new stack).
int ast_str_get_hint (struct ast_str **hint, ssize_t hintsize, struct ast_str **name, ssize_t namesize, struct ast_channel *c, const char *context, const char *exten)
 If an extension hint exists, return non-zero.
int ast_unlock_context (struct ast_context *con)
int ast_unlock_contexts (void)
 Unlocks contexts.
void ast_unregister_switch (struct ast_switch *sw)
 Unregister an alternative switch.
int ast_wrlock_context (struct ast_context *con)
 Write locks a given context.
int ast_wrlock_contexts (void)
 Write locks the context list.
void pbx_builtin_clear_globals (void)
const char * pbx_builtin_getvar_helper (struct ast_channel *chan, const char *name)
 Return a pointer to the value of the corresponding channel variable.
void pbx_builtin_pushvar_helper (struct ast_channel *chan, const char *name, const char *value)
 Add a variable to the channel variable stack, without removing any previously set value.
int pbx_builtin_raise_exception (struct ast_channel *chan, const char *data)
int pbx_builtin_serialize_variables (struct ast_channel *chan, struct ast_str **buf)
 Create a human-readable string, specifying all variables and their corresponding values.
int pbx_builtin_setvar (struct ast_channel *chan, const char *data)
 Parse and set a single channel variable, where the name and value are separated with an '=' character.
int pbx_builtin_setvar_helper (struct ast_channel *chan, const char *name, const char *value)
 Add a variable to the channel variable stack, removing the most recently set value for the same name.
int pbx_builtin_setvar_multiple (struct ast_channel *chan, const char *data)
 Parse and set multiple channel variables, where the pairs are separated by the ',' character, and name and value are separated with an '=' character.
int pbx_checkcondition (const char *condition)
 Evaluate a condition.
int pbx_exec (struct ast_channel *c, struct ast_app *app, const char *data)
 Execute an application.
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)
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)


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

Referenced by load_module(), and reload().

#define AST_MAX_APP   32

Max length of an application

Definition at line 39 of file pbx.h.

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

#define AST_PBX_ERROR   1

Jump to the 'e' exten

Definition at line 49 of file pbx.h.

#define AST_PBX_GOTO_FAILED   -3

Definition at line 41 of file pbx.h.

Referenced by __ast_goto_if_exists(), and dial_exec_full().

#define AST_PBX_HANGUP   -1

Special return values from applications to the PBX.

Jump to the 'h' exten

Definition at line 47 of file pbx.h.

#define AST_PBX_INCOMPLETE   12

Return to PBX matching, allowing more digits for the extension

Definition at line 50 of file pbx.h.

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

#define AST_PBX_KEEP   0

Definition at line 42 of file pbx.h.

#define AST_PBX_MAX_STACK   128

Definition at line 1201 of file pbx.h.

#define AST_PBX_OK   0

No errors

Definition at line 48 of file pbx.h.

#define AST_PBX_REPLACE   1

Definition at line 43 of file pbx.h.

#define PRIORITY_HINT   -1

Special Priority for a hint

Definition at line 53 of file pbx.h.

Referenced by add_extensions(), ast_add_extension2_lockopt(), ast_hint_extension_nolock(), ast_merge_contexts_and_delete(), destroy_exten(), destroy_station(), handle_cli_dialplan_add_extension(), handle_cli_dialplan_remove_extension(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), park_add_hints(), and print_ext().

#define STATUS_NO_CONTEXT   1

Definition at line 1196 of file pbx.h.

#define STATUS_NO_EXTENSION   2

Definition at line 1197 of file pbx.h.

#define STATUS_NO_LABEL   4

Definition at line 1199 of file pbx.h.

#define STATUS_NO_PRIORITY   3

Definition at line 1198 of file pbx.h.

#define STATUS_SUCCESS   5

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

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

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

Data structure associated with an Asterisk switch

Definition at line 111 of file pbx.h.


Enumeration Type Documentation

enum ast_extension_states

Extension states.

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

Definition at line 60 of file pbx.h.

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

enum ast_pbx_result

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

00286                     {
00287    AST_PBX_SUCCESS = 0,
00288    AST_PBX_FAILED = -1,
00289    AST_PBX_CALL_LIMIT = -2,
00290 };

enum ext_match_t

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 

Definition at line 1187 of file pbx.h.

01187                  {
01188    E_MATCHMORE =  0x00, /* extension can match but only with more 'digits' */
01189    E_CANMATCH =   0x01, /* extension can match with or without more 'digits' */
01190    E_MATCH =   0x02, /* extension is an exact match */
01191    E_MATCH_MASK = 0x03, /* mask for the argument to extension_match_core() */
01192    E_SPAWN =   0x12, /* want to spawn an extension. Requires exact match */
01193    E_FINDLABEL =  0x22  /* returns the priority for a given label. Requires exact match */
01194 };


Function Documentation

int __ast_custom_function_register ( struct ast_custom_function acf,
struct ast_module mod 
)

Register a custom function.

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

03414 {
03415    struct ast_custom_function *cur;
03416    char tmps[80];
03417 
03418    if (!acf) {
03419       return -1;
03420    }
03421 
03422    acf->mod = mod;
03423 #ifdef AST_XML_DOCS
03424    acf->docsrc = AST_STATIC_DOC;
03425 #endif
03426 
03427    if (acf_retrieve_docs(acf)) {
03428       return -1;
03429    }
03430 
03431    AST_RWLIST_WRLOCK(&acf_root);
03432 
03433    AST_RWLIST_TRAVERSE(&acf_root, cur, acflist) {
03434       if (!strcmp(acf->name, cur->name)) {
03435          ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name);
03436          AST_RWLIST_UNLOCK(&acf_root);
03437          return -1;
03438       }
03439    }
03440 
03441    /* Store in alphabetical order */
03442    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) {
03443       if (strcasecmp(acf->name, cur->name) < 0) {
03444          AST_RWLIST_INSERT_BEFORE_CURRENT(acf, acflist);
03445          break;
03446       }
03447    }
03448    AST_RWLIST_TRAVERSE_SAFE_END;
03449 
03450    if (!cur) {
03451       AST_RWLIST_INSERT_TAIL(&acf_root, acf, acflist);
03452    }
03453 
03454    AST_RWLIST_UNLOCK(&acf_root);
03455 
03456    ast_verb(2, "Registered custom function '%s'\n", term_color(tmps, acf->name, COLOR_BRCYAN, 0, sizeof(tmps)));
03457 
03458    return 0;
03459 }

int ast_active_calls ( void   ) 

Retrieve the number of active calls.

Definition at line 5067 of file pbx.c.

References countcalls.

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

05068 {
05069    return countcalls;
05070 }

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

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

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

07742 {
07743    int ret = -1;
07744    struct ast_context *c = find_context_locked(context);
07745 
07746    if (c) {
07747       ret = ast_add_extension2(c, replace, extension, priority, label, callerid,
07748          application, data, datad, registrar);
07749       ast_unlock_contexts();
07750    }
07751 
07752    return ret;
07753 }

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

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

References ast_add_extension2_lockopt().

Referenced by add_extensions(), ast_add_extension(), build_parkinglot(), context_merge(), load_module(), manage_parkinglot(), park_call_full(), and pbx_load_users().

08064 {
08065    return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid, application, data, datad, registrar, 1, 1);
08066 }

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 7778 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(), console_transfer(), dahdi_handle_dtmf(), handle_request_bye(), handle_request_refer(), my_handle_dtmf(), pbx_parseable_goto(), process_ast_dsp(), process_sdp(), sip_read(), and socket_process().

07779 {
07780    int res = 0;
07781 
07782    ast_channel_lock(chan);
07783 
07784    if (chan->pbx) { /* This channel is currently in the PBX */
07785       ast_explicit_goto(chan, context, exten, priority + 1);
07786       ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO);
07787    } else {
07788       /* In order to do it when the channel doesn't really exist within
07789          the PBX, we have to make a new channel, masquerade, and start the PBX
07790          at the new location */
07791       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);
07792       if (!tmpchan) {
07793          res = -1;
07794       } else {
07795          if (chan->cdr) {
07796             ast_cdr_discard(tmpchan->cdr);
07797             tmpchan->cdr = ast_cdr_dup(chan->cdr);  /* share the love */
07798          }
07799          /* Make formats okay */
07800          tmpchan->readformat = chan->readformat;
07801          tmpchan->writeformat = chan->writeformat;
07802          /* Setup proper location */
07803          ast_explicit_goto(tmpchan,
07804             S_OR(context, chan->context), S_OR(exten, chan->exten), priority);
07805 
07806          /* Masquerade into temp channel */
07807          if (ast_channel_masquerade(tmpchan, chan)) {
07808             /* Failed to set up the masquerade.  It's probably chan_local
07809              * in the middle of optimizing itself out.  Sad. :( */
07810             ast_hangup(tmpchan);
07811             tmpchan = NULL;
07812             res = -1;
07813          } else {
07814             /* it may appear odd to unlock chan here since the masquerade is on
07815              * tmpchan, but no channel locks should be held when doing a masquerade
07816              * since a masquerade requires a lock on the channels ao2 container. */
07817             ast_channel_unlock(chan);
07818             ast_do_masquerade(tmpchan);
07819             ast_channel_lock(chan);
07820             /* Start the PBX going on our stolen channel */
07821             if (ast_pbx_start(tmpchan)) {
07822                ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name);
07823                ast_hangup(tmpchan);
07824                res = -1;
07825             }
07826          }
07827       }
07828    }
07829    ast_channel_unlock(chan);
07830    return res;
07831 }

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

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

07834 {
07835    struct ast_channel *chan;
07836    int res = -1;
07837 
07838    if ((chan = ast_channel_get_by_name(channame))) {
07839       res = ast_async_goto(chan, context, exten, priority);
07840       chan = ast_channel_unref(chan);
07841    }
07842 
07843    return res;
07844 }

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

References __ast_goto_if_exists().

10133 {
10134    return __ast_goto_if_exists(chan, context, exten, priority, 1);
10135 }

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

References pbx_parseable_goto().

Referenced by asyncgoto_exec(), and handle_redirect().

10198 {
10199    return pbx_parseable_goto(chan, goto_string, 1);
10200 }

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

07370 {
07371    char *info_save, *info;
07372    int j, num_fields, last_sep = -1;
07373 
07374    /* Check for empty just in case */
07375    if (ast_strlen_zero(info_in)) {
07376       return 0;
07377    }
07378 
07379    /* make a copy just in case we were passed a static string */
07380    info_save = info = ast_strdupa(info_in);
07381 
07382    /* count the number of fields in the timespec */
07383    for (j = 0, num_fields = 1; info[j] != '\0'; j++) {
07384       if (info[j] == ',') {
07385          last_sep = j;
07386          num_fields++;
07387       }
07388    }
07389 
07390    /* save the timezone, if it is specified */
07391    if (num_fields == 5) {
07392       i->timezone = ast_strdup(info + last_sep + 1);
07393    } else {
07394       i->timezone = NULL;
07395    }
07396 
07397    /* Assume everything except time */
07398    i->monthmask = 0xfff;   /* 12 bits */
07399    i->daymask = 0x7fffffffU; /* 31 bits */
07400    i->dowmask = 0x7f; /* 7 bits */
07401    /* on each call, use strsep() to move info to the next argument */
07402    get_timerange(i, strsep(&info, "|,"));
07403    if (info)
07404       i->dowmask = get_range(strsep(&info, "|,"), 7, days, "day of week");
07405    if (info)
07406       i->daymask = get_range(strsep(&info, "|,"), 31, NULL, "day");
07407    if (info)
07408       i->monthmask = get_range(strsep(&info, "|,"), 12, months, "month");
07409    return 1;
07410 }

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

References E_CANMATCH, and pbx_extension_helper().

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

04597 {
04598    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0);
04599 }

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

References ast_check_timing2(), and ast_tvnow().

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

07413 {
07414    return ast_check_timing2(i, ast_tvnow());
07415 }

int ast_check_timing2 ( const struct ast_timing i,
const struct timeval  tv 
)

Evaluate a pre-constructed bitmap as to whether a particular time falls within the range specified.

Parameters:
i Pointer to an ast_timing structure.
tv Specified time
Return values:
Returns 1, if the time matches or 0, if the time falls outside of the specified range.

Definition at line 7417 of file pbx.c.

References ast_localtime(), ast_log(), ast_timing::daymask, ast_timing::dowmask, LOG_WARNING, ast_timing::minmask, ast_timing::monthmask, ast_timing::timezone, ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, and ast_tm::tm_wday.

Referenced by ast_check_timing(), and pbx_builtin_gotoiftime().

07418 {
07419    struct ast_tm tm;
07420 
07421    ast_localtime(&tv, &tm, i->timezone);
07422 
07423    /* If it's not the right month, return */
07424    if (!(i->monthmask & (1 << tm.tm_mon)))
07425       return 0;
07426 
07427    /* If it's not that time of the month.... */
07428    /* Warning, tm_mday has range 1..31! */
07429    if (!(i->daymask & (1 << (tm.tm_mday-1))))
07430       return 0;
07431 
07432    /* If it's not the right day of the week */
07433    if (!(i->dowmask & (1 << tm.tm_wday)))
07434       return 0;
07435 
07436    /* Sanity check the hour just to be safe */
07437    if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) {
07438       ast_log(LOG_WARNING, "Insane time...\n");
07439       return 0;
07440    }
07441 
07442    /* Now the tough part, we calculate if it fits
07443       in the right time based on min/hour */
07444    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))))
07445       return 0;
07446 
07447    /* If we got this far, then we're good */
07448    return 1;
07449 }

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

References app, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strdup, and ast_app::list.

Referenced by handle_orig(), and handle_show_application().

10203 {
10204    struct ast_app *app = NULL;
10205    int which = 0;
10206    char *ret = NULL;
10207    size_t wordlen = strlen(word);
10208 
10209    AST_RWLIST_RDLOCK(&apps);
10210    AST_RWLIST_TRAVERSE(&apps, app, list) {
10211       if (!strncasecmp(word, app->name, wordlen) && ++which > state) {
10212          ret = ast_strdup(app->name);
10213          break;
10214       }
10215    }
10216    AST_RWLIST_UNLOCK(&apps);
10217 
10218    return ret;
10219 }

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

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

Referenced by handle_cli_dialplan_add_ignorepat().

07652 {
07653    int ret = -1;
07654    struct ast_context *c = find_context_locked(context);
07655 
07656    if (c) {
07657       ret = ast_context_add_ignorepat2(c, value, registrar);
07658       ast_unlock_contexts();
07659    }
07660    return ret;
07661 }

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

Definition at line 7663 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_context_add_ignorepat(), and context_merge_incls_swits_igps_other_registrars().

07664 {
07665    struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL;
07666    int length;
07667    char *pattern;
07668    length = sizeof(struct ast_ignorepat);
07669    length += strlen(value) + 1;
07670    if (!(ignorepat = ast_calloc(1, length)))
07671       return -1;
07672    /* The cast to char * is because we need to write the initial value.
07673     * The field is not supposed to be modified otherwise.  Also, gcc 4.2
07674     * sees the cast as dereferencing a type-punned pointer and warns about
07675     * it.  This is the workaround (we're telling gcc, yes, that's really
07676     * what we wanted to do).
07677     */
07678    pattern = (char *) ignorepat->pattern;
07679    strcpy(pattern, value);
07680    ignorepat->next = NULL;
07681    ignorepat->registrar = registrar;
07682    ast_wrlock_context(con);
07683    for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) {
07684       ignorepatl = ignorepatc;
07685       if (!strcasecmp(ignorepatc->pattern, value)) {
07686          /* Already there */
07687          ast_unlock_context(con);
07688          errno = EEXIST;
07689          return -1;
07690       }
07691    }
07692    if (ignorepatl)
07693       ignorepatl->next = ignorepat;
07694    else
07695       con->ignorepats = ignorepat;
07696    ast_unlock_context(con);
07697    return 0;
07698 
07699 }

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

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

Referenced by handle_cli_dialplan_add_include().

07199 {
07200    int ret = -1;
07201    struct ast_context *c = find_context_locked(context);
07202 
07203    if (c) {
07204       ret = ast_context_add_include2(c, include, registrar);
07205       ast_unlock_contexts();
07206    }
07207    return ret;
07208 }

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 7466 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_context_add_include(), and context_merge_incls_swits_igps_other_registrars().

07468 {
07469    struct ast_include *new_include;
07470    char *c;
07471    struct ast_include *i, *il = NULL; /* include, include_last */
07472    int length;
07473    char *p;
07474 
07475    length = sizeof(struct ast_include);
07476    length += 2 * (strlen(value) + 1);
07477 
07478    /* allocate new include structure ... */
07479    if (!(new_include = ast_calloc(1, length)))
07480       return -1;
07481    /* Fill in this structure. Use 'p' for assignments, as the fields
07482     * in the structure are 'const char *'
07483     */
07484    p = new_include->stuff;
07485    new_include->name = p;
07486    strcpy(p, value);
07487    p += strlen(value) + 1;
07488    new_include->rname = p;
07489    strcpy(p, value);
07490    /* Strip off timing info, and process if it is there */
07491    if ( (c = strchr(p, ',')) ) {
07492       *c++ = '\0';
07493       new_include->hastime = ast_build_timing(&(new_include->timing), c);
07494    }
07495    new_include->next      = NULL;
07496    new_include->registrar = registrar;
07497 
07498    ast_wrlock_context(con);
07499 
07500    /* ... go to last include and check if context is already included too... */
07501    for (i = con->includes; i; i = i->next) {
07502       if (!strcasecmp(i->name, new_include->name)) {
07503          ast_destroy_timing(&(new_include->timing));
07504          ast_free(new_include);
07505          ast_unlock_context(con);
07506          errno = EEXIST;
07507          return -1;
07508       }
07509       il = i;
07510    }
07511 
07512    /* ... include new context into context list, unlock, return */
07513    if (il)
07514       il->next = new_include;
07515    else
07516       con->includes = new_include;
07517    ast_verb(3, "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con));
07518 
07519    ast_unlock_context(con);
07520 
07521    return 0;
07522 }

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

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

07530 {
07531    int ret = -1;
07532    struct ast_context *c = find_context_locked(context);
07533 
07534    if (c) { /* found, add switch to this context */
07535       ret = ast_context_add_switch2(c, sw, data, eval, registrar);
07536       ast_unlock_contexts();
07537    }
07538    return ret;
07539 }

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 7548 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, store_hint::list, ast_sw::name, ast_sw::registrar, and ast_sw::stuff.

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

07550 {
07551    struct ast_sw *new_sw;
07552    struct ast_sw *i;
07553    int length;
07554    char *p;
07555 
07556    length = sizeof(struct ast_sw);
07557    length += strlen(value) + 1;
07558    if (data)
07559       length += strlen(data);
07560    length++;
07561 
07562    /* allocate new sw structure ... */
07563    if (!(new_sw = ast_calloc(1, length)))
07564       return -1;
07565    /* ... fill in this structure ... */
07566    p = new_sw->stuff;
07567    new_sw->name = p;
07568    strcpy(new_sw->name, value);
07569    p += strlen(value) + 1;
07570    new_sw->data = p;
07571    if (data) {
07572       strcpy(new_sw->data, data);
07573       p += strlen(data) + 1;
07574    } else {
07575       strcpy(new_sw->data, "");
07576       p++;
07577    }
07578    new_sw->eval     = eval;
07579    new_sw->registrar = registrar;
07580 
07581    /* ... try to lock this context ... */
07582    ast_wrlock_context(con);
07583 
07584    /* ... go to last sw and check if context is already swd too... */
07585    AST_LIST_TRAVERSE(&con->alts, i, list) {
07586       if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) {
07587          ast_free(new_sw);
07588          ast_unlock_context(con);
07589          errno = EEXIST;
07590          return -1;
07591       }
07592    }
07593 
07594    /* ... sw new context into context list, unlock, return */
07595    AST_LIST_INSERT_TAIL(&con->alts, new_sw, list);
07596 
07597    ast_verb(3, "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con));
07598 
07599    ast_unlock_context(con);
07600 
07601    return 0;
07602 }

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

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

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

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

02512 {
02513    struct ast_context *tmp = NULL;
02514    struct fake_context item;
02515 
02516    ast_copy_string(item.name, name, sizeof(item.name));
02517 
02518    ast_rdlock_contexts();
02519    if( contexts_table ) {
02520       tmp = ast_hashtab_lookup(contexts_table,&item);
02521    } else {
02522       while ( (tmp = ast_walk_contexts(tmp)) ) {
02523          if (!name || !strcasecmp(name, tmp->name)) {
02524             break;
02525          }
02526       }
02527    }
02528    ast_unlock_contexts();
02529    return tmp;
02530 }

struct ast_context* ast_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.

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 6843 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, name, fake_context::name, ast_context::name, ast_context::next, ast_context::refcount, ast_context::registrar, ast_context::root, and ast_context::root_table.

Referenced by build_parkinglot(), config_parse_variables(), context_merge(), load_module(), lua_register_switches(), manage_parkinglot(), park_call_full(), pbx_load_config(), pbx_load_users(), and set_config().

06844 {
06845    struct ast_context *tmp, **local_contexts;
06846    struct fake_context search;
06847    int length = sizeof(struct ast_context) + strlen(name) + 1;
06848 
06849    if (!contexts_table) {
06850       contexts_table = ast_hashtab_create(17,
06851                                  ast_hashtab_compare_contexts,
06852                                  ast_hashtab_resize_java,
06853                                  ast_hashtab_newsize_java,
06854                                  ast_hashtab_hash_contexts,
06855                                  0);
06856    }
06857 
06858    ast_copy_string(search.name, name, sizeof(search.name));
06859    if (!extcontexts) {
06860       ast_rdlock_contexts();
06861       local_contexts = &contexts;
06862       tmp = ast_hashtab_lookup(contexts_table, &search);
06863       ast_unlock_contexts();
06864       if (tmp) {
06865          tmp->refcount++;
06866          return tmp;
06867       }
06868    } else { /* local contexts just in a linked list; search there for the new context; slow, linear search, but not frequent */
06869       local_contexts = extcontexts;
06870       tmp = ast_hashtab_lookup(exttable, &search);
06871       if (tmp) {
06872          tmp->refcount++;
06873          return tmp;
06874       }
06875    }
06876 
06877    if ((tmp = ast_calloc(1, length))) {
06878       ast_rwlock_init(&tmp->lock);
06879       ast_mutex_init(&tmp->macrolock);
06880       strcpy(tmp->name, name);
06881       tmp->root = NULL;
06882       tmp->root_table = NULL;
06883       tmp->registrar = ast_strdup(registrar);
06884       tmp->includes = NULL;
06885       tmp->ignorepats = NULL;
06886       tmp->refcount = 1;
06887    } else {
06888       ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name);
06889       return NULL;
06890    }
06891 
06892    if (!extcontexts) {
06893       ast_wrlock_contexts();
06894       tmp->next = *local_contexts;
06895       *local_contexts = tmp;
06896       ast_hashtab_insert_safe(contexts_table, tmp); /*put this context into the tree */
06897       ast_unlock_contexts();
06898       ast_debug(1, "Registered context '%s'(%p) in table %p registrar: %s\n", tmp->name, tmp, contexts_table, registrar);
06899       ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar);
06900    } else {
06901       tmp->next = *local_contexts;
06902       if (exttable)
06903          ast_hashtab_insert_immediate(exttable, tmp); /*put this context into the tree */
06904 
06905       *local_contexts = tmp;
06906       ast_debug(1, "Registered context '%s'(%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar);
06907       ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar);
06908    }
06909    return tmp;
06910 }

int ast_context_lockmacro ( const char *  context  ) 

locks the macrolock in the given given context

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

05448 {
05449    struct ast_context *c = NULL;
05450    int ret = -1;
05451    struct fake_context item;
05452 
05453    ast_rdlock_contexts();
05454 
05455    ast_copy_string(item.name, context, sizeof(item.name));
05456 
05457    c = ast_hashtab_lookup(contexts_table,&item);
05458    if (c)
05459       ret = 0;
05460    ast_unlock_contexts();
05461 
05462    /* if we found context, lock macrolock */
05463    if (ret == 0) {
05464       ret = ast_mutex_lock(&c->macrolock);
05465    }
05466 
05467    return ret;
05468 }

int ast_context_remove_extension ( const char *  context,
const char *  extension,
int  priority,
const char *  registrar 
)

Simply remove extension from context.

Parameters:
context context to remove extension from
extension which extension to remove
priority priority of extension to remove (0 to remove all)
registrar registrar of the extension
This function removes an extension from a given context.

Return values:
0 on success
-1 on failure

Definition at line 5255 of file pbx.c.

References ast_context_remove_extension_callerid().

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

05256 {
05257    return ast_context_remove_extension_callerid(context, extension, priority, NULL, 0, registrar);
05258 }

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

References ast_context_remove_extension_callerid2().

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

05283 {
05284    return ast_context_remove_extension_callerid2(con, extension, priority, NULL, 0, registrar, already_locked);
05285 }

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

05261 {
05262    int ret = -1; /* default error return */
05263    struct ast_context *c = find_context_locked(context);
05264 
05265    if (c) { /* ... remove extension ... */
05266       ret = ast_context_remove_extension_callerid2(c, extension, priority, callerid, matchcallerid, registrar, 1);
05267       ast_unlock_contexts();
05268    }
05269    return ret;
05270 }

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 5287 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, destroy_exten(), exten, ast_exten::exten, ast_exten::label, LOG_ERROR, LOG_NOTICE, LOG_WARNING, ast_exten::matchcid, ast_exten::next, ast_exten::peer, ast_exten::peer_label_table, ast_exten::peer_table, ast_exten::priority, ast_exten::registrar, and match_char::x.

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

05288 {
05289    struct ast_exten *exten, *prev_exten = NULL;
05290    struct ast_exten *peer;
05291    struct ast_exten ex, *exten2, *exten3;
05292    char dummy_name[1024];
05293    struct ast_exten *previous_peer = NULL;
05294    struct ast_exten *next_peer = NULL;
05295    int found = 0;
05296 
05297    if (!already_locked)
05298       ast_wrlock_context(con);
05299 
05300    /* Handle this is in the new world */
05301 
05302    /* FIXME For backwards compatibility, if callerid==NULL, then remove ALL
05303     * peers, not just those matching the callerid. */
05304 #ifdef NEED_DEBUG
05305    ast_verb(3,"Removing %s/%s/%d%s%s from trees, registrar=%s\n", con->name, extension, priority, matchcallerid ? "/" : "", matchcallerid ? callerid : "", registrar);
05306 #endif
05307 #ifdef CONTEXT_DEBUG
05308    check_contexts(__FILE__, __LINE__);
05309 #endif
05310    /* find this particular extension */
05311    ex.exten = dummy_name;
05312    ex.matchcid = matchcallerid && !ast_strlen_zero(callerid); /* don't say match if there's no callerid */
05313    ex.cidmatch = callerid;
05314    ast_copy_string(dummy_name, extension, sizeof(dummy_name));
05315    exten = ast_hashtab_lookup(con->root_table, &ex);
05316    if (exten) {
05317       if (priority == 0) {
05318          exten2 = ast_hashtab_remove_this_object(con->root_table, exten);
05319          if (!exten2)
05320             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);
05321          if (con->pattern_tree) {
05322             struct match_char *x = add_exten_to_pattern_tree(con, exten, 1);
05323 
05324             if (x->exten) { /* this test for safety purposes */
05325                x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */
05326                x->exten = 0; /* get rid of what will become a bad pointer */
05327             } else {
05328                ast_log(LOG_WARNING,"Trying to delete an exten from a context, but the pattern tree node returned isn't a full extension\n");
05329             }
05330          }
05331       } else {
05332          ex.priority = priority;
05333          exten2 = ast_hashtab_lookup(exten->peer_table, &ex);
05334          if (exten2) {
05335 
05336             if (exten2->label) { /* if this exten has a label, remove that, too */
05337                exten3 = ast_hashtab_remove_this_object(exten->peer_label_table,exten2);
05338                if (!exten3)
05339                   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);
05340             }
05341 
05342             exten3 = ast_hashtab_remove_this_object(exten->peer_table, exten2);
05343             if (!exten3)
05344                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);
05345             if (exten2 == exten && exten2->peer) {
05346                exten2 = ast_hashtab_remove_this_object(con->root_table, exten);
05347                ast_hashtab_insert_immediate(con->root_table, exten2->peer);
05348             }
05349             if (ast_hashtab_size(exten->peer_table) == 0) {
05350                /* well, if the last priority of an exten is to be removed,
05351                   then, the extension is removed, too! */
05352                exten3 = ast_hashtab_remove_this_object(con->root_table, exten);
05353                if (!exten3)
05354                   ast_log(LOG_ERROR,"Did not remove this exten (%s) from the context root_table (%s) (priority %d)\n", exten->exten, con->name, priority);
05355                if (con->pattern_tree) {
05356                   struct match_char *x = add_exten_to_pattern_tree(con, exten, 1);
05357                   if (x->exten) { /* this test for safety purposes */
05358                      x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */
05359                      x->exten = 0; /* get rid of what will become a bad pointer */
05360                   }
05361                }
05362             }
05363          } else {
05364             ast_log(LOG_ERROR,"Could not find priority %d of exten %s in context %s!\n",
05365                   priority, exten->exten, con->name);
05366          }
05367       }
05368    } else {
05369       /* hmmm? this exten is not in this pattern tree? */
05370       ast_log(LOG_WARNING,"Cannot find extension %s in root_table in context %s\n",
05371             extension, con->name);
05372    }
05373 #ifdef NEED_DEBUG
05374    if (con->pattern_tree) {
05375       ast_log(LOG_NOTICE,"match char tree after exten removal:\n");
05376       log_match_char_tree(con->pattern_tree, " ");
05377    }
05378 #endif
05379 
05380    /* scan the extension list to find first matching extension-registrar */
05381    for (exten = con->root; exten; prev_exten = exten, exten = exten->next) {
05382       if (!strcmp(exten->exten, extension) &&
05383          (!registrar || !strcmp(exten->registrar, registrar)) &&
05384          (!matchcallerid || (!ast_strlen_zero(callerid) && !ast_strlen_zero(exten->cidmatch) && !strcmp(exten->cidmatch, callerid)) || (ast_strlen_zero(callerid) && ast_strlen_zero(exten->cidmatch))))
05385          break;
05386    }
05387    if (!exten) {
05388       /* we can't find right extension */
05389       if (!already_locked)
05390          ast_unlock_context(con);
05391       return -1;
05392    }
05393 
05394    /* scan the priority list to remove extension with exten->priority == priority */
05395    for (peer = exten, next_peer = exten->peer ? exten->peer : exten->next;
05396        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)));
05397          peer = next_peer, next_peer = next_peer ? (next_peer->peer ? next_peer->peer : next_peer->next) : NULL) {
05398       if ((priority == 0 || peer->priority == priority) &&
05399             (!callerid || !matchcallerid || (matchcallerid && !strcmp(peer->cidmatch, callerid))) &&
05400             (!registrar || !strcmp(peer->registrar, registrar) )) {
05401          found = 1;
05402 
05403          /* we are first priority extension? */
05404          if (!previous_peer) {
05405             /*
05406              * We are first in the priority chain, so must update the extension chain.
05407              * The next node is either the next priority or the next extension
05408              */
05409             struct ast_exten *next_node = peer->peer ? peer->peer : peer->next;
05410             if (peer->peer) {
05411                /* move the peer_table and peer_label_table down to the next peer, if
05412                   it is there */
05413                peer->peer->peer_table = peer->peer_table;
05414                peer->peer->peer_label_table = peer->peer_label_table;
05415                peer->peer_table = NULL;
05416                peer->peer_label_table = NULL;
05417             }
05418             if (!prev_exten) {   /* change the root... */
05419                con->root = next_node;
05420             } else {
05421                prev_exten->next = next_node; /* unlink */
05422             }
05423             if (peer->peer)   { /* update the new head of the pri list */
05424                peer->peer->next = peer->next;
05425             }
05426          } else { /* easy, we are not first priority in extension */
05427             previous_peer->peer = peer->peer;
05428          }
05429 
05430          /* now, free whole priority extension */
05431          destroy_exten(peer);
05432       } else {
05433          previous_peer = peer;
05434       }
05435    }
05436    if (!already_locked)
05437       ast_unlock_context(con);
05438    return found ? 0 : -1;
05439 }

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

Definition at line 7608 of file pbx.c.

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

Referenced by handle_cli_dialplan_remove_ignorepat().

07609 {
07610    int ret = -1;
07611    struct ast_context *c = find_context_locked(context);
07612 
07613    if (c) {
07614       ret = ast_context_remove_ignorepat2(c, ignorepat, registrar);
07615       ast_unlock_contexts();
07616    }
07617    return ret;
07618 }

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

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

07621 {
07622    struct ast_ignorepat *ip, *ipl = NULL;
07623 
07624    ast_wrlock_context(con);
07625 
07626    for (ip = con->ignorepats; ip; ip = ip->next) {
07627       if (!strcmp(ip->pattern, ignorepat) &&
07628          (!registrar || (registrar == ip->registrar))) {
07629          if (ipl) {
07630             ipl->next = ip->next;
07631             ast_free(ip);
07632          } else {
07633             con->ignorepats = ip->next;
07634             ast_free(ip);
07635          }
07636          ast_unlock_context(con);
07637          return 0;
07638       }
07639       ipl = ip;
07640    }
07641 
07642    ast_unlock_context(con);
07643    errno = EINVAL;
07644    return -1;
07645 }

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

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

Referenced by handle_cli_dialplan_remove_include().

05147 {
05148    int ret = -1;
05149    struct ast_context *c = find_context_locked(context);
05150 
05151    if (c) {
05152       /* found, remove include from this context ... */
05153       ret = ast_context_remove_include2(c, include, registrar);
05154       ast_unlock_contexts();
05155    }
05156    return ret;
05157 }

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

Removes an include by an ast_context structure.

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

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

05169 {
05170    struct ast_include *i, *pi = NULL;
05171    int ret = -1;
05172 
05173    ast_wrlock_context(con);
05174 
05175    /* find our include */
05176    for (i = con->includes; i; pi = i, i = i->next) {
05177       if (!strcmp(i->name, include) &&
05178             (!registrar || !strcmp(i->registrar, registrar))) {
05179          /* remove from list */
05180          ast_verb(3, "Removing inclusion of context '%s' in context '%s; registrar=%s'\n", include, ast_get_context_name(con), registrar);
05181          if (pi)
05182             pi->next = i->next;
05183          else
05184             con->includes = i->next;
05185          /* free include and return */
05186          ast_destroy_timing(&(i->timing));
05187          ast_free(i);
05188          ret = 0;
05189          break;
05190       }
05191    }
05192 
05193    ast_unlock_context(con);
05194 
05195    return ret;
05196 }

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

Remove a switch.

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

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

05204 {
05205    int ret = -1; /* default error return */
05206    struct ast_context *c = find_context_locked(context);
05207 
05208    if (c) {
05209       /* remove switch from this context ... */
05210       ret = ast_context_remove_switch2(c, sw, data, registrar);
05211       ast_unlock_contexts();
05212    }
05213    return ret;
05214 }

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 5224 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::list, ast_sw::name, and ast_sw::registrar.

Referenced by ast_context_remove_switch().

05225 {
05226    struct ast_sw *i;
05227    int ret = -1;
05228 
05229    ast_wrlock_context(con);
05230 
05231    /* walk switches */
05232    AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) {
05233       if (!strcmp(i->name, sw) && !strcmp(i->data, data) &&
05234          (!registrar || !strcmp(i->registrar, registrar))) {
05235          /* found, remove from list */
05236          ast_verb(3, "Removing switch '%s' from context '%s; registrar=%s'\n", sw, ast_get_context_name(con), registrar);
05237          AST_LIST_REMOVE_CURRENT(list);
05238          ast_free(i); /* free switch and return */
05239          ret = 0;
05240          break;
05241       }
05242    }
05243    AST_LIST_TRAVERSE_SAFE_END;
05244 
05245    ast_unlock_context(con);
05246 
05247    return ret;
05248 }

int ast_context_unlockmacro ( const char *  context  ) 

Unlocks the macrolock in the given context.

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

05476 {
05477    struct ast_context *c = NULL;
05478    int ret = -1;
05479    struct fake_context item;
05480 
05481    ast_rdlock_contexts();
05482 
05483    ast_copy_string(item.name, context, sizeof(item.name));
05484 
05485    c = ast_hashtab_lookup(contexts_table,&item);
05486    if (c)
05487       ret = 0;
05488    ast_unlock_contexts();
05489 
05490    /* if we found context, unlock macrolock */
05491    if (ret == 0) {
05492       ret = ast_mutex_unlock(&c->macrolock);
05493    }
05494 
05495    return ret;
05496 }

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

10088 {
10089    struct ast_include *inc = NULL;
10090    int res = 0;
10091 
10092    while ( (inc = ast_walk_context_includes(con, inc)) ) {
10093       if (ast_context_find(inc->rname))
10094          continue;
10095 
10096       res = -1;
10097       ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n",
10098          ast_get_context_name(con), inc->rname);
10099       break;
10100    }
10101 
10102    return res;
10103 }

struct ast_custom_function* ast_custom_function_find ( const char *  name  ) 

Definition at line 3324 of file pbx.c.

References ast_custom_function::acflist, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, and ast_custom_function::name.

Referenced by ast_func_read(), ast_func_read2(), ast_func_write(), config_curl(), destroy_curl(), handle_show_function(), op_func(), realtime_curl(), realtime_multi_curl(), require_curl(), store_curl(), update2_curl(), and update_curl().

03325 {
03326    struct ast_custom_function *acf = NULL;
03327 
03328    AST_RWLIST_RDLOCK(&acf_root);
03329    AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) {
03330       if (!strcmp(name, acf->name))
03331          break;
03332    }
03333    AST_RWLIST_UNLOCK(&acf_root);
03334 
03335    return acf;
03336 }

int ast_custom_function_unregister ( struct ast_custom_function acf  ) 

Unregister a custom function.

Definition at line 3338 of file pbx.c.

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

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

03339 {
03340    struct ast_custom_function *cur;
03341 
03342    if (!acf) {
03343       return -1;
03344    }
03345 
03346    AST_RWLIST_WRLOCK(&acf_root);
03347    if ((cur = AST_RWLIST_REMOVE(&acf_root, acf, acflist))) {
03348 #ifdef AST_XML_DOCS
03349       if (cur->docsrc == AST_XML_DOC) {
03350          ast_string_field_free_memory(acf);
03351       }
03352 #endif
03353       ast_verb(2, "Unregistered custom function %s\n", cur->name);
03354    }
03355    AST_RWLIST_UNLOCK(&acf_root);
03356 
03357    return cur ? 0 : -1;
03358 }

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

07452 {
07453    if (i->timezone) {
07454       ast_free(i->timezone);
07455       i->timezone = NULL;
07456    }
07457    return 0;
07458 }

enum ast_extension_states ast_devstate_to_extenstate ( enum ast_device_state  devstate  ) 

Map devstate to an extension state.

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

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

04145 {
04146    switch (devstate) {
04147    case AST_DEVICE_ONHOLD:
04148       return AST_EXTENSION_ONHOLD;
04149    case AST_DEVICE_BUSY:
04150       return AST_EXTENSION_BUSY;
04151    case AST_DEVICE_UNKNOWN:
04152       return AST_EXTENSION_NOT_INUSE;
04153    case AST_DEVICE_UNAVAILABLE:
04154    case AST_DEVICE_INVALID:
04155       return AST_EXTENSION_UNAVAILABLE;
04156    case AST_DEVICE_RINGINUSE:
04157       return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING);
04158    case AST_DEVICE_RINGING:
04159       return AST_EXTENSION_RINGING;
04160    case AST_DEVICE_INUSE:
04161       return AST_EXTENSION_INUSE;
04162    case AST_DEVICE_NOT_INUSE:
04163       return AST_EXTENSION_NOT_INUSE;
04164    case AST_DEVICE_TOTAL: /* not a device state, included for completeness */
04165       break;
04166    }
04167 
04168    return AST_EXTENSION_NOT_INUSE;
04169 }

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 4581 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_bridge_call(), ast_pbx_outgoing_exten(), cb_events(), cli_console_dial(), conf_run(), console_dial(), console_transfer(), dahdi_handle_dtmf(), dahdi_r2_on_call_offered(), dahdi_r2_on_dnis_digit_received(), dial_exec_full(), disa_exec(), dp_lookup(), dundi_lookup_local(), findmeexec(), 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_dtmf(), park_space_reserve(), parkandannounce_exec(), pbx_builtin_waitexten(), phone_check_exception(), pri_dchannel(), pri_ss_thread(), privacy_exec(), process_ast_dsp(), process_sdp(), readexten_exec(), register_peer_exten(), rpt_exec(), show_debug_helper(), sip_new(), sip_read(), skinny_ss(), socket_process(), vm_authenticate(), and waitstream_core().

04582 {
04583    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0);
04584 }

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 7755 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(), do_bridge_masquerade(), handle_setpriority(), pbx_parseable_goto(), and return_exec().

07756 {
07757    if (!chan)
07758       return -1;
07759 
07760    ast_channel_lock(chan);
07761 
07762    if (!ast_strlen_zero(context))
07763       ast_copy_string(chan->context, context, sizeof(chan->context));
07764    if (!ast_strlen_zero(exten))
07765       ast_copy_string(chan->exten, exten, sizeof(chan->exten));
07766    if (priority > -1) {
07767       chan->priority = priority;
07768       /* see flag description in channel.h for explanation */
07769       if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP))
07770          chan->priority--;
07771    }
07772 
07773    ast_channel_unlock(chan);
07774 
07775    return 0;
07776 }

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

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

02489 {
02490    if (needmore != E_MATCHMORE && needmore != E_CANMATCH)
02491       ast_log(LOG_WARNING, "invalid argument %d\n", needmore);
02492    return extension_match_core(pattern, data, needmore);
02493 }

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

References ext_cmp().

Referenced by lua_extension_cmp().

02291 {
02292    return ext_cmp(a, b);
02293 }

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 2483 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(), show_dialplan_helper(), and sig_pri_msn_match().

02484 {
02485    return extension_match_core(pattern, data, E_MATCH);
02486 }

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

References ast_exten::app, ast_add_extension(), ast_extension_state2(), ast_free_ptr, ast_hint_extension(), ast_strdup, ast_exten::cidmatch, ast_exten::data, ast_exten::exten, ast_exten::label, ast_exten::matchcid, ast_context::name, ast_exten::parent, ast_exten::priority, and ast_exten::registrar.

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

04208 {
04209    struct ast_exten *e;
04210 
04211    if (!(e = ast_hint_extension(c, context, exten))) {  /* Do we have a hint for this extension ? */
04212       return -1;                   /* No hint, return -1 */
04213    }
04214 
04215    if (e->exten[0] == '_') {
04216       /* Create this hint on-the-fly */
04217       ast_add_extension(e->parent->name, 0, exten, e->priority, e->label,
04218          e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr,
04219          e->registrar);
04220       if (!(e = ast_hint_extension(c, context, exten))) {
04221          /* Improbable, but not impossible */
04222          return -1;
04223       }
04224    }
04225 
04226    return ast_extension_state2(e);  /* Check all devices in the hint */
04227 }

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

References ARRAY_LEN, extension_states, and cfextension_states::text.

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

04196 {
04197    int i;
04198 
04199    for (i = 0; (i < ARRAY_LEN(extension_states)); i++) {
04200       if (extension_states[i].extension_state == extension_state)
04201          return extension_states[i].text;
04202    }
04203    return "Unknown";
04204 }

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

References ao2_alloc, ao2_find, ao2_link, ao2_lock, ao2_ref, ao2_unlock, ast_exten::app, ast_add_extension(), ast_free_ptr, ast_hint_extension(), ast_strdup, ast_hint::callbacks, ast_exten::cidmatch, ast_state_cb::data, ast_exten::data, ast_exten::exten, hints, ast_exten::label, ast_exten::matchcid, ast_context::name, ast_exten::parent, ast_exten::priority, ast_exten::registrar, statecbs, and stateid.

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

04306 {
04307    struct ast_hint *hint;
04308    struct ast_state_cb *state_cb;
04309    struct ast_exten *e;
04310 
04311    /* If there's no context and extension:  add callback to statecbs list */
04312    if (!context && !exten) {
04313       ao2_lock(hints);
04314 
04315       state_cb = ao2_find(statecbs, callback, 0);
04316       if (state_cb) {
04317          state_cb->data = data;
04318          ao2_ref(state_cb, -1);
04319          ao2_unlock(hints);
04320          return 0;
04321       }
04322 
04323       /* Now insert the callback */
04324       if (!(state_cb = ao2_alloc(sizeof(*state_cb), NULL))) {
04325          ao2_unlock(hints);
04326          return -1;
04327       }
04328       state_cb->id = 0;
04329       state_cb->callback = callback;
04330       state_cb->data = data;
04331 
04332       ao2_link(statecbs, state_cb);
04333       ao2_ref(state_cb, -1);
04334 
04335       ao2_unlock(hints);
04336       return 0;
04337    }
04338 
04339    if (!context || !exten)
04340       return -1;
04341 
04342    /* This callback type is for only one hint, so get the hint */
04343    e = ast_hint_extension(NULL, context, exten);
04344    if (!e) {
04345       return -1;
04346    }
04347 
04348    /* If this is a pattern, dynamically create a new extension for this
04349     * particular match.  Note that this will only happen once for each
04350     * individual extension, because the pattern will no longer match first.
04351     */
04352    if (e->exten[0] == '_') {
04353       ast_add_extension(e->parent->name, 0, exten, e->priority, e->label,
04354          e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr,
04355          e->registrar);
04356       e = ast_hint_extension(NULL, context, exten);
04357       if (!e || e->exten[0] == '_') {
04358          return -1;
04359       }
04360    }
04361 
04362    /* Find the hint in the list of hints */
04363    hint = ao2_find(hints, e, 0);
04364 
04365    if (!hint) {
04366       return -1;
04367    }
04368 
04369    /* Now insert the callback in the callback list  */
04370    if (!(state_cb = ao2_alloc(sizeof(*state_cb), NULL))) {
04371       ao2_ref(hint, -1);
04372       return -1;
04373    }
04374 
04375    state_cb->id = stateid++;     /* Unique ID for this callback */
04376    state_cb->callback = callback;   /* Pointer to callback routine */
04377    state_cb->data = data;     /* Data for the callback */
04378 
04379    ao2_lock(hint);
04380    ao2_link(hint->callbacks, state_cb);
04381    ao2_ref(state_cb, -1);
04382    ao2_unlock(hint);
04383 
04384    ao2_ref(hint, -1);
04385 
04386    return state_cb->id;
04387 }

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

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

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

04406 {
04407    struct ast_state_cb *p_cur = NULL;
04408    int ret = -1;
04409 
04410    if (!id && !callback) {
04411       return -1;
04412    }
04413 
04414    if (!id) {  /* id == 0 is a callback without extension */
04415       ao2_lock(hints);
04416       p_cur = ao2_find(statecbs, callback, OBJ_UNLINK);
04417       if (p_cur) {
04418          ret = 0;
04419          ao2_ref(p_cur, -1);
04420       }
04421       ao2_unlock(hints);
04422    } else { /* callback with extension, find the callback based on ID */
04423       struct ast_hint *hint;
04424 
04425       hint = ao2_callback(hints, 0, find_hint_by_cb_id, &id);
04426 
04427       if (hint) {
04428          ao2_lock(hint);
04429          p_cur = ao2_find(hint->callbacks, &id, OBJ_UNLINK);
04430          if (p_cur) {
04431             ret = 0;
04432             ao2_ref(p_cur, -1);
04433          }
04434          ao2_unlock(hint);
04435          ao2_ref(hint, -1);
04436       }
04437    }
04438 
04439    return ret;
04440 }

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

04587 {
04588    return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
04589 }

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

References E_FINDLABEL, and pbx_extension_helper().

04592 {
04593    return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
04594 }

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

References __ast_module_user_add(), __ast_module_user_remove(), args, ast_copy_string(), ast_custom_function_find(), ast_free, ast_log(), ast_str_buffer(), ast_str_create(), ast_str_size(), ast_strdupa, ast_module_user::chan, 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().

03483 {
03484    char *copy = ast_strdupa(function);
03485    char *args = func_args(copy);
03486    struct ast_custom_function *acfptr = ast_custom_function_find(copy);
03487    int res;
03488    struct ast_module_user *u = NULL;
03489 
03490    if (acfptr == NULL) {
03491       ast_log(LOG_ERROR, "Function %s not registered\n", copy);
03492    } else if (!acfptr->read && !acfptr->read2) {
03493       ast_log(LOG_ERROR, "Function %s cannot be read\n", copy);
03494    } else if (acfptr->read) {
03495       if (acfptr->mod) {
03496          u = __ast_module_user_add(acfptr->mod, chan);
03497       }
03498       res = acfptr->read(chan, copy, args, workspace, len);
03499       if (acfptr->mod && u) {
03500          __ast_module_user_remove(acfptr->mod, u);
03501       }
03502       return res;
03503    } else {
03504       struct ast_str *str = ast_str_create(16);
03505       if (acfptr->mod) {
03506          u = __ast_module_user_add(acfptr->mod, chan);
03507       }
03508       res = acfptr->read2(chan, copy, args, &str, 0);
03509       if (acfptr->mod && u) {
03510          __ast_module_user_remove(acfptr->mod, u);
03511       }
03512       ast_copy_string(workspace, ast_str_buffer(str), len > ast_str_size(str) ? ast_str_size(str) : len);
03513       ast_free(str);
03514       return res;
03515    }
03516    return -1;
03517 }

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

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

Referenced by append_channel_vars(), and ast_str_substitute_variables_full().

03520 {
03521    char *copy = ast_strdupa(function);
03522    char *args = func_args(copy);
03523    struct ast_custom_function *acfptr = ast_custom_function_find(copy);
03524    int res;
03525    struct ast_module_user *u = NULL;
03526 
03527    if (acfptr == NULL) {
03528       ast_log(LOG_ERROR, "Function %s not registered\n", copy);
03529    } else if (!acfptr->read && !acfptr->read2) {
03530       ast_log(LOG_ERROR, "Function %s cannot be read\n", copy);
03531    } else {
03532       if (acfptr->mod) {
03533          u = __ast_module_user_add(acfptr->mod, chan);
03534       }
03535       if (acfptr->read2) {
03536          /* ast_str enabled */
03537          ast_str_reset(*str);
03538          res = acfptr->read2(chan, copy, args, str, maxlen);
03539       } else {
03540          /* Legacy function pointer, allocate buffer for result */
03541          int maxsize = ast_str_size(*str);
03542          if (maxlen > -1) {
03543             if (maxlen == 0) {
03544                if (acfptr->read_max) {
03545                   maxsize = acfptr->read_max;
03546                } else {
03547                   maxsize = VAR_BUF_SIZE;
03548                }
03549             } else {
03550                maxsize = maxlen;
03551             }
03552             ast_str_make_space(str, maxsize);
03553          }
03554          res = acfptr->read(chan, copy, args, ast_str_buffer(*str), maxsize);
03555       }
03556       if (acfptr->mod && u) {
03557          __ast_module_user_remove(acfptr->mod, u);
03558       }
03559       return res;
03560    }
03561    return -1;
03562 }

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

References __ast_module_user_add(), __ast_module_user_remove(), args, ast_custom_function_find(), ast_log(), ast_strdupa, ast_module_user::chan, 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().

03565 {
03566    char *copy = ast_strdupa(function);
03567    char *args = func_args(copy);
03568    struct ast_custom_function *acfptr = ast_custom_function_find(copy);
03569 
03570    if (acfptr == NULL)
03571       ast_log(LOG_ERROR, "Function %s not registered\n", copy);
03572    else if (!acfptr->write)
03573       ast_log(LOG_ERROR, "Function %s cannot be written to\n", copy);
03574    else {
03575       int res;
03576       struct ast_module_user *u = NULL;
03577       if (acfptr->mod)
03578          u = __ast_module_user_add(acfptr->mod, chan);
03579       res = acfptr->write(chan, copy, args, value);
03580       if (acfptr->mod && u)
03581          __ast_module_user_remove(acfptr->mod, u);
03582       return res;
03583    }
03584 
03585    return -1;
03586 }

const char* ast_get_context_name ( struct ast_context con  ) 

Definition at line 9939 of file pbx.c.

References ast_context::name.

Referenced by _macro_exec(), ast_context_add_include2(), ast_context_add_switch2(), ast_context_remove_include2(), ast_context_remove_switch2(), ast_context_verify_includes(), complete_dialplan_add_extension(), complete_dialplan_add_ignorepat(), complete_dialplan_add_include(), complete_dialplan_remove_extension(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), complete_show_dialplan_context(), context_merge_incls_swits_igps_other_registrars(), dundi_precache_full(), find_matching_endwhile(), find_matching_priority(), handle_cli_dialplan_save(), handle_show_hint(), handle_show_hints(), hints_data_provider_get(), manager_show_dialplan_helper(), show_debug_helper(), and show_dialplan_helper().

09940 {
09941    return con ? con->name : NULL;
09942 }

const char* ast_get_context_registrar ( struct ast_context c  ) 

Definition at line 9977 of file pbx.c.

References ast_context::registrar.

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

09978 {
09979    return c ? c->registrar : NULL;
09980 }

const char* ast_get_extension_app ( struct ast_exten e  ) 

Definition at line 10007 of file pbx.c.

References ast_exten::app.

Referenced by _macro_exec(), ast_add_hint(), ast_extension_state2(), ast_get_hint(), ast_parking_ext_valid(), ast_str_get_hint(), find_matching_endwhile(), handle_cli_dialplan_save(), handle_show_hint(), handle_show_hints(), handle_statechange(), hints_data_provider_get(), manager_show_dialplan_helper(), and print_ext().

10008 {
10009    return e ? e->app : NULL;
10010 }

void* ast_get_extension_app_data ( struct ast_exten e  ) 

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

10013 {
10014    return e ? e->data : NULL;
10015 }

const char* ast_get_extension_cidmatch ( struct ast_exten e  ) 

Definition at line 10002 of file pbx.c.

References ast_exten::cidmatch.

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

10003 {
10004    return e ? e->cidmatch : NULL;
10005 }

struct ast_context* ast_get_extension_context ( struct ast_exten exten  ) 

Definition at line 9944 of file pbx.c.

References exten.

Referenced by handle_show_hint(), handle_show_hints(), and hints_data_provider_get().

09945 {
09946    return exten ? exten->parent : NULL;
09947 }

const char* ast_get_extension_label ( struct ast_exten e  ) 

Definition at line 9954 of file pbx.c.

References exten.

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

09955 {
09956    return exten ? exten->label : NULL;
09957 }

int ast_get_extension_matchcid ( struct ast_exten e  ) 

Definition at line 9997 of file pbx.c.

References ast_exten::matchcid.

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

09998 {
09999    return e ? e->matchcid : 0;
10000 }

const char* ast_get_extension_name ( struct ast_exten exten  ) 

Definition at line 9949 of file pbx.c.

References exten.

Referenced by ast_add_hint(), complete_core_show_hint(), complete_dialplan_remove_extension(), dundi_precache_full(), find_matching_priority(), handle_cli_dialplan_save(), handle_show_hint(), handle_show_hints(), hint_hash(), hints_data_provider_get(), manager_show_dialplan_helper(), and show_dialplan_helper().

09950 {
09951    return exten ? exten->exten : NULL;
09952 }

int ast_get_extension_priority ( struct ast_exten exten  ) 

Definition at line 9969 of file pbx.c.

References exten.

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

09970 {
09971    return exten ? exten->priority : -1;
09972 }

const char* ast_get_extension_registrar ( struct ast_exten e  ) 

Definition at line 9982 of file pbx.c.

References ast_exten::registrar.

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

09983 {
09984    return e ? e->registrar : NULL;
09985 }

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

04544 {
04545    struct ast_exten *e = ast_hint_extension(c, context, exten);
04546 
04547    if (e) {
04548       if (hint)
04549          ast_copy_string(hint, ast_get_extension_app(e), hintsize);
04550       if (name) {
04551          const char *tmp = ast_get_extension_app_data(e);
04552          if (tmp)
04553             ast_copy_string(name, tmp, namesize);
04554       }
04555       return -1;
04556    }
04557    return 0;
04558 }

const char* ast_get_ignorepat_name ( struct ast_ignorepat ip  ) 

Definition at line 9964 of file pbx.c.

References ast_ignorepat::pattern.

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

09965 {
09966    return ip ? ip->pattern : NULL;
09967 }

const char* ast_get_ignorepat_registrar ( struct ast_ignorepat ip  ) 

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

09993 {
09994    return ip ? ip->registrar : NULL;
09995 }

const char* ast_get_include_name ( struct ast_include include  ) 

Definition at line 9959 of file pbx.c.

References ast_include::name.

Referenced by complete_dialplan_remove_include(), context_merge_incls_swits_igps_other_registrars(), find_matching_priority(), handle_cli_dialplan_save(), lookup_ci(), manager_show_dialplan_helper(), and show_dialplan_helper().

09960 {
09961    return inc ? inc->name : NULL;
09962 }

const char* ast_get_include_registrar ( struct ast_include i  ) 

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

09988 {
09989    return i ? i->registrar : NULL;
09990 }

const char* ast_get_switch_data ( struct ast_sw sw  ) 

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

10023 {
10024    return sw ? sw->data : NULL;
10025 }

int ast_get_switch_eval ( struct ast_sw sw  ) 

Definition at line 10027 of file pbx.c.

References ast_sw::eval.

Referenced by context_merge_incls_swits_igps_other_registrars().

10028 {
10029    return sw->eval;
10030 }

const char* ast_get_switch_name ( struct ast_sw sw  ) 

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

10018 {
10019    return sw ? sw->name : NULL;
10020 }

const char* ast_get_switch_registrar ( struct ast_sw sw  ) 

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

10033 {
10034    return sw ? sw->registrar : NULL;
10035 }

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

References __ast_goto_if_exists().

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

10128 {
10129    return __ast_goto_if_exists(chan, context, exten, priority, 0);
10130 }

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

hashtable functions for contexts

Definition at line 1046 of file pbx.c.

References ast_context::name.

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

01047 {
01048    const struct ast_context *ac = ah_a;
01049    const struct ast_context *bc = ah_b;
01050    if (!ac || !bc) /* safety valve, but it might prevent a crash you'd rather have happen */
01051       return 1;
01052    /* assume context names are registered in a string table! */
01053    return strcmp(ac->name, bc->name);
01054 }

unsigned int ast_hashtab_hash_contexts ( const void *  obj  ) 

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

01090 {
01091    const struct ast_context *ac = obj;
01092    return ast_hashtab_hash_string(ac->name);
01093 }

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 7701 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(), pri_ss_thread(), and skinny_ss().

07702 {
07703    struct ast_context *con = ast_context_find(context);
07704    if (con) {
07705       struct ast_ignorepat *pat;
07706       for (pat = con->ignorepats; pat; pat = pat->next) {
07707          if (ast_extension_match(pat->pattern, pattern))
07708             return 1;
07709       }
07710    }
07711 
07712    return 0;
07713 }

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

References E_MATCHMORE, and pbx_extension_helper().

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

04602 {
04603    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0);
04604 }

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

References __ast_internal_context_destroy(), ao2_callback, ao2_container_count(), ao2_find, AO2_ITERATOR_DONTLOCK, ao2_iterator_init(), ao2_iterator_next, ao2_link, ao2_lock, ao2_ref, ao2_unlock, ast_add_extension_nolock(), ast_calloc, AST_EXTENSION_REMOVED, ast_free, ast_free_ptr, ast_hashtab_destroy(), ast_hashtab_end_traversal(), ast_hashtab_next(), ast_hashtab_start_traversal(), ast_hint_extension_nolock(), AST_LIST_HEAD_INIT_VALUE, AST_LIST_INSERT_HEAD, AST_LIST_INSERT_TAIL, AST_LIST_REMOVE_HEAD, ast_rdlock_contexts(), ast_strdup, ast_tvdiff_us(), ast_tvnow(), ast_unlock_contexts(), ast_verb, ast_state_cb::callback, ast_hint::callbacks, context_merge(), contexts, contexts_table, ast_state_cb::data, E_MATCH, ast_hint::exten, ast_exten::exten, store_hint::exten, hints, store_hint::laststate, ast_hint::laststate, store_hint::list, ast_context::name, store_hint::next, ast_context::next, OBJ_UNLINK, ast_exten::parent, pbx_find_extension(), PRIORITY_HINT, and pbx_find_info::stacklen.

Referenced by lua_reload_extensions(), and pbx_load_module().

07043 {
07044    double ft;
07045    struct ast_context *tmp, *oldcontextslist;
07046    struct ast_hashtab *oldtable;
07047    struct store_hints store = AST_LIST_HEAD_INIT_VALUE;
07048    struct store_hint *this;
07049    struct ast_hint *hint;
07050    struct ast_exten *exten;
07051    int length;
07052    struct ast_state_cb *thiscb;
07053    struct ast_hashtab_iter *iter;
07054    struct ao2_iterator i;
07055 
07056    /* it is very important that this function hold the hint list lock _and_ the conlock
07057       during its operation; not only do we need to ensure that the list of contexts
07058       and extensions does not change, but also that no hint callbacks (watchers) are
07059       added or removed during the merge/delete process
07060 
07061       in addition, the locks _must_ be taken in this order, because there are already
07062       other code paths that use this order
07063    */
07064 
07065    struct timeval begintime, writelocktime, endlocktime, enddeltime;
07066 
07067    begintime = ast_tvnow();
07068    ast_rdlock_contexts();
07069    iter = ast_hashtab_start_traversal(contexts_table);
07070    while ((tmp = ast_hashtab_next(iter))) {
07071       context_merge(extcontexts, exttable, tmp, registrar);
07072    }
07073    ast_hashtab_end_traversal(iter);
07074 
07075    ao2_lock(hints);
07076    writelocktime = ast_tvnow();
07077 
07078    /* preserve all watchers for hints */
07079    i = ao2_iterator_init(hints, AO2_ITERATOR_DONTLOCK);
07080    for (hint = ao2_iterator_next(&i); hint; ao2_ref(hint, -1), hint = ao2_iterator_next(&i)) {
07081       if (ao2_container_count(hint->callbacks)) {
07082 
07083          length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2 + sizeof(*this);
07084          if (!(this = ast_calloc(1, length))) {
07085             continue;
07086          }
07087          ao2_lock(hint);
07088 
07089          if (hint->exten == NULL) {
07090             ao2_unlock(hint);
07091             continue;
07092          }
07093 
07094          /* this removes all the callbacks from the hint into 'this'. */
07095          while ((thiscb = ao2_callback(hint->callbacks, OBJ_UNLINK, NULL, NULL))) {
07096             AST_LIST_INSERT_TAIL(&this->callbacks, thiscb, entry);
07097             /* We intentionally do not unref thiscb to account for the non-ao2 reference in this->callbacks */
07098          }
07099 
07100          this->laststate = hint->laststate;
07101          this->context = this->data;
07102          strcpy(this->data, hint->exten->parent->name);
07103          this->exten = this->data + strlen(this->context) + 1;
07104          strcpy(this->exten, hint->exten->exten);
07105          ao2_unlock(hint);
07106          AST_LIST_INSERT_HEAD(&store, this, list);
07107       }
07108    }
07109 
07110    /* save the old table and list */
07111    oldtable = contexts_table;
07112    oldcontextslist = contexts;
07113 
07114    /* move in the new table and list */
07115    contexts_table = exttable;
07116    contexts = *extcontexts;
07117 
07118    /* restore the watchers for hints that can be found; notify those that
07119       cannot be restored
07120    */
07121    while ((this = AST_LIST_REMOVE_HEAD(&store, list))) {
07122       struct pbx_find_info q = { .stacklen = 0 };
07123       exten = pbx_find_extension(NULL, NULL, &q, this->context, this->exten, PRIORITY_HINT, NULL, "", E_MATCH);
07124       /* If this is a pattern, dynamically create a new extension for this
07125        * particular match.  Note that this will only happen once for each
07126        * individual extension, because the pattern will no longer match first.
07127        */
07128       if (exten && exten->exten[0] == '_') {
07129          ast_add_extension_nolock(exten->parent->name, 0, this->exten, PRIORITY_HINT, NULL,
07130             0, exten->app, ast_strdup(exten->data), ast_free_ptr, exten->registrar);
07131          /* rwlocks are not recursive locks */
07132          exten = ast_hint_extension_nolock(NULL, this->context, this->exten);
07133       }
07134 
07135       /* Find the hint in the list of hints */
07136       hint = ao2_find(hints, exten, 0);
07137       if (!exten || !hint) {
07138          /* this hint has been removed, notify the watchers */
07139          while ((thiscb = AST_LIST_REMOVE_HEAD(&this->callbacks, entry))) {
07140             thiscb->callback(this->context, this->exten, AST_EXTENSION_REMOVED, thiscb->data);
07141             ao2_ref(thiscb, -1);  /* Ref that we added when putting into this->callbacks */
07142          }
07143       } else {
07144          ao2_lock(hint);
07145          while ((thiscb = AST_LIST_REMOVE_HEAD(&this->callbacks, entry))) {
07146             ao2_link(hint->callbacks, thiscb);
07147             ao2_ref(thiscb, -1);  /* Ref that we added when putting into this->callbacks */
07148          }
07149          hint->laststate = this->laststate;
07150          ao2_unlock(hint);
07151       }
07152       ast_free(this);
07153       if (hint) {
07154          ao2_ref(hint, -1);
07155       }
07156    }
07157 
07158    ao2_unlock(hints);
07159    ast_unlock_contexts();
07160    endlocktime = ast_tvnow();
07161 
07162    /* the old list and hashtab no longer are relevant, delete them while the rest of asterisk
07163       is now freely using the new stuff instead */
07164 
07165    ast_hashtab_destroy(oldtable, NULL);
07166 
07167    for (tmp = oldcontextslist; tmp; ) {
07168       struct ast_context *next;  /* next starting point */
07169       next = tmp->next;
07170       __ast_internal_context_destroy(tmp);
07171       tmp = next;
07172    }
07173    enddeltime = ast_tvnow();
07174 
07175    ft = ast_tvdiff_us(writelocktime, begintime);
07176    ft /= 1000000.0;
07177    ast_verb(3,"Time to scan old dialplan and merge leftovers back into the new: %8.6f sec\n", ft);
07178 
07179    ft = ast_tvdiff_us(endlocktime, writelocktime);
07180    ft /= 1000000.0;
07181    ast_verb(3,"Time to restore hints and swap in new dialplan: %8.6f sec\n", ft);
07182 
07183    ft = ast_tvdiff_us(enddeltime, endlocktime);
07184    ft /= 1000000.0;
07185    ast_verb(3,"Time to delete the old dialplan: %8.6f sec\n", ft);
07186 
07187    ft = ast_tvdiff_us(enddeltime, begintime);
07188    ft /= 1000000.0;
07189    ast_verb(3,"Total time merge_contexts_delete: %8.6f sec\n", ft);
07190    return;
07191 }

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

10193 {
10194    return pbx_parseable_goto(chan, goto_string, 0);
10195 }

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

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

Definition at line 8544 of file pbx.c.

References __ast_request_and_dial(), 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(), async_stat::chan, errno, LOG_WARNING, and outgoing_helper::vars.

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

08545 {
08546    struct ast_channel *chan;
08547    struct app_tmp *tmp;
08548    int res = -1, cdr_res = -1;
08549    struct outgoing_helper oh;
08550 
08551    memset(&oh, 0, sizeof(oh));
08552    oh.vars = vars;
08553    oh.account = account;
08554 
08555    if (locked_channel)
08556       *locked_channel = NULL;
08557    if (ast_strlen_zero(app)) {
08558       res = -1;
08559       goto outgoing_app_cleanup;
08560    }
08561    if (synchronous) {
08562       chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh);
08563       if (chan) {
08564          ast_set_variables(chan, vars);
08565          if (account)
08566             ast_cdr_setaccount(chan, account);
08567          if (chan->_state == AST_STATE_UP) {
08568             res = 0;
08569             ast_verb(4, "Channel %s was answered.\n", chan->name);
08570             tmp = ast_calloc(1, sizeof(*tmp));
08571             if (!tmp)
08572                res = -1;
08573             else {
08574                ast_copy_string(tmp->app, app, sizeof(tmp->app));
08575                if (appdata)
08576                   ast_copy_string(tmp->data, appdata, sizeof(tmp->data));
08577                tmp->chan = chan;
08578                if (synchronous > 1) {
08579                   if (locked_channel)
08580                      ast_channel_unlock(chan);
08581                   ast_pbx_run_app(tmp);
08582                } else {
08583                   if (locked_channel)
08584                      ast_channel_lock(chan);
08585                   if (ast_pthread_create_detached(&tmp->t, NULL, ast_pbx_run_app, tmp)) {
08586                      ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno));
08587                      ast_free(tmp);
08588                      if (locked_channel)
08589                         ast_channel_unlock(chan);
08590                      ast_hangup(chan);
08591                      res = -1;
08592                   } else {
08593                      if (locked_channel)
08594                         *locked_channel = chan;
08595                   }
08596                }
08597             }
08598          } else {
08599             ast_verb(4, "Channel %s was never answered.\n", chan->name);
08600             if (chan->cdr) { /* update the cdr */
08601                /* here we update the status of the call, which sould be busy.
08602                 * if that fails then we set the status to failed */
08603                if (ast_cdr_disposition(chan->cdr, chan->hangupcause))
08604                   ast_cdr_failed(chan->cdr);
08605             }
08606             ast_hangup(chan);
08607          }
08608       }
08609 
08610       if (res < 0) { /* the call failed for some reason */
08611          if (*reason == 0) { /* if the call failed (not busy or no answer)
08612                         * update the cdr with the failed message */
08613             cdr_res = ast_pbx_outgoing_cdr_failed();
08614             if (cdr_res != 0) {
08615                res = cdr_res;
08616                goto outgoing_app_cleanup;
08617             }
08618          }
08619       }
08620 
08621    } else {
08622       struct async_stat *as;
08623       if (!(as = ast_calloc(1, sizeof(*as)))) {
08624          res = -1;
08625          goto outgoing_app_cleanup;
08626       }
08627       chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh);
08628       if (!chan) {
08629          ast_free(as);
08630          res = -1;
08631          goto outgoing_app_cleanup;
08632       }
08633       as->chan = chan;
08634       ast_copy_string(as->app, app, sizeof(as->app));
08635       if (appdata)
08636          ast_copy_string(as->appdata,  appdata, sizeof(as->appdata));
08637       as->timeout = timeout;
08638       ast_set_variables(chan, vars);
08639       if (account)
08640          ast_cdr_setaccount(chan, account);
08641       /* Start a new thread, and get something handling this channel. */
08642       if (locked_channel)
08643          ast_channel_lock(chan);
08644       if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) {
08645          ast_log(LOG_WARNING, "Failed to start async wait\n");
08646          ast_free(as);
08647          if (locked_channel)
08648             ast_channel_unlock(chan);
08649          ast_hangup(chan);
08650          res = -1;
08651          goto outgoing_app_cleanup;
08652       } else {
08653          if (locked_channel)
08654             *locked_channel = chan;
08655       }
08656       res = 0;
08657    }
08658 outgoing_app_cleanup:
08659    ast_variables_destroy(vars);
08660    return res;
08661 }

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

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

Definition at line 8378 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, outgoing_helper::cid_name, outgoing_helper::cid_num, outgoing_helper::context, ast_channel::context, outgoing_helper::exten, ast_channel::hangupcause, LOG_ERROR, LOG_WARNING, ast_channel::name, outgoing_helper::parent_channel, pbx_builtin_setvar_helper(), outgoing_helper::priority, set_ext_pri(), and outgoing_helper::vars.

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

08379 {
08380    struct ast_channel *chan;
08381    struct async_stat *as;
08382    int res = -1, cdr_res = -1;
08383    struct outgoing_helper oh;
08384 
08385    if (synchronous) {
08386       oh.context = context;
08387       oh.exten = exten;
08388       oh.priority = priority;
08389       oh.cid_num = cid_num;
08390       oh.cid_name = cid_name;
08391       oh.account = account;
08392       oh.vars = vars;
08393       oh.parent_channel = NULL;
08394 
08395       chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh);
08396       if (channel) {
08397          *channel = chan;
08398          if (chan)
08399             ast_channel_lock(chan);
08400       }
08401       if (chan) {
08402          if (chan->_state == AST_STATE_UP) {
08403                res = 0;
08404             ast_verb(4, "Channel %s was answered.\n", chan->name);
08405 
08406             if (synchronous > 1) {
08407                if (channel)
08408                   ast_channel_unlock(chan);
08409                if (ast_pbx_run(chan)) {
08410                   ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name);
08411                   if (channel)
08412                      *channel = NULL;
08413                   ast_hangup(chan);
08414                   chan = NULL;
08415                   res = -1;
08416                }
08417             } else {
08418                if (ast_pbx_start(chan)) {
08419                   ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name);
08420                   if (channel) {
08421                      *channel = NULL;
08422                      ast_channel_unlock(chan);
08423                   }
08424                   ast_hangup(chan);
08425                   res = -1;
08426                }
08427                chan = NULL;
08428             }
08429          } else {
08430             ast_verb(4, "Channel %s was never answered.\n", chan->name);
08431 
08432             if (chan->cdr) { /* update the cdr */
08433                /* here we update the status of the call, which sould be busy.
08434                 * if that fails then we set the status to failed */
08435                if (ast_cdr_disposition(chan->cdr, chan->hangupcause))
08436                   ast_cdr_failed(chan->cdr);
08437             }
08438 
08439             if (channel) {
08440                *channel = NULL;
08441                ast_channel_unlock(chan);
08442             }
08443             ast_hangup(chan);
08444             chan = NULL;
08445          }
08446       }
08447 
08448       if (res < 0) { /* the call failed for some reason */
08449          if (*reason == 0) { /* if the call failed (not busy or no answer)
08450                         * update the cdr with the failed message */
08451             cdr_res = ast_pbx_outgoing_cdr_failed();
08452             if (cdr_res != 0) {
08453                res = cdr_res;
08454                goto outgoing_exten_cleanup;
08455             }
08456          }
08457 
08458          /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */
08459          /* check if "failed" exists */
08460          if (ast_exists_extension(chan, context, "failed", 1, NULL)) {
08461             chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", NULL, 0, "OutgoingSpoolFailed");
08462             if (chan) {
08463                char failed_reason[4] = "";
08464                if (!ast_strlen_zero(context))
08465                   ast_copy_string(chan->context, context, sizeof(chan->context));
08466                set_ext_pri(chan, "failed", 1);
08467                ast_set_variables(chan, vars);
08468                snprintf(failed_reason, sizeof(failed_reason), "%d", *reason);
08469                pbx_builtin_setvar_helper(chan, "REASON", failed_reason);
08470                if (account)
08471                   ast_cdr_setaccount(chan, account);
08472                if (ast_pbx_run(chan)) {
08473                   ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name);
08474                   ast_hangup(chan);
08475                }
08476                chan = NULL;
08477             }
08478          }
08479       }
08480    } else {
08481       if (!(as = ast_calloc(1, sizeof(*as)))) {
08482          res = -1;
08483          goto outgoing_exten_cleanup;
08484       }
08485       chan = ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name);
08486       if (channel) {
08487          *channel = chan;
08488          if (chan)
08489             ast_channel_lock(chan);
08490       }
08491       if (!chan) {
08492          ast_free(as);
08493          res = -1;
08494          goto outgoing_exten_cleanup;
08495       }
08496       as->chan = chan;
08497       ast_copy_string(as->context, context, sizeof(as->context));
08498       set_ext_pri(as->chan,  exten, priority);
08499       as->timeout = timeout;
08500       ast_set_variables(chan, vars);
08501       if (account)
08502          ast_cdr_setaccount(chan, account);
08503       if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) {
08504          ast_log(LOG_WARNING, "Failed to start async wait\n");
08505          ast_free(as);
08506          if (channel) {
08507             *channel = NULL;
08508             ast_channel_unlock(chan);
08509          }
08510          ast_hangup(chan);
08511          res = -1;
08512          goto outgoing_exten_cleanup;
08513       }
08514       res = 0;
08515    }
08516 outgoing_exten_cleanup:
08517    ast_variables_destroy(vars);
08518    return res;
08519 }

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

References ast_pbx_run_args().

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

05063 {
05064    return ast_pbx_run_args(c, NULL);
05065 }

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

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

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

05048 {
05049    enum ast_pbx_result res = AST_PBX_SUCCESS;
05050 
05051    if (increase_call_count(c)) {
05052       return AST_PBX_CALL_LIMIT;
05053    }
05054 
05055    res = __ast_pbx_run(c, args);
05056 
05057    decrease_call_count();
05058 
05059    return res;
05060 }

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

05026 {
05027    pthread_t t;
05028 
05029    if (!c) {
05030       ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
05031       return AST_PBX_FAILED;
05032    }
05033 
05034    if (increase_call_count(c))
05035       return AST_PBX_CALL_LIMIT;
05036 
05037    /* Start a new thread, and get something handling this channel. */
05038    if (ast_pthread_create_detached(&t, NULL, pbx_thread, c)) {
05039       ast_log(LOG_WARNING, "Failed to create new channel thread\n");
05040       decrease_call_count();
05041       return AST_PBX_FAILED;
05042    }
05043 
05044    return AST_PBX_SUCCESS;
05045 }

int ast_processed_calls ( void   ) 

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

Definition at line 5072 of file pbx.c.

References totalcalls.

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

05073 {
05074    return totalcalls;
05075 }

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

09927 {
09928    return ast_rwlock_rdlock(&con->lock);
09929 }

int ast_rdlock_contexts ( void   ) 

Read locks the context list.

Return values:
0 on success
-1 on error

Definition at line 9908 of file pbx.c.

References ast_mutex_lock, and conlock.

Referenced by _macro_exec(), ast_context_find(), ast_context_find_or_create(), ast_context_lockmacro(), ast_context_unlockmacro(), ast_hint_extension(), ast_merge_contexts_and_delete(), complete_dialplan_add_extension(), complete_dialplan_add_ignorepat(), complete_dialplan_add_include(), complete_dialplan_remove_extension(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), complete_show_dialplan_context(), dundi_precache_full(), find_context_locked(), find_matching_endwhile(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), pbx_extension_helper(), show_debug_helper(), show_dialplan_helper(), and unreference_cached_app().

09909 {
09910    return ast_mutex_lock(&conlock);
09911 }

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

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

Referenced by load_module().

05595 {
05596    struct ast_switch *tmp;
05597 
05598    AST_RWLIST_WRLOCK(&switches);
05599    AST_RWLIST_TRAVERSE(&switches, tmp, list) {
05600       if (!strcasecmp(tmp->name, sw->name)) {
05601          AST_RWLIST_UNLOCK(&switches);
05602          ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name);
05603          return -1;
05604       }
05605    }
05606    AST_RWLIST_INSERT_TAIL(&switches, sw, list);
05607    AST_RWLIST_UNLOCK(&switches);
05608 
05609    return 0;
05610 }

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

04607 {
04608    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN, found, combined_find_spawn);
04609 }

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

References ast_get_extension_app(), ast_get_extension_app_data(), ast_hint_extension(), ast_str_set(), and fake_context::name.

Referenced by ast_str_retrieve_variable().

04562 {
04563    struct ast_exten *e = ast_hint_extension(c, context, exten);
04564 
04565    if (!e) {
04566       return 0;
04567    }
04568 
04569    if (hint) {
04570       ast_str_set(hint, hintsize, "%s", ast_get_extension_app(e));
04571    }
04572    if (name) {
04573       const char *tmp = ast_get_extension_app_data(e);
04574       if (tmp) {
04575          ast_str_set(name, namesize, "%s", tmp);
04576       }
04577    }
04578    return -1;
04579 }

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

References ast_party_caller::ani2, ARRAY_LEN, ast_channel_lock, ast_channel_unlock, ast_config_AST_SYSTEM_NAME, ast_debug, ast_eid_default, ast_eid_to_str(), AST_LIST_TRAVERSE, ast_party_id_presentation(), ast_rwlock_rdlock, ast_rwlock_unlock, ast_str_buffer(), ast_str_get_hint(), ast_str_set(), ast_str_substring(), ast_strdupa, ast_var_name(), ast_var_value(), ast_channel::caller, ast_channel::context, ast_channel::dialed, ast_channel::exten, globals, globalslock, ast_channel::hangupcause, ast_party_caller::id, ast_channel::name, ast_party_id::number, parse_variable_name(), ast_party_number::plan, ast_channel::priority, str, ast_party_dialed::transit_network_select, and ast_channel::uniqueid.

Referenced by ast_str_substitute_variables_full(), and pbx_retrieve_variable().

02987 {
02988    const char not_found = '\0';
02989    char *tmpvar;
02990    const char *ret;
02991    const char *s; /* the result */
02992    int offset, length;
02993    int i, need_substring;
02994    struct varshead *places[2] = { headp, &globals };  /* list of places where we may look */
02995 
02996    if (c) {
02997       ast_channel_lock(c);
02998       places[0] = &c->varshead;
02999    }
03000    /*
03001     * Make a copy of var because parse_variable_name() modifies the string.
03002     * Then if called directly, we might need to run substring() on the result;
03003     * remember this for later in 'need_substring', 'offset' and 'length'
03004     */
03005    tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */
03006    need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */);
03007 
03008    /*
03009     * Look first into predefined variables, then into variable lists.
03010     * Variable 's' points to the result, according to the following rules:
03011     * s == &not_found (set at the beginning) means that we did not find a
03012     * matching variable and need to look into more places.
03013     * If s != &not_found, s is a valid result string as follows:
03014     * s = NULL if the variable does not have a value;
03015     * you typically do this when looking for an unset predefined variable.
03016     * s = workspace if the result has been assembled there;
03017     * typically done when the result is built e.g. with an snprintf(),
03018     * so we don't need to do an additional copy.
03019     * s != workspace in case we have a string, that needs to be copied
03020     * (the ast_copy_string is done once for all at the end).
03021     * Typically done when the result is already available in some string.
03022     */
03023    s = &not_found;   /* default value */
03024    if (c) { /* This group requires a valid channel */
03025       /* Names with common parts are looked up a piece at a time using strncmp. */
03026       if (!strncmp(var, "CALL", 4)) {
03027          if (!strncmp(var + 4, "ING", 3)) {
03028             if (!strcmp(var + 7, "PRES")) {        /* CALLINGPRES */
03029                ast_str_set(str, maxlen, "%d",
03030                   ast_party_id_presentation(&c->caller.id));
03031                s = ast_str_buffer(*str);
03032             } else if (!strcmp(var + 7, "ANI2")) {    /* CALLINGANI2 */
03033                ast_str_set(str, maxlen, "%d", c->caller.ani2);
03034                s = ast_str_buffer(*str);
03035             } else if (!strcmp(var + 7, "TON")) {     /* CALLINGTON */
03036                ast_str_set(str, maxlen, "%d", c->caller.id.number.plan);
03037                s = ast_str_buffer(*str);
03038             } else if (!strcmp(var + 7, "TNS")) {     /* CALLINGTNS */
03039                ast_str_set(str, maxlen, "%d", c->dialed.transit_network_select);
03040                s = ast_str_buffer(*str);
03041             }
03042          }
03043       } else if (!strcmp(var, "HINT")) {
03044          s = ast_str_get_hint(str, maxlen, NULL, 0, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL;
03045       } else if (!strcmp(var, "HINTNAME")) {
03046          s = ast_str_get_hint(NULL, 0, str, maxlen, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL;
03047       } else if (!strcmp(var, "EXTEN")) {
03048          s = c->exten;
03049       } else if (!strcmp(var, "CONTEXT")) {
03050          s = c->context;
03051       } else if (!strcmp(var, "PRIORITY")) {
03052          ast_str_set(str, maxlen, "%d", c->priority);
03053          s = ast_str_buffer(*str);
03054       } else if (!strcmp(var, "CHANNEL")) {
03055          s = c->name;
03056       } else if (!strcmp(var, "UNIQUEID")) {
03057          s = c->uniqueid;
03058       } else if (!strcmp(var, "HANGUPCAUSE")) {
03059          ast_str_set(str, maxlen, "%d", c->hangupcause);
03060          s = ast_str_buffer(*str);
03061       }
03062    }
03063    if (s == &not_found) { /* look for more */
03064       if (!strcmp(var, "EPOCH")) {
03065          ast_str_set(str, maxlen, "%u", (int) time(NULL));
03066          s = ast_str_buffer(*str);
03067       } else if (!strcmp(var, "SYSTEMNAME")) {
03068          s = ast_config_AST_SYSTEM_NAME;
03069       } else if (!strcmp(var, "ENTITYID")) {
03070          char workspace[20];
03071          ast_eid_to_str(workspace, sizeof(workspace), &ast_eid_default);
03072          s = workspace;
03073       }
03074    }
03075    /* if not found, look into chanvars or global vars */
03076    for (i = 0; s == &not_found && i < ARRAY_LEN(places); i++) {
03077       struct ast_var_t *variables;
03078       if (!places[i])
03079          continue;
03080       if (places[i] == &globals)
03081          ast_rwlock_rdlock(&globalslock);
03082       AST_LIST_TRAVERSE(places[i], variables, entries) {
03083          if (!strcasecmp(ast_var_name(variables), var)) {
03084             s = ast_var_value(variables);
03085             break;
03086          }
03087       }
03088       if (places[i] == &globals)
03089          ast_rwlock_unlock(&globalslock);
03090    }
03091    if (s == &not_found || s == NULL) {
03092       ast_debug(5, "Result of '%s' is NULL\n", var);
03093       ret = NULL;
03094    } else {
03095       ast_debug(5, "Result of '%s' is '%s'\n", var, s);
03096       if (s != ast_str_buffer(*str)) {
03097          ast_str_set(str, maxlen, "%s", s);
03098       }
03099       ret = ast_str_buffer(*str);
03100       if (need_substring) {
03101          ret = ast_str_substring(*str, offset, length);
03102          ast_debug(2, "Final result of '%s' is '%s'\n", var, ret);
03103       }
03104    }
03105 
03106    if (c) {
03107       ast_channel_unlock(c);
03108    }
03109    return ret;
03110 }

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

References ast_str_substitute_variables_full().

Referenced by _macro_exec(), acf_odbc_read(), acf_odbc_write(), config_curl(), custom_log(), cut_internal(), destroy_curl(), exec_exec(), func_mchan_read(), function_eval2(), function_fieldnum_helper(), function_fieldqty_helper(), handle_getvariablefull(), import_helper(), listfilter(), make_email_file(), realtime_curl(), realtime_multi_curl(), replace(), require_curl(), sendmail(), sendpage(), shift_pop(), store_curl(), syslog_log(), tryexec_exec(), unshift_push(), update2_curl(), and update_curl().

03765 {
03766    size_t used;
03767    ast_str_substitute_variables_full(buf, maxlen, chan, NULL, templ, &used);
03768 }

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

03589 {
03590    /* Substitutes variables into buf, based on string templ */
03591    char *cp4 = NULL;
03592    const char *tmp, *whereweare;
03593    int orig_size = 0;
03594    int offset, offset2, isfunction;
03595    const char *nextvar, *nextexp, *nextthing;
03596    const char *vars, *vare;
03597    char *finalvars;
03598    int pos, brackets, needsub, len;
03599    struct ast_str *substr1 = ast_str_create(16), *substr2 = NULL, *substr3 = ast_str_create(16);
03600 
03601    ast_str_reset(*buf);
03602    whereweare = tmp = templ;
03603    while (!ast_strlen_zero(whereweare)) {
03604       /* Assume we're copying the whole remaining string */
03605       pos = strlen(whereweare);
03606       nextvar = NULL;
03607       nextexp = NULL;
03608       nextthing = strchr(whereweare, '$');
03609       if (nextthing) {
03610          switch (nextthing[1]) {
03611          case '{':
03612             nextvar = nextthing;
03613             pos = nextvar - whereweare;
03614             break;
03615          case '[':
03616             nextexp = nextthing;
03617             pos = nextexp - whereweare;
03618             break;
03619          default:
03620             pos = 1;
03621          }
03622       }
03623 
03624       if (pos) {
03625          /* Copy that many bytes */
03626          ast_str_append_substr(buf, maxlen, whereweare, pos);
03627 
03628          templ += pos;
03629          whereweare += pos;
03630       }
03631 
03632       if (nextvar) {
03633          /* We have a variable.  Find the start and end, and determine
03634             if we are going to have to recursively call ourselves on the
03635             contents */
03636          vars = vare = nextvar + 2;
03637          brackets = 1;
03638          needsub = 0;
03639 
03640          /* Find the end of it */
03641          while (brackets && *vare) {
03642             if ((vare[0] == '$') && (vare[1] == '{')) {
03643                needsub++;
03644             } else if (vare[0] == '{') {
03645                brackets++;
03646             } else if (vare[0] == '}') {
03647                brackets--;
03648             } else if ((vare[0] == '$') && (vare[1] == '['))
03649                needsub++;
03650             vare++;
03651          }
03652          if (brackets)
03653             ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n");
03654          len = vare - vars - 1;
03655 
03656          /* Skip totally over variable string */
03657          whereweare += (len + 3);
03658 
03659          /* Store variable name (and truncate) */
03660          ast_str_set_substr(&substr1, 0, vars, len);
03661          ast_debug(5, "Evaluating '%s' (from '%s' len %d)\n", ast_str_buffer(substr1), vars, len);
03662 
03663          /* Substitute if necessary */
03664          if (needsub) {
03665             size_t used;
03666             if (!substr2) {
03667                substr2 = ast_str_create(16);
03668             }
03669 
03670             ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used);
03671             finalvars = ast_str_buffer(substr2);
03672          } else {
03673             finalvars = ast_str_buffer(substr1);
03674          }
03675 
03676          parse_variable_name(finalvars, &offset, &offset2, &isfunction);
03677          if (isfunction) {
03678             /* Evaluate function */
03679             if (c || !headp) {
03680                cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3);
03681             } else {
03682                struct varshead old;
03683                struct ast_channel *bogus = ast_dummy_channel_alloc();
03684                if (bogus) {
03685                   memcpy(&old, &bogus->varshead, sizeof(old));
03686                   memcpy(&bogus->varshead, headp, sizeof(bogus->varshead));
03687                   cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3);
03688                   /* Don't deallocate the varshead that was passed in */
03689                   memcpy(&bogus->varshead, &old, sizeof(bogus->varshead));
03690                   ast_channel_release(bogus);
03691                } else {
03692                   ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution.  Function results may be blank.\n");
03693                }
03694             }
03695             ast_debug(2, "Function result is '%s'\n", cp4 ? cp4 : "(null)");
03696          } else {
03697             /* Retrieve variable value */
03698             ast_str_retrieve_variable(&substr3, 0, c, headp, finalvars);
03699             cp4 = ast_str_buffer(substr3);
03700          }
03701          if (cp4) {
03702             ast_str_substring(substr3, offset, offset2);
03703             ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3));
03704          }
03705       } else if (nextexp) {
03706          /* We have an expression.  Find the start and end, and determine
03707             if we are going to have to recursively call ourselves on the
03708             contents */
03709          vars = vare = nextexp + 2;
03710          brackets = 1;
03711          needsub = 0;
03712 
03713          /* Find the end of it */
03714          while (brackets && *vare) {
03715             if ((vare[0] == '$') && (vare[1] == '[')) {
03716                needsub++;
03717                brackets++;
03718                vare++;
03719             } else if (vare[0] == '[') {
03720                brackets++;
03721             } else if (vare[0] == ']') {
03722                brackets--;
03723             } else if ((vare[0] == '$') && (vare[1] == '{')) {
03724                needsub++;
03725                vare++;
03726             }
03727             vare++;
03728          }
03729          if (brackets)
03730             ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n");
03731          len = vare - vars - 1;
03732 
03733          /* Skip totally over expression */
03734          whereweare += (len + 3);
03735 
03736          /* Store variable name (and truncate) */
03737          ast_str_set_substr(&substr1, 0, vars, len);
03738 
03739          /* Substitute if necessary */
03740          if (needsub) {
03741             size_t used;
03742             if (!substr2) {
03743                substr2 = ast_str_create(16);
03744             }
03745 
03746             ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used);
03747             finalvars = ast_str_buffer(substr2);
03748          } else {
03749             finalvars = ast_str_buffer(substr1);
03750          }
03751 
03752          if (ast_str_expr(&substr3, 0, c, finalvars)) {
03753             ast_debug(2, "Expression result is '%s'\n", ast_str_buffer(substr3));
03754          }
03755          ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3));
03756       }
03757    }
03758    *used = ast_str_strlen(*buf) - orig_size;
03759    ast_free(substr1);
03760    ast_free(substr2);
03761    ast_free(substr3);
03762 }

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

03771 {
03772    size_t used;
03773    ast_str_substitute_variables_full(buf, maxlen, NULL, headp, templ, &used);
03774 }

int ast_unlock_context ( struct ast_context con  ) 

Return values:
Unlocks the given context
Parameters:
con context to unlock
Return values:
0 on success
-1 on failure

Definition at line 9931 of file pbx.c.

References ast_rwlock_unlock, and ast_context::lock.

Referenced by __ast_context_destroy(), _macro_exec(), 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(), ast_context_remove_switch2(), 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().

09932 {
09933    return ast_rwlock_unlock(&con->lock);
09934 }

int ast_unlock_contexts ( void   ) 

Unlocks contexts.

Return values:
0 on success
-1 on failure

Definition at line 9913 of file pbx.c.

References ast_mutex_unlock, and conlock.

Referenced by _macro_exec(), ast_add_extension(), ast_context_add_ignorepat(), ast_context_add_include(), ast_context_add_switch(), ast_context_destroy(), ast_context_find(), ast_context_find_or_create(), ast_context_lockmacro(), ast_context_remove_extension_callerid(), ast_context_remove_ignorepat(), ast_context_remove_include(), ast_context_remove_switch(), ast_context_unlockmacro(), ast_hint_extension(), ast_merge_contexts_and_delete(), complete_dialplan_add_extension(), complete_dialplan_add_ignorepat(), complete_dialplan_add_include(), complete_dialplan_remove_extension(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), complete_show_dialplan_context(), dundi_precache_full(), find_context_locked(), find_matching_endwhile(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), pbx_extension_helper(), show_debug_helper(), show_dialplan_helper(), and unreference_cached_app().

09914 {
09915    return ast_mutex_unlock(&conlock);
09916 }

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

References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and ast_switch::list.

Referenced by __unload_module(), and unload_module().

05613 {
05614    AST_RWLIST_WRLOCK(&switches);
05615    AST_RWLIST_REMOVE(&switches, sw, list);
05616    AST_RWLIST_UNLOCK(&switches);
05617 }

struct ast_exten* ast_walk_context_extensions ( struct ast_context con,
struct ast_exten priority 
)

Definition at line 10045 of file pbx.c.

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

10047 {
10048    if (!exten)
10049       return con ? con->root : NULL;
10050    else
10051       return exten->next;
10052 }

struct ast_ignorepat* ast_walk_context_ignorepats ( struct ast_context con,
struct ast_ignorepat ip 
)

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

10080 {
10081    if (!ip)
10082       return con ? con->ignorepats : NULL;
10083    else
10084       return ip->next;
10085 }

struct ast_include* ast_walk_context_includes ( struct ast_context con,
struct ast_include inc 
)

Definition at line 10069 of file pbx.c.

References ast_context::includes, and ast_include::next.

Referenced by ast_context_verify_includes(), complete_dialplan_remove_include(), context_merge_incls_swits_igps_other_registrars(), find_matching_priority(), handle_cli_dialplan_save(), lookup_ci(), manager_show_dialplan_helper(), and show_dialplan_helper().

10071 {
10072    if (!inc)
10073       return con ? con->includes : NULL;
10074    else
10075       return inc->next;
10076 }

struct ast_sw* ast_walk_context_switches ( struct ast_context con,
struct ast_sw sw 
)

Definition at line 10054 of file pbx.c.

References ast_context::alts, AST_LIST_FIRST, AST_LIST_NEXT, and ast_sw::list.

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

10056 {
10057    if (!sw)
10058       return con ? AST_LIST_FIRST(&con->alts) : NULL;
10059    else
10060       return AST_LIST_NEXT(sw, list);
10061 }

struct ast_context* ast_walk_contexts ( struct ast_context con  ) 

Definition at line 10040 of file pbx.c.

References contexts, and ast_context::next.

Referenced by _macro_exec(), ast_context_find(), complete_dialplan_add_extension(), complete_dialplan_add_ignorepat(), complete_dialplan_add_include(), complete_dialplan_remove_extension(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), complete_show_dialplan_context(), dundi_precache_full(), find_matching_endwhile(), find_matching_priority(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), pbx_load_module(), show_debug_helper(), show_dialplan_helper(), and unreference_cached_app().

10041 {
10042    return con ? con->next : contexts;
10043 }

struct ast_exten* ast_walk_extension_priorities ( struct ast_exten exten,
struct ast_exten priority 
)

Definition at line 10063 of file pbx.c.

References exten, and ast_exten::priority.

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

10065 {
10066    return priority ? priority->peer : exten;
10067 }

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

09922 {
09923    return ast_rwlock_wrlock(&con->lock);
09924 }

int ast_wrlock_contexts ( void   ) 

Write locks the context list.

Return values:
0 on success
-1 on error

Definition at line 9903 of file pbx.c.

References ast_mutex_lock, and conlock.

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

09904 {
09905    return ast_mutex_lock(&conlock);
09906 }

void pbx_builtin_clear_globals ( void   ) 

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

09698 {
09699    struct ast_var_t *vardata;
09700 
09701    ast_rwlock_wrlock(&globalslock);
09702    while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries)))
09703       ast_var_delete(vardata);
09704    ast_rwlock_unlock(&globalslock);
09705 }

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 9459 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, and globalslock.

Referenced by _macro_exec(), _while_exec(), agentmonitoroutgoing_exec(), analog_call(), append_channel_vars(), array(), ast_bridge_call(), ast_bridge_timelimit(), ast_call_forward(), ast_channel_connected_line_macro(), ast_channel_redirecting_macro(), ast_eivr_getvariable(), ast_hangup(), ast_monitor_stop(), bridge_play_sounds(), builtin_atxfer(), builtin_automixmonitor(), builtin_automonitor(), check_goto_on_transfer(), common_exec(), conf_run(), confbridge_exec(), crement_function_read(), dahdi_hangup(), dahdi_r2_answer(), dahdi_r2_get_channel_category(), dial_exec_full(), do_forward(), dundi_exec(), dundi_helper(), feature_interpret(), find_by_mark(), findparkinglotname(), func_channel_read(), generic_fax_exec(), get_also_info(), get_index(), get_refer_info(), global_read(), hash_read(), iax2_call(), iax2_exec(), import_ch(), leave_voicemail(), local_attended_transfer(), local_hangup(), local_read(), login_exec(), macro_fixup(), minivm_delete_exec(), minivm_notify_exec(), misdn_answer(), misdn_hangup(), morsecode_exec(), notify_new_message(), oh323_call(), oh323_hangup(), park_call_full(), park_space_reserve(), pbx_builtin_background(), pbx_builtin_gotoiftime(), queue_exec(), real_ctx(), receivefax_exec(), retrydial_exec(), ring_entry(), run_agi(), sendfax_exec(), set_config_flags(), set_local_info(), sig_pri_call(), sig_pri_hangup(), sip_addheader(), sla_trunk_exec(), speech_background(), try_suggested_sip_codec(), and update_bridge_vars().

09460 {
09461    struct ast_var_t *variables;
09462    const char *ret = NULL;
09463    int i;
09464    struct varshead *places[2] = { NULL, &globals };
09465 
09466    if (!name)
09467       return NULL;
09468 
09469    if (chan) {
09470       ast_channel_lock(chan);
09471       places[0] = &chan->varshead;
09472    }
09473 
09474    for (i = 0; i < 2; i++) {
09475       if (!places[i])
09476          continue;
09477       if (places[i] == &globals)
09478          ast_rwlock_rdlock(&globalslock);
09479       AST_LIST_TRAVERSE(places[i], variables, entries) {
09480          if (!strcmp(name, ast_var_name(variables))) {
09481             ret = ast_var_value(variables);
09482             break;
09483          }
09484       }
09485       if (places[i] == &globals)
09486          ast_rwlock_unlock(&globalslock);
09487       if (ret)
09488          break;
09489    }
09490 
09491    if (chan)
09492       ast_channel_unlock(chan);
09493 
09494    return ret;
09495 }

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 9497 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, and LOG_WARNING.

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

09498 {
09499    struct ast_var_t *newvariable;
09500    struct varshead *headp;
09501 
09502    if (name[strlen(name)-1] == ')') {
09503       char *function = ast_strdupa(name);
09504 
09505       ast_log(LOG_WARNING, "Cannot push a value onto a function\n");
09506       ast_func_write(chan, function, value);
09507       return;
09508    }
09509 
09510    if (chan) {
09511       ast_channel_lock(chan);
09512       headp = &chan->varshead;
09513    } else {
09514       ast_rwlock_wrlock(&globalslock);
09515       headp = &globals;
09516    }
09517 
09518    if (value) {
09519       if (headp == &globals)
09520          ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value);
09521       newvariable = ast_var_assign(name, value);
09522       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
09523    }
09524 
09525    if (chan)
09526       ast_channel_unlock(chan);
09527    else
09528       ast_rwlock_unlock(&globalslock);
09529 }

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

Definition at line 3124 of file pbx.c.

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

Referenced by __ast_pbx_run().

03125 {
03126    struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL);
03127    struct pbx_exception *exception = NULL;
03128 
03129    if (!ds) {
03130       ds = ast_datastore_alloc(&exception_store_info, NULL);
03131       if (!ds)
03132          return -1;
03133       if (!(exception = ast_calloc_with_stringfields(1, struct pbx_exception, 128))) {
03134          ast_datastore_free(ds);
03135          return -1;
03136       }
03137       ds->data = exception;
03138       ast_channel_datastore_add(chan, ds);
03139    } else
03140       exception = ds->data;
03141 
03142    ast_string_field_set(exception, reason, reason);
03143    ast_string_field_set(exception, context, chan->context);
03144    ast_string_field_set(exception, exten, chan->exten);
03145    exception->priority = chan->priority;
03146    set_ext_pri(chan, "e", 0);
03147    return 0;
03148 }

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

09429 {
09430    struct ast_var_t *variables;
09431    const char *var, *val;
09432    int total = 0;
09433 
09434    if (!chan)
09435       return 0;
09436 
09437    ast_str_reset(*buf);
09438 
09439    ast_channel_lock(chan);
09440 
09441    AST_LIST_TRAVERSE(&chan->varshead, variables, entries) {
09442       if ((var = ast_var_name(variables)) && (val = ast_var_value(variables))
09443          /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */
09444          ) {
09445          if (ast_str_append(buf, 0, "%s=%s\n", var, val) < 0) {
09446             ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
09447             break;
09448          } else
09449             total++;
09450       } else
09451          break;
09452    }
09453 
09454    ast_channel_unlock(chan);
09455 
09456    return total;
09457 }

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

09590 {
09591    char *name, *value, *mydata;
09592 
09593    if (ast_compat_app_set) {
09594       return pbx_builtin_setvar_multiple(chan, data);
09595    }
09596 
09597    if (ast_strlen_zero(data)) {
09598       ast_log(LOG_WARNING, "Set requires one variable name/value pair.\n");
09599       return 0;
09600    }
09601 
09602    mydata = ast_strdupa(data);
09603    name = strsep(&mydata, "=");
09604    value = mydata;
09605    if (!value) {
09606       ast_log(LOG_WARNING, "Set requires an '=' to be a valid assignment.\n");
09607       return 0;
09608    }
09609 
09610    if (strchr(name, ' ')) {
09611       ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, mydata);
09612    }
09613 
09614    pbx_builtin_setvar_helper(chan, name, value);
09615 
09616    return 0;
09617 }

int pbx_builtin_setvar_helper ( struct ast_channel chan,
const char *  name,
const char *  value 
)

Add a variable to the channel variable stack, removing the most recently set value for the same name.

Note:
Will lock the channel. May also be used to set a channel dialplan function to a particular value.
See also:
ast_func_write
Returns:
-1 if the dialplan function fails to be set
Version:
1.8 changed the function to return an error code

Definition at line 9531 of file pbx.c.

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

Referenced by __analog_ss_thread(), __oh323_new(), _macro_exec(), _while_exec(), acf_curl_helper(), acf_fetch(), acf_odbc_read(), acf_odbc_write(), acf_transaction_write(), action_atxfer(), action_setvar(), admin_exec(), agi_exec_full(), aji_status_exec(), analog_ss_thread(), aqm_exec(), array(), ast_bridge_call(), ast_cc_agent_set_interfaces_chanvar(), ast_cel_fabricate_channel_from_event(), ast_eivr_setvariable(), ast_iax2_new(), ast_monitor_start(), ast_monitor_stop(), ast_pbx_outgoing_exten(), ast_rtp_instance_set_stats_vars(), ast_set_cc_interfaces_chanvar(), ast_set_variables(), asyncgoto_exec(), background_detect_exec(), bridge_exec(), bridge_play_sounds(), builtin_atxfer(), builtin_automixmonitor(), builtin_automonitor(), builtin_blindtransfer(), cb_events(), ccreq_exec(), chanavail_exec(), channel_spy(), commit_exec(), conf_run(), controlplayback_exec(), count_exec(), crement_function_read(), dahdi_handle_dtmf(), dahdi_new(), dial_exec_full(), do_waiting(), end_bridge_callback(), export_aoc_vars(), export_ch(), feature_exec_app(), feature_request_and_dial(), frame_set_var(), func_mchan_write(), function_db_delete(), function_db_exists(), function_db_read(), function_realtime_store(), generic_recall(), get_rdnis(), get_refer_info(), global_write(), gosub_release_frame(), handle_incoming(), handle_request_bye(), handle_request_refer(), handle_set_chanvar(), handle_set_global(), handle_setvariable(), hash_read(), hash_write(), isAnsweringMachine(), leave_queue(), leave_voicemail(), local_hangup(), lua_set_variable(), lua_set_variable_value(), macro_fixup(), manage_parkinglot(), mgcp_new(), minivm_accmess_exec(), minivm_delete_exec(), minivm_greet_exec(), minivm_notify_exec(), minivm_record_exec(), misdn_call(), mixmonitor_exec(), my_handle_dtmf(), originate_exec(), ospauth_exec(), ospfinished_exec(), osplookup_exec(), ospnext_exec(), park_exec_full(), parse_moved_contact(), pbx_builtin_background(), pbx_builtin_gotoiftime(), pbx_builtin_importvar(), pbx_builtin_setvar(), pbx_builtin_setvar_multiple(), pbx_load_config(), phase_e_handler(), play_message_datetime(), playback_exec(), pqm_exec(), prep_email_sub_vars(), process_ast_dsp(), process_sdp(), read_exec(), readexten_exec(), readfile_exec(), receivefax_exec(), record_exec(), reload_module(), return_exec(), rollback_exec(), rotate_file(), rpt_exec(), rqm_exec(), sendfax_exec(), sendimage_exec(), sendtext_exec(), sendurl_exec(), set(), set_channel_variables(), set_queue_result(), shift_pop(), sig_pri_new_ast_channel(), sip_addheader(), sip_hangup(), sip_new(), sip_read(), skinny_new(), sla_calc_trunk_timeouts(), sla_station_exec(), sla_trunk_exec(), socket_process(), speech_create(), start_monitor_exec(), system_exec_helper(), testtime_write(), transfer_exec(), transmit(), tryexec_exec(), unshift_push(), update_bridge_vars(), update_qe_rule(), upqm_exec(), vm_box_exists(), vm_exec(), vmauthenticate(), waituntil_exec(), and zapateller_exec().

09532 {
09533    struct ast_var_t *newvariable;
09534    struct varshead *headp;
09535    const char *nametail = name;
09536 
09537    if (name[strlen(name) - 1] == ')') {
09538       char *function = ast_strdupa(name);
09539 
09540       return ast_func_write(chan, function, value);
09541    }
09542 
09543    if (chan) {
09544       ast_channel_lock(chan);
09545       headp = &chan->varshead;
09546    } else {
09547       ast_rwlock_wrlock(&globalslock);
09548       headp = &globals;
09549    }
09550 
09551    /* For comparison purposes, we have to strip leading underscores */
09552    if (*nametail == '_') {
09553       nametail++;
09554       if (*nametail == '_')
09555          nametail++;
09556    }
09557 
09558    AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) {
09559       if (strcmp(ast_var_name(newvariable), nametail) == 0) {
09560          /* there is already such a variable, delete it */
09561          AST_LIST_REMOVE_CURRENT(entries);
09562          ast_var_delete(newvariable);
09563          break;
09564       }
09565    }
09566    AST_LIST_TRAVERSE_SAFE_END;
09567 
09568    if (value) {
09569       if (headp == &globals)
09570          ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value);
09571       newvariable = ast_var_assign(name, value);
09572       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
09573       manager_event(EVENT_FLAG_DIALPLAN, "VarSet",
09574          "Channel: %s\r\n"
09575          "Variable: %s\r\n"
09576          "Value: %s\r\n"
09577          "Uniqueid: %s\r\n",
09578          chan ? chan->name : "none", name, value,
09579          chan ? chan->uniqueid : "none");
09580    }
09581 
09582    if (chan)
09583       ast_channel_unlock(chan);
09584    else
09585       ast_rwlock_unlock(&globalslock);
09586    return 0;
09587 }

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

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

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

09620 {
09621    char *data;
09622    int x;
09623    AST_DECLARE_APP_ARGS(args,
09624       AST_APP_ARG(pair)[24];
09625    );
09626    AST_DECLARE_APP_ARGS(pair,
09627       AST_APP_ARG(name);
09628       AST_APP_ARG(value);
09629    );
09630 
09631    if (ast_strlen_zero(vdata)) {
09632       ast_log(LOG_WARNING, "MSet requires at least one variable name/value pair.\n");
09633       return 0;
09634    }
09635 
09636    data = ast_strdupa(vdata);
09637    AST_STANDARD_APP_ARGS(args, data);
09638 
09639    for (x = 0; x < args.argc; x++) {
09640       AST_NONSTANDARD_APP_ARGS(pair, args.pair[x], '=');
09641       if (pair.argc == 2) {
09642          pbx_builtin_setvar_helper(chan, pair.name, pair.value);
09643          if (strchr(pair.name, ' '))
09644             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);
09645       } else if (!chan) {
09646          ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '='\n", pair.name);
09647       } else {
09648          ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '=' (in %s@%s:%d\n", pair.name, chan->exten, chan->context, chan->priority);
09649       }
09650    }
09651 
09652    return 0;
09653 }

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

References ast_strlen_zero().

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

09708 {
09709    int res;
09710    if (ast_strlen_zero(condition)) {                /* NULL or empty strings are false */
09711       return 0;
09712    } else if (sscanf(condition, "%30d", &res) == 1) { /* Numbers are evaluated for truth */
09713       return res;
09714    } else {                                         /* Strings are true */
09715       return 1;
09716    }
09717 }

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

References __ast_module_user_add(), __ast_module_user_remove(), app, 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, LOG_WARNING, 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(), and tryexec_exec().

01381 {
01382    int res;
01383    struct ast_module_user *u = NULL;
01384    const char *saved_c_appl;
01385    const char *saved_c_data;
01386 
01387    if (c->cdr && !ast_check_hangup(c))
01388       ast_cdr_setapp(c->cdr, app->name, data);
01389 
01390    /* save channel values */
01391    saved_c_appl= c->appl;
01392    saved_c_data= c->data;
01393 
01394    c->appl = app->name;
01395    c->data = data;
01396    ast_cel_report_event(c, AST_CEL_APP_START, NULL, NULL, NULL);
01397 
01398    if (app->module)
01399       u = __ast_module_user_add(app->module, c);
01400    if (strcasecmp(app->name, "system") && !ast_strlen_zero(data) &&
01401          strchr(data, '|') && !strchr(data, ',') && !ast_opt_dont_warn) {
01402       ast_log(LOG_WARNING, "The application delimiter is now the comma, not "
01403          "the pipe.  Did you forget to convert your dialplan?  (%s(%s))\n",
01404          app->name, (char *) data);
01405    }
01406    res = app->execute(c, S_OR(data, ""));
01407    if (app->module && u)
01408       __ast_module_user_remove(app->module, u);
01409    ast_cel_report_event(c, AST_CEL_APP_END, NULL, NULL, NULL);
01410    /* restore channel values */
01411    c->appl = saved_c_appl;
01412    c->data = saved_c_data;
01413    return res;
01414 }

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 
)

Definition at line 2550 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(), pbx_find_info::data, ast_sw::data, E_CANMATCH, E_FINDLABEL, E_MATCHMORE, ast_sw::eval, ast_switch::exists, scoreboard::exten, ast_exten::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, fake_context::name, ast_sw::name, ast_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(), ast_parking_ext_valid(), check_goto(), check_pval_item(), pbx_extension_helper(), pbx_find_extension(), and register_peer_exten().

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

struct ast_app* pbx_findapp ( const char *  app  ) 

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

References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_app::list, 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(), and tryexec_exec().

01423 {
01424    struct ast_app *tmp;
01425 
01426    AST_RWLIST_RDLOCK(&apps);
01427    AST_RWLIST_TRAVERSE(&apps, tmp, list) {
01428       if (!strcasecmp(tmp->name, app))
01429          break;
01430    }
01431    AST_RWLIST_UNLOCK(&apps);
01432 
01433    return tmp;
01434 }

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:
See also

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

02976 {
02977    struct ast_str *str = ast_str_create(16);
02978    const char *cret;
02979 
02980    cret = ast_str_retrieve_variable(&str, 0, c, headp, var);
02981    ast_copy_string(workspace, ast_str_buffer(str), workspacelen);
02982    *ret = cret ? workspace : NULL;
02983    ast_free(str);
02984 }

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

References autofallthrough.

Referenced by pbx_load_module().

05078 {
05079    int oldval = autofallthrough;
05080    autofallthrough = newval;
05081    return oldval;
05082 }

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

References extenpatternmatchnew.

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

05085 {
05086    int oldval = extenpatternmatchnew;
05087    extenpatternmatchnew = newval;
05088    return oldval;
05089 }

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

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

Referenced by pbx_load_module().

05092 {
05093    if (overrideswitch) {
05094       ast_free(overrideswitch);
05095    }
05096    if (!ast_strlen_zero(newval)) {
05097       overrideswitch = ast_strdup(newval);
05098    } else {
05099       overrideswitch = NULL;
05100    }
05101 }

void pbx_substitute_variables_helper ( struct ast_channel c,
const char *  cp1,
char *  cp2,
int  count 
)

Definition at line 3972 of file pbx.c.

References pbx_substitute_variables_helper_full(), and ast_channel::varshead.

Referenced by add_extensions(), ast_add_extension2_lockopt(), function_eval(), get_manager_event_info(), get_mapping_weight(), import_helper(), launch_monitor_thread(), manager_log(), pbx_builtin_importvar(), pbx_find_extension(), pbx_load_config(), pbx_substitute_variables(), rotate_file(), rpt_do_lstats(), rpt_exec(), substituted(), and write_cdr().

03973 {
03974    size_t used;
03975    pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count, &used);
03976 }

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

03777 {
03778    /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!!  */
03779    char *cp4 = NULL;
03780    const char *tmp, *whereweare, *orig_cp2 = cp2;
03781    int length, offset, offset2, isfunction;
03782    char *workspace = NULL;
03783    char *ltmp = NULL, *var = NULL;
03784    char *nextvar, *nextexp, *nextthing;
03785    char *vars, *vare;
03786    int pos, brackets, needsub, len;
03787 
03788    *cp2 = 0; /* just in case nothing ends up there */
03789    whereweare=tmp=cp1;
03790    while (!ast_strlen_zero(whereweare) && count) {
03791       /* Assume we're copying the whole remaining string */
03792       pos = strlen(whereweare);
03793       nextvar = NULL;
03794       nextexp = NULL;
03795       nextthing = strchr(whereweare, '$');
03796       if (nextthing) {
03797          switch (nextthing[1]) {
03798          case '{':
03799             nextvar = nextthing;
03800             pos = nextvar - whereweare;
03801             break;
03802          case '[':
03803             nextexp = nextthing;
03804             pos = nextexp - whereweare;
03805             break;
03806          default:
03807             pos = 1;
03808          }
03809       }
03810 
03811       if (pos) {
03812          /* Can't copy more than 'count' bytes */
03813          if (pos > count)
03814             pos = count;
03815 
03816          /* Copy that many bytes */
03817          memcpy(cp2, whereweare, pos);
03818 
03819          count -= pos;
03820          cp2 += pos;
03821          whereweare += pos;
03822          *cp2 = 0;
03823       }
03824 
03825       if (nextvar) {
03826          /* We have a variable.  Find the start and end, and determine
03827             if we are going to have to recursively call ourselves on the
03828             contents */
03829          vars = vare = nextvar + 2;
03830          brackets = 1;
03831          needsub = 0;
03832 
03833          /* Find the end of it */
03834          while (brackets && *vare) {
03835             if ((vare[0] == '$') && (vare[1] == '{')) {
03836                needsub++;
03837             } else if (vare[0] == '{') {
03838                brackets++;
03839             } else if (vare[0] == '}') {
03840                brackets--;
03841             } else if ((vare[0] == '$') && (vare[1] == '['))
03842                needsub++;
03843             vare++;
03844          }
03845          if (brackets)
03846             ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n");
03847          len = vare - vars - 1;
03848 
03849          /* Skip totally over variable string */
03850          whereweare += (len + 3);
03851 
03852          if (!var)
03853             var = alloca(VAR_BUF_SIZE);
03854 
03855          /* Store variable name (and truncate) */
03856          ast_copy_string(var, vars, len + 1);
03857 
03858          /* Substitute if necessary */
03859          if (needsub) {
03860             size_t used;
03861             if (!ltmp)
03862                ltmp = alloca(VAR_BUF_SIZE);
03863 
03864             pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used);
03865             vars = ltmp;
03866          } else {
03867             vars = var;
03868          }
03869 
03870          if (!workspace)
03871             workspace = alloca(VAR_BUF_SIZE);
03872 
03873          workspace[0] = '\0';
03874 
03875          parse_variable_name(vars, &offset, &offset2, &isfunction);
03876          if (isfunction) {
03877             /* Evaluate function */
03878             if (c || !headp)
03879                cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
03880             else {
03881                struct varshead old;
03882                struct ast_channel *c = ast_dummy_channel_alloc();
03883                if (c) {
03884                   memcpy(&old, &c->varshead, sizeof(old));
03885                   memcpy(&c->varshead, headp, sizeof(c->varshead));
03886                   cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
03887                   /* Don't deallocate the varshead that was passed in */
03888                   memcpy(&c->varshead, &old, sizeof(c->varshead));
03889                   c = ast_channel_release(c);
03890                } else {
03891                   ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution.  Function results may be blank.\n");
03892                }
03893             }
03894             ast_debug(2, "Function result is '%s'\n", cp4 ? cp4 : "(null)");
03895          } else {
03896             /* Retrieve variable value */
03897             pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp);
03898          }
03899          if (cp4) {
03900             cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE);
03901 
03902             length = strlen(cp4);
03903             if (length > count)
03904                length = count;
03905             memcpy(cp2, cp4, length);
03906             count -= length;
03907             cp2 += length;
03908             *cp2 = 0;
03909          }
03910       } else if (nextexp) {
03911          /* We have an expression.  Find the start and end, and determine
03912             if we are going to have to recursively call ourselves on the
03913             contents */
03914          vars = vare = nextexp + 2;
03915          brackets = 1;
03916          needsub = 0;
03917 
03918          /* Find the end of it */
03919          while (brackets && *vare) {
03920             if ((vare[0] == '$') && (vare[1] == '[')) {
03921                needsub++;
03922                brackets++;
03923                vare++;
03924             } else if (vare[0] == '[') {
03925                brackets++;
03926             } else if (vare[0] == ']') {
03927                brackets--;
03928             } else if ((vare[0] == '$') && (vare[1] == '{')) {
03929                needsub++;
03930                vare++;
03931             }
03932             vare++;
03933          }
03934          if (brackets)
03935             ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n");
03936          len = vare - vars - 1;
03937 
03938          /* Skip totally over expression */
03939          whereweare += (len + 3);
03940 
03941          if (!var)
03942             var = alloca(VAR_BUF_SIZE);
03943 
03944          /* Store variable name (and truncate) */
03945          ast_copy_string(var, vars, len + 1);
03946 
03947          /* Substitute if necessary */
03948          if (needsub) {
03949             size_t used;
03950             if (!ltmp)
03951                ltmp = alloca(VAR_BUF_SIZE);
03952 
03953             pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used);
03954             vars = ltmp;
03955          } else {
03956             vars = var;
03957          }
03958 
03959          length = ast_expr(vars, cp2, count, c);
03960 
03961          if (length) {
03962             ast_debug(1, "Expression result is '%s'\n", cp2);
03963             count -= length;
03964             cp2 += length;
03965             *cp2 = 0;
03966          }
03967       }
03968    }
03969    *used = cp2 - orig_cp2;
03970 }

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

Definition at line 3978 of file pbx.c.

References pbx_substitute_variables_helper_full().

Referenced by dundi_lookup_local(), and loopback_subst().

03979 {
03980    size_t used;
03981    pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count, &used);
03982 }


Generated on Mon Jun 27 16:51:17 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7