Sat Mar 10 01:55:34 2012

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 void(*) ast_state_cb_destroy_type (int id, void *data)
 Typedef for devicestate and hint callback removal indication callback.
typedef int(*) ast_state_cb_type (char *context, char *id, enum ast_extension_states state, void *data)
 Typedef for devicestate and hint callbacks.
typedef int( ast_switch_f )(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
 All switch functions have the same interface, so define a type for them.

Enumerations

enum  ast_extension_states {
  AST_EXTENSION_REMOVED = -2, AST_EXTENSION_DEACTIVATED = -1, AST_EXTENSION_NOT_INUSE = 0, AST_EXTENSION_INUSE = 1 << 0,
  AST_EXTENSION_BUSY = 1 << 1, AST_EXTENSION_UNAVAILABLE = 1 << 2, AST_EXTENSION_RINGING = 1 << 3, AST_EXTENSION_ONHOLD = 1 << 4
}
 Extension states. More...
enum  ast_pbx_result { AST_PBX_SUCCESS = 0, AST_PBX_FAILED = -1, AST_PBX_CALL_LIMIT = -2 }
 The result codes when starting the PBX on a channel with ast_pbx_start. More...
enum  ext_match_t {
  E_MATCHMORE = 0x00, E_CANMATCH = 0x01, E_MATCH = 0x02, E_MATCH_MASK = 0x03,
  E_SPAWN = 0x12, E_FINDLABEL = 0x22
}

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 change_cb, void *data)
 Registers a state change callback.
int ast_extension_state_add_destroy (const char *context, const char *exten, ast_state_cb_type change_cb, ast_state_cb_destroy_type destroy_cb, void *data)
 Registers a state change callback with destructor.
int ast_extension_state_del (int id, ast_state_cb_type change_cb)
 Deletes a registered state change callback by ID.
int ast_findlabel_extension (struct ast_channel *c, const char *context, const char *exten, const char *label, const char *callerid)
 Find the priority of an extension that has the specified label.
int ast_findlabel_extension2 (struct ast_channel *c, struct ast_context *con, const char *exten, const char *label, const char *callerid)
 Find the priority of an extension that has the specified label.
int ast_func_read (struct ast_channel *chan, const char *function, char *workspace, size_t len)
 executes a read operation on a function
int ast_func_read2 (struct ast_channel *chan, const char *function, struct ast_str **str, ssize_t maxlen)
 executes a read operation on a function
int ast_func_write (struct ast_channel *chan, const char *function, const char *value)
 executes a write operation on a function
int ast_get_hint (char *hint, int hintsize, char *name, int namesize, struct ast_channel *c, const char *context, const char *exten)
 If an extension hint exists, return non-zero.
int ast_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority)
int ast_ignore_pattern (const char *context, const char *pattern)
 Checks to see if a number should be ignored.
int ast_matchmore_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
 Looks to see if adding anything to this extension might match something. (exists ^ canmatch).
void ast_merge_contexts_and_delete (struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *registrar)
 Merge the temporary contexts into a global contexts list and delete from the global list the ones that are being added.
int ast_parseable_goto (struct ast_channel *chan, const char *goto_string)
int ast_pbx_outgoing_app (const char *type, format_t format, void *data, int timeout, const char *app, const char *appdata, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel)
int ast_pbx_outgoing_exten (const char *type, format_t format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel)
enum ast_pbx_result ast_pbx_run (struct ast_channel *c)
 Execute the PBX in the current thread.
enum ast_pbx_result ast_pbx_run_args (struct ast_channel *c, struct ast_pbx_args *args)
 Execute the PBX in the current thread.
enum ast_pbx_result ast_pbx_start (struct ast_channel *c)
 Create a new thread and start the PBX.
int ast_processed_calls (void)
 Retrieve the total number of calls processed through the PBX since last restart.
int ast_rdlock_context (struct ast_context *con)
 Read locks a given context.
int ast_rdlock_contexts (void)
 Read locks the context list.
int ast_register_switch (struct ast_switch *sw)
 Register an alternative dialplan switch.
int ast_spawn_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid, int *found, int combined_find_spawn)
 Launch a new extension (i.e. new stack).
int ast_str_get_hint (struct ast_str **hint, ssize_t hintsize, struct ast_str **name, ssize_t namesize, struct ast_channel *c, const char *context, const char *exten)
 If an extension hint exists, return non-zero.
int ast_unlock_context (struct ast_context *con)
int ast_unlock_contexts (void)
 Unlocks contexts.
void ast_unregister_switch (struct ast_switch *sw)
 Unregister an alternative switch.
int ast_wrlock_context (struct ast_context *con)
 Write locks a given context.
int ast_wrlock_contexts (void)
 Write locks the context list.
void pbx_builtin_clear_globals (void)
const char * pbx_builtin_getvar_helper (struct ast_channel *chan, const char *name)
 Return a pointer to the value of the corresponding channel variable.
void pbx_builtin_pushvar_helper (struct ast_channel *chan, const char *name, const char *value)
 Add a variable to the channel variable stack, without removing any previously set value.
int pbx_builtin_raise_exception (struct ast_channel *chan, const char *data)
int pbx_builtin_serialize_variables (struct ast_channel *chan, struct ast_str **buf)
 Create a human-readable string, specifying all variables and their corresponding values.
int pbx_builtin_setvar (struct ast_channel *chan, const char *data)
 Parse and set a single channel variable, where the name and value are separated with an '=' character.
int pbx_builtin_setvar_helper (struct ast_channel *chan, const char *name, const char *value)
 Add a variable to the channel variable stack, removing the most recently set value for the same name.
int pbx_builtin_setvar_multiple (struct ast_channel *chan, const char *data)
 Parse and set multiple channel variables, where the pairs are separated by the ',' character, and name and value are separated with an '=' character.
int pbx_checkcondition (const char *condition)
 Evaluate a condition.
int pbx_exec (struct ast_channel *c, struct ast_app *app, const char *data)
 Execute an application.
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 1144 of file pbx.h.

Referenced by load_module(), and reload().

#define AST_MAX_APP   32

Max length of an application

Definition at line 39 of file pbx.h.

Referenced by destroy_station(), handle_show_function(), 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 1227 of file pbx.h.

#define AST_PBX_OK   0

No errors

Definition at line 48 of file pbx.h.

#define AST_PBX_REPLACE   1

Definition at line 43 of file pbx.h.

#define PRIORITY_HINT   -1

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_space(), 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 1222 of file pbx.h.

#define STATUS_NO_EXTENSION   2

Definition at line 1223 of file pbx.h.

#define STATUS_NO_LABEL   4

Definition at line 1225 of file pbx.h.

#define STATUS_NO_PRIORITY   3

Definition at line 1224 of file pbx.h.

#define STATUS_SUCCESS   5

Definition at line 1226 of file pbx.h.


Typedef Documentation

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

Typedef for devicestate and hint callback removal indication callback.

Definition at line 82 of file pbx.h.

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

Typedef for devicestate and hint callbacks.

Definition at line 79 of file pbx.h.

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

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

Data structure associated with an Asterisk switch

Definition at line 114 of file pbx.h.


Enumeration Type Documentation

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

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

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

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


Function Documentation

int __ast_custom_function_register ( struct ast_custom_function acf,
struct ast_module mod 
)

Register a custom function.

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

03575 {
03576    struct ast_custom_function *cur;
03577    char tmps[80];
03578 
03579    if (!acf) {
03580       return -1;
03581    }
03582 
03583    acf->mod = mod;
03584 #ifdef AST_XML_DOCS
03585    acf->docsrc = AST_STATIC_DOC;
03586 #endif
03587 
03588    if (acf_retrieve_docs(acf)) {
03589       return -1;
03590    }
03591 
03592    AST_RWLIST_WRLOCK(&acf_root);
03593 
03594    AST_RWLIST_TRAVERSE(&acf_root, cur, acflist) {
03595       if (!strcmp(acf->name, cur->name)) {
03596          ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name);
03597          AST_RWLIST_UNLOCK(&acf_root);
03598          return -1;
03599       }
03600    }
03601 
03602    /* Store in alphabetical order */
03603    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) {
03604       if (strcasecmp(acf->name, cur->name) < 0) {
03605          AST_RWLIST_INSERT_BEFORE_CURRENT(acf, acflist);
03606          break;
03607       }
03608    }
03609    AST_RWLIST_TRAVERSE_SAFE_END;
03610 
03611    if (!cur) {
03612       AST_RWLIST_INSERT_TAIL(&acf_root, acf, acflist);
03613    }
03614 
03615    AST_RWLIST_UNLOCK(&acf_root);
03616 
03617    ast_verb(2, "Registered custom function '%s'\n", term_color(tmps, acf->name, COLOR_BRCYAN, 0, sizeof(tmps)));
03618 
03619    return 0;
03620 }

int ast_active_calls ( void   ) 

Retrieve the number of active calls.

Definition at line 5387 of file pbx.c.

References countcalls.

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

05388 {
05389    return countcalls;
05390 }

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

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

Referenced by ast_extension_state(), ast_extension_state_add_destroy(), handle_cli_dialplan_add_extension(), manage_parked_call(), park_add_hints(), park_call_full(), parkinglot_activate(), register_exten(), register_peer_exten(), and RegisterExtension().

08115 {
08116    int ret = -1;
08117    struct ast_context *c;
08118 
08119    c = find_context_locked(context);
08120    if (c) {
08121       ret = ast_add_extension2(c, replace, extension, priority, label, callerid,
08122          application, data, datad, registrar);
08123       ast_unlock_contexts();
08124    }
08125 
08126    return ret;
08127 }

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

References ast_add_extension2_lockopt().

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

08462 {
08463    return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid,
08464       application, data, datad, registrar, 1);
08465 }

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

Set the channel to next execute the specified dialplan location.

See also:
ast_async_parseable_goto, ast_async_goto_if_exists
Note:
Do _NOT_ hold any channel locks when calling this function.

Definition at line 8152 of file pbx.c.

References ast_channel::_state, accountcode, ast_channel::accountcode, amaflags, 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_strdupa, 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().

08153 {
08154    int res = 0;
08155    struct ast_channel *tmpchan;
08156    struct {
08157       char *accountcode;
08158       char *exten;
08159       char *context;
08160       char *linkedid;
08161       char *name;
08162       struct ast_cdr *cdr;
08163       int amaflags;
08164       int state;
08165       format_t readformat;
08166       format_t writeformat;
08167    } tmpvars = { 0, };
08168 
08169    ast_channel_lock(chan);
08170    if (chan->pbx) { /* This channel is currently in the PBX */
08171       ast_explicit_goto(chan, context, exten, priority + 1);
08172       ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO);
08173       ast_channel_unlock(chan);
08174       return res;
08175    }
08176 
08177    /* In order to do it when the channel doesn't really exist within
08178     * the PBX, we have to make a new channel, masquerade, and start the PBX
08179     * at the new location */
08180    tmpvars.accountcode = ast_strdupa(chan->accountcode);
08181    tmpvars.exten = ast_strdupa(chan->exten);
08182    tmpvars.context = ast_strdupa(chan->context);
08183    tmpvars.linkedid = ast_strdupa(chan->linkedid);
08184    tmpvars.name = ast_strdupa(chan->name);
08185    tmpvars.amaflags = chan->amaflags;
08186    tmpvars.state = chan->_state;
08187    tmpvars.writeformat = chan->writeformat;
08188    tmpvars.readformat = chan->readformat;
08189    tmpvars.cdr = chan->cdr ? ast_cdr_dup(chan->cdr) : NULL;
08190 
08191    ast_channel_unlock(chan);
08192 
08193    /* Do not hold any channel locks while calling channel_alloc() since the function
08194     * locks the channel container when linking the new channel in. */
08195    if (!(tmpchan = ast_channel_alloc(0, tmpvars.state, 0, 0, tmpvars.accountcode, tmpvars.exten, tmpvars.context, tmpvars.linkedid, tmpvars.amaflags, "AsyncGoto/%s", tmpvars.name))) {
08196       ast_cdr_discard(tmpvars.cdr);
08197       return -1;
08198    }
08199 
08200    /* copy the cdr info over */
08201    if (tmpvars.cdr) {
08202       ast_cdr_discard(tmpchan->cdr);
08203       tmpchan->cdr = tmpvars.cdr;
08204       tmpvars.cdr = NULL;
08205    }
08206 
08207    /* Make formats okay */
08208    tmpchan->readformat = tmpvars.readformat;
08209    tmpchan->writeformat = tmpvars.writeformat;
08210 
08211    /* Setup proper location. Never hold another channel lock while calling this function. */
08212    ast_explicit_goto(tmpchan, S_OR(context, tmpvars.context), S_OR(exten, tmpvars.exten), priority);
08213 
08214    /* Masquerade into tmp channel */
08215    if (ast_channel_masquerade(tmpchan, chan)) {
08216       /* Failed to set up the masquerade.  It's probably chan_local
08217        * in the middle of optimizing itself out.  Sad. :( */
08218       ast_hangup(tmpchan);
08219       tmpchan = NULL;
08220       res = -1;
08221    } else {
08222       ast_do_masquerade(tmpchan);
08223       /* Start the PBX going on our stolen channel */
08224       if (ast_pbx_start(tmpchan)) {
08225          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name);
08226          ast_hangup(tmpchan);
08227          res = -1;
08228       }
08229    }
08230 
08231    return res;
08232 }

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

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

08235 {
08236    struct ast_channel *chan;
08237    int res = -1;
08238 
08239    if ((chan = ast_channel_get_by_name(channame))) {
08240       res = ast_async_goto(chan, context, exten, priority);
08241       chan = ast_channel_unref(chan);
08242    }
08243 
08244    return res;
08245 }

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

References __ast_goto_if_exists().

10548 {
10549    return __ast_goto_if_exists(chan, context, exten, priority, 1);
10550 }

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

References pbx_parseable_goto().

Referenced by asyncgoto_exec(), and handle_redirect().

10613 {
10614    return pbx_parseable_goto(chan, goto_string, 1);
10615 }

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

07737 {
07738    char *info;
07739    int j, num_fields, last_sep = -1;
07740 
07741    /* Check for empty just in case */
07742    if (ast_strlen_zero(info_in)) {
07743       return 0;
07744    }
07745 
07746    /* make a copy just in case we were passed a static string */
07747    info = ast_strdupa(info_in);
07748 
07749    /* count the number of fields in the timespec */
07750    for (j = 0, num_fields = 1; info[j] != '\0'; j++) {
07751       if (info[j] == ',') {
07752          last_sep = j;
07753          num_fields++;
07754       }
07755    }
07756 
07757    /* save the timezone, if it is specified */
07758    if (num_fields == 5) {
07759       i->timezone = ast_strdup(info + last_sep + 1);
07760    } else {
07761       i->timezone = NULL;
07762    }
07763 
07764    /* Assume everything except time */
07765    i->monthmask = 0xfff;   /* 12 bits */
07766    i->daymask = 0x7fffffffU; /* 31 bits */
07767    i->dowmask = 0x7f; /* 7 bits */
07768    /* on each call, use strsep() to move info to the next argument */
07769    get_timerange(i, strsep(&info, "|,"));
07770    if (info)
07771       i->dowmask = get_range(strsep(&info, "|,"), 7, days, "day of week");
07772    if (info)
07773       i->daymask = get_range(strsep(&info, "|,"), 31, NULL, "day");
07774    if (info)
07775       i->monthmask = get_range(strsep(&info, "|,"), 12, months, "month");
07776    return 1;
07777 }

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

04876 {
04877    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0);
04878 }

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

References ast_check_timing2(), and ast_tvnow().

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

