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

Go to the source code of this file.
Data Structures | |
| struct | ast_custom_function |
| Data structure associated with a custom dialplan function. More... | |
| struct | ast_pbx |
| struct | ast_pbx_args |
| Options for ast_pbx_run(). More... | |
| struct | ast_switch |
| struct | ast_timing |
| struct | pbx_find_info |
Defines | |
| #define | ast_custom_function_register(acf) __ast_custom_function_register(acf, ast_module_info->self) |
| Register a custom function. | |
| #define | AST_MAX_APP 32 |
| #define | AST_PBX_GOTO_FAILED -3 |
| #define | AST_PBX_KEEP 0 |
| #define | AST_PBX_MAX_STACK 128 |
| #define | AST_PBX_REPLACE 1 |
| #define | PRIORITY_HINT -1 |
| #define | STATUS_NO_CONTEXT 1 |
| #define | STATUS_NO_EXTENSION 2 |
| #define | STATUS_NO_LABEL 4 |
| #define | STATUS_NO_PRIORITY 3 |
| #define | STATUS_SUCCESS 5 |
| #define | AST_PBX_ERROR 1 |
| #define | AST_PBX_HANGUP -1 |
| Special return values from applications to the PBX. | |
| #define | AST_PBX_INCOMPLETE 12 |
| #define | AST_PBX_OK 0 |
Typedefs | |
| typedef int(* | ast_state_cb_type )(char *context, char *id, enum ast_extension_states state, void *data) |
| Typedef for devicestate and hint callbacks. | |
| typedef int( | ast_switch_f )(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) |
| All switch functions have the same interface, so define a type for them. | |
Enumerations | |
| enum | ast_extension_states { AST_EXTENSION_REMOVED = -2, AST_EXTENSION_DEACTIVATED = -1, AST_EXTENSION_NOT_INUSE = 0, AST_EXTENSION_INUSE = 1 << 0, AST_EXTENSION_BUSY = 1 << 1, AST_EXTENSION_UNAVAILABLE = 1 << 2, AST_EXTENSION_RINGING = 1 << 3, AST_EXTENSION_ONHOLD = 1 << 4 } |
| Extension states. More... | |
| enum | ast_pbx_result { AST_PBX_SUCCESS = 0, AST_PBX_FAILED = -1, AST_PBX_CALL_LIMIT = -2 } |
| The result codes when starting the PBX on a channel with ast_pbx_start. More... | |
| enum | ext_match_t { E_MATCHMORE = 0x00, E_CANMATCH = 0x01, E_MATCH = 0x02, E_MATCH_MASK = 0x03, E_SPAWN = 0x12, E_FINDLABEL = 0x22, E_MATCHMORE = 0x00, E_CANMATCH = 0x01, E_MATCH = 0x02, E_MATCH_MASK = 0x03, E_SPAWN = 0x12, E_FINDLABEL = 0x22 } |
Functions | |
| int | __ast_custom_function_register (struct ast_custom_function *acf, struct ast_module *mod) |
| Register a custom function. | |
| int | ast_active_calls (void) |
| Retrieve the number of active calls. | |
| int | ast_add_extension (const char *context, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar) |
| Add and extension to an extension context. | |
| int | ast_add_extension2 (struct ast_context *con, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar) |
| Add an extension to an extension context, this time with an ast_context *. | |
| int | ast_async_goto (struct ast_channel *chan, const char *context, const char *exten, int priority) |
| Set the channel to next execute the specified dialplan location. | |
| int | ast_async_goto_by_name (const char *chan, const char *context, const char *exten, int priority) |
| Set the channel to next execute the specified dialplan location. | |
| int | ast_async_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority) |
| int | ast_async_parseable_goto (struct ast_channel *chan, const char *goto_string) |
| int | ast_build_timing (struct ast_timing *i, const char *info) |
| Construct a timing bitmap, for use in time-based conditionals. | |
| int | ast_canmatch_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid) |
| Looks for a valid matching extension. | |
| int | ast_check_timing (const struct ast_timing *i) |
| Evaluate a pre-constructed bitmap as to whether the current time falls within the range specified. | |
| char * | ast_complete_applications (const char *line, const char *word, int state) |
| Command completion for the list of installed applications. | |
| int | ast_context_add_ignorepat (const char *context, const char *ignorepat, const char *registrar) |
| Add an ignorepat. | |
| int | ast_context_add_ignorepat2 (struct ast_context *con, const char *ignorepat, const char *registrar) |
| int | ast_context_add_include (const char *context, const char *include, const char *registrar) |
| Add a context include. | |
| int | ast_context_add_include2 (struct ast_context *con, const char *include, const char *registrar) |
| Add a context include. | |
| int | ast_context_add_switch (const char *context, const char *sw, const char *data, int eval, const char *registrar) |
| Add a switch. | |
| int | ast_context_add_switch2 (struct ast_context *con, const char *sw, const char *data, int eval, const char *registrar) |
| Adds a switch (first param is a ast_context). | |
| void | ast_context_destroy (struct ast_context *con, const char *registrar) |
| Destroy a context (matches the specified context (or ANY context if NULL). | |
| struct ast_context * | ast_context_find (const char *name) |
| Find a context. | |
| struct ast_context * | ast_context_find_or_create (struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *name, const char *registrar) |
| Register a new context or find an existing one. | |
| 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_function * | ast_custom_function_find (const char *name) |
| int | ast_custom_function_unregister (struct ast_custom_function *acf) |
| Unregister a custom function. | |
| int | ast_destroy_timing (struct ast_timing *i) |
| Deallocates memory structures associated with a timing bitmap. | |
| enum ast_extension_states | ast_devstate_to_extenstate (enum ast_device_state devstate) |
| Map devstate to an extension state. | |
| int | ast_exists_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid) |
| Determine whether an extension exists. | |
| int | ast_explicit_goto (struct ast_channel *chan, const char *context, const char *exten, int priority) |
| int | ast_extension_close (const char *pattern, const char *data, int needmore) |
| int | ast_extension_cmp (const char *a, const char *b) |
| Determine if one extension should match before another. | |
| int | ast_extension_match (const char *pattern, const char *extension) |
| Determine if a given extension matches a given pattern (in NXX format). | |
| int | ast_extension_patmatch (const char *pattern, const char *data) |
| int | ast_extension_state (struct ast_channel *c, const char *context, const char *exten) |
| Uses hint and devicestate callback to get the state of an extension. | |
| const char * | ast_extension_state2str (int extension_state) |
| Return string representation of the state of an extension. | |
| int | ast_extension_state_add (const char *context, const char *exten, ast_state_cb_type callback, void *data) |
| Registers a state change callback. | |
| int | ast_extension_state_del (int id, ast_state_cb_type callback) |
| Deletes a registered state change callback by ID. | |
| int | ast_findlabel_extension (struct ast_channel *c, const char *context, const char *exten, const char *label, const char *callerid) |
| Find the priority of an extension that has the specified label. | |
| int | ast_findlabel_extension2 (struct ast_channel *c, struct ast_context *con, const char *exten, const char *label, const char *callerid) |
| Find the priority of an extension that has the specified label. | |
| int | ast_func_read (struct ast_channel *chan, const char *function, char *workspace, size_t len) |
| executes a read operation on a function | |
| int | ast_func_read2 (struct ast_channel *chan, const char *function, struct ast_str **str, ssize_t maxlen) |
| executes a read operation on a function | |
| int | ast_func_write (struct ast_channel *chan, const char *function, const char *value) |
| executes a write operation on a function | |
| int | ast_get_hint (char *hint, int hintsize, char *name, int namesize, struct ast_channel *c, const char *context, const char *exten) |
| If an extension hint exists, return non-zero. | |
| int | ast_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority) |
| int | ast_ignore_pattern (const char *context, const char *pattern) |
| Checks to see if a number should be ignored. | |
| int | ast_matchmore_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid) |
| Looks to see if adding anything to this extension might match something. (exists ^ canmatch). | |
| void | ast_merge_contexts_and_delete (struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *registrar) |
| Merge the temporary contexts into a global contexts list and delete from the global list the ones that are being added. | |
| int | ast_parseable_goto (struct ast_channel *chan, const char *goto_string) |
| int | ast_pbx_outgoing_app (const char *type, int format, void *data, int timeout, const char *app, const char *appdata, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel) |
| int | ast_pbx_outgoing_exten (const char *type, int format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel) |
| enum ast_pbx_result | ast_pbx_run (struct ast_channel *c) |
| Execute the PBX in the current thread. | |
| enum ast_pbx_result | ast_pbx_run_args (struct ast_channel *c, struct ast_pbx_args *args) |
| Execute the PBX in the current thread. | |
| enum ast_pbx_result | ast_pbx_start (struct ast_channel *c) |
| Create a new thread and start the PBX. | |
| int | ast_processed_calls (void) |
| Retrieve the total number of calls processed through the PBX since last restart. | |
| int | ast_rdlock_context (struct ast_context *con) |
| Read locks a given context. | |
| int | ast_rdlock_contexts (void) |
| Read locks the context list. | |
| int | ast_register_switch (struct ast_switch *sw) |
| Register an alternative dialplan switch. | |
| int | ast_spawn_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid, int *found, int combined_find_spawn) |
| Launch a new extension (i.e. new stack). | |
| int | ast_str_get_hint (struct ast_str **hint, ssize_t hintsize, struct ast_str **name, ssize_t namesize, struct ast_channel *c, const char *context, const char *exten) |
| If an extension hint exists, return non-zero. | |
| int | ast_unlock_context (struct ast_context *con) |
| int | ast_unlock_contexts (void) |
| Unlocks contexts. | |
| void | ast_unregister_switch (struct ast_switch *sw) |
| Unregister an alternative switch. | |
| int | ast_wrlock_context (struct ast_context *con) |
| Write locks a given context. | |
| int | ast_wrlock_contexts (void) |
| Write locks the context list. | |
| int | ast_wrlock_contexts_version (void) |
| void | pbx_builtin_clear_globals (void) |
| const char * | pbx_builtin_getvar_helper (struct ast_channel *chan, const char *name) |
| Return a pointer to the value of the corresponding channel variable. | |
| void | pbx_builtin_pushvar_helper (struct ast_channel *chan, const char *name, const char *value) |
| Add a variable to the channel variable stack, without removing any previously set value. | |
| int | pbx_builtin_raise_exception (struct ast_channel *chan, const char *data) |
| int | pbx_builtin_serialize_variables (struct ast_channel *chan, struct ast_str **buf) |
| Create a human-readable string, specifying all variables and their corresponding values. | |
| int | pbx_builtin_setvar (struct ast_channel *chan, const char *data) |
| Parse and set a single channel variable, where the name and value are separated with an '=' character. | |
| void | pbx_builtin_setvar_helper (struct ast_channel *chan, const char *name, const char *value) |
| Add a variable to the channel variable stack, removing the most recently set value for the same name. | |
| int | pbx_builtin_setvar_multiple (struct ast_channel *chan, const char *data) |
| Parse and set multiple channel variables, where the pairs are separated by the ',' character, and name and value are separated with an '=' character. | |
| int | pbx_checkcondition (const char *condition) |
| Evaluate a condition. | |
| int | pbx_exec (struct ast_channel *c, struct ast_app *app, const char *data) |
| Execute an application. | |
| struct ast_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) |
| struct ast_app * | pbx_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) |
| const char * | ast_get_context_name (struct ast_context *con) |
| struct ast_context * | ast_get_extension_context (struct ast_exten *exten) |
| const char * | ast_get_extension_name (struct ast_exten *exten) |
| const char * | ast_get_ignorepat_name (struct ast_ignorepat *ip) |
| const char * | ast_get_include_name (struct ast_include *include) |
| const char * | ast_get_switch_data (struct ast_sw *sw) |
| int | ast_get_switch_eval (struct ast_sw *sw) |
| const char * | ast_get_switch_name (struct ast_sw *sw) |
Registrar info functions ... | |
| const char * | ast_get_context_registrar (struct ast_context *c) |
| const char * | ast_get_extension_registrar (struct ast_exten *e) |
| const char * | ast_get_ignorepat_registrar (struct ast_ignorepat *ip) |
| const char * | ast_get_include_registrar (struct ast_include *i) |
| const char * | ast_get_switch_registrar (struct ast_sw *sw) |
Other Extension stuff | |
| const char * | ast_get_extension_app (struct ast_exten *e) |
| void * | ast_get_extension_app_data (struct ast_exten *e) |
| const char * | ast_get_extension_cidmatch (struct ast_exten *e) |
| const char * | ast_get_extension_label (struct ast_exten *e) |
| int | ast_get_extension_matchcid (struct ast_exten *e) |
| int | ast_get_extension_priority (struct ast_exten *exten) |
| int | ast_hashtab_compare_contexts (const void *ah_a, const void *ah_b) |
| hashtable functions for contexts | |
| unsigned int | ast_hashtab_hash_contexts (const void *obj) |
Substitution routines, using dynamic string buffers | |
| const char * | ast_str_retrieve_variable (struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, struct varshead *headp, const char *var) |
| void | ast_str_substitute_variables (struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, const char *templ) |
| void | ast_str_substitute_variables_full (struct ast_str **buf, ssize_t maxlen, struct ast_channel *c, struct varshead *headp, const char *templ, size_t *used) |
| void | ast_str_substitute_variables_varshead (struct ast_str **buf, ssize_t maxlen, struct varshead *headp, const char *templ) |
Walking functions ... | |
| struct ast_exten * | ast_walk_context_extensions (struct ast_context *con, struct ast_exten *priority) |
| struct ast_ignorepat * | ast_walk_context_ignorepats (struct ast_context *con, struct ast_ignorepat *ip) |
| struct ast_include * | ast_walk_context_includes (struct ast_context *con, struct ast_include *inc) |
| struct ast_sw * | ast_walk_context_switches (struct ast_context *con, struct ast_sw *sw) |
| struct ast_context * | ast_walk_contexts (struct ast_context *con) |
| struct ast_exten * | ast_walk_extension_priorities (struct ast_exten *exten, struct ast_exten *priority) |
Substitution routines, using static string buffers | |
| void | pbx_substitute_variables_helper (struct ast_channel *c, const char *cp1, char *cp2, int count) |
| void | pbx_substitute_variables_helper_full (struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int cp2_size, size_t *used) |
| void | pbx_substitute_variables_varshead (struct varshead *headp, const char *cp1, char *cp2, int count) |
Definition in file pbx.h.
| #define ast_custom_function_register | ( | acf | ) | __ast_custom_function_register(acf, ast_module_info->self) |
Register a custom function.
Definition at line 1108 of file pbx.h.
Referenced by load_module(), and reload().
| #define AST_MAX_APP 32 |
Max length of an application
Definition at line 37 of file pbx.h.
Referenced by destroy_station(), handle_show_function(), print_app_docs(), and sla_build_station().
| #define AST_PBX_ERROR 1 |
| #define AST_PBX_GOTO_FAILED -3 |
| #define AST_PBX_HANGUP -1 |
| #define AST_PBX_INCOMPLETE 12 |
Return to PBX matching, allowing more digits for the extension
Definition at line 48 of file pbx.h.
Referenced by __ast_pbx_run(), dial_exec_full(), pbx_builtin_incomplete(), and retrydial_exec().
| #define PRIORITY_HINT -1 |
Special Priority for a hint
Definition at line 51 of file pbx.h.
Referenced by add_extensions(), add_pri_lockopt(), ast_add_extension2_lockopt(), ast_hint_extension_nolock(), ast_merge_contexts_and_delete(), destroy_exten(), destroy_station(), handle_cli_dialplan_add_extension(), handle_cli_dialplan_remove_extension(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), park_add_hints(), pbx_load_config(), print_ext(), and sla_build_station().
| typedef int(* ast_state_cb_type)(char *context, char *id, enum ast_extension_states state, void *data) |
| typedef int( ast_switch_f)(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) |
| enum ast_extension_states |
Extension states.
| AST_EXTENSION_REMOVED | Extension removed |
| AST_EXTENSION_DEACTIVATED | Extension hint removed |
| AST_EXTENSION_NOT_INUSE | No device INUSE or BUSY |
| AST_EXTENSION_INUSE | One or more devices INUSE |
| AST_EXTENSION_BUSY | All devices BUSY |
| AST_EXTENSION_UNAVAILABLE | All devices UNAVAILABLE/UNREGISTERED |
| AST_EXTENSION_RINGING | All devices RINGING |
| AST_EXTENSION_ONHOLD | All devices ONHOLD |
Definition at line 58 of file pbx.h.
00058 { 00059 AST_EXTENSION_REMOVED = -2, /*!< Extension removed */ 00060 AST_EXTENSION_DEACTIVATED = -1, /*!< Extension hint removed */ 00061 AST_EXTENSION_NOT_INUSE = 0, /*!< No device INUSE or BUSY */ 00062 AST_EXTENSION_INUSE = 1 << 0, /*!< One or more devices INUSE */ 00063 AST_EXTENSION_BUSY = 1 << 1, /*!< All devices BUSY */ 00064 AST_EXTENSION_UNAVAILABLE = 1 << 2, /*!< All devices UNAVAILABLE/UNREGISTERED */ 00065 AST_EXTENSION_RINGING = 1 << 3, /*!< All devices RINGING */ 00066 AST_EXTENSION_ONHOLD = 1 << 4, /*!< All devices ONHOLD */ 00067 };
| enum ast_pbx_result |
The result codes when starting the PBX on a channel with ast_pbx_start.
Definition at line 276 of file pbx.h.
00276 { 00277 AST_PBX_SUCCESS = 0, 00278 AST_PBX_FAILED = -1, 00279 AST_PBX_CALL_LIMIT = -2, 00280 };
| enum ext_match_t |
When looking up extensions, we can have different requests identified by the 'action' argument, as follows.
| E_MATCHMORE | |
| E_CANMATCH | |
| E_MATCH | |
| E_MATCH_MASK | |
| E_SPAWN | |
| E_FINDLABEL | |
| E_MATCHMORE | |
| E_CANMATCH | |
| E_MATCH | |
| E_MATCH_MASK | |
| E_SPAWN | |
| E_FINDLABEL |
Definition at line 1177 of file pbx.h.
01177 { 01178 E_MATCHMORE = 0x00, /* extension can match but only with more 'digits' */ 01179 E_CANMATCH = 0x01, /* extension can match with or without more 'digits' */ 01180 E_MATCH = 0x02, /* extension is an exact match */ 01181 E_MATCH_MASK = 0x03, /* mask for the argument to extension_match_core() */ 01182 E_SPAWN = 0x12, /* want to spawn an extension. Requires exact match */ 01183 E_FINDLABEL = 0x22 /* returns the priority for a given label. Requires exact match */ 01184 };
| int __ast_custom_function_register | ( | struct ast_custom_function * | acf, | |
| struct ast_module * | mod | |||
| ) |
Register a custom function.
Definition at line 3358 of file pbx.c.
References acf_retrieve_docs(), ast_custom_function::acflist, ast_log(), AST_RWLIST_INSERT_BEFORE_CURRENT, AST_RWLIST_INSERT_TAIL, AST_RWLIST_TRAVERSE, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, AST_STATIC_DOC, ast_verb, COLOR_BRCYAN, ast_custom_function::docsrc, LOG_ERROR, ast_custom_function::mod, ast_custom_function::name, and term_color().
Referenced by load_pbx().
03359 { 03360 struct ast_custom_function *cur; 03361 char tmps[80]; 03362 03363 if (!acf) { 03364 return -1; 03365 } 03366 03367 acf->mod = mod; 03368 #ifdef AST_XML_DOCS 03369 acf->docsrc = AST_STATIC_DOC; 03370 #endif 03371 03372 if (acf_retrieve_docs(acf)) { 03373 return -1; 03374 } 03375 03376 AST_RWLIST_WRLOCK(&acf_root); 03377 03378 AST_RWLIST_TRAVERSE(&acf_root, cur, acflist) { 03379 if (!strcmp(acf->name, cur->name)) { 03380 ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name); 03381 AST_RWLIST_UNLOCK(&acf_root); 03382 return -1; 03383 } 03384 } 03385 03386 /* Store in alphabetical order */ 03387 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) { 03388 if (strcasecmp(acf->name, cur->name) < 0) { 03389 AST_RWLIST_INSERT_BEFORE_CURRENT(acf, acflist); 03390 break; 03391 } 03392 } 03393 AST_RWLIST_TRAVERSE_SAFE_END; 03394 03395 if (!cur) { 03396 AST_RWLIST_INSERT_TAIL(&acf_root, acf, acflist); 03397 } 03398 03399 AST_RWLIST_UNLOCK(&acf_root); 03400 03401 ast_verb(2, "Registered custom function '%s'\n", term_color(tmps, acf->name, COLOR_BRCYAN, 0, sizeof(tmps))); 03402 03403 return 0; 03404 }
| int ast_active_calls | ( | void | ) |
Retrieve the number of active calls.
Definition at line 4934 of file pbx.c.
References countcalls.
Referenced by ast_var_Config(), handle_chanlist(), handle_showcalls(), and sysinfo_helper().
04935 { 04936 return countcalls; 04937 }
| int ast_add_extension | ( | const char * | context, | |
| int | replace, | |||
| const char * | extension, | |||
| int | priority, | |||
| const char * | label, | |||
| const char * | callerid, | |||
| const char * | application, | |||
| void * | data, | |||
| void(*)(void *) | datad, | |||
| const char * | registrar | |||
| ) |
Add and extension to an extension context.
| 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 |
| 0 | success | |
| -1 | failure |
Definition at line 7590 of file pbx.c.
References ast_add_extension2(), ast_unlock_contexts(), and find_context_locked().
Referenced by ast_extension_state_add(), handle_cli_dialplan_add_extension(), park_add_hints(), register_exten(), register_peer_exten(), and RegisterExtension().
07593 { 07594 int ret = -1; 07595 struct ast_context *c = find_context_locked(context); 07596 07597 if (c) { 07598 ret = ast_add_extension2(c, replace, extension, priority, label, callerid, 07599 application, data, datad, registrar); 07600 ast_unlock_contexts(); 07601 } 07602 07603 return ret; 07604 }
| int ast_add_extension2 | ( | struct ast_context * | con, | |
| int | replace, | |||
| const char * | extension, | |||
| int | priority, | |||
| const char * | label, | |||
| const char * | callerid, | |||
| const char * | application, | |||
| void * | data, | |||
| void(*)(void *) | datad, | |||
| const char * | registrar | |||
| ) |
Add an extension to an extension context, this time with an ast_context *.
We sort extensions in order of matching preference, so that we can stop the search as soon as we find a suitable match. This ordering also takes care of wildcards such as '.' (meaning "one or more of any character") and '!' (which is 'earlymatch', meaning "zero or more of any character" but also impacts the return value from CANMATCH and EARLYMATCH.
The extension match rules defined in the devmeeting 2006.05.05 are quite simple: WE SELECT THE LONGEST MATCH. In detail, "longest" means the number of matched characters in the extension. In case of ties (e.g. _XXX and 333) in the length of a pattern, we give priority to entries with the smallest cardinality (e.g, [5-9] comes before [2-8] before the former has only 5 elements, while the latter has 7, etc. In case of same cardinality, the first element in the range counts. If we still have a tie, any final '!' will make this as a possibly less specific pattern.
EBUSY - can't lock EEXIST - extension with the same priority exist and no replace is set
Definition at line 7911 of file pbx.c.
References ast_add_extension2_lockopt().
Referenced by add_extensions(), ast_add_extension(), build_parkinglot(), context_merge(), load_config(), load_module(), manage_parkinglot(), park_call_full(), pbx_load_config(), pbx_load_users(), sla_build_station(), and sla_build_trunk().
07915 { 07916 return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid, application, data, datad, registrar, 1, 1); 07917 }
| int ast_async_goto | ( | struct ast_channel * | chan, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority | |||
| ) |
Set the channel to next execute the specified dialplan location.
Definition at line 7629 of file pbx.c.
References ast_channel::_state, ast_channel::accountcode, ast_channel::amaflags, ast_cdr_discard(), ast_cdr_dup(), ast_channel_alloc, ast_channel_lock, ast_channel_masquerade(), ast_channel_unlock, ast_do_masquerade(), ast_explicit_goto(), ast_hangup(), ast_log(), ast_pbx_start(), AST_SOFTHANGUP_ASYNCGOTO, ast_softhangup_nolock(), ast_channel::cdr, ast_channel::context, ast_channel::exten, ast_channel::linkedid, LOG_WARNING, ast_channel::name, ast_channel::pbx, ast_channel::readformat, S_OR, and ast_channel::writeformat.
Referenced by __ast_goto_if_exists(), action_redirect(), ast_async_goto_by_name(), builtin_blindtransfer(), change_t38_state(), console_transfer(), dahdi_handle_dtmfup(), handle_request_bye(), handle_request_refer(), my_handle_dtmfup(), pbx_parseable_goto(), process_ast_dsp(), and socket_process().
07630 { 07631 int res = 0; 07632 07633 ast_channel_lock(chan); 07634 07635 if (chan->pbx) { /* This channel is currently in the PBX */ 07636 ast_explicit_goto(chan, context, exten, priority + 1); 07637 ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO); 07638 } else { 07639 /* In order to do it when the channel doesn't really exist within 07640 the PBX, we have to make a new channel, masquerade, and start the PBX 07641 at the new location */ 07642 struct ast_channel *tmpchan = ast_channel_alloc(0, chan->_state, 0, 0, chan->accountcode, chan->exten, chan->context, chan->linkedid, chan->amaflags, "AsyncGoto/%s", chan->name); 07643 if (!tmpchan) { 07644 res = -1; 07645 } else { 07646 if (chan->cdr) { 07647 ast_cdr_discard(tmpchan->cdr); 07648 tmpchan->cdr = ast_cdr_dup(chan->cdr); /* share the love */ 07649 } 07650 /* Make formats okay */ 07651 tmpchan->readformat = chan->readformat; 07652 tmpchan->writeformat = chan->writeformat; 07653 /* Setup proper location */ 07654 ast_explicit_goto(tmpchan, 07655 S_OR(context, chan->context), S_OR(exten, chan->exten), priority); 07656 07657 /* Masquerade into temp channel */ 07658 if (ast_channel_masquerade(tmpchan, chan)) { 07659 /* Failed to set up the masquerade. It's probably chan_local 07660 * in the middle of optimizing itself out. Sad. :( */ 07661 ast_hangup(tmpchan); 07662 tmpchan = NULL; 07663 res = -1; 07664 } else { 07665 /* it may appear odd to unlock chan here since the masquerade is on 07666 * tmpchan, but no channel locks should be held when doing a masquerade 07667 * since a masquerade requires a lock on the channels ao2 container. */ 07668 ast_channel_unlock(chan); 07669 ast_do_masquerade(tmpchan); 07670 ast_channel_lock(chan); 07671 /* Start the PBX going on our stolen channel */ 07672 if (ast_pbx_start(tmpchan)) { 07673 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name); 07674 ast_hangup(tmpchan); 07675 res = -1; 07676 } 07677 } 07678 } 07679 } 07680 ast_channel_unlock(chan); 07681 return res; 07682 }
| int ast_async_goto_by_name | ( | const char * | chan, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority | |||
| ) |
Set the channel to next execute the specified dialplan location.
Definition at line 7684 of file pbx.c.
References ast_async_goto(), ast_channel_get_by_name(), and ast_channel_unref.
07685 { 07686 struct ast_channel *chan; 07687 int res = -1; 07688 07689 if ((chan = ast_channel_get_by_name(channame))) { 07690 res = ast_async_goto(chan, context, exten, priority); 07691 chan = ast_channel_unref(chan); 07692 } 07693 07694 return res; 07695 }
| int ast_async_goto_if_exists | ( | struct ast_channel * | chan, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority | |||
| ) |
Definition at line 9847 of file pbx.c.
References __ast_goto_if_exists().
09848 { 09849 return __ast_goto_if_exists(chan, context, exten, priority, 1); 09850 }
| int ast_async_parseable_goto | ( | struct ast_channel * | chan, | |
| const char * | goto_string | |||
| ) |
Definition at line 9910 of file pbx.c.
References pbx_parseable_goto().
Referenced by asyncgoto_exec(), and handle_redirect().
09911 { 09912 return pbx_parseable_goto(chan, goto_string, 1); 09913 }
| int ast_build_timing | ( | struct ast_timing * | i, | |
| const char * | info | |||
| ) |
Construct a timing bitmap, for use in time-based conditionals.
| 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. |
| Returns | 1 on success or 0 on failure. |
Definition at line 7224 of file pbx.c.
References ast_strdup, ast_strdupa, ast_strlen_zero(), ast_timing::daymask, days, ast_timing::dowmask, get_range(), get_timerange(), ast_timing::monthmask, months, strsep(), and ast_timing::timezone.
Referenced by ast_context_add_include2(), iftime(), pbx_builtin_execiftime(), and pbx_builtin_gotoiftime().
07225 { 07226 char *info_save, *info; 07227 int j, num_fields, last_sep = -1; 07228 07229 /* Check for empty just in case */ 07230 if (ast_strlen_zero(info_in)) { 07231 return 0; 07232 } 07233 07234 /* make a copy just in case we were passed a static string */ 07235 info_save = info = ast_strdupa(info_in); 07236 07237 /* count the number of fields in the timespec */ 07238 for (j = 0, num_fields = 1; info[j] != '\0'; j++) { 07239 if (info[j] == ',') { 07240 last_sep = j; 07241 num_fields++; 07242 } 07243 } 07244 07245 /* save the timezone, if it is specified */ 07246 if (num_fields == 5) { 07247 i->timezone = ast_strdup(info + last_sep + 1); 07248 } else { 07249 i->timezone = NULL; 07250 } 07251 07252 /* Assume everything except time */ 07253 i->monthmask = 0xfff; /* 12 bits */ 07254 i->daymask = 0x7fffffffU; /* 31 bits */ 07255 i->dowmask = 0x7f; /* 7 bits */ 07256 /* on each call, use strsep() to move info to the next argument */ 07257 get_timerange(i, strsep(&info, "|,")); 07258 if (info) 07259 i->dowmask = get_range(strsep(&info, "|,"), 7, days, "day of week"); 07260 if (info) 07261 i->daymask = get_range(strsep(&info, "|,"), 31, NULL, "day"); 07262 if (info) 07263 i->monthmask = get_range(strsep(&info, "|,"), 12, months, "month"); 07264 return 1; 07265 }
| int ast_canmatch_extension | ( | struct ast_channel * | c, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority, | |||
| const char * | callerid | |||
| ) |
Looks for a valid matching extension.
| 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 |
Definition at line 4495 of file pbx.c.
References E_CANMATCH, and pbx_extension_helper().
Referenced by __analog_ss_thread(), analog_ss_thread(), background_detect_exec(), cb_events(), do_immediate_setup(), dp_lookup(), dundi_lookup_local(), get_also_info(), get_destination(), handle_link_data(), handle_link_phone_dtmf(), leave_voicemail(), local_dtmf_helper(), loopback_canmatch(), mgcp_ss(), phone_check_exception(), skinny_ss(), and valid_exit().
04496 { 04497 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0); 04498 }
| int ast_check_timing | ( | const struct ast_timing * | i | ) |
Evaluate a pre-constructed bitmap as to whether the current time falls within the range specified.
| i | Pointer to an ast_timing structure. |
| Returns | 1, if the time matches or 0, if the current time falls outside of the specified range. |
Definition at line 7267 of file pbx.c.
References ast_localtime(), ast_log(), ast_tvnow(), ast_timing::daymask, ast_timing::dowmask, LOG_WARNING, ast_timing::minmask, ast_timing::monthmask, ast_timing::timezone, ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, and ast_tm::tm_wday.
Referenced by iftime(), include_valid(), pbx_builtin_execiftime(), and pbx_builtin_gotoiftime().
07268 { 07269 struct ast_tm tm; 07270 struct timeval now = ast_tvnow(); 07271 07272 ast_localtime(&now, &tm, i->timezone); 07273 07274 /* If it's not the right month, return */ 07275 if (!(i->monthmask & (1 << tm.tm_mon))) 07276 return 0; 07277 07278 /* If it's not that time of the month.... */ 07279 /* Warning, tm_mday has range 1..31! */ 07280 if (!(i->daymask & (1 << (tm.tm_mday-1)))) 07281 return 0; 07282 07283 /* If it's not the right day of the week */ 07284 if (!(i->dowmask & (1 << tm.tm_wday))) 07285 return 0; 07286 07287 /* Sanity check the hour just to be safe */ 07288 if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) { 07289 ast_log(LOG_WARNING, "Insane time...\n"); 07290 return 0; 07291 } 07292 07293 /* Now the tough part, we calculate if it fits 07294 in the right time based on min/hour */ 07295 if (!(i->minmask[tm.tm_hour * 2 + (tm.tm_min >= 30 ? 1 : 0)] & (1 << (tm.tm_min >= 30 ? tm.tm_min - 30 : tm.tm_min)))) 07296 return 0; 07297 07298 /* If we got this far, then we're good */ 07299 return 1; 07300 }
| char* ast_complete_applications | ( | const char * | line, | |
| const char * | word, | |||
| int | state | |||
| ) |
Command completion for the list of installed applications.
This can be called from a CLI command completion function that wants to complete from the list of available applications.
Definition at line 9915 of file pbx.c.
References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strdup, and ast_app::name.
Referenced by handle_orig(), and handle_show_application().
09916 { 09917 struct ast_app *app = NULL; 09918 int which = 0; 09919 char *ret = NULL; 09920 size_t wordlen = strlen(word); 09921 09922 AST_RWLIST_RDLOCK(&apps); 09923 AST_RWLIST_TRAVERSE(&apps, app, list) { 09924 if (!strncasecmp(word, app->name, wordlen) && ++which > state) { 09925 ret = ast_strdup(app->name); 09926 break; 09927 } 09928 } 09929 AST_RWLIST_UNLOCK(&apps); 09930 09931 return ret; 09932 }
| int ast_context_add_ignorepat | ( | const char * | context, | |
| const char * | ignorepat, | |||
| const char * | registrar | |||
| ) |
Add an ignorepat.
| context | which context to add the ignorpattern to | |
| ignorepat | ignorepattern to set up for the extension | |
| registrar | registrar of the ignore pattern |
| 0 | on success | |
| -1 | on failure |
Definition at line 7502 of file pbx.c.
References ast_context_add_ignorepat2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_add_ignorepat().
07503 { 07504 int ret = -1; 07505 struct ast_context *c = find_context_locked(context); 07506 07507 if (c) { 07508 ret = ast_context_add_ignorepat2(c, value, registrar); 07509 ast_unlock_contexts(); 07510 } 07511 return ret; 07512 }
| int ast_context_add_ignorepat2 | ( | struct ast_context * | con, | |
| const char * | ignorepat, | |||
| const char * | registrar | |||
| ) |
Definition at line 7514 of file pbx.c.
References ast_calloc, ast_unlock_context(), ast_wrlock_context(), errno, ast_context::ignorepats, ast_ignorepat::next, ast_ignorepat::pattern, and ast_ignorepat::registrar.
Referenced by ast_compile_ael2(), ast_context_add_ignorepat(), context_merge_incls_swits_igps_other_registrars(), and pbx_load_config().
07515 { 07516 struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL; 07517 int length; 07518 char *pattern; 07519 length = sizeof(struct ast_ignorepat); 07520 length += strlen(value) + 1; 07521 if (!(ignorepat = ast_calloc(1, length))) 07522 return -1; 07523 /* The cast to char * is because we need to write the initial value. 07524 * The field is not supposed to be modified otherwise. Also, gcc 4.2 07525 * sees the cast as dereferencing a type-punned pointer and warns about 07526 * it. This is the workaround (we're telling gcc, yes, that's really 07527 * what we wanted to do). 07528 */ 07529 pattern = (char *) ignorepat->pattern; 07530 strcpy(pattern, value); 07531 ignorepat->next = NULL; 07532 ignorepat->registrar = registrar; 07533 ast_wrlock_context(con); 07534 for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) { 07535 ignorepatl = ignorepatc; 07536 if (!strcasecmp(ignorepatc->pattern, value)) { 07537 /* Already there */ 07538 ast_unlock_context(con); 07539 errno = EEXIST; 07540 return -1; 07541 } 07542 } 07543 if (ignorepatl) 07544 ignorepatl->next = ignorepat; 07545 else 07546 con->ignorepats = ignorepat; 07547 ast_unlock_context(con); 07548 return 0; 07549 07550 }
| int ast_context_add_include | ( | const char * | context, | |
| const char * | include, | |||
| const char * | registrar | |||
| ) |
Add a context include.
| context | context to add include to | |
| include | new include to add | |
| registrar | who's registering it |
| 0 | on success | |
| -1 | on error |
Definition at line 7053 of file pbx.c.
References ast_context_add_include2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_add_include().
07054 { 07055 int ret = -1; 07056 struct ast_context *c = find_context_locked(context); 07057 07058 if (c) { 07059 ret = ast_context_add_include2(c, include, registrar); 07060 ast_unlock_contexts(); 07061 } 07062 return ret; 07063 }
| int ast_context_add_include2 | ( | struct ast_context * | con, | |
| const char * | include, | |||
| const char * | registrar | |||
| ) |
Add a context include.
| con | context to add the include to | |
| include | include to add | |
| registrar | who registered the context |
| 0 | on success | |
| -1 | on failure |
Definition at line 7317 of file pbx.c.
References ast_build_timing(), ast_calloc, ast_destroy_timing(), ast_free, ast_get_context_name(), ast_unlock_context(), ast_verb, ast_wrlock_context(), errno, ast_include::hastime, ast_context::includes, ast_include::name, ast_include::next, ast_include::registrar, ast_include::rname, ast_include::stuff, and ast_include::timing.
Referenced by ast_compile_ael2(), ast_context_add_include(), context_merge_incls_swits_igps_other_registrars(), and pbx_load_config().
07319 { 07320 struct ast_include *new_include; 07321 char *c; 07322 struct ast_include *i, *il = NULL; /* include, include_last */ 07323 int length; 07324 char *p; 07325 07326 length = sizeof(struct ast_include); 07327 length += 2 * (strlen(value) + 1); 07328 07329 /* allocate new include structure ... */ 07330 if (!(new_include = ast_calloc(1, length))) 07331 return -1; 07332 /* Fill in this structure. Use 'p' for assignments, as the fields 07333 * in the structure are 'const char *' 07334 */ 07335 p = new_include->stuff; 07336 new_include->name = p; 07337 strcpy(p, value); 07338 p += strlen(value) + 1; 07339 new_include->rname = p; 07340 strcpy(p, value); 07341 /* Strip off timing info, and process if it is there */ 07342 if ( (c = strchr(p, ',')) ) { 07343 *c++ = '\0'; 07344 new_include->hastime = ast_build_timing(&(new_include->timing), c); 07345 } 07346 new_include->next = NULL; 07347 new_include->registrar = registrar; 07348 07349 ast_wrlock_context(con); 07350 07351 /* ... go to last include and check if context is already included too... */ 07352 for (i = con->includes; i; i = i->next) { 07353 if (!strcasecmp(i->name, new_include->name)) { 07354 ast_destroy_timing(&(new_include->timing)); 07355 ast_free(new_include); 07356 ast_unlock_context(con); 07357 errno = EEXIST; 07358 return -1; 07359 } 07360 il = i; 07361 } 07362 07363 /* ... include new context into context list, unlock, return */ 07364 if (il) 07365 il->next = new_include; 07366 else 07367 con->includes = new_include; 07368 ast_verb(3, "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con)); 07369 07370 ast_unlock_context(con); 07371 07372 return 0; 07373 }
| int ast_context_add_switch | ( | const char * | context, | |
| const char * | sw, | |||
| const char * | data, | |||
| int | eval, | |||
| const char * | registrar | |||
| ) |
Add a switch.
| 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 |
| 0 | on success | |
| -1 | on failure |
Definition at line 7380 of file pbx.c.
References ast_context_add_switch2(), ast_unlock_contexts(), and find_context_locked().
07381 { 07382 int ret = -1; 07383 struct ast_context *c = find_context_locked(context); 07384 07385 if (c) { /* found, add switch to this context */ 07386 ret = ast_context_add_switch2(c, sw, data, eval, registrar); 07387 ast_unlock_contexts(); 07388 } 07389 return ret; 07390 }
| int ast_context_add_switch2 | ( | struct ast_context * | con, | |
| const char * | sw, | |||
| const char * | data, | |||
| int | eval, | |||
| const char * | registrar | |||
| ) |
Adds a switch (first param is a ast_context).
Definition at line 7399 of file pbx.c.
References ast_context::alts, ast_calloc, ast_free, ast_get_context_name(), AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, ast_unlock_context(), ast_verb, ast_wrlock_context(), ast_sw::data, errno, ast_sw::eval, ast_sw::name, ast_sw::registrar, and ast_sw::stuff.
Referenced by ast_compile_ael2(), ast_context_add_switch(), context_merge_incls_swits_igps_other_registrars(), lua_register_switches(), and pbx_load_config().
07401 { 07402 struct ast_sw *new_sw; 07403 struct ast_sw *i; 07404 int length; 07405 char *p; 07406 07407 length = sizeof(struct ast_sw); 07408 length += strlen(value) + 1; 07409 if (data) 07410 length += strlen(data); 07411 length++; 07412 07413 /* allocate new sw structure ... */ 07414 if (!(new_sw = ast_calloc(1, length))) 07415 return -1; 07416 /* ... fill in this structure ... */ 07417 p = new_sw->stuff; 07418 new_sw->name = p; 07419 strcpy(new_sw->name, value); 07420 p += strlen(value) + 1; 07421 new_sw->data = p; 07422 if (data) { 07423 strcpy(new_sw->data, data); 07424 p += strlen(data) + 1; 07425 } else { 07426 strcpy(new_sw->data, ""); 07427 p++; 07428 } 07429 new_sw->eval = eval; 07430 new_sw->registrar = registrar; 07431 07432 /* ... try to lock this context ... */ 07433 ast_wrlock_context(con); 07434 07435 /* ... go to last sw and check if context is already swd too... */ 07436 AST_LIST_TRAVERSE(&con->alts, i, list) { 07437 if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) { 07438 ast_free(new_sw); 07439 ast_unlock_context(con); 07440 errno = EEXIST; 07441 return -1; 07442 } 07443 } 07444 07445 /* ... sw new context into context list, unlock, return */ 07446 AST_LIST_INSERT_TAIL(&con->alts, new_sw, list); 07447 07448 ast_verb(3, "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con)); 07449 07450 ast_unlock_context(con); 07451 07452 return 0; 07453 }
| void ast_context_destroy | ( | struct ast_context * | con, | |
| const char * | registrar | |||
| ) |
Destroy a context (matches the specified context (or ANY context if NULL).
| con | context to destroy | |
| registrar | who registered it |
Definition at line 8702 of file pbx.c.
References __ast_context_destroy(), ast_unlock_contexts(), ast_wrlock_contexts(), contexts, and contexts_table.
Referenced by __unload_module(), cleanup_stale_contexts(), parkinglot_destroy(), sla_destroy(), and unload_module().
08703 { 08704 ast_wrlock_contexts(); 08705 __ast_context_destroy(contexts, contexts_table, con,registrar); 08706 ast_unlock_contexts(); 08707 }
| struct ast_context* ast_context_find | ( | const char * | name | ) | [read] |
Find a context.
| name | name of the context to find |
Definition at line 2454 of file pbx.c.
References ast_copy_string(), ast_hashtab_lookup(), ast_rdlock_contexts(), ast_unlock_contexts(), ast_walk_contexts(), contexts_table, ast_context::name, and fake_context::name.
Referenced by __unload_module(), _macro_exec(), ast_context_verify_includes(), ast_ignore_pattern(), cleanup_stale_contexts(), isexten_function_read(), load_config(), manage_parkinglot(), park_exec_full(), parkinglot_destroy(), register_exten(), register_peer_exten(), unload_module(), and unregister_exten().
02455 { 02456 struct ast_context *tmp = NULL; 02457 struct fake_context item; 02458 02459 ast_copy_string(item.name, name, sizeof(item.name)); 02460 02461 ast_rdlock_contexts(); 02462 if( contexts_table ) { 02463 tmp = ast_hashtab_lookup(contexts_table,&item); 02464 } else { 02465 while ( (tmp = ast_walk_contexts(tmp)) ) { 02466 if (!name || !strcasecmp(name, tmp->name)) { 02467 break; 02468 } 02469 } 02470 } 02471 ast_unlock_contexts(); 02472 return tmp; 02473 }
| struct ast_context* ast_context_find_or_create | ( | struct ast_context ** | extcontexts, | |
| struct ast_hashtab * | exttable, | |||
| const char * | name, | |||
| const char * | registrar | |||
| ) | [read] |
Register a new context or find an existing one.
| 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 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.
Definition at line 6710 of file pbx.c.
References ast_calloc, ast_copy_string(), ast_debug, ast_hashtab_compare_contexts(), ast_hashtab_create(), ast_hashtab_hash_contexts(), ast_hashtab_insert_immediate(), ast_hashtab_insert_safe(), ast_hashtab_lookup(), ast_hashtab_newsize_java(), ast_hashtab_resize_java(), ast_log(), ast_mutex_init(), ast_rdlock_contexts(), ast_rwlock_init(), ast_strdup, ast_unlock_contexts(), ast_verb, ast_wrlock_contexts(), contexts, contexts_table, ast_context::ignorepats, ast_context::includes, local_contexts, ast_context::lock, LOG_ERROR, ast_context::macrolock, ast_context::name, fake_context::name, ast_context::next, ast_context::refcount, ast_context::registrar, ast_context::root, and ast_context::root_table.
Referenced by ast_compile_ael2(), build_parkinglot(), config_parse_variables(), context_merge(), load_config(), load_module(), lua_register_switches(), manage_parkinglot(), park_call_full(), pbx_load_config(), pbx_load_users(), reload_config(), set_config(), sla_build_station(), and sla_build_trunk().
06711 { 06712 struct ast_context *tmp, **local_contexts; 06713 struct fake_context search; 06714 int length = sizeof(struct ast_context) + strlen(name) + 1; 06715 06716 if (!contexts_table) { 06717 contexts_table = ast_hashtab_create(17, 06718 ast_hashtab_compare_contexts, 06719 ast_hashtab_resize_java, 06720 ast_hashtab_newsize_java, 06721 ast_hashtab_hash_contexts, 06722 0); 06723 } 06724 06725 ast_copy_string(search.name, name, sizeof(search.name)); 06726 if (!extcontexts) { 06727 ast_rdlock_contexts(); 06728 local_contexts = &contexts; 06729 tmp = ast_hashtab_lookup(contexts_table, &search); 06730 ast_unlock_contexts(); 06731 if (tmp) { 06732 tmp->refcount++; 06733 return tmp; 06734 } 06735 } else { /* local contexts just in a linked list; search there for the new context; slow, linear search, but not frequent */ 06736 local_contexts = extcontexts; 06737 tmp = ast_hashtab_lookup(exttable, &search); 06738 if (tmp) { 06739 tmp->refcount++; 06740 return tmp; 06741 } 06742 } 06743 06744 if ((tmp = ast_calloc(1, length))) { 06745 ast_rwlock_init(&tmp->lock); 06746 ast_mutex_init(&tmp->macrolock); 06747 strcpy(tmp->name, name); 06748 tmp->root = NULL; 06749 tmp->root_table = NULL; 06750 tmp->registrar = ast_strdup(registrar); 06751 tmp->includes = NULL; 06752 tmp->ignorepats = NULL; 06753 tmp->refcount = 1; 06754 } else { 06755 ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name); 06756 return NULL; 06757 } 06758 06759 if (!extcontexts) { 06760 ast_wrlock_contexts(); 06761 tmp->next = *local_contexts; 06762 *local_contexts = tmp; 06763 ast_hashtab_insert_safe(contexts_table, tmp); /*put this context into the tree */ 06764 ast_unlock_contexts(); 06765 ast_debug(1, "Registered context '%s'(%p) in table %p registrar: %s\n", tmp->name, tmp, contexts_table, registrar); 06766 ast_verb(3, "Registered extension context '%s' (%p) in table %p; registrar: %s\n", tmp->name, tmp, contexts_table, registrar); 06767 } else { 06768 tmp->next = *local_contexts; 06769 if (exttable) 06770 ast_hashtab_insert_immediate(exttable, tmp); /*put this context into the tree */ 06771 06772 *local_contexts = tmp; 06773 ast_debug(1, "Registered context '%s'(%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar); 06774 ast_verb(3, "Registered extension context '%s' (%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar); 06775 } 06776 return tmp; 06777 }
| int ast_context_lockmacro | ( | const char * | context | ) |
locks the macrolock in the given given context
| macrocontext | name of the macro-context to lock |
| 0 | on success | |
| -1 | on failure |
Definition at line 5314 of file pbx.c.
References ast_copy_string(), ast_hashtab_lookup(), ast_mutex_lock(), ast_rdlock_contexts(), ast_unlock_contexts(), contexts_table, ast_context::macrolock, and fake_context::name.
Referenced by _macro_exec().
05315 { 05316 struct ast_context *c = NULL; 05317 int ret = -1; 05318 struct fake_context item; 05319 05320 ast_rdlock_contexts(); 05321 05322 ast_copy_string(item.name, context, sizeof(item.name)); 05323 05324 c = ast_hashtab_lookup(contexts_table,&item); 05325 if (c) 05326 ret = 0; 05327 ast_unlock_contexts(); 05328 05329 /* if we found context, lock macrolock */ 05330 if (ret == 0) { 05331 ret = ast_mutex_lock(&c->macrolock); 05332 } 05333 05334 return ret; 05335 }
| int ast_context_remove_extension | ( | const char * | context, | |
| const char * | extension, | |||
| int | priority, | |||
| const char * | registrar | |||
| ) |
Simply remove extension from context.
| 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 |
| 0 | on success | |
| -1 | on failure |
Definition at line 5122 of file pbx.c.
References ast_context_remove_extension_callerid().
Referenced by destroy_station(), destroy_trunk(), register_peer_exten(), unregister_exten(), and UnregisterExtension().
05123 { 05124 return ast_context_remove_extension_callerid(context, extension, priority, NULL, 0, registrar); 05125 }
| int ast_context_remove_extension2 | ( | struct ast_context * | con, | |
| const char * | extension, | |||
| int | priority, | |||
| const char * | registrar, | |||
| int | already_locked | |||
| ) |
This functionc locks given context, search for the right extension and fires out all peer in this extensions with given priority. If priority is set to 0, all peers are removed. After that, unlock context and return.
Definition at line 5149 of file pbx.c.
References ast_context_remove_extension_callerid2().
Referenced by load_config(), manage_parkinglot(), park_exec_full(), and unload_module().
05150 { 05151 return ast_context_remove_extension_callerid2(con, extension, priority, NULL, 0, registrar, already_locked); 05152 }
| int ast_context_remove_extension_callerid | ( | const char * | context, | |
| const char * | extension, | |||
| int | priority, | |||
| const char * | callerid, | |||
| int | matchcid, | |||
| const char * | registrar | |||
| ) |
Definition at line 5127 of file pbx.c.
References ast_context_remove_extension_callerid2(), ast_unlock_contexts(), and find_context_locked().
Referenced by ast_context_remove_extension(), and handle_cli_dialplan_remove_extension().
05128 { 05129 int ret = -1; /* default error return */ 05130 struct ast_context *c = find_context_locked(context); 05131 05132 if (c) { /* ... remove extension ... */ 05133 ret = ast_context_remove_extension_callerid2(c, extension, priority, callerid, matchcallerid, registrar, 1); 05134 ast_unlock_contexts(); 05135 } 05136 return ret; 05137 }
| int ast_context_remove_extension_callerid2 | ( | struct ast_context * | con, | |
| const char * | extension, | |||
| int | priority, | |||
| const char * | callerid, | |||
| int | matchcid, | |||
| const char * | registrar, | |||
| int | already_locked | |||
| ) |
Definition at line 5154 of file pbx.c.
References add_exten_to_pattern_tree(), ast_copy_string(), ast_hashtab_insert_immediate(), ast_hashtab_lookup(), ast_hashtab_remove_this_object(), ast_hashtab_size(), ast_log(), ast_strlen_zero(), ast_unlock_context(), ast_verb, ast_wrlock_context(), ast_exten::cidmatch, match_char::deleted, destroy_exten(), match_char::exten, ast_exten::exten, ast_exten::label, LOG_ERROR, LOG_NOTICE, LOG_WARNING, ast_exten::matchcid, ast_context::name, ast_exten::next, ast_context::pattern_tree, ast_exten::peer, ast_exten::peer_label_table, ast_exten::peer_table, ast_exten::priority, ast_exten::registrar, ast_context::root, ast_context::root_table, and match_char::x.
Referenced by __ast_context_destroy(), ast_context_remove_extension2(), and ast_context_remove_extension_callerid().
05155 { 05156 struct ast_exten *exten, *prev_exten = NULL; 05157 struct ast_exten *peer; 05158 struct ast_exten ex, *exten2, *exten3; 05159 char dummy_name[1024]; 05160 struct ast_exten *previous_peer = NULL; 05161 struct ast_exten *next_peer = NULL; 05162 int found = 0; 05163 05164 if (!already_locked) 05165 ast_wrlock_context(con); 05166 05167 /* Handle this is in the new world */ 05168 05169 /* FIXME For backwards compatibility, if callerid==NULL, then remove ALL 05170 * peers, not just those matching the callerid. */ 05171 #ifdef NEED_DEBUG 05172 ast_verb(3,"Removing %s/%s/%d%s%s from trees, registrar=%s\n", con->name, extension, priority, matchcallerid ? "/" : "", matchcallerid ? callerid : "", registrar); 05173 #endif 05174 #ifdef CONTEXT_DEBUG 05175 check_contexts(__FILE__, __LINE__); 05176 #endif 05177 /* find this particular extension */ 05178 ex.exten = dummy_name; 05179 ex.matchcid = matchcallerid && !ast_strlen_zero(callerid); /* don't say match if there's no callerid */ 05180 ex.cidmatch = callerid; 05181 ast_copy_string(dummy_name, extension, sizeof(dummy_name)); 05182 exten = ast_hashtab_lookup(con->root_table, &ex); 05183 if (exten) { 05184 if (priority == 0) { 05185 exten2 = ast_hashtab_remove_this_object(con->root_table, exten); 05186 if (!exten2) 05187 ast_log(LOG_ERROR,"Trying to delete the exten %s from context %s, but could not remove from the root_table\n", extension, con->name); 05188 if (con->pattern_tree) { 05189 struct match_char *x = add_exten_to_pattern_tree(con, exten, 1); 05190 05191 if (x->exten) { /* this test for safety purposes */ 05192 x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */ 05193 x->exten = 0; /* get rid of what will become a bad pointer */ 05194 } else { 05195 ast_log(LOG_WARNING,"Trying to delete an exten from a context, but the pattern tree node returned isn't a full extension\n"); 05196 } 05197 } 05198 } else { 05199 ex.priority = priority; 05200 exten2 = ast_hashtab_lookup(exten->peer_table, &ex); 05201 if (exten2) { 05202 05203 if (exten2->label) { /* if this exten has a label, remove that, too */ 05204 exten3 = ast_hashtab_remove_this_object(exten->peer_label_table,exten2); 05205 if (!exten3) 05206 ast_log(LOG_ERROR,"Did not remove this priority label (%d/%s) from the peer_label_table of context %s, extension %s!\n", priority, exten2->label, con->name, exten2->exten); 05207 } 05208 05209 exten3 = ast_hashtab_remove_this_object(exten->peer_table, exten2); 05210 if (!exten3) 05211 ast_log(LOG_ERROR,"Did not remove this priority (%d) from the peer_table of context %s, extension %s!\n", priority, con->name, exten2->exten); 05212 if (exten2 == exten && exten2->peer) { 05213 exten2 = ast_hashtab_remove_this_object(con->root_table, exten); 05214 ast_hashtab_insert_immediate(con->root_table, exten2->peer); 05215 } 05216 if (ast_hashtab_size(exten->peer_table) == 0) { 05217 /* well, if the last priority of an exten is to be removed, 05218 then, the extension is removed, too! */ 05219 exten3 = ast_hashtab_remove_this_object(con->root_table, exten); 05220 if (!exten3) 05221 ast_log(LOG_ERROR,"Did not remove this exten (%s) from the context root_table (%s) (priority %d)\n", exten->exten, con->name, priority); 05222 if (con->pattern_tree) { 05223 struct match_char *x = add_exten_to_pattern_tree(con, exten, 1); 05224 if (x->exten) { /* this test for safety purposes */ 05225 x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */ 05226 x->exten = 0; /* get rid of what will become a bad pointer */ 05227 } 05228 } 05229 } 05230 } else { 05231 ast_log(LOG_ERROR,"Could not find priority %d of exten %s in context %s!\n", 05232 priority, exten->exten, con->name); 05233 } 05234 } 05235 } else { 05236 /* hmmm? this exten is not in this pattern tree? */ 05237 ast_log(LOG_WARNING,"Cannot find extension %s in root_table in context %s\n", 05238 extension, con->name); 05239 } 05240 #ifdef NEED_DEBUG 05241 if (con->pattern_tree) { 05242 ast_log(LOG_NOTICE,"match char tree after exten removal:\n"); 05243 log_match_char_tree(con->pattern_tree, " "); 05244 } 05245 #endif 05246 05247 /* scan the extension list to find first matching extension-registrar */ 05248 for (exten = con->root; exten; prev_exten = exten, exten = exten->next) { 05249 if (!strcmp(exten->exten, extension) && 05250 (!registrar || !strcmp(exten->registrar, registrar)) && 05251 (!matchcallerid || (!ast_strlen_zero(callerid) && !ast_strlen_zero(exten->cidmatch) && !strcmp(exten->cidmatch, callerid)) || (ast_strlen_zero(callerid) && ast_strlen_zero(exten->cidmatch)))) 05252 break; 05253 } 05254 if (!exten) { 05255 /* we can't find right extension */ 05256 if (!already_locked) 05257 ast_unlock_context(con); 05258 return -1; 05259 } 05260 05261 /* scan the priority list to remove extension with exten->priority == priority */ 05262 for (peer = exten, next_peer = exten->peer ? exten->peer : exten->next; 05263 peer && !strcmp(peer->exten, extension) && (!matchcallerid || (!ast_strlen_zero(callerid) && !ast_strlen_zero(peer->cidmatch) && !strcmp(peer->cidmatch,callerid)) || (ast_strlen_zero(callerid) && ast_strlen_zero(peer->cidmatch))); 05264 peer = next_peer, next_peer = next_peer ? (next_peer->peer ? next_peer->peer : next_peer->next) : NULL) { 05265 if ((priority == 0 || peer->priority == priority) && 05266 (!callerid || !matchcallerid || (matchcallerid && !strcmp(peer->cidmatch, callerid))) && 05267 (!registrar || !strcmp(peer->registrar, registrar) )) { 05268 found = 1; 05269 05270 /* we are first priority extension? */ 05271 if (!previous_peer) { 05272 /* 05273 * We are first in the priority chain, so must update the extension chain. 05274 * The next node is either the next priority or the next extension 05275 */ 05276 struct ast_exten *next_node = peer->peer ? peer->peer : peer->next; 05277 if (peer->peer) { 05278 /* move the peer_table and peer_label_table down to the next peer, if 05279 it is there */ 05280 peer->peer->peer_table = peer->peer_table; 05281 peer->peer->peer_label_table = peer->peer_label_table; 05282 peer->peer_table = NULL; 05283 peer->peer_label_table = NULL; 05284 } 05285 if (!prev_exten) { /* change the root... */ 05286 con->root = next_node; 05287 } else { 05288 prev_exten->next = next_node; /* unlink */ 05289 } 05290 if (peer->peer) { /* update the new head of the pri list */ 05291 peer->peer->next = peer->next; 05292 } 05293 } else { /* easy, we are not first priority in extension */ 05294 previous_peer->peer = peer->peer; 05295 } 05296 05297 /* now, free whole priority extension */ 05298 destroy_exten(peer); 05299 } else { 05300 previous_peer = peer; 05301 } 05302 } 05303 if (!already_locked) 05304 ast_unlock_context(con); 05305 return found ? 0 : -1; 05306 }
| int ast_context_remove_ignorepat | ( | const char * | context, | |
| const char * | ignorepat, | |||
| const char * | registrar | |||
| ) |
Definition at line 7459 of file pbx.c.
References ast_context_remove_ignorepat2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_remove_ignorepat().
07460 { 07461 int ret = -1; 07462 struct ast_context *c = find_context_locked(context); 07463 07464 if (c) { 07465 ret = ast_context_remove_ignorepat2(c, ignorepat, registrar); 07466 ast_unlock_contexts(); 07467 } 07468 return ret; 07469 }
| int ast_context_remove_ignorepat2 | ( | struct ast_context * | con, | |
| const char * | ignorepat, | |||
| const char * | registrar | |||
| ) |
Definition at line 7471 of file pbx.c.
References ast_free, ast_unlock_context(), ast_wrlock_context(), errno, ast_context::ignorepats, ast_ignorepat::next, ast_ignorepat::pattern, and ast_ignorepat::registrar.
Referenced by ast_context_remove_ignorepat().
07472 { 07473 struct ast_ignorepat *ip, *ipl = NULL; 07474 07475 ast_wrlock_context(con); 07476 07477 for (ip = con->ignorepats; ip; ip = ip->next) { 07478 if (!strcmp(ip->pattern, ignorepat) && 07479 (!registrar || (registrar == ip->registrar))) { 07480 if (ipl) { 07481 ipl->next = ip->next; 07482 ast_free(ip); 07483 } else { 07484 con->ignorepats = ip->next; 07485 ast_free(ip); 07486 } 07487 ast_unlock_context(con); 07488 return 0; 07489 } 07490 ipl = ip; 07491 } 07492 07493 ast_unlock_context(con); 07494 errno = EINVAL; 07495 return -1; 07496 }
| int ast_context_remove_include | ( | const char * | context, | |
| const char * | include, | |||
| const char * | registrar | |||
| ) |
Remove a context include.
| 0 | on success | |
| -1 | on failure |
Definition at line 5013 of file pbx.c.
References ast_context_remove_include2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_remove_include().
05014 { 05015 int ret = -1; 05016 struct ast_context *c = find_context_locked(context); 05017 05018 if (c) { 05019 /* found, remove include from this context ... */ 05020 ret = ast_context_remove_include2(c, include, registrar); 05021 ast_unlock_contexts(); 05022 } 05023 return ret; 05024 }
| int ast_context_remove_include2 | ( | struct ast_context * | con, | |
| const char * | include, | |||
| const char * | registrar | |||
| ) |
Removes an include by an ast_context structure.
| 0 | on success | |
| -1 | on success |
| 0 | on success. | |
| -1 | on failure. |
Definition at line 5035 of file pbx.c.
References ast_destroy_timing(), ast_free, ast_get_context_name(), ast_unlock_context(), ast_verb, ast_wrlock_context(), ast_context::includes, ast_include::name, ast_include::next, ast_include::registrar, and ast_include::timing.
Referenced by ast_context_remove_include().
05036 { 05037 struct ast_include *i, *pi = NULL; 05038 int ret = -1; 05039 05040 ast_wrlock_context(con); 05041 05042 /* find our include */ 05043 for (i = con->includes; i; pi = i, i = i->next) { 05044 if (!strcmp(i->name, include) && 05045 (!registrar || !strcmp(i->registrar, registrar))) { 05046 /* remove from list */ 05047 ast_verb(3, "Removing inclusion of context '%s' in context '%s; registrar=%s'\n", include, ast_get_context_name(con), registrar); 05048 if (pi) 05049 pi->next = i->next; 05050 else 05051 con->includes = i->next; 05052 /* free include and return */ 05053 ast_destroy_timing(&(i->timing)); 05054 ast_free(i); 05055 ret = 0; 05056 break; 05057 } 05058 } 05059 05060 ast_unlock_context(con); 05061 05062 return ret; 05063 }
| int ast_context_remove_switch | ( | const char * | context, | |
| const char * | sw, | |||
| const char * | data, | |||
| const char * | registrar | |||
| ) |
Remove a switch.
Removes a switch with the given parameters
| 0 | on success | |
| -1 | on failure |
Definition at line 5070 of file pbx.c.
References ast_context_remove_switch2(), ast_unlock_contexts(), and find_context_locked().
05071 { 05072 int ret = -1; /* default error return */ 05073 struct ast_context *c = find_context_locked(context); 05074 05075 if (c) { 05076 /* remove switch from this context ... */ 05077 ret = ast_context_remove_switch2(c, sw, data, registrar); 05078 ast_unlock_contexts(); 05079 } 05080 return ret; 05081 }
| int ast_context_remove_switch2 | ( | struct ast_context * | con, | |
| const char * | sw, | |||
| const char * | data, | |||
| const char * | registrar | |||
| ) |
This function locks given context, removes switch, unlock context and return.
Definition at line 5091 of file pbx.c.
References ast_context::alts, ast_free, ast_get_context_name(), AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_unlock_context(), ast_verb, ast_wrlock_context(), ast_sw::data, ast_sw::name, and ast_sw::registrar.
Referenced by ast_context_remove_switch().
05092 { 05093 struct ast_sw *i; 05094 int ret = -1; 05095 05096 ast_wrlock_context(con); 05097 05098 /* walk switches */ 05099 AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) { 05100 if (!strcmp(i->name, sw) && !strcmp(i->data, data) && 05101 (!registrar || !strcmp(i->registrar, registrar))) { 05102 /* found, remove from list */ 05103 ast_verb(3, "Removing switch '%s' from context '%s; registrar=%s'\n", sw, ast_get_context_name(con), registrar); 05104 AST_LIST_REMOVE_CURRENT(list); 05105 ast_free(i); /* free switch and return */ 05106 ret = 0; 05107 break; 05108 } 05109 } 05110 AST_LIST_TRAVERSE_SAFE_END; 05111 05112 ast_unlock_context(con); 05113 05114 return ret; 05115 }
| int ast_context_unlockmacro | ( | const char * | context | ) |
Unlocks the macrolock in the given context.
| macrocontext | name of the macro-context to unlock |
| 0 | on success | |
| -1 | on failure |
Definition at line 5342 of file pbx.c.
References ast_copy_string(), ast_hashtab_lookup(), ast_mutex_unlock(), ast_rdlock_contexts(), ast_unlock_contexts(), contexts_table, ast_context::macrolock, and fake_context::name.
Referenced by _macro_exec().
05343 { 05344 struct ast_context *c = NULL; 05345 int ret = -1; 05346 struct fake_context item; 05347 05348 ast_rdlock_contexts(); 05349 05350 ast_copy_string(item.name, context, sizeof(item.name)); 05351 05352 c = ast_hashtab_lookup(contexts_table,&item); 05353 if (c) 05354 ret = 0; 05355 ast_unlock_contexts(); 05356 05357 /* if we found context, unlock macrolock */ 05358 if (ret == 0) { 05359 ret = ast_mutex_unlock(&c->macrolock); 05360 } 05361 05362 return ret; 05363 }
| int ast_context_verify_includes | ( | struct ast_context * | con | ) |
Verifies includes in an ast_contect structure.
| con | context in which to verify the includes |
| 0 | if no problems found | |
| -1 | if there were any missing context |
Definition at line 9803 of file pbx.c.
References ast_context_find(), ast_get_context_name(), ast_log(), ast_walk_context_includes(), LOG_WARNING, and ast_include::rname.
Referenced by pbx_load_module().
09804 { 09805 struct ast_include *inc = NULL; 09806 int res = 0; 09807 09808 while ( (inc = ast_walk_context_includes(con, inc)) ) { 09809 if (ast_context_find(inc->rname)) 09810 continue; 09811 09812 res = -1; 09813 ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n", 09814 ast_get_context_name(con), inc->rname); 09815 break; 09816 } 09817 09818 return res; 09819 }
| struct ast_custom_function* ast_custom_function_find | ( | const char * | name | ) | [read] |
Definition at line 3269 of file pbx.c.
References ast_custom_function::acflist, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, and ast_custom_function::name.
Referenced by ast_func_read(), ast_func_read2(), ast_func_write(), config_curl(), destroy_curl(), handle_show_function(), op_func(), realtime_curl(), realtime_multi_curl(), require_curl(), store_curl(), update2_curl(), and update_curl().
03270 { 03271 struct ast_custom_function *acf = NULL; 03272 03273 AST_RWLIST_RDLOCK(&acf_root); 03274 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) { 03275 if (!strcmp(name, acf->name)) 03276 break; 03277 } 03278 AST_RWLIST_UNLOCK(&acf_root); 03279 03280 return acf; 03281 }
| int ast_custom_function_unregister | ( | struct ast_custom_function * | acf | ) |
Unregister a custom function.
Definition at line 3283 of file pbx.c.
References ast_custom_function::acflist, AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_string_field_free_memory, ast_verb, AST_XML_DOC, ast_custom_function::docsrc, and ast_custom_function::name.
Referenced by load_module(), reload(), and unload_module().
03284 { 03285 struct ast_custom_function *cur; 03286 03287 if (!acf) { 03288 return -1; 03289 } 03290 03291 AST_RWLIST_WRLOCK(&acf_root); 03292 if ((cur = AST_RWLIST_REMOVE(&acf_root, acf, acflist))) { 03293 #ifdef AST_XML_DOCS 03294 if (cur->docsrc == AST_XML_DOC) { 03295 ast_string_field_free_memory(acf); 03296 } 03297 #endif 03298 ast_verb(2, "Unregistered custom function %s\n", cur->name); 03299 } 03300 AST_RWLIST_UNLOCK(&acf_root); 03301 03302 return cur ? 0 : -1; 03303 }
| int ast_destroy_timing | ( | struct ast_timing * | i | ) |
Deallocates memory structures associated with a timing bitmap.
| i | Pointer to an ast_timing structure. |
| 0 | success | |
| non-zero | failure (number suitable to pass to |
Definition at line 7302 of file pbx.c.
References ast_free, and ast_timing::timezone.
Referenced by ast_context_add_include2(), ast_context_remove_include2(), iftime(), pbx_builtin_execiftime(), and pbx_builtin_gotoiftime().
07303 { 07304 if (i->timezone) { 07305 ast_free(i->timezone); 07306 i->timezone = NULL; 07307 } 07308 return 0; 07309 }
| enum ast_extension_states ast_devstate_to_extenstate | ( | enum ast_device_state | devstate | ) |
Map devstate to an extension state.
| [in] | device | state |
Definition at line 4086 of file pbx.c.
References AST_DEVICE_BUSY, AST_DEVICE_INUSE, AST_DEVICE_INVALID, AST_DEVICE_NOT_INUSE, AST_DEVICE_ONHOLD, AST_DEVICE_RINGING, AST_DEVICE_RINGINUSE, AST_DEVICE_TOTAL, AST_DEVICE_UNAVAILABLE, AST_DEVICE_UNKNOWN, AST_EXTENSION_BUSY, AST_EXTENSION_INUSE, AST_EXTENSION_NOT_INUSE, AST_EXTENSION_ONHOLD, AST_EXTENSION_RINGING, and AST_EXTENSION_UNAVAILABLE.
Referenced by ast_extension_state2().
04087 { 04088 switch (devstate) { 04089 case AST_DEVICE_ONHOLD: 04090 return AST_EXTENSION_ONHOLD; 04091 case AST_DEVICE_BUSY: 04092 return AST_EXTENSION_BUSY; 04093 case AST_DEVICE_UNAVAILABLE: 04094 case AST_DEVICE_UNKNOWN: 04095 case AST_DEVICE_INVALID: 04096 return AST_EXTENSION_UNAVAILABLE; 04097 case AST_DEVICE_RINGINUSE: 04098 return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING); 04099 case AST_DEVICE_RINGING: 04100 return AST_EXTENSION_RINGING; 04101 case AST_DEVICE_INUSE: 04102 return AST_EXTENSION_INUSE; 04103 case AST_DEVICE_NOT_INUSE: 04104 return AST_EXTENSION_NOT_INUSE; 04105 case AST_DEVICE_TOTAL: /* not a device state, included for completeness */ 04106 break; 04107 } 04108 04109 return AST_EXTENSION_NOT_INUSE; 04110 }
| int ast_exists_extension | ( | struct ast_channel * | c, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority, | |||
| const char * | callerid | |||
| ) |
Determine whether an extension exists.
| 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 |
Definition at line 4480 of file pbx.c.
References E_MATCH, and pbx_extension_helper().
Referenced by __analog_ss_thread(), __ast_goto_if_exists(), __ast_pbx_run(), _macro_exec(), acf_isexten_exec(), analog_ss_thread(), answer_call(), ast_app_dtget(), ast_bridge_call(), ast_pbx_outgoing_exten(), builtin_atxfer(), builtin_blindtransfer(), cb_events(), change_t38_state(), cli_console_dial(), conf_run(), console_dial(), console_transfer(), dahdi_handle_dtmfup(), dial_exec_full(), disa_exec(), dp_lookup(), dundi_lookup_local(), get_also_info(), get_destination(), get_refer_info(), gosub_exec(), handle_gosub(), handle_link_data(), handle_link_phone_dtmf(), handle_stimulus_message(), isexten_function_read(), leave_voicemail(), local_alloc(), local_call(), local_devicestate(), local_dtmf_helper(), loopback_exists(), metermaidstate(), mgcp_ss(), minivm_greet_exec(), misdn_overlap_dial_task(), my_handle_dtmfup(), park_space_reserve(), parkandannounce_exec(), pbx_builtin_waitexten(), phone_check_exception(), privacy_exec(), process_ast_dsp(), readexten_exec(), register_peer_exten(), rpt_exec(), show_debug_helper(), skinny_ss(), socket_process(), and waitstream_core().
04481 { 04482 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0); 04483 }
| int ast_explicit_goto | ( | struct ast_channel * | chan, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority | |||
| ) |
Definition at line 7606 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, ast_copy_string(), AST_FLAG_IN_AUTOLOOP, ast_strlen_zero(), ast_test_flag, ast_channel::context, ast_channel::exten, and ast_channel::priority.
Referenced by __ast_goto_if_exists(), ast_async_goto(), builtin_atxfer(), disa_exec(), do_bridge_masquerade(), handle_setpriority(), pbx_parseable_goto(), and return_exec().
07607 { 07608 if (!chan) 07609 return -1; 07610 07611 ast_channel_lock(chan); 07612 07613 if (!ast_strlen_zero(context)) 07614 ast_copy_string(chan->context, context, sizeof(chan->context)); 07615 if (!ast_strlen_zero(exten)) 07616 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 07617 if (priority > -1) { 07618 chan->priority = priority; 07619 /* see flag description in channel.h for explanation */ 07620 if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP)) 07621 chan->priority--; 07622 } 07623 07624 ast_channel_unlock(chan); 07625 07626 return 0; 07627 }
| int ast_extension_close | ( | const char * | pattern, | |
| const char * | data, | |||
| int | needmore | |||
| ) |
Definition at line 2431 of file pbx.c.
References ast_log(), E_CANMATCH, E_MATCHMORE, extension_match_core(), and LOG_WARNING.
Referenced by lua_find_extension(), and realtime_switch_common().
02432 { 02433 if (needmore != E_MATCHMORE && needmore != E_CANMATCH) 02434 ast_log(LOG_WARNING, "invalid argument %d\n", needmore); 02435 return extension_match_core(pattern, data, needmore); 02436 }
| int ast_extension_cmp | ( | const char * | a, | |
| const char * | b | |||
| ) |
Determine if one extension should match before another.
Checks whether or extension a should match before extension b
| 0 | if the two extensions have equal matching priority | |
| 1 | on a > b | |
| -1 | on a < b |
Definition at line 2233 of file pbx.c.
References ext_cmp().
Referenced by lua_extension_cmp().
02234 { 02235 return ext_cmp(a, b); 02236 }
| int ast_extension_match | ( | const char * | pattern, | |
| const char * | extension | |||
| ) |
Determine if a given extension matches a given pattern (in NXX format).
Checks whether or not the given extension matches the given pattern.
| 1 | on match | |
| 0 | on failure |
Definition at line 2426 of file pbx.c.
References E_MATCH, and extension_match_core().
Referenced by ast_ignore_pattern(), do_say(), find_matching_priority(), load_module(), loopback_canmatch(), loopback_exists(), loopback_matchmore(), lua_find_extension(), manager_show_dialplan_helper(), matchcid(), misdn_cfg_is_msn_valid(), realtime_switch_common(), reload(), and show_dialplan_helper().
02427 { 02428 return extension_match_core(pattern, data, E_MATCH); 02429 }
| int ast_extension_patmatch | ( | const char * | pattern, | |
| const char * | data | |||
| ) |
| int ast_extension_state | ( | struct ast_channel * | c, | |
| const char * | context, | |||
| const char * | exten | |||
| ) |
Uses hint and devicestate callback to get the state of an extension.
| c | this is not important | |
| context | which context to look in | |
| exten | which extension to get state |
Definition at line 4148 of file pbx.c.
References ast_extension_state2(), and ast_hint_extension().
Referenced by action_extensionstate(), extstate_read(), and handle_request_subscribe().
04149 { 04150 struct ast_exten *e; 04151 04152 if (!(e = ast_hint_extension(c, context, exten))) { /* Do we have a hint for this extension ? */ 04153 return -1; /* No hint, return -1 */ 04154 } 04155 04156 return ast_extension_state2(e); /* Check all devices in the hint */ 04157 }
| const char* ast_extension_state2str | ( | int | extension_state | ) |
Return string representation of the state of an extension.
| extension_state | is the numerical state delivered by ast_extension_state |
Definition at line 4136 of file pbx.c.
References ARRAY_LEN, extension_states, and cfextension_states::text.
Referenced by cb_extensionstate(), handle_request_subscribe(), handle_show_hint(), handle_show_hints(), and show_channels_cb().
04137 { 04138 int i; 04139 04140 for (i = 0; (i < ARRAY_LEN(extension_states)); i++) { 04141 if (extension_states[i].extension_state == extension_state) 04142 return extension_states[i].text; 04143 } 04144 return "Unknown"; 04145 }
| int ast_extension_state_add | ( | const char * | context, | |
| const char * | exten, | |||
| ast_state_cb_type | callback, | |||
| void * | data | |||
| ) |
Registers a state change callback.
| context | which context to look in | |
| exten | which extension to get state | |
| callback | callback to call if state changed | |
| data | to pass to callback |
| -1 | on failure | |
| ID | on success |
Definition at line 4212 of file pbx.c.
References ast_exten::app, ast_add_extension(), ast_calloc, ast_free_ptr, ast_hint_extension(), AST_LIST_INSERT_HEAD, AST_LIST_TRAVERSE, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_strdup, ast_state_cb::callback, ast_hint::callbacks, ast_exten::cidmatch, ast_exten::data, ast_state_cb::data, ast_hint::exten, ast_exten::exten, ast_state_cb::id, ast_exten::label, ast_context::name, ast_exten::parent, ast_exten::priority, ast_exten::registrar, and stateid.
Referenced by __init_manager(), handle_request_subscribe(), and skinny_register().
04214 { 04215 struct ast_hint *hint; 04216 struct ast_state_cb *cblist; 04217 struct ast_exten *e; 04218 04219 /* If there's no context and extension: add callback to statecbs list */ 04220 if (!context && !exten) { 04221 AST_RWLIST_WRLOCK(&hints); 04222 04223 AST_LIST_TRAVERSE(&statecbs, cblist, entry) { 04224 if (cblist->callback == callback) { 04225 cblist->data = data; 04226 AST_RWLIST_UNLOCK(&hints); 04227 return 0; 04228 } 04229 } 04230 04231 /* Now insert the callback */ 04232 if (!(cblist = ast_calloc(1, sizeof(*cblist)))) { 04233 AST_RWLIST_UNLOCK(&hints); 04234 return -1; 04235 } 04236 cblist->id = 0; 04237 cblist->callback = callback; 04238 cblist->data = data; 04239 04240 AST_LIST_INSERT_HEAD(&statecbs, cblist, entry); 04241 04242 AST_RWLIST_UNLOCK(&hints); 04243 04244 return 0; 04245 } 04246 04247 if (!context || !exten) 04248 return -1; 04249 04250 /* This callback type is for only one hint, so get the hint */ 04251 e = ast_hint_extension(NULL, context, exten); 04252 if (!e) { 04253 return -1; 04254 } 04255 04256 /* If this is a pattern, dynamically create a new extension for this 04257 * particular match. Note that this will only happen once for each 04258 * individual extension, because the pattern will no longer match first. 04259 */ 04260 if (e->exten[0] == '_') { 04261 ast_add_extension(e->parent->name, 0, exten, e->priority, e->label, 04262 e->cidmatch, e->app, ast_strdup(e->data), ast_free_ptr, 04263 e->registrar); 04264 e = ast_hint_extension(NULL, context, exten); 04265 if (!e || e->exten[0] == '_') { 04266 return -1; 04267 } 04268 } 04269 04270 /* Find the hint in the list of hints */ 04271 AST_RWLIST_WRLOCK(&hints); 04272 04273 AST_RWLIST_TRAVERSE(&hints, hint, list) { 04274 if (hint->exten == e) 04275 break; 04276 } 04277 04278 if (!hint) { 04279 /* We have no hint, sorry */ 04280 AST_RWLIST_UNLOCK(&hints); 04281 return -1; 04282 } 04283 04284 /* Now insert the callback in the callback list */ 04285 if (!(cblist = ast_calloc(1, sizeof(*cblist)))) { 04286 AST_RWLIST_UNLOCK(&hints); 04287 return -1; 04288 } 04289 04290 cblist->id = stateid++; /* Unique ID for this callback */ 04291 cblist->callback = callback; /* Pointer to callback routine */ 04292 cblist->data = data; /* Data for the callback */ 04293 04294 AST_LIST_INSERT_HEAD(&hint->callbacks, cblist, entry); 04295 04296 AST_RWLIST_UNLOCK(&hints); 04297 04298 return cblist->id; 04299 }
| int ast_extension_state_del | ( | int | id, | |
| ast_state_cb_type | callback | |||
| ) |
Deletes a registered state change callback by ID.
| id | of the callback to delete | |
| callback | callback |
| 0 | success | |
| -1 | failure |
Definition at line 4302 of file pbx.c.
References ast_free, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_state_cb::callback, ast_hint::callbacks, and ast_state_cb::id.
Referenced by dialog_unlink_all(), handle_request_subscribe(), and skinny_unregister().
04303 { 04304 struct ast_state_cb *p_cur = NULL; 04305 int ret = -1; 04306 04307 if (!id && !callback) 04308 return -1; 04309 04310 AST_RWLIST_WRLOCK(&hints); 04311 04312 if (!id) { /* id == 0 is a callback without extension */ 04313 AST_LIST_TRAVERSE_SAFE_BEGIN(&statecbs, p_cur, entry) { 04314 if (p_cur->callback == callback) { 04315 AST_LIST_REMOVE_CURRENT(entry); 04316 break; 04317 } 04318 } 04319 AST_LIST_TRAVERSE_SAFE_END; 04320 } else { /* callback with extension, find the callback based on ID */ 04321 struct ast_hint *hint; 04322 AST_RWLIST_TRAVERSE(&hints, hint, list) { 04323 AST_LIST_TRAVERSE_SAFE_BEGIN(&hint->callbacks, p_cur, entry) { 04324 if (p_cur->id == id) { 04325 AST_LIST_REMOVE_CURRENT(entry); 04326 break; 04327 } 04328 } 04329 AST_LIST_TRAVERSE_SAFE_END; 04330 04331 if (p_cur) 04332 break; 04333 } 04334 } 04335 04336 if (p_cur) { 04337 ast_free(p_cur); 04338 } 04339 04340 AST_RWLIST_UNLOCK(&hints); 04341 04342 return ret; 04343 }
| int ast_findlabel_extension | ( | struct ast_channel * | c, | |
| const char * | context, | |||
| const char * | exten, | |||
| const char * | label, | |||
| const char * | callerid | |||
| ) |
Find the priority of an extension that has the specified label.
| 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 |
| the | priority which matches the given label in the extension | |
| -1 | if not found. |
Definition at line 4485 of file pbx.c.
References E_FINDLABEL, and pbx_extension_helper().
Referenced by action_originate(), action_redirect(), handle_gosub(), handle_setpriority(), isexten_function_read(), and pbx_parseable_goto().
04486 { 04487 return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0); 04488 }
| int ast_findlabel_extension2 | ( | struct ast_channel * | c, | |
| struct ast_context * | con, | |||
| const char * | exten, | |||
| const char * | label, | |||
| const char * | callerid | |||
| ) |
Find the priority of an extension that has the specified label.
This function is the same as ast_findlabel_extension, except that it accepts a pointer to an ast_context structure to specify the context instead of the name of the context. Otherwise, the functions behave the same.
Definition at line 4490 of file pbx.c.
References E_FINDLABEL, and pbx_extension_helper().
Referenced by pbx_load_config().
04491 { 04492 return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0); 04493 }
| int ast_func_read | ( | struct ast_channel * | chan, | |
| const char * | function, | |||
| char * | workspace, | |||
| size_t | len | |||
| ) |
executes a read operation on a function
| 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 |
| 0 | success | |
| non-zero | failure |
Definition at line 3427 of file pbx.c.
References __ast_module_user_add(), __ast_module_user_remove(), ast_copy_string(), ast_custom_function_find(), ast_free, ast_log(), ast_str_buffer(), ast_str_create(), ast_str_size(), ast_strdupa, copy(), func_args(), LOG_ERROR, ast_custom_function::mod, ast_custom_function::read, ast_custom_function::read2, and str.
Referenced by action_getvar(), action_status(), handle_getvariable(), lua_get_variable_value(), and pbx_substitute_variables_helper_full().
03428 { 03429 char *copy = ast_strdupa(function); 03430 char *args = func_args(copy); 03431 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 03432 int res; 03433 struct ast_module_user *u = NULL; 03434 03435 if (acfptr == NULL) { 03436 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 03437 } else if (!acfptr->read && !acfptr->read2) { 03438 ast_log(LOG_ERROR, "Function %s cannot be read\n", copy); 03439 } else if (acfptr->read) { 03440 if (acfptr->mod) { 03441 u = __ast_module_user_add(acfptr->mod, chan); 03442 } 03443 res = acfptr->read(chan, copy, args, workspace, len); 03444 if (acfptr->mod && u) { 03445 __ast_module_user_remove(acfptr->mod, u); 03446 } 03447 return res; 03448 } else { 03449 struct ast_str *str = ast_str_create(16); 03450 if (acfptr->mod) { 03451 u = __ast_module_user_add(acfptr->mod, chan); 03452 } 03453 res = acfptr->read2(chan, copy, args, &str, 0); 03454 if (acfptr->mod && u) { 03455 __ast_module_user_remove(acfptr->mod, u); 03456 } 03457 ast_copy_string(workspace, ast_str_buffer(str), len > ast_str_size(str) ? ast_str_size(str) : len); 03458 ast_free(str); 03459 return res; 03460 } 03461 return -1; 03462 }
| int ast_func_read2 | ( | struct ast_channel * | chan, | |
| const char * | function, | |||
| struct ast_str ** | str, | |||
| ssize_t | maxlen | |||
| ) |
executes a read operation on a function
| chan | Channel to execute on | |
| function | Data containing the function call string (will be modified) | |
| str | A dynamic string buffer into which to place the result. | |
| maxlen | <0 if the dynamic buffer should not grow; >0 if the dynamic buffer should be limited to that number of bytes; 0 if the dynamic buffer has no upper limit |
| 0 | success | |
| non-zero | failure |
Definition at line 3464 of file pbx.c.
References __ast_module_user_add(), __ast_module_user_remove(), ast_custom_function_find(), ast_log(), ast_str_buffer(), ast_str_make_space(), ast_str_reset(), ast_str_size(), ast_strdupa, copy(), func_args(), LOG_ERROR, maxsize, ast_custom_function::mod, ast_custom_function::read, ast_custom_function::read2, ast_custom_function::read_max, and VAR_BUF_SIZE.
Referenced by ast_str_substitute_variables_full().
03465 { 03466 char *copy = ast_strdupa(function); 03467 char *args = func_args(copy); 03468 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 03469 int res; 03470 struct ast_module_user *u = NULL; 03471 03472 if (acfptr == NULL) { 03473 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 03474 } else if (!acfptr->read && !acfptr->read2) { 03475 ast_log(LOG_ERROR, "Function %s cannot be read\n", copy); 03476 } else { 03477 if (acfptr->mod) { 03478 u = __ast_module_user_add(acfptr->mod, chan); 03479 } 03480 if (acfptr->read2) { 03481 /* ast_str enabled */ 03482 ast_str_reset(*str); 03483 res = acfptr->read2(chan, copy, args, str, maxlen); 03484 } else { 03485 /* Legacy function pointer, allocate buffer for result */ 03486 int maxsize = ast_str_size(*str); 03487 if (maxlen > -1) { 03488 if (maxlen == 0) { 03489 if (acfptr->read_max) { 03490 maxsize = acfptr->read_max; 03491 } else { 03492 maxsize = VAR_BUF_SIZE; 03493 } 03494 } else { 03495 maxsize = maxlen; 03496 } 03497 ast_str_make_space(str, maxsize); 03498 } 03499 res = acfptr->read(chan, copy, args, ast_str_buffer(*str), maxsize); 03500 } 03501 if (acfptr->mod && u) { 03502 __ast_module_user_remove(acfptr->mod, u); 03503 } 03504 return res; 03505 } 03506 return -1; 03507 }
| int ast_func_write | ( | struct ast_channel * | chan, | |
| const char * | function, | |||
| const char * | value | |||
| ) |
executes a write operation on a function
| chan | Channel to execute on | |
| function | Data containing the function call string (will be modified) | |
| value | A value parameter to pass for writing |
| 0 | success | |
| non-zero | failure |
Definition at line 3509 of file pbx.c.
References __ast_module_user_add(), __ast_module_user_remove(), ast_custom_function_find(), ast_log(), ast_strdupa, copy(), func_args(), LOG_ERROR, ast_custom_function::mod, and ast_custom_function::write.
Referenced by conf_run(), pbx_builtin_pushvar_helper(), and pbx_builtin_setvar_helper().
03510 { 03511 char *copy = ast_strdupa(function); 03512 char *args = func_args(copy); 03513 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 03514 03515 if (acfptr == NULL) 03516 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 03517 else if (!acfptr->write) 03518 ast_log(LOG_ERROR, "Function %s cannot be written to\n", copy); 03519 else { 03520 int res; 03521 struct ast_module_user *u = NULL; 03522 if (acfptr->mod) 03523 u = __ast_module_user_add(acfptr->mod, chan); 03524 res = acfptr->write(chan, copy, args, value); 03525 if (acfptr->mod && u) 03526 __ast_module_user_remove(acfptr->mod, u); 03527 return res; 03528 } 03529 03530 return -1; 03531 }
| const char* ast_get_context_name | ( | struct ast_context * | con | ) |
Definition at line 9655 of file pbx.c.
References ast_context::name.
Referenced by _macro_exec(), ast_context_add_include2(), ast_context_add_switch2(), ast_context_remove_include2(), ast_context_remove_switch2(), ast_context_verify_includes(), complete_dialplan_add_extension(), complete_dialplan_add_ignorepat(), complete_dialplan_add_include(), complete_dialplan_remove_extension(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), complete_show_dialplan_context(), context_merge_incls_swits_igps_other_registrars(), dundi_precache_full(), find_matching_endwhile(), find_matching_priority(), handle_cli_dialplan_save(), handle_show_hint(), handle_show_hints(), manager_show_dialplan_helper(), show_debug_helper(), and show_dialplan_helper().
09656 { 09657 return con ? con->name : NULL; 09658 }
| const char* ast_get_context_registrar | ( | struct ast_context * | c | ) |
Definition at line 9693 of file pbx.c.
References ast_context::registrar.
Referenced by handle_cli_dialplan_save(), show_debug_helper(), and show_dialplan_helper().
09694 { 09695 return c ? c->registrar : NULL; 09696 }
| const char* ast_get_extension_app | ( | struct ast_exten * | e | ) |
Definition at line 9723 of file pbx.c.
References ast_exten::app.
Referenced by _macro_exec(), ast_add_hint_nolock(), ast_extension_state2(), ast_get_hint(), ast_str_get_hint(), find_matching_endwhile(), handle_cli_dialplan_save(), handle_show_hint(), handle_show_hints(), handle_statechange(), manager_show_dialplan_helper(), and print_ext().
09724 { 09725 return e ? e->app : NULL; 09726 }
| void* ast_get_extension_app_data | ( | struct ast_exten * | e | ) |
Definition at line 9728 of file pbx.c.
References ast_exten::data.
Referenced by _macro_exec(), ast_get_hint(), ast_str_get_hint(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and print_ext().
09729 { 09730 return e ? e->data : NULL; 09731 }
| const char* ast_get_extension_cidmatch | ( | struct ast_exten * | e | ) |
Definition at line 9718 of file pbx.c.
References ast_exten::cidmatch.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), and handle_cli_dialplan_save().
09719 { 09720 return e ? e->cidmatch : NULL; 09721 }
| struct ast_context* ast_get_extension_context | ( | struct ast_exten * | exten | ) | [read] |
Definition at line 9660 of file pbx.c.
References ast_exten::parent.
Referenced by handle_show_hint(), and handle_show_hints().
09661 { 09662 return exten ? exten->parent : NULL; 09663 }
| const char* ast_get_extension_label | ( | struct ast_exten * | e | ) |
Definition at line 9670 of file pbx.c.
References ast_exten::label.
Referenced by handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
| int ast_get_extension_matchcid | ( | struct ast_exten * | e | ) |
Definition at line 9713 of file pbx.c.
References ast_exten::matchcid.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), and handle_cli_dialplan_save().
09714 { 09715 return e ? e->matchcid : 0; 09716 }
| const char* ast_get_extension_name | ( | struct ast_exten * | exten | ) |
Definition at line 9665 of file pbx.c.
References ast_exten::exten.
Referenced by ast_add_hint_nolock(), complete_core_show_hint(), complete_dialplan_remove_extension(), dundi_precache_full(), find_matching_priority(), handle_cli_dialplan_save(), handle_show_hint(), handle_show_hints(), manager_show_dialplan_helper(), and show_dialplan_helper().
09666 { 09667 return exten ? exten->exten : NULL; 09668 }
| int ast_get_extension_priority | ( | struct ast_exten * | exten | ) |
Definition at line 9685 of file pbx.c.
References ast_exten::priority.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and print_ext().
09686 { 09687 return exten ? exten->priority : -1; 09688 }
| const char* ast_get_extension_registrar | ( | struct ast_exten * | e | ) |
Definition at line 9698 of file pbx.c.
References ast_exten::registrar.
Referenced by handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
09699 { 09700 return e ? e->registrar : NULL; 09701 }
| int ast_get_hint | ( | char * | hint, | |
| int | hintsize, | |||
| char * | name, | |||
| int | namesize, | |||
| struct ast_channel * | c, | |||
| const char * | context, | |||
| const char * | exten | |||
| ) |
If an extension hint exists, return non-zero.
| 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 |
Definition at line 4442 of file pbx.c.
References ast_copy_string(), ast_get_extension_app(), ast_get_extension_app_data(), and ast_hint_extension().
Referenced by action_extensionstate(), get_cid_name(), get_destination(), hint_read(), manager_state_cb(), skinny_extensionstate_cb(), and state_notify_build_xml().
04443 { 04444 struct ast_exten *e = ast_hint_extension(c, context, exten); 04445 04446 if (e) { 04447 if (hint) 04448 ast_copy_string(hint, ast_get_extension_app(e), hintsize); 04449 if (name) { 04450 const char *tmp = ast_get_extension_app_data(e); 04451 if (tmp) 04452 ast_copy_string(name, tmp, namesize); 04453 } 04454 return -1; 04455 } 04456 return 0; 04457 }
| const char* ast_get_ignorepat_name | ( | struct ast_ignorepat * | ip | ) |
Definition at line 9680 of file pbx.c.
References ast_ignorepat::pattern.
Referenced by complete_dialplan_remove_ignorepat(), context_merge_incls_swits_igps_other_registrars(), handle_cli_dialplan_save(), lookup_c_ip(), manager_show_dialplan_helper(), and show_dialplan_helper().
09681 { 09682 return ip ? ip->pattern : NULL; 09683 }
| const char* ast_get_ignorepat_registrar | ( | struct ast_ignorepat * | ip | ) |
Definition at line 9708 of file pbx.c.
References ast_ignorepat::registrar.
Referenced by context_merge_incls_swits_igps_other_registrars(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
09709 { 09710 return ip ? ip->registrar : NULL; 09711 }
| const char* ast_get_include_name | ( | struct ast_include * | include | ) |
Definition at line 9675 of file pbx.c.
References ast_include::name.
Referenced by complete_dialplan_remove_include(), context_merge_incls_swits_igps_other_registrars(), find_matching_priority(), handle_cli_dialplan_save(), lookup_ci(), manager_show_dialplan_helper(), and show_dialplan_helper().
| const char* ast_get_include_registrar | ( | struct ast_include * | i | ) |
Definition at line 9703 of file pbx.c.
References ast_include::registrar.
Referenced by context_merge_incls_swits_igps_other_registrars(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
09704 { 09705 return i ? i->registrar : NULL; 09706 }
| const char* ast_get_switch_data | ( | struct ast_sw * | sw | ) |
Definition at line 9738 of file pbx.c.
References ast_sw::data.
Referenced by context_merge_incls_swits_igps_other_registrars(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
09739 { 09740 return sw ? sw->data : NULL; 09741 }
| int ast_get_switch_eval | ( | struct ast_sw * | sw | ) |
Definition at line 9743 of file pbx.c.
References ast_sw::eval.
Referenced by context_merge_incls_swits_igps_other_registrars().
09744 { 09745 return sw->eval; 09746 }
| const char* ast_get_switch_name | ( | struct ast_sw * | sw | ) |
Definition at line 9733 of file pbx.c.
References ast_sw::name.
Referenced by context_merge_incls_swits_igps_other_registrars(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
09734 { 09735 return sw ? sw->name : NULL; 09736 }
| const char* ast_get_switch_registrar | ( | struct ast_sw * | sw | ) |
Definition at line 9748 of file pbx.c.
References ast_sw::registrar.
Referenced by context_merge_incls_swits_igps_other_registrars(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
09749 { 09750 return sw ? sw->registrar : NULL; 09751 }
| int ast_goto_if_exists | ( | struct ast_channel * | chan, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority | |||
| ) |
Definition at line 9842 of file pbx.c.
References __ast_goto_if_exists().
Referenced by background_detect_exec(), channel_spy(), common_exec(), conf_run(), dial_exec_full(), goto_exten(), onedigit_goto(), priority_jump(), select_entry(), and valid_exit().
09843 { 09844 return __ast_goto_if_exists(chan, context, exten, priority, 0); 09845 }
| int ast_hashtab_compare_contexts | ( | const void * | ah_a, | |
| const void * | ah_b | |||
| ) |
hashtable functions for contexts
Definition at line 1013 of file pbx.c.
References ast_context::name.
Referenced by ast_context_find_or_create(), lua_register_switches(), and pbx_load_module().
01014 { 01015 const struct ast_context *ac = ah_a; 01016 const struct ast_context *bc = ah_b; 01017 if (!ac || !bc) /* safety valve, but it might prevent a crash you'd rather have happen */ 01018 return 1; 01019 /* assume context names are registered in a string table! */ 01020 return strcmp(ac->name, bc->name); 01021 }
| unsigned int ast_hashtab_hash_contexts | ( | const void * | obj | ) |
Definition at line 1056 of file pbx.c.
References ast_hashtab_hash_string(), and ast_context::name.
Referenced by ast_context_find_or_create(), lua_register_switches(), and pbx_load_module().
01057 { 01058 const struct ast_context *ac = obj; 01059 return ast_hashtab_hash_string(ac->name); 01060 }
| int ast_ignore_pattern | ( | const char * | context, | |
| const char * | pattern | |||
| ) |
Checks to see if a number should be ignored.
| context | context to search within | |
| pattern | to check whether it should be ignored or not |
| 0 | if the pattern should not be ignored | |
| non-zero | if the pattern should be ignored |
Definition at line 7552 of file pbx.c.
References ast_context_find(), ast_extension_match(), ast_context::ignorepats, ast_ignorepat::next, and ast_ignorepat::pattern.
Referenced by __analog_ss_thread(), analog_ss_thread(), ast_app_dtget(), disa_exec(), dp_lookup(), dundi_lookup_local(), handle_enbloc_call_message(), handle_soft_key_event_message(), handle_stimulus_message(), mgcp_ss(), and skinny_ss().
07553 { 07554 struct ast_context *con = ast_context_find(context); 07555 if (con) { 07556 struct ast_ignorepat *pat; 07557 for (pat = con->ignorepats; pat; pat = pat->next) { 07558 if (ast_extension_match(pat->pattern, pattern)) 07559 return 1; 07560 } 07561 } 07562 07563 return 0; 07564 }
| int ast_matchmore_extension | ( | struct ast_channel * | c, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority, | |||
| const char * | callerid | |||
| ) |
Looks to see if adding anything to this extension might match something. (exists ^ canmatch).
| 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 |
Definition at line 4500 of file pbx.c.
References E_MATCHMORE, and pbx_extension_helper().
Referenced by __analog_ss_thread(), __ast_pbx_run(), analog_ss_thread(), ast_app_dtget(), collect_digits(), disa_exec(), dp_lookup(), dundi_lookup_local(), handle_link_data(), handle_link_phone_dtmf(), local_dtmf_helper(), loopback_matchmore(), mgcp_ss(), pbx_builtin_background(), readexten_exec(), and skinny_ss().
04501 { 04502 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0); 04503 }
| void ast_merge_contexts_and_delete | ( | struct ast_context ** | extcontexts, | |
| struct ast_hashtab * | exttable, | |||
| const char * | registrar | |||
| ) |
Merge the temporary contexts into a global contexts list and delete from the global list the ones that are being added.
| extcontexts | pointer to the ast_context structure | |
| exttable | pointer to the ast_hashtab structure that contains all the elements in extcontexts | |
| registrar | of the context; if it's set the routine will delete all contexts that belong to that registrar; if NULL only the contexts that are specified in extcontexts |
Definition at line 6909 of file pbx.c.
References __ast_internal_context_destroy(), ast_exten::app, ast_add_extension_nolock(), ast_calloc, AST_EXTENSION_REMOVED, ast_free, ast_free_ptr, ast_hashtab_destroy(), ast_hashtab_end_traversal(), ast_hashtab_next(), ast_hashtab_start_traversal(), ast_hint_extension_nolock(), AST_LIST_APPEND_LIST, AST_LIST_EMPTY, AST_LIST_HEAD_INIT_VALUE, AST_LIST_INSERT_HEAD, AST_LIST_REMOVE_HEAD, ast_log(), ast_rdlock_contexts(), AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_strdup, ast_tvdiff_us(), ast_tvnow(), ast_unlock_contexts(), ast_verb, ast_wrlock_contexts(), ast_wrlock_contexts_version(), ast_state_cb::callback, ast_hint::callbacks, context_merge(), contexts, contexts_table, ast_state_cb::data, ast_exten::data, E_MATCH, ast_exten::exten, ast_hint::exten, ast_hint::laststate, LOG_WARNING, ast_context::name, ast_context::next, ast_sw::next, ast_exten::parent, pbx_find_extension(), PRIORITY_HINT, ast_context::registrar, and pbx_find_info::stacklen.
Referenced by lua_reload_extensions(), and pbx_load_module().
06910 { 06911 double ft; 06912 struct ast_context *tmp, *oldcontextslist; 06913 struct ast_hashtab *oldtable; 06914 struct store_hints store = AST_LIST_HEAD_INIT_VALUE; 06915 struct store_hint *this; 06916 struct ast_hint *hint; 06917 struct ast_exten *exten; 06918 int length; 06919 struct ast_state_cb *thiscb; 06920 struct ast_hashtab_iter *iter; 06921 06922 /* it is very important that this function hold the hint list lock _and_ the conlock 06923 during its operation; not only do we need to ensure that the list of contexts 06924 and extensions does not change, but also that no hint callbacks (watchers) are 06925 added or removed during the merge/delete process 06926 06927 in addition, the locks _must_ be taken in this order, because there are already 06928 other code paths that use this order 06929 */ 06930 06931 struct timeval begintime, writelocktime, endlocktime, enddeltime; 06932 int wrlock_ver; 06933 06934 begintime = ast_tvnow(); 06935 ast_rdlock_contexts(); 06936 iter = ast_hashtab_start_traversal(contexts_table); 06937 while ((tmp = ast_hashtab_next(iter))) { 06938 context_merge(extcontexts, exttable, tmp, registrar); 06939 } 06940 ast_hashtab_end_traversal(iter); 06941 wrlock_ver = ast_wrlock_contexts_version(); 06942 06943 ast_unlock_contexts(); /* this feels real retarded, but you must do 06944 what you must do If this isn't done, the following 06945 wrlock is a guraranteed deadlock */ 06946 ast_wrlock_contexts(); 06947 if (ast_wrlock_contexts_version() > wrlock_ver+1) { 06948 ast_log(LOG_WARNING,"==================!!!!!!!!!!!!!!!Something changed the contexts in the middle of merging contexts!\n"); 06949 } 06950 06951 AST_RWLIST_WRLOCK(&hints); 06952 writelocktime = ast_tvnow(); 06953 06954 /* preserve all watchers for hints associated with this registrar */ 06955 AST_RWLIST_TRAVERSE(&hints, hint, list) { 06956 if (!AST_LIST_EMPTY(&hint->callbacks) && !strcmp(registrar, hint->exten->parent->registrar)) { 06957 length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2 + sizeof(*this); 06958 if (!(this = ast_calloc(1, length))) 06959 continue; 06960 AST_LIST_APPEND_LIST(&this->callbacks, &hint->callbacks, entry); 06961 this->laststate = hint->laststate; 06962 this->context = this->data; 06963 strcpy(this->data, hint->exten->parent->name); 06964 this->exten = this->data + strlen(this->context) + 1; 06965 strcpy(this->exten, hint->exten->exten); 06966 AST_LIST_INSERT_HEAD(&store, this, list); 06967 } 06968 } 06969 06970 /* save the old table and list */ 06971 oldtable = contexts_table; 06972 oldcontextslist = contexts; 06973 06974 /* move in the new table and list */ 06975 contexts_table = exttable; 06976 contexts = *extcontexts; 06977 06978 /* restore the watchers for hints that can be found; notify those that 06979 cannot be restored 06980 */ 06981 while ((this = AST_LIST_REMOVE_HEAD(&store, list))) { 06982 struct pbx_find_info q = { .stacklen = 0 }; 06983 exten = pbx_find_extension(NULL, NULL, &q, this->context, this->exten, PRIORITY_HINT, NULL, "", E_MATCH); 06984 /* If this is a pattern, dynamically create a new extension for this 06985 * particular match. Note that this will only happen once for each 06986 * individual extension, because the pattern will no longer match first. 06987 */ 06988 if (exten && exten->exten[0] == '_') { 06989 ast_add_extension_nolock(exten->parent->name, 0, this->exten, PRIORITY_HINT, NULL, 06990 0, exten->app, ast_strdup(exten->data), ast_free_ptr, registrar); 06991 /* rwlocks are not recursive locks */ 06992 exten = ast_hint_extension_nolock(NULL, this->context, this->exten); 06993 } 06994 06995 /* Find the hint in the list of hints */ 06996 AST_RWLIST_TRAVERSE(&hints, hint, list) { 06997 if (hint->exten == exten) 06998 break; 06999 } 07000 if (!exten || !hint) { 07001 /* this hint has been removed, notify the watchers */ 07002 while ((thiscb = AST_LIST_REMOVE_HEAD(&this->callbacks, entry))) { 07003 thiscb->callback(this->context, this->exten, AST_EXTENSION_REMOVED, thiscb->data); 07004 ast_free(thiscb); 07005 } 07006 } else { 07007 AST_LIST_APPEND_LIST(&hint->callbacks, &this->callbacks, entry); 07008 hint->laststate = this->laststate; 07009 } 07010 ast_free(this); 07011 } 07012 07013 AST_RWLIST_UNLOCK(&hints); 07014 ast_unlock_contexts(); 07015 endlocktime = ast_tvnow(); 07016 07017 /* the old list and hashtab no longer are relevant, delete them while the rest of asterisk 07018 is now freely using the new stuff instead */ 07019 07020 ast_hashtab_destroy(oldtable, NULL); 07021 07022 for (tmp = oldcontextslist; tmp; ) { 07023 struct ast_context *next; /* next starting point */ 07024 next = tmp->next; 07025 __ast_internal_context_destroy(tmp); 07026 tmp = next; 07027 } 07028 enddeltime = ast_tvnow(); 07029 07030 ft = ast_tvdiff_us(writelocktime, begintime); 07031 ft /= 1000000.0; 07032 ast_verb(3,"Time to scan old dialplan and merge leftovers back into the new: %8.6f sec\n", ft); 07033 07034 ft = ast_tvdiff_us(endlocktime, writelocktime); 07035 ft /= 1000000.0; 07036 ast_verb(3,"Time to restore hints and swap in new dialplan: %8.6f sec\n", ft); 07037 07038 ft = ast_tvdiff_us(enddeltime, endlocktime); 07039 ft /= 1000000.0; 07040 ast_verb(3,"Time to delete the old dialplan: %8.6f sec\n", ft); 07041 07042 ft = ast_tvdiff_us(enddeltime, begintime); 07043 ft /= 1000000.0; 07044 ast_verb(3,"Total time merge_contexts_delete: %8.6f sec\n", ft); 07045 return; 07046 }
| int ast_parseable_goto | ( | struct ast_channel * | chan, | |
| const char * | goto_string | |||
| ) |
Definition at line 9905 of file pbx.c.
References pbx_parseable_goto().
Referenced by _while_exec(), check_goto_on_transfer(), dial_exec_full(), gosub_exec(), ivr_dispatch(), parkandannounce_exec(), pbx_builtin_goto(), and while_continue_exec().
09906 { 09907 return pbx_parseable_goto(chan, goto_string, 0); 09908 }
| int ast_pbx_outgoing_app | ( | const char * | type, | |
| int | format, | |||
| void * | data, | |||
| int | timeout, | |||
| const char * | app, | |||
| const char * | appdata, | |||
| int * | reason, | |||
| int | sync, | |||
| const char * | cid_num, | |||
| const char * | cid_name, | |||
| struct ast_variable * | vars, | |||
| const char * | account, | |||
| struct ast_channel ** | locked_channel | |||
| ) |
Synchronously or asynchronously make an outbound call and send it to a particular application with given extension
Definition at line 8393 of file pbx.c.
References __ast_request_and_dial(), ast_channel::_state, outgoing_helper::account, async_stat::app, app_tmp::app, async_stat::appdata, ast_calloc, ast_cdr_disposition(), ast_cdr_failed(), ast_cdr_setaccount(), ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_free, ast_hangup(), ast_log(), ast_pbx_outgoing_cdr_failed(), ast_pbx_run_app(), ast_pthread_create_detached, ast_set_variables(), AST_STATE_UP, ast_strlen_zero(), ast_variables_destroy(), ast_verb, async_wait(), ast_channel::cdr, async_stat::chan, app_tmp::chan, app_tmp::data, errno, ast_channel::hangupcause, LOG_WARNING, ast_channel::name, async_stat::p, app_tmp::t, async_stat::timeout, and outgoing_helper::vars.
Referenced by action_originate(), attempt_thread(), fast_originate(), orig_app(), and originate_exec().
08394 { 08395 struct ast_channel *chan; 08396 struct app_tmp *tmp; 08397 int res = -1, cdr_res = -1; 08398 struct outgoing_helper oh; 08399 08400 memset(&oh, 0, sizeof(oh)); 08401 oh.vars = vars; 08402 oh.account = account; 08403 08404 if (locked_channel) 08405 *locked_channel = NULL; 08406 if (ast_strlen_zero(app)) { 08407 res = -1; 08408 goto outgoing_app_cleanup; 08409 } 08410 if (synchronous) { 08411 chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh); 08412 if (chan) { 08413 ast_set_variables(chan, vars); 08414 if (account) 08415 ast_cdr_setaccount(chan, account); 08416 if (chan->_state == AST_STATE_UP) { 08417 res = 0; 08418 ast_verb(4, "Channel %s was answered.\n", chan->name); 08419 tmp = ast_calloc(1, sizeof(*tmp)); 08420 if (!tmp) 08421 res = -1; 08422 else { 08423 ast_copy_string(tmp->app, app, sizeof(tmp->app)); 08424 if (appdata) 08425 ast_copy_string(tmp->data, appdata, sizeof(tmp->data)); 08426 tmp->chan = chan; 08427 if (synchronous > 1) { 08428 if (locked_channel) 08429 ast_channel_unlock(chan); 08430 ast_pbx_run_app(tmp); 08431 } else { 08432 if (locked_channel) 08433 ast_channel_lock(chan); 08434 if (ast_pthread_create_detached(&tmp->t, NULL, ast_pbx_run_app, tmp)) { 08435 ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno)); 08436 ast_free(tmp); 08437 if (locked_channel) 08438 ast_channel_unlock(chan); 08439 ast_hangup(chan); 08440 res = -1; 08441 } else { 08442 if (locked_channel) 08443 *locked_channel = chan; 08444 } 08445 } 08446 } 08447 } else { 08448 ast_verb(4, "Channel %s was never answered.\n", chan->name); 08449 if (chan->cdr) { /* update the cdr */ 08450 /* here we update the status of the call, which sould be busy. 08451 * if that fails then we set the status to failed */ 08452 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 08453 ast_cdr_failed(chan->cdr); 08454 } 08455 ast_hangup(chan); 08456 } 08457 } 08458 08459 if (res < 0) { /* the call failed for some reason */ 08460 if (*reason == 0) { /* if the call failed (not busy or no answer) 08461 * update the cdr with the failed message */ 08462 cdr_res = ast_pbx_outgoing_cdr_failed(); 08463 if (cdr_res != 0) { 08464 res = cdr_res; 08465 goto outgoing_app_cleanup; 08466 } 08467 } 08468 } 08469 08470 } else { 08471 struct async_stat *as; 08472 if (!(as = ast_calloc(1, sizeof(*as)))) { 08473 res = -1; 08474 goto outgoing_app_cleanup; 08475 } 08476 chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh); 08477 if (!chan) { 08478 ast_free(as); 08479 res = -1; 08480 goto outgoing_app_cleanup; 08481 } 08482 as->chan = chan; 08483 ast_copy_string(as->app, app, sizeof(as->app)); 08484 if (appdata) 08485 ast_copy_string(as->appdata, appdata, sizeof(as->appdata)); 08486 as->timeout = timeout; 08487 ast_set_variables(chan, vars); 08488 if (account) 08489 ast_cdr_setaccount(chan, account); 08490 /* Start a new thread, and get something handling this channel. */ 08491 if (locked_channel) 08492 ast_channel_lock(chan); 08493 if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) { 08494 ast_log(LOG_WARNING, "Failed to start async wait\n"); 08495 ast_free(as); 08496 if (locked_channel) 08497 ast_channel_unlock(chan); 08498 ast_hangup(chan); 08499 res = -1; 08500 goto outgoing_app_cleanup; 08501 } else { 08502 if (locked_channel) 08503 *locked_channel = chan; 08504 } 08505 res = 0; 08506 } 08507 outgoing_app_cleanup: 08508 ast_variables_destroy(vars); 08509 return res; 08510 }
| int ast_pbx_outgoing_exten | ( | const char * | type, | |
| int | format, | |||
| void * | data, | |||
| int | timeout, | |||
| const char * | context, | |||
| const char * | exten, | |||
| int | priority, | |||
| int * | reason, | |||
| int | sync, | |||
| const char * | cid_num, | |||
| const char * | cid_name, | |||
| struct ast_variable * | vars, | |||
| const char * | account, | |||
| struct ast_channel ** | locked_channel | |||
| ) |
Synchronously or asynchronously make an outbound call and send it to a particular extension
Definition at line 8227 of file pbx.c.
References __ast_request_and_dial(), ast_channel::_state, outgoing_helper::account, ast_calloc, ast_cdr_disposition(), ast_cdr_failed(), ast_cdr_setaccount(), ast_channel_alloc, ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_exists_extension(), ast_free, ast_hangup(), ast_log(), ast_pbx_outgoing_cdr_failed(), ast_pbx_run(), ast_pbx_start(), ast_pthread_create_detached, ast_request_and_dial(), ast_set_variables(), AST_STATE_DOWN, AST_STATE_UP, ast_strlen_zero(), ast_variables_destroy(), ast_verb, async_wait(), ast_channel::cdr, async_stat::chan, outgoing_helper::cid_name, outgoing_helper::cid_num, async_stat::context, ast_channel::context, outgoing_helper::context, outgoing_helper::exten, ast_channel::hangupcause, LOG_ERROR, LOG_WARNING, ast_channel::name, async_stat::p, outgoing_helper::parent_channel, pbx_builtin_setvar_helper(), outgoing_helper::priority, set_ext_pri(), async_stat::timeout, and outgoing_helper::vars.
Referenced by action_originate(), attempt_thread(), fast_originate(), orig_exten(), and originate_exec().
08228 { 08229 struct ast_channel *chan; 08230 struct async_stat *as; 08231 int res = -1, cdr_res = -1; 08232 struct outgoing_helper oh; 08233 08234 if (synchronous) { 08235 oh.context = context; 08236 oh.exten = exten; 08237 oh.priority = priority; 08238 oh.cid_num = cid_num; 08239 oh.cid_name = cid_name; 08240 oh.account = account; 08241 oh.vars = vars; 08242 oh.parent_channel = NULL; 08243 08244 chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh); 08245 if (channel) { 08246 *channel = chan; 08247 if (chan) 08248 ast_channel_lock(chan); 08249 } 08250 if (chan) { 08251 if (chan->_state == AST_STATE_UP) { 08252 res = 0; 08253 ast_verb(4, "Channel %s was answered.\n", chan->name); 08254 08255 if (synchronous > 1) { 08256 if (channel) 08257 ast_channel_unlock(chan); 08258 if (ast_pbx_run(chan)) { 08259 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 08260 if (channel) 08261 *channel = NULL; 08262 ast_hangup(chan); 08263 chan = NULL; 08264 res = -1; 08265 } 08266 } else { 08267 if (ast_pbx_start(chan)) { 08268 ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name); 08269 if (channel) { 08270 *channel = NULL; 08271 ast_channel_unlock(chan); 08272 } 08273 ast_hangup(chan); 08274 res = -1; 08275 } 08276 chan = NULL; 08277 } 08278 } else { 08279 ast_verb(4, "Channel %s was never answered.\n", chan->name); 08280 08281 if (chan->cdr) { /* update the cdr */ 08282 /* here we update the status of the call, which sould be busy. 08283 * if that fails then we set the status to failed */ 08284 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 08285 ast_cdr_failed(chan->cdr); 08286 } 08287 08288 if (channel) { 08289 *channel = NULL; 08290 ast_channel_unlock(chan); 08291 } 08292 ast_hangup(chan); 08293 chan = NULL; 08294 } 08295 } 08296 08297 if (res < 0) { /* the call failed for some reason */ 08298 if (*reason == 0) { /* if the call failed (not busy or no answer) 08299 * update the cdr with the failed message */ 08300 cdr_res = ast_pbx_outgoing_cdr_failed(); 08301 if (cdr_res != 0) { 08302 res = cdr_res; 08303 goto outgoing_exten_cleanup; 08304 } 08305 } 08306 08307 /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */ 08308 /* check if "failed" exists */ 08309 if (ast_exists_extension(chan, context, "failed", 1, NULL)) { 08310 chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", NULL, 0, "OutgoingSpoolFailed"); 08311 if (chan) { 08312 char failed_reason[4] = ""; 08313 if (!ast_strlen_zero(context)) 08314 ast_copy_string(chan->context, context, sizeof(chan->context)); 08315 set_ext_pri(chan, "failed", 1); 08316 ast_set_variables(chan, vars); 08317 snprintf(failed_reason, sizeof(failed_reason), "%d", *reason); 08318 pbx_builtin_setvar_helper(chan, "REASON", failed_reason); 08319 if (account) 08320 ast_cdr_setaccount(chan, account); 08321 if (ast_pbx_run(chan)) { 08322 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 08323 ast_hangup(chan); 08324 } 08325 chan = NULL; 08326 } 08327 } 08328 } 08329 } else { 08330 if (!(as = ast_calloc(1, sizeof(*as)))) { 08331 res = -1; 08332 goto outgoing_exten_cleanup; 08333 } 08334 chan = ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name); 08335 if (channel) { 08336 *channel = chan; 08337 if (chan) 08338 ast_channel_lock(chan); 08339 } 08340 if (!chan) { 08341 ast_free(as); 08342 res = -1; 08343 goto outgoing_exten_cleanup; 08344 } 08345 as->chan = chan; 08346 ast_copy_string(as->context, context, sizeof(as->context)); 08347 set_ext_pri(as->chan, exten, priority); 08348 as->timeout = timeout; 08349 ast_set_variables(chan, vars); 08350 if (account) 08351 ast_cdr_setaccount(chan, account); 08352 if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) { 08353 ast_log(LOG_WARNING, "Failed to start async wait\n"); 08354 ast_free(as); 08355 if (channel) { 08356 *channel = NULL; 08357 ast_channel_unlock(chan); 08358 } 08359 ast_hangup(chan); 08360 res = -1; 08361 goto outgoing_exten_cleanup; 08362 } 08363 res = 0; 08364 } 08365 outgoing_exten_cleanup: 08366 ast_variables_destroy(vars); 08367 return res; 08368 }
| enum ast_pbx_result ast_pbx_run | ( | struct ast_channel * | c | ) |
Execute the PBX in the current thread.
| c | channel to run the pbx on |
| Zero | on success | |
| non-zero | on failure |
Definition at line 4929 of file pbx.c.
References ast_pbx_run_args().
Referenced by __analog_ss_thread(), analog_ss_thread(), ast_pbx_outgoing_exten(), async_wait(), do_notify(), mgcp_ss(), skinny_newcall(), and unistim_ss().
04930 { 04931 return ast_pbx_run_args(c, NULL); 04932 }
| enum ast_pbx_result ast_pbx_run_args | ( | struct ast_channel * | c, | |
| struct ast_pbx_args * | args | |||
| ) |
Execute the PBX in the current thread.
| c | channel to run the pbx on | |
| args | options for the pbx |
| Zero | on success | |
| non-zero | on failure |
Definition at line 4914 of file pbx.c.
References __ast_pbx_run(), AST_PBX_CALL_LIMIT, AST_PBX_SUCCESS, decrease_call_count(), and increase_call_count().
Referenced by ast_pbx_run(), dial_exec_full(), handle_gosub(), and try_calling().
04915 { 04916 enum ast_pbx_result res = AST_PBX_SUCCESS; 04917 04918 if (increase_call_count(c)) { 04919 return AST_PBX_CALL_LIMIT; 04920 } 04921 04922 res = __ast_pbx_run(c, args); 04923 04924 decrease_call_count(); 04925 04926 return res; 04927 }
| enum ast_pbx_result ast_pbx_start | ( | struct ast_channel * | c | ) |
Create a new thread and start the PBX.
| c | channel to start the pbx on |
| Zero | on success | |
| non-zero | on failure |
Definition at line 4892 of file pbx.c.
References ast_log(), AST_PBX_CALL_LIMIT, AST_PBX_FAILED, AST_PBX_SUCCESS, ast_pthread_create_detached, decrease_call_count(), increase_call_count(), LOG_WARNING, and pbx_thread().
Referenced by __oh323_new(), alsa_new(), ast_async_goto(), ast_iax2_new(), ast_pbx_outgoing_exten(), bridge_call_thread(), bridge_exec(), check_goto_on_transfer(), console_new(), dahdi_new(), dial_exec_full(), gtalk_new(), gtalk_newcall(), handle_request_invite(), jingle_new(), jingle_newcall(), local_call(), manage_parkinglot(), mgcp_new(), nbs_new(), oss_new(), pbx_start_chan(), phone_new(), rpt_call(), sip_new(), skinny_new(), unistim_new(), and usbradio_new().
04893 { 04894 pthread_t t; 04895 04896 if (!c) { 04897 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n"); 04898 return AST_PBX_FAILED; 04899 } 04900 04901 if (increase_call_count(c)) 04902 return AST_PBX_CALL_LIMIT; 04903 04904 /* Start a new thread, and get something handling this channel. */ 04905 if (ast_pthread_create_detached(&t, NULL, pbx_thread, c)) { 04906 ast_log(LOG_WARNING, "Failed to create new channel thread\n"); 04907 decrease_call_count(); 04908 return AST_PBX_FAILED; 04909 } 04910 04911 return AST_PBX_SUCCESS; 04912 }
| int ast_processed_calls | ( | void | ) |
Retrieve the total number of calls processed through the PBX since last restart.
Definition at line 4939 of file pbx.c.
References totalcalls.
Referenced by ast_var_Config(), handle_chanlist(), and handle_showcalls().
04940 { 04941 return totalcalls; 04942 }
| int ast_rdlock_context | ( | struct ast_context * | con | ) |
Read locks a given context.
| con | context to lock |
| 0 | on success | |
| -1 | on failure |
Definition at line 9642 of file pbx.c.
References ast_rwlock_rdlock(), and ast_context::lock.
Referenced by _macro_exec(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), dundi_precache_full(), find_matching_endwhile(), handle_cli_dialplan_save(), lookup_c_ip(), lookup_ci(), manager_show_dialplan_helper(), show_debug_helper(), and show_dialplan_helper().
09643 { 09644 return ast_rwlock_rdlock(&con->lock); 09645 }
| int ast_rdlock_contexts | ( | void | ) |
Read locks the context list.
| 0 | on success | |
| -1 | on error |
Definition at line 9624 of file pbx.c.
References ast_rwlock_rdlock(), and conlock.
Referenced by _macro_exec(), ast_context_find(), ast_context_find_or_create(), ast_context_lockmacro(), ast_context_unlockmacro(), ast_hint_extension(), ast_merge_contexts_and_delete(), complete_dialplan_add_extension(), complete_dialplan_add_ignorepat(), complete_dialplan_add_include(), complete_dialplan_remove_extension(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), complete_show_dialplan_context(), dundi_precache_full(), find_context_locked(), find_matching_endwhile(), handle_cli_dialplan_save(), handle_statechange(), manager_show_dialplan_helper(), pbx_extension_helper(), show_debug_helper(), show_dialplan_helper(), and unreference_cached_app().
09625 { 09626 return ast_rwlock_rdlock(&conlock); 09627 }
| int ast_register_switch | ( | struct ast_switch * | sw | ) |
Register an alternative dialplan switch.
| sw | switch to register |
| 0 | success | |
| non-zero | failure |
Definition at line 5461 of file pbx.c.
References ast_log(), AST_RWLIST_INSERT_TAIL, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, LOG_WARNING, and ast_switch::name.
Referenced by load_module().
05462 { 05463 struct ast_switch *tmp; 05464 05465 AST_RWLIST_WRLOCK(&switches); 05466 AST_RWLIST_TRAVERSE(&switches, tmp, list) { 05467 if (!strcasecmp(tmp->name, sw->name)) { 05468 AST_RWLIST_UNLOCK(&switches); 05469 ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name); 05470 return -1; 05471 } 05472 } 05473 AST_RWLIST_INSERT_TAIL(&switches, sw, list); 05474 AST_RWLIST_UNLOCK(&switches); 05475 05476 return 0; 05477 }
| int ast_spawn_extension | ( | struct ast_channel * | c, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority, | |||
| const char * | callerid, | |||
| int * | found, | |||
| int | combined_find_spawn | |||
| ) |
Launch a new extension (i.e. new stack).
| 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. |
| 0 | on success | |
| -1 | on failure. |
Definition at line 4505 of file pbx.c.
References E_SPAWN, and pbx_extension_helper().
Referenced by __ast_pbx_run(), _macro_exec(), ast_bridge_call(), dial_exec_full(), and loopback_exec().
04506 { 04507 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN, found, combined_find_spawn); 04508 }
| int ast_str_get_hint | ( | struct ast_str ** | hint, | |
| ssize_t | hintsize, | |||
| struct ast_str ** | name, | |||
| ssize_t | namesize, | |||
| struct ast_channel * | c, | |||
| const char * | context, | |||
| const char * | exten | |||
| ) |
If an extension hint exists, return non-zero.
| hint | buffer for hint | |
| hintsize | Maximum size of hint buffer (<0 to prevent growth, >0 to limit growth to that number of bytes, or 0 for unlimited growth) | |
| name | buffer for name portion of hint | |
| namesize | Maximum size of name buffer (<0 to prevent growth, >0 to limit growth to that number of bytes, or 0 for unlimited growth) | |
| c | Channel from which to return the hint. This is only important when the hint or name contains an expression to be expanded. | |
| context | which context to look in | |
| exten | which extension to search for |
Definition at line 4460 of file pbx.c.
References ast_get_extension_app(), ast_get_extension_app_data(), ast_hint_extension(), and ast_str_set().
Referenced by ast_str_retrieve_variable().
04461 { 04462 struct ast_exten *e = ast_hint_extension(c, context, exten); 04463 04464 if (!e) { 04465 return 0; 04466 } 04467 04468 if (hint) { 04469 ast_str_set(hint, hintsize, "%s", ast_get_extension_app(e)); 04470 } 04471 if (name) { 04472 const char *tmp = ast_get_extension_app_data(e); 04473 if (tmp) { 04474 ast_str_set(name, namesize, "%s", tmp); 04475 } 04476 } 04477 return -1; 04478 }
| const char* ast_str_retrieve_variable | ( | struct ast_str ** | buf, | |
| ssize_t | maxlen, | |||
| struct ast_channel * | chan, | |||
| struct varshead * | headp, | |||
| const char * | var | |||
| ) |
| buf | Result will be placed in this buffer. | |
| maxlen | -1 if the buffer should not grow, 0 if the buffer may grow to any size, and >0 if the buffer should grow only to that number of bytes. | |
| chan | Channel variables from which to extract values, and channel to pass to any dialplan functions. | |
| headp | If no channel is specified, a channel list from which to extract variable values | |
| var | Variable name to retrieve. |
Definition at line 2929 of file pbx.c.
References ARRAY_LEN, ast_channel_lock, ast_channel_unlock, ast_config_AST_SYSTEM_NAME, ast_debug, ast_eid_default, ast_eid_to_str(), AST_LIST_TRAVERSE, ast_rwlock_rdlock(), ast_rwlock_unlock(), ast_str_buffer(), ast_str_get_hint(), ast_str_set(), ast_str_substring(), ast_strdupa, ast_var_name(), ast_var_value(), ast_channel::cid, ast_callerid::cid_ani2, ast_callerid::cid_pres, ast_callerid::cid_tns, ast_callerid::cid_ton, ast_channel::context, ast_var_t::entries, ast_channel::exten, globals, globalslock, ast_channel::hangupcause, ast_channel::name, parse_variable_name(), ast_channel::priority, s, ast_channel::uniqueid, and ast_channel::varshead.
Referenced by ast_str_substitute_variables_full(), and pbx_retrieve_variable().
02930 { 02931 const char not_found = '\0'; 02932 char *tmpvar; 02933 const char *ret; 02934 const char *s; /* the result */ 02935 int offset, length; 02936 int i, need_substring; 02937 struct varshead *places[2] = { headp, &globals }; /* list of places where we may look */ 02938 02939 if (c) { 02940 ast_channel_lock(c); 02941 places[0] = &c->varshead; 02942 } 02943 /* 02944 * Make a copy of var because parse_variable_name() modifies the string. 02945 * Then if called directly, we might need to run substring() on the result; 02946 * remember this for later in 'need_substring', 'offset' and 'length' 02947 */ 02948 tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */ 02949 need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */); 02950 02951 /* 02952 * Look first into predefined variables, then into variable lists. 02953 * Variable 's' points to the result, according to the following rules: 02954 * s == ¬_found (set at the beginning) means that we did not find a 02955 * matching variable and need to look into more places. 02956 * If s != ¬_found, s is a valid result string as follows: 02957 * s = NULL if the variable does not have a value; 02958 * you typically do this when looking for an unset predefined variable. 02959 * s = workspace if the result has been assembled there; 02960 * typically done when the result is built e.g. with an snprintf(), 02961 * so we don't need to do an additional copy. 02962 * s != workspace in case we have a string, that needs to be copied 02963 * (the ast_copy_string is done once for all at the end). 02964 * Typically done when the result is already available in some string. 02965 */ 02966 s = ¬_found; /* default value */ 02967 if (c) { /* This group requires a valid channel */ 02968 /* Names with common parts are looked up a piece at a time using strncmp. */ 02969 if (!strncmp(var, "CALL", 4)) { 02970 if (!strncmp(var + 4, "ING", 3)) { 02971 if (!strcmp(var + 7, "PRES")) { /* CALLINGPRES */ 02972 ast_str_set(str, maxlen, "%d", c->cid.cid_pres); 02973 s = ast_str_buffer(*str); 02974 } else if (!strcmp(var + 7, "ANI2")) { /* CALLINGANI2 */ 02975 ast_str_set(str, maxlen, "%d", c->cid.cid_ani2); 02976 s = ast_str_buffer(*str); 02977 } else if (!strcmp(var + 7, "TON")) { /* CALLINGTON */ 02978 ast_str_set(str, maxlen, "%d", c->cid.cid_ton); 02979 s = ast_str_buffer(*str); 02980 } else if (!strcmp(var + 7, "TNS")) { /* CALLINGTNS */ 02981 ast_str_set(str, maxlen, "%d", c->cid.cid_tns); 02982 s = ast_str_buffer(*str); 02983 } 02984 } 02985 } else if (!strcmp(var, "HINT")) { 02986 s = ast_str_get_hint(str, maxlen, NULL, 0, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL; 02987 } else if (!strcmp(var, "HINTNAME")) { 02988 s = ast_str_get_hint(NULL, 0, str, maxlen, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL; 02989 } else if (!strcmp(var, "EXTEN")) { 02990 s = c->exten; 02991 } else if (!strcmp(var, "CONTEXT")) { 02992 s = c->context; 02993 } else if (!strcmp(var, "PRIORITY")) { 02994 ast_str_set(str, maxlen, "%d", c->priority); 02995 s = ast_str_buffer(*str); 02996 } else if (!strcmp(var, "CHANNEL")) { 02997 s = c->name; 02998 } else if (!strcmp(var, "UNIQUEID")) { 02999 s = c->uniqueid; 03000 } else if (!strcmp(var, "HANGUPCAUSE")) { 03001 ast_str_set(str, maxlen, "%d", c->hangupcause); 03002 s = ast_str_buffer(*str); 03003 } 03004 } 03005 if (s == ¬_found) { /* look for more */ 03006 if (!strcmp(var, "EPOCH")) { 03007 ast_str_set(str, maxlen, "%u", (int) time(NULL)); 03008 s = ast_str_buffer(*str); 03009 } else if (!strcmp(var, "SYSTEMNAME")) { 03010 s = ast_config_AST_SYSTEM_NAME; 03011 } else if (!strcmp(var, "ENTITYID")) { 03012 char workspace[20]; 03013 ast_eid_to_str(workspace, sizeof(workspace), &ast_eid_default); 03014 s = workspace; 03015 } 03016 } 03017 /* if not found, look into chanvars or global vars */ 03018 for (i = 0; s == ¬_found && i < ARRAY_LEN(places); i++) { 03019 struct ast_var_t *variables; 03020 if (!places[i]) 03021 continue; 03022 if (places[i] == &globals) 03023 ast_rwlock_rdlock(&globalslock); 03024 AST_LIST_TRAVERSE(places[i], variables, entries) { 03025 if (!strcasecmp(ast_var_name(variables), var)) { 03026 s = ast_var_value(variables); 03027 break; 03028 } 03029 } 03030 if (places[i] == &globals) 03031 ast_rwlock_unlock(&globalslock); 03032 } 03033 if (s == ¬_found || s == NULL) { 03034 ast_debug(5, "Result of '%s' is NULL\n", var); 03035 ret = NULL; 03036 } else { 03037 ast_debug(5, "Result of '%s' is '%s'\n", var, s); 03038 if (s != ast_str_buffer(*str)) { 03039 ast_str_set(str, maxlen, "%s", s); 03040 } 03041 ret = ast_str_buffer(*str); 03042 if (need_substring) { 03043 ret = ast_str_substring(*str, offset, length); 03044 ast_debug(2, "Final result of '%s' is '%s'\n", var, ret); 03045 } 03046 } 03047 03048 if (c) { 03049 ast_channel_unlock(c); 03050 } 03051 return ret; 03052 }
| void ast_str_substitute_variables | ( | struct ast_str ** | buf, | |
| ssize_t | maxlen, | |||
| struct ast_channel * | chan, | |||
| const char * | templ | |||
| ) |
| buf | Result will be placed in this buffer. | |
| maxlen | -1 if the buffer should not grow, 0 if the buffer may grow to any size, and >0 if the buffer should grow only to that number of bytes. | |
| chan | Channel variables from which to extract values, and channel to pass to any dialplan functions. | |
| templ | Variable template to expand. |
Definition at line 3709 of file pbx.c.
References ast_str_substitute_variables_full().
Referenced by _macro_exec(), acf_odbc_read(), acf_odbc_write(), cli_odbc_read(), cli_odbc_write(), config_curl(), custom_log(), cut_internal(), destroy_curl(), exec_exec(), func_mchan_read(), function_eval2(), function_fieldqty_helper(), handle_getvariablefull(), import_helper(), make_email_file(), realtime_curl(), realtime_multi_curl(), require_curl(), sendmail(), sendpage(), store_curl(), syslog_log(), tryexec_exec(), update2_curl(), and update_curl().
03710 { 03711 size_t used; 03712 ast_str_substitute_variables_full(buf, maxlen, chan, NULL, templ, &used); 03713 }
| void ast_str_substitute_variables_full | ( | struct ast_str ** | buf, | |
| ssize_t | maxlen, | |||
| struct ast_channel * | c, | |||
| struct varshead * | headp, | |||
| const char * | templ, | |||
| size_t * | used | |||
| ) |
| buf | Result will be placed in this buffer. | |
| maxlen | -1 if the buffer should not grow, 0 if the buffer may grow to any size, and >0 if the buffer should grow only to that number of bytes. | |
| c | Channel variables from which to extract values, and channel to pass to any dialplan functions. | |
| headp | If no channel is specified, a channel list from which to extract variable values | |
| templ | Variable template to expand. | |
| used | Number of bytes read from the template. |
Definition at line 3533 of file pbx.c.
References ast_channel_release(), ast_debug, ast_dummy_channel_alloc(), ast_free, ast_func_read2(), ast_log(), ast_str_append(), ast_str_append_substr(), ast_str_buffer(), ast_str_create(), ast_str_expr(), ast_str_reset(), ast_str_retrieve_variable(), ast_str_set_substr(), ast_str_strlen(), ast_str_substitute_variables_full(), ast_str_substring(), ast_strlen_zero(), len(), LOG_ERROR, LOG_WARNING, parse_variable_name(), and ast_channel::varshead.
Referenced by ast_str_substitute_variables(), ast_str_substitute_variables_full(), and ast_str_substitute_variables_varshead().
03534 { 03535 /* Substitutes variables into buf, based on string templ */ 03536 char *cp4 = NULL; 03537 const char *tmp, *whereweare; 03538 int orig_size = 0; 03539 int offset, offset2, isfunction; 03540 const char *nextvar, *nextexp, *nextthing; 03541 const char *vars, *vare; 03542 char *finalvars; 03543 int pos, brackets, needsub, len; 03544 struct ast_str *substr1 = ast_str_create(16), *substr2 = NULL, *substr3 = ast_str_create(16); 03545 03546 ast_str_reset(*buf); 03547 whereweare = tmp = templ; 03548 while (!ast_strlen_zero(whereweare)) { 03549 /* Assume we're copying the whole remaining string */ 03550 pos = strlen(whereweare); 03551 nextvar = NULL; 03552 nextexp = NULL; 03553 nextthing = strchr(whereweare, '$'); 03554 if (nextthing) { 03555 switch (nextthing[1]) { 03556 case '{': 03557 nextvar = nextthing; 03558 pos = nextvar - whereweare; 03559 break; 03560 case '[': 03561 nextexp = nextthing; 03562 pos = nextexp - whereweare; 03563 break; 03564 default: 03565 pos = 1; 03566 } 03567 } 03568 03569 if (pos) { 03570 /* Copy that many bytes */ 03571 ast_str_append_substr(buf, maxlen, whereweare, pos); 03572 03573 templ += pos; 03574 whereweare += pos; 03575 } 03576 03577 if (nextvar) { 03578 /* We have a variable. Find the start and end, and determine 03579 if we are going to have to recursively call ourselves on the 03580 contents */ 03581 vars = vare = nextvar + 2; 03582 brackets = 1; 03583 needsub = 0; 03584 03585 /* Find the end of it */ 03586 while (brackets && *vare) { 03587 if ((vare[0] == '$') && (vare[1] == '{')) { 03588 needsub++; 03589 } else if (vare[0] == '{') { 03590 brackets++; 03591 } else if (vare[0] == '}') { 03592 brackets--; 03593 } else if ((vare[0] == '$') && (vare[1] == '[')) 03594 needsub++; 03595 vare++; 03596 } 03597 if (brackets) 03598 ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n"); 03599 len = vare - vars - 1; 03600 03601 /* Skip totally over variable string */ 03602 whereweare += (len + 3); 03603 03604 /* Store variable name (and truncate) */ 03605 ast_str_set_substr(&substr1, 0, vars, len); 03606 ast_debug(5, "Evaluating '%s' (from '%s' len %d)\n", ast_str_buffer(substr1), vars, len); 03607 03608 /* Substitute if necessary */ 03609 if (needsub) { 03610 size_t used; 03611 if (!substr2) { 03612 substr2 = ast_str_create(16); 03613 } 03614 03615 ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used); 03616 finalvars = ast_str_buffer(substr2); 03617 } else { 03618 finalvars = ast_str_buffer(substr1); 03619 } 03620 03621 parse_variable_name(finalvars, &offset, &offset2, &isfunction); 03622 if (isfunction) { 03623 /* Evaluate function */ 03624 if (c || !headp) { 03625 cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3); 03626 } else { 03627 struct varshead old; 03628 struct ast_channel *bogus = ast_dummy_channel_alloc(); 03629 if (bogus) { 03630 memcpy(&old, &bogus->varshead, sizeof(old)); 03631 memcpy(&bogus->varshead, headp, sizeof(bogus->varshead)); 03632 cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3); 03633 /* Don't deallocate the varshead that was passed in */ 03634 memcpy(&bogus->varshead, &old, sizeof(bogus->varshead)); 03635 ast_channel_release(bogus); 03636 } else { 03637 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n"); 03638 } 03639 } 03640 ast_debug(2, "Function result is '%s'\n", cp4 ? cp4 : "(null)"); 03641 } else { 03642 /* Retrieve variable value */ 03643 ast_str_retrieve_variable(&substr3, 0, c, headp, finalvars); 03644 cp4 = ast_str_buffer(substr3); 03645 } 03646 if (cp4) { 03647 ast_str_substring(substr3, offset, offset2); 03648 ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3)); 03649 } 03650 } else if (nextexp) { 03651 /* We have an expression. Find the start and end, and determine 03652 if we are going to have to recursively call ourselves on the 03653 contents */ 03654 vars = vare = nextexp + 2; 03655 brackets = 1; 03656 needsub = 0; 03657 03658 /* Find the end of it */ 03659 while (brackets && *vare) { 03660 if ((vare[0] == '$') && (vare[1] == '[')) { 03661 needsub++; 03662 brackets++; 03663 vare++; 03664 } else if (vare[0] == '[') { 03665 brackets++; 03666 } else if (vare[0] == ']') { 03667 brackets--; 03668 } else if ((vare[0] == '$') && (vare[1] == '{')) { 03669 needsub++; 03670 vare++; 03671 } 03672 vare++; 03673 } 03674 if (brackets) 03675 ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n"); 03676 len = vare - vars - 1; 03677 03678 /* Skip totally over expression */ 03679 whereweare += (len + 3); 03680 03681 /* Store variable name (and truncate) */ 03682 ast_str_set_substr(&substr1, 0, vars, len); 03683 03684 /* Substitute if necessary */ 03685 if (needsub) { 03686 size_t used; 03687 if (!substr2) { 03688 substr2 = ast_str_create(16); 03689 } 03690 03691 ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used); 03692 finalvars = ast_str_buffer(substr2); 03693 } else { 03694 finalvars = ast_str_buffer(substr1); 03695 } 03696 03697 if (ast_str_expr(&substr3, 0, c, finalvars)) { 03698 ast_debug(2, "Expression result is '%s'\n", ast_str_buffer(substr3)); 03699 } 03700 ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3)); 03701 } 03702 } 03703 *used = ast_str_strlen(*buf) - orig_size; 03704 ast_free(substr1); 03705 ast_free(substr2); 03706 ast_free(substr3); 03707 }
| void ast_str_substitute_variables_varshead | ( | struct ast_str ** | buf, | |
| ssize_t | maxlen, | |||
| struct varshead * | headp, | |||
| const char * | templ | |||
| ) |
| buf | Result will be placed in this buffer. | |
| maxlen | -1 if the buffer should not grow, 0 if the buffer may grow to any size, and >0 if the buffer should grow only to that number of bytes. | |
| headp | If no channel is specified, a channel list from which to extract variable values | |
| templ | Variable template to expand. |
Definition at line 3715 of file pbx.c.
References ast_str_substitute_variables_full().
Referenced by add_user_extension(), build_user_routes(), phoneprov_callback(), pp_each_extension_helper(), and pp_each_user_helper().
03716 { 03717 size_t used; 03718 ast_str_substitute_variables_full(buf, maxlen, NULL, headp, templ, &used); 03719 }
| int ast_unlock_context | ( | struct ast_context * | con | ) |
| Unlocks | the given context |
| con | context to unlock |
| 0 | on success | |
| -1 | on failure |
Definition at line 9647 of file pbx.c.
References ast_rwlock_unlock(), and ast_context::lock.
Referenced by __ast_context_destroy(), _macro_exec(), ast_add_extension2_lockopt(), ast_context_add_ignorepat2(), ast_context_add_include2(), ast_context_add_switch2(), ast_context_remove_extension_callerid2(), ast_context_remove_ignorepat2(), ast_context_remove_include2(), ast_context_remove_switch2(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), dundi_precache_full(), find_matching_endwhile(), handle_cli_dialplan_save(), lookup_c_ip(), lookup_ci(), manager_show_dialplan_helper(), show_debug_helper(), and show_dialplan_helper().
09648 { 09649 return ast_rwlock_unlock(&con->lock); 09650 }
| int ast_unlock_contexts | ( | void | ) |
Unlocks contexts.
| 0 | on success | |
| -1 | on failure |
Definition at line 9629 of file pbx.c.
References ast_rwlock_unlock(), and conlock.
Referenced by _macro_exec(), ast_add_extension(), ast_context_add_ignorepat(), ast_context_add_include(), ast_context_add_switch(), ast_context_destroy(), ast_context_find(), ast_context_find_or_create(), ast_context_lockmacro(), ast_context_remove_extension_callerid(), ast_context_remove_ignorepat(), ast_context_remove_include(), ast_context_remove_switch(), ast_context_unlockmacro(), ast_hint_extension(), ast_merge_contexts_and_delete(), complete_dialplan_add_extension(), complete_dialplan_add_ignorepat(), complete_dialplan_add_include(), complete_dialplan_remove_extension(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), complete_show_dialplan_context(), dundi_precache_full(), find_context_locked(), find_matching_endwhile(), handle_cli_dialplan_save(), handle_statechange(), manager_show_dialplan_helper(), pbx_extension_helper(), show_debug_helper(), show_dialplan_helper(), and unreference_cached_app().
09630 { 09631 return ast_rwlock_unlock(&conlock); 09632 }
| void ast_unregister_switch | ( | struct ast_switch * | sw | ) |
Unregister an alternative switch.
| sw | switch to unregister |
Definition at line 5479 of file pbx.c.
References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.
Referenced by __unload_module(), and unload_module().
05480 { 05481 AST_RWLIST_WRLOCK(&switches); 05482 AST_RWLIST_REMOVE(&switches, sw, list); 05483 AST_RWLIST_UNLOCK(&switches); 05484 }
| struct ast_exten* ast_walk_context_extensions | ( | struct ast_context * | con, | |
| struct ast_exten * | priority | |||
| ) | [read] |
Definition at line 9761 of file pbx.c.
References ast_exten::next, and ast_context::root.
Referenced by complete_dialplan_remove_extension(), dundi_precache_full(), find_matching_priority(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), pbx_find_extension(), show_dialplan_helper(), and unreference_cached_app().
09763 { 09764 if (!exten) 09765 return con ? con->root : NULL; 09766 else 09767 return exten->next; 09768 }
| struct ast_ignorepat* ast_walk_context_ignorepats | ( | struct ast_context * | con, | |
| struct ast_ignorepat * | ip | |||
| ) | [read] |
Definition at line 9794 of file pbx.c.
References ast_context::ignorepats, and ast_ignorepat::next.
Referenced by complete_dialplan_remove_ignorepat(), context_merge_incls_swits_igps_other_registrars(), handle_cli_dialplan_save(), lookup_c_ip(), manager_show_dialplan_helper(), and show_dialplan_helper().
09796 { 09797 if (!ip) 09798 return con ? con->ignorepats : NULL; 09799 else 09800 return ip->next; 09801 }
| struct ast_include* ast_walk_context_includes | ( | struct ast_context * | con, | |
| struct ast_include * | inc | |||
| ) | [read] |
Definition at line 9785 of file pbx.c.
References ast_context::includes, and ast_include::next.
Referenced by ast_context_verify_includes(), complete_dialplan_remove_include(), context_merge_incls_swits_igps_other_registrars(), find_matching_priority(), handle_cli_dialplan_save(), lookup_ci(), manager_show_dialplan_helper(), and show_dialplan_helper().
09787 { 09788 if (!inc) 09789 return con ? con->includes : NULL; 09790 else 09791 return inc->next; 09792 }
| struct ast_sw* ast_walk_context_switches | ( | struct ast_context * | con, | |
| struct ast_sw * | sw | |||
| ) | [read] |
Definition at line 9770 of file pbx.c.
References ast_context::alts, AST_LIST_FIRST, and AST_LIST_NEXT.
Referenced by context_merge_incls_swits_igps_other_registrars(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
09772 { 09773 if (!sw) 09774 return con ? AST_LIST_FIRST(&con->alts) : NULL; 09775 else 09776 return AST_LIST_NEXT(sw, list); 09777 }
| struct ast_context* ast_walk_contexts | ( | struct ast_context * | con | ) | [read] |
Definition at line 9756 of file pbx.c.
References contexts, and ast_context::next.
Referenced by _macro_exec(), ast_context_find(), complete_dialplan_add_extension(), complete_dialplan_add_ignorepat(), complete_dialplan_add_include(), complete_dialplan_remove_extension(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), complete_show_dialplan_context(), dundi_precache_full(), find_matching_endwhile(), find_matching_priority(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), pbx_load_module(), show_debug_helper(), show_dialplan_helper(), and unreference_cached_app().
| struct ast_exten* ast_walk_extension_priorities | ( | struct ast_exten * | exten, | |
| struct ast_exten * | priority | |||
| ) | [read] |
Definition at line 9779 of file pbx.c.
References ast_exten::peer.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), show_dialplan_helper(), and unreference_cached_app().
09781 { 09782 return priority ? priority->peer : exten; 09783 }
| int ast_wrlock_context | ( | struct ast_context * | con | ) |
Write locks a given context.
| con | context to lock |
| 0 | on success | |
| -1 | on failure |
Definition at line 9637 of file pbx.c.
References ast_rwlock_wrlock(), and ast_context::lock.
Referenced by __ast_context_destroy(), ast_add_extension2_lockopt(), ast_context_add_ignorepat2(), ast_context_add_include2(), ast_context_add_switch2(), ast_context_remove_extension_callerid2(), ast_context_remove_ignorepat2(), ast_context_remove_include2(), and ast_context_remove_switch2().
09638 { 09639 return ast_rwlock_wrlock(&con->lock); 09640 }
| int ast_wrlock_contexts | ( | void | ) |
Write locks the context list.
| 0 | on success | |
| -1 | on error |
Definition at line 9616 of file pbx.c.
References ast_atomic_fetchadd_int(), ast_rwlock_wrlock(), conlock, and conlock_wrlock_version.
Referenced by ast_context_destroy(), ast_context_find_or_create(), ast_merge_contexts_and_delete(), and complete_dialplan_remove_include().
09617 { 09618 int res = ast_rwlock_wrlock(&conlock); 09619 if (!res) 09620 ast_atomic_fetchadd_int(&conlock_wrlock_version, 1); 09621 return res; 09622 }
| int ast_wrlock_contexts_version | ( | void | ) |
Definition at line 9608 of file pbx.c.
References conlock_wrlock_version.
Referenced by ast_merge_contexts_and_delete().
09609 { 09610 return conlock_wrlock_version; 09611 }
| void pbx_builtin_clear_globals | ( | void | ) |
Definition at line 9453 of file pbx.c.
References AST_LIST_REMOVE_HEAD, ast_rwlock_unlock(), ast_rwlock_wrlock(), ast_var_delete(), ast_var_t::entries, globals, and globalslock.
Referenced by handle_cli_dialplan_reload(), and reload().
09454 { 09455 struct ast_var_t *vardata; 09456 09457 ast_rwlock_wrlock(&globalslock); 09458 while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries))) 09459 ast_var_delete(vardata); 09460 ast_rwlock_unlock(&globalslock); 09461 }
| const char* pbx_builtin_getvar_helper | ( | struct ast_channel * | chan, | |
| const char * | name | |||
| ) |
Return a pointer to the value of the corresponding channel variable.
This function will return a pointer to the buffer inside the channel variable. This value should only be accessed with the channel locked. If the value needs to be kept around, it should be done by using the following thread-safe code:
const char *var; ast_channel_lock(chan); if ((var = pbx_builtin_getvar_helper(chan, "MYVAR"))) { var = ast_strdupa(var); } ast_channel_unlock(chan);
Definition at line 9223 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, AST_LIST_TRAVERSE, ast_rwlock_rdlock(), ast_rwlock_unlock(), ast_var_name(), ast_var_value(), globals, globalslock, and ast_channel::varshead.
Referenced by __ast_pbx_run(), _macro_exec(), _while_exec(), agentmonitoroutgoing_exec(), analog_call(), array(), array_insert(), array_remove(), ast_bridge_call(), ast_bridge_timelimit(), ast_call_forward(), ast_channel_connected_line_macro(), ast_eivr_getvariable(), ast_hangup(), ast_monitor_stop(), bridge_play_sounds(), builtin_atxfer(), builtin_automixmonitor(), builtin_automonitor(), check_goto_on_transfer(), common_exec(), conf_run(), confbridge_exec(), crement_function_read(), dahdi_call(), dahdi_hangup(), dial_exec_full(), do_forward(), dundi_exec(), dundi_helper(), feature_interpret(), find_by_mark(), find_conf_realtime(), findparkinglotname(), func_channel_read(), get_also_info(), get_index(), get_refer_info(), global_read(), hash_read(), iax2_exec(), import_ch(), leave_voicemail(), listfilter(), local_attended_transfer(), local_hangup(), local_read(), login_exec(), macro_fixup(), minivm_delete_exec(), minivm_notify_exec(), misdn_answer(), misdn_hangup(), morsecode_exec(), notify_new_message(), oh323_call(), oh323_hangup(), park_call_full(), park_space_reserve(), queue_exec(), real_ctx(), retrydial_exec(), ring_entry(), run_agi(), set_config_flags(), set_local_info(), sip_addheader(), sla_trunk_exec(), speech_background(), try_calling(), try_suggested_sip_codec(), update_bridge_vars(), and wait_for_answer().
09224 { 09225 struct ast_var_t *variables; 09226 const char *ret = NULL; 09227 int i; 09228 struct varshead *places[2] = { NULL, &globals }; 09229 09230 if (!name) 09231 return NULL; 09232 09233 if (chan) { 09234 ast_channel_lock(chan); 09235 places[0] = &chan->varshead; 09236 } 09237 09238 for (i = 0; i < 2; i++) { 09239 if (!places[i]) 09240 continue; 09241 if (places[i] == &globals) 09242 ast_rwlock_rdlock(&globalslock); 09243 AST_LIST_TRAVERSE(places[i], variables, entries) { 09244 if (!strcmp(name, ast_var_name(variables))) { 09245 ret = ast_var_value(variables); 09246 break; 09247 } 09248 } 09249 if (places[i] == &globals) 09250 ast_rwlock_unlock(&globalslock); 09251 if (ret) 09252 break; 09253 } 09254 09255 if (chan) 09256 ast_channel_unlock(chan); 09257 09258 return ret; 09259 }
| void pbx_builtin_pushvar_helper | ( | struct ast_channel * | chan, | |
| const char * | name, | |||
| const char * | value | |||
| ) |
Add a variable to the channel variable stack, without removing any previously set value.
Definition at line 9261 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, ast_func_write(), AST_LIST_INSERT_HEAD, ast_log(), ast_rwlock_unlock(), ast_rwlock_wrlock(), ast_strdupa, ast_var_assign(), ast_verb, globals, globalslock, LOG_WARNING, and ast_channel::varshead.
Referenced by acf_odbc_read(), acf_odbc_write(), cli_odbc_read(), cli_odbc_write(), and frame_set_var().
09262 { 09263 struct ast_var_t *newvariable; 09264 struct varshead *headp; 09265 09266 if (name[strlen(name)-1] == ')') { 09267 char *function = ast_strdupa(name); 09268 09269 ast_log(LOG_WARNING, "Cannot push a value onto a function\n"); 09270 ast_func_write(chan, function, value); 09271 return; 09272 } 09273 09274 if (chan) { 09275 ast_channel_lock(chan); 09276 headp = &chan->varshead; 09277 } else { 09278 ast_rwlock_wrlock(&globalslock); 09279 headp = &globals; 09280 } 09281 09282 if (value) { 09283 if (headp == &globals) 09284 ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value); 09285 newvariable = ast_var_assign(name, value); 09286 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 09287 } 09288 09289 if (chan) 09290 ast_channel_unlock(chan); 09291 else 09292 ast_rwlock_unlock(&globalslock); 09293 }
| int pbx_builtin_raise_exception | ( | struct ast_channel * | chan, | |
| const char * | data | |||
| ) |
Definition at line 3066 of file pbx.c.
References ast_calloc, ast_channel_datastore_add(), ast_channel_datastore_find(), ast_datastore_alloc, ast_datastore_free(), ast_free, ast_string_field_init, ast_string_field_set, ast_channel::context, ast_datastore::data, exception_store_info, ast_channel::exten, ast_channel::priority, pbx_exception::priority, and set_ext_pri().
Referenced by __ast_pbx_run().
03067 { 03068 struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL); 03069 struct pbx_exception *exception = NULL; 03070 03071 if (!ds) { 03072 ds = ast_datastore_alloc(&exception_store_info, NULL); 03073 if (!ds) 03074 return -1; 03075 exception = ast_calloc(1, sizeof(struct pbx_exception)); 03076 if (!exception) { 03077 ast_datastore_free(ds); 03078 return -1; 03079 } 03080 if (ast_string_field_init(exception, 128)) { 03081 ast_free(exception); 03082 ast_datastore_free(ds); 03083 return -1; 03084 } 03085 ds->data = exception; 03086 ast_channel_datastore_add(chan, ds); 03087 } else 03088 exception = ds->data; 03089 03090 ast_string_field_set(exception, reason, reason); 03091 ast_string_field_set(exception, context, chan->context); 03092 ast_string_field_set(exception, exten, chan->exten); 03093 exception->priority = chan->priority; 03094 set_ext_pri(chan, "e", 0); 03095 return 0; 03096 }
| int pbx_builtin_serialize_variables | ( | struct ast_channel * | chan, | |
| struct ast_str ** | buf | |||
| ) |
Create a human-readable string, specifying all variables and their corresponding values.
| chan | Channel from which to read variables | |
| buf | Dynamic string in which to place the result (should be allocated with ast_str_create). |
Definition at line 9192 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, AST_LIST_TRAVERSE, ast_log(), ast_str_append(), ast_str_reset(), ast_var_name(), ast_var_value(), ast_var_t::entries, LOG_ERROR, total, var, and ast_channel::varshead.
Referenced by ast_var_channels_table(), dumpchan_exec(), handle_show_chanvar(), handle_showchan(), and vars2manager().
09193 { 09194 struct ast_var_t *variables; 09195 const char *var, *val; 09196 int total = 0; 09197 09198 if (!chan) 09199 return 0; 09200 09201 ast_str_reset(*buf); 09202 09203 ast_channel_lock(chan); 09204 09205 AST_LIST_TRAVERSE(&chan->varshead, variables, entries) { 09206 if ((var = ast_var_name(variables)) && (val = ast_var_value(variables)) 09207 /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */ 09208 ) { 09209 if (ast_str_append(buf, 0, "%s=%s\n", var, val) < 0) { 09210 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n"); 09211 break; 09212 } else 09213 total++; 09214 } else 09215 break; 09216 } 09217 09218 ast_channel_unlock(chan); 09219 09220 return total; 09221 }
| int pbx_builtin_setvar | ( | struct ast_channel * | chan, | |
| const char * | data | |||
| ) |
Parse and set a single channel variable, where the name and value are separated with an '=' character.
Definition at line 9352 of file pbx.c.
References ast_compat_app_set, ast_log(), ast_strdupa, ast_strlen_zero(), LOG_WARNING, pbx_builtin_setvar_helper(), pbx_builtin_setvar_multiple(), strsep(), and value.
Referenced by ast_compile_ael2(), and rpt_exec().
09353 { 09354 char *name, *value, *mydata; 09355 09356 if (ast_compat_app_set) { 09357 return pbx_builtin_setvar_multiple(chan, data); 09358 } 09359 09360 if (ast_strlen_zero(data)) { 09361 ast_log(LOG_WARNING, "Set requires one variable name/value pair.\n"); 09362 return 0; 09363 } 09364 09365 mydata = ast_strdupa(data); 09366 name = strsep(&mydata, "="); 09367 value = mydata; 09368 if (strchr(name, ' ')) 09369 ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, mydata); 09370 09371 pbx_builtin_setvar_helper(chan, name, value); 09372 return(0); 09373 }
| void pbx_builtin_setvar_helper | ( | struct ast_channel * | chan, | |
| const char * | name, | |||
| const char * | value | |||
| ) |
Add a variable to the channel variable stack, removing the most recently set value for the same name.
Definition at line 9295 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, ast_func_write(), AST_LIST_INSERT_HEAD, AST_LIST_REMOVE, AST_LIST_TRAVERSE, ast_rwlock_unlock(), ast_rwlock_wrlock(), ast_strdupa, ast_var_assign(), ast_var_delete(), ast_var_name(), ast_verb, EVENT_FLAG_DIALPLAN, globals, globalslock, manager_event, ast_channel::name, ast_channel::uniqueid, and ast_channel::varshead.
Referenced by __ast_pbx_run(), __oh323_new(), _macro_exec(), _while_exec(), acf_curl_helper(), acf_fetch(), acf_odbc_read(), acf_odbc_write(), acf_transaction_write(), action_atxfer(), action_setvar(), admin_exec(), agi_exec_full(), aji_status_exec(), analog_ss_thread(), aqm_exec(), array(), array_insert(), array_remove(), ast_bridge_call(), ast_cel_fabricate_channel_from_event(), ast_eivr_setvariable(), ast_iax2_new(), ast_monitor_start(), ast_pbx_outgoing_exten(), ast_rtp_instance_set_stats_vars(), ast_set_variables(), asyncgoto_exec(), background_detect_exec(), bridge_exec(), bridge_play_sounds(), builtin_atxfer(), builtin_automixmonitor(), builtin_automonitor(), builtin_blindtransfer(), cb_events(), chanavail_exec(), change_t38_state(), channel_spy(), commit_exec(), conf_run(), controlplayback_exec(), count_exec(), crement_function_read(), dahdi_handle_dtmfup(), dahdi_new(), dial_exec_full(), disa_exec(), do_waiting(), end_bridge_callback(), export_aoc_vars(), export_ch(), feature_exec_app(), feature_request_and_dial(), frame_set_var(), func_mchan_write(), function_db_delete(), function_db_exists(), function_db_read(), function_realtime_store(), get_rdnis(), get_refer_info(), global_write(), gosub_release_frame(), handle_request_bye(), handle_request_refer(), handle_response(), handle_set_chanvar(), handle_set_global(), handle_setvariable(), hash_read(), hash_write(), isAnsweringMachine(), leave_queue(), leave_voicemail(), local_hangup(), lua_set_variable(), lua_set_variable_value(), macro_fixup(), manage_parkinglot(), mgcp_new(), minivm_accmess_exec(), minivm_delete_exec(), minivm_greet_exec(), minivm_notify_exec(), minivm_record_exec(), misdn_call(), mixmonitor_exec(), my_handle_dtmfup(), originate_exec(), ospauth_exec(), ospfinished_exec(), osplookup_exec(), ospnext_exec(), park_exec_full(), parse_moved_contact(), pbx_builtin_background(), pbx_builtin_importvar(), pbx_builtin_setvar(), pbx_builtin_setvar_multiple(), pbx_load_config(), phase_e_handler(), play_message_datetime(), playback_exec(), pqm_exec(), prep_email_sub_vars(), privacy_exec(), process_ast_dsp(), read_exec(), readexten_exec(), readfile_exec(), realtimefield_read(), record_exec(), return_exec(), rollback_exec(), rotate_file(), rpt_exec(), rqm_exec(), sendimage_exec(), sendtext_exec(), sendurl_exec(), set(), set_queue_result(), sip_addheader(), sip_hangup(), sip_new(), skinny_new(), sla_calc_trunk_timeouts(), sla_station_exec(), sla_trunk_exec(), socket_process(), speech_create(), start_monitor_exec(), system_exec_helper(), transfer_exec(), transmit(), tryexec_exec(), update_bridge_vars(), update_qe_rule(), upqm_exec(), vm_box_exists(), vm_exec(), vmauthenticate(), waituntil_exec(), and zapateller_exec().
09296 { 09297 struct ast_var_t *newvariable; 09298 struct varshead *headp; 09299 const char *nametail = name; 09300 09301 if (name[strlen(name) - 1] == ')') { 09302 char *function = ast_strdupa(name); 09303 09304 ast_func_write(chan, function, value); 09305 return; 09306 } 09307 09308 if (chan) { 09309 ast_channel_lock(chan); 09310 headp = &chan->varshead; 09311 } else { 09312 ast_rwlock_wrlock(&globalslock); 09313 headp = &globals; 09314 } 09315 09316 /* For comparison purposes, we have to strip leading underscores */ 09317 if (*nametail == '_') { 09318 nametail++; 09319 if (*nametail == '_') 09320 nametail++; 09321 } 09322 09323 AST_LIST_TRAVERSE (headp, newvariable, entries) { 09324 if (strcasecmp(ast_var_name(newvariable), nametail) == 0) { 09325 /* there is already such a variable, delete it */ 09326 AST_LIST_REMOVE(headp, newvariable, entries); 09327 ast_var_delete(newvariable); 09328 break; 09329 } 09330 } 09331 09332 if (value) { 09333 if (headp == &globals) 09334 ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value); 09335 newvariable = ast_var_assign(name, value); 09336 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 09337 manager_event(EVENT_FLAG_DIALPLAN, "VarSet", 09338 "Channel: %s\r\n" 09339 "Variable: %s\r\n" 09340 "Value: %s\r\n" 09341 "Uniqueid: %s\r\n", 09342 chan ? chan->name : "none", name, value, 09343 chan ? chan->uniqueid : "none"); 09344 } 09345 09346 if (chan) 09347 ast_channel_unlock(chan); 09348 else 09349 ast_rwlock_unlock(&globalslock); 09350 }
| int pbx_builtin_setvar_multiple | ( | struct ast_channel * | chan, | |
| const char * | data | |||
| ) |
Parse and set multiple channel variables, where the pairs are separated by the ',' character, and name and value are separated with an '=' character.
Definition at line 9375 of file pbx.c.
References AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), AST_NONSTANDARD_APP_ARGS, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_channel::context, ast_channel::exten, LOG_WARNING, ast_channel::name, pbx_builtin_setvar_helper(), ast_channel::priority, and value.
Referenced by pbx_builtin_setvar(), queue_function_var(), set_queue_variables(), and try_calling().
09376 { 09377 char *data; 09378 int x; 09379 AST_DECLARE_APP_ARGS(args, 09380 AST_APP_ARG(pair)[24]; 09381 ); 09382 AST_DECLARE_APP_ARGS(pair, 09383 AST_APP_ARG(name); 09384 AST_APP_ARG(value); 09385 ); 09386 09387 if (ast_strlen_zero(vdata)) { 09388 ast_log(LOG_WARNING, "MSet requires at least one variable name/value pair.\n"); 09389 return 0; 09390 } 09391 09392 data = ast_strdupa(vdata); 09393 AST_STANDARD_APP_ARGS(args, data); 09394 09395 for (x = 0; x < args.argc; x++) { 09396 AST_NONSTANDARD_APP_ARGS(pair, args.pair[x], '='); 09397 if (pair.argc == 2) { 09398 pbx_builtin_setvar_helper(chan, pair.name, pair.value); 09399 if (strchr(pair.name, ' ')) 09400 ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", pair.name, pair.value); 09401 } else if (!chan) { 09402 ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '='\n", pair.name); 09403 } else { 09404 ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '=' (in %s@%s:%d\n", pair.name, chan->exten, chan->context, chan->priority); 09405 } 09406 } 09407 09408 return 0; 09409 }
| int pbx_checkcondition | ( | const char * | condition | ) |
Evaluate a condition.
| 0 | if the condition is NULL or of zero length | |
| int | If the string is an integer, the integer representation of the integer is returned | |
| 1 | Any other non-empty string |
Definition at line 9463 of file pbx.c.
References ast_strlen_zero().
Referenced by _macro_exec(), _while_exec(), acf_if(), execif_exec(), gosubif_exec(), macroif_exec(), and pbx_builtin_gotoif().
09464 { 09465 int res; 09466 if (ast_strlen_zero(condition)) { /* NULL or empty strings are false */ 09467 return 0; 09468 } else if (sscanf(condition, "%30d", &res) == 1) { /* Numbers are evaluated for truth */ 09469 return res; 09470 } else { /* Strings are true */ 09471 return 1; 09472 } 09473 }
| int pbx_exec | ( | struct ast_channel * | c, | |
| struct ast_app * | app, | |||
| const char * | data | |||
| ) |
Execute an application.
| c | channel to execute on | |
| app | which app to execute | |
| data | the data passed into the app |
| 0 | success | |
| -1 | failure |
| c | Channel |
| app | Application |
| data | Data for execution |
Definition at line 1341 of file pbx.c.
References __ast_module_user_add(), __ast_module_user_remove(), ast_channel::appl, ast_cdr_setapp(), AST_CEL_APP_END, AST_CEL_APP_START, ast_cel_report_event(), ast_check_hangup(), ast_log(), ast_opt_dont_warn, ast_strlen_zero(), ast_channel::cdr, ast_channel::data, ast_app::execute, LOG_WARNING, ast_app::module, ast_app::name, and S_OR.
Referenced by answer_exec_run(), ast_app_run_macro(), ast_bridge_call(), ast_pbx_run_app(), async_wait(), builtin_automixmonitor(), builtin_automonitor(), conf_run(), dial_exec_full(), do_magic_pickup(), dundi_exec(), exec_exec(), execif_exec(), feature_exec_app(), forward_message(), handle_exec(), handle_gosub(), iax2_exec(), lua_pbx_exec(), page_exec(), pbx_builtin_execiftime(), pbx_extension_helper(), realtime_exec(), try_calling(), and tryexec_exec().
01344 { 01345 int res; 01346 struct ast_module_user *u = NULL; 01347 const char *saved_c_appl; 01348 const char *saved_c_data; 01349 01350 if (c->cdr && !ast_check_hangup(c)) 01351 ast_cdr_setapp(c->cdr, app->name, data); 01352 01353 /* save channel values */ 01354 saved_c_appl= c->appl; 01355 saved_c_data= c->data; 01356 01357 c->appl = app->name; 01358 c->data = data; 01359 ast_cel_report_event(c, AST_CEL_APP_START, NULL, NULL, NULL); 01360 01361 if (app->module) 01362 u = __ast_module_user_add(app->module, c); 01363 if (strcasecmp(app->name, "system") && !ast_strlen_zero(data) && 01364 strchr(data, '|') && !strchr(data, ',') && !ast_opt_dont_warn) { 01365 ast_log(LOG_WARNING, "The application delimiter is now the comma, not " 01366 "the pipe. Did you forget to convert your dialplan? (%s(%s))\n", 01367 app->name, (char *) data); 01368 } 01369 res = app->execute(c, S_OR(data, "")); 01370 if (app->module && u) 01371 __ast_module_user_remove(app->module, u); 01372 ast_cel_report_event(c, AST_CEL_APP_END, NULL, NULL, NULL); 01373 /* restore channel values */ 01374 c->appl = saved_c_appl; 01375 c->data = saved_c_data; 01376 return res; 01377 }
| struct ast_exten* pbx_find_extension | ( | struct ast_channel * | chan, | |
| struct ast_context * | bypass, | |||
| struct pbx_find_info * | q, | |||
| const char * | context, | |||
| const char * | exten, | |||
| int | priority, | |||
| const char * | label, | |||
| const char * | callerid, | |||
| enum ext_match_t | action | |||
| ) | [read] |
Definition at line 2493 of file pbx.c.
References ast_context::alts, ast_autoservice_start(), ast_autoservice_stop(), ast_copy_string(), ast_hashtab_lookup(), AST_LIST_TRAVERSE, ast_log(), AST_PBX_MAX_STACK, ast_str_buffer(), ast_str_size(), ast_str_thread_get(), ast_strdupa, ast_strlen_zero(), ast_walk_context_extensions(), ast_switch::canmatch, scoreboard::canmatch_exten, contexts_table, create_match_char_tree(), ast_sw::data, pbx_find_info::data, E_CANMATCH, E_FINDLABEL, E_MATCHMORE, ast_sw::eval, ast_switch::exists, ast_exten::exten, scoreboard::exten, extenpatternmatchnew, extension_match_core(), pbx_find_info::foundcontext, include_valid(), ast_context::includes, pbx_find_info::incstack, ast_exten::label, scoreboard::last_char, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, match(), matchcid(), ast_switch::matchmore, ast_context::name, ast_sw::name, fake_context::name, new_find_extension(), ast_include::next, scoreboard::node, overrideswitch, ast_context::pattern_tree, pbx_find_extension(), pbx_findswitch(), pbx_substitute_variables_helper(), ast_exten::priority, ast_include::rname, ast_context::root_table, pbx_find_info::stacklen, pbx_find_info::status, STATUS_NO_CONTEXT, STATUS_NO_EXTENSION, STATUS_NO_LABEL, STATUS_NO_PRIORITY, STATUS_SUCCESS, strsep(), switch_data, pbx_find_info::swo, scoreboard::total_length, scoreboard::total_specificity, and trie_find_next_match().
Referenced by ast_hint_extension_nolock(), ast_merge_contexts_and_delete(), check_goto(), check_pval_item(), pbx_extension_helper(), pbx_find_extension(), and register_peer_exten().
02497 { 02498 int x, res; 02499 struct ast_context *tmp = NULL; 02500 struct ast_exten *e = NULL, *eroot = NULL; 02501 struct ast_include *i = NULL; 02502 struct ast_sw *sw = NULL; 02503 struct ast_exten pattern = {NULL, }; 02504 struct scoreboard score = {0, }; 02505 struct ast_str *tmpdata = NULL; 02506 02507 pattern.label = label; 02508 pattern.priority = priority; 02509 #ifdef NEED_DEBUG_HERE 02510 ast_log(LOG_NOTICE, "Looking for cont/ext/prio/label/action = %s/%s/%d/%s/%d\n", context, exten, priority, label, (int) action); 02511 #endif 02512 02513 /* Initialize status if appropriate */ 02514 if (q->stacklen == 0) { 02515 q->status = STATUS_NO_CONTEXT; 02516 q->swo = NULL; 02517 q->data = NULL; 02518 q->foundcontext = NULL; 02519 } else if (q->stacklen >= AST_PBX_MAX_STACK) { 02520 ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n"); 02521 return NULL; 02522 } 02523 02524 /* Check first to see if we've already been checked */ 02525 for (x = 0; x < q->stacklen; x++) { 02526 if (!strcasecmp(q->incstack[x], context)) 02527 return NULL; 02528 } 02529 02530 if (bypass) { /* bypass means we only look there */ 02531 tmp = bypass; 02532 } else { /* look in contexts */ 02533 struct fake_context item; 02534 02535 ast_copy_string(item.name, context, sizeof(item.name)); 02536 02537 tmp = ast_hashtab_lookup(contexts_table, &item); 02538 if (!tmp) { 02539 return NULL; 02540 } 02541 } 02542 02543 if (q->status < STATUS_NO_EXTENSION) 02544 q->status = STATUS_NO_EXTENSION; 02545 02546 /* Do a search for matching extension */ 02547 02548 eroot = NULL; 02549 score.total_specificity = 0; 02550 score.exten = 0; 02551 score.total_length = 0; 02552 if (!tmp->pattern_tree && tmp->root_table) { 02553 create_match_char_tree(tmp); 02554 #ifdef NEED_DEBUG 02555 ast_log(LOG_DEBUG, "Tree Created in context %s:\n", context); 02556 log_match_char_tree(tmp->pattern_tree," "); 02557 #endif 02558 } 02559 #ifdef NEED_DEBUG 02560 ast_log(LOG_NOTICE, "The Trie we are searching in:\n"); 02561 log_match_char_tree(tmp->pattern_tree, ":: "); 02562 #endif 02563 02564 do { 02565 if (!ast_strlen_zero(overrideswitch)) { 02566 char *osw = ast_strdupa(overrideswitch), *name; 02567 struct ast_switch *asw; 02568 ast_switch_f *aswf = NULL; 02569 char *datap; 02570 int eval = 0; 02571 02572 name = strsep(&osw, "/"); 02573 asw = pbx_findswitch(name); 02574 02575 if (!asw) { 02576 ast_log(LOG_WARNING, "No such switch '%s'\n", name); 02577 break; 02578 } 02579 02580 if (osw && strchr(osw, '$')) { 02581 eval = 1; 02582 } 02583 02584 if (eval && !(tmpdata = ast_str_thread_get(&switch_data, 512))) { 02585 ast_log(LOG_WARNING, "Can't evaluate overrideswitch?!"); 02586 break; 02587 } else if (eval) { 02588 /* Substitute variables now */ 02589 pbx_substitute_variables_helper(chan, osw, ast_str_buffer(tmpdata), ast_str_size(tmpdata)); 02590 datap = ast_str_buffer(tmpdata); 02591 } else { 02592 datap = osw; 02593 } 02594 02595 /* equivalent of extension_match_core() at the switch level */ 02596 if (action == E_CANMATCH) 02597 aswf = asw->canmatch; 02598 else if (action == E_MATCHMORE) 02599 aswf = asw->matchmore; 02600 else /* action == E_MATCH */ 02601 aswf = asw->exists; 02602 if (!aswf) { 02603 res = 0; 02604 } else { 02605 if (chan) { 02606 ast_autoservice_start(chan); 02607 } 02608 res = aswf(chan, context, exten, priority, callerid, datap); 02609 if (chan) { 02610 ast_autoservice_stop(chan); 02611 } 02612 } 02613 if (res) { /* Got a match */ 02614 q->swo = asw; 02615 q->data = datap; 02616 q->foundcontext = context; 02617 /* XXX keep status = STATUS_NO_CONTEXT ? */ 02618 return NULL; 02619 } 02620 } 02621 } while (0); 02622 02623 if (extenpatternmatchnew) { 02624 new_find_extension(exten, &score, tmp->pattern_tree, 0, 0, callerid, label, action); 02625 eroot = score.exten; 02626 02627 if (score.last_char == '!' && action == E_MATCHMORE) { 02628 /* We match an extension ending in '!'. 02629 * The decision in this case is final and is NULL (no match). 02630 */ 02631 #ifdef NEED_DEBUG_HERE 02632 ast_log(LOG_NOTICE,"Returning MATCHMORE NULL with exclamation point.\n"); 02633 #endif 02634 return NULL; 02635 } 02636 02637 if (!eroot && (action == E_CANMATCH || action == E_MATCHMORE) && score.canmatch_exten) { 02638 q->status = STATUS_SUCCESS; 02639 #ifdef NEED_DEBUG_HERE 02640 ast_log(LOG_NOTICE,"Returning CANMATCH exten %s\n", score.canmatch_exten->exten); 02641 #endif 02642 return score.canmatch_exten; 02643 } 02644 02645 if ((action == E_MATCHMORE || action == E_CANMATCH) && eroot) { 02646 if (score.node) { 02647 struct ast_exten *z = trie_find_next_match(score.node); 02648 if (z) { 02649 #ifdef NEED_DEBUG_HERE 02650 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten %s\n", z->exten); 02651 #endif 02652 } else { 02653 if (score.canmatch_exten) { 02654 #ifdef NEED_DEBUG_HERE 02655 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE canmatchmatch exten %s(%p)\n", score.canmatch_exten->exten, score.canmatch_exten); 02656 #endif 02657 return score.canmatch_exten; 02658 } else { 02659 #ifdef NEED_DEBUG_HERE 02660 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten NULL\n"); 02661 #endif 02662 } 02663 } 02664 return z; 02665 } 02666 #ifdef NEED_DEBUG_HERE 02667 ast_log(LOG_NOTICE, "Returning CANMATCH/MATCHMORE NULL (no next_match)\n"); 02668 #endif 02669 return NULL; /* according to the code, complete matches are null matches in MATCHMORE mode */ 02670 } 02671 02672 if (eroot) { 02673 /* found entry, now look for the right priority */ 02674 if (q->status < STATUS_NO_PRIORITY) 02675 q->status = STATUS_NO_PRIORITY; 02676 e = NULL; 02677 if (action == E_FINDLABEL && label ) { 02678 if (q->status < STATUS_NO_LABEL) 02679 q->status = STATUS_NO_LABEL; 02680 e = ast_hashtab_lookup(eroot->peer_label_table, &pattern); 02681 } else { 02682 e = ast_hashtab_lookup(eroot->peer_table, &pattern); 02683 } 02684 if (e) { /* found a valid match */ 02685 q->status = STATUS_SUCCESS; 02686 q->foundcontext = context; 02687 #ifdef NEED_DEBUG_HERE 02688 ast_log(LOG_NOTICE,"Returning complete match of exten %s\n", e->exten); 02689 #endif 02690 return e; 02691 } 02692 } 02693 } else { /* the old/current default exten pattern match algorithm */ 02694 02695 /* scan the list trying to match extension and CID */ 02696 eroot = NULL; 02697 while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) { 02698 int match = extension_match_core(eroot->exten, exten, action); 02699 /* 0 on fail, 1 on match, 2 on earlymatch */ 02700 02701 if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid))) 02702 continue; /* keep trying */ 02703 if (match == 2 && action == E_MATCHMORE) { 02704 /* We match an extension ending in '!'. 02705 * The decision in this case is final and is NULL (no match). 02706 */ 02707 return NULL; 02708 } 02709 /* found entry, now look for the right priority */ 02710 if (q->status < STATUS_NO_PRIORITY) 02711 q->status = STATUS_NO_PRIORITY; 02712 e = NULL; 02713 if (action == E_FINDLABEL && label ) { 02714 if (q->status < STATUS_NO_LABEL) 02715 q->status = STATUS_NO_LABEL; 02716 e = ast_hashtab_lookup(eroot->peer_label_table, &pattern); 02717 } else { 02718 e = ast_hashtab_lookup(eroot->peer_table, &pattern); 02719 } 02720 if (e) { /* found a valid match */ 02721 q->status = STATUS_SUCCESS; 02722 q->foundcontext = context; 02723 return e; 02724 } 02725 } 02726 } 02727 02728 /* Check alternative switches */ 02729 AST_LIST_TRAVERSE(&tmp->alts, sw, list) { 02730 struct ast_switch *asw = pbx_findswitch(sw->name); 02731 ast_switch_f *aswf = NULL; 02732 char *datap; 02733 02734 if (!asw) { 02735 ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name); 02736 continue; 02737 } 02738 02739 /* Substitute variables now */ 02740 if (sw->eval) { 02741 if (!(tmpdata = ast_str_thread_get(&switch_data, 512))) { 02742 ast_log(LOG_WARNING, "Can't evaluate switch?!"); 02743 continue; 02744 } 02745 pbx_substitute_variables_helper(chan, sw->data, ast_str_buffer(tmpdata), ast_str_size(tmpdata)); 02746 } 02747 02748 /* equivalent of extension_match_core() at the switch level */ 02749 if (action == E_CANMATCH) 02750 aswf = asw->canmatch; 02751 else if (action == E_MATCHMORE) 02752 aswf = asw->matchmore; 02753 else /* action == E_MATCH */ 02754 aswf = asw->exists; 02755 datap = sw->eval ? ast_str_buffer(tmpdata) : sw->data; 02756 if (!aswf) 02757 res = 0; 02758 else { 02759 if (chan) 02760 ast_autoservice_start(chan); 02761 res = aswf(chan, context, exten, priority, callerid, datap); 02762 if (chan) 02763 ast_autoservice_stop(chan); 02764 } 02765 if (res) { /* Got a match */ 02766 q->swo = asw; 02767 q->data = datap; 02768 q->foundcontext = context; 02769 /* XXX keep status = STATUS_NO_CONTEXT ? */ 02770 return NULL; 02771 } 02772 } 02773 q->incstack[q->stacklen++] = tmp->name; /* Setup the stack */ 02774 /* Now try any includes we have in this context */ 02775 for (i = tmp->includes; i; i = i->next) { 02776 if (include_valid(i)) { 02777 if ((e = pbx_find_extension(chan, bypass, q, i->rname, exten, priority, label, callerid, action))) { 02778 #ifdef NEED_DEBUG_HERE 02779 ast_log(LOG_NOTICE,"Returning recursive match of %s\n", e->exten); 02780 #endif 02781 return e; 02782 } 02783 if (q->swo) 02784 return NULL; 02785 } 02786 } 02787 return NULL; 02788 }
| struct ast_app* pbx_findapp | ( | const char * | app | ) | [read] |
Look up an application.
| app | name of the app |
Definition at line 1385 of file pbx.c.
References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, and ast_app::name.
Referenced by answer_exec_run(), ast_app_run_macro(), ast_bridge_call(), ast_pbx_run_app(), async_wait(), builtin_automixmonitor(), builtin_automonitor(), conf_run(), dial_exec_full(), do_magic_pickup(), dundi_exec(), exec_exec(), execif_exec(), feature_exec_app(), forward_message(), handle_exec(), handle_gosub(), iax2_exec(), lua_pbx_exec(), page_exec(), pbx_builtin_execiftime(), pbx_extension_helper(), realtime_exec(), try_calling(), and tryexec_exec().
01386 { 01387 struct ast_app *tmp; 01388 01389 AST_RWLIST_RDLOCK(&apps); 01390 AST_RWLIST_TRAVERSE(&apps, tmp, list) { 01391 if (!strcasecmp(tmp->name, app)) 01392 break; 01393 } 01394 AST_RWLIST_UNLOCK(&apps); 01395 01396 return tmp; 01397 }
| void pbx_retrieve_variable | ( | struct ast_channel * | c, | |
| const char * | var, | |||
| char ** | ret, | |||
| char * | workspace, | |||
| int | workspacelen, | |||
| struct varshead * | headp | |||
| ) |
Retrieve the value of a builtin variable or variable from the channel variable stack.
Definition at line 2918 of file pbx.c.
References ast_copy_string(), ast_free, ast_str_buffer(), ast_str_create(), ast_str_retrieve_variable(), and str.
Referenced by action_getvar(), action_status(), handle_getvariable(), lua_get_variable(), lua_get_variable_value(), and pbx_substitute_variables_helper_full().
02919 { 02920 struct ast_str *str = ast_str_create(16); 02921 const char *cret; 02922 02923 cret = ast_str_retrieve_variable(&str, 0, c, headp, var); 02924 ast_copy_string(workspace, ast_str_buffer(str), workspacelen); 02925 *ret = cret ? workspace : NULL; 02926 ast_free(str); 02927 }
| int pbx_set_autofallthrough | ( | int | newval | ) |
Set "autofallthrough" flag, if newval is <0, does not actually set. If set to 1, sets to auto fall through. If newval set to 0, sets to no auto fall through (reads extension instead). Returns previous value.
Definition at line 4944 of file pbx.c.
References autofallthrough.
Referenced by pbx_load_module().
04945 { 04946 int oldval = autofallthrough; 04947 autofallthrough = newval; 04948 return oldval; 04949 }
| int pbx_set_extenpatternmatchnew | ( | int | newval | ) |
Set "extenpatternmatchnew" flag, if newval is <0, does not actually set. If set to 1, sets to use the new Trie-based pattern matcher. If newval set to 0, sets to use the old linear-search algorithm. Returns previous value.
Definition at line 4951 of file pbx.c.
References extenpatternmatchnew.
Referenced by handle_set_extenpatternmatchnew(), handle_unset_extenpatternmatchnew(), and pbx_load_module().
04952 { 04953 int oldval = extenpatternmatchnew; 04954 extenpatternmatchnew = newval; 04955 return oldval; 04956 }
| void pbx_set_overrideswitch | ( | const char * | newval | ) |
Set "overrideswitch" field. If set and of nonzero length, all contexts will be tried directly through the named switch prior to any other matching within that context.
Definition at line 4958 of file pbx.c.
References ast_free, ast_strdup, ast_strlen_zero(), and overrideswitch.
Referenced by pbx_load_module().
04959 { 04960 if (overrideswitch) { 04961 ast_free(overrideswitch); 04962 } 04963 if (!ast_strlen_zero(newval)) { 04964 overrideswitch = ast_strdup(newval); 04965 } else { 04966 overrideswitch = NULL; 04967 } 04968 }
| void pbx_substitute_variables_helper | ( | struct ast_channel * | c, | |
| const char * | cp1, | |||
| char * | cp2, | |||
| int | count | |||
| ) |
Definition at line 3917 of file pbx.c.
References pbx_substitute_variables_helper_full(), and ast_channel::varshead.
Referenced by add_extensions(), ast_add_extension2_lockopt(), function_eval(), get_mapping_weight(), import_helper(), launch_monitor_thread(), manager_log(), pbx_builtin_importvar(), pbx_find_extension(), pbx_load_config(), pbx_substitute_variables(), realtime_exec(), rotate_file(), rpt_do_lstats(), rpt_exec(), sqlite3_log(), substituted(), and try_calling().
03918 { 03919 size_t used; 03920 pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count, &used); 03921 }
| void pbx_substitute_variables_helper_full | ( | struct ast_channel * | c, | |
| struct varshead * | headp, | |||
| const char * | cp1, | |||
| char * | cp2, | |||
| int | cp2_size, | |||
| size_t * | used | |||
| ) |
Definition at line 3721 of file pbx.c.
References ast_channel_release(), ast_copy_string(), ast_debug, ast_dummy_channel_alloc(), ast_expr(), ast_func_read(), ast_log(), ast_strlen_zero(), len(), LOG_ERROR, LOG_WARNING, parse_variable_name(), pbx_retrieve_variable(), pbx_substitute_variables_helper_full(), substring(), var, VAR_BUF_SIZE, and ast_channel::varshead.
Referenced by pbx_substitute_variables_helper(), pbx_substitute_variables_helper_full(), and pbx_substitute_variables_varshead().
03722 { 03723 /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!! */ 03724 char *cp4 = NULL; 03725 const char *tmp, *whereweare, *orig_cp2 = cp2; 03726 int length, offset, offset2, isfunction; 03727 char *workspace = NULL; 03728 char *ltmp = NULL, *var = NULL; 03729 char *nextvar, *nextexp, *nextthing; 03730 char *vars, *vare; 03731 int pos, brackets, needsub, len; 03732 03733 *cp2 = 0; /* just in case nothing ends up there */ 03734 whereweare=tmp=cp1; 03735 while (!ast_strlen_zero(whereweare) && count) { 03736 /* Assume we're copying the whole remaining string */ 03737 pos = strlen(whereweare); 03738 nextvar = NULL; 03739 nextexp = NULL; 03740 nextthing = strchr(whereweare, '$'); 03741 if (nextthing) { 03742 switch (nextthing[1]) { 03743 case '{': 03744 nextvar = nextthing; 03745 pos = nextvar - whereweare; 03746 break; 03747 case '[': 03748 nextexp = nextthing; 03749 pos = nextexp - whereweare; 03750 break; 03751 default: 03752 pos = 1; 03753 } 03754 } 03755 03756 if (pos) { 03757 /* Can't copy more than 'count' bytes */ 03758 if (pos > count) 03759 pos = count; 03760 03761 /* Copy that many bytes */ 03762 memcpy(cp2, whereweare, pos); 03763 03764 count -= pos; 03765 cp2 += pos; 03766 whereweare += pos; 03767 *cp2 = 0; 03768 } 03769 03770 if (nextvar) { 03771 /* We have a variable. Find the start and end, and determine 03772 if we are going to have to recursively call ourselves on the 03773 contents */ 03774 vars = vare = nextvar + 2; 03775 brackets = 1; 03776 needsub = 0; 03777 03778 /* Find the end of it */ 03779 while (brackets && *vare) { 03780 if ((vare[0] == '$') && (vare[1] == '{')) { 03781 needsub++; 03782 } else if (vare[0] == '{') { 03783 brackets++; 03784 } else if (vare[0] == '}') { 03785 brackets--; 03786 } else if ((vare[0] == '$') && (vare[1] == '[')) 03787 needsub++; 03788 vare++; 03789 } 03790 if (brackets) 03791 ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n"); 03792 len = vare - vars - 1; 03793 03794 /* Skip totally over variable string */ 03795 whereweare += (len + 3); 03796 03797 if (!var) 03798 var = alloca(VAR_BUF_SIZE); 03799 03800 /* Store variable name (and truncate) */ 03801 ast_copy_string(var, vars, len + 1); 03802 03803 /* Substitute if necessary */ 03804 if (needsub) { 03805 size_t used; 03806 if (!ltmp) 03807 ltmp = alloca(VAR_BUF_SIZE); 03808 03809 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used); 03810 vars = ltmp; 03811 } else { 03812 vars = var; 03813 } 03814 03815 if (!workspace) 03816 workspace = alloca(VAR_BUF_SIZE); 03817 03818 workspace[0] = '\0'; 03819 03820 parse_variable_name(vars, &offset, &offset2, &isfunction); 03821 if (isfunction) { 03822 /* Evaluate function */ 03823 if (c || !headp) 03824 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 03825 else { 03826 struct varshead old; 03827 struct ast_channel *c = ast_dummy_channel_alloc(); 03828 if (c) { 03829 memcpy(&old, &c->varshead, sizeof(old)); 03830 memcpy(&c->varshead, headp, sizeof(c->varshead)); 03831 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 03832 /* Don't deallocate the varshead that was passed in */ 03833 memcpy(&c->varshead, &old, sizeof(c->varshead)); 03834 c = ast_channel_release(c); 03835 } else { 03836 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n"); 03837 } 03838 } 03839 ast_debug(2, "Function result is '%s'\n", cp4 ? cp4 : "(null)"); 03840 } else { 03841 /* Retrieve variable value */ 03842 pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp); 03843 } 03844 if (cp4) { 03845 cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE); 03846 03847 length = strlen(cp4); 03848 if (length > count) 03849 length = count; 03850 memcpy(cp2, cp4, length); 03851 count -= length; 03852 cp2 += length; 03853 *cp2 = 0; 03854 } 03855 } else if (nextexp) { 03856 /* We have an expression. Find the start and end, and determine 03857 if we are going to have to recursively call ourselves on the 03858 contents */ 03859 vars = vare = nextexp + 2; 03860 brackets = 1; 03861 needsub = 0; 03862 03863 /* Find the end of it */ 03864 while (brackets && *vare) { 03865 if ((vare[0] == '$') && (vare[1] == '[')) { 03866 needsub++; 03867 brackets++; 03868 vare++; 03869 } else if (vare[0] == '[') { 03870 brackets++; 03871 } else if (vare[0] == ']') { 03872 brackets--; 03873 } else if ((vare[0] == '$') && (vare[1] == '{')) { 03874 needsub++; 03875 vare++; 03876 } 03877 vare++; 03878 } 03879 if (brackets) 03880 ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n"); 03881 len = vare - vars - 1; 03882 03883 /* Skip totally over expression */ 03884 whereweare += (len + 3); 03885 03886 if (!var) 03887 var = alloca(VAR_BUF_SIZE); 03888 03889 /* Store variable name (and truncate) */ 03890 ast_copy_string(var, vars, len + 1); 03891 03892 /* Substitute if necessary */ 03893 if (needsub) { 03894 size_t used; 03895 if (!ltmp) 03896 ltmp = alloca(VAR_BUF_SIZE); 03897 03898 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used); 03899 vars = ltmp; 03900 } else { 03901 vars = var; 03902 } 03903 03904 length = ast_expr(vars, cp2, count, c); 03905 03906 if (length) { 03907 ast_debug(1, "Expression result is '%s'\n", cp2); 03908 count -= length; 03909 cp2 += length; 03910 *cp2 = 0; 03911 } 03912 } 03913 } 03914 *used = cp2 - orig_cp2; 03915 }
| void pbx_substitute_variables_varshead | ( | struct varshead * | headp, | |
| const char * | cp1, | |||
| char * | cp2, | |||
| int | count | |||
| ) |
Definition at line 3923 of file pbx.c.
References pbx_substitute_variables_helper_full().
Referenced by do_say(), dundi_lookup_local(), and loopback_subst().
03924 { 03925 size_t used; 03926 pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count, &used); 03927 }
1.5.6