Fri Nov 12 12:06:17 2010

Asterisk developer's documentation


pbx.h File Reference

Core PBX routines and definitions. More...

#include "asterisk/sched.h"
#include "asterisk/devicestate.h"
#include "asterisk/chanvars.h"
#include "asterisk/hashtab.h"
#include "asterisk/stringfields.h"
Include dependency graph for pbx.h:

Go to the source code of this file.

Data Structures

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

Defines

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

#define AST_PBX_ERROR   1
#define AST_PBX_HANGUP   -1
 Special return values from applications to the PBX.
#define AST_PBX_INCOMPLETE   12
#define AST_PBX_OK   0

Typedefs

typedef int(* ast_state_cb_type )(char *context, char *id, enum ast_extension_states state, void *data)
 Typedef for devicestate and hint callbacks.
typedef int( ast_switch_f )(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
 All switch functions have the same interface, so define a type for them.

Enumerations

enum  ast_doc_src { AST_XML_DOC, AST_STATIC_DOC }
 

From where the documentation come from.

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

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

Functions

int __ast_custom_function_register (struct ast_custom_function *acf, struct ast_module *mod)
 Register a custom function.
int ast_active_calls (void)
 Retrieve the number of active calls.
int ast_add_extension (const char *context, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar)
 Add and extension to an extension context.
int ast_add_extension2 (struct ast_context *con, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar)
 Add an extension to an extension context, this time with an ast_context *.
int ast_async_goto (struct ast_channel *chan, const char *context, const char *exten, int priority)
 Set the channel to next execute the specified dialplan location.
int ast_async_goto_by_name (const char *chan, const char *context, const char *exten, int priority)
 Set the channel to next execute the specified dialplan location.
int ast_async_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority)
int ast_async_parseable_goto (struct ast_channel *chan, const char *goto_string)
int ast_build_timing (struct ast_timing *i, const char *info)
 Construct a timing bitmap, for use in time-based conditionals.
int ast_canmatch_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
 Looks for a valid matching extension.
int ast_check_timing (const struct ast_timing *i)
 Evaluate a pre-constructed bitmap as to whether the current time falls within the range specified.
int ast_context_add_ignorepat (const char *context, const char *ignorepat, const char *registrar)
 Add an ignorepat.
int ast_context_add_ignorepat2 (struct ast_context *con, const char *ignorepat, const char *registrar)
int ast_context_add_include (const char *context, const char *include, const char *registrar)
 Add a context include.
int ast_context_add_include2 (struct ast_context *con, const char *include, const char *registrar)
 Add a context include.
int ast_context_add_switch (const char *context, const char *sw, const char *data, int eval, const char *registrar)
 Add a switch.
int ast_context_add_switch2 (struct ast_context *con, const char *sw, const char *data, int eval, const char *registrar)
 Adds a switch (first param is a ast_context).
void ast_context_destroy (struct ast_context *con, const char *registrar)
 Destroy a context (matches the specified context (or ANY context if NULL).
struct ast_contextast_context_find (const char *name)
 Find a context.
struct ast_contextast_context_find_or_create (struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *name, const char *registrar)
 Register a new context or find an existing one.
int ast_context_lockmacro (const char *macrocontext)
 locks the macrolock in the given given context
int ast_context_remove_ignorepat (const char *context, const char *ignorepat, const char *registrar)
int ast_context_remove_ignorepat2 (struct ast_context *con, const char *ignorepat, const char *registrar)
int ast_context_remove_include (const char *context, const char *include, const char *registrar)
 Remove a context include.
int ast_context_remove_include2 (struct ast_context *con, const char *include, const char *registrar)
 Removes an include by an ast_context structure.
int ast_context_remove_switch (const char *context, const char *sw, const char *data, const char *registrar)
 Remove a switch.
int ast_context_remove_switch2 (struct ast_context *con, const char *sw, const char *data, const char *registrar)
 This function locks given context, removes switch, unlock context and return.
int ast_context_unlockmacro (const char *macrocontext)
 Unlocks the macrolock in the given context.
int ast_context_verify_includes (struct ast_context *con)
 Verifies includes in an ast_contect structure.
struct ast_custom_functionast_custom_function_find (const char *name)
int ast_custom_function_unregister (struct ast_custom_function *acf)
 Unregister a custom function.
int ast_destroy_timing (struct ast_timing *i)
 Deallocates memory structures associated with a timing bitmap.
enum ast_extension_states ast_devstate_to_extenstate (enum ast_device_state devstate)
 Map devstate to an extension state.
int ast_exists_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
 Determine whether an extension exists.
int ast_explicit_goto (struct ast_channel *chan, const char *context, const char *exten, int priority)
int ast_extension_close (const char *pattern, const char *data, int needmore)
int ast_extension_cmp (const char *a, const char *b)
 Determine if one extension should match before another.
int ast_extension_match (const char *pattern, const char *extension)
 Determine if a given extension matches a given pattern (in NXX format).
int ast_extension_patmatch (const char *pattern, const char *data)
int ast_extension_state (struct ast_channel *c, const char *context, const char *exten)
 Uses hint and devicestate callback to get the state of an extension.
const char * ast_extension_state2str (int extension_state)
 Return string representation of the state of an extension.
int ast_extension_state_add (const char *context, const char *exten, ast_state_cb_type callback, void *data)
 Registers a state change callback.
int ast_extension_state_del (int id, ast_state_cb_type callback)
 Deletes a registered state change callback by ID.
int ast_findlabel_extension (struct ast_channel *c, const char *context, const char *exten, const char *label, const char *callerid)
 Find the priority of an extension that has the specified label.
int ast_findlabel_extension2 (struct ast_channel *c, struct ast_context *con, const char *exten, const char *label, const char *callerid)
 Find the priority of an extension that has the specified label.
int ast_func_read (struct ast_channel *chan, const char *function, char *workspace, size_t len)
 executes a read operation on a function
int ast_func_write (struct ast_channel *chan, const char *function, const char *value)
 executes a write operation on a function
int ast_get_hint (char *hint, int hintsize, char *name, int namesize, struct ast_channel *c, const char *context, const char *exten)
 If an extension hint exists, return non-zero.
int ast_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority)
int ast_ignore_pattern (const char *context, const char *pattern)
 Checks to see if a number should be ignored.
int ast_matchmore_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
 Looks to see if adding anything to this extension might match something. (exists ^ canmatch).
void ast_merge_contexts_and_delete (struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *registrar)
 Merge the temporary contexts into a global contexts list and delete from the global list the ones that are being added.
int ast_parseable_goto (struct ast_channel *chan, const char *goto_string)
int ast_pbx_outgoing_app (const char *type, int format, void *data, int timeout, const char *app, const char *appdata, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel)
int ast_pbx_outgoing_exten (const char *type, int format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel)
enum ast_pbx_result ast_pbx_run (struct ast_channel *c)
 Execute the PBX in the current thread.
enum ast_pbx_result ast_pbx_run_args (struct ast_channel *c, struct ast_pbx_args *args)
 Execute the PBX in the current thread.
enum ast_pbx_result ast_pbx_start (struct ast_channel *c)
 Create a new thread and start the PBX.
int ast_processed_calls (void)
 Retrieve the total number of calls processed through the PBX since last restart.
int ast_rdlock_context (struct ast_context *con)
 Read locks a given context.
int ast_rdlock_contexts (void)
 Read locks the context list.
int ast_register_switch (struct ast_switch *sw)
 Register an alternative dialplan switch.
int ast_spawn_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid, int *found, int combined_find_spawn)
 Launch a new extension (i.e. new stack).
int ast_unlock_context (struct ast_context *con)
int ast_unlock_contexts (void)
 Unlocks contexts.
void ast_unregister_switch (struct ast_switch *sw)
 Unregister an alternative switch.
int ast_wrlock_context (struct ast_context *con)
 Write locks a given context.
int ast_wrlock_contexts (void)
 Write locks the context list.
int ast_wrlock_contexts_version (void)
void pbx_builtin_clear_globals (void)
const char * pbx_builtin_getvar_helper (struct ast_channel *chan, const char *name)
 Return a pointer to the value of the corresponding channel variable.
void pbx_builtin_pushvar_helper (struct ast_channel *chan, const char *name, const char *value)
 Add a variable to the channel variable stack, without removing any previously set value.
int pbx_builtin_raise_exception (struct ast_channel *chan, void *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, void *data)
 Parse and set a single channel variable, where the name and value are separated with an '=' character.
void pbx_builtin_setvar_helper (struct ast_channel *chan, const char *name, const char *value)
 Add a variable to the channel variable stack, removing the most recently set value for the same name.
int pbx_builtin_setvar_multiple (struct ast_channel *chan, void *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, void *data)
 Execute an application.
struct ast_extenpbx_find_extension (struct ast_channel *chan, struct ast_context *bypass, struct pbx_find_info *q, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action)
struct ast_apppbx_findapp (const char *app)
 Look up an application.
void pbx_retrieve_variable (struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp)
 Retrieve the value of a builtin variable or variable from the channel variable stack.
int pbx_set_autofallthrough (int newval)
int pbx_set_extenpatternmatchnew (int newval)
void pbx_set_overrideswitch (const char *newval)

int ast_context_remove_extension (const char *context, const char *extension, int priority, const char *registrar)
 Simply remove extension from context.
int ast_context_remove_extension2 (struct ast_context *con, const char *extension, int priority, const char *registrar, int already_locked)
 This functionc locks given context, search for the right extension and fires out all peer in this extensions with given priority. If priority is set to 0, all peers are removed. After that, unlock context and return.
int ast_context_remove_extension_callerid (const char *context, const char *extension, int priority, const char *callerid, int matchcid, const char *registrar)
int ast_context_remove_extension_callerid2 (struct ast_context *con, const char *extension, int priority, const char *callerid, int matchcid, const char *registrar, int already_locked)

Functions for returning values from structures

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

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

const char * ast_get_extension_app (struct ast_exten *e)
void * ast_get_extension_app_data (struct ast_exten *e)
const char * ast_get_extension_cidmatch (struct ast_exten *e)
const char * ast_get_extension_label (struct ast_exten *e)
int ast_get_extension_matchcid (struct ast_exten *e)
int ast_get_extension_priority (struct ast_exten *exten)

int ast_hashtab_compare_contexts (const void *ah_a, const void *ah_b)
 hashtable functions for contexts
unsigned int ast_hashtab_hash_contexts (const void *obj)
Substitution routines, using static string buffers

void ast_str_substitute_variables (struct ast_str **buf, size_t maxlen, struct ast_channel *chan, const char *templ)
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)
Walking functions ...

struct ast_extenast_walk_context_extensions (struct ast_context *con, struct ast_exten *priority)
struct ast_ignorepatast_walk_context_ignorepats (struct ast_context *con, struct ast_ignorepat *ip)
struct ast_includeast_walk_context_includes (struct ast_context *con, struct ast_include *inc)
struct ast_swast_walk_context_switches (struct ast_context *con, struct ast_sw *sw)
struct ast_contextast_walk_contexts (struct ast_context *con)
struct ast_extenast_walk_extension_priorities (struct ast_exten *exten, struct ast_exten *priority)

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

Referenced by load_module(), and reload().

#define AST_MAX_APP   32

Max length of an application

Definition at line 36 of file pbx.h.

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

#define AST_PBX_ERROR   1

Jump to the 'e' exten

Definition at line 45 of file pbx.h.

Referenced by __ast_pbx_run().

#define AST_PBX_HANGUP   -1

Special return values from applications to the PBX.

Jump to the 'h' exten

Definition at line 43 of file pbx.h.

#define AST_PBX_INCOMPLETE   12

Return to PBX matching, allowing more digits for the extension

Definition at line 46 of file pbx.h.

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

#define AST_PBX_KEEP   0

Definition at line 38 of file pbx.h.

#define AST_PBX_MAX_STACK   128

Definition at line 1095 of file pbx.h.

#define AST_PBX_OK   0

No errors

Definition at line 44 of file pbx.h.

#define AST_PBX_REPLACE   1

Definition at line 39 of file pbx.h.

#define PRIORITY_HINT   -1
#define STATUS_NO_CONTEXT   1

Definition at line 1090 of file pbx.h.

#define STATUS_NO_EXTENSION   2

Definition at line 1091 of file pbx.h.

#define STATUS_NO_LABEL   4

Definition at line 1093 of file pbx.h.

#define STATUS_NO_PRIORITY   3

Definition at line 1092 of file pbx.h.

#define STATUS_SUCCESS   5

Definition at line 1094 of file pbx.h.


Typedef Documentation

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

Typedef for devicestate and hint callbacks.

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


Enumeration Type Documentation

From where the documentation come from.

Enumerator:
AST_XML_DOC 

From XML documentation

AST_STATIC_DOC 

From application/function registration

Definition at line 77 of file pbx.h.

00077                  {
00078    AST_XML_DOC,            /*!< From XML documentation */
00079    AST_STATIC_DOC          /*!< From application/function registration */
00080 };

Extension states.

Note:
States can be combined
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 55 of file pbx.h.

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

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

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

Definition at line 262 of file pbx.h.

00262                     {
00263    AST_PBX_SUCCESS = 0,
00264    AST_PBX_FAILED = -1,
00265    AST_PBX_CALL_LIMIT = -2,
00266 };

When looking up extensions, we can have different requests identified by the 'action' argument, as follows. Note that the coding is such that the low 4 bits are the third argument to extension_match_core.

Enumerator:
E_MATCHMORE 
E_CANMATCH 
E_MATCH 
E_MATCH_MASK 
E_SPAWN 
E_FINDLABEL 
E_MATCHMORE 
E_CANMATCH 
E_MATCH 
E_MATCH_MASK 
E_SPAWN 
E_FINDLABEL 

Definition at line 1081 of file pbx.h.

01081                  {
01082    E_MATCHMORE =  0x00, /* extension can match but only with more 'digits' */
01083    E_CANMATCH =   0x01, /* extension can match with or without more 'digits' */
01084    E_MATCH =   0x02, /* extension is an exact match */
01085    E_MATCH_MASK = 0x03, /* mask for the argument to extension_match_core() */
01086    E_SPAWN =   0x12, /* want to spawn an extension. Requires exact match */
01087    E_FINDLABEL =  0x22  /* returns the priority for a given label. Requires exact match */
01088 };


Function Documentation

int __ast_custom_function_register ( struct ast_custom_function acf,
struct ast_module mod 
)

Register a custom function.

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

03290 {
03291    struct ast_custom_function *cur;
03292    char tmps[80];
03293 
03294    if (!acf) {
03295       return -1;
03296    }
03297 
03298    acf->mod = mod;
03299    acf->docsrc = AST_STATIC_DOC;
03300 
03301    if (acf_retrieve_docs(acf)) {
03302       return -1;
03303    }
03304 
03305    AST_RWLIST_WRLOCK(&acf_root);
03306 
03307    AST_RWLIST_TRAVERSE(&acf_root, cur, acflist) {
03308       if (!strcmp(acf->name, cur->name)) {
03309          ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name);
03310          AST_RWLIST_UNLOCK(&acf_root);
03311          return -1;
03312       }
03313    }
03314 
03315    /* Store in alphabetical order */
03316    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) {
03317       if (strcasecmp(acf->name, cur->name) < 0) {
03318          AST_RWLIST_INSERT_BEFORE_CURRENT(acf, acflist);
03319          break;
03320       }
03321    }
03322    AST_RWLIST_TRAVERSE_SAFE_END;
03323 
03324    if (!cur) {
03325       AST_RWLIST_INSERT_TAIL(&acf_root, acf, acflist);
03326    }
03327 
03328    AST_RWLIST_UNLOCK(&acf_root);
03329 
03330    ast_verb(2, "Registered custom function '%s'\n", term_color(tmps, acf->name, COLOR_BRCYAN, 0, sizeof(tmps)));
03331 
03332    return 0;
03333 }