07780 {
07781    return ast_check_timing2(i, ast_tvnow());
07782 }

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

07785 {
07786    struct ast_tm tm;
07787 
07788    ast_localtime(&tv, &tm, i->timezone);
07789 
07790    /* If it's not the right month, return */
07791    if (!(i->monthmask & (1 << tm.tm_mon)))
07792       return 0;
07793 
07794    /* If it's not that time of the month.... */
07795    /* Warning, tm_mday has range 1..31! */
07796    if (!(i->daymask & (1 << (tm.tm_mday-1))))
07797       return 0;
07798 
07799    /* If it's not the right day of the week */
07800    if (!(i->dowmask & (1 << tm.tm_wday)))
07801       return 0;
07802 
07803    /* Sanity check the hour just to be safe */
07804    if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) {
07805       ast_log(LOG_WARNING, "Insane time...\n");
07806       return 0;
07807    }
07808 
07809    /* Now the tough part, we calculate if it fits
07810       in the right time based on min/hour */
07811    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))))
07812       return 0;
07813 
07814    /* If we got this far, then we're good */
07815    return 1;
07816 }

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

10618 {
10619    struct ast_app *app = NULL;
10620    int which = 0;
10621    char *ret = NULL;
10622    size_t wordlen = strlen(word);
10623 
10624    AST_RWLIST_RDLOCK(&apps);
10625    AST_RWLIST_TRAVERSE(&apps, app, list) {
10626       if (!strncasecmp(word, app->name, wordlen) && ++which > state) {
10627          ret = ast_strdup(app->name);
10628          break;
10629       }
10630    }
10631    AST_RWLIST_UNLOCK(&apps);
10632 
10633    return ret;
10634 }

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

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

Referenced by handle_cli_dialplan_add_ignorepat().

08021 {
08022    int ret = -1;
08023    struct ast_context *c;
08024 
08025    c = find_context_locked(context);
08026    if (c) {
08027       ret = ast_context_add_ignorepat2(c, value, registrar);
08028       ast_unlock_contexts();
08029    }
08030    return ret;
08031 }

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

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

08034 {
08035    struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL;
08036    int length;
08037    char *pattern;
08038    length = sizeof(struct ast_ignorepat);
08039    length += strlen(value) + 1;
08040    if (!(ignorepat = ast_calloc(1, length)))
08041       return -1;
08042    /* The cast to char * is because we need to write the initial value.
08043     * The field is not supposed to be modified otherwise.  Also, gcc 4.2
08044     * sees the cast as dereferencing a type-punned pointer and warns about
08045     * it.  This is the workaround (we're telling gcc, yes, that's really
08046     * what we wanted to do).
08047     */
08048    pattern = (char *) ignorepat->pattern;
08049    strcpy(pattern, value);
08050    ignorepat->next = NULL;
08051    ignorepat->registrar = registrar;
08052    ast_wrlock_context(con);
08053    for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) {
08054       ignorepatl = ignorepatc;
08055       if (!strcasecmp(ignorepatc->pattern, value)) {
08056          /* Already there */
08057          ast_unlock_context(con);
08058          errno = EEXIST;
08059          return -1;
08060       }
08061    }
08062    if (ignorepatl)
08063       ignorepatl->next = ignorepat;
08064    else
08065       con->ignorepats = ignorepat;
08066    ast_unlock_context(con);
08067    return 0;
08068 
08069 }

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

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

Referenced by handle_cli_dialplan_add_include().

07565 {
07566    int ret = -1;
07567    struct ast_context *c;
07568 
07569    c = find_context_locked(context);
07570    if (c) {
07571       ret = ast_context_add_include2(c, include, registrar);
07572       ast_unlock_contexts();
07573    }
07574    return ret;
07575 }

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

07835 {
07836    struct ast_include *new_include;
07837    char *c;
07838    struct ast_include *i, *il = NULL; /* include, include_last */
07839    int length;
07840    char *p;
07841 
07842    length = sizeof(struct ast_include);
07843    length += 2 * (strlen(value) + 1);
07844 
07845    /* allocate new include structure ... */
07846    if (!(new_include = ast_calloc(1, length)))
07847       return -1;
07848    /* Fill in this structure. Use 'p' for assignments, as the fields
07849     * in the structure are 'const char *'
07850     */
07851    p = new_include->stuff;
07852    new_include->name = p;
07853    strcpy(p, value);
07854    p += strlen(value) + 1;
07855    new_include->rname = p;
07856    strcpy(p, value);
07857    /* Strip off timing info, and process if it is there */
07858    if ( (c = strchr(p, ',')) ) {
07859       *c++ = '\0';
07860       new_include->hastime = ast_build_timing(&(new_include->timing), c);
07861    }
07862    new_include->next      = NULL;
07863    new_include->registrar = registrar;
07864 
07865    ast_wrlock_context(con);
07866 
07867    /* ... go to last include and check if context is already included too... */
07868    for (i = con->includes; i; i = i->next) {
07869       if (!strcasecmp(i->name, new_include->name)) {
07870          ast_destroy_timing(&(new_include->timing));
07871          ast_free(new_include);
07872          ast_unlock_context(con);
07873          errno = EEXIST;
07874          return -1;
07875       }
07876       il = i;
07877    }
07878 
07879    /* ... include new context into context list, unlock, return */
07880    if (il)
07881       il->next = new_include;
07882    else
07883       con->includes = new_include;
07884    ast_verb(3, "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con));
07885 
07886    ast_unlock_context(con);
07887 
07888    return 0;
07889 }

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

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

07897 {
07898    int ret = -1;
07899    struct ast_context *c;
07900 
07901    c = find_context_locked(context);
07902    if (c) { /* found, add switch to this context */
07903       ret = ast_context_add_switch2(c, sw, data, eval, registrar);
07904       ast_unlock_contexts();
07905    }
07906    return ret;
07907 }

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

07918 {
07919    struct ast_sw *new_sw;
07920    struct ast_sw *i;
07921    int length;
07922    char *p;
07923 
07924    length = sizeof(struct ast_sw);
07925    length += strlen(value) + 1;
07926    if (data)
07927       length += strlen(data);
07928    length++;
07929 
07930    /* allocate new sw structure ... */
07931    if (!(new_sw = ast_calloc(1, length)))
07932       return -1;
07933    /* ... fill in this structure ... */
07934    p = new_sw->stuff;
07935    new_sw->name = p;
07936    strcpy(new_sw->name, value);
07937    p += strlen(value) + 1;
07938    new_sw->data = p;
07939    if (data) {
07940       strcpy(new_sw->data, data);
07941       p += strlen(data) + 1;
07942    } else {
07943       strcpy(new_sw->data, "");
07944       p++;
07945    }
07946    new_sw->eval     = eval;
07947    new_sw->registrar = registrar;
07948 
07949    /* ... try to lock this context ... */
07950    ast_wrlock_context(con);
07951 
07952    /* ... go to last sw and check if context is already swd too... */
07953    AST_LIST_TRAVERSE(&con->alts, i, list) {
07954       if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) {
07955          ast_free(new_sw);
07956          ast_unlock_context(con);
07957          errno = EEXIST;
07958          return -1;
07959       }
07960    }
07961 
07962    /* ... sw new context into context list, unlock, return */
07963    AST_LIST_INSERT_TAIL(&con->alts, new_sw, list);
07964 
07965    ast_verb(3, "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con));
07966 
07967    ast_unlock_context(con);
07968 
07969    return 0;
07970 }

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

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

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

struct ast_context* ast_context_find ( const char *  name  ) 

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 2656 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_features_reload(), ast_ignore_pattern(), cleanup_stale_contexts(), isexten_function_read(), manage_parkinglot(), parked_call_exec(), register_exten(), register_peer_exten(), remove_dead_dialplan_useage(), unload_module(), and unregister_exten().

02657 {
02658    struct ast_context *tmp;
02659    struct fake_context item;
02660 
02661    if (!name) {
02662       return NULL;
02663    }
02664    ast_rdlock_contexts();
02665    if (contexts_table) {
02666       ast_copy_string(item.name, name, sizeof(item.name));
02667       tmp = ast_hashtab_lookup(contexts_table, &item);
02668    } else {
02669       tmp = NULL;
02670       while ((tmp = ast_walk_contexts(tmp))) {
02671          if (!strcasecmp(name, tmp->name)) {
02672             break;
02673          }
02674       }
02675    }
02676    ast_unlock_contexts();
02677    return tmp;
02678 }

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 7165 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 config_parse_variables(), context_merge(), load_module(), lua_register_switches(), manage_parked_call(), parkinglot_activate(), pbx_load_config(), pbx_load_users(), and set_config().

07166 {
07167    struct ast_context *tmp, **local_contexts;
07168    struct fake_context search;
07169    int length = sizeof(struct ast_context) + strlen(name) + 1;
07170 
07171    if (!contexts_table) {
07172       /* Protect creation of contexts_table from reentrancy. */
07173       ast_wrlock_contexts();
07174       if (!contexts_table) {
07175          contexts_table = ast_hashtab_create(17,
07176             ast_hashtab_compare_contexts,
07177             ast_hashtab_resize_java,
07178             ast_hashtab_newsize_java,
07179             ast_hashtab_hash_contexts,
07180             0);
07181       }
07182       ast_unlock_contexts();
07183    }
07184 
07185    ast_copy_string(search.name, name, sizeof(search.name));
07186    if (!extcontexts) {
07187       ast_rdlock_contexts();
07188       local_contexts = &contexts;
07189       tmp = ast_hashtab_lookup(contexts_table, &search);
07190       ast_unlock_contexts();
07191       if (tmp) {
07192          tmp->refcount++;
07193          return tmp;
07194       }
07195    } else { /* local contexts just in a linked list; search there for the new context; slow, linear search, but not frequent */
07196       local_contexts = extcontexts;
07197       tmp = ast_hashtab_lookup(exttable, &search);
07198       if (tmp) {
07199          tmp->refcount++;
07200          return tmp;
07201       }
07202    }
07203 
07204    if ((tmp = ast_calloc(1, length))) {
07205       ast_rwlock_init(&tmp->lock);
07206       ast_mutex_init(&tmp->macrolock);
07207       strcpy(tmp->name, name);
07208       tmp->root = NULL;
07209       tmp->root_table = NULL;
07210       tmp->registrar = ast_strdup(registrar);
07211       tmp->includes = NULL;
07212       tmp->ignorepats = NULL;
07213       tmp->refcount = 1;
07214    } else {
07215       ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name);
07216       return NULL;
07217    }
07218 
07219    if (!extcontexts) {
07220       ast_wrlock_contexts();
07221       tmp->next = *local_contexts;
07222       *local_contexts = tmp;
07223       ast_hashtab_insert_safe(contexts_table, tmp); /*put this context into the tree */
07224       ast_unlock_contexts();
07225       ast_debug(1, "Registered context '%s'(%p) in table %p registrar: %s\n", tmp->name, tmp, contexts_table, registrar);
07226       ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar);
07227    } else {
07228       tmp->next = *local_contexts;
07229       if (exttable)
07230          ast_hashtab_insert_immediate(exttable, tmp); /*put this context into the tree */
07231 
07232       *local_contexts = tmp;
07233       ast_debug(1, "Registered context '%s'(%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar);
07234       ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar);
07235    }
07236    return tmp;
07237 }

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

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

Referenced by _macro_exec().

05766 {
05767    struct ast_context *c;
05768    int ret = -1;
05769 
05770    c = find_context_locked(context);
05771    if (c) {
05772       ast_unlock_contexts();
05773 
05774       /* if we found context, lock macrolock */
05775       ret = ast_mutex_lock(&c->macrolock);
05776    }
05777 
05778    return ret;
05779 }

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

Simply remove extension from context.

Note:
This function will lock conlock.

Definition at line 5570 of file pbx.c.

References ast_context_remove_extension_callerid().

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

05571 {
05572    return ast_context_remove_extension_callerid(context, extension, priority, NULL, 0, registrar);
05573 }

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

References ast_context_remove_extension_callerid2().

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

05601 {
05602    return ast_context_remove_extension_callerid2(con, extension, priority, NULL, 0, registrar, already_locked);
05603 }

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

05576 {
05577    int ret = -1; /* default error return */
05578    struct ast_context *c;
05579 
05580    c = find_context_locked(context);
05581    if (c) { /* ... remove extension ... */
05582       ret = ast_context_remove_extension_callerid2(c, extension, priority, callerid,
05583          matchcallerid, registrar, 0);
05584       ast_unlock_contexts();
05585    }
05586 
05587    return ret;
05588 }

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

