Wed Apr 6 11:30:07 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 3414 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().

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

int ast_active_calls ( void   ) 

Retrieve the number of active calls.

Definition at line 5064 of file pbx.c.

References countcalls.

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

05065 {
05066    return countcalls;
05067 }

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

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

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

08061 {
08062    return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid, application, data, datad, registrar, 1, 1);
08063 }

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

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

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

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

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

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

References __ast_goto_if_exists().

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

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

References pbx_parseable_goto().

Referenced by asyncgoto_exec(), and handle_redirect().

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

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

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

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

04594 {
04595    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0);
04596 }

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

References ast_check_timing2(), and ast_tvnow().

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

07410 {
07411    return ast_check_timing2(i, ast_tvnow());
07412 }

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

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

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

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

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

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

Referenced by handle_cli_dialplan_add_ignorepat().

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

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

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

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

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

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

Referenced by handle_cli_dialplan_add_include().

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

References ast_context_remove_extension_callerid().

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

05253 {
05254    return ast_context_remove_extension_callerid(context, extension, priority, NULL, 0, registrar);
05255 }

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

References ast_context_remove_extension_callerid2().

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

05280 {
05281    return ast_context_remove_extension_callerid2(con, extension, priority, NULL, 0, registrar, already_locked);
05282 }

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

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

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

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

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

Definition at line 7605 of file pbx.c.

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

Referenced by handle_cli_dialplan_remove_ignorepat().

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

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

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

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

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

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

Referenced by handle_cli_dialplan_remove_include().

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

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

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

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

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

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

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

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

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

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

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

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

struct ast_custom_function* ast_custom_function_find ( const char *  name  ) 

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

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

int ast_custom_function_unregister ( struct ast_custom_function acf  ) 

Unregister a custom function.

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

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

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

07449 {
07450    if (i->timezone) {
07451       ast_free(i->timezone);
07452       i->timezone = NULL;
07453    }
07454    return 0;
07455 }

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

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

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

04579 {
04580    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0);
04581 }

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

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

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

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

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

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

References ext_cmp().

Referenced by lua_extension_cmp().

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

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

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

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

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

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

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

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

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

References ao2_callback, ao2_lock, ao2_ref, ao2_unlock, ast_free, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_state_cb::callback, ast_state_cb::entry, find_hint_by_cb_id(), hints, and ast_state_cb::id.

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

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

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

04584 {
04585    return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
04586 }

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

References E_FINDLABEL, and pbx_extension_helper().

04589 {
04590    return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
04591 }

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

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

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

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

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

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

const char* ast_get_context_name ( struct ast_context con  ) 

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

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

const char* ast_get_context_registrar ( struct ast_context c  ) 

Definition at line 9978 of file pbx.c.

References ast_context::registrar.

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

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

const char* ast_get_extension_app ( struct ast_exten e  ) 

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

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

void* ast_get_extension_app_data ( struct ast_exten e  ) 

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

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

const char* ast_get_extension_cidmatch ( struct ast_exten e  ) 

Definition at line 10003 of file pbx.c.

References ast_exten::cidmatch.

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

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

struct ast_context* ast_get_extension_context ( struct ast_exten exten  ) 

Definition at line 9945 of file pbx.c.

References exten.

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

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

const char* ast_get_extension_label ( struct ast_exten e  ) 

Definition at line 9955 of file pbx.c.

References exten.

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

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

int ast_get_extension_matchcid ( struct ast_exten e  ) 

Definition at line 9998 of file pbx.c.

References ast_exten::matchcid.

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

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

const char* ast_get_extension_name ( struct ast_exten exten  ) 

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

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

int ast_get_extension_priority ( struct ast_exten exten  ) 

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

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

const char* ast_get_extension_registrar ( struct ast_exten e  ) 

Definition at line 9983 of file pbx.c.

References ast_exten::registrar.

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

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

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

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

const char* ast_get_ignorepat_name ( struct ast_ignorepat ip  ) 

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

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

const char* ast_get_ignorepat_registrar ( struct ast_ignorepat ip  ) 

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

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

const char* ast_get_include_name ( struct ast_include include  ) 

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

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

const char* ast_get_include_registrar ( struct ast_include i  ) 

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

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