int ast_active_calls ( void   ) 

Retrieve the number of active calls.

Definition at line 4601 of file pbx.c.

References countcalls.

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

04602 {
04603    return countcalls;
04604 }

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

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

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

07308 {
07309    int ret = -1;
07310    struct ast_context *c = find_context_locked(context);
07311 
07312    if (c) {
07313       ret = ast_add_extension2(c, replace, extension, priority, label, callerid,
07314          application, data, datad, registrar);
07315       ast_unlock_contexts();
07316    }
07317 
07318    return ret;
07319 }

int ast_add_extension2 ( struct ast_context con,
int  replace,
const char *  extension,
int  priority,
const char *  label,
const char *  callerid,
const char *  application,
void *  data,
void(*)(void *)  datad,
const char *  registrar 
)

Add an extension to an extension context, this time with an ast_context *.

Note:
For details about the arguments, check ast_add_extension()

Add an extension to an extension context, this time with an ast_context *.

We sort extensions in order of matching preference, so that we can stop the search as soon as we find a suitable match. This ordering also takes care of wildcards such as '.' (meaning "one or more of any character") and '!' (which is 'earlymatch', meaning "zero or more of any character" but also impacts the return value from CANMATCH and EARLYMATCH.

The extension match rules defined in the devmeeting 2006.05.05 are quite simple: WE SELECT THE LONGEST MATCH. In detail, "longest" means the number of matched characters in the extension. In case of ties (e.g. _XXX and 333) in the length of a pattern, we give priority to entries with the smallest cardinality (e.g, [5-9] comes before [2-8] before the former has only 5 elements, while the latter has 7, etc. In case of same cardinality, the first element in the range counts. If we still have a tie, any final '!' will make this as a possibly less specific pattern.

EBUSY - can't lock EEXIST - extension with the same priority exist and no replace is set

Definition at line 7624 of file pbx.c.

References ast_add_extension2_lockopt().

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

07628 {
07629    return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid, application, data, datad, registrar, 1, 1);
07630 }

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

Set the channel to next execute the specified dialplan location.

See also:
ast_async_parseable_goto, ast_async_goto_if_exists

Definition at line 7344 of file pbx.c.

References ast_channel::_state, ast_channel::accountcode, ast_channel::amaflags, ast_cdr_discard(), ast_cdr_dup(), ast_channel_alloc, ast_channel_lock, ast_channel_masquerade(), ast_channel_unlock, ast_do_masquerade(), ast_explicit_goto(), ast_hangup(), ast_log(), ast_pbx_start(), AST_SOFTHANGUP_ASYNCGOTO, ast_softhangup_nolock(), ast_channel::cdr, ast_channel::context, ast_channel::exten, 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_dtmfup(), handle_request_bye(), handle_request_refer(), pbx_parseable_goto(), process_ast_dsp(), sip_read(), and socket_process().

07345 {
07346    int res = 0;
07347 
07348    ast_channel_lock(chan);
07349 
07350    if (chan->pbx) { /* This channel is currently in the PBX */
07351       ast_explicit_goto(chan, context, exten, priority + 1);
07352       ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO);
07353    } else {
07354       /* In order to do it when the channel doesn't really exist within
07355          the PBX, we have to make a new channel, masquerade, and start the PBX
07356          at the new location */
07357       struct ast_channel *tmpchan = ast_channel_alloc(0, chan->_state, 0, 0, chan->accountcode, chan->exten, chan->context, chan->amaflags, "AsyncGoto/%s", chan->name);
07358       if (!tmpchan) {
07359          res = -1;
07360       } else {
07361          if (chan->cdr) {
07362             ast_cdr_discard(tmpchan->cdr);
07363             tmpchan->cdr = ast_cdr_dup(chan->cdr);  /* share the love */
07364          }
07365          /* Make formats okay */
07366          tmpchan->readformat = chan->readformat;
07367          tmpchan->writeformat = chan->writeformat;
07368          /* Setup proper location */
07369          ast_explicit_goto(tmpchan,
07370             S_OR(context, chan->context), S_OR(exten, chan->exten), priority);
07371 
07372          /* Masquerade into temp channel */
07373          if (ast_channel_masquerade(tmpchan, chan)) {
07374             /* Failed to set up the masquerade.  It's probably chan_local
07375              * in the middle of optimizing itself out.  Sad. :( */
07376             ast_hangup(tmpchan);
07377             tmpchan = NULL;
07378             res = -1;
07379          } else {
07380             /* Grab the locks and get going */
07381             ast_channel_lock(tmpchan);
07382             ast_do_masquerade(tmpchan);
07383             ast_channel_unlock(tmpchan);
07384             /* Start the PBX going on our stolen channel */
07385             if (ast_pbx_start(tmpchan)) {
07386                ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name);
07387                ast_hangup(tmpchan);
07388                res = -1;
07389             }
07390          }
07391       }
07392    }
07393    ast_channel_unlock(chan);
07394    return res;
07395 }

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

References ast_async_goto(), ast_channel_unlock, and ast_get_channel_by_name_locked().

07398 {
07399    struct ast_channel *chan;
07400    int res = -1;
07401 
07402    chan = ast_get_channel_by_name_locked(channame);
07403    if (chan) {
07404       res = ast_async_goto(chan, context, exten, priority);
07405       ast_channel_unlock(chan);
07406    }
07407    return res;
07408 }

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

References __ast_goto_if_exists().

09576 {
09577    return __ast_goto_if_exists(chan, context, exten, priority, 1);
09578 }

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

References pbx_parseable_goto().

Referenced by asyncgoto_exec(), and handle_redirect().

09639 {
09640    return pbx_parseable_goto(chan, goto_string, 1);
09641 }

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

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

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

06940 {
06941    char *info_save, *info;
06942    int j, num_fields, last_sep = -1;
06943 
06944    /* Check for empty just in case */
06945    if (ast_strlen_zero(info_in)) {
06946       return 0;
06947    }
06948 
06949    /* make a copy just in case we were passed a static string */
06950    info_save = info = ast_strdupa(info_in);
06951 
06952    /* count the number of fields in the timespec */
06953    for (j = 0, num_fields = 1; info[j] != '\0'; j++) {
06954       if (info[j] == ',') {
06955          last_sep = j;
06956          num_fields++;
06957       }
06958    }
06959 
06960    /* save the timezone, if it is specified */
06961    if (num_fields == 5) {
06962       i->timezone = ast_strdup(info + last_sep + 1);
06963    } else {
06964       i->timezone = NULL;
06965    }
06966 
06967    /* Assume everything except time */
06968    i->monthmask = 0xfff;   /* 12 bits */
06969    i->daymask = 0x7fffffffU; /* 31 bits */
06970    i->dowmask = 0x7f; /* 7 bits */
06971    /* on each call, use strsep() to move info to the next argument */
06972    get_timerange(i, strsep(&info, "|,"));
06973    if (info)
06974       i->dowmask = get_range(strsep(&info, "|,"), 7, days, "day of week");
06975    if (info)
06976       i->daymask = get_range(strsep(&info, "|,"), 31, NULL, "day");
06977    if (info)
06978       i->monthmask = get_range(strsep(&info, "|,"), 12, months, "month");
06979    return 1;
06980 }

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

References E_CANMATCH, and pbx_extension_helper().

Referenced by 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(), pri_dchannel(), skinny_ss(), ss_thread(), and valid_exit().

04159 {
04160    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0);
04161 }

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

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

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

06983 {
06984    struct ast_tm tm;
06985    struct timeval now = ast_tvnow();
06986 
06987    ast_localtime(&now, &tm, i->timezone);
06988 
06989    /* If it's not the right month, return */
06990    if (!(i->monthmask & (1 << tm.tm_mon)))
06991       return 0;
06992 
06993    /* If it's not that time of the month.... */
06994    /* Warning, tm_mday has range 1..31! */
06995    if (!(i->daymask & (1 << (tm.tm_mday-1))))
06996       return 0;
06997 
06998    /* If it's not the right day of the week */
06999    if (!(i->dowmask & (1 << tm.tm_wday)))
07000       return 0;
07001 
07002    /* Sanity check the hour just to be safe */
07003    if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) {
07004       ast_log(LOG_WARNING, "Insane time...\n");
07005       return 0;
07006    }
07007 
07008    /* Now the tough part, we calculate if it fits
07009       in the right time based on min/hour */
07010    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))))
07011       return 0;
07012 
07013    /* If we got this far, then we're good */
07014    return 1;
07015 }

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

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

Referenced by handle_cli_dialplan_add_ignorepat().

07218 {
07219    int ret = -1;
07220    struct ast_context *c = find_context_locked(context);
07221 
07222    if (c) {
07223       ret = ast_context_add_ignorepat2(c, value, registrar);
07224       ast_unlock_contexts();
07225    }
07226    return ret;
07227 }

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

Definition at line 7229 of file pbx.c.

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

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

07230 {
07231    struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL;
07232    int length;
07233    char *pattern;
07234    length = sizeof(struct ast_ignorepat);
07235    length += strlen(value) + 1;
07236    if (!(ignorepat = ast_calloc(1, length)))
07237       return -1;
07238    /* The cast to char * is because we need to write the initial value.
07239     * The field is not supposed to be modified otherwise.  Also, gcc 4.2
07240     * sees the cast as dereferencing a type-punned pointer and warns about
07241     * it.  This is the workaround (we're telling gcc, yes, that's really
07242     * what we wanted to do).
07243     */
07244    pattern = (char *) ignorepat->pattern;
07245    strcpy(pattern, value);
07246    ignorepat->next = NULL;
07247    ignorepat->registrar = registrar;
07248    ast_wrlock_context(con);
07249    for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) {
07250       ignorepatl = ignorepatc;
07251       if (!strcasecmp(ignorepatc->pattern, value)) {
07252          /* Already there */
07253          ast_unlock_context(con);
07254          errno = EEXIST;
07255          return -1;
07256       }
07257    }
07258    if (ignorepatl)
07259       ignorepatl->next = ignorepat;
07260    else
07261       con->ignorepats = ignorepat;
07262    ast_unlock_context(con);
07263    return 0;
07264 
07265 }

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

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

Referenced by handle_cli_dialplan_add_include().

06769 {
06770    int ret = -1;
06771    struct ast_context *c = find_context_locked(context);
06772 
06773    if (c) {
06774       ret = ast_context_add_include2(c, include, registrar);
06775       ast_unlock_contexts();
06776    }
06777    return ret;
06778 }

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

References ast_build_timing(), ast_calloc, ast_destroy_timing(), ast_free, ast_get_context_name(), ast_unlock_context(), ast_verb, ast_wrlock_context(), errno, ast_include::hastime, ast_context::includes, ast_include::name, ast_include::next, ast_include::registrar, ast_include::rname, ast_include::stuff, and ast_include::timing.

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

07034 {
07035    struct ast_include *new_include;
07036    char *c;
07037    struct ast_include *i, *il = NULL; /* include, include_last */
07038    int length;
07039    char *p;
07040 
07041    length = sizeof(struct ast_include);
07042    length += 2 * (strlen(value) + 1);
07043 
07044    /* allocate new include structure ... */
07045    if (!(new_include = ast_calloc(1, length)))
07046       return -1;
07047    /* Fill in this structure. Use 'p' for assignments, as the fields
07048     * in the structure are 'const char *'
07049     */
07050    p = new_include->stuff;
07051    new_include->name = p;
07052    strcpy(p, value);
07053    p += strlen(value) + 1;
07054    new_include->rname = p;
07055    strcpy(p, value);
07056    /* Strip off timing info, and process if it is there */
07057    if ( (c = strchr(p, ',')) ) {
07058       *c++ = '\0';
07059       new_include->hastime = ast_build_timing(&(new_include->timing), c);
07060    }
07061    new_include->next      = NULL;
07062    new_include->registrar = registrar;
07063 
07064    ast_wrlock_context(con);
07065 
07066    /* ... go to last include and check if context is already included too... */
07067    for (i = con->includes; i; i = i->next) {
07068       if (!strcasecmp(i->name, new_include->name)) {
07069          ast_destroy_timing(&(new_include->timing));
07070          ast_free(new_include);
07071          ast_unlock_context(con);
07072          errno = EEXIST;
07073          return -1;
07074       }
07075       il = i;
07076    }
07077 
07078    /* ... include new context into context list, unlock, return */
07079    if (il)
07080       il->next = new_include;
07081    else
07082       con->includes = new_include;
07083    ast_verb(3, "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con));
07084 
07085    ast_unlock_context(con);
07086 
07087    return 0;
07088 }

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

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

07096 {
07097    int ret = -1;
07098    struct ast_context *c = find_context_locked(context);
07099 
07100    if (c) { /* found, add switch to this context */
07101       ret = ast_context_add_switch2(c, sw, data, eval, registrar);
07102       ast_unlock_contexts();
07103    }
07104    return ret;
07105 }

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

References ast_context::alts, ast_calloc, ast_free, ast_get_context_name(), AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, ast_unlock_context(), ast_verb, ast_wrlock_context(), ast_sw::data, errno, ast_sw::eval, ast_sw::name, ast_sw::registrar, and ast_sw::stuff.

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

07116 {
07117    struct ast_sw *new_sw;
07118    struct ast_sw *i;
07119    int length;
07120    char *p;
07121 
07122    length = sizeof(struct ast_sw);
07123    length += strlen(value) + 1;
07124    if (data)
07125       length += strlen(data);
07126    length++;
07127 
07128    /* allocate new sw structure ... */
07129    if (!(new_sw = ast_calloc(1, length)))
07130       return -1;
07131    /* ... fill in this structure ... */
07132    p = new_sw->stuff;
07133    new_sw->name = p;
07134    strcpy(new_sw->name, value);
07135    p += strlen(value) + 1;
07136    new_sw->data = p;
07137    if (data) {
07138       strcpy(new_sw->data, data);
07139       p += strlen(data) + 1;
07140    } else {
07141       strcpy(new_sw->data, "");
07142       p++;
07143    }
07144    new_sw->eval     = eval;
07145    new_sw->registrar = registrar;
07146 
07147    /* ... try to lock this context ... */
07148    ast_wrlock_context(con);
07149 
07150    /* ... go to last sw and check if context is already swd too... */
07151    AST_LIST_TRAVERSE(&con->alts, i, list) {
07152       if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) {
07153          ast_free(new_sw);
07154          ast_unlock_context(con);
07155          errno = EEXIST;
07156          return -1;
07157       }
07158    }
07159 
07160    /* ... sw new context into context list, unlock, return */
07161    AST_LIST_INSERT_TAIL(&con->alts, new_sw, list);
07162 
07163    ast_verb(3, "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con));
07164 
07165    ast_unlock_context(con);
07166 
07167    return 0;
07168 }

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

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

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

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

Find a context.

Parameters:
name name of the context to find

Will search for the context with the given name.

Returns:
the ast_context on success, NULL on failure.

Definition at line 2430 of file pbx.c.

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

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

02431 {
02432    struct ast_context *tmp = NULL;
02433    struct fake_context item;
02434 
02435    ast_copy_string(item.name, name, sizeof(item.name));
02436 
02437    ast_rdlock_contexts();
02438    if( contexts_table ) {
02439       tmp = ast_hashtab_lookup(contexts_table,&item);
02440    } else {
02441       while ( (tmp = ast_walk_contexts(tmp)) ) {
02442          if (!name || !strcasecmp(name, tmp->name)) {
02443             break;
02444          }
02445       }
02446    }
02447    ast_unlock_contexts();
02448    return tmp;
02449 }

struct ast_context* ast_context_find_or_create ( struct ast_context **  extcontexts,
struct ast_hashtab exttable,
const char *  name,
const char *  registrar 
) [read]

Register a new context or find an existing one.

Parameters:
extcontexts pointer to the ast_context structure pointer
exttable pointer to the hashtable that contains all the elements in extcontexts
name name of the new context
registrar registrar of the context

This function allows you to play in two environments: the global contexts (active dialplan) or an external context set of your choosing. To act on the external set, make sure extcontexts and exttable are set; for the globals, make sure both extcontexts and exttable are NULL.

This will first search for a context with your name. If it exists already, it will not create a new one. If it does not exist, it will create a new one with the given name and registrar.

Returns:
NULL on failure, and an ast_context structure on success

Definition at line 6424 of file pbx.c.

References ast_calloc, ast_copy_string(), ast_debug, ast_hashtab_compare_contexts(), ast_hashtab_create(), ast_hashtab_hash_contexts(), ast_hashtab_insert_immediate(), ast_hashtab_insert_safe(), ast_hashtab_lookup(), ast_hashtab_newsize_java(), ast_hashtab_resize_java(), ast_log(), ast_mutex_init(), ast_rdlock_contexts(), ast_rwlock_init(), ast_strdup, ast_unlock_contexts(), ast_verb, ast_wrlock_contexts(), contexts, contexts_table, ast_context::ignorepats, ast_context::includes, local_contexts, ast_context::lock, LOG_ERROR, ast_context::macrolock, ast_context::name, fake_context::name, ast_context::next, ast_context::refcount, ast_context::registrar, ast_context::root, and ast_context::root_table.

Referenced by ast_compile_ael2(), build_parkinglot(), config_parse_variables(), context_merge(), load_config(), load_module(), lua_register_switches(), manage_parkinglot(), park_call_full(), pbx_load_config(), pbx_load_users(), reload_config(), set_config(), sla_build_station(), and sla_build_trunk().

06425 {
06426    struct ast_context *tmp, **local_contexts;
06427    struct fake_context search;
06428    int length = sizeof(struct ast_context) + strlen(name) + 1;
06429 
06430    if (!contexts_table) {
06431       contexts_table = ast_hashtab_create(17,
06432                                  ast_hashtab_compare_contexts,
06433                                  ast_hashtab_resize_java,
06434                                  ast_hashtab_newsize_java,
06435                                  ast_hashtab_hash_contexts,
06436                                  0);
06437    }
06438 
06439    ast_copy_string(search.name, name, sizeof(search.name));
06440    if (!extcontexts) {
06441       ast_rdlock_contexts();
06442       local_contexts = &contexts;
06443       tmp = ast_hashtab_lookup(contexts_table, &search);
06444       ast_unlock_contexts();
06445       if (tmp) {
06446          tmp->refcount++;
06447          return tmp;
06448       }
06449    } else { /* local contexts just in a linked list; search there for the new context; slow, linear search, but not frequent */
06450       local_contexts = extcontexts;
06451       tmp = ast_hashtab_lookup(exttable, &search);
06452       if (tmp) {
06453          tmp->refcount++;
06454          return tmp;
06455       }
06456    }
06457 
06458    if ((tmp = ast_calloc(1, length))) {
06459       ast_rwlock_init(&tmp->lock);
06460       ast_mutex_init(&tmp->macrolock);
06461       strcpy(tmp->name, name);
06462       tmp->root = NULL;
06463       tmp->root_table = NULL;
06464       tmp->registrar = ast_strdup(registrar);
06465       tmp->includes = NULL;
06466       tmp->ignorepats = NULL;
06467       tmp->refcount = 1;
06468    } else {
06469       ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name);
06470       return NULL;
06471    }
06472 
06473    if (!extcontexts) {
06474       ast_wrlock_contexts();
06475       tmp->next = *local_contexts;
06476       *local_contexts = tmp;
06477       ast_hashtab_insert_safe(contexts_table, tmp); /*put this context into the tree */
06478       ast_unlock_contexts();
06479       ast_debug(1, "Registered context '%s'(%p) in table %p registrar: %s\n", tmp->name, tmp, contexts_table, registrar);
06480       ast_verb(3, "Registered extension context '%s' (%p) in table %p; registrar: %s\n", tmp->name, tmp, contexts_table, registrar);
06481    } else {
06482       tmp->next = *local_contexts;
06483       if (exttable)
06484          ast_hashtab_insert_immediate(exttable, tmp); /*put this context into the tree */
06485 
06486       *local_contexts = tmp;
06487       ast_debug(1, "Registered context '%s'(%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar);
06488       ast_verb(3, "Registered extension context '%s' (%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar);
06489    }
06490    return tmp;
06491 }

int ast_context_lockmacro ( const char *  context  ) 

locks the macrolock in the given given context

Parameters:
macrocontext name of the macro-context to lock

Locks the given macro-context to ensure only one thread (call) can execute it at a time

Return values:
0 on success
-1 on failure
Note:
This function locks contexts list by &conlist, searches for the right context structure, and locks the macrolock mutex in that context. macrolock is used to limit a macro to be executed by one call at a time.

Definition at line 4988 of file pbx.c.

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

Referenced by _macro_exec().

04989 {
04990    struct ast_context *c = NULL;
04991    int ret = -1;
04992    struct fake_context item;
04993 
04994    ast_rdlock_contexts();
04995 
04996    ast_copy_string(item.name, context, sizeof(item.name));
04997 
04998    c = ast_hashtab_lookup(contexts_table,&item);
04999    if (c)
05000       ret = 0;
05001 
05002 
05003 #ifdef NOTNOW
05004 
05005    while ((c = ast_walk_contexts(c))) {
05006       if (!strcmp(ast_get_context_name(c), context)) {
05007          ret = 0;
05008          break;
05009       }
05010    }
05011 
05012 #endif
05013    ast_unlock_contexts();
05014 
05015    /* if we found context, lock macrolock */
05016    if (ret == 0) {
05017       ret = ast_mutex_lock(&c->macrolock);
05018    }
05019 
05020    return ret;
05021 }

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

Simply remove extension from context.

Parameters:
context context to remove extension from
extension which extension to remove
priority priority of extension to remove (0 to remove all)
callerid NULL to remove all; non-NULL to match a single record per priority
matchcid non-zero to match callerid element (if non-NULL); 0 to match default case
registrar registrar of the extension

This function removes an extension from a given context.

Return values:
0 on success
-1 on failure

Definition at line 4796 of file pbx.c.

References ast_context_remove_extension_callerid().

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

04797 {
04798    return ast_context_remove_extension_callerid(context, extension, priority, NULL, 0, registrar);
04799 }

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

References ast_context_remove_extension_callerid2().

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

04824 {
04825    return ast_context_remove_extension_callerid2(con, extension, priority, NULL, 0, registrar, already_locked);
04826 }

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

04802 {
04803    int ret = -1; /* default error return */
04804    struct ast_context *c = find_context_locked(context);
04805 
04806    if (c) { /* ... remove extension ... */
04807       ret = ast_context_remove_extension_callerid2(c, extension, priority, callerid, matchcallerid, registrar, 1);
04808       ast_unlock_contexts();
04809    }
04810    return ret;
04811 }

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

References add_exten_to_pattern_tree(), ast_copy_string(), ast_hashtab_insert_immediate(), ast_hashtab_lookup(), ast_hashtab_remove_this_object(), ast_hashtab_size(), ast_log(), ast_strlen_zero(), ast_unlock_context(), ast_verb, ast_wrlock_context(), ast_exten::cidmatch, match_char::deleted, destroy_exten(), match_char::exten, ast_exten::exten, ast_exten::label, LOG_ERROR, log_match_char_tree(), LOG_NOTICE, LOG_WARNING, ast_exten::matchcid, ast_context::name, ast_exten::next, ast_context::pattern_tree, ast_exten::peer, ast_exten::peer_label_table, ast_exten::peer_table, ast_exten::priority, ast_exten::registrar, ast_context::root, ast_context::root_table, and match_char::x.

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

04829 {
04830    struct ast_exten *exten, *prev_exten = NULL;
04831    struct ast_exten *peer;
04832    struct ast_exten ex, *exten2, *exten3;
04833    char dummy_name[1024];
04834    struct ast_exten *previous_peer = NULL;
04835    struct ast_exten *next_peer = NULL;
04836    int found = 0;
04837 
04838    if (!already_locked)
04839       ast_wrlock_context(con);
04840 
04841    /* Handle this is in the new world */
04842 
04843    /* FIXME For backwards compatibility, if callerid==NULL, then remove ALL
04844     * peers, not just those matching the callerid. */
04845 #ifdef NEED_DEBUG
04846    ast_verb(3,"Removing %s/%s/%d%s%s from trees, registrar=%s\n", con->name, extension, priority, matchcallerid ? "/" : "", matchcallerid ? callerid : "", registrar);
04847 #endif
04848 #ifdef CONTEXT_DEBUG
04849    check_contexts(__FILE__, __LINE__);
04850 #endif
04851    /* find this particular extension */
04852    ex.exten = dummy_name;
04853    ex.matchcid = matchcallerid && !ast_strlen_zero(callerid); /* don't say match if there's no callerid */
04854    ex.cidmatch = callerid;
04855    ast_copy_string(dummy_name, extension, sizeof(dummy_name));
04856    exten = ast_hashtab_lookup(con->root_table, &ex);
04857    if (exten) {
04858       if (priority == 0) {
04859          exten2 = ast_hashtab_remove_this_object(con->root_table, exten);
04860          if (!exten2)
04861             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);
04862          if (con->pattern_tree) {
04863             struct match_char *x = add_exten_to_pattern_tree(con, exten, 1);
04864 
04865             if (x->exten) { /* this test for safety purposes */
04866                x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */
04867                x->exten = 0; /* get rid of what will become a bad pointer */
04868             } else {
04869                ast_log(LOG_WARNING,"Trying to delete an exten from a context, but the pattern tree node returned isn't a full extension\n");
04870             }
04871          }
04872       } else {
04873          ex.priority = priority;
04874          exten2 = ast_hashtab_lookup(exten->peer_table, &ex);
04875          if (exten2) {
04876 
04877             if (exten2->label) { /* if this exten has a label, remove that, too */
04878                exten3 = ast_hashtab_remove_this_object(exten->peer_label_table,exten2);
04879                if (!exten3)
04880                   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);
04881             }
04882 
04883             exten3 = ast_hashtab_remove_this_object(exten->peer_table, exten2);
04884             if (!exten3)
04885                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);
04886             if (exten2 == exten && exten2->peer) {
04887                exten2 = ast_hashtab_remove_this_object(con->root_table, exten);
04888                ast_hashtab_insert_immediate(con->root_table, exten2->peer);
04889             }
04890             if (ast_hashtab_size(exten->peer_table) == 0) {
04891                /* well, if the last priority of an exten is to be removed,
04892                   then, the extension is removed, too! */
04893                exten3 = ast_hashtab_remove_this_object(con->root_table, exten);
04894                if (!exten3)
04895                   ast_log(LOG_ERROR,"Did not remove this exten (%s) from the context root_table (%s) (priority %d)\n", exten->exten, con->name, priority);
04896                if (con->pattern_tree) {
04897                   struct match_char *x = add_exten_to_pattern_tree(con, exten, 1);
04898                   if (x->exten) { /* this test for safety purposes */
04899                      x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */
04900                      x->exten = 0; /* get rid of what will become a bad pointer */
04901                   }
04902                }
04903             }
04904          } else {
04905             ast_log(LOG_ERROR,"Could not find priority %d of exten %s in context %s!\n",
04906                   priority, exten->exten, con->name);
04907          }
04908       }
04909    } else {
04910       /* hmmm? this exten is not in this pattern tree? */
04911       ast_log(LOG_WARNING,"Cannot find extension %s in root_table in context %s\n",
04912             extension, con->name);
04913    }
04914 #ifdef NEED_DEBUG
04915    if (con->pattern_tree) {
04916       ast_log(LOG_NOTICE,"match char tree after exten removal:\n");
04917       log_match_char_tree(con->pattern_tree, " ");
04918    }
04919 #endif
04920 
04921    /* scan the extension list to find first matching extension-registrar */
04922    for (exten = con->root; exten; prev_exten = exten, exten = exten->next) {
04923       if (!strcmp(exten->exten, extension) &&
04924          (!registrar || !strcmp(exten->registrar, registrar)) &&
04925          (!matchcallerid || (!ast_strlen_zero(callerid) && !ast_strlen_zero(exten->cidmatch) && !strcmp(exten->cidmatch, callerid)) || (ast_strlen_zero(callerid) && ast_strlen_zero(exten->cidmatch))))
04926          break;
04927    }
04928    if (!exten) {
04929       /* we can't find right extension */
04930       if (!already_locked)
04931          ast_unlock_context(con);
04932       return -1;
04933    }
04934 
04935    /* scan the priority list to remove extension with exten->priority == priority */
04936    for (peer = exten, next_peer = exten->peer ? exten->peer : exten->next;
04937        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)));
04938          peer = next_peer, next_peer = next_peer ? (next_peer->peer ? next_peer->peer : next_peer->next) : NULL) {
04939       if ((priority == 0 || peer->priority == priority) &&
04940             (!callerid || !matchcallerid || (matchcallerid && !strcmp(peer->cidmatch, callerid))) &&
04941             (!registrar || !strcmp(peer->registrar, registrar) )) {
04942          found = 1;
04943 
04944          /* we are first priority extension? */
04945          if (!previous_peer) {
04946             /*
04947              * We are first in the priority chain, so must update the extension chain.
04948              * The next node is either the next priority or the next extension
04949              */
04950             struct ast_exten *next_node = peer->peer ? peer->peer : peer->next;
04951             if (peer->peer) {
04952                /* move the peer_table and peer_label_table down to the next peer, if
04953                   it is there */
04954                peer->peer->peer_table = peer->peer_table;
04955                peer->peer->peer_label_table = peer->peer_label_table;
04956                peer->peer_table = NULL;
04957                peer->peer_label_table = NULL;
04958             }
04959             if (!prev_exten) {   /* change the root... */
04960                con->root = next_node;
04961             } else {
04962                prev_exten->next = next_node; /* unlink */
04963             }
04964             if (peer->peer)   { /* update the new head of the pri list */
04965                peer->peer->next = peer->next;
04966             }
04967          } else { /* easy, we are not first priority in extension */
04968             previous_peer->peer = peer->peer;
04969          }
04970 
04971          /* now, free whole priority extension */
04972          destroy_exten(peer);
04973       } else {
04974          previous_peer = peer;
04975       }
04976    }
04977    if (!already_locked)
04978       ast_unlock_context(con);
04979    return found ? 0 : -1;
04980 }

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

Definition at line 7174 of file pbx.c.

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

Referenced by handle_cli_dialplan_remove_ignorepat().

07175 {
07176    int ret = -1;
07177    struct ast_context *c = find_context_locked(context);
07178 
07179    if (c) {
07180       ret = ast_context_remove_ignorepat2(c, ignorepat, registrar);
07181       ast_unlock_contexts();
07182    }
07183    return ret;
07184 }

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

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

07187 {
07188    struct ast_ignorepat *ip, *ipl = NULL;
07189 
07190    ast_wrlock_context(con);
07191 
07192    for (ip = con->ignorepats; ip; ip = ip->next) {
07193       if (!strcmp(ip->pattern, ignorepat) &&
07194          (!registrar || (registrar == ip->registrar))) {
07195          if (ipl) {
07196             ipl->next = ip->next;
07197             ast_free(ip);
07198          } else {
07199             con->ignorepats = ip->next;
07200             ast_free(ip);
07201          }
07202          ast_unlock_context(con);
07203          return 0;
07204       }
07205       ipl = ip;
07206    }
07207 
07208    ast_unlock_context(con);
07209    errno = EINVAL;
07210    return -1;
07211 }

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

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

Referenced by handle_cli_dialplan_remove_include().

04688 {
04689    int ret = -1;
04690    struct ast_context *c = find_context_locked(context);
04691 
04692    if (c) {
04693       /* found, remove include from this context ... */
04694       ret = ast_context_remove_include2(c, include, registrar);
04695       ast_unlock_contexts();
04696    }
04697    return ret;
04698 }

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

Removes an include by an ast_context structure.

Note:
See ast_context_add_include2 for information on arguments
Return values:
0 on success
-1 on success

Removes an include by an ast_context structure.

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

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

04710 {
04711    struct ast_include *i, *pi = NULL;
04712    int ret = -1;
04713 
04714    ast_wrlock_context(con);
04715 
04716    /* find our include */
04717    for (i = con->includes; i; pi = i, i = i->next) {
04718       if (!strcmp(i->name, include) &&
04719             (!registrar || !strcmp(i->registrar, registrar))) {
04720          /* remove from list */
04721          ast_verb(3, "Removing inclusion of context '%s' in context '%s; registrar=%s'\n", include, ast_get_context_name(con), registrar);
04722          if (pi)
04723             pi->next = i->next;
04724          else
04725             con->includes = i->next;
04726          /* free include and return */
04727          ast_destroy_timing(&(i->timing));
04728          ast_free(i);
04729          ret = 0;
04730          break;
04731       }
04732    }
04733 
04734    ast_unlock_context(con);
04735 
04736    return ret;
04737 }

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

Remove a switch.

Removes a switch with the given parameters

Return values:
0 on success
-1 on failure
Note:
This function locks contexts list by &conlist, search for the rigt context structure, leave context list locked and call ast_context_remove_switch2 which removes switch, unlock contexts list and return ...

Definition at line 4744 of file pbx.c.

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

04745 {
04746    int ret = -1; /* default error return */
04747    struct ast_context *c = find_context_locked(context);
04748 
04749    if (c) {
04750       /* remove switch from this context ... */
04751       ret = ast_context_remove_switch2(c, sw, data, registrar);
04752       ast_unlock_contexts();
04753    }
04754    return ret;
04755 }

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

References ast_context::alts, ast_free, ast_get_context_name(), AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_unlock_context(), ast_verb, ast_wrlock_context(), ast_sw::data, ast_sw::name, and ast_sw::registrar.

Referenced by ast_context_remove_switch().

04766 {
04767    struct ast_sw *i;
04768    int ret = -1;
04769 
04770    ast_wrlock_context(con);
04771 
04772    /* walk switches */
04773    AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) {
04774       if (!strcmp(i->name, sw) && !strcmp(i->data, data) &&
04775          (!registrar || !strcmp(i->registrar, registrar))) {
04776          /* found, remove from list */
04777          ast_verb(3, "Removing switch '%s' from context '%s; registrar=%s'\n", sw, ast_get_context_name(con), registrar);
04778          AST_LIST_REMOVE_CURRENT(list);
04779          ast_free(i); /* free switch and return */
04780          ret = 0;
04781          break;
04782       }
04783    }
04784    AST_LIST_TRAVERSE_SAFE_END;
04785 
04786    ast_unlock_context(con);
04787 
04788    return ret;
04789 }

int ast_context_unlockmacro ( const char *  context  ) 

Unlocks the macrolock in the given context.

Parameters:
macrocontext name of the macro-context to unlock

Unlocks the given macro-context so that another thread (call) can execute it

Return values:
0 on success
-1 on failure
Note:
This function locks contexts list by &conlist, searches for the right context structure, and unlocks the macrolock mutex in that context. macrolock is used to limit a macro to be executed by one call at a time.

Definition at line 5028 of file pbx.c.

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

Referenced by _macro_exec().

05029 {
05030    struct ast_context *c = NULL;
05031    int ret = -1;
05032    struct fake_context item;
05033 
05034    ast_rdlock_contexts();
05035 
05036    ast_copy_string(item.name, context, sizeof(item.name));
05037 
05038    c = ast_hashtab_lookup(contexts_table,&item);
05039    if (c)
05040       ret = 0;
05041 #ifdef NOTNOW
05042 
05043    while ((c = ast_walk_contexts(c))) {
05044       if (!strcmp(ast_get_context_name(c), context)) {
05045          ret = 0;
05046          break;
05047       }
05048    }
05049 
05050 #endif
05051    ast_unlock_contexts();
05052 
05053    /* if we found context, unlock macrolock */
05054    if (ret == 0) {
05055       ret = ast_mutex_unlock(&c->macrolock);
05056    }
05057 
05058    return ret;
05059 }

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

09533 {
09534    struct ast_include *inc = NULL;
09535    int res = 0;
09536 
09537    while ( (inc = ast_walk_context_includes(con, inc)) ) {
09538       if (ast_context_find(inc->rname))
09539          continue;
09540 
09541       res = -1;
09542       ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n",
09543          ast_get_context_name(con), inc->rname);
09544       break;
09545    }
09546 
09547    return res;
09548 }

struct ast_custom_function* ast_custom_function_find ( const char *  name  )  [read]
int ast_custom_function_unregister ( struct ast_custom_function acf  ) 

Unregister a custom function.

Definition at line 3216 of file pbx.c.

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

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

03217 {
03218    struct ast_custom_function *cur;
03219 
03220    if (!acf) {
03221       return -1;
03222    }
03223 
03224    AST_RWLIST_WRLOCK(&acf_root);
03225    if ((cur = AST_RWLIST_REMOVE(&acf_root, acf, acflist))) {
03226       if (cur->docsrc == AST_XML_DOC) {
03227          ast_string_field_free_memory(acf);
03228       }
03229       ast_verb(2, "Unregistered custom function %s\n", cur->name);
03230    }
03231    AST_RWLIST_UNLOCK(&acf_root);
03232 
03233    return cur ? 0 : -1;
03234 }

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

07018 {
07019    if (i->timezone) {
07020       ast_free(i->timezone);
07021       i->timezone = NULL;
07022    }
07023    return 0;
07024 }

enum ast_extension_states ast_devstate_to_extenstate ( enum ast_device_state  devstate  ) 

Map devstate to an extension state.

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

Definition at line 3770 of file pbx.c.

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

Referenced by ast_extension_state2().

03771 {
03772    switch (devstate) {
03773    case AST_DEVICE_ONHOLD:
03774       return AST_EXTENSION_ONHOLD;
03775    case AST_DEVICE_BUSY:
03776       return AST_EXTENSION_BUSY;
03777    case AST_DEVICE_UNAVAILABLE:
03778    case AST_DEVICE_UNKNOWN:
03779    case AST_DEVICE_INVALID:
03780       return AST_EXTENSION_UNAVAILABLE;
03781    case AST_DEVICE_RINGINUSE:
03782       return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING);
03783    case AST_DEVICE_RINGING:
03784       return AST_EXTENSION_RINGING;
03785    case AST_DEVICE_INUSE:
03786       return AST_EXTENSION_INUSE;
03787    case AST_DEVICE_NOT_INUSE:
03788       return AST_EXTENSION_NOT_INUSE;
03789    case AST_DEVICE_TOTAL: /* not a device state, included for completeness */
03790       break;
03791    }
03792 
03793    return AST_EXTENSION_NOT_INUSE;
03794 }

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

References E_MATCH, and pbx_extension_helper().

Referenced by __ast_goto_if_exists(), __ast_pbx_run(), _macro_exec(), acf_isexten_exec(), answer_call(), ast_app_dtget(), ast_bridge_call(), ast_pbx_outgoing_exten(), builtin_atxfer(), builtin_blindtransfer(), cb_events(), cli_console_dial(), conf_run(), console_dial(), console_transfer(), dahdi_handle_dtmfup(), dial_exec_full(), disa_exec(), dp_lookup(), dundi_lookup_local(), get_also_info(), get_destination(), get_refer_info(), gosub_exec(), handle_gosub(), handle_link_data(), handle_link_phone_dtmf(), handle_stimulus_message(), isexten_function_read(), leave_voicemail(), local_alloc(), local_call(), local_devicestate(), local_dtmf_helper(), loopback_exists(), metermaidstate(), mgcp_ss(), minivm_greet_exec(), misdn_overlap_dial_task(), park_space_reserve(), parkandannounce_exec(), pbx_builtin_waitexten(), phone_check_exception(), pri_dchannel(), privacy_exec(), process_ast_dsp(), readexten_exec(), register_peer_exten(), rpt_exec(), show_debug_helper(), sip_read(), skinny_ss(), socket_process(), ss7_linkset(), ss_thread(), and waitstream_core().

04144 {
04145    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0);
04146 }

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

References ast_channel_lock, ast_channel_unlock, ast_copy_string(), AST_FLAG_IN_AUTOLOOP, ast_strlen_zero(), ast_test_flag, ast_channel::context, ast_channel::exten, and ast_channel::priority.

Referenced by __ast_goto_if_exists(), ast_async_goto(), builtin_atxfer(), disa_exec(), do_bridge_masquerade(), handle_setpriority(), pbx_parseable_goto(), and return_exec().

07322 {
07323    if (!chan)
07324       return -1;
07325 
07326    ast_channel_lock(chan);
07327 
07328    if (!ast_strlen_zero(context))
07329       ast_copy_string(chan->context, context, sizeof(chan->context));
07330    if (!ast_strlen_zero(exten))
07331       ast_copy_string(chan->exten, exten, sizeof(chan->exten));
07332    if (priority > -1) {
07333       chan->priority = priority;
07334       /* see flag description in channel.h for explanation */
07335       if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP))
07336          chan->priority--;
07337    }
07338 
07339    ast_channel_unlock(chan);
07340 
07341    return 0;
07342 }

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

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

02408 {
02409    if (needmore != E_MATCHMORE && needmore != E_CANMATCH)
02410       ast_log(LOG_WARNING, "invalid argument %d\n", needmore);
02411    return extension_match_core(pattern, data, needmore);
02412 }

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

References ext_cmp().

Referenced by lua_extension_cmp().

02210 {
02211    return ext_cmp(a, b);
02212 }

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

References E_MATCH, and extension_match_core().

Referenced by ast_ignore_pattern(), do_say(), find_matching_priority(), load_module(), loopback_canmatch(), loopback_exists(), loopback_matchmore(), lua_find_extension(), manager_show_dialplan_helper(), matchcid(), misdn_cfg_is_msn_valid(), realtime_switch_common(), reload(), and show_dialplan_helper().

02403 {
02404    return extension_match_core(pattern, data, E_MATCH);
02405 }

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

References ast_extension_state2(), and ast_hint_extension().

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

03833 {
03834    struct ast_exten *e;
03835 
03836    if (!(e = ast_hint_extension(c, context, exten))) {  /* Do we have a hint for this extension ? */
03837       return -1;                   /* No hint, return -1 */
03838    }
03839 
03840    return ast_extension_state2(e);  /* Check all devices in the hint */
03841 }

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

References ARRAY_LEN, extension_states, and cfextension_states::text.

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

03821 {
03822    int i;
03823 
03824    for (i = 0; (i < ARRAY_LEN(extension_states)); i++) {
03825       if (extension_states[i].extension_state == extension_state)
03826          return extension_states[i].text;
03827    }
03828    return "Unknown";
03829 }

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

Registers a state change callback.

Parameters:
context which context to look in
exten which extension to get state
callback callback to call if state changed
data to pass to callback

The callback is called if the state of an extension is changed.

Return values:
-1 on failure
ID on success

Definition at line 3896 of file pbx.c.

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

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

03898 {
03899    struct ast_hint *hint;
03900    struct ast_state_cb *cblist;
03901    struct ast_exten *e;
03902 
03903    /* If there's no context and extension:  add callback to statecbs list */
03904    if (!context && !exten) {
03905       AST_RWLIST_WRLOCK(&hints);
03906 
03907       AST_LIST_TRAVERSE(&statecbs, cblist, entry) {
03908          if (cblist->callback == callback) {
03909             cblist->data = data;
03910             AST_RWLIST_UNLOCK(&hints);
03911             return 0;
03912          }
03913       }
03914 
03915       /* Now insert the callback */
03916       if (!(cblist = ast_calloc(1, sizeof(*cblist)))) {
03917          AST_RWLIST_UNLOCK(&hints);
03918          return -1;
03919       }
03920       cblist->id = 0;
03921       cblist->callback = callback;
03922       cblist->data = data;
03923 
03924       AST_LIST_INSERT_HEAD(&statecbs, cblist, entry);
03925 
03926       AST_RWLIST_UNLOCK(&hints);
03927 
03928       return 0;
03929    }
03930 
03931    if (!context || !exten)
03932       return -1;
03933 
03934    /* This callback type is for only one hint, so get the hint */
03935    e = ast_hint_extension(NULL, context, exten);
03936    if (!e) {
03937       return -1;
03938    }
03939 
03940    /* If this is a pattern, dynamically create a new extension for this
03941     * particular match.  Note that this will only happen once for each
03942     * individual extension, because the pattern will no longer match first.
03943     */
03944    if (e->exten[0] == '_') {
03945       ast_add_extension(e->parent->name, 0, exten, e->priority, e->label,
03946          e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr,
03947          e->registrar);
03948       e = ast_hint_extension(NULL, context, exten);
03949       if (!e || e->exten[0] == '_') {
03950          return -1;
03951       }
03952    }
03953 
03954    /* Find the hint in the list of hints */
03955    AST_RWLIST_WRLOCK(&hints);
03956 
03957    AST_RWLIST_TRAVERSE(&hints, hint, list) {
03958       if (hint->exten == e)
03959          break;
03960    }
03961 
03962    if (!hint) {
03963       /* We have no hint, sorry */
03964       AST_RWLIST_UNLOCK(&hints);
03965       return -1;
03966    }
03967 
03968    /* Now insert the callback in the callback list  */
03969    if (!(cblist = ast_calloc(1, sizeof(*cblist)))) {
03970       AST_RWLIST_UNLOCK(&hints);
03971       return -1;
03972    }
03973 
03974    cblist->id = stateid++;    /* Unique ID for this callback */
03975    cblist->callback = callback;  /* Pointer to callback routine */
03976    cblist->data = data;    /* Data for the callback */
03977 
03978    AST_LIST_INSERT_HEAD(&hint->callbacks, cblist, entry);
03979 
03980    AST_RWLIST_UNLOCK(&hints);
03981 
03982    return cblist->id;
03983 }

int ast_extension_state_del ( int  id,
ast_state_cb_type  callback 
)

Deletes a registered state change callback by ID.

Parameters:
id of the callback to delete
callback callback

Removes the callback from list of callbacks

Return values:
0 success
-1 failure

Definition at line 3986 of file pbx.c.

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

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

03987 {
03988    struct ast_state_cb *p_cur = NULL;
03989    int ret = -1;
03990 
03991    if (!id && !callback)
03992       return -1;
03993 
03994    AST_RWLIST_WRLOCK(&hints);
03995 
03996    if (!id) {  /* id == 0 is a callback without extension */
03997       AST_LIST_TRAVERSE_SAFE_BEGIN(&statecbs, p_cur, entry) {
03998          if (p_cur->callback == callback) {
03999             AST_LIST_REMOVE_CURRENT(entry);
04000             break;
04001          }
04002       }
04003       AST_LIST_TRAVERSE_SAFE_END;
04004    } else { /* callback with extension, find the callback based on ID */
04005       struct ast_hint *hint;
04006       AST_RWLIST_TRAVERSE(&hints, hint, list) {
04007          AST_LIST_TRAVERSE_SAFE_BEGIN(&hint->callbacks, p_cur, entry) {
04008             if (p_cur->id == id) {
04009                AST_LIST_REMOVE_CURRENT(entry);
04010                break;
04011             }
04012          }
04013          AST_LIST_TRAVERSE_SAFE_END;
04014 
04015          if (p_cur)
04016             break;
04017       }
04018    }
04019 
04020    if (p_cur) {
04021       ast_free(p_cur);
04022    }
04023 
04024    AST_RWLIST_UNLOCK(&hints);
04025 
04026    return ret;
04027 }

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

04149 {
04150    return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
04151 }

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

References E_FINDLABEL, and pbx_extension_helper().

Referenced by pbx_load_config().

04154 {
04155    return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
04156 }

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

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

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

03357 {
03358    char *copy = ast_strdupa(function);
03359    char *args = func_args(copy);
03360    struct ast_custom_function *acfptr = ast_custom_function_find(copy);
03361 
03362    if (acfptr == NULL)
03363       ast_log(LOG_ERROR, "Function %s not registered\n", copy);
03364    else if (!acfptr->read)
03365       ast_log(LOG_ERROR, "Function %s cannot be read\n", copy);
03366    else {
03367       int res;
03368       struct ast_module_user *u = NULL;
03369       if (acfptr->mod)
03370          u = __ast_module_user_add(acfptr->mod, chan);
03371       res = acfptr->read(chan, copy, args, workspace, len);
03372       if (acfptr->mod && u)
03373          __ast_module_user_remove(acfptr->mod, u);
03374       return res;
03375    }
03376    return -1;
03377 }

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

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

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

03380 {
03381    char *copy = ast_strdupa(function);
03382    char *args = func_args(copy);
03383    struct ast_custom_function *acfptr = ast_custom_function_find(copy);
03384 
03385    if (acfptr == NULL)
03386       ast_log(LOG_ERROR, "Function %s not registered\n", copy);
03387    else if (!acfptr->write)
03388       ast_log(LOG_ERROR, "Function %s cannot be written to\n", copy);
03389    else {
03390       int res;
03391       struct ast_module_user *u = NULL;
03392       if (acfptr->mod)
03393          u = __ast_module_user_add(acfptr->mod, chan);
03394       res = acfptr->write(chan, copy, args, value);
03395       if (acfptr->mod && u)
03396          __ast_module_user_remove(acfptr->mod, u);
03397       return res;
03398    }
03399 
03400    return -1;
03401 }

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

Definition at line 9422 of file pbx.c.

References ast_context::registrar.

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

09423 {
09424    return c ? c->registrar : NULL;
09425 }

const char* ast_get_extension_app ( struct ast_exten e  ) 
void* ast_get_extension_app_data ( struct ast_exten e  ) 

Definition at line 9457 of file pbx.c.

References ast_exten::data.

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

09458 {
09459    return e ? e->data : NULL;
09460 }

const char* ast_get_extension_cidmatch ( struct ast_exten e  ) 

Definition at line 9447 of file pbx.c.

References ast_exten::cidmatch.

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

09448 {
09449    return e ? e->cidmatch : NULL;
09450 }

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

Definition at line 9389 of file pbx.c.

References ast_exten::parent.

Referenced by handle_show_hint(), and handle_show_hints().

09390 {
09391    return exten ? exten->parent : NULL;
09392 }

const char* ast_get_extension_label ( struct ast_exten e  ) 

Definition at line 9399 of file pbx.c.

References ast_exten::label.

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

09400 {
09401    return exten ? exten->label : NULL;
09402 }

int ast_get_extension_matchcid ( struct ast_exten e  ) 

Definition at line 9442 of file pbx.c.

References ast_exten::matchcid.

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

09443 {
09444    return e ? e->matchcid : 0;
09445 }

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

Definition at line 9414 of file pbx.c.

References ast_exten::priority.

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

09415 {
09416    return exten ? exten->priority : -1;
09417 }

const char* ast_get_extension_registrar ( struct ast_exten e  ) 

Definition at line 9427 of file pbx.c.

References ast_exten::registrar.

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

09428 {
09429    return e ? e->registrar : NULL;
09430 }

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 4126 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(), pbx_retrieve_variable(), skinny_extensionstate_cb(), and transmit_state_notify().

04127 {
04128    struct ast_exten *e = ast_hint_extension(c, context, exten);
04129 
04130    if (e) {
04131       if (hint)
04132          ast_copy_string(hint, ast_get_extension_app(e), hintsize);
04133       if (name) {
04134          const char *tmp = ast_get_extension_app_data(e);
04135          if (tmp)
04136             ast_copy_string(name, tmp, namesize);
04137       }
04138       return -1;
04139    }
04140    return 0;
04141 }

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

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

09438 {
09439    return ip ? ip->registrar : NULL;
09440 }

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

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

09433 {
09434    return i ? i->registrar : NULL;
09435 }

const char* ast_get_switch_data ( struct ast_sw sw  ) 

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

09468 {
09469    return sw ? sw->data : NULL;
09470 }

int ast_get_switch_eval ( struct ast_sw sw  ) 

Definition at line 9472 of file pbx.c.

References ast_sw::eval.

Referenced by context_merge_incls_swits_igps_other_registrars().

09473 {
09474    return sw->eval;
09475 }

const char* ast_get_switch_name ( struct ast_sw sw  ) 

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

09463 {
09464    return sw ? sw->name : NULL;
09465 }

const char* ast_get_switch_registrar ( struct ast_sw sw  ) 

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

09478 {
09479    return sw ? sw->registrar : NULL;
09480 }

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

References __ast_goto_if_exists().

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

09571 {
09572    return __ast_goto_if_exists(chan, context, exten, priority, 0);
09573 }

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

hashtable functions for contexts

Definition at line 994 of file pbx.c.

References ast_context::name.

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

00995 {
00996    const struct ast_context *ac = ah_a;
00997    const struct ast_context *bc = ah_b;
00998    if (!ac || !bc) /* safety valve, but it might prevent a crash you'd rather have happen */
00999       return 1;
01000    /* assume context names are registered in a string table! */
01001    return strcmp(ac->name, bc->name);
01002 }

unsigned int ast_hashtab_hash_contexts ( const void *  obj  ) 

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

01038 {
01039    const struct ast_context *ac = obj;
01040    return ast_hashtab_hash_string(ac->name);
01041 }

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

References ast_context_find(), ast_extension_match(), ast_context::ignorepats, ast_ignorepat::next, and ast_ignorepat::pattern.

Referenced by ast_app_dtget(), disa_exec(), dp_lookup(), dundi_lookup_local(), handle_enbloc_call_message(), handle_soft_key_event_message(), handle_stimulus_message(), mgcp_ss(), skinny_ss(), and ss_thread().

07268 {
07269    struct ast_context *con = ast_context_find(context);
07270    if (con) {
07271       struct ast_ignorepat *pat;
07272       for (pat = con->ignorepats; pat; pat = pat->next) {
07273          if (ast_extension_match(pat->pattern, pattern))
07274             return 1;
07275       }
07276    }
07277 
07278    return 0;
07279 }

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

References E_MATCHMORE, and pbx_extension_helper().

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

04164 {
04165    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0);
04166 }

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

References __ast_internal_context_destroy(), ast_exten::app, ast_add_extension_nolock(), ast_calloc, AST_EXTENSION_REMOVED, ast_free, ast_free_ptr(), ast_hashtab_destroy(), ast_hashtab_end_traversal(), ast_hashtab_next(), ast_hashtab_start_traversal(), ast_hint_extension_nolock(), AST_LIST_APPEND_LIST, AST_LIST_EMPTY, AST_LIST_HEAD_INIT_VALUE, AST_LIST_INSERT_HEAD, AST_LIST_REMOVE_HEAD, ast_log(), ast_rdlock_contexts(), AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_strdup, ast_tvdiff_us(), ast_tvnow(), ast_unlock_contexts(), ast_verb, ast_wrlock_contexts(), ast_wrlock_contexts_version(), ast_state_cb::callback, ast_hint::callbacks, context_merge(), contexts, contexts_table, ast_state_cb::data, ast_exten::data, E_MATCH, ast_exten::exten, ast_hint::exten, ast_hint::laststate, LOG_WARNING, ast_context::name, ast_context::next, ast_sw::next, ast_exten::parent, pbx_find_extension(), PRIORITY_HINT, ast_exten::registrar, and pbx_find_info::stacklen.

Referenced by lua_reload_extensions(), and pbx_load_module().

06624 {
06625    double ft;
06626    struct ast_context *tmp, *oldcontextslist;
06627    struct ast_hashtab *oldtable;
06628    struct store_hints store = AST_LIST_HEAD_INIT_VALUE;
06629    struct store_hint *this;
06630    struct ast_hint *hint;
06631    struct ast_exten *exten;
06632    int length;
06633    struct ast_state_cb *thiscb;
06634    struct ast_hashtab_iter *iter;
06635 
06636    /* it is very important that this function hold the hint list lock _and_ the conlock
06637       during its operation; not only do we need to ensure that the list of contexts
06638       and extensions does not change, but also that no hint callbacks (watchers) are
06639       added or removed during the merge/delete process
06640 
06641       in addition, the locks _must_ be taken in this order, because there are already
06642       other code paths that use this order
06643    */
06644 
06645    struct timeval begintime, writelocktime, endlocktime, enddeltime;
06646    int wrlock_ver;
06647 
06648    begintime = ast_tvnow();
06649    ast_rdlock_contexts();
06650    iter = ast_hashtab_start_traversal(contexts_table);
06651    while ((tmp = ast_hashtab_next(iter))) {
06652       context_merge(extcontexts, exttable, tmp, registrar);
06653    }
06654    ast_hashtab_end_traversal(iter);
06655    wrlock_ver = ast_wrlock_contexts_version();
06656 
06657    ast_unlock_contexts(); /* this feels real retarded, but you must do
06658                        what you must do If this isn't done, the following 
06659                         wrlock is a guraranteed deadlock */
06660    ast_wrlock_contexts();
06661    if (ast_wrlock_contexts_version() > wrlock_ver+1) {
06662       ast_log(LOG_WARNING,"==================!!!!!!!!!!!!!!!Something changed the contexts in the middle of merging contexts!\n");
06663    }
06664 
06665    AST_RWLIST_WRLOCK(&hints);
06666    writelocktime = ast_tvnow();
06667 
06668    /* preserve all watchers for hints */
06669    AST_RWLIST_TRAVERSE(&hints, hint, list) {
06670       if (!AST_LIST_EMPTY(&hint->callbacks)) {
06671          length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2 + sizeof(*this);
06672          if (!(this = ast_calloc(1, length)))
06673             continue;
06674          /* this removes all the callbacks from the hint into this. */
06675          AST_LIST_APPEND_LIST(&this->callbacks, &hint->callbacks, entry);
06676          this->laststate = hint->laststate;
06677          this->context = this->data;
06678          strcpy(this->data, hint->exten->parent->name);
06679          this->exten = this->data + strlen(this->context) + 1;
06680          strcpy(this->exten, hint->exten->exten);
06681          AST_LIST_INSERT_HEAD(&store, this, list);
06682       }
06683    }
06684 
06685    /* save the old table and list */
06686    oldtable = contexts_table;
06687    oldcontextslist = contexts;
06688 
06689    /* move in the new table and list */
06690    contexts_table = exttable;
06691    contexts = *extcontexts;
06692 
06693    /* restore the watchers for hints that can be found; notify those that
06694       cannot be restored
06695    */
06696    while ((this = AST_LIST_REMOVE_HEAD(&store, list))) {
06697       struct pbx_find_info q = { .stacklen = 0 };
06698       exten = pbx_find_extension(NULL, NULL, &q, this->context, this->exten, PRIORITY_HINT, NULL, "", E_MATCH);
06699       /* If this is a pattern, dynamically create a new extension for this
06700        * particular match.  Note that this will only happen once for each
06701        * individual extension, because the pattern will no longer match first.
06702        */
06703       if (exten && exten->exten[0] == '_') {
06704          ast_add_extension_nolock(exten->parent->name, 0, this->exten, PRIORITY_HINT, NULL,
06705             0, exten->app, ast_strdup(exten->data), ast_free_ptr, exten->registrar);
06706          /* rwlocks are not recursive locks */
06707          exten = ast_hint_extension_nolock(NULL, this->context, this->exten);
06708       }
06709 
06710       /* Find the hint in the list of hints */
06711       AST_RWLIST_TRAVERSE(&hints, hint, list) {
06712          if (hint->exten == exten)
06713             break;
06714       }
06715       if (!exten || !hint) {
06716          /* this hint has been removed, notify the watchers */
06717          while ((thiscb = AST_LIST_REMOVE_HEAD(&this->callbacks, entry))) {
06718             thiscb->callback(this->context, this->exten, AST_EXTENSION_REMOVED, thiscb->data);
06719             ast_free(thiscb);
06720          }
06721       } else {
06722          AST_LIST_APPEND_LIST(&hint->callbacks, &this->callbacks, entry);
06723          hint->laststate = this->laststate;
06724       }
06725       ast_free(this);
06726    }
06727 
06728    AST_RWLIST_UNLOCK(&hints);
06729    ast_unlock_contexts();
06730    endlocktime = ast_tvnow();
06731 
06732    /* the old list and hashtab no longer are relevant, delete them while the rest of asterisk
06733       is now freely using the new stuff instead */
06734 
06735    ast_hashtab_destroy(oldtable, NULL);
06736 
06737    for (tmp = oldcontextslist; tmp; ) {
06738       struct ast_context *next;  /* next starting point */
06739       next = tmp->next;
06740       __ast_internal_context_destroy(tmp);
06741       tmp = next;
06742    }
06743    enddeltime = ast_tvnow();
06744 
06745    ft = ast_tvdiff_us(writelocktime, begintime);
06746    ft /= 1000000.0;
06747    ast_verb(3,"Time to scan old dialplan and merge leftovers back into the new: %8.6f sec\n", ft);
06748 
06749    ft = ast_tvdiff_us(endlocktime, writelocktime);
06750    ft /= 1000000.0;
06751    ast_verb(3,"Time to restore hints and swap in new dialplan: %8.6f sec\n", ft);
06752 
06753    ft = ast_tvdiff_us(enddeltime, endlocktime);
06754    ft /= 1000000.0;
06755    ast_verb(3,"Time to delete the old dialplan: %8.6f sec\n", ft);
06756 
06757    ft = ast_tvdiff_us(enddeltime, begintime);
06758    ft /= 1000000.0;
06759    ast_verb(3,"Total time merge_contexts_delete: %8.6f sec\n", ft);
06760    return;
06761 }

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

09634 {
09635    return pbx_parseable_goto(chan, goto_string, 0);
09636 }

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

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

Definition at line 8106 of file pbx.c.

References __ast_request_and_dial(), ast_channel::_state, outgoing_helper::account, async_stat::app, app_tmp::app, async_stat::appdata, ast_calloc, ast_cdr_disposition(), ast_cdr_failed(), ast_cdr_setaccount(), ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_free, ast_hangup(), ast_log(), ast_pbx_outgoing_cdr_failed(), ast_pbx_run_app(), ast_pthread_create_detached, ast_set_variables(), AST_STATE_UP, ast_strlen_zero(), ast_variables_destroy(), ast_verb, async_wait(), ast_channel::cdr, async_stat::chan, app_tmp::chan, app_tmp::data, errno, ast_channel::hangupcause, LOG_WARNING, ast_channel::name, async_stat::p, app_tmp::t, async_stat::timeout, and outgoing_helper::vars.

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

08107 {
08108    struct ast_channel *chan;
08109    struct app_tmp *tmp;
08110    int res = -1, cdr_res = -1;
08111    struct outgoing_helper oh;
08112 
08113    memset(&oh, 0, sizeof(oh));
08114    oh.vars = vars;
08115    oh.account = account;
08116 
08117    if (locked_channel)
08118       *locked_channel = NULL;
08119    if (ast_strlen_zero(app)) {
08120       res = -1;
08121       goto outgoing_app_cleanup;
08122    }
08123    if (synchronous) {
08124       chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
08125       if (chan) {
08126          ast_set_variables(chan, vars);
08127          if (account)
08128             ast_cdr_setaccount(chan, account);
08129          if (chan->_state == AST_STATE_UP) {
08130             res = 0;
08131             ast_verb(4, "Channel %s was answered.\n", chan->name);
08132             tmp = ast_calloc(1, sizeof(*tmp));
08133             if (!tmp)
08134                res = -1;
08135             else {
08136                ast_copy_string(tmp->app, app, sizeof(tmp->app));
08137                if (appdata)
08138                   ast_copy_string(tmp->data, appdata, sizeof(tmp->data));
08139                tmp->chan = chan;
08140                if (synchronous > 1) {
08141                   if (locked_channel)
08142                      ast_channel_unlock(chan);
08143                   ast_pbx_run_app(tmp);
08144                } else {
08145                   if (locked_channel)
08146                      ast_channel_lock(chan);
08147                   if (ast_pthread_create_detached(&tmp->t, NULL, ast_pbx_run_app, tmp)) {
08148                      ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno));
08149                      ast_free(tmp);
08150                      if (locked_channel)
08151                         ast_channel_unlock(chan);
08152                      ast_hangup(chan);
08153                      res = -1;
08154                   } else {
08155                      if (locked_channel)
08156                         *locked_channel = chan;
08157                   }
08158                }
08159             }
08160          } else {
08161             ast_verb(4, "Channel %s was never answered.\n", chan->name);
08162             if (chan->cdr) { /* update the cdr */
08163                /* here we update the status of the call, which sould be busy.
08164                 * if that fails then we set the status to failed */
08165                if (ast_cdr_disposition(chan->cdr, chan->hangupcause))
08166                   ast_cdr_failed(chan->cdr);
08167             }
08168             ast_hangup(chan);
08169          }
08170       }
08171 
08172       if (res < 0) { /* the call failed for some reason */
08173          if (*reason == 0) { /* if the call failed (not busy or no answer)
08174                         * update the cdr with the failed message */
08175             cdr_res = ast_pbx_outgoing_cdr_failed();
08176             if (cdr_res != 0) {
08177                res = cdr_res;
08178                goto outgoing_app_cleanup;
08179             }
08180          }
08181       }
08182 
08183    } else {
08184       struct async_stat *as;
08185       if (!(as = ast_calloc(1, sizeof(*as)))) {
08186          res = -1;
08187          goto outgoing_app_cleanup;
08188       }
08189       chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
08190       if (!chan) {
08191          ast_free(as);
08192          res = -1;
08193          goto outgoing_app_cleanup;
08194       }
08195       as->chan = chan;
08196       ast_copy_string(as->app, app, sizeof(as->app));
08197       if (appdata)
08198          ast_copy_string(as->appdata,  appdata, sizeof(as->appdata));
08199       as->timeout = timeout;
08200       ast_set_variables(chan, vars);
08201       if (account)
08202          ast_cdr_setaccount(chan, account);
08203       /* Start a new thread, and get something handling this channel. */
08204       if (locked_channel)
08205          ast_channel_lock(chan);
08206       if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) {
08207          ast_log(LOG_WARNING, "Failed to start async wait\n");
08208          ast_free(as);
08209          if (locked_channel)
08210             ast_channel_unlock(chan);
08211          ast_hangup(chan);
08212          res = -1;
08213          goto outgoing_app_cleanup;
08214       } else {
08215          if (locked_channel)
08216             *locked_channel = chan;
08217       }
08218       res = 0;
08219    }
08220 outgoing_app_cleanup:
08221    ast_variables_destroy(vars);
08222    return res;
08223 }

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

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

Definition at line 7940 of file pbx.c.

References __ast_request_and_dial(), ast_channel::_state, outgoing_helper::account, ast_calloc, ast_cdr_disposition(), ast_cdr_failed(), ast_cdr_setaccount(), ast_channel_alloc, ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_exists_extension(), ast_free, ast_hangup(), ast_log(), ast_pbx_outgoing_cdr_failed(), ast_pbx_run(), ast_pbx_start(), ast_pthread_create_detached, ast_request_and_dial(), ast_set_variables(), AST_STATE_DOWN, AST_STATE_UP, ast_strlen_zero(), ast_variables_destroy(), ast_verb, async_wait(), ast_channel::cdr, async_stat::chan, outgoing_helper::cid_name, outgoing_helper::cid_num, async_stat::context, ast_channel::context, outgoing_helper::context, outgoing_helper::exten, ast_channel::hangupcause, LOG_ERROR, LOG_WARNING, ast_channel::name, async_stat::p, outgoing_helper::parent_channel, pbx_builtin_setvar_helper(), outgoing_helper::priority, set_ext_pri(), async_stat::timeout, and outgoing_helper::vars.

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

07941 {
07942    struct ast_channel *chan;
07943    struct async_stat *as;
07944    int res = -1, cdr_res = -1;
07945    struct outgoing_helper oh;
07946 
07947    if (synchronous) {
07948       oh.context = context;
07949       oh.exten = exten;
07950       oh.priority = priority;
07951       oh.cid_num = cid_num;
07952       oh.cid_name = cid_name;
07953       oh.account = account;
07954       oh.vars = vars;
07955       oh.parent_channel = NULL;
07956 
07957       chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
07958       if (channel) {
07959          *channel = chan;
07960          if (chan)
07961             ast_channel_lock(chan);
07962       }
07963       if (chan) {
07964          if (chan->_state == AST_STATE_UP) {
07965                res = 0;
07966             ast_verb(4, "Channel %s was answered.\n", chan->name);
07967 
07968             if (synchronous > 1) {
07969                if (channel)
07970                   ast_channel_unlock(chan);
07971                if (ast_pbx_run(chan)) {
07972                   ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name);
07973                   if (channel)
07974                      *channel = NULL;
07975                   ast_hangup(chan);
07976                   chan = NULL;
07977                   res = -1;
07978                }
07979             } else {
07980                if (ast_pbx_start(chan)) {
07981                   ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name);
07982                   if (channel) {
07983                      *channel = NULL;
07984                      ast_channel_unlock(chan);
07985                   }
07986                   ast_hangup(chan);
07987                   res = -1;
07988                }
07989                chan = NULL;
07990             }
07991          } else {
07992             ast_verb(4, "Channel %s was never answered.\n", chan->name);
07993 
07994             if (chan->cdr) { /* update the cdr */
07995                /* here we update the status of the call, which sould be busy.
07996                 * if that fails then we set the status to failed */
07997                if (ast_cdr_disposition(chan->cdr, chan->hangupcause))
07998                   ast_cdr_failed(chan->cdr);
07999             }
08000 
08001             if (channel) {
08002                *channel = NULL;
08003                ast_channel_unlock(chan);
08004             }
08005             ast_hangup(chan);
08006             chan = NULL;
08007          }
08008       }
08009 
08010       if (res < 0) { /* the call failed for some reason */
08011          if (*reason == 0) { /* if the call failed (not busy or no answer)
08012                         * update the cdr with the failed message */
08013             cdr_res = ast_pbx_outgoing_cdr_failed();
08014             if (cdr_res != 0) {
08015                res = cdr_res;
08016                goto outgoing_exten_cleanup;
08017             }
08018          }
08019 
08020          /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */
08021          /* check if "failed" exists */
08022          if (ast_exists_extension(chan, context, "failed", 1, NULL)) {
08023             chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "OutgoingSpoolFailed");
08024             if (chan) {
08025                char failed_reason[4] = "";
08026                if (!ast_strlen_zero(context))
08027                   ast_copy_string(chan->context, context, sizeof(chan->context));
08028                set_ext_pri(chan, "failed", 1);
08029                ast_set_variables(chan, vars);
08030                snprintf(failed_reason, sizeof(failed_reason), "%d", *reason);
08031                pbx_builtin_setvar_helper(chan, "REASON", failed_reason);
08032                if (account)
08033                   ast_cdr_setaccount(chan, account);
08034                if (ast_pbx_run(chan)) {
08035                   ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name);
08036                   ast_hangup(chan);
08037                }
08038                chan = NULL;
08039             }
08040          }
08041       }
08042    } else {
08043       if (!(as = ast_calloc(1, sizeof(*as)))) {
08044          res = -1;
08045          goto outgoing_exten_cleanup;
08046       }
08047       chan = ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name);
08048       if (channel) {
08049          *channel = chan;
08050          if (chan)
08051             ast_channel_lock(chan);
08052       }
08053       if (!chan) {
08054          ast_free(as);
08055          res = -1;
08056          goto outgoing_exten_cleanup;
08057       }
08058       as->chan = chan;
08059       ast_copy_string(as->context, context, sizeof(as->context));
08060       set_ext_pri(as->chan,  exten, priority);
08061       as->timeout = timeout;
08062       ast_set_variables(chan, vars);
08063       if (account)
08064          ast_cdr_setaccount(chan, account);
08065       if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) {
08066          ast_log(LOG_WARNING, "Failed to start async wait\n");
08067          ast_free(as);
08068          if (channel) {
08069             *channel = NULL;
08070             ast_channel_unlock(chan);
08071          }
08072          ast_hangup(chan);
08073          res = -1;
08074          goto outgoing_exten_cleanup;
08075       }
08076       res = 0;
08077    }
08078 outgoing_exten_cleanup:
08079    ast_variables_destroy(vars);
08080    return res;
08081 }

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

References ast_pbx_run_args().

Referenced by ast_pbx_outgoing_exten(), async_wait(), do_idle_thread(), mgcp_ss(), skinny_newcall(), ss_thread(), and unistim_ss().

04597 {
04598    return ast_pbx_run_args(c, NULL);
04599 }

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

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

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

04582 {
04583    enum ast_pbx_result res = AST_PBX_SUCCESS;
04584 
04585    if (increase_call_count(c)) {
04586       return AST_PBX_CALL_LIMIT;
04587    }
04588 
04589    res = __ast_pbx_run(c, args);
04590 
04591    decrease_call_count();
04592 
04593    return res;
04594 }

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

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

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

04560 {
04561    pthread_t t;
04562 
04563    if (!c) {
04564       ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
04565       return AST_PBX_FAILED;
04566    }
04567 
04568    if (increase_call_count(c))
04569       return AST_PBX_CALL_LIMIT;
04570 
04571    /* Start a new thread, and get something handling this channel. */
04572    if (ast_pthread_create_detached(&t, NULL, pbx_thread, c)) {
04573       ast_log(LOG_WARNING, "Failed to create new channel thread\n");
04574       decrease_call_count();
04575       return AST_PBX_FAILED;
04576    }
04577 
04578    return AST_PBX_SUCCESS;
04579 }

int ast_processed_calls ( void   ) 

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

Definition at line 4606 of file pbx.c.

References totalcalls.

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

04607 {
04608    return totalcalls;
04609 }

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

09372 {
09373    return ast_rwlock_rdlock(&con->lock);
09374 }

int ast_rdlock_contexts ( void   ) 
int ast_register_switch ( struct ast_switch sw  ) 

Register an alternative dialplan switch.

Parameters:
sw switch to register

This function registers a populated ast_switch structure with the asterisk switching architecture.

Return values:
0 success
non-zero failure

Definition at line 5157 of file pbx.c.

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

Referenced by load_module().

05158 {
05159    struct ast_switch *tmp;
05160 
05161    AST_RWLIST_WRLOCK(&switches);
05162    AST_RWLIST_TRAVERSE(&switches, tmp, list) {
05163       if (!strcasecmp(tmp->name, sw->name)) {
05164          AST_RWLIST_UNLOCK(&switches);
05165          ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name);
05166          return -1;
05167       }
05168    }
05169    AST_RWLIST_INSERT_TAIL(&switches, sw, list);
05170    AST_RWLIST_UNLOCK(&switches);
05171 
05172    return 0;
05173 }

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

04169 {
04170    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN, found, combined_find_spawn);
04171 }

void ast_str_substitute_variables ( struct ast_str **  buf,
size_t  maxlen,
struct ast_channel chan,
const char *  templ 
)

Definition at line 114 of file strings.c.

References ast_str_make_space(), first, and pbx_substitute_variables_helper_full().

Referenced by acf_odbc_read(), acf_odbc_write(), cli_odbc_read(), and cli_odbc_write().

00115 {
00116    int first = 1;
00117    do {
00118       ast_str_make_space(buf, maxlen ? maxlen :
00119          (first ? strlen(template) * 2 : (*buf)->__AST_STR_LEN * 2));
00120       pbx_substitute_variables_helper_full(chan, NULL, template, (*buf)->__AST_STR_STR, (*buf)->__AST_STR_LEN - 1, &((*buf)->__AST_STR_USED));
00121       first = 0;
00122    } while (maxlen == 0 && (*buf)->__AST_STR_LEN - 5 < (*buf)->__AST_STR_USED);
00123 }

int ast_unlock_context ( struct ast_context con  ) 
int ast_unlock_contexts ( void   ) 
void ast_unregister_switch ( struct ast_switch sw  ) 

Unregister an alternative switch.

Parameters:
sw switch to unregister

Unregisters a switch from asterisk.

Returns:
nothing

Definition at line 5175 of file pbx.c.

References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

Referenced by __unload_module(), and unload_module().

05176 {
05177    AST_RWLIST_WRLOCK(&switches);
05178    AST_RWLIST_REMOVE(&switches, sw, list);
05179    AST_RWLIST_UNLOCK(&switches);
05180 }

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

Definition at line 9490 of file pbx.c.

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

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

09492 {
09493    if (!exten)
09494       return con ? con->root : NULL;
09495    else
09496       return exten->next;
09497 }

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

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

09525 {
09526    if (!ip)
09527       return con ? con->ignorepats : NULL;
09528    else
09529       return ip->next;
09530 }

struct ast_include* ast_walk_context_includes ( struct ast_context con,
struct ast_include inc 
) [read]
struct ast_sw* ast_walk_context_switches ( struct ast_context con,
struct ast_sw sw 
) [read]

Definition at line 9499 of file pbx.c.

References ast_context::alts, AST_LIST_FIRST, and AST_LIST_NEXT.

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

09501 {
09502    if (!sw)
09503       return con ? AST_LIST_FIRST(&con->alts) : NULL;
09504    else
09505       return AST_LIST_NEXT(sw, list);
09506 }

struct ast_context* ast_walk_contexts ( struct ast_context con  )  [read]
struct ast_exten* ast_walk_extension_priorities ( struct ast_exten exten,
struct ast_exten priority 
) [read]
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 9366 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().

09367 {
09368    return ast_rwlock_wrlock(&con->lock);
09369 }

int ast_wrlock_contexts ( void   ) 

Write locks the context list.

Return values:
0 on success
-1 on error

Definition at line 9345 of file pbx.c.

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

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

09346 {
09347    int res = ast_rwlock_wrlock(&conlock);
09348    if (!res)
09349       ast_atomic_fetchadd_int(&conlock_wrlock_version, 1);
09350    return res;
09351 }

int ast_wrlock_contexts_version ( void   ) 

Definition at line 9337 of file pbx.c.

References conlock_wrlock_version.

Referenced by ast_merge_contexts_and_delete().

09338 {
09339    return conlock_wrlock_version;
09340 }

void pbx_builtin_clear_globals ( void   ) 

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

09183 {
09184    struct ast_var_t *vardata;
09185 
09186    ast_rwlock_wrlock(&globalslock);
09187    while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries)))
09188       ast_var_delete(vardata);
09189    ast_rwlock_unlock(&globalslock);
09190 }

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

References ast_channel_lock, ast_channel_unlock, AST_LIST_TRAVERSE, ast_rwlock_rdlock(), ast_rwlock_unlock(), ast_var_name(), ast_var_value(), globals, globalslock, and ast_channel::varshead.

Referenced by __ast_pbx_run(), _macro_exec(), _while_exec(), agent_hangup(), agent_read(), agentmonitoroutgoing_exec(), array(), ast_bridge_call(), ast_call_forward(), ast_eivr_getvariable(), ast_monitor_stop(), bridge_play_sounds(), builtin_atxfer(), builtin_automixmonitor(), builtin_automonitor(), check_goto_on_transfer(), common_exec(), conf_exec(), conf_run(), confbridge_exec(), dahdi_call(), dahdi_hangup(), dial_exec_full(), do_forward(), do_timelimit(), dundi_exec(), dundi_helper(), feature_interpret(), find_by_mark(), find_conf_realtime(), findparkinglotname(), get_also_info(), get_index(), get_refer_info(), global_read(), hash_read(), iax2_call(), iax2_exec(), import_ch(), leave_voicemail(), listfilter(), local_attended_transfer(), local_hangup(), local_read(), login_exec(), macro_fixup(), minivm_delete_exec(), minivm_notify_exec(), misdn_answer(), misdn_hangup(), morsecode_exec(), notify_new_message(), oh323_call(), oh323_hangup(), park_call_full(), park_space_reserve(), pbx_builtin_background(), queue_exec(), real_ctx(), retrydial_exec(), ring_entry(), run_agi(), set_config_flags(), set_local_info(), sip_addheader(), sla_trunk_exec(), speech_background(), try_calling(), try_suggested_sip_codec(), update_bridge_vars(), and wait_for_answer().

08952 {
08953    struct ast_var_t *variables;
08954    const char *ret = NULL;
08955    int i;
08956    struct varshead *places[2] = { NULL, &globals };
08957 
08958    if (!name)
08959       return NULL;
08960 
08961    if (chan) {
08962       ast_channel_lock(chan);
08963       places[0] = &chan->varshead;
08964    }
08965 
08966    for (i = 0; i < 2; i++) {
08967       if (!places[i])
08968          continue;
08969       if (places[i] == &globals)
08970          ast_rwlock_rdlock(&globalslock);
08971       AST_LIST_TRAVERSE(places[i], variables, entries) {
08972          if (!strcmp(name, ast_var_name(variables))) {
08973             ret = ast_var_value(variables);
08974             break;
08975          }
08976       }
08977       if (places[i] == &globals)
08978          ast_rwlock_unlock(&globalslock);
08979       if (ret)
08980          break;
08981    }
08982 
08983    if (chan)
08984       ast_channel_unlock(chan);
08985 
08986    return ret;
08987 }

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 8989 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_var_assign(), ast_verb, globals, globalslock, LOG_WARNING, and ast_channel::varshead.

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

08990 {
08991    struct ast_var_t *newvariable;
08992    struct varshead *headp;
08993 
08994    if (name[strlen(name)-1] == ')') {
08995       char *function = ast_strdupa(name);
08996 
08997       ast_log(LOG_WARNING, "Cannot push a value onto a function\n");
08998       ast_func_write(chan, function, value);
08999       return;
09000    }
09001 
09002    if (chan) {
09003       ast_channel_lock(chan);
09004       headp = &chan->varshead;
09005    } else {
09006       ast_rwlock_wrlock(&globalslock);
09007       headp = &globals;
09008    }
09009 
09010    if (value) {
09011       if (headp == &globals)
09012          ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value);
09013       newvariable = ast_var_assign(name, value);
09014       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
09015    }
09016 
09017    if (chan)
09018       ast_channel_unlock(chan);
09019    else
09020       ast_rwlock_unlock(&globalslock);
09021 }

int pbx_builtin_raise_exception ( struct ast_channel chan,
void *  data 
)

Definition at line 2995 of file pbx.c.

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

Referenced by __ast_pbx_run().

02996 {
02997    const char *reason = vreason;
02998    struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL);
02999    struct pbx_exception *exception = NULL;
03000 
03001    if (!ds) {
03002       ds = ast_datastore_alloc(&exception_store_info, NULL);
03003       if (!ds)
03004          return -1;
03005       exception = ast_calloc(1, sizeof(struct pbx_exception));
03006       if (!exception) {
03007          ast_datastore_free(ds);
03008          return -1;
03009       }
03010       if (ast_string_field_init(exception, 128)) {
03011          ast_free(exception);
03012          ast_datastore_free(ds);
03013          return -1;
03014       }
03015       ds->data = exception;
03016       ast_channel_datastore_add(chan, ds);
03017    } else
03018       exception = ds->data;
03019 
03020    ast_string_field_set(exception, reason, reason);
03021    ast_string_field_set(exception, context, chan->context);
03022    ast_string_field_set(exception, exten, chan->exten);
03023    exception->priority = chan->priority;
03024    set_ext_pri(chan, "e", 0);
03025    return 0;
03026 }

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
See also:
ast_str_create).
Note:
Will lock the channel.

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

08921 {
08922    struct ast_var_t *variables;
08923    const char *var, *val;
08924    int total = 0;
08925 
08926    if (!chan)
08927       return 0;
08928 
08929    ast_str_reset(*buf);
08930 
08931    ast_channel_lock(chan);
08932 
08933    AST_LIST_TRAVERSE(&chan->varshead, variables, entries) {
08934       if ((var = ast_var_name(variables)) && (val = ast_var_value(variables))
08935          /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */
08936          ) {
08937          if (ast_str_append(buf, 0, "%s=%s\n", var, val) < 0) {
08938             ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
08939             break;
08940          } else
08941             total++;
08942       } else
08943          break;
08944    }
08945 
08946    ast_channel_unlock(chan);
08947 
08948    return total;
08949 }

int pbx_builtin_setvar ( struct ast_channel chan,
void *  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 9081 of file pbx.c.

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

Referenced by ast_compile_ael2(), and rpt_exec().

09082 {
09083    char *name, *value, *mydata;
09084 
09085    if (ast_compat_app_set) {
09086       return pbx_builtin_setvar_multiple(chan, data);
09087    }
09088 
09089    if (ast_strlen_zero(data)) {
09090       ast_log(LOG_WARNING, "Set requires one variable name/value pair.\n");
09091       return 0;
09092    }
09093 
09094    mydata = ast_strdupa(data);
09095    name = strsep(&mydata, "=");
09096    value = mydata;
09097    if (strchr(name, ' '))
09098       ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, mydata);
09099 
09100    pbx_builtin_setvar_helper(chan, name, value);
09101    return(0);
09102 }

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

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

Note:
Will lock the channel. May also be used to set a channel dialplan function to a particular value.
See also:
ast_func_write

Definition at line 9023 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_var_assign(), ast_var_delete(), ast_var_name(), ast_verb, EVENT_FLAG_DIALPLAN, globals, globalslock, manager_event, ast_channel::name, ast_channel::uniqueid, and ast_channel::varshead.

Referenced by __ast_pbx_run(), __oh323_new(), _macro_exec(), _while_exec(), acf_curl_exec(), acf_fetch(), acf_odbc_read(), acf_odbc_write(), acf_transaction_write(), action_atxfer(), action_setvar(), admin_exec(), agi_exec_full(), aji_status_exec(), aqm_exec(), array(), ast_bridge_call(), ast_eivr_setvariable(), ast_iax2_new(), ast_monitor_start(), ast_pbx_outgoing_exten(), ast_rtp_set_vars(), ast_set_variables(), asyncgoto_exec(), background_detect_exec(), bridge_exec(), bridge_play_sounds(), builtin_atxfer(), builtin_automixmonitor(), builtin_automonitor(), builtin_blindtransfer(), cb_events(), chanavail_exec(), channel_spy(), commit_exec(), conf_run(), controlplayback_exec(), count_exec(), dahdi_handle_dtmfup(), dahdi_new(), dial_exec_full(), disa_exec(), do_waiting(), end_bridge_callback(), export_aoc_vars(), export_ch(), feature_request_and_dial(), frame_set_var(), function_db_delete(), function_db_exists(), function_db_read(), function_realtime_store(), get_rdnis(), get_refer_info(), global_write(), gosub_release_frame(), handle_request_bye(), handle_request_refer(), handle_set_chanvar(), handle_set_global(), handle_setvariable(), hash_read(), hash_write(), isAnsweringMachine(), leave_voicemail(), local_hangup(), lua_set_variable(), lua_set_variable_value(), macro_fixup(), manage_parkinglot(), minivm_accmess_exec(), minivm_delete_exec(), minivm_greet_exec(), minivm_notify_exec(), minivm_record_exec(), misdn_call(), mixmonitor_exec(), originate_exec(), ospauth_exec(), ospfinished_exec(), osplookup_exec(), ospnext_exec(), park_exec_full(), parse_moved_contact(), pbx_builtin_background(), pbx_builtin_importvar(), pbx_builtin_setvar(), pbx_builtin_setvar_multiple(), pbx_load_config(), phase_e_handler(), play_message_datetime(), playback_exec(), pqm_exec(), prep_email_sub_vars(), pri_dchannel(), privacy_exec(), process_ast_dsp(), read_exec(), readexten_exec(), readfile_exec(), realtimefield_read(), record_exec(), return_exec(), rollback_exec(), rotate_file(), rpt_exec(), rqm_exec(), sendimage_exec(), sendtext_exec(), sendurl_exec(), set(), set_agentbycallerid(), set_queue_result(), 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(), ss_thread(), start_monitor_exec(), system_exec_helper(), transfer_exec(), transmit(), tryexec_exec(), update_bridge_vars(), update_qe_rule(), upqm_exec(), vm_box_exists(), vm_exec(), vmauthenticate(), waituntil_exec(), and zapateller_exec().

09024 {
09025    struct ast_var_t *newvariable;
09026    struct varshead *headp;
09027    const char *nametail = name;
09028 
09029    if (name[strlen(name) - 1] == ')') {
09030       char *function = ast_strdupa(name);
09031 
09032       ast_func_write(chan, function, value);
09033       return;
09034    }
09035 
09036    if (chan) {
09037       ast_channel_lock(chan);
09038       headp = &chan->varshead;
09039    } else {
09040       ast_rwlock_wrlock(&globalslock);
09041       headp = &globals;
09042    }
09043 
09044    /* For comparison purposes, we have to strip leading underscores */
09045    if (*nametail == '_') {
09046       nametail++;
09047       if (*nametail == '_')
09048          nametail++;
09049    }
09050 
09051    AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) {
09052       if (strcasecmp(ast_var_name(newvariable), nametail) == 0) {
09053          /* there is already such a variable, delete it */
09054          AST_LIST_REMOVE_CURRENT(entries);
09055          ast_var_delete(newvariable);
09056          break;
09057       }
09058    }
09059    AST_LIST_TRAVERSE_SAFE_END;
09060 
09061    if (value) {
09062       if (headp == &globals)
09063          ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value);
09064       newvariable = ast_var_assign(name, value);
09065       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
09066       manager_event(EVENT_FLAG_DIALPLAN, "VarSet",
09067          "Channel: %s\r\n"
09068          "Variable: %s\r\n"
09069          "Value: %s\r\n"
09070          "Uniqueid: %s\r\n",
09071          chan ? chan->name : "none", name, value,
09072          chan ? chan->uniqueid : "none");
09073    }
09074 
09075    if (chan)
09076       ast_channel_unlock(chan);
09077    else
09078       ast_rwlock_unlock(&globalslock);
09079 }

int pbx_builtin_setvar_multiple ( struct ast_channel chan,
void *  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 9104 of file pbx.c.

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

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

09105 {
09106    char *data;
09107    int x;
09108    AST_DECLARE_APP_ARGS(args,
09109       AST_APP_ARG(pair)[24];
09110    );
09111    AST_DECLARE_APP_ARGS(pair,
09112       AST_APP_ARG(name);
09113       AST_APP_ARG(value);
09114    );
09115 
09116    if (ast_strlen_zero(vdata)) {
09117       ast_log(LOG_WARNING, "MSet requires at least one variable name/value pair.\n");
09118       return 0;
09119    }
09120 
09121    data = ast_strdupa(vdata);
09122    AST_STANDARD_APP_ARGS(args, data);
09123 
09124    for (x = 0; x < args.argc; x++) {
09125       AST_NONSTANDARD_APP_ARGS(pair, args.pair[x], '=');
09126       if (pair.argc == 2) {
09127          pbx_builtin_setvar_helper(chan, pair.name, pair.value);
09128          if (strchr(pair.name, ' '))
09129             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);
09130       } else if (!chan) {
09131          ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '='\n", pair.name);
09132       } else {
09133          ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '=' (in %s@%s:%d\n", pair.name, chan->exten, chan->context, chan->priority);
09134       }
09135    }
09136 
09137    return 0;
09138 }

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

References ast_strlen_zero().

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

09193 {
09194    int res;
09195    if (ast_strlen_zero(condition)) {                /* NULL or empty strings are false */
09196       return 0;
09197    } else if (sscanf(condition, "%30d", &res) == 1) { /* Numbers are evaluated for truth */
09198       return res;
09199    } else {                                         /* Strings are true */
09200       return 1;
09201    }
09202 }

int pbx_exec ( struct ast_channel c,
struct ast_app app,
void *  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 1322 of file pbx.c.

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

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

01325 {
01326    int res;
01327    struct ast_module_user *u = NULL;
01328    const char *saved_c_appl;
01329    const char *saved_c_data;
01330 
01331    if (c->cdr && !ast_check_hangup(c))
01332       ast_cdr_setapp(c->cdr, app->name, data);
01333 
01334    /* save channel values */
01335    saved_c_appl= c->appl;
01336    saved_c_data= c->data;
01337 
01338    c->appl = app->name;
01339    c->data = data;
01340    if (app->module)
01341       u = __ast_module_user_add(app->module, c);
01342    if (strcasecmp(app->name, "system") && !ast_strlen_zero(data) &&
01343          strchr(data, '|') && !strchr(data, ',') && !ast_opt_dont_warn) {
01344       ast_log(LOG_WARNING, "The application delimiter is now the comma, not "
01345          "the pipe.  Did you forget to convert your dialplan?  (%s(%s))\n",
01346          app->name, (char *) data);
01347    }
01348    res = app->execute(c, S_OR((char *) data, ""));
01349    if (app->module && u)
01350       __ast_module_user_remove(app->module, u);
01351    /* restore channel values */
01352    c->appl = saved_c_appl;
01353    c->data = saved_c_data;
01354    return res;
01355 }

struct ast_exten* pbx_find_extension ( struct ast_channel chan,
struct ast_context bypass,
struct pbx_find_info q,
const char *  context,
const char *  exten,
int  priority,
const char *  label,
const char *  callerid,
enum ext_match_t  action 
) [read]

Definition at line 2469 of file pbx.c.

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

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

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

struct ast_app* pbx_findapp ( const char *  app  )  [read]

Look up an application.

Parameters:
app name of the app

This function searches for the ast_app structure within the apps that are registered for the one with the name you passed in.

Returns:
the ast_app structure that matches on success, or NULL on failure

Definition at line 1363 of file pbx.c.

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

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

01364 {
01365    struct ast_app *tmp;
01366 
01367    AST_RWLIST_RDLOCK(&apps);
01368    AST_RWLIST_TRAVERSE(&apps, tmp, list) {
01369       if (!strcasecmp(tmp->name, app))
01370          break;
01371    }
01372    AST_RWLIST_UNLOCK(&apps);
01373 
01374    return tmp;
01375 }

void pbx_retrieve_variable ( struct ast_channel c,
const char *  var,
char **  ret,
char *  workspace,
int  workspacelen,
struct varshead headp 
)

Retrieve the value of a builtin variable or variable from the channel variable stack.

Note:
Will lock the channel.

Retrieve the value of a builtin variable or variable from the channel variable stack.

Note:
See also

Definition at line 2867 of file pbx.c.

References ARRAY_LEN, ast_channel_lock, ast_channel_unlock, ast_config_AST_SYSTEM_NAME, ast_copy_string(), ast_eid_default, ast_eid_to_str(), ast_get_hint(), AST_LIST_TRAVERSE, ast_rwlock_rdlock(), ast_rwlock_unlock(), ast_var_name(), ast_var_value(), ast_channel::cid, ast_callerid::cid_ani2, ast_callerid::cid_pres, ast_callerid::cid_tns, ast_callerid::cid_ton, ast_channel::context, ast_var_t::entries, ast_channel::exten, globals, globalslock, ast_channel::hangupcause, ast_channel::name, parse_variable_name(), ast_channel::priority, s, substring(), ast_channel::uniqueid, and ast_channel::varshead.

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

02868 {
02869    const char not_found = '\0';
02870    char *tmpvar;
02871    const char *s; /* the result */
02872    int offset, length;
02873    int i, need_substring;
02874    struct varshead *places[2] = { headp, &globals };  /* list of places where we may look */
02875 
02876    if (c) {
02877       ast_channel_lock(c);
02878       places[0] = &c->varshead;
02879    }
02880    /*
02881     * Make a copy of var because parse_variable_name() modifies the string.
02882     * Then if called directly, we might need to run substring() on the result;
02883     * remember this for later in 'need_substring', 'offset' and 'length'
02884     */
02885    tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */
02886    need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */);
02887 
02888    /*
02889     * Look first into predefined variables, then into variable lists.
02890     * Variable 's' points to the result, according to the following rules:
02891     * s == &not_found (set at the beginning) means that we did not find a
02892     * matching variable and need to look into more places.
02893     * If s != &not_found, s is a valid result string as follows:
02894     * s = NULL if the variable does not have a value;
02895     * you typically do this when looking for an unset predefined variable.
02896     * s = workspace if the result has been assembled there;
02897     * typically done when the result is built e.g. with an snprintf(),
02898     * so we don't need to do an additional copy.
02899     * s != workspace in case we have a string, that needs to be copied
02900     * (the ast_copy_string is done once for all at the end).
02901     * Typically done when the result is already available in some string.
02902     */
02903    s = &not_found;   /* default value */
02904    if (c) { /* This group requires a valid channel */
02905       /* Names with common parts are looked up a piece at a time using strncmp. */
02906       if (!strncmp(var, "CALL", 4)) {
02907          if (!strncmp(var + 4, "ING", 3)) {
02908             if (!strcmp(var + 7, "PRES")) {        /* CALLINGPRES */
02909                snprintf(workspace, workspacelen, "%d", c->cid.cid_pres);
02910                s = workspace;
02911             } else if (!strcmp(var + 7, "ANI2")) {    /* CALLINGANI2 */
02912                snprintf(workspace, workspacelen, "%d", c->cid.cid_ani2);
02913                s = workspace;
02914             } else if (!strcmp(var + 7, "TON")) {     /* CALLINGTON */
02915                snprintf(workspace, workspacelen, "%d", c->cid.cid_ton);
02916                s = workspace;
02917             } else if (!strcmp(var + 7, "TNS")) {     /* CALLINGTNS */
02918                snprintf(workspace, workspacelen, "%d", c->cid.cid_tns);
02919                s = workspace;
02920             }
02921          }
02922       } else if (!strcmp(var, "HINT")) {
02923          s = ast_get_hint(workspace, workspacelen, NULL, 0, c, c->context, c->exten) ? workspace : NULL;
02924       } else if (!strcmp(var, "HINTNAME")) {
02925          s = ast_get_hint(NULL, 0, workspace, workspacelen, c, c->context, c->exten) ? workspace : NULL;
02926       } else if (!strcmp(var, "EXTEN")) {
02927          s = c->exten;
02928       } else if (!strcmp(var, "CONTEXT")) {
02929          s = c->context;
02930       } else if (!strcmp(var, "PRIORITY")) {
02931          snprintf(workspace, workspacelen, "%d", c->priority);
02932          s = workspace;
02933       } else if (!strcmp(var, "CHANNEL")) {
02934          s = c->name;
02935       } else if (!strcmp(var, "UNIQUEID")) {
02936          s = c->uniqueid;
02937       } else if (!strcmp(var, "HANGUPCAUSE")) {
02938          snprintf(workspace, workspacelen, "%d", c->hangupcause);
02939          s = workspace;
02940       }
02941    }
02942    if (s == &not_found) { /* look for more */
02943       if (!strcmp(var, "EPOCH")) {
02944          snprintf(workspace, workspacelen, "%u",(int)time(NULL));
02945          s = workspace;
02946       } else if (!strcmp(var, "SYSTEMNAME")) {
02947          s = ast_config_AST_SYSTEM_NAME;
02948       } else if (!strcmp(var, "ENTITYID")) {
02949          ast_eid_to_str(workspace, workspacelen, &ast_eid_default);
02950          s = workspace;
02951       }
02952    }
02953    /* if not found, look into chanvars or global vars */
02954    for (i = 0; s == &not_found && i < ARRAY_LEN(places); i++) {
02955       struct ast_var_t *variables;
02956       if (!places[i])
02957          continue;
02958       if (places[i] == &globals)
02959          ast_rwlock_rdlock(&globalslock);
02960       AST_LIST_TRAVERSE(places[i], variables, entries) {
02961          if (!strcasecmp(ast_var_name(variables), var)) {
02962             s = ast_var_value(variables);
02963             break;
02964          }
02965       }
02966       if (places[i] == &globals)
02967          ast_rwlock_unlock(&globalslock);
02968    }
02969    if (s == &not_found || s == NULL)
02970       *ret = NULL;
02971    else {
02972       if (s != workspace)
02973          ast_copy_string(workspace, s, workspacelen);
02974       *ret = workspace;
02975       if (need_substring)
02976          *ret = substring(*ret, offset, length, workspace, workspacelen);
02977    }
02978 
02979    if (c)
02980       ast_channel_unlock(c);
02981 }

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

References autofallthrough.

Referenced by pbx_load_module().

04612 {
04613    int oldval = autofallthrough;
04614    autofallthrough = newval;
04615    return oldval;
04616 }

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

References extenpatternmatchnew.

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

04619 {
04620    int oldval = extenpatternmatchnew;
04621    extenpatternmatchnew = newval;
04622    return oldval;
04623 }

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

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

Referenced by pbx_load_module().

04626 {
04627    if (overrideswitch) {
04628       ast_free(overrideswitch);
04629    }
04630    if (!ast_strlen_zero(newval)) {
04631       overrideswitch = ast_strdup(newval);
04632    } else {
04633       overrideswitch = NULL;
04634    }
04635 }

void pbx_substitute_variables_helper ( struct ast_channel c,
const char *  cp1,
char *  cp2,
int  count 
)
void pbx_substitute_variables_helper_full ( struct ast_channel c,
struct varshead headp,
const char *  cp1,
char *  cp2,
int  cp2_size,
size_t *  used 
)

Definition at line 3403 of file pbx.c.

References ast_channel_alloc, ast_channel_free(), ast_copy_string(), ast_debug, 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 ast_str_substitute_variables(), pbx_substitute_variables_helper(), pbx_substitute_variables_helper_full(), and pbx_substitute_variables_varshead().

03404 {
03405    /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!!  */
03406    char *cp4;
03407    const char *tmp, *whereweare, *orig_cp2 = cp2;
03408    int length, offset, offset2, isfunction;
03409    char *workspace = NULL;
03410    char *ltmp = NULL, *var = NULL;
03411    char *nextvar, *nextexp, *nextthing;
03412    char *vars, *vare;
03413    int pos, brackets, needsub, len;
03414 
03415    *cp2 = 0; /* just in case nothing ends up there */
03416    whereweare=tmp=cp1;
03417    while (!ast_strlen_zero(whereweare) && count) {
03418       /* Assume we're copying the whole remaining string */
03419       pos = strlen(whereweare);
03420       nextvar = NULL;
03421       nextexp = NULL;
03422       nextthing = strchr(whereweare, '$');
03423       if (nextthing) {
03424          switch (nextthing[1]) {
03425          case '{':
03426             nextvar = nextthing;
03427             pos = nextvar - whereweare;
03428             break;
03429          case '[':
03430             nextexp = nextthing;
03431             pos = nextexp - whereweare;
03432             break;
03433          default:
03434             pos = 1;
03435          }
03436       }
03437 
03438       if (pos) {
03439          /* Can't copy more than 'count' bytes */
03440          if (pos > count)
03441             pos = count;
03442 
03443          /* Copy that many bytes */
03444          memcpy(cp2, whereweare, pos);
03445 
03446          count -= pos;
03447          cp2 += pos;
03448          whereweare += pos;
03449          *cp2 = 0;
03450       }
03451 
03452       if (nextvar) {
03453          /* We have a variable.  Find the start and end, and determine
03454             if we are going to have to recursively call ourselves on the
03455             contents */
03456          vars = vare = nextvar + 2;
03457          brackets = 1;
03458          needsub = 0;
03459 
03460          /* Find the end of it */
03461          while (brackets && *vare) {
03462             if ((vare[0] == '$') && (vare[1] == '{')) {
03463                needsub++;
03464             } else if (vare[0] == '{') {
03465                brackets++;
03466             } else if (vare[0] == '}') {
03467                brackets--;
03468             } else if ((vare[0] == '$') && (vare[1] == '['))
03469                needsub++;
03470             vare++;
03471          }
03472          if (brackets)
03473             ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n");
03474          len = vare - vars - 1;
03475 
03476          /* Skip totally over variable string */
03477          whereweare += (len + 3);
03478 
03479          if (!var)
03480             var = alloca(VAR_BUF_SIZE);
03481 
03482          /* Store variable name (and truncate) */
03483          ast_copy_string(var, vars, len + 1);
03484 
03485          /* Substitute if necessary */
03486          if (needsub) {
03487             size_t used;
03488             if (!ltmp)
03489                ltmp = alloca(VAR_BUF_SIZE);
03490 
03491             pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used);
03492             vars = ltmp;
03493          } else {
03494             vars = var;
03495          }
03496 
03497          if (!workspace)
03498             workspace = alloca(VAR_BUF_SIZE);
03499 
03500          workspace[0] = '\0';
03501 
03502          parse_variable_name(vars, &offset, &offset2, &isfunction);
03503          if (isfunction) {
03504             /* Evaluate function */
03505             if (c || !headp)
03506                cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
03507             else {
03508                struct varshead old;
03509                struct ast_channel *bogus = ast_channel_alloc(0, 0, "", "", "", "", "", 0, "Bogus/%p", vars);
03510                if (bogus) {
03511                   memcpy(&old, &bogus->varshead, sizeof(old));
03512                   memcpy(&bogus->varshead, headp, sizeof(bogus->varshead));
03513                   cp4 = ast_func_read(bogus, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
03514                   /* Don't deallocate the varshead that was passed in */
03515                   memcpy(&bogus->varshead, &old, sizeof(bogus->varshead));
03516                   ast_channel_free(bogus);
03517                } else
03518                   ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution.  Function results may be blank.\n");
03519             }
03520             ast_debug(2, "Function result is '%s'\n", cp4 ? cp4 : "(null)");
03521          } else {
03522             /* Retrieve variable value */
03523             pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp);
03524          }
03525          if (cp4) {
03526             cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE);
03527 
03528             length = strlen(cp4);
03529             if (length > count)
03530                length = count;
03531             memcpy(cp2, cp4, length);
03532             count -= length;
03533             cp2 += length;
03534             *cp2 = 0;
03535          }
03536       } else if (nextexp) {
03537          /* We have an expression.  Find the start and end, and determine
03538             if we are going to have to recursively call ourselves on the
03539             contents */
03540          vars = vare = nextexp + 2;
03541          brackets = 1;
03542          needsub = 0;
03543 
03544          /* Find the end of it */
03545          while (brackets && *vare) {
03546             if ((vare[0] == '$') && (vare[1] == '[')) {
03547                needsub++;
03548                brackets++;
03549                vare++;
03550             } else if (vare[0] == '[') {
03551                brackets++;
03552             } else if (vare[0] == ']') {
03553                brackets--;
03554             } else if ((vare[0] == '$') && (vare[1] == '{')) {
03555                needsub++;
03556                vare++;
03557             }
03558             vare++;
03559          }
03560          if (brackets)
03561             ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n");
03562          len = vare - vars - 1;
03563 
03564          /* Skip totally over expression */
03565          whereweare += (len + 3);
03566 
03567          if (!var)
03568             var = alloca(VAR_BUF_SIZE);
03569 
03570          /* Store variable name (and truncate) */
03571          ast_copy_string(var, vars, len + 1);
03572 
03573          /* Substitute if necessary */
03574          if (needsub) {
03575             size_t used;
03576             if (!ltmp)
03577                ltmp = alloca(VAR_BUF_SIZE);
03578 
03579             pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used);
03580             vars = ltmp;
03581          } else {
03582             vars = var;
03583          }
03584 
03585          length = ast_expr(vars, cp2, count, c);
03586 
03587          if (length) {
03588             ast_debug(1, "Expression result is '%s'\n", cp2);
03589             count -= length;
03590             cp2 += length;
03591             *cp2 = 0;
03592          }
03593       }
03594    }
03595    *used = cp2 - orig_cp2;
03596 }

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

Definition at line 3604 of file pbx.c.

References pbx_substitute_variables_helper_full().

Referenced by add_user_extension(), build_user_routes(), do_say(), dundi_lookup_local(), loopback_subst(), phoneprov_callback(), pp_each_extension_exec(), and pp_each_user_exec().

03605 {
03606    size_t used;
03607    pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count, &used);
03608 }


Generated by  doxygen 1.6.2