05606 {
05607    struct ast_exten *exten, *prev_exten = NULL;
05608    struct ast_exten *peer;
05609    struct ast_exten ex, *exten2, *exten3;
05610    char dummy_name[1024];
05611    struct ast_exten *previous_peer = NULL;
05612    struct ast_exten *next_peer = NULL;
05613    int found = 0;
05614 
05615    if (!already_locked)
05616       ast_wrlock_context(con);
05617 
05618    /* Handle this is in the new world */
05619 
05620    /* FIXME For backwards compatibility, if callerid==NULL, then remove ALL
05621     * peers, not just those matching the callerid. */
05622 #ifdef NEED_DEBUG
05623    ast_verb(3,"Removing %s/%s/%d%s%s from trees, registrar=%s\n", con->name, extension, priority, matchcallerid ? "/" : "", matchcallerid ? callerid : "", registrar);
05624 #endif
05625 #ifdef CONTEXT_DEBUG
05626    check_contexts(__FILE__, __LINE__);
05627 #endif
05628    /* find this particular extension */
05629    ex.exten = dummy_name;
05630    ex.matchcid = matchcallerid && !ast_strlen_zero(callerid); /* don't say match if there's no callerid */
05631    ex.cidmatch = callerid;
05632    ast_copy_string(dummy_name, extension, sizeof(dummy_name));
05633    exten = ast_hashtab_lookup(con->root_table, &ex);
05634    if (exten) {
05635       if (priority == 0) {
05636          exten2 = ast_hashtab_remove_this_object(con->root_table, exten);
05637          if (!exten2)
05638             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);
05639          if (con->pattern_tree) {
05640             struct match_char *x = add_exten_to_pattern_tree(con, exten, 1);
05641 
05642             if (x->exten) { /* this test for safety purposes */
05643                x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */
05644                x->exten = 0; /* get rid of what will become a bad pointer */
05645             } else {
05646                ast_log(LOG_WARNING,"Trying to delete an exten from a context, but the pattern tree node returned isn't a full extension\n");
05647             }
05648          }
05649       } else {
05650          ex.priority = priority;
05651          exten2 = ast_hashtab_lookup(exten->peer_table, &ex);
05652          if (exten2) {
05653 
05654             if (exten2->label) { /* if this exten has a label, remove that, too */
05655                exten3 = ast_hashtab_remove_this_object(exten->peer_label_table,exten2);
05656                if (!exten3)
05657                   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);
05658             }
05659 
05660             exten3 = ast_hashtab_remove_this_object(exten->peer_table, exten2);
05661             if (!exten3)
05662                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);
05663             if (exten2 == exten && exten2->peer) {
05664                exten2 = ast_hashtab_remove_this_object(con->root_table, exten);
05665                ast_hashtab_insert_immediate(con->root_table, exten2->peer);
05666             }
05667             if (ast_hashtab_size(exten->peer_table) == 0) {
05668                /* well, if the last priority of an exten is to be removed,
05669                   then, the extension is removed, too! */
05670                exten3 = ast_hashtab_remove_this_object(con->root_table, exten);
05671                if (!exten3)
05672                   ast_log(LOG_ERROR,"Did not remove this exten (%s) from the context root_table (%s) (priority %d)\n", exten->exten, con->name, priority);
05673                if (con->pattern_tree) {
05674                   struct match_char *x = add_exten_to_pattern_tree(con, exten, 1);
05675                   if (x->exten) { /* this test for safety purposes */
05676                      x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */
05677                      x->exten = 0; /* get rid of what will become a bad pointer */
05678                   }
05679                }
05680             }
05681          } else {
05682             ast_log(LOG_ERROR,"Could not find priority %d of exten %s in context %s!\n",
05683                   priority, exten->exten, con->name);
05684          }
05685       }
05686    } else {
05687       /* hmmm? this exten is not in this pattern tree? */
05688       ast_log(LOG_WARNING,"Cannot find extension %s in root_table in context %s\n",
05689             extension, con->name);
05690    }
05691 #ifdef NEED_DEBUG
05692    if (con->pattern_tree) {
05693       ast_log(LOG_NOTICE,"match char tree after exten removal:\n");
05694       log_match_char_tree(con->pattern_tree, " ");
05695    }
05696 #endif
05697 
05698    /* scan the extension list to find first matching extension-registrar */
05699    for (exten = con->root; exten; prev_exten = exten, exten = exten->next) {
05700       if (!strcmp(exten->exten, extension) &&
05701          (!registrar || !strcmp(exten->registrar, registrar)) &&
05702          (!matchcallerid || (!ast_strlen_zero(callerid) && !ast_strlen_zero(exten->cidmatch) && !strcmp(exten->cidmatch, callerid)) || (ast_strlen_zero(callerid) && ast_strlen_zero(exten->cidmatch))))
05703          break;
05704    }
05705    if (!exten) {
05706       /* we can't find right extension */
05707       if (!already_locked)
05708          ast_unlock_context(con);
05709       return -1;
05710    }
05711 
05712    /* scan the priority list to remove extension with exten->priority == priority */
05713    for (peer = exten, next_peer = exten->peer ? exten->peer : exten->next;
05714        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)));
05715          peer = next_peer, next_peer = next_peer ? (next_peer->peer ? next_peer->peer : next_peer->next) : NULL) {
05716       if ((priority == 0 || peer->priority == priority) &&
05717             (!callerid || !matchcallerid || (matchcallerid && !strcmp(peer->cidmatch, callerid))) &&
05718             (!registrar || !strcmp(peer->registrar, registrar) )) {
05719          found = 1;
05720 
05721          /* we are first priority extension? */
05722          if (!previous_peer) {
05723             /*
05724              * We are first in the priority chain, so must update the extension chain.
05725              * The next node is either the next priority or the next extension
05726              */
05727             struct ast_exten *next_node = peer->peer ? peer->peer : peer->next;
05728             if (peer->peer) {
05729                /* move the peer_table and peer_label_table down to the next peer, if
05730                   it is there */
05731                peer->peer->peer_table = peer->peer_table;
05732                peer->peer->peer_label_table = peer->peer_label_table;
05733                peer->peer_table = NULL;
05734                peer->peer_label_table = NULL;
05735             }
05736             if (!prev_exten) {   /* change the root... */
05737                con->root = next_node;
05738             } else {
05739                prev_exten->next = next_node; /* unlink */
05740             }
05741             if (peer->peer)   { /* update the new head of the pri list */
05742                peer->peer->next = peer->next;
05743             }
05744          } else { /* easy, we are not first priority in extension */
05745             previous_peer->peer = peer->peer;
05746          }
05747 
05748          /* now, free whole priority extension */
05749          destroy_exten(peer);
05750       } else {
05751          previous_peer = peer;
05752       }
05753    }
05754    if (!already_locked)
05755       ast_unlock_context(con);
05756    return found ? 0 : -1;
05757 }

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

Definition at line 7976 of file pbx.c.

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

Referenced by handle_cli_dialplan_remove_ignorepat().

07977 {
07978    int ret = -1;
07979    struct ast_context *c;
07980 
07981    c = find_context_locked(context);
07982    if (c) {
07983       ret = ast_context_remove_ignorepat2(c, ignorepat, registrar);
07984       ast_unlock_contexts();
07985    }
07986    return ret;
07987 }

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

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

07990 {
07991    struct ast_ignorepat *ip, *ipl = NULL;
07992 
07993    ast_wrlock_context(con);
07994 
07995    for (ip = con->ignorepats; ip; ip = ip->next) {
07996       if (!strcmp(ip->pattern, ignorepat) &&
07997          (!registrar || (registrar == ip->registrar))) {
07998          if (ipl) {
07999             ipl->next = ip->next;
08000             ast_free(ip);
08001          } else {
08002             con->ignorepats = ip->next;
08003             ast_free(ip);
08004          }
08005          ast_unlock_context(con);
08006          return 0;
08007       }
08008       ipl = ip;
08009    }
08010 
08011    ast_unlock_context(con);
08012    errno = EINVAL;
08013    return -1;
08014 }

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

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

Referenced by handle_cli_dialplan_remove_include().

05464 {
05465    int ret = -1;
05466    struct ast_context *c;
05467 
05468    c = find_context_locked(context);
05469    if (c) {
05470       /* found, remove include from this context ... */
05471       ret = ast_context_remove_include2(c, include, registrar);
05472       ast_unlock_contexts();
05473    }
05474    return ret;
05475 }

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

05487 {
05488    struct ast_include *i, *pi = NULL;
05489    int ret = -1;
05490 
05491    ast_wrlock_context(con);
05492 
05493    /* find our include */
05494    for (i = con->includes; i; pi = i, i = i->next) {
05495       if (!strcmp(i->name, include) &&
05496             (!registrar || !strcmp(i->registrar, registrar))) {
05497          /* remove from list */
05498          ast_verb(3, "Removing inclusion of context '%s' in context '%s; registrar=%s'\n", include, ast_get_context_name(con), registrar);
05499          if (pi)
05500             pi->next = i->next;
05501          else
05502             con->includes = i->next;
05503          /* free include and return */
05504          ast_destroy_timing(&(i->timing));
05505          ast_free(i);
05506          ret = 0;
05507          break;
05508       }
05509    }
05510 
05511    ast_unlock_context(con);
05512 
05513    return ret;
05514 }

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

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

05522 {
05523    int ret = -1; /* default error return */
05524    struct ast_context *c;
05525 
05526    c = find_context_locked(context);
05527    if (c) {
05528       /* remove switch from this context ... */
05529       ret = ast_context_remove_switch2(c, sw, data, registrar);
05530       ast_unlock_contexts();
05531    }
05532    return ret;
05533 }

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

05544 {
05545    struct ast_sw *i;
05546    int ret = -1;
05547 
05548    ast_wrlock_context(con);
05549 
05550    /* walk switches */
05551    AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) {
05552       if (!strcmp(i->name, sw) && !strcmp(i->data, data) &&
05553          (!registrar || !strcmp(i->registrar, registrar))) {
05554          /* found, remove from list */
05555          ast_verb(3, "Removing switch '%s' from context '%s; registrar=%s'\n", sw, ast_get_context_name(con), registrar);
05556          AST_LIST_REMOVE_CURRENT(list);
05557          ast_free(i); /* free switch and return */
05558          ret = 0;
05559          break;
05560       }
05561    }
05562    AST_LIST_TRAVERSE_SAFE_END;
05563 
05564    ast_unlock_context(con);
05565 
05566    return ret;
05567 }

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

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

Referenced by _macro_exec().

05787 {
05788    struct ast_context *c;
05789    int ret = -1;
05790 
05791    c = find_context_locked(context);
05792    if (c) {
05793       ast_unlock_contexts();
05794 
05795       /* if we found context, unlock macrolock */
05796       ret = ast_mutex_unlock(&c->macrolock);
05797    }
05798 
05799    return ret;
05800 }

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

10503 {
10504    struct ast_include *inc = NULL;
10505    int res = 0;
10506 
10507    while ( (inc = ast_walk_context_includes(con, inc)) ) {
10508       if (ast_context_find(inc->rname))
10509          continue;
10510 
10511       res = -1;
10512       ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n",
10513          ast_get_context_name(con), inc->rname);
10514       break;
10515    }
10516 
10517    return res;
10518 }

struct ast_custom_function* ast_custom_function_find ( const char *  name  ) 

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

03486 {
03487    struct ast_custom_function *acf = NULL;
03488 
03489    AST_RWLIST_RDLOCK(&acf_root);
03490    AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) {
03491       if (!strcmp(name, acf->name))
03492          break;
03493    }
03494    AST_RWLIST_UNLOCK(&acf_root);
03495 
03496    return acf;
03497 }

int ast_custom_function_unregister ( struct ast_custom_function acf  ) 

Unregister a custom function.

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

03500 {
03501    struct ast_custom_function *cur;
03502 
03503    if (!acf) {
03504       return -1;
03505    }
03506 
03507    AST_RWLIST_WRLOCK(&acf_root);
03508    if ((cur = AST_RWLIST_REMOVE(&acf_root, acf, acflist))) {
03509 #ifdef AST_XML_DOCS
03510       if (cur->docsrc == AST_XML_DOC) {
03511          ast_string_field_free_memory(acf);
03512       }
03513 #endif
03514       ast_verb(2, "Unregistered custom function %s\n", cur->name);
03515    }
03516    AST_RWLIST_UNLOCK(&acf_root);
03517 
03518    return cur ? 0 : -1;
03519 }

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

07819 {
07820    if (i->timezone) {
07821       ast_free(i->timezone);
07822       i->timezone = NULL;
07823    }
07824    return 0;
07825 }

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

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

Referenced by ast_extension_state3().

04309 {
04310    switch (devstate) {
04311    case AST_DEVICE_ONHOLD:
04312       return AST_EXTENSION_ONHOLD;
04313    case AST_DEVICE_BUSY:
04314       return AST_EXTENSION_BUSY;
04315    case AST_DEVICE_UNKNOWN:
04316       return AST_EXTENSION_NOT_INUSE;
04317    case AST_DEVICE_UNAVAILABLE:
04318    case AST_DEVICE_INVALID:
04319       return AST_EXTENSION_UNAVAILABLE;
04320    case AST_DEVICE_RINGINUSE:
04321       return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING);
04322    case AST_DEVICE_RINGING:
04323       return AST_EXTENSION_RINGING;
04324    case AST_DEVICE_INUSE:
04325       return AST_EXTENSION_INUSE;
04326    case AST_DEVICE_NOT_INUSE:
04327       return AST_EXTENSION_NOT_INUSE;
04328    case AST_DEVICE_TOTAL: /* not a device state, included for completeness */
04329       break;
04330    }
04331 
04332    return AST_EXTENSION_NOT_INUSE;
04333 }

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

References E_MATCH, and pbx_extension_helper().

Referenced by __analog_ss_thread(), __ast_goto_if_exists(), __ast_pbx_run(), _macro_exec(), acf_isexten_exec(), analog_ss_thread(), answer_call(), ast_bridge_call(), ast_pbx_outgoing_exten(), cb_events(), cli_console_dial(), conf_run(), console_dial(), console_transfer(), dahdi_handle_dtmf(), dahdi_r2_on_call_offered(), dahdi_r2_on_dnis_digit_received(), dial_exec_full(), disa_exec(), dp_lookup(), dundi_lookup_local(), findmeexec(), get_also_info(), get_destination(), get_refer_info(), gosub_exec(), handle_gosub(), handle_link_data(), handle_link_phone_dtmf(), handle_stimulus_message(), isexten_function_read(), leave_voicemail(), local_alloc(), local_call(), local_devicestate(), local_dtmf_helper(), loopback_exists(), metermaidstate(), mgcp_ss(), minivm_greet_exec(), misdn_overlap_dial_task(), my_handle_dtmf(), 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().

04861 {
04862    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0);
04863 }

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

08130 {
08131    if (!chan)
08132       return -1;
08133 
08134    ast_channel_lock(chan);
08135 
08136    if (!ast_strlen_zero(context))
08137       ast_copy_string(chan->context, context, sizeof(chan->context));
08138    if (!ast_strlen_zero(exten))
08139       ast_copy_string(chan->exten, exten, sizeof(chan->exten));
08140    if (priority > -1) {
08141       chan->priority = priority;
08142       /* see flag description in channel.h for explanation */
08143       if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP))
08144          chan->priority--;
08145    }
08146 
08147    ast_channel_unlock(chan);
08148 
08149    return 0;
08150 }

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

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

02634 {
02635    if (needmore != E_MATCHMORE && needmore != E_CANMATCH)
02636       ast_log(LOG_WARNING, "invalid argument %d\n", needmore);
02637    return extension_match_core(pattern, data, needmore);
02638 }

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

References ext_cmp().

Referenced by lua_extension_cmp().

02436 {
02437    return ext_cmp(a, b);
02438 }

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

02629 {
02630    return extension_match_core(pattern, data, E_MATCH);
02631 }

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

04379 {
04380    struct ast_exten *e;
04381 
04382    if (!(e = ast_hint_extension(c, context, exten))) {  /* Do we have a hint for this extension ? */
04383       return -1;                   /* No hint, return -1 */
04384    }
04385 
04386    if (e->exten[0] == '_') {
04387       /* Create this hint on-the-fly */
04388       ast_add_extension(e->parent->name, 0, exten, e->priority, e->label,
04389          e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr,
04390          e->registrar);
04391       if (!(e = ast_hint_extension(c, context, exten))) {
04392          /* Improbable, but not impossible */
04393          return -1;
04394       }
04395    }
04396 
04397    return ast_extension_state2(e);  /* Check all devices in the hint */
04398 }

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

04367 {
04368    int i;
04369 
04370    for (i = 0; (i < ARRAY_LEN(extension_states)); i++) {
04371       if (extension_states[i].extension_state == extension_state)
04372          return extension_states[i].text;
04373    }
04374    return "Unknown";
04375 }

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

Registers a state change callback.

Parameters:
context which context to look in
exten which extension to get state
change_cb callback to call if state changed
data to pass to callback
Note:
The change_cb is called if the state of an extension is changed.
Return values:
-1 on failure
ID on success

Definition at line 4599 of file pbx.c.

References ast_extension_state_add_destroy().

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

04601 {
04602    return ast_extension_state_add_destroy(context, exten, change_cb, NULL, data);
04603 }

int ast_extension_state_add_destroy ( const char *  context,
const char *  exten,
ast_state_cb_type  change_cb,
ast_state_cb_destroy_type  destroy_cb,
void *  data 
)

Registers a state change callback with destructor.

Since:
1.8.9

10.1.0

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

The destroy_cb is called when the registration is deleted so the registerer can release any associated resources.

Return values:
-1 on failure
ID on success

Definition at line 4512 of file pbx.c.

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

Referenced by ast_extension_state_add(), and handle_request_subscribe().

04514 {
04515    struct ast_hint *hint;
04516    struct ast_state_cb *state_cb;
04517    struct ast_exten *e;
04518    int id;
04519 
04520    /* If there's no context and extension:  add callback to statecbs list */
04521    if (!context && !exten) {
04522       /* Prevent multiple adds from adding the same change_cb at the same time. */
04523       ao2_lock(statecbs);
04524 
04525       /* Remove any existing change_cb. */
04526       ao2_find(statecbs, change_cb, OBJ_UNLINK | OBJ_NODATA);
04527 
04528       /* Now insert the change_cb */
04529       if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) {
04530          ao2_unlock(statecbs);
04531          return -1;
04532       }
04533       state_cb->id = 0;
04534       state_cb->change_cb = change_cb;
04535       state_cb->destroy_cb = destroy_cb;
04536       state_cb->data = data;
04537       ao2_link(statecbs, state_cb);
04538 
04539       ao2_ref(state_cb, -1);
04540       ao2_unlock(statecbs);
04541       return 0;
04542    }
04543 
04544    if (!context || !exten)
04545       return -1;
04546 
04547    /* This callback type is for only one hint, so get the hint */
04548    e = ast_hint_extension(NULL, context, exten);
04549    if (!e) {
04550       return -1;
04551    }
04552 
04553    /* If this is a pattern, dynamically create a new extension for this
04554     * particular match.  Note that this will only happen once for each
04555     * individual extension, because the pattern will no longer match first.
04556     */
04557    if (e->exten[0] == '_') {
04558       ast_add_extension(e->parent->name, 0, exten, e->priority, e->label,
04559          e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr,
04560          e->registrar);
04561       e = ast_hint_extension(NULL, context, exten);
04562       if (!e || e->exten[0] == '_') {
04563          return -1;
04564       }
04565    }
04566 
04567    /* Find the hint in the hints container */
04568    ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */
04569    hint = ao2_find(hints, e, 0);
04570    if (!hint) {
04571       ao2_unlock(hints);
04572       return -1;
04573    }
04574 
04575    /* Now insert the callback in the callback list  */
04576    if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) {
04577       ao2_ref(hint, -1);
04578       ao2_unlock(hints);
04579       return -1;
04580    }
04581    do {
04582       id = stateid++;      /* Unique ID for this callback */
04583       /* Do not allow id to ever be -1 or 0. */
04584    } while (id == -1 || id == 0);
04585    state_cb->id = id;
04586    state_cb->change_cb = change_cb; /* Pointer to callback routine */
04587    state_cb->destroy_cb = destroy_cb;
04588    state_cb->data = data;     /* Data for the callback */
04589    ao2_link(hint->callbacks, state_cb);
04590 
04591    ao2_ref(state_cb, -1);
04592    ao2_ref(hint, -1);
04593    ao2_unlock(hints);
04594 
04595    return id;
04596 }

int ast_extension_state_del ( int  id,
ast_state_cb_type  change_cb 
)

Deletes a registered state change callback by ID.

Parameters:
id of the registered state callback to delete
change_cb callback to call if state changed (Used if id == 0 (global))
Return values:
0 success
-1 failure

Definition at line 4621 of file pbx.c.

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

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

04622 {
04623    struct ast_state_cb *p_cur;
04624    int ret = -1;
04625 
04626    if (!id) {  /* id == 0 is a callback without extension */
04627       if (!change_cb) {
04628          return ret;
04629       }
04630       p_cur = ao2_find(statecbs, change_cb, OBJ_UNLINK);
04631       if (p_cur) {
04632          ret = 0;
04633          ao2_ref(p_cur, -1);
04634       }
04635    } else { /* callback with extension, find the callback based on ID */
04636       struct ast_hint *hint;
04637 
04638       ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */
04639       hint = ao2_callback(hints, 0, find_hint_by_cb_id, &id);
04640       if (hint) {
04641          p_cur = ao2_find(hint->callbacks, &id, OBJ_UNLINK);
04642          if (p_cur) {
04643             ret = 0;
04644             ao2_ref(p_cur, -1);
04645          }
04646          ao2_ref(hint, -1);
04647       }
04648       ao2_unlock(hints);
04649    }
04650 
04651    return ret;
04652 }

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

04866 {
04867    return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
04868 }

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

References E_FINDLABEL, and pbx_extension_helper().

04871 {
04872    return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
04873 }

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

03644 {
03645    char *copy = ast_strdupa(function);
03646    char *args = func_args(copy);
03647    struct ast_custom_function *acfptr = ast_custom_function_find(copy);
03648    int res;
03649    struct ast_module_user *u = NULL;
03650 
03651    if (acfptr == NULL) {
03652       ast_log(LOG_ERROR, "Function %s not registered\n", copy);
03653    } else if (!acfptr->read && !acfptr->read2) {
03654       ast_log(LOG_ERROR, "Function %s cannot be read\n", copy);
03655    } else if (acfptr->read) {
03656       if (acfptr->mod) {
03657          u = __ast_module_user_add(acfptr->mod, chan);
03658       }
03659       res = acfptr->read(chan, copy, args, workspace, len);
03660       if (acfptr->mod && u) {
03661          __ast_module_user_remove(acfptr->mod, u);
03662       }
03663       return res;
03664    } else {
03665       struct ast_str *str = ast_str_create(16);
03666       if (acfptr->mod) {
03667          u = __ast_module_user_add(acfptr->mod, chan);
03668       }
03669       res = acfptr->read2(chan, copy, args, &str, 0);
03670       if (acfptr->mod && u) {
03671          __ast_module_user_remove(acfptr->mod, u);
03672       }
03673       ast_copy_string(workspace, ast_str_buffer(str), len > ast_str_size(str) ? ast_str_size(str) : len);
03674       ast_free(str);
03675       return res;
03676    }
03677    return -1;
03678 }

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

03681 {
03682    char *copy = ast_strdupa(function);
03683    char *args = func_args(copy);
03684    struct ast_custom_function *acfptr = ast_custom_function_find(copy);
03685    int res;
03686    struct ast_module_user *u = NULL;
03687 
03688    if (acfptr == NULL) {
03689       ast_log(LOG_ERROR, "Function %s not registered\n", copy);
03690    } else if (!acfptr->read && !acfptr->read2) {
03691       ast_log(LOG_ERROR, "Function %s cannot be read\n", copy);
03692    } else {
03693       if (acfptr->mod) {
03694          u = __ast_module_user_add(acfptr->mod, chan);
03695       }
03696       ast_str_reset(*str);
03697       if (acfptr->read2) {
03698          /* ast_str enabled */
03699          res = acfptr->read2(chan, copy, args, str, maxlen);
03700       } else {
03701          /* Legacy function pointer, allocate buffer for result */
03702          int maxsize = ast_str_size(*str);
03703          if (maxlen > -1) {
03704             if (maxlen == 0) {
03705                if (acfptr->read_max) {
03706                   maxsize = acfptr->read_max;
03707                } else {
03708                   maxsize = VAR_BUF_SIZE;
03709                }
03710             } else {
03711                maxsize = maxlen;
03712             }
03713             ast_str_make_space(str, maxsize);
03714          }
03715          res = acfptr->read(chan, copy, args, ast_str_buffer(*str), maxsize);
03716       }
03717       if (acfptr->mod && u) {
03718          __ast_module_user_remove(acfptr->mod, u);
03719       }
03720       return res;
03721    }
03722    return -1;
03723 }

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

03726 {
03727    char *copy = ast_strdupa(function);
03728    char *args = func_args(copy);
03729    struct ast_custom_function *acfptr = ast_custom_function_find(copy);
03730 
03731    if (acfptr == NULL)
03732       ast_log(LOG_ERROR, "Function %s not registered\n", copy);
03733    else if (!acfptr->write)
03734       ast_log(LOG_ERROR, "Function %s cannot be written to\n", copy);
03735    else {
03736       int res;
03737       struct ast_module_user *u = NULL;
03738       if (acfptr->mod)
03739          u = __ast_module_user_add(acfptr->mod, chan);
03740       res = acfptr->write(chan, copy, args, value);
03741       if (acfptr->mod && u)
03742          __ast_module_user_remove(acfptr->mod, u);
03743       return res;
03744    }
03745 
03746    return -1;
03747 }

const char* ast_get_context_name ( struct ast_context con  ) 

Definition at line 10354 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(), ast_remove_hint(), 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(), destroy_hint(), dundi_precache_full(), find_matching_endwhile(), find_matching_priority(), handle_cli_dialplan_save(), handle_show_hint(), handle_show_hints(), handle_statechange(), hints_data_provider_get(), manager_show_dialplan_helper(), show_debug_helper(), and show_dialplan_helper().

10355 {
10356    return con ? con->name : NULL;
10357 }

const char* ast_get_context_registrar ( struct ast_context c  ) 

Definition at line 10392 of file pbx.c.

References ast_context::registrar.

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

10393 {
10394    return c ? c->registrar : NULL;
10395 }

const char* ast_get_extension_app ( struct ast_exten e  ) 

Definition at line 10422 of file pbx.c.

References ast_exten::app.

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

10423 {
10424    return e ? e->app : NULL;
10425 }

void* ast_get_extension_app_data ( struct ast_exten e  ) 

Definition at line 10427 of file pbx.c.

References ast_exten::data.

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

10428 {
10429    return e ? e->data : NULL;
10430 }

const char* ast_get_extension_cidmatch ( struct ast_exten e  ) 

Definition at line 10417 of file pbx.c.

References ast_exten::cidmatch.

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

10418 {
10419    return e ? e->cidmatch : NULL;
10420 }

struct ast_context* ast_get_extension_context ( struct ast_exten exten  ) 

Definition at line 10359 of file pbx.c.

References exten.

Referenced by ast_remove_hint(), destroy_hint(), handle_show_hint(), handle_show_hints(), handle_statechange(), and hints_data_provider_get().

10360 {
10361    return exten ? exten->parent : NULL;
10362 }

const char* ast_get_extension_label ( struct ast_exten e  ) 

Definition at line 10369 of file pbx.c.

References exten.

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

10370 {
10371    return exten ? exten->label : NULL;
10372 }

int ast_get_extension_matchcid ( struct ast_exten e  ) 

Definition at line 10412 of file pbx.c.

References ast_exten::matchcid.

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

10413 {
10414    return e ? e->matchcid : 0;
10415 }

const char* ast_get_extension_name ( struct ast_exten exten  ) 

Definition at line 10364 of file pbx.c.

References exten.

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

10365 {
10366    return exten ? exten->exten : NULL;
10367 }

int ast_get_extension_priority ( struct ast_exten exten  ) 

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

10385 {
10386    return exten ? exten->priority : -1;
10387 }

const char* ast_get_extension_registrar ( struct ast_exten e  ) 

Definition at line 10397 of file pbx.c.

References ast_exten::registrar.

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

10398 {
10399    return e ? e->registrar : NULL;
10400 }

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

04823 {
04824    struct ast_exten *e = ast_hint_extension(c, context, exten);
04825 
04826    if (e) {
04827       if (hint)
04828          ast_copy_string(hint, ast_get_extension_app(e), hintsize);
04829       if (name) {
04830          const char *tmp = ast_get_extension_app_data(e);
04831          if (tmp)
04832             ast_copy_string(name, tmp, namesize);
04833       }
04834       return -1;
04835    }
04836    return 0;
04837 }

const char* ast_get_ignorepat_name ( struct ast_ignorepat ip  ) 

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

10380 {
10381    return ip ? ip->pattern : NULL;
10382 }

const char* ast_get_ignorepat_registrar ( struct ast_ignorepat ip  ) 

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

10408 {
10409    return ip ? ip->registrar : NULL;
10410 }

const char* ast_get_include_name ( struct ast_include include  ) 

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

10375 {
10376    return inc ? inc->name : NULL;
10377 }

const char* ast_get_include_registrar ( struct ast_include i  ) 

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

10403 {
10404    return i ? i->registrar : NULL;
10405 }

const char* ast_get_switch_data ( struct ast_sw sw  ) 

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

10438 {
10439    return sw ? sw->data : NULL;
10440 }

int ast_get_switch_eval ( struct ast_sw sw  ) 

Definition at line 10442 of file pbx.c.

References ast_sw::eval.

Referenced by context_merge_incls_swits_igps_other_registrars().

10443 {
10444    return sw->eval;
10445 }

const char* ast_get_switch_name ( struct ast_sw sw  ) 

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

10433 {
10434    return sw ? sw->name : NULL;
10435 }

const char* ast_get_switch_registrar ( struct ast_sw sw  ) 

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

10448 {
10449    return sw ? sw->registrar : NULL;
10450 }

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

10543 {
10544    return __ast_goto_if_exists(chan, context, exten, priority, 0);
10545 }

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

hashtable functions for contexts

Definition at line 1065 of file pbx.c.

References ast_context::name.

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

01066 {
01067    const struct ast_context *ac = ah_a;
01068    const struct ast_context *bc = ah_b;
01069    if (!ac || !bc) /* safety valve, but it might prevent a crash you'd rather have happen */
01070       return 1;
01071    /* assume context names are registered in a string table! */
01072    return strcmp(ac->name, bc->name);
01073 }

unsigned int ast_hashtab_hash_contexts ( const void *  obj  ) 

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

01109 {
01110    const struct ast_context *ac = obj;
01111    return ast_hashtab_hash_string(ac->name);
01112 }

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

08072 {
08073    struct ast_context *con = ast_context_find(context);
08074 
08075    if (con) {
08076       struct ast_ignorepat *pat;
08077 
08078       for (pat = con->ignorepats; pat; pat = pat->next) {
08079          if (ast_extension_match(pat->pattern, pattern))
08080             return 1;
08081       }
08082    }
08083 
08084    return 0;
08085 }

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

04881 {
04882    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0);
04883 }

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

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

Referenced by lua_reload_extensions(), and pbx_load_module().

07370 {
07371    double ft;
07372    struct ast_context *tmp;
07373    struct ast_context *oldcontextslist;
07374    struct ast_hashtab *oldtable;
07375    struct store_hints hints_stored = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
07376    struct store_hints hints_removed = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
07377    struct store_hint *saved_hint;
07378    struct ast_hint *hint;
07379    struct ast_exten *exten;
07380    int length;
07381    struct ast_state_cb *thiscb;
07382    struct ast_hashtab_iter *iter;
07383    struct ao2_iterator i;
07384    struct timeval begintime;
07385    struct timeval writelocktime;
07386    struct timeval endlocktime;
07387    struct timeval enddeltime;
07388 
07389    /*
07390     * It is very important that this function hold the hints
07391     * container lock _and_ the conlock during its operation; not
07392     * only do we need to ensure that the list of contexts and
07393     * extensions does not change, but also that no hint callbacks
07394     * (watchers) are added or removed during the merge/delete
07395     * process
07396     *
07397     * In addition, the locks _must_ be taken in this order, because
07398     * there are already other code paths that use this order
07399     */
07400 
07401    begintime = ast_tvnow();
07402    ast_mutex_lock(&context_merge_lock);/* Serialize ast_merge_contexts_and_delete */
07403    ast_wrlock_contexts();
07404    iter = ast_hashtab_start_traversal(contexts_table);
07405    while ((tmp = ast_hashtab_next(iter))) {
07406       context_merge(extcontexts, exttable, tmp, registrar);
07407    }
07408    ast_hashtab_end_traversal(iter);
07409 
07410    ao2_lock(hints);
07411    writelocktime = ast_tvnow();
07412 
07413    /* preserve all watchers for hints */
07414    i = ao2_iterator_init(hints, AO2_ITERATOR_DONTLOCK);
07415    for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
07416       if (ao2_container_count(hint->callbacks)) {
07417          ao2_lock(hint);
07418          if (!hint->exten) {
07419             /* The extension has already been destroyed. (Should never happen here) */
07420             ao2_unlock(hint);
07421             continue;
07422          }
07423 
07424          length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2
07425             + sizeof(*saved_hint);
07426          if (!(saved_hint = ast_calloc(1, length))) {
07427             ao2_unlock(hint);
07428             continue;
07429          }
07430 
07431          /* This removes all the callbacks from the hint into saved_hint. */
07432          while ((thiscb = ao2_callback(hint->callbacks, OBJ_UNLINK, NULL, NULL))) {
07433             AST_LIST_INSERT_TAIL(&saved_hint->callbacks, thiscb, entry);
07434             /*
07435              * We intentionally do not unref thiscb to account for the
07436              * non-ao2 reference in saved_hint->callbacks
07437              */
07438          }
07439 
07440          saved_hint->laststate = hint->laststate;
07441          saved_hint->context = saved_hint->data;
07442          strcpy(saved_hint->data, hint->exten->parent->name);
07443          saved_hint->exten = saved_hint->data + strlen(saved_hint->context) + 1;
07444          strcpy(saved_hint->exten, hint->exten->exten);
07445          ao2_unlock(hint);
07446          AST_LIST_INSERT_HEAD(&hints_stored, saved_hint, list);
07447       }
07448    }
07449    ao2_iterator_destroy(&i);
07450 
07451    /* save the old table and list */
07452    oldtable = contexts_table;
07453    oldcontextslist = contexts;
07454 
07455    /* move in the new table and list */
07456    contexts_table = exttable;
07457    contexts = *extcontexts;
07458 
07459    /*
07460     * Restore the watchers for hints that can be found; notify
07461     * those that cannot be restored.
07462     */
07463    while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_stored, list))) {
07464       struct pbx_find_info q = { .stacklen = 0 };
07465 
07466       exten = pbx_find_extension(NULL, NULL, &q, saved_hint->context, saved_hint->exten,
07467          PRIORITY_HINT, NULL, "", E_MATCH);
07468       /*
07469        * If this is a pattern, dynamically create a new extension for this
07470        * particular match.  Note that this will only happen once for each
07471        * individual extension, because the pattern will no longer match first.
07472        */
07473       if (exten && exten->exten[0] == '_') {
07474          ast_add_extension_nolock(exten->parent->name, 0, saved_hint->exten,
07475             PRIORITY_HINT, NULL, 0, exten->app, ast_strdup(exten->data), ast_free_ptr,
07476             exten->registrar);
07477          /* rwlocks are not recursive locks */
07478          exten = ast_hint_extension_nolock(NULL, saved_hint->context,
07479             saved_hint->exten);
07480       }
07481 
07482       /* Find the hint in the hints container */
07483       hint = exten ? ao2_find(hints, exten, 0) : NULL;
07484       if (!hint) {
07485          /*
07486           * Notify watchers of this removed hint later when we aren't
07487           * encumberd by so many locks.
07488           */
07489          AST_LIST_INSERT_HEAD(&hints_removed, saved_hint, list);
07490       } else {
07491          ao2_lock(hint);
07492          while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) {
07493             ao2_link(hint->callbacks, thiscb);
07494             /* Ref that we added when putting into saved_hint->callbacks */
07495             ao2_ref(thiscb, -1);
07496          }
07497          hint->laststate = saved_hint->laststate;
07498          ao2_unlock(hint);
07499          ao2_ref(hint, -1);
07500          ast_free(saved_hint);
07501       }
07502    }
07503 
07504    ao2_unlock(hints);
07505    ast_unlock_contexts();
07506 
07507    /*
07508     * Notify watchers of all removed hints with the same lock
07509     * environment as handle_statechange().
07510     */
07511    while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_removed, list))) {
07512       /* this hint has been removed, notify the watchers */
07513       while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) {
07514          thiscb->change_cb(saved_hint->context, saved_hint->exten,
07515             AST_EXTENSION_REMOVED, thiscb->data);
07516          /* Ref that we added when putting into saved_hint->callbacks */
07517          ao2_ref(thiscb, -1);
07518       }
07519       ast_free(saved_hint);
07520    }
07521 
07522    ast_mutex_unlock(&context_merge_lock);
07523    endlocktime = ast_tvnow();
07524 
07525    /*
07526     * The old list and hashtab no longer are relevant, delete them
07527     * while the rest of asterisk is now freely using the new stuff
07528     * instead.
07529     */
07530 
07531    ast_hashtab_destroy(oldtable, NULL);
07532 
07533    for (tmp = oldcontextslist; tmp; ) {
07534       struct ast_context *next;  /* next starting point */
07535 
07536       next = tmp->next;
07537       __ast_internal_context_destroy(tmp);
07538       tmp = next;
07539    }
07540    enddeltime = ast_tvnow();
07541 
07542    ft = ast_tvdiff_us(writelocktime, begintime);
07543    ft /= 1000000.0;
07544    ast_verb(3,"Time to scan old dialplan and merge leftovers back into the new: %8.6f sec\n", ft);
07545 
07546    ft = ast_tvdiff_us(endlocktime, writelocktime);
07547    ft /= 1000000.0;
07548    ast_verb(3,"Time to restore hints and swap in new dialplan: %8.6f sec\n", ft);
07549 
07550    ft = ast_tvdiff_us(enddeltime, endlocktime);
07551    ft /= 1000000.0;
07552    ast_verb(3,"Time to delete the old dialplan: %8.6f sec\n", ft);
07553 
07554    ft = ast_tvdiff_us(enddeltime, begintime);
07555    ft /= 1000000.0;
07556    ast_verb(3,"Total time merge_contexts_delete: %8.6f sec\n", ft);
07557 }

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

10608 {
10609    return pbx_parseable_goto(chan, goto_string, 0);
10610 }

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 8948 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_string_field_free_memory, ast_string_field_init, ast_string_field_set, 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().

08949 {
08950    struct ast_channel *chan;
08951    struct app_tmp *tmp;
08952    int res = -1, cdr_res = -1;
08953    struct outgoing_helper oh;
08954 
08955    memset(&oh, 0, sizeof(oh));
08956    oh.vars = vars;
08957    oh.account = account;
08958 
08959    if (locked_channel)
08960       *locked_channel = NULL;
08961    if (ast_strlen_zero(app)) {
08962       res = -1;
08963       goto outgoing_app_cleanup;
08964    }
08965    if (synchronous) {
08966       chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh);
08967       if (chan) {
08968          ast_set_variables(chan, vars);
08969          if (account)
08970             ast_cdr_setaccount(chan, account);
08971          if (chan->_state == AST_STATE_UP) {
08972             res = 0;
08973             ast_verb(4, "Channel %s was answered.\n", chan->name);
08974             tmp = ast_calloc(1, sizeof(*tmp));
08975             if (!tmp || ast_string_field_init(tmp, 252)) {
08976                if (tmp) {
08977                   ast_free(tmp);
08978                }
08979                res = -1;
08980             } else {
08981                ast_string_field_set(tmp, app, app);
08982                ast_string_field_set(tmp, data, appdata);
08983                tmp->chan = chan;
08984                if (synchronous > 1) {
08985                   if (locked_channel)
08986                      ast_channel_unlock(chan);
08987                   ast_pbx_run_app(tmp);
08988                } else {
08989                   if (locked_channel)
08990                      ast_channel_lock(chan);
08991                   if (ast_pthread_create_detached(&tmp->t, NULL, ast_pbx_run_app, tmp)) {
08992                      ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno));
08993                      ast_string_field_free_memory(tmp);
08994                      ast_free(tmp);
08995                      if (locked_channel)
08996                         ast_channel_unlock(chan);
08997                      ast_hangup(chan);
08998                      res = -1;
08999                   } else {
09000                      if (locked_channel)
09001                         *locked_channel = chan;
09002                   }
09003                }
09004             }
09005          } else {
09006             ast_verb(4, "Channel %s was never answered.\n", chan->name);
09007             if (chan->cdr) { /* update the cdr */
09008                /* here we update the status of the call, which sould be busy.
09009                 * if that fails then we set the status to failed */
09010                if (ast_cdr_disposition(chan->cdr, chan->hangupcause))
09011                   ast_cdr_failed(chan->cdr);
09012             }
09013             ast_hangup(chan);
09014          }
09015       }
09016 
09017       if (res < 0) { /* the call failed for some reason */
09018          if (*reason == 0) { /* if the call failed (not busy or no answer)
09019                         * update the cdr with the failed message */
09020             cdr_res = ast_pbx_outgoing_cdr_failed();
09021             if (cdr_res != 0) {
09022                res = cdr_res;
09023                goto outgoing_app_cleanup;
09024             }
09025          }
09026       }
09027 
09028    } else {
09029       struct async_stat *as;
09030       if (!(as = ast_calloc(1, sizeof(*as)))) {
09031          res = -1;
09032          goto outgoing_app_cleanup;
09033       }
09034       chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh);
09035       if (!chan) {
09036          ast_free(as);
09037          res = -1;
09038          goto outgoing_app_cleanup;
09039       }
09040       as->chan = chan;
09041       ast_copy_string(as->app, app, sizeof(as->app));
09042       if (appdata)
09043          ast_copy_string(as->appdata,  appdata, sizeof(as->appdata));
09044       as->timeout = timeout;
09045       ast_set_variables(chan, vars);
09046       if (account)
09047          ast_cdr_setaccount(chan, account);
09048       /* Start a new thread, and get something handling this channel. */
09049       if (locked_channel)
09050          ast_channel_lock(chan);
09051       if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) {
09052          ast_log(LOG_WARNING, "Failed to start async wait\n");
09053          ast_free(as);
09054          if (locked_channel)
09055             ast_channel_unlock(chan);
09056          ast_hangup(chan);
09057          res = -1;
09058          goto outgoing_app_cleanup;
09059       } else {
09060          if (locked_channel)
09061             *locked_channel = chan;
09062       }
09063       res = 0;
09064    }
09065 outgoing_app_cleanup:
09066    ast_variables_destroy(vars);
09067    return res;
09068 }

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

08780 {
08781    struct ast_channel *chan;
08782    struct async_stat *as;
08783    int res = -1, cdr_res = -1;
08784    struct outgoing_helper oh;
08785 
08786    if (synchronous) {
08787       oh.context = context;
08788       oh.exten = exten;
08789       oh.priority = priority;
08790       oh.cid_num = cid_num;
08791       oh.cid_name = cid_name;
08792       oh.account = account;
08793       oh.vars = vars;
08794       oh.parent_channel = NULL;
08795 
08796       chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh);
08797       if (channel) {
08798          *channel = chan;
08799          if (chan)
08800             ast_channel_lock(chan);
08801       }
08802       if (chan) {
08803          if (chan->_state == AST_STATE_UP) {
08804                res = 0;
08805             ast_verb(4, "Channel %s was answered.\n", chan->name);
08806 
08807             if (synchronous > 1) {
08808                if (channel)
08809                   ast_channel_unlock(chan);
08810                if (ast_pbx_run(chan)) {
08811                   ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name);
08812                   if (channel)
08813                      *channel = NULL;
08814                   ast_hangup(chan);
08815                   chan = NULL;
08816                   res = -1;
08817                }
08818             } else {
08819                if (ast_pbx_start(chan)) {
08820                   ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name);
08821                   if (channel) {
08822                      *channel = NULL;
08823                      ast_channel_unlock(chan);
08824                   }
08825                   ast_hangup(chan);
08826                   res = -1;
08827                }
08828                chan = NULL;
08829             }
08830          } else {
08831             ast_verb(4, "Channel %s was never answered.\n", chan->name);
08832 
08833             if (chan->cdr) { /* update the cdr */
08834                /* here we update the status of the call, which sould be busy.
08835                 * if that fails then we set the status to failed */
08836                if (ast_cdr_disposition(chan->cdr, chan->hangupcause))
08837                   ast_cdr_failed(chan->cdr);
08838             }
08839 
08840             if (channel) {
08841                *channel = NULL;
08842                ast_channel_unlock(chan);
08843             }
08844             ast_hangup(chan);
08845             chan = NULL;
08846          }
08847       }
08848 
08849       if (res < 0) { /* the call failed for some reason */
08850          if (*reason == 0) { /* if the call failed (not busy or no answer)
08851                         * update the cdr with the failed message */
08852             cdr_res = ast_pbx_outgoing_cdr_failed();
08853             if (cdr_res != 0) {
08854                res = cdr_res;
08855                goto outgoing_exten_cleanup;
08856             }
08857          }
08858 
08859          /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */
08860          /* check if "failed" exists */
08861          if (ast_exists_extension(chan, context, "failed", 1, NULL)) {
08862             chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", NULL, 0, "OutgoingSpoolFailed");
08863             if (chan) {
08864                char failed_reason[4] = "";
08865                if (!ast_strlen_zero(context))
08866                   ast_copy_string(chan->context, context, sizeof(chan->context));
08867                set_ext_pri(chan, "failed", 1);
08868                ast_set_variables(chan, vars);
08869                snprintf(failed_reason, sizeof(failed_reason), "%d", *reason);
08870                pbx_builtin_setvar_helper(chan, "REASON", failed_reason);
08871                if (account)
08872                   ast_cdr_setaccount(chan, account);
08873                if (ast_pbx_run(chan)) {
08874                   ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name);
08875                   ast_hangup(chan);
08876                }
08877                chan = NULL;
08878             }
08879          }
08880       }
08881    } else {
08882       if (!(as = ast_calloc(1, sizeof(*as)))) {
08883          res = -1;
08884          goto outgoing_exten_cleanup;
08885       }
08886       chan = ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name);
08887       if (channel) {
08888          *channel = chan;
08889          if (chan)
08890             ast_channel_lock(chan);
08891       }
08892       if (!chan) {
08893          ast_free(as);
08894          res = -1;
08895          goto outgoing_exten_cleanup;
08896       }
08897       as->chan = chan;
08898       ast_copy_string(as->context, context, sizeof(as->context));
08899       set_ext_pri(as->chan,  exten, priority);
08900       as->timeout = timeout;
08901       ast_set_variables(chan, vars);
08902       if (account)
08903          ast_cdr_setaccount(chan, account);
08904       if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) {
08905          ast_log(LOG_WARNING, "Failed to start async wait\n");
08906          ast_free(as);
08907          if (channel) {
08908             *channel = NULL;
08909             ast_channel_unlock(chan);
08910          }
08911          ast_hangup(chan);
08912          res = -1;
08913          goto outgoing_exten_cleanup;
08914       }
08915       res = 0;
08916    }
08917 outgoing_exten_cleanup:
08918    ast_variables_destroy(vars);
08919    return res;
08920 }

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

05383 {
05384    return ast_pbx_run_args(c, NULL);
05385 }

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

References __ast_pbx_run(), args, ast_log(), AST_OPT_FLAG_FULLY_BOOTED, ast_options, AST_PBX_CALL_LIMIT, AST_PBX_FAILED, AST_PBX_SUCCESS, ast_test_flag, decrease_call_count(), increase_call_count(), and LOG_WARNING.

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

05363 {
05364    enum ast_pbx_result res = AST_PBX_SUCCESS;
05365 
05366    if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) {
05367       ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n");
05368       return AST_PBX_FAILED;
05369    }
05370 
05371    if (increase_call_count(c)) {
05372       return AST_PBX_CALL_LIMIT;
05373    }
05374 
05375    res = __ast_pbx_run(c, args);
05376 
05377    decrease_call_count();
05378 
05379    return res;
05380 }

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

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

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

05336 {
05337    pthread_t t;
05338 
05339    if (!c) {
05340       ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
05341       return AST_PBX_FAILED;
05342    }
05343 
05344    if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) {
05345       ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n");
05346       return AST_PBX_FAILED;
05347    }
05348 
05349    if (increase_call_count(c))
05350       return AST_PBX_CALL_LIMIT;
05351 
05352    /* Start a new thread, and get something handling this channel. */
05353    if (ast_pthread_create_detached(&t, NULL, pbx_thread, c)) {
05354       ast_log(LOG_WARNING, "Failed to create new channel thread\n");
05355       decrease_call_count();
05356       return AST_PBX_FAILED;
05357    }
05358 
05359    return AST_PBX_SUCCESS;
05360 }

int ast_processed_calls ( void   ) 

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

Definition at line 5392 of file pbx.c.

References totalcalls.

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

05393 {
05394    return totalcalls;
05395 }

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

10342 {
10343    return ast_rwlock_rdlock(&con->lock);
10344 }

int ast_rdlock_contexts ( void   ) 

Read locks the context list.

Return values:
0 on success
-1 on error

Definition at line 10323 of file pbx.c.

References ast_mutex_lock, and conlock.

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

10324 {
10325    return ast_mutex_lock(&conlock);
10326 }

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

05899 {
05900    struct ast_switch *tmp;
05901 
05902    AST_RWLIST_WRLOCK(&switches);
05903    AST_RWLIST_TRAVERSE(&switches, tmp, list) {
05904       if (!strcasecmp(tmp->name, sw->name)) {
05905          AST_RWLIST_UNLOCK(&switches);
05906          ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name);
05907          return -1;
05908       }
05909    }
05910    AST_RWLIST_INSERT_TAIL(&switches, sw, list);
05911    AST_RWLIST_UNLOCK(&switches);
05912 
05913    return 0;
05914 }

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

04886 {
04887    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN, found, combined_find_spawn);
04888 }

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

04841 {
04842    struct ast_exten *e = ast_hint_extension(c, context, exten);
04843 
04844    if (!e) {
04845       return 0;
04846    }
04847 
04848    if (hint) {
04849       ast_str_set(hint, hintsize, "%s", ast_get_extension_app(e));
04850    }
04851    if (name) {
04852       const char *tmp = ast_get_extension_app_data(e);
04853       if (tmp) {
04854          ast_str_set(name, namesize, "%s", tmp);
04855       }
04856    }
04857    return -1;
04858 }

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

03131 {
03132    const char not_found = '\0';
03133    char *tmpvar;
03134    const char *ret;
03135    const char *s; /* the result */
03136    int offset, length;
03137    int i, need_substring;
03138    struct varshead *places[2] = { headp, &globals };  /* list of places where we may look */
03139 
03140    if (c) {
03141       ast_channel_lock(c);
03142       places[0] = &c->varshead;
03143    }
03144    /*
03145     * Make a copy of var because parse_variable_name() modifies the string.
03146     * Then if called directly, we might need to run substring() on the result;
03147     * remember this for later in 'need_substring', 'offset' and 'length'
03148     */
03149    tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */
03150    need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */);
03151 
03152    /*
03153     * Look first into predefined variables, then into variable lists.
03154     * Variable 's' points to the result, according to the following rules:
03155     * s == &not_found (set at the beginning) means that we did not find a
03156     * matching variable and need to look into more places.
03157     * If s != &not_found, s is a valid result string as follows:
03158     * s = NULL if the variable does not have a value;
03159     * you typically do this when looking for an unset predefined variable.
03160     * s = workspace if the result has been assembled there;
03161     * typically done when the result is built e.g. with an snprintf(),
03162     * so we don't need to do an additional copy.
03163     * s != workspace in case we have a string, that needs to be copied
03164     * (the ast_copy_string is done once for all at the end).
03165     * Typically done when the result is already available in some string.
03166     */
03167    s = &not_found;   /* default value */
03168    if (c) { /* This group requires a valid channel */
03169       /* Names with common parts are looked up a piece at a time using strncmp. */
03170       if (!strncmp(var, "CALL", 4)) {
03171          if (!strncmp(var + 4, "ING", 3)) {
03172             if (!strcmp(var + 7, "PRES")) {        /* CALLINGPRES */
03173                ast_str_set(str, maxlen, "%d",
03174                   ast_party_id_presentation(&c->caller.id));
03175                s = ast_str_buffer(*str);
03176             } else if (!strcmp(var + 7, "ANI2")) {    /* CALLINGANI2 */
03177                ast_str_set(str, maxlen, "%d", c->caller.ani2);
03178                s = ast_str_buffer(*str);
03179             } else if (!strcmp(var + 7, "TON")) {     /* CALLINGTON */
03180                ast_str_set(str, maxlen, "%d", c->caller.id.number.plan);
03181                s = ast_str_buffer(*str);
03182             } else if (!strcmp(var + 7, "TNS")) {     /* CALLINGTNS */
03183                ast_str_set(str, maxlen, "%d", c->dialed.transit_network_select);
03184                s = ast_str_buffer(*str);
03185             }
03186          }
03187       } else if (!strcmp(var, "HINT")) {
03188          s = ast_str_get_hint(str, maxlen, NULL, 0, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL;
03189       } else if (!strcmp(var, "HINTNAME")) {
03190          s = ast_str_get_hint(NULL, 0, str, maxlen, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL;
03191       } else if (!strcmp(var, "EXTEN")) {
03192          s = c->exten;
03193       } else if (!strcmp(var, "CONTEXT")) {
03194          s = c->context;
03195       } else if (!strcmp(var, "PRIORITY")) {
03196          ast_str_set(str, maxlen, "%d", c->priority);
03197          s = ast_str_buffer(*str);
03198       } else if (!strcmp(var, "CHANNEL")) {
03199          s = c->name;
03200       } else if (!strcmp(var, "UNIQUEID")) {
03201          s = c->uniqueid;
03202       } else if (!strcmp(var, "HANGUPCAUSE")) {
03203          ast_str_set(str, maxlen, "%d", c->hangupcause);
03204          s = ast_str_buffer(*str);
03205       }
03206    }
03207    if (s == &not_found) { /* look for more */
03208       if (!strcmp(var, "EPOCH")) {
03209          ast_str_set(str, maxlen, "%u", (int) time(NULL));
03210          s = ast_str_buffer(*str);
03211       } else if (!strcmp(var, "SYSTEMNAME")) {
03212          s = ast_config_AST_SYSTEM_NAME;
03213       } else if (!strcmp(var, "ENTITYID")) {
03214          char workspace[20];
03215          ast_eid_to_str(workspace, sizeof(workspace), &ast_eid_default);
03216          s = workspace;
03217       }
03218    }
03219    /* if not found, look into chanvars or global vars */
03220    for (i = 0; s == &not_found && i < ARRAY_LEN(places); i++) {
03221       struct ast_var_t *variables;
03222       if (!places[i])
03223          continue;
03224       if (places[i] == &globals)
03225          ast_rwlock_rdlock(&globalslock);
03226       AST_LIST_TRAVERSE(places[i], variables, entries) {
03227          if (!strcasecmp(ast_var_name(variables), var)) {
03228             s = ast_var_value(variables);
03229             break;
03230          }
03231       }
03232       if (places[i] == &globals)
03233          ast_rwlock_unlock(&globalslock);
03234    }
03235    if (s == &not_found || s == NULL) {
03236       ast_debug(5, "Result of '%s' is NULL\n", var);
03237       ret = NULL;
03238    } else {
03239       ast_debug(5, "Result of '%s' is '%s'\n", var, s);
03240       if (s != ast_str_buffer(*str)) {
03241          ast_str_set(str, maxlen, "%s", s);
03242       }
03243       ret = ast_str_buffer(*str);
03244       if (need_substring) {
03245          ret = ast_str_substring(*str, offset, length);
03246          ast_debug(2, "Final result of '%s' is '%s'\n", var, ret);
03247       }
03248    }
03249 
03250    if (c) {
03251       ast_channel_unlock(c);
03252    }
03253    return ret;
03254 }

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

03929 {
03930    size_t used;
03931    ast_str_substitute_variables_full(buf, maxlen, chan, NULL, templ, &used);
03932 }

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

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

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

03750 {
03751    /* Substitutes variables into buf, based on string templ */
03752    char *cp4 = NULL;
03753    const char *tmp, *whereweare;
03754    int orig_size = 0;
03755    int offset, offset2, isfunction;
03756    const char *nextvar, *nextexp, *nextthing;
03757    const char *vars, *vare;
03758    char *finalvars;
03759    int pos, brackets, needsub, len;
03760    struct ast_str *substr1 = ast_str_create(16), *substr2 = NULL, *substr3 = ast_str_create(16);
03761 
03762    ast_str_reset(*buf);
03763    whereweare = tmp = templ;
03764    while (!ast_strlen_zero(whereweare)) {
03765       /* reset our buffer */
03766       ast_str_reset(substr3);
03767 
03768       /* Assume we're copying the whole remaining string */
03769       pos = strlen(whereweare);
03770       nextvar = NULL;
03771       nextexp = NULL;
03772       nextthing = strchr(whereweare, '$');
03773       if (nextthing) {
03774          switch (nextthing[1]) {
03775          case '{':
03776             nextvar = nextthing;
03777             pos = nextvar - whereweare;
03778             break;
03779          case '[':
03780             nextexp = nextthing;
03781             pos = nextexp - whereweare;
03782             break;
03783          default:
03784             pos = 1;
03785          }
03786       }
03787 
03788       if (pos) {
03789          /* Copy that many bytes */
03790          ast_str_append_substr(buf, maxlen, whereweare, pos);
03791 
03792          templ += pos;
03793          whereweare += pos;
03794       }
03795 
03796       if (nextvar) {
03797          /* We have a variable.  Find the start and end, and determine
03798             if we are going to have to recursively call ourselves on the
03799             contents */
03800          vars = vare = nextvar + 2;
03801          brackets = 1;
03802          needsub = 0;
03803 
03804          /* Find the end of it */
03805          while (brackets && *vare) {
03806             if ((vare[0] == '$') && (vare[1] == '{')) {
03807                needsub++;
03808             } else if (vare[0] == '{') {
03809                brackets++;
03810             } else if (vare[0] == '}') {
03811                brackets--;
03812             } else if ((vare[0] == '$') && (vare[1] == '['))
03813                needsub++;
03814             vare++;
03815          }
03816          if (brackets)
03817             ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n");
03818          len = vare - vars - 1;
03819 
03820          /* Skip totally over variable string */
03821          whereweare += (len + 3);
03822 
03823          /* Store variable name (and truncate) */
03824          ast_str_set_substr(&substr1, 0, vars, len);
03825          ast_debug(5, "Evaluating '%s' (from '%s' len %d)\n", ast_str_buffer(substr1), vars, len);
03826 
03827          /* Substitute if necessary */
03828          if (needsub) {
03829             size_t used;
03830             if (!substr2) {
03831                substr2 = ast_str_create(16);
03832             }
03833 
03834             ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used);
03835             finalvars = ast_str_buffer(substr2);
03836          } else {
03837             finalvars = ast_str_buffer(substr1);
03838          }
03839 
03840          parse_variable_name(finalvars, &offset, &offset2, &isfunction);
03841          if (isfunction) {
03842             /* Evaluate function */
03843             if (c || !headp) {
03844                cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3);
03845             } else {
03846                struct varshead old;
03847                struct ast_channel *bogus = ast_dummy_channel_alloc();
03848                if (bogus) {
03849                   memcpy(&old, &bogus->varshead, sizeof(old));
03850                   memcpy(&bogus->varshead, headp, sizeof(bogus->varshead));
03851                   cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3);
03852                   /* Don't deallocate the varshead that was passed in */
03853                   memcpy(&bogus->varshead, &old, sizeof(bogus->varshead));
03854                   ast_channel_unref(bogus);
03855                } else {
03856                   ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution.  Function results may be blank.\n");
03857                }
03858             }
03859             ast_debug(2, "Function result is '%s'\n", cp4 ? cp4 : "(null)");
03860          } else {
03861             /* Retrieve variable value */
03862             ast_str_retrieve_variable(&substr3, 0, c, headp, finalvars);
03863             cp4 = ast_str_buffer(substr3);
03864          }
03865          if (cp4) {
03866             ast_str_substring(substr3, offset, offset2);
03867             ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3));
03868          }
03869       } else if (nextexp) {
03870          /* We have an expression.  Find the start and end, and determine
03871             if we are going to have to recursively call ourselves on the
03872             contents */
03873          vars = vare = nextexp + 2;
03874          brackets = 1;
03875          needsub = 0;
03876 
03877          /* Find the end of it */
03878          while (brackets && *vare) {
03879             if ((vare[0] == '$') && (vare[1] == '[')) {
03880                needsub++;
03881                brackets++;
03882                vare++;
03883             } else if (vare[0] == '[') {
03884                brackets++;
03885             } else if (vare[0] == ']') {
03886                brackets--;
03887             } else if ((vare[0] == '$') && (vare[1] == '{')) {
03888                needsub++;
03889                vare++;
03890             }
03891             vare++;
03892          }
03893          if (brackets)
03894             ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n");
03895          len = vare - vars - 1;
03896 
03897          /* Skip totally over expression */
03898          whereweare += (len + 3);
03899 
03900          /* Store variable name (and truncate) */
03901          ast_str_set_substr(&substr1, 0, vars, len);
03902 
03903          /* Substitute if necessary */
03904          if (needsub) {
03905             size_t used;
03906             if (!substr2) {
03907                substr2 = ast_str_create(16);
03908             }
03909 
03910             ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used);
03911             finalvars = ast_str_buffer(substr2);
03912          } else {
03913             finalvars = ast_str_buffer(substr1);
03914          }
03915 
03916          if (ast_str_expr(&substr3, 0, c, finalvars)) {
03917             ast_debug(2, "Expression result is '%s'\n", ast_str_buffer(substr3));
03918          }
03919          ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3));
03920       }
03921    }
03922    *used = ast_str_strlen(*buf) - orig_size;
03923    ast_free(substr1);
03924    ast_free(substr2);
03925    ast_free(substr3);
03926 }

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

03935 {
03936    size_t used;
03937    ast_str_substitute_variables_full(buf, maxlen, NULL, headp, templ, &used);
03938 }

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

10347 {
10348    return ast_rwlock_unlock(&con->lock);
10349 }

int ast_unlock_contexts ( void   ) 

Unlocks contexts.

Return values:
0 on success
-1 on failure

Definition at line 10328 of file pbx.c.

References ast_mutex_unlock, and conlock.

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

10329 {
10330    return ast_mutex_unlock(&conlock);
10331 }

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

05917 {
05918    AST_RWLIST_WRLOCK(&switches);
05919    AST_RWLIST_REMOVE(&switches, sw, list);
05920    AST_RWLIST_UNLOCK(&switches);
05921 }

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

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

10462 {
10463    if (!exten)
10464       return con ? con->root : NULL;
10465    else
10466       return exten->next;
10467 }

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

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

10495 {
10496    if (!ip)
10497       return con ? con->ignorepats : NULL;
10498    else
10499       return ip->next;
10500 }

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

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

10486 {
10487    if (!inc)
10488       return con ? con->includes : NULL;
10489    else
10490       return inc->next;
10491 }

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

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

10471 {
10472    if (!sw)
10473       return con ? AST_LIST_FIRST(&con->alts) : NULL;
10474    else
10475       return AST_LIST_NEXT(sw, list);
10476 }

struct ast_context* ast_walk_contexts ( struct ast_context con  ) 

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

10456 {
10457    return con ? con->next : contexts;
10458 }

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

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

10480 {
10481    return priority ? priority->peer : exten;
10482 }

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

10337 {
10338    return ast_rwlock_wrlock(&con->lock);
10339 }

int ast_wrlock_contexts ( void   ) 

Write locks the context list.

Return values:
0 on success
-1 on error

Definition at line 10318 of file pbx.c.

References ast_mutex_lock, and conlock.

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

10319 {
10320    return ast_mutex_lock(&conlock);
10321 }

void pbx_builtin_clear_globals ( void   ) 

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

10113 {
10114    struct ast_var_t *vardata;
10115 
10116    ast_rwlock_wrlock(&globalslock);
10117    while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries)))
10118       ast_var_delete(vardata);
10119    ast_rwlock_unlock(&globalslock);
10120 }

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 9874 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(), create_dynamic_parkinglot(), crement_function_read(), dahdi_hangup(), dahdi_r2_answer(), dahdi_r2_get_channel_category(), dial_exec_full(), do_forward(), dundi_exec(), dundi_helper(), feature_check(), 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().

09875 {
09876    struct ast_var_t *variables;
09877    const char *ret = NULL;
09878    int i;
09879    struct varshead *places[2] = { NULL, &globals };
09880 
09881    if (!name)
09882       return NULL;
09883 
09884    if (chan) {
09885       ast_channel_lock(chan);
09886       places[0] = &chan->varshead;
09887    }
09888 
09889    for (i = 0; i < 2; i++) {
09890       if (!places[i])
09891          continue;
09892       if (places[i] == &globals)
09893          ast_rwlock_rdlock(&globalslock);
09894       AST_LIST_TRAVERSE(places[i], variables, entries) {
09895          if (!strcmp(name, ast_var_name(variables))) {
09896             ret = ast_var_value(variables);
09897             break;
09898          }
09899       }
09900       if (places[i] == &globals)
09901          ast_rwlock_unlock(&globalslock);
09902       if (ret)
09903          break;
09904    }
09905 
09906    if (chan)
09907       ast_channel_unlock(chan);
09908 
09909    return ret;
09910 }

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

09913 {
09914    struct ast_var_t *newvariable;
09915    struct varshead *headp;
09916 
09917    if (name[strlen(name)-1] == ')') {
09918       char *function = ast_strdupa(name);
09919 
09920       ast_log(LOG_WARNING, "Cannot push a value onto a function\n");
09921       ast_func_write(chan, function, value);
09922       return;
09923    }
09924 
09925    if (chan) {
09926       ast_channel_lock(chan);
09927       headp = &chan->varshead;
09928    } else {
09929       ast_rwlock_wrlock(&globalslock);
09930       headp = &globals;
09931    }
09932 
09933    if (value) {
09934       if (headp == &globals)
09935          ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value);
09936       newvariable = ast_var_assign(name, value);
09937       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
09938    }
09939 
09940    if (chan)
09941       ast_channel_unlock(chan);
09942    else
09943       ast_rwlock_unlock(&globalslock);
09944 }

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

Definition at line 3305 of file pbx.c.

References raise_exception().

03306 {
03307    /* Priority will become 1, next time through the AUTOLOOP */
03308    return raise_exception(chan, reason, 0);
03309 }

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

09844 {
09845    struct ast_var_t *variables;
09846    const char *var, *val;
09847    int total = 0;
09848 
09849    if (!chan)
09850       return 0;
09851 
09852    ast_str_reset(*buf);
09853 
09854    ast_channel_lock(chan);
09855 
09856    AST_LIST_TRAVERSE(&chan->varshead, variables, entries) {
09857       if ((var = ast_var_name(variables)) && (val = ast_var_value(variables))
09858          /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */
09859          ) {
09860          if (ast_str_append(buf, 0, "%s=%s\n", var, val) < 0) {
09861             ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
09862             break;
09863          } else
09864             total++;
09865       } else
09866          break;
09867    }
09868 
09869    ast_channel_unlock(chan);
09870 
09871    return total;
09872 }

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

10005 {
10006    char *name, *value, *mydata;
10007 
10008    if (ast_compat_app_set) {
10009       return pbx_builtin_setvar_multiple(chan, data);
10010    }
10011 
10012    if (ast_strlen_zero(data)) {
10013       ast_log(LOG_WARNING, "Set requires one variable name/value pair.\n");
10014       return 0;
10015    }
10016 
10017    mydata = ast_strdupa(data);
10018    name = strsep(&mydata, "=");
10019    value = mydata;
10020    if (!value) {
10021       ast_log(LOG_WARNING, "Set requires an '=' to be a valid assignment.\n");
10022       return 0;
10023    }
10024 
10025    if (strchr(name, ' ')) {
10026       ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, mydata);
10027    }
10028 
10029    pbx_builtin_setvar_helper(chan, name, value);
10030 
10031    return 0;
10032 }

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 9946 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_eivr_setvariable(), ast_iax2_new(), ast_monitor_start(), ast_monitor_stop(), ast_pbx_outgoing_exten(), ast_pickup_call(), ast_rtp_instance_set_stats_vars(), ast_set_cc_interfaces_chanvar(), ast_set_variables(), asyncgoto_exec(), background_detect_exec(), bridge_exec(), bridge_play_sounds(), builtin_atxfer(), builtin_automixmonitor(), builtin_automonitor(), builtin_blindtransfer(), cb_events(), cccancel_exec(), ccreq_exec(), chanavail_exec(), channel_spy(), commit_exec(), conf_run(), controlplayback_exec(), count_exec(), crement_function_read(), dahdi_handle_dtmf(), dahdi_new(), dial_exec_full(), do_waiting(), end_bridge_callback(), export_aoc_vars(), export_ch(), feature_exec_app(), feature_request_and_dial(), frame_set_var(), func_mchan_write(), function_db_delete(), function_db_exists(), function_db_read(), function_realtime_store(), generic_recall(), get_rdnis(), get_refer_info(), global_write(), gosub_release_frame(), handle_incoming(), handle_request_bye(), handle_request_refer(), handle_set_chanvar(), handle_set_global(), handle_setvariable(), hash_read(), hash_write(), isAnsweringMachine(), leave_queue(), leave_voicemail(), local_hangup(), lua_set_variable(), lua_set_variable_value(), macro_fixup(), manage_parked_call(), mgcp_new(), minivm_accmess_exec(), minivm_delete_exec(), minivm_greet_exec(), minivm_notify_exec(), minivm_record_exec(), misdn_call(), mixmonitor_exec(), my_handle_dtmf(), originate_exec(), ospauth_exec(), ospfinished_exec(), osplookup_exec(), ospnext_exec(), parked_call_exec(), parse_moved_contact(), pbx_builtin_background(), pbx_builtin_gotoiftime(), pbx_builtin_importvar(), pbx_builtin_setvar(), pbx_builtin_setvar_multiple(), pbx_load_config(), phase_e_handler(), play_message_datetime(), playback_exec(), pqm_exec(), prep_email_sub_vars(), 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().

09947 {
09948    struct ast_var_t *newvariable;
09949    struct varshead *headp;
09950    const char *nametail = name;
09951 
09952    if (name[strlen(name) - 1] == ')') {
09953       char *function = ast_strdupa(name);
09954 
09955       return ast_func_write(chan, function, value);
09956    }
09957 
09958    if (chan) {
09959       ast_channel_lock(chan);
09960       headp = &chan->varshead;
09961    } else {
09962       ast_rwlock_wrlock(&globalslock);
09963       headp = &globals;
09964    }
09965 
09966    /* For comparison purposes, we have to strip leading underscores */
09967    if (*nametail == '_') {
09968       nametail++;
09969       if (*nametail == '_')
09970          nametail++;
09971    }
09972 
09973    AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) {
09974       if (strcmp(ast_var_name(newvariable), nametail) == 0) {
09975          /* there is already such a variable, delete it */
09976          AST_LIST_REMOVE_CURRENT(entries);
09977          ast_var_delete(newvariable);
09978          break;
09979       }
09980    }
09981    AST_LIST_TRAVERSE_SAFE_END;
09982 
09983    if (value) {
09984       if (headp == &globals)
09985          ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value);
09986       newvariable = ast_var_assign(name, value);
09987       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
09988       manager_event(EVENT_FLAG_DIALPLAN, "VarSet",
09989          "Channel: %s\r\n"
09990          "Variable: %s\r\n"
09991          "Value: %s\r\n"
09992          "Uniqueid: %s\r\n",
09993          chan ? chan->name : "none", name, value,
09994          chan ? chan->uniqueid : "none");
09995    }
09996 
09997    if (chan)
09998       ast_channel_unlock(chan);
09999    else
10000       ast_rwlock_unlock(&globalslock);
10001    return 0;
10002 }

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

10035 {
10036    char *data;
10037    int x;
10038    AST_DECLARE_APP_ARGS(args,
10039       AST_APP_ARG(pair)[24];
10040    );
10041    AST_DECLARE_APP_ARGS(pair,
10042       AST_APP_ARG(name);
10043       AST_APP_ARG(value);
10044    );
10045 
10046    if (ast_strlen_zero(vdata)) {
10047       ast_log(LOG_WARNING, "MSet requires at least one variable name/value pair.\n");
10048       return 0;
10049    }
10050 
10051    data = ast_strdupa(vdata);
10052    AST_STANDARD_APP_ARGS(args, data);
10053 
10054    for (x = 0; x < args.argc; x++) {
10055       AST_NONSTANDARD_APP_ARGS(pair, args.pair[x], '=');
10056       if (pair.argc == 2) {
10057          pbx_builtin_setvar_helper(chan, pair.name, pair.value);
10058          if (strchr(pair.name, ' '))
10059             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);
10060       } else if (!chan) {
10061          ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '='\n", pair.name);
10062       } else {
10063          ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '=' (in %s@%s:%d\n", pair.name, chan->exten, chan->context, chan->priority);
10064       }
10065    }
10066 
10067    return 0;
10068 }

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

10123 {
10124    int res;
10125    if (ast_strlen_zero(condition)) {                /* NULL or empty strings are false */
10126       return 0;
10127    } else if (sscanf(condition, "%30d", &res) == 1) { /* Numbers are evaluated for truth */
10128       return res;
10129    } else {                                         /* Strings are true */
10130       return 1;
10131    }
10132 }

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 1402 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 aelsub_exec(), answer_exec_run(), ast_app_run_macro(), ast_bridge_call(), ast_pbx_run_app(), async_wait(), builtin_automixmonitor(), builtin_automonitor(), conf_run(), dial_exec_full(), do_magic_pickup(), dundi_exec(), exec_exec(), execif_exec(), feature_exec_app(), forward_message(), handle_exec(), handle_gosub(), iax2_exec(), lua_pbx_exec(), page_exec(), pbx_builtin_execiftime(), pbx_extension_helper(), and tryexec_exec().

01405 {
01406    int res;
01407    struct ast_module_user *u = NULL;
01408    const char *saved_c_appl;
01409    const char *saved_c_data;
01410 
01411    if (c->cdr && !ast_check_hangup(c))
01412       ast_cdr_setapp(c->cdr, app->name, data);
01413 
01414    /* save channel values */
01415    saved_c_appl= c->appl;
01416    saved_c_data= c->data;
01417 
01418    c->appl = app->name;
01419    c->data = data;
01420    ast_cel_report_event(c, AST_CEL_APP_START, NULL, NULL, NULL);
01421 
01422    if (app->module)
01423       u = __ast_module_user_add(app->module, c);
01424    if (strcasecmp(app->name, "system") && !ast_strlen_zero(data) &&
01425          strchr(data, '|') && !strchr(data, ',') && !ast_opt_dont_warn) {
01426       ast_log(LOG_WARNING, "The application delimiter is now the comma, not "
01427          "the pipe.  Did you forget to convert your dialplan?  (%s(%s))\n",
01428          app->name, (char *) data);
01429    }
01430    res = app->execute(c, S_OR(data, ""));
01431    if (app->module && u)
01432       __ast_module_user_remove(app->module, u);
01433    ast_cel_report_event(c, AST_CEL_APP_END, NULL, NULL, NULL);
01434    /* restore channel values */
01435    c->appl = saved_c_appl;
01436    c->data = saved_c_data;
01437    return res;
01438 }

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

References ast_context::alts, ast_autoservice_start(), ast_autoservice_stop(), ast_hashtab_lookup(), AST_LIST_TRAVERSE, ast_log(), AST_PBX_MAX_STACK, ast_str_buffer(), ast_str_size(), ast_str_thread_get(), ast_strdupa, ast_strlen_zero(), ast_walk_context_extensions(), ast_switch::canmatch, scoreboard::canmatch_exten, create_match_char_tree(), 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(), find_context(), pbx_find_info::foundcontext, include_valid(), ast_context::includes, pbx_find_info::incstack, ast_exten::label, scoreboard::last_char, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, match(), matchcid(), ast_switch::matchmore, ast_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(), check_goto(), check_pval_item(), get_parking_exten(), pbx_extension_helper(), pbx_find_extension(), register_peer_exten(), and remove_exten_if_exist().

02702 {
02703    int x, res;
02704    struct ast_context *tmp = NULL;
02705    struct ast_exten *e = NULL, *eroot = NULL;
02706    struct ast_include *i = NULL;
02707    struct ast_sw *sw = NULL;
02708    struct ast_exten pattern = {NULL, };
02709    struct scoreboard score = {0, };
02710    struct ast_str *tmpdata = NULL;
02711 
02712    pattern.label = label;
02713    pattern.priority = priority;
02714 #ifdef NEED_DEBUG_HERE
02715    ast_log(LOG_NOTICE, "Looking for cont/ext/prio/label/action = %s/%s/%d/%s/%d\n", context, exten, priority, label, (int) action);
02716 #endif
02717 
02718    /* Initialize status if appropriate */
02719    if (q->stacklen == 0) {
02720       q->status = STATUS_NO_CONTEXT;
02721       q->swo = NULL;
02722       q->data = NULL;
02723       q->foundcontext = NULL;
02724    } else if (q->stacklen >= AST_PBX_MAX_STACK) {
02725       ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n");
02726       return NULL;
02727    }
02728 
02729    /* Check first to see if we've already been checked */
02730    for (x = 0; x < q->stacklen; x++) {
02731       if (!strcasecmp(q->incstack[x], context))
02732          return NULL;
02733    }
02734 
02735    if (bypass) { /* bypass means we only look there */
02736       tmp = bypass;
02737    } else {      /* look in contexts */
02738       tmp = find_context(context);
02739       if (!tmp) {
02740          return NULL;
02741       }
02742    }
02743 
02744    if (q->status < STATUS_NO_EXTENSION)
02745       q->status = STATUS_NO_EXTENSION;
02746 
02747    /* Do a search for matching extension */
02748 
02749    eroot = NULL;
02750    score.total_specificity = 0;
02751    score.exten = 0;
02752    score.total_length = 0;
02753    if (!tmp->pattern_tree && tmp->root_table) {
02754       create_match_char_tree(tmp);
02755 #ifdef NEED_DEBUG
02756       ast_log(LOG_DEBUG, "Tree Created in context %s:\n", context);
02757       log_match_char_tree(tmp->pattern_tree," ");
02758 #endif
02759    }
02760 #ifdef NEED_DEBUG
02761    ast_log(LOG_NOTICE, "The Trie we are searching in:\n");
02762    log_match_char_tree(tmp->pattern_tree, "::  ");
02763 #endif
02764 
02765    do {
02766       if (!ast_strlen_zero(overrideswitch)) {
02767          char *osw = ast_strdupa(overrideswitch), *name;
02768          struct ast_switch *asw;
02769          ast_switch_f *aswf = NULL;
02770          char *datap;
02771          int eval = 0;
02772 
02773          name = strsep(&osw, "/");
02774          asw = pbx_findswitch(name);
02775 
02776          if (!asw) {
02777             ast_log(LOG_WARNING, "No such switch '%s'\n", name);
02778             break;
02779          }
02780 
02781          if (osw && strchr(osw, '$')) {
02782             eval = 1;
02783          }
02784 
02785          if (eval && !(tmpdata = ast_str_thread_get(&switch_data, 512))) {
02786             ast_log(LOG_WARNING, "Can't evaluate overrideswitch?!");
02787             break;
02788          } else if (eval) {
02789             /* Substitute variables now */
02790             pbx_substitute_variables_helper(chan, osw, ast_str_buffer(tmpdata), ast_str_size(tmpdata));
02791             datap = ast_str_buffer(tmpdata);
02792          } else {
02793             datap = osw;
02794          }
02795 
02796          /* equivalent of extension_match_core() at the switch level */
02797          if (action == E_CANMATCH)
02798             aswf = asw->canmatch;
02799          else if (action == E_MATCHMORE)
02800             aswf = asw->matchmore;
02801          else /* action == E_MATCH */
02802             aswf = asw->exists;
02803          if (!aswf) {
02804             res = 0;
02805          } else {
02806             if (chan) {
02807                ast_autoservice_start(chan);
02808             }
02809             res = aswf(chan, context, exten, priority, callerid, datap);
02810             if (chan) {
02811                ast_autoservice_stop(chan);
02812             }
02813          }
02814          if (res) {  /* Got a match */
02815             q->swo = asw;
02816             q->data = datap;
02817             q->foundcontext = context;
02818             /* XXX keep status = STATUS_NO_CONTEXT ? */
02819             return NULL;
02820          }
02821       }
02822    } while (0);
02823 
02824    if (extenpatternmatchnew) {
02825       new_find_extension(exten, &score, tmp->pattern_tree, 0, 0, callerid, label, action);
02826       eroot = score.exten;
02827 
02828       if (score.last_char == '!' && action == E_MATCHMORE) {
02829          /* We match an extension ending in '!'.
02830           * The decision in this case is final and is NULL (no match).
02831           */
02832 #ifdef NEED_DEBUG_HERE
02833          ast_log(LOG_NOTICE,"Returning MATCHMORE NULL with exclamation point.\n");
02834 #endif
02835          return NULL;
02836       }
02837 
02838       if (!eroot && (action == E_CANMATCH || action == E_MATCHMORE) && score.canmatch_exten) {
02839          q->status = STATUS_SUCCESS;
02840 #ifdef NEED_DEBUG_HERE
02841          ast_log(LOG_NOTICE,"Returning CANMATCH exten %s\n", score.canmatch_exten->exten);
02842 #endif
02843          return score.canmatch_exten;
02844       }
02845 
02846       if ((action == E_MATCHMORE || action == E_CANMATCH)  && eroot) {
02847          if (score.node) {
02848             struct ast_exten *z = trie_find_next_match(score.node);
02849             if (z) {
02850 #ifdef NEED_DEBUG_HERE
02851                ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten %s\n", z->exten);
02852 #endif
02853             } else {
02854                if (score.canmatch_exten) {
02855 #ifdef NEED_DEBUG_HERE
02856                   ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE canmatchmatch exten %s(%p)\n", score.canmatch_exten->exten, score.canmatch_exten);
02857 #endif
02858                   return score.canmatch_exten;
02859                } else {
02860 #ifdef NEED_DEBUG_HERE
02861                   ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten NULL\n");
02862 #endif
02863                }
02864             }
02865             return z;
02866          }
02867 #ifdef NEED_DEBUG_HERE
02868          ast_log(LOG_NOTICE, "Returning CANMATCH/MATCHMORE NULL (no next_match)\n");
02869 #endif
02870          return NULL;  /* according to the code, complete matches are null matches in MATCHMORE mode */
02871       }
02872 
02873       if (eroot) {
02874          /* found entry, now look for the right priority */
02875          if (q->status < STATUS_NO_PRIORITY)
02876             q->status = STATUS_NO_PRIORITY;
02877          e = NULL;
02878          if (action == E_FINDLABEL && label ) {
02879             if (q->status < STATUS_NO_LABEL)
02880                q->status = STATUS_NO_LABEL;
02881             e = ast_hashtab_lookup(eroot->peer_label_table, &pattern);
02882          } else {
02883             e = ast_hashtab_lookup(eroot->peer_table, &pattern);
02884          }
02885          if (e) { /* found a valid match */
02886             q->status = STATUS_SUCCESS;
02887             q->foundcontext = context;
02888 #ifdef NEED_DEBUG_HERE
02889             ast_log(LOG_NOTICE,"Returning complete match of exten %s\n", e->exten);
02890 #endif
02891             return e;
02892          }
02893       }
02894    } else {   /* the old/current default exten pattern match algorithm */
02895 
02896       /* scan the list trying to match extension and CID */
02897       eroot = NULL;
02898       while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) {
02899          int match = extension_match_core(eroot->exten, exten, action);
02900          /* 0 on fail, 1 on match, 2 on earlymatch */
02901 
02902          if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid)))
02903             continue;   /* keep trying */
02904          if (match == 2 && action == E_MATCHMORE) {
02905             /* We match an extension ending in '!'.
02906              * The decision in this case is final and is NULL (no match).
02907              */
02908             return NULL;
02909          }
02910          /* found entry, now look for the right priority */
02911          if (q->status < STATUS_NO_PRIORITY)
02912             q->status = STATUS_NO_PRIORITY;
02913          e = NULL;
02914          if (action == E_FINDLABEL && label ) {
02915             if (q->status < STATUS_NO_LABEL)
02916                q->status = STATUS_NO_LABEL;
02917             e = ast_hashtab_lookup(eroot->peer_label_table, &pattern);
02918          } else {
02919             e = ast_hashtab_lookup(eroot->peer_table, &pattern);
02920          }
02921          if (e) { /* found a valid match */
02922             q->status = STATUS_SUCCESS;
02923             q->foundcontext = context;
02924             return e;
02925          }
02926       }
02927    }
02928 
02929    /* Check alternative switches */
02930    AST_LIST_TRAVERSE(&tmp->alts, sw, list) {
02931       struct ast_switch *asw = pbx_findswitch(sw->name);
02932       ast_switch_f *aswf = NULL;
02933       char *datap;
02934 
02935       if (!asw) {
02936          ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name);
02937          continue;
02938       }
02939 
02940       /* Substitute variables now */
02941       if (sw->eval) {
02942          if (!(tmpdata = ast_str_thread_get(&switch_data, 512))) {
02943             ast_log(LOG_WARNING, "Can't evaluate switch?!");
02944             continue;
02945          }
02946          pbx_substitute_variables_helper(chan, sw->data, ast_str_buffer(tmpdata), ast_str_size(tmpdata));
02947       }
02948 
02949       /* equivalent of extension_match_core() at the switch level */
02950       if (action == E_CANMATCH)
02951          aswf = asw->canmatch;
02952       else if (action == E_MATCHMORE)
02953          aswf = asw->matchmore;
02954       else /* action == E_MATCH */
02955          aswf = asw->exists;
02956       datap = sw->eval ? ast_str_buffer(tmpdata) : sw->data;
02957       if (!aswf)
02958          res = 0;
02959       else {
02960          if (chan)
02961             ast_autoservice_start(chan);
02962          res = aswf(chan, context, exten, priority, callerid, datap);
02963          if (chan)
02964             ast_autoservice_stop(chan);
02965       }
02966       if (res) {  /* Got a match */
02967          q->swo = asw;
02968          q->data = datap;
02969          q->foundcontext = context;
02970          /* XXX keep status = STATUS_NO_CONTEXT ? */
02971          return NULL;
02972       }
02973    }
02974    q->incstack[q->stacklen++] = tmp->name;   /* Setup the stack */
02975    /* Now try any includes we have in this context */
02976    for (i = tmp->includes; i; i = i->next) {
02977       if (include_valid(i)) {
02978          if ((e = pbx_find_extension(chan, bypass, q, i->rname, exten, priority, label, callerid, action))) {
02979 #ifdef NEED_DEBUG_HERE
02980             ast_log(LOG_NOTICE,"Returning recursive match of %s\n", e->exten);
02981 #endif
02982             return e;
02983          }
02984          if (q->swo)
02985             return NULL;
02986       }
02987    }
02988    return NULL;
02989 }

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

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

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

01447 {
01448    struct ast_app *tmp;
01449 
01450    AST_RWLIST_RDLOCK(&apps);
01451    AST_RWLIST_TRAVERSE(&apps, tmp, list) {
01452       if (!strcasecmp(tmp->name, app))
01453          break;
01454    }
01455    AST_RWLIST_UNLOCK(&apps);
01456 
01457    return tmp;
01458 }

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

03120 {
03121    struct ast_str *str = ast_str_create(16);
03122    const char *cret;
03123 
03124    cret = ast_str_retrieve_variable(&str, 0, c, headp, var);
03125    ast_copy_string(workspace, ast_str_buffer(str), workspacelen);
03126    *ret = cret ? workspace : NULL;
03127    ast_free(str);
03128 }

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

References autofallthrough.

Referenced by pbx_load_module().

05398 {
05399    int oldval = autofallthrough;
05400    autofallthrough = newval;
05401    return oldval;
05402 }

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

References extenpatternmatchnew.

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

05405 {
05406    int oldval = extenpatternmatchnew;
05407    extenpatternmatchnew = newval;
05408    return oldval;
05409 }

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

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

Referenced by pbx_load_module().

05412 {
05413    if (overrideswitch) {
05414       ast_free(overrideswitch);
05415    }
05416    if (!ast_strlen_zero(newval)) {
05417       overrideswitch = ast_strdup(newval);
05418    } else {
05419       overrideswitch = NULL;
05420    }
05421 }

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

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

04137 {
04138    size_t used;
04139    pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count, &used);
04140 }

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

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

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

03941 {
03942    /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!!  */
03943    char *cp4 = NULL;
03944    const char *tmp, *whereweare, *orig_cp2 = cp2;
03945    int length, offset, offset2, isfunction;
03946    char *workspace = NULL;
03947    char *ltmp = NULL, *var = NULL;
03948    char *nextvar, *nextexp, *nextthing;
03949    char *vars, *vare;
03950    int pos, brackets, needsub, len;
03951 
03952    *cp2 = 0; /* just in case nothing ends up there */
03953    whereweare=tmp=cp1;
03954    while (!ast_strlen_zero(whereweare) && count) {
03955       /* Assume we're copying the whole remaining string */
03956       pos = strlen(whereweare);
03957       nextvar = NULL;
03958       nextexp = NULL;
03959       nextthing = strchr(whereweare, '$');
03960       if (nextthing) {
03961          switch (nextthing[1]) {
03962          case '{':
03963             nextvar = nextthing;
03964             pos = nextvar - whereweare;
03965             break;
03966          case '[':
03967             nextexp = nextthing;
03968             pos = nextexp - whereweare;
03969             break;
03970          default:
03971             pos = 1;
03972          }
03973       }
03974 
03975       if (pos) {
03976          /* Can't copy more than 'count' bytes */
03977          if (pos > count)
03978             pos = count;
03979 
03980          /* Copy that many bytes */
03981          memcpy(cp2, whereweare, pos);
03982 
03983          count -= pos;
03984          cp2 += pos;
03985          whereweare += pos;
03986          *cp2 = 0;
03987       }
03988 
03989       if (nextvar) {
03990          /* We have a variable.  Find the start and end, and determine
03991             if we are going to have to recursively call ourselves on the
03992             contents */
03993          vars = vare = nextvar + 2;
03994          brackets = 1;
03995          needsub = 0;
03996 
03997          /* Find the end of it */
03998          while (brackets && *vare) {
03999             if ((vare[0] == '$') && (vare[1] == '{')) {
04000                needsub++;
04001             } else if (vare[0] == '{') {
04002                brackets++;
04003             } else if (vare[0] == '}') {
04004                brackets--;
04005             } else if ((vare[0] == '$') && (vare[1] == '['))
04006                needsub++;
04007             vare++;
04008          }
04009          if (brackets)
04010             ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n");
04011          len = vare - vars - 1;
04012 
04013          /* Skip totally over variable string */
04014          whereweare += (len + 3);
04015 
04016          if (!var)
04017             var = alloca(VAR_BUF_SIZE);
04018 
04019          /* Store variable name (and truncate) */
04020          ast_copy_string(var, vars, len + 1);
04021 
04022          /* Substitute if necessary */
04023          if (needsub) {
04024             size_t used;
04025             if (!ltmp)
04026                ltmp = alloca(VAR_BUF_SIZE);
04027 
04028             pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used);
04029             vars = ltmp;
04030          } else {
04031             vars = var;
04032          }
04033 
04034          if (!workspace)
04035             workspace = alloca(VAR_BUF_SIZE);
04036 
04037          workspace[0] = '\0';
04038 
04039          parse_variable_name(vars, &offset, &offset2, &isfunction);
04040          if (isfunction) {
04041             /* Evaluate function */
04042             if (c || !headp)
04043                cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
04044             else {
04045                struct varshead old;
04046                struct ast_channel *c = ast_dummy_channel_alloc();
04047                if (c) {
04048                   memcpy(&old, &c->varshead, sizeof(old));
04049                   memcpy(&c->varshead, headp, sizeof(c->varshead));
04050                   cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
04051                   /* Don't deallocate the varshead that was passed in */
04052                   memcpy(&c->varshead, &old, sizeof(c->varshead));
04053                   c = ast_channel_unref(c);
04054                } else {
04055                   ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution.  Function results may be blank.\n");
04056                }
04057             }
04058             ast_debug(2, "Function result is '%s'\n", cp4 ? cp4 : "(null)");
04059          } else {
04060             /* Retrieve variable value */
04061             pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp);
04062          }
04063          if (cp4) {
04064             cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE);
04065 
04066             length = strlen(cp4);
04067             if (length > count)
04068                length = count;
04069             memcpy(cp2, cp4, length);
04070             count -= length;
04071             cp2 += length;
04072             *cp2 = 0;
04073          }
04074       } else if (nextexp) {
04075          /* We have an expression.  Find the start and end, and determine
04076             if we are going to have to recursively call ourselves on the
04077             contents */
04078          vars = vare = nextexp + 2;
04079          brackets = 1;
04080          needsub = 0;
04081 
04082          /* Find the end of it */
04083          while (brackets && *vare) {
04084             if ((vare[0] == '$') && (vare[1] == '[')) {
04085                needsub++;
04086                brackets++;
04087                vare++;
04088             } else if (vare[0] == '[') {
04089                brackets++;
04090             } else if (vare[0] == ']') {
04091                brackets--;
04092             } else if ((vare[0] == '$') && (vare[1] == '{')) {
04093                needsub++;
04094                vare++;
04095             }
04096             vare++;
04097          }
04098          if (brackets)
04099             ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n");
04100          len = vare - vars - 1;
04101 
04102          /* Skip totally over expression */
04103          whereweare += (len + 3);
04104 
04105          if (!var)
04106             var = alloca(VAR_BUF_SIZE);
04107 
04108          /* Store variable name (and truncate) */
04109          ast_copy_string(var, vars, len + 1);
04110 
04111          /* Substitute if necessary */
04112          if (needsub) {
04113             size_t used;
04114             if (!ltmp)
04115                ltmp = alloca(VAR_BUF_SIZE);
04116 
04117             pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used);
04118             vars = ltmp;
04119          } else {
04120             vars = var;
04121          }
04122 
04123          length = ast_expr(vars, cp2, count, c);
04124 
04125          if (length) {
04126             ast_debug(1, "Expression result is '%s'\n", cp2);
04127             count -= length;
04128             cp2 += length;
04129             *cp2 = 0;
04130          }
04131       }
04132    }
04133    *used = cp2 - orig_cp2;
04134 }

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

Definition at line 4142 of file pbx.c.

References pbx_substitute_variables_helper_full().

Referenced by dundi_lookup_local(), and loopback_subst().

04143 {
04144    size_t used;
04145    pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count, &used);
04146 }


Generated on Sat Mar 10 01:55:35 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7