const char* ast_get_switch_data ( struct ast_sw sw  ) 

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

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

int ast_get_switch_eval ( struct ast_sw sw  ) 

Definition at line 10028 of file pbx.c.

References ast_sw::eval.

Referenced by context_merge_incls_swits_igps_other_registrars().

10029 {
10030    return sw->eval;
10031 }

const char* ast_get_switch_name ( struct ast_sw sw  ) 

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

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

const char* ast_get_switch_registrar ( struct ast_sw sw  ) 

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

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

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

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

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

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

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

04599 {
04600    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0);
04601 }

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

References __ast_internal_context_destroy(), ao2_find, AO2_ITERATOR_DONTLOCK, ao2_iterator_init(), ao2_iterator_next, 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_APPEND_LIST, AST_LIST_EMPTY, AST_LIST_HEAD_INIT_VALUE, AST_LIST_INSERT_HEAD, 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, ast_hint::laststate, store_hint::list, ast_context::name, store_hint::next, ast_context::next, ast_exten::parent, pbx_find_extension(), PRIORITY_HINT, and pbx_find_info::stacklen.

Referenced by lua_reload_extensions(), and pbx_load_module().

07048 {
07049    double ft;
07050    struct ast_context *tmp, *oldcontextslist;
07051    struct ast_hashtab *oldtable;
07052    struct store_hints store = AST_LIST_HEAD_INIT_VALUE;
07053    struct store_hint *this;
07054    struct ast_hint *hint;
07055    struct ast_exten *exten;
07056    int length;
07057    struct ast_state_cb *thiscb;
07058    struct ast_hashtab_iter *iter;
07059    struct ao2_iterator i;
07060 
07061    /* it is very important that this function hold the hint list lock _and_ the conlock
07062       during its operation; not only do we need to ensure that the list of contexts
07063       and extensions does not change, but also that no hint callbacks (watchers) are
07064       added or removed during the merge/delete process
07065 
07066       in addition, the locks _must_ be taken in this order, because there are already
07067       other code paths that use this order
07068    */
07069 
07070    struct timeval begintime, writelocktime, endlocktime, enddeltime;
07071 
07072    begintime = ast_tvnow();
07073    ast_rdlock_contexts();
07074    iter = ast_hashtab_start_traversal(contexts_table);
07075    while ((tmp = ast_hashtab_next(iter))) {
07076       context_merge(extcontexts, exttable, tmp, registrar);
07077    }
07078    ast_hashtab_end_traversal(iter);
07079 
07080    ao2_lock(hints);
07081    writelocktime = ast_tvnow();
07082 
07083    /* preserve all watchers for hints */
07084    i = ao2_iterator_init(hints, AO2_ITERATOR_DONTLOCK);
07085    for (hint = ao2_iterator_next(&i); hint; ao2_ref(hint, -1), hint = ao2_iterator_next(&i)) {
07086       if (!AST_LIST_EMPTY(&hint->callbacks)) {
07087          length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2 + sizeof(*this);
07088          if (!(this = ast_calloc(1, length))) {
07089             continue;
07090          }
07091          ao2_lock(hint);
07092 
07093          if (hint->exten == NULL) {
07094             ao2_unlock(hint);
07095             continue;
07096          }
07097 
07098          /* this removes all the callbacks from the hint into this. */
07099          AST_LIST_APPEND_LIST(&this->callbacks, &hint->callbacks, entry);
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             ast_free(thiscb);
07142          }
07143       } else {
07144          ao2_lock(hint);
07145          AST_LIST_APPEND_LIST(&hint->callbacks, &this->callbacks, entry);
07146          hint->laststate = this->laststate;
07147          ao2_unlock(hint);
07148       }
07149       ast_free(this);
07150       if (hint) {
07151          ao2_ref(hint, -1);
07152       }
07153    }
07154 
07155    ao2_unlock(hints);
07156    ast_unlock_contexts();
07157    endlocktime = ast_tvnow();
07158 
07159    /* the old list and hashtab no longer are relevant, delete them while the rest of asterisk
07160       is now freely using the new stuff instead */
07161 
07162    ast_hashtab_destroy(oldtable, NULL);
07163 
07164    for (tmp = oldcontextslist; tmp; ) {
07165       struct ast_context *next;  /* next starting point */
07166       next = tmp->next;
07167       __ast_internal_context_destroy(tmp);
07168       tmp = next;
07169    }
07170    enddeltime = ast_tvnow();
07171 
07172    ft = ast_tvdiff_us(writelocktime, begintime);
07173    ft /= 1000000.0;
07174    ast_verb(3,"Time to scan old dialplan and merge leftovers back into the new: %8.6f sec\n", ft);
07175 
07176    ft = ast_tvdiff_us(endlocktime, writelocktime);
07177    ft /= 1000000.0;
07178    ast_verb(3,"Time to restore hints and swap in new dialplan: %8.6f sec\n", ft);
07179 
07180    ft = ast_tvdiff_us(enddeltime, endlocktime);
07181    ft /= 1000000.0;
07182    ast_verb(3,"Time to delete the old dialplan: %8.6f sec\n", ft);
07183 
07184    ft = ast_tvdiff_us(enddeltime, begintime);
07185    ft /= 1000000.0;
07186    ast_verb(3,"Total time merge_contexts_delete: %8.6f sec\n", ft);
07187    return;
07188 }

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

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

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

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

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

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

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

05060 {
05061    return ast_pbx_run_args(c, NULL);
05062 }

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

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

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 5022 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(), ss7_start_call(), unistim_new(), and usbradio_new().

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

int ast_processed_calls ( void   ) 

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

Definition at line 5069 of file pbx.c.

References totalcalls.

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

05070 {
05071    return totalcalls;
05072 }

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

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

int ast_rdlock_contexts ( void   ) 

Read locks the context list.

Return values:
0 on success
-1 on error

Definition at line 9909 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(), handle_statechange(), manager_show_dialplan_helper(), pbx_extension_helper(), show_debug_helper(), show_dialplan_helper(), and unreference_cached_app().

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

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

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

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

04604 {
04605    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN, found, combined_find_spawn);
04606 }

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

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

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

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

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

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

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

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

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

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

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

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

int ast_unlock_contexts ( void   ) 

Unlocks contexts.

Return values:
0 on success
-1 on failure

Definition at line 9914 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(), handle_statechange(), manager_show_dialplan_helper(), pbx_extension_helper(), show_debug_helper(), show_dialplan_helper(), and unreference_cached_app().

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

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

05610 {
05611    AST_RWLIST_WRLOCK(&switches);
05612    AST_RWLIST_REMOVE(&switches, sw, list);
05613    AST_RWLIST_UNLOCK(&switches);
05614 }

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

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

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

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

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

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

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

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

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

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

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

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

struct ast_context* ast_walk_contexts ( struct ast_context con  ) 

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

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

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

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

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

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

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

int ast_wrlock_contexts ( void   ) 

Write locks the context list.

Return values:
0 on success
-1 on error

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

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

void pbx_builtin_clear_globals ( void   ) 

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

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

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 9456 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(), sig_ss7_call(), sig_ss7_hangup(), sip_addheader(), sla_trunk_exec(), speech_background(), try_suggested_sip_codec(), and update_bridge_vars().

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

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

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

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

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

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

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

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

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

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

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 9528 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(), 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(), sig_ss7_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(), ss7_start_call(), 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().

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

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

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

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

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

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

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

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

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

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

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

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

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

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

References autofallthrough.

Referenced by pbx_load_module().

05075 {
05076    int oldval = autofallthrough;
05077    autofallthrough = newval;
05078    return oldval;
05079 }

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

References extenpatternmatchnew.

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

05082 {
05083    int oldval = extenpatternmatchnew;
05084    extenpatternmatchnew = newval;
05085    return oldval;
05086 }

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

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

Referenced by pbx_load_module().

05089 {
05090    if (overrideswitch) {
05091       ast_free(overrideswitch);
05092    }
05093    if (!ast_strlen_zero(newval)) {
05094       overrideswitch = ast_strdup(newval);
05095    } else {
05096       overrideswitch = NULL;
05097    }
05098 }

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

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

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

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

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

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

Definition at line 3979 of file pbx.c.

References pbx_substitute_variables_helper_full().

Referenced by dundi_lookup_local(), and loopback_subst().

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


Generated on Wed Apr 6 11:30:07 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7