#include "asterisk.h"
#include <sys/types.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include <time.h>
#include <sys/time.h>
#include <limits.h>
#include "asterisk/lock.h"
#include "asterisk/cli.h"
#include "asterisk/pbx.h"
#include "asterisk/channel.h"
#include "asterisk/options.h"
#include "asterisk/logger.h"
#include "asterisk/file.h"
#include "asterisk/callerid.h"
#include "asterisk/cdr.h"
#include "asterisk/config.h"
#include "asterisk/term.h"
#include "asterisk/manager.h"
#include "asterisk/ast_expr.h"
#include "asterisk/linkedlists.h"
#include "asterisk/say.h"
#include "asterisk/utils.h"
#include "asterisk/causes.h"
#include "asterisk/musiconhold.h"
#include "asterisk/app.h"
#include "asterisk/devicestate.h"
#include "asterisk/stringfields.h"
#include "asterisk/threadstorage.h"
Include dependency graph for pbx.c:
Go to the source code of this file.
Data Structures | |
struct | app_tmp |
struct | ast_app |
ast_app: A registered application More... | |
struct | ast_context |
ast_context: An extension context More... | |
struct | ast_exten |
ast_exten: An extension The dialplan is saved as a linked list with each context having it's own linked list of extensions - one item per priority. More... | |
struct | ast_hint |
Structure for dial plan hints. More... | |
struct | ast_ignorepat |
ast_ignorepat: Ignore patterns in dial plan More... | |
struct | ast_include |
ast_include: include= support in extensions.conf More... | |
struct | ast_state_cb |
ast_state_cb: An extension state notify register item More... | |
struct | ast_sw |
ast_sw: Switch statement in extensions.conf More... | |
struct | async_stat |
struct | cfextension_states |
struct | dialplan_counters |
struct | pbx_builtin |
Declaration of builtin applications. More... | |
struct | pbx_find_info |
struct | store_hint |
Defines | |
#define | AST_PBX_MAX_STACK 128 |
#define | BACKGROUND_MATCHEXTEN (1 << 2) |
#define | BACKGROUND_NOANSWER (1 << 1) |
#define | BACKGROUND_PLAYBACK (1 << 3) |
#define | BACKGROUND_SKIP (1 << 0) |
#define | EXT_DATA_SIZE 8192 |
#define | SAY_STUBS |
#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 | SWITCH_DATA_LENGTH 256 |
#define | VAR_BUF_SIZE 4096 |
#define | VAR_HARDTRAN 3 |
#define | VAR_NORMAL 1 |
#define | VAR_SOFTTRAN 2 |
#define | WAITEXTEN_MOH (1 << 0) |
Enumerations | |
enum | ext_match_t { E_MATCHMORE = 0x00, E_CANMATCH = 0x01, E_MATCH = 0x02, E_MATCH_MASK = 0x03, E_SPAWN = 0x12, E_FINDLABEL = 0x22 } |
Functions | |
static struct ast_context * | __ast_context_create (struct ast_context **extcontexts, const char *name, const char *registrar, int existsokay) |
void | __ast_context_destroy (struct ast_context *con, const char *registrar) |
static int | __ast_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority, int async) |
static int | __ast_pbx_run (struct ast_channel *c) |
static int | _extension_match_core (const char *pattern, const char *data, enum ext_match_t mode) |
static int | add_pri (struct ast_context *con, struct ast_exten *tmp, struct ast_exten *el, struct ast_exten *e, int replace) |
add the extension in the priority chain. returns 0 on success, -1 on failure | |
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 *. | |
static int | ast_add_hint (struct ast_exten *e) |
ast_add_hint: Add hint to hint list, check initial extension state | |
AST_APP_OPTIONS (resetcdr_opts,{AST_APP_OPTION('w', AST_CDR_FLAG_POSTED), AST_APP_OPTION('a', AST_CDR_FLAG_LOCKED), AST_APP_OPTION('v', AST_CDR_FLAG_KEEP_VARS),}) | |
AST_APP_OPTIONS (waitexten_opts,{AST_APP_OPTION_ARG('m', WAITEXTEN_MOH, 0),}) | |
AST_APP_OPTIONS (background_opts,{AST_APP_OPTION('s', BACKGROUND_SKIP), AST_APP_OPTION('n', BACKGROUND_NOANSWER), AST_APP_OPTION('m', BACKGROUND_MATCHEXTEN), AST_APP_OPTION('p', BACKGROUND_PLAYBACK),}) | |
int | ast_async_goto (struct ast_channel *chan, const char *context, const char *exten, int priority) |
int | ast_async_goto_by_name (const char *channame, const char *context, const char *exten, int priority) |
int | ast_async_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority) |
int | ast_build_timing (struct ast_timing *i, const char *info_in) |
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. | |
static int | ast_change_hint (struct ast_exten *oe, struct ast_exten *ne) |
ast_change_hint: Change hint for an extension | |
int | ast_check_timing (const struct ast_timing *i) |
int | ast_context_add_ignorepat (const char *context, const char *value, const char *registrar) |
Add an ignorepat. | |
int | ast_context_add_ignorepat2 (struct ast_context *con, const char *value, 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 *value, 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 *value, const char *data, int eval, const char *registrar) |
Adds a switch (first param is a ast_context). | |
ast_context * | ast_context_create (struct ast_context **extcontexts, const char *name, const char *registrar) |
Register a new context. | |
void | ast_context_destroy (struct ast_context *con, const char *registrar) |
Destroy a context (matches the specified context (or ANY context if NULL). | |
ast_context * | ast_context_find (const char *name) |
Find a context. | |
ast_context * | ast_context_find_or_create (struct ast_context **extcontexts, const char *name, const char *registrar) |
int | ast_context_lockmacro (const char *context) |
locks the macrolock in the given given context | |
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) |
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_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 *context) |
Unlocks the macrolock in the given context. | |
int | ast_context_verify_includes (struct ast_context *con) |
Verifies includes in an ast_contect structure. | |
ast_custom_function * | ast_custom_function_find (const char *name) |
int | ast_custom_function_register (struct ast_custom_function *acf) |
Reigster a custom function. | |
int | ast_custom_function_unregister (struct ast_custom_function *acf) |
Unregister a custom function. | |
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_match (const char *pattern, const char *data) |
Determine if a given extension matches a given pattern (in NXX format). | |
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. | |
static int | ast_extension_state2 (struct ast_exten *e) |
ast_extensions_state2: Check state of extension by using hints | |
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, char *function, char *workspace, size_t len) |
executes a read operation on a function | |
int | ast_func_write (struct ast_channel *chan, char *function, const char *value) |
executes a write operation on a function | |
const char * | ast_get_context_name (struct ast_context *con) |
const char * | ast_get_context_registrar (struct ast_context *c) |
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) |
ast_context * | ast_get_extension_context (struct ast_exten *exten) |
const char * | ast_get_extension_label (struct ast_exten *exten) |
int | ast_get_extension_matchcid (struct ast_exten *e) |
const char * | ast_get_extension_name (struct ast_exten *exten) |
int | ast_get_extension_priority (struct ast_exten *exten) |
const char * | ast_get_extension_registrar (struct ast_exten *e) |
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 exists, return non-zero. | |
const char * | ast_get_ignorepat_name (struct ast_ignorepat *ip) |
const char * | ast_get_ignorepat_registrar (struct ast_ignorepat *ip) |
const char * | ast_get_include_name (struct ast_include *inc) |
const char * | ast_get_include_registrar (struct ast_include *i) |
const char * | ast_get_switch_data (struct ast_sw *sw) |
const char * | ast_get_switch_name (struct ast_sw *sw) |
const char * | ast_get_switch_registrar (struct ast_sw *sw) |
int | ast_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority) |
static struct ast_exten * | ast_hint_extension (struct ast_channel *c, const char *context, const char *exten) |
ast_hint_extension: Find hint for given extension in context | |
void | ast_hint_state_changed (const char *device, char *cid_num, char *cid_name) |
int | ast_ignore_pattern (const char *context, const char *pattern) |
Checks to see if a number should be ignored. | |
AST_LIST_HEAD (store_hints, store_hint) | |
static | AST_LIST_HEAD_STATIC (hints, ast_hint) |
static | AST_LIST_HEAD_STATIC (switches, ast_switch) |
static | AST_LIST_HEAD_STATIC (apps, ast_app) |
static | AST_LIST_HEAD_STATIC (acf_root, ast_custom_function) |
int | ast_lock_context (struct ast_context *con) |
Locks a given context. | |
int | ast_lock_contexts () |
Locks the context list. | |
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, const char *registrar) |
Merge the temporary contexts into a global contexts list and delete from the global list the ones that are being added. | |
AST_MUTEX_DEFINE_STATIC (maxcalllock) | |
AST_MUTEX_DEFINE_STATIC (globalslock) | |
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_app_uniqueid (const char *type, int format, void *data, int timeout, const char *app, const char *appdata, int *reason, int sync, int callingpres, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel, char *uniqueid) |
static int | ast_pbx_outgoing_cdr_failed (void) |
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 **channel) |
int | ast_pbx_outgoing_exten_uniqueid (const char *type, int format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int sync, int callingpres, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **channel, char *uniqueid) |
enum ast_pbx_result | ast_pbx_run (struct ast_channel *c) |
Execute the PBX in the current thread. | |
static void * | ast_pbx_run_app (void *data) |
run the application and free the descriptor once done | |
enum ast_pbx_result | ast_pbx_start (struct ast_channel *c) |
Create a new thread and start the PBX. | |
int | ast_rdlock_contexts (void) |
int | ast_register_application (const char *app, int(*execute)(struct ast_channel *, void *), const char *synopsis, const char *description) |
Register an application. | |
int | ast_register_switch (struct ast_switch *sw) |
Register an alternative dialplan switch. | |
static int | ast_remove_hint (struct ast_exten *e) |
ast_remove_hint: Remove hint from extension | |
AST_RWLOCK_DEFINE_STATIC (conlock) | |
int | ast_spawn_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid) |
Launch a new extension (i.e. new stack). | |
AST_THREADSTORAGE (switch_data, switch_data_init) | |
int | ast_unlock_context (struct ast_context *con) |
int | ast_unlock_contexts () |
Unlocks contexts. | |
int | ast_unregister_application (const char *app) |
Unregister an application. | |
void | ast_unregister_switch (struct ast_switch *sw) |
Unregister an alternative switch. | |
ast_exten * | ast_walk_context_extensions (struct ast_context *con, struct ast_exten *exten) |
ast_ignorepat * | ast_walk_context_ignorepats (struct ast_context *con, struct ast_ignorepat *ip) |
ast_include * | ast_walk_context_includes (struct ast_context *con, struct ast_include *inc) |
ast_sw * | ast_walk_context_switches (struct ast_context *con, struct ast_sw *sw) |
ast_context * | ast_walk_contexts (struct ast_context *con) |
ast_exten * | ast_walk_extension_priorities (struct ast_exten *exten, struct ast_exten *priority) |
int | ast_wrlock_contexts (void) |
static void * | async_wait (void *data) |
static int | collect_digits (struct ast_channel *c, int waittime, char *buf, int buflen, int pos) |
collect digits from the channel into the buffer, return -1 on error, 0 on timeout or done. | |
static char * | complete_show_application (const char *line, const char *word, int pos, int state) |
static char * | complete_show_applications (const char *line, const char *word, int pos, int state) |
static char * | complete_show_applications_deprecated (const char *line, const char *word, int pos, int state) |
static char * | complete_show_dialplan_context (const char *line, const char *word, int pos, int state) |
static char * | complete_show_function (const char *line, const char *word, int pos, int state) |
static void | decrease_call_count (void) |
static void | destroy_exten (struct ast_exten *e) |
static int | ext_cmp (const char *a, const char *b) |
the full routine to compare extensions in rules. | |
static int | ext_cmp1 (const char **p) |
helper functions to sort extensions and patterns in the desired way, so that more specific patterns appear first. | |
static int | ext_strncpy (char *dst, const char *src, int len) |
copy a string skipping whitespace | |
static int | extension_match_core (const char *pattern, const char *data, enum ext_match_t mode) |
static struct ast_context * | find_context_locked (const char *context) |
static char * | func_args (char *function) |
return a pointer to the arguments of the function, and terminates the function name with '\0' | |
static unsigned | get_range (char *src, int max, char *const names[], const char *msg) |
helper function to return a range up to max (7, 12, 31 respectively). names, if supplied, is an array of names that should be mapped to numbers. | |
static void | get_timerange (struct ast_timing *i, char *times) |
store a bitmask of valid times, one bit each 2 minute | |
static int | handle_set_global (int fd, int argc, char *argv[]) |
static int | handle_set_global_deprecated (int fd, int argc, char *argv[]) |
CLI support for setting global variables. | |
static int | handle_show_application (int fd, int argc, char *argv[]) |
static int | handle_show_application_deprecated (int fd, int argc, char *argv[]) |
static int | handle_show_applications (int fd, int argc, char *argv[]) |
static int | handle_show_applications_deprecated (int fd, int argc, char *argv[]) |
static int | handle_show_dialplan (int fd, int argc, char *argv[]) |
static int | handle_show_function (int fd, int argc, char *argv[]) |
static int | handle_show_function_deprecated (int fd, int argc, char *argv[]) |
static int | handle_show_functions (int fd, int argc, char *argv[]) |
static int | handle_show_functions_deprecated (int fd, int argc, char *argv[]) |
static int | handle_show_globals (int fd, int argc, char *argv[]) |
CLI support for listing global variables in a parseable way. | |
static int | handle_show_hints (int fd, int argc, char *argv[]) |
handle_show_hints: CLI support for listing registred dial plan hints | |
static int | handle_show_switches (int fd, int argc, char *argv[]) |
handle_show_switches: CLI support for listing registred dial plan switches | |
static int | include_valid (struct ast_include *i) |
static int | increase_call_count (const struct ast_channel *c) |
int | load_pbx (void) |
static int | lookup_name (const char *s, char *const names[], int max) |
Helper for get_range. return the index of the matching entry, starting from 1. If names is not supplied, try numeric values. | |
static int | matchcid (const char *cidpattern, const char *callerid) |
static int | parse_variable_name (char *var, int *offset, int *length, int *isfunc) |
extract offset:length from variable name. Returns 1 if there is a offset:length part, which is trimmed off (values go into variables) | |
static int | pbx_builtin_answer (struct ast_channel *, void *) |
static int | pbx_builtin_background (struct ast_channel *, void *) |
static int | pbx_builtin_busy (struct ast_channel *, void *) |
void | pbx_builtin_clear_globals (void) |
static int | pbx_builtin_congestion (struct ast_channel *, void *) |
static int | pbx_builtin_execiftime (struct ast_channel *, void *) |
const char * | pbx_builtin_getvar_helper (struct ast_channel *chan, const char *name) |
static int | pbx_builtin_goto (struct ast_channel *, void *) |
static int | pbx_builtin_gotoif (struct ast_channel *, void *) |
static int | pbx_builtin_gotoiftime (struct ast_channel *, void *) |
static int | pbx_builtin_hangup (struct ast_channel *, void *) |
static int | pbx_builtin_importvar (struct ast_channel *, void *) |
static int | pbx_builtin_noop (struct ast_channel *, void *) |
static int | pbx_builtin_progress (struct ast_channel *, void *) |
void | pbx_builtin_pushvar_helper (struct ast_channel *chan, const char *name, const char *value) |
static int | pbx_builtin_resetcdr (struct ast_channel *, void *) |
static int | pbx_builtin_ringing (struct ast_channel *, void *) |
static int | pbx_builtin_saycharacters (struct ast_channel *, void *) |
static int | pbx_builtin_saydigits (struct ast_channel *, void *) |
static int | pbx_builtin_saynumber (struct ast_channel *, void *) |
static int | pbx_builtin_sayphonetic (struct ast_channel *, void *) |
int | pbx_builtin_serialize_variables (struct ast_channel *chan, char *buf, size_t size) |
static int | pbx_builtin_setamaflags (struct ast_channel *, void *) |
static int | pbx_builtin_setglobalvar (struct ast_channel *, void *) |
int | pbx_builtin_setvar (struct ast_channel *, void *) |
void | pbx_builtin_setvar_helper (struct ast_channel *chan, const char *name, const char *value) |
static int | pbx_builtin_wait (struct ast_channel *, void *) |
static int | pbx_builtin_waitexten (struct ast_channel *, void *) |
int | pbx_checkcondition (const char *condition) |
Evaluate a condition. | |
static void | pbx_destroy (struct ast_pbx *p) |
int | pbx_exec (struct ast_channel *c, struct ast_app *app, void *data) |
Execute an application. | |
static int | pbx_extension_helper (struct ast_channel *c, struct ast_context *con, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action) |
The return value depends on the action:. | |
static 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) |
ast_app * | pbx_findapp (const char *app) |
Look up an application. | |
static struct ast_switch * | pbx_findswitch (const char *sw) |
void | pbx_retrieve_variable (struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp) |
pbx_retrieve_variable: Support for Asterisk built-in variables --- | |
int | pbx_set_autofallthrough (int newval) |
static void | pbx_substitute_variables (char *passdata, int datalen, struct ast_channel *c, struct ast_exten *e) |
void | pbx_substitute_variables_helper (struct ast_channel *c, const char *cp1, char *cp2, int count) |
static void | pbx_substitute_variables_helper_full (struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count) |
void | pbx_substitute_variables_varshead (struct varshead *headp, const char *cp1, char *cp2, int count) |
static void * | pbx_thread (void *data) |
static void | print_ext (struct ast_exten *e, char *buf, int buflen) |
helper function to print an extension | |
static void | set_ext_pri (struct ast_channel *c, const char *exten, int pri) |
static int | show_dialplan_helper (int fd, const char *context, const char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude, int includecount, const char *includes[]) |
static char * | substring (const char *value, int offset, int length, char *workspace, size_t workspace_len) |
takes a substring. It is ok to call with value == workspace. | |
static void | wait_for_hangup (struct ast_channel *chan, void *data) |
Variables | |
static int | autofallthrough = 1 |
static struct pbx_builtin | builtins [] |
Declaration of builtin applications. | |
static struct ast_cli_entry | cli_set_global_deprecated |
static struct ast_cli_entry | cli_show_application_deprecated |
static struct ast_cli_entry | cli_show_applications_deprecated |
static struct ast_cli_entry | cli_show_dialplan_deprecated |
static struct ast_cli_entry | cli_show_function_deprecated |
static struct ast_cli_entry | cli_show_functions_deprecated |
static struct ast_cli_entry | cli_show_globals_deprecated |
static struct ast_cli_entry | cli_show_hints_deprecated |
static struct ast_cli_entry | cli_show_switches_deprecated |
static struct ast_context * | contexts |
static int | countcalls |
static char * | days [] |
static struct cfextension_states | extension_states [] |
static struct varshead | globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE |
static char * | months [] |
static struct ast_cli_entry | pbx_cli [] |
static char | set_global_help [] |
static char | show_application_help [] |
static char | show_applications_help [] |
static char | show_dialplan_help [] |
static char | show_function_help [] |
static char | show_functions_help [] |
static char | show_globals_help [] |
static char | show_hints_help [] |
static char | show_switches_help [] |
ast_state_cb * | statecbs |
static int | stateid = 1 |
Definition in file pbx.c.
#define AST_PBX_MAX_STACK 128 |
Go no deeper than this through includes (not counting loops)
Definition at line 549 of file pbx.c.
Referenced by handle_show_dialplan(), pbx_find_extension(), and show_dialplan_helper().
#define BACKGROUND_MATCHEXTEN (1 << 2) |
#define BACKGROUND_NOANSWER (1 << 1) |
#define BACKGROUND_PLAYBACK (1 << 3) |
#define BACKGROUND_SKIP (1 << 0) |
#define EXT_DATA_SIZE 8192 |
Definition at line 78 of file pbx.c.
Referenced by pbx_extension_helper(), and realtime_exec().
#define STATUS_NO_CONTEXT 1 |
Definition at line 911 of file pbx.c.
Referenced by pbx_extension_helper(), and pbx_find_extension().
#define STATUS_NO_EXTENSION 2 |
Definition at line 912 of file pbx.c.
Referenced by pbx_extension_helper(), and pbx_find_extension().
#define STATUS_NO_LABEL 4 |
Definition at line 914 of file pbx.c.
Referenced by pbx_extension_helper(), and pbx_find_extension().
#define STATUS_NO_PRIORITY 3 |
Definition at line 913 of file pbx.c.
Referenced by pbx_extension_helper(), and pbx_find_extension().
#define STATUS_SUCCESS 5 |
#define VAR_BUF_SIZE 4096 |
Definition at line 83 of file pbx.c.
Referenced by ast_add_extension2(), pbx_builtin_importvar(), and pbx_substitute_variables_helper_full().
#define WAITEXTEN_MOH (1 << 0) |
enum ext_match_t |
When looking up extensions, we can have different requests identified by the 'action' argument, as follows. Note that the coding is such that the low 4 bits are the third argument to extension_match_core.
Definition at line 754 of file pbx.c.
00754 { 00755 E_MATCHMORE = 0x00, /* extension can match but only with more 'digits' */ 00756 E_CANMATCH = 0x01, /* extension can match with or without more 'digits' */ 00757 E_MATCH = 0x02, /* extension is an exact match */ 00758 E_MATCH_MASK = 0x03, /* mask for the argument to extension_match_core() */ 00759 E_SPAWN = 0x12, /* want to spawn an extension. Requires exact match */ 00760 E_FINDLABEL = 0x22 /* returns the priority for a given label. Requires exact match */ 00761 };
static struct ast_context* __ast_context_create | ( | struct ast_context ** | extcontexts, | |
const char * | name, | |||
const char * | registrar, | |||
int | existsokay | |||
) | [static] |
Definition at line 3873 of file pbx.c.
References ast_log(), ast_rdlock_contexts(), ast_unlock_contexts(), contexts, local_contexts, LOG_WARNING, name, and ast_context::next.
Referenced by ast_context_create(), and ast_context_find_or_create().
03874 { 03875 struct ast_context *tmp, **local_contexts; 03876 int length = sizeof(struct ast_context) + strlen(name) + 1; 03877 03878 if (!extcontexts) { 03879 ast_rdlock_contexts(); 03880 local_contexts = &contexts; 03881 } else 03882 local_contexts = extcontexts; 03883 03884 for (tmp = *local_contexts; tmp; tmp = tmp->next) { 03885 if (!strcasecmp(tmp->name, name)) { 03886 if (!existsokay) { 03887 ast_log(LOG_WARNING, "Tried to register context '%s', already in use\n", name); 03888 tmp = NULL; 03889 } 03890 if (!extcontexts) 03891 ast_unlock_contexts(); 03892 return tmp; 03893 } 03894 } 03895 03896 if (!extcontexts) 03897 ast_unlock_contexts(); 03898 03899 if ((tmp = ast_calloc(1, length))) { 03900 ast_mutex_init(&tmp->lock); 03901 ast_mutex_init(&tmp->macrolock); 03902 strcpy(tmp->name, name); 03903 tmp->registrar = registrar; 03904 if (!extcontexts) 03905 ast_wrlock_contexts(); 03906 tmp->next = *local_contexts; 03907 *local_contexts = tmp; 03908 if (!extcontexts) 03909 ast_unlock_contexts(); 03910 if (option_debug) 03911 ast_log(LOG_DEBUG, "Registered context '%s'\n", tmp->name); 03912 if (option_verbose > 2) 03913 ast_verbose( VERBOSE_PREFIX_3 "Registered extension context '%s'\n", tmp->name); 03914 } 03915 03916 return tmp; 03917 }
void __ast_context_destroy | ( | struct ast_context * | con, | |
const char * | registrar | |||
) |
Definition at line 5310 of file pbx.c.
References AST_LIST_REMOVE_HEAD, ast_log(), ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), contexts, destroy_exten(), el, free, ast_exten::next, ast_include::next, ast_context::next, ast_ignorepat::next, and ast_exten::peer.
Referenced by ast_context_destroy(), and ast_merge_contexts_and_delete().
05311 { 05312 struct ast_context *tmp, *tmpl=NULL; 05313 struct ast_include *tmpi; 05314 struct ast_sw *sw; 05315 struct ast_exten *e, *el, *en; 05316 struct ast_ignorepat *ipi; 05317 05318 for (tmp = contexts; tmp; ) { 05319 struct ast_context *next; /* next starting point */ 05320 for (; tmp; tmpl = tmp, tmp = tmp->next) { 05321 if (option_debug) 05322 ast_log(LOG_DEBUG, "check ctx %s %s\n", tmp->name, tmp->registrar); 05323 if ( (!registrar || !strcasecmp(registrar, tmp->registrar)) && 05324 (!con || !strcasecmp(tmp->name, con->name)) ) 05325 break; /* found it */ 05326 } 05327 if (!tmp) /* not found, we are done */ 05328 break; 05329 ast_mutex_lock(&tmp->lock); 05330 if (option_debug) 05331 ast_log(LOG_DEBUG, "delete ctx %s %s\n", tmp->name, tmp->registrar); 05332 next = tmp->next; 05333 if (tmpl) 05334 tmpl->next = next; 05335 else 05336 contexts = next; 05337 /* Okay, now we're safe to let it go -- in a sense, we were 05338 ready to let it go as soon as we locked it. */ 05339 ast_mutex_unlock(&tmp->lock); 05340 for (tmpi = tmp->includes; tmpi; ) { /* Free includes */ 05341 struct ast_include *tmpil = tmpi; 05342 tmpi = tmpi->next; 05343 free(tmpil); 05344 } 05345 for (ipi = tmp->ignorepats; ipi; ) { /* Free ignorepats */ 05346 struct ast_ignorepat *ipl = ipi; 05347 ipi = ipi->next; 05348 free(ipl); 05349 } 05350 while ((sw = AST_LIST_REMOVE_HEAD(&tmp->alts, list))) 05351 free(sw); 05352 for (e = tmp->root; e;) { 05353 for (en = e->peer; en;) { 05354 el = en; 05355 en = en->peer; 05356 destroy_exten(el); 05357 } 05358 el = e; 05359 e = e->next; 05360 destroy_exten(el); 05361 } 05362 ast_mutex_destroy(&tmp->lock); 05363 free(tmp); 05364 /* if we have a specific match, we are done, otherwise continue */ 05365 tmp = con ? NULL : next; 05366 } 05367 }
static int __ast_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority, | |||
int | async | |||
) | [static] |
Definition at line 6361 of file pbx.c.
References ast_async_goto(), ast_exists_extension(), ast_explicit_goto(), ast_channel::cid, ast_callerid::cid_num, ast_channel::context, and ast_channel::exten.
Referenced by ast_async_goto_if_exists(), and ast_goto_if_exists().
06362 { 06363 int (*goto_func)(struct ast_channel *chan, const char *context, const char *exten, int priority); 06364 06365 if (!chan) 06366 return -2; 06367 06368 if (context == NULL) 06369 context = chan->context; 06370 if (exten == NULL) 06371 exten = chan->exten; 06372 06373 goto_func = (async) ? ast_async_goto : ast_explicit_goto; 06374 if (ast_exists_extension(chan, context, exten, priority, chan->cid.cid_num)) 06375 return goto_func(chan, context, exten, priority); 06376 else 06377 return -3; 06378 }
static int __ast_pbx_run | ( | struct ast_channel * | c | ) | [static] |
Definition at line 2359 of file pbx.c.
References ast_channel::_softhangup, ast_channel::amaflags, ast_calloc, ast_cdr_alloc(), ast_cdr_init(), ast_cdr_start(), ast_exists_extension(), AST_FLAG_IN_AUTOLOOP, ast_log(), AST_PBX_KEEPALIVE, ast_set_flag, AST_SOFTHANGUP_ASYNCGOTO, AST_SOFTHANGUP_TIMEOUT, ast_spawn_extension(), ast_test_flag, ast_verbose(), ast_channel::cdr, ast_channel::cid, ast_callerid::cid_num, ast_channel::context, ast_pbx::dtimeout, error(), ast_channel::exten, free, LOG_DEBUG, LOG_WARNING, option_debug, option_verbose, ast_channel::pbx, ast_channel::priority, ast_pbx::rtimeout, set_ext_pri(), ast_cdr::start, and VERBOSE_PREFIX_2.
Referenced by ast_pbx_run(), and pbx_thread().
02360 { 02361 int found = 0; /* set if we find at least one match */ 02362 int res = 0; 02363 int autoloopflag; 02364 int error = 0; /* set an error conditions */ 02365 02366 /* A little initial setup here */ 02367 if (c->pbx) { 02368 ast_log(LOG_WARNING, "%s already has PBX structure??\n", c->name); 02369 /* XXX and now what ? */ 02370 free(c->pbx); 02371 } 02372 if (!(c->pbx = ast_calloc(1, sizeof(*c->pbx)))) 02373 return -1; 02374 if (c->amaflags) { 02375 if (!c->cdr) { 02376 c->cdr = ast_cdr_alloc(); 02377 if (!c->cdr) { 02378 ast_log(LOG_WARNING, "Unable to create Call Detail Record\n"); 02379 free(c->pbx); 02380 return -1; 02381 } 02382 ast_cdr_init(c->cdr, c); 02383 } 02384 } 02385 /* Set reasonable defaults */ 02386 c->pbx->rtimeout = 10; 02387 c->pbx->dtimeout = 5; 02388 02389 autoloopflag = ast_test_flag(c, AST_FLAG_IN_AUTOLOOP); /* save value to restore at the end */ 02390 ast_set_flag(c, AST_FLAG_IN_AUTOLOOP); 02391 02392 /* Start by trying whatever the channel is set to */ 02393 if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) { 02394 /* If not successful fall back to 's' */ 02395 if (option_verbose > 1) 02396 ast_verbose( VERBOSE_PREFIX_2 "Starting %s at %s,%s,%d failed so falling back to exten 's'\n", c->name, c->context, c->exten, c->priority); 02397 /* XXX the original code used the existing priority in the call to 02398 * ast_exists_extension(), and reset it to 1 afterwards. 02399 * I believe the correct thing is to set it to 1 immediately. 02400 */ 02401 set_ext_pri(c, "s", 1); 02402 if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) { 02403 /* JK02: And finally back to default if everything else failed */ 02404 if (option_verbose > 1) 02405 ast_verbose( VERBOSE_PREFIX_2 "Starting %s at %s,%s,%d still failed so falling back to context 'default'\n", c->name, c->context, c->exten, c->priority); 02406 ast_copy_string(c->context, "default", sizeof(c->context)); 02407 } 02408 } 02409 if (c->cdr && ast_tvzero(c->cdr->start)) 02410 ast_cdr_start(c->cdr); 02411 for (;;) { 02412 char dst_exten[256]; /* buffer to accumulate digits */ 02413 int pos = 0; /* XXX should check bounds */ 02414 int digit = 0; 02415 02416 /* loop on priorities in this context/exten */ 02417 while (ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) { 02418 found = 1; 02419 if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num))) { 02420 /* Something bad happened, or a hangup has been requested. */ 02421 if (strchr("0123456789ABCDEF*#", res)) { 02422 if (option_debug) 02423 ast_log(LOG_DEBUG, "Oooh, got something to jump out with ('%c')!\n", res); 02424 pos = 0; 02425 dst_exten[pos++] = digit = res; 02426 dst_exten[pos] = '\0'; 02427 break; 02428 } 02429 if (res == AST_PBX_KEEPALIVE) { 02430 if (option_debug) 02431 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name); 02432 if (option_verbose > 1) 02433 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name); 02434 error = 1; 02435 break; 02436 } 02437 if (option_debug) 02438 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 02439 if (option_verbose > 1) 02440 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 02441 if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) { 02442 c->_softhangup = 0; 02443 } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) { 02444 /* atimeout, nothing bad */ 02445 } else { 02446 if (c->cdr) 02447 ast_cdr_update(c); 02448 error = 1; 02449 break; 02450 } 02451 } 02452 if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) { 02453 c->_softhangup = 0; 02454 } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT && ast_exists_extension(c,c->context,"T",1,c->cid.cid_num)) { 02455 set_ext_pri(c, "T", 0); /* 0 will become 1 with the c->priority++; at the end */ 02456 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 02457 c->whentohangup = 0; 02458 c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT; 02459 } else if (c->_softhangup) { 02460 if (option_debug) 02461 ast_log(LOG_DEBUG, "Extension %s, priority %d returned normally even though call was hung up\n", 02462 c->exten, c->priority); 02463 error = 1; 02464 break; 02465 } 02466 c->priority++; 02467 } /* end while - from here on we can use 'break' to go out */ 02468 if (error) 02469 break; 02470 02471 /* XXX we get here on non-existing extension or a keypress or hangup ? */ 02472 02473 if (!ast_exists_extension(c, c->context, c->exten, 1, c->cid.cid_num)) { 02474 /* If there is no match at priority 1, it is not a valid extension anymore. 02475 * Try to continue at "i", 1 or exit if the latter does not exist. 02476 */ 02477 if (ast_exists_extension(c, c->context, "i", 1, c->cid.cid_num)) { 02478 if (option_verbose > 2) 02479 ast_verbose(VERBOSE_PREFIX_3 "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, c->name); 02480 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", c->exten); 02481 set_ext_pri(c, "i", 1); 02482 } else { 02483 ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n", 02484 c->name, c->exten, c->context); 02485 error = 1; /* we know what to do with it */ 02486 break; 02487 } 02488 } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) { 02489 /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */ 02490 c->_softhangup = 0; 02491 } else { /* keypress received, get more digits for a full extension */ 02492 int waittime = 0; 02493 if (digit) 02494 waittime = c->pbx->dtimeout; 02495 else if (!autofallthrough) 02496 waittime = c->pbx->rtimeout; 02497 if (!waittime) { 02498 const char *status = pbx_builtin_getvar_helper(c, "DIALSTATUS"); 02499 if (!status) 02500 status = "UNKNOWN"; 02501 if (option_verbose > 2) 02502 ast_verbose(VERBOSE_PREFIX_2 "Auto fallthrough, channel '%s' status is '%s'\n", c->name, status); 02503 if (!strcasecmp(status, "CONGESTION")) 02504 res = pbx_builtin_congestion(c, "10"); 02505 else if (!strcasecmp(status, "CHANUNAVAIL")) 02506 res = pbx_builtin_congestion(c, "10"); 02507 else if (!strcasecmp(status, "BUSY")) 02508 res = pbx_builtin_busy(c, "10"); 02509 error = 1; /* XXX disable message */ 02510 break; /* exit from the 'for' loop */ 02511 } 02512 02513 if (collect_digits(c, waittime, dst_exten, sizeof(dst_exten), pos)) 02514 break; 02515 if (ast_exists_extension(c, c->context, dst_exten, 1, c->cid.cid_num)) /* Prepare the next cycle */ 02516 set_ext_pri(c, dst_exten, 1); 02517 else { 02518 /* No such extension */ 02519 if (!ast_strlen_zero(dst_exten)) { 02520 /* An invalid extension */ 02521 if (ast_exists_extension(c, c->context, "i", 1, c->cid.cid_num)) { 02522 if (option_verbose > 2) 02523 ast_verbose( VERBOSE_PREFIX_3 "Invalid extension '%s' in context '%s' on %s\n", dst_exten, c->context, c->name); 02524 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", dst_exten); 02525 set_ext_pri(c, "i", 1); 02526 } else { 02527 ast_log(LOG_WARNING, "Invalid extension '%s', but no rule 'i' in context '%s'\n", dst_exten, c->context); 02528 found = 1; /* XXX disable message */ 02529 break; 02530 } 02531 } else { 02532 /* A simple timeout */ 02533 if (ast_exists_extension(c, c->context, "t", 1, c->cid.cid_num)) { 02534 if (option_verbose > 2) 02535 ast_verbose( VERBOSE_PREFIX_3 "Timeout on %s\n", c->name); 02536 set_ext_pri(c, "t", 1); 02537 } else { 02538 ast_log(LOG_WARNING, "Timeout, but no rule 't' in context '%s'\n", c->context); 02539 found = 1; /* XXX disable message */ 02540 break; 02541 } 02542 } 02543 } 02544 if (c->cdr) { 02545 if (option_verbose > 2) 02546 ast_verbose(VERBOSE_PREFIX_2 "CDR updated on %s\n",c->name); 02547 ast_cdr_update(c); 02548 } 02549 } 02550 } 02551 if (!found && !error) 02552 ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name); 02553 if (res != AST_PBX_KEEPALIVE) 02554 ast_softhangup(c, c->hangupcause ? c->hangupcause : AST_CAUSE_NORMAL_CLEARING); 02555 if ((res != AST_PBX_KEEPALIVE) && ast_exists_extension(c, c->context, "h", 1, c->cid.cid_num)) { 02556 if (c->cdr && ast_opt_end_cdr_before_h_exten) 02557 ast_cdr_end(c->cdr); 02558 set_ext_pri(c, "h", 1); 02559 while(ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) { 02560 if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num))) { 02561 /* Something bad happened, or a hangup has been requested. */ 02562 if (option_debug) 02563 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 02564 if (option_verbose > 1) 02565 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 02566 break; 02567 } 02568 c->priority++; 02569 } 02570 } 02571 ast_set2_flag(c, autoloopflag, AST_FLAG_IN_AUTOLOOP); 02572 02573 pbx_destroy(c->pbx); 02574 c->pbx = NULL; 02575 if (res != AST_PBX_KEEPALIVE) 02576 ast_hangup(c); 02577 return 0; 02578 }
static int _extension_match_core | ( | const char * | pattern, | |
const char * | data, | |||
enum ext_match_t | mode | |||
) | [static] |
Definition at line 772 of file pbx.c.
References ast_log(), E_MATCH, E_MATCH_MASK, E_MATCHMORE, and LOG_WARNING.
Referenced by extension_match_core().
00773 { 00774 mode &= E_MATCH_MASK; /* only consider the relevant bits */ 00775 00776 if ( (mode == E_MATCH) && (pattern[0] == '_') && (strcasecmp(pattern,data)==0) ) /* note: if this test is left out, then _x. will not match _x. !!! */ 00777 return 1; 00778 00779 if (pattern[0] != '_') { /* not a pattern, try exact or partial match */ 00780 int ld = strlen(data), lp = strlen(pattern); 00781 00782 if (lp < ld) /* pattern too short, cannot match */ 00783 return 0; 00784 /* depending on the mode, accept full or partial match or both */ 00785 if (mode == E_MATCH) 00786 return !strcmp(pattern, data); /* 1 on match, 0 on fail */ 00787 if (ld == 0 || !strncasecmp(pattern, data, ld)) /* partial or full match */ 00788 return (mode == E_MATCHMORE) ? lp > ld : 1; /* XXX should consider '!' and '/' ? */ 00789 else 00790 return 0; 00791 } 00792 pattern++; /* skip leading _ */ 00793 /* 00794 * XXX below we stop at '/' which is a separator for the CID info. However we should 00795 * not store '/' in the pattern at all. When we insure it, we can remove the checks. 00796 */ 00797 while (*data && *pattern && *pattern != '/') { 00798 const char *end; 00799 00800 if (*data == '-') { /* skip '-' in data (just a separator) */ 00801 data++; 00802 continue; 00803 } 00804 switch (toupper(*pattern)) { 00805 case '[': /* a range */ 00806 end = strchr(pattern+1, ']'); /* XXX should deal with escapes ? */ 00807 if (end == NULL) { 00808 ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n"); 00809 return 0; /* unconditional failure */ 00810 } 00811 for (pattern++; pattern != end; pattern++) { 00812 if (pattern+2 < end && pattern[1] == '-') { /* this is a range */ 00813 if (*data >= pattern[0] && *data <= pattern[2]) 00814 break; /* match found */ 00815 else { 00816 pattern += 2; /* skip a total of 3 chars */ 00817 continue; 00818 } 00819 } else if (*data == pattern[0]) 00820 break; /* match found */ 00821 } 00822 if (pattern == end) 00823 return 0; 00824 pattern = end; /* skip and continue */ 00825 break; 00826 case 'N': 00827 if (*data < '2' || *data > '9') 00828 return 0; 00829 break; 00830 case 'X': 00831 if (*data < '0' || *data > '9') 00832 return 0; 00833 break; 00834 case 'Z': 00835 if (*data < '1' || *data > '9') 00836 return 0; 00837 break; 00838 case '.': /* Must match, even with more digits */ 00839 return 1; 00840 case '!': /* Early match */ 00841 return 2; 00842 case ' ': 00843 case '-': /* Ignore these in patterns */ 00844 data--; /* compensate the final data++ */ 00845 break; 00846 default: 00847 if (*data != *pattern) 00848 return 0; 00849 } 00850 data++; 00851 pattern++; 00852 } 00853 if (*data) /* data longer than pattern, no match */ 00854 return 0; 00855 /* 00856 * match so far, but ran off the end of the data. 00857 * Depending on what is next, determine match or not. 00858 */ 00859 if (*pattern == '\0' || *pattern == '/') /* exact match */ 00860 return (mode == E_MATCHMORE) ? 0 : 1; /* this is a failure for E_MATCHMORE */ 00861 else if (*pattern == '!') /* early match */ 00862 return 2; 00863 else /* partial match */ 00864 return (mode == E_MATCH) ? 0 : 1; /* this is a failure for E_MATCH */ 00865 }
static int add_pri | ( | struct ast_context * | con, | |
struct ast_exten * | tmp, | |||
struct ast_exten * | el, | |||
struct ast_exten * | e, | |||
int | replace | |||
) | [static] |
add the extension in the priority chain. returns 0 on success, -1 on failure
Definition at line 4685 of file pbx.c.
References ast_change_hint(), ast_log(), ast_exten::data, ast_exten::datad, el, ast_exten::exten, free, LOG_WARNING, ast_exten::next, ast_exten::peer, ast_exten::priority, PRIORITY_HINT, and ast_context::root.
Referenced by ast_add_extension2().
04687 { 04688 struct ast_exten *ep; 04689 04690 for (ep = NULL; e ; ep = e, e = e->peer) { 04691 if (e->priority >= tmp->priority) 04692 break; 04693 } 04694 if (!e) { /* go at the end, and ep is surely set because the list is not empty */ 04695 ep->peer = tmp; 04696 return 0; /* success */ 04697 } 04698 if (e->priority == tmp->priority) { 04699 /* Can't have something exactly the same. Is this a 04700 replacement? If so, replace, otherwise, bonk. */ 04701 if (!replace) { 04702 ast_log(LOG_WARNING, "Unable to register extension '%s', priority %d in '%s', already in use\n", tmp->exten, tmp->priority, con->name); 04703 if (tmp->datad) 04704 tmp->datad(tmp->data); 04705 free(tmp); 04706 return -1; 04707 } 04708 /* we are replacing e, so copy the link fields and then update 04709 * whoever pointed to e to point to us 04710 */ 04711 tmp->next = e->next; /* not meaningful if we are not first in the peer list */ 04712 tmp->peer = e->peer; /* always meaningful */ 04713 if (ep) /* We're in the peer list, just insert ourselves */ 04714 ep->peer = tmp; 04715 else if (el) /* We're the first extension. Take over e's functions */ 04716 el->next = tmp; 04717 else /* We're the very first extension. */ 04718 con->root = tmp; 04719 if (tmp->priority == PRIORITY_HINT) 04720 ast_change_hint(e,tmp); 04721 /* Destroy the old one */ 04722 if (e->datad) 04723 e->datad(e->data); 04724 free(e); 04725 } else { /* Slip ourselves in just before e */ 04726 tmp->peer = e; 04727 tmp->next = e->next; /* extension chain, or NULL if e is not the first extension */ 04728 if (ep) /* Easy enough, we're just in the peer list */ 04729 ep->peer = tmp; 04730 else { /* we are the first in some peer list, so link in the ext list */ 04731 if (el) 04732 el->next = tmp; /* in the middle... */ 04733 else 04734 con->root = tmp; /* ... or at the head */ 04735 e->next = NULL; /* e is no more at the head, so e->next must be reset */ 04736 } 04737 /* And immediately return success. */ 04738 if (tmp->priority == PRIORITY_HINT) 04739 ast_add_hint(tmp); 04740 } 04741 return 0; 04742 }
int ast_active_calls | ( | void | ) |
Retrieve the number of active calls.
Definition at line 2683 of file pbx.c.
References countcalls.
Referenced by handle_chanlist(), and handle_chanlist_deprecated().
02684 { 02685 return countcalls; 02686 }
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 4560 of file pbx.c.
References ast_add_extension2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_context_add_extension(), handle_context_add_extension_deprecated(), park_add_hints(), and register_peer_exten().
04563 { 04564 int ret = -1; 04565 struct ast_context *c = find_context_locked(context); 04566 04567 if (c) { 04568 ret = ast_add_extension2(c, replace, extension, priority, label, callerid, 04569 application, data, datad, registrar); 04570 ast_unlock_contexts(); 04571 } 04572 return ret; 04573 }
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 4769 of file pbx.c.
References add_pri(), ast_exten::app, ast_add_hint(), ast_calloc, AST_LIST_FIRST, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), ast_exten::cidmatch, ast_exten::data, ast_exten::datad, el, errno, ext_cmp(), ext_strncpy(), ast_exten::exten, ast_exten::label, ast_context::lock, ast_exten::matchcid, ast_exten::next, option_verbose, ast_exten::parent, pbx_substitute_variables_varshead(), ast_exten::priority, PRIORITY_HINT, ast_exten::registrar, ast_context::root, ast_exten::stuff, VAR_BUF_SIZE, and VERBOSE_PREFIX_3.
Referenced by add_extensions(), ast_add_extension(), ast_autoanswer_login(), autoanswer_reregister_extensions(), do_parking_thread(), park_call_full(), pbx_load_config(), and pbx_load_users().
04773 { 04774 /* 04775 * Sort extensions (or patterns) according to the rules indicated above. 04776 * These are implemented by the function ext_cmp()). 04777 * All priorities for the same ext/pattern/cid are kept in a list, 04778 * using the 'peer' field as a link field.. 04779 */ 04780 struct ast_exten *tmp, *e, *el = NULL; 04781 int res; 04782 int length; 04783 char *p; 04784 char expand_buf[VAR_BUF_SIZE] = { 0, }; 04785 04786 /* if we are adding a hint, and there are global variables, and the hint 04787 contains variable references, then expand them 04788 */ 04789 ast_mutex_lock(&globalslock); 04790 if (priority == PRIORITY_HINT && AST_LIST_FIRST(&globals) && strstr(application, "${")) { 04791 pbx_substitute_variables_varshead(&globals, application, expand_buf, sizeof(expand_buf)); 04792 application = expand_buf; 04793 } 04794 ast_mutex_unlock(&globalslock); 04795 04796 length = sizeof(struct ast_exten); 04797 length += strlen(extension) + 1; 04798 length += strlen(application) + 1; 04799 if (label) 04800 length += strlen(label) + 1; 04801 if (callerid) 04802 length += strlen(callerid) + 1; 04803 else 04804 length ++; /* just the '\0' */ 04805 04806 /* Be optimistic: Build the extension structure first */ 04807 if (!(tmp = ast_calloc(1, length))) 04808 return -1; 04809 04810 /* use p as dst in assignments, as the fields are const char * */ 04811 p = tmp->stuff; 04812 if (label) { 04813 tmp->label = p; 04814 strcpy(p, label); 04815 p += strlen(label) + 1; 04816 } 04817 tmp->exten = p; 04818 p += ext_strncpy(p, extension, strlen(extension) + 1) + 1; 04819 tmp->priority = priority; 04820 tmp->cidmatch = p; /* but use p for assignments below */ 04821 if (callerid) { 04822 p += ext_strncpy(p, callerid, strlen(callerid) + 1) + 1; 04823 tmp->matchcid = 1; 04824 } else { 04825 *p++ = '\0'; 04826 tmp->matchcid = 0; 04827 } 04828 tmp->app = p; 04829 strcpy(p, application); 04830 tmp->parent = con; 04831 tmp->data = data; 04832 tmp->datad = datad; 04833 tmp->registrar = registrar; 04834 04835 ast_mutex_lock(&con->lock); 04836 res = 0; /* some compilers will think it is uninitialized otherwise */ 04837 for (e = con->root; e; el = e, e = e->next) { /* scan the extension list */ 04838 res = ext_cmp(e->exten, extension); 04839 if (res == 0) { /* extension match, now look at cidmatch */ 04840 if (!e->matchcid && !tmp->matchcid) 04841 res = 0; 04842 else if (tmp->matchcid && !e->matchcid) 04843 res = 1; 04844 else if (e->matchcid && !tmp->matchcid) 04845 res = -1; 04846 else 04847 res = strcasecmp(e->cidmatch, tmp->cidmatch); 04848 } 04849 if (res >= 0) 04850 break; 04851 } 04852 if (e && res == 0) { /* exact match, insert in the pri chain */ 04853 res = add_pri(con, tmp, el, e, replace); 04854 ast_mutex_unlock(&con->lock); 04855 if (res < 0) { 04856 errno = EEXIST; /* XXX do we care ? */ 04857 return 0; /* XXX should we return -1 maybe ? */ 04858 } 04859 } else { 04860 /* 04861 * not an exact match, this is the first entry with this pattern, 04862 * so insert in the main list right before 'e' (if any) 04863 */ 04864 tmp->next = e; 04865 if (el) 04866 el->next = tmp; 04867 else 04868 con->root = tmp; 04869 ast_mutex_unlock(&con->lock); 04870 if (tmp->priority == PRIORITY_HINT) 04871 ast_add_hint(tmp); 04872 } 04873 if (option_debug) { 04874 if (tmp->matchcid) { 04875 if (option_debug) 04876 ast_log(LOG_DEBUG, "Added extension '%s' priority %d (CID match '%s') to %s\n", 04877 tmp->exten, tmp->priority, tmp->cidmatch, con->name); 04878 } else { 04879 if (option_debug) 04880 ast_log(LOG_DEBUG, "Added extension '%s' priority %d to %s\n", 04881 tmp->exten, tmp->priority, con->name); 04882 } 04883 } 04884 if (option_verbose > 2) { 04885 if (tmp->matchcid) { 04886 ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d (CID match '%s')to %s\n", 04887 tmp->exten, tmp->priority, tmp->cidmatch, con->name); 04888 } else { 04889 ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d to %s\n", 04890 tmp->exten, tmp->priority, con->name); 04891 } 04892 } 04893 return 0; 04894 }
static int ast_add_hint | ( | struct ast_exten * | e | ) | [static] |
ast_add_hint: Add hint to hint list, check initial extension state
Definition at line 2181 of file pbx.c.
References ast_calloc, ast_extension_state2(), ast_get_extension_app(), ast_get_extension_name(), AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_hint::exten, LOG_DEBUG, and option_debug.
Referenced by ast_add_extension2().
02182 { 02183 struct ast_hint *hint; 02184 02185 if (!e) 02186 return -1; 02187 02188 AST_LIST_LOCK(&hints); 02189 02190 /* Search if hint exists, do nothing */ 02191 AST_LIST_TRAVERSE(&hints, hint, list) { 02192 if (hint->exten == e) { 02193 AST_LIST_UNLOCK(&hints); 02194 if (option_debug > 1) 02195 ast_log(LOG_DEBUG, "HINTS: Not re-adding existing hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e)); 02196 return -1; 02197 } 02198 } 02199 02200 if (option_debug > 1) 02201 ast_log(LOG_DEBUG, "HINTS: Adding hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e)); 02202 02203 if (!(hint = ast_calloc(1, sizeof(*hint)))) { 02204 AST_LIST_UNLOCK(&hints); 02205 return -1; 02206 } 02207 /* Initialize and insert new item at the top */ 02208 hint->exten = e; 02209 hint->laststate = ast_extension_state2(e); 02210 AST_LIST_INSERT_HEAD(&hints, hint, list); 02211 02212 AST_LIST_UNLOCK(&hints); 02213 return 0; 02214 }
AST_APP_OPTIONS | ( | resetcdr_opts | ) |
AST_APP_OPTIONS | ( | waitexten_opts | ) |
AST_APP_OPTIONS | ( | background_opts | ) |
int ast_async_goto | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 4598 of file pbx.c.
References ast_channel::_state, ast_channel::amaflags, ast_cdr_discard(), ast_cdr_dup(), ast_channel_alloc(), ast_channel_lock, ast_channel_masquerade(), ast_channel_unlock, ast_do_masquerade(), ast_explicit_goto(), ast_hangup(), ast_log(), ast_pbx_start(), AST_SOFTHANGUP_ASYNCGOTO, ast_softhangup_nolock(), ast_channel::cdr, ast_channel::context, ast_channel::exten, LOG_WARNING, ast_channel::pbx, ast_channel::readformat, S_OR, and ast_channel::writeformat.
Referenced by __ast_goto_if_exists(), action_redirect(), ast_async_goto_by_name(), builtin_blindtransfer(), console_transfer(), console_transfer_deprecated(), handle_request_bye(), handle_request_refer(), process_ast_dsp(), socket_process(), and zt_handle_dtmfup().
04599 { 04600 int res = 0; 04601 04602 ast_channel_lock(chan); 04603 04604 if (chan->pbx) { /* This channel is currently in the PBX */ 04605 ast_explicit_goto(chan, context, exten, priority); 04606 ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO); 04607 } else { 04608 /* In order to do it when the channel doesn't really exist within 04609 the PBX, we have to make a new channel, masquerade, and start the PBX 04610 at the new location */ 04611 struct ast_channel *tmpchan = ast_channel_alloc(0, chan->_state, 0, 0, chan->accountcode, chan->exten, chan->context, chan->amaflags, "AsyncGoto/%s", chan->name); 04612 if (!tmpchan) { 04613 res = -1; 04614 } else { 04615 if (chan->cdr) { 04616 ast_cdr_discard(tmpchan->cdr); 04617 tmpchan->cdr = ast_cdr_dup(chan->cdr); /* share the love */ 04618 } 04619 /* Make formats okay */ 04620 tmpchan->readformat = chan->readformat; 04621 tmpchan->writeformat = chan->writeformat; 04622 /* Setup proper location */ 04623 ast_explicit_goto(tmpchan, 04624 S_OR(context, chan->context), S_OR(exten, chan->exten), priority); 04625 04626 /* Masquerade into temp channel */ 04627 ast_channel_masquerade(tmpchan, chan); 04628 04629 /* Grab the locks and get going */ 04630 ast_channel_lock(tmpchan); 04631 ast_do_masquerade(tmpchan); 04632 ast_channel_unlock(tmpchan); 04633 /* Start the PBX going on our stolen channel */ 04634 if (ast_pbx_start(tmpchan)) { 04635 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name); 04636 ast_hangup(tmpchan); 04637 res = -1; 04638 } 04639 } 04640 } 04641 ast_channel_unlock(chan); 04642 return res; 04643 }
int ast_async_goto_by_name | ( | const char * | channame, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 4645 of file pbx.c.
References ast_async_goto(), ast_channel_unlock, and ast_get_channel_by_name_locked().
04646 { 04647 struct ast_channel *chan; 04648 int res = -1; 04649 04650 chan = ast_get_channel_by_name_locked(channame); 04651 if (chan) { 04652 res = ast_async_goto(chan, context, exten, priority); 04653 ast_channel_unlock(chan); 04654 } 04655 return res; 04656 }
int ast_async_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 6385 of file pbx.c.
References __ast_goto_if_exists().
Referenced by asyncgoto_exec().
06386 { 06387 return __ast_goto_if_exists(chan, context, exten, priority, 1); 06388 }
int ast_build_timing | ( | struct ast_timing * | i, | |
const char * | info_in | |||
) |
Definition at line 4243 of file pbx.c.
References ast_strlen_zero(), ast_timing::daymask, days, ast_timing::dowmask, get_range(), get_timerange(), ast_timing::monthmask, months, and strsep().
Referenced by ast_context_add_include2(), iftime(), pbx_builtin_execiftime(), and pbx_builtin_gotoiftime().
04244 { 04245 char info_save[256]; 04246 char *info; 04247 04248 /* Check for empty just in case */ 04249 if (ast_strlen_zero(info_in)) 04250 return 0; 04251 /* make a copy just in case we were passed a static string */ 04252 ast_copy_string(info_save, info_in, sizeof(info_save)); 04253 info = info_save; 04254 /* Assume everything except time */ 04255 i->monthmask = 0xfff; /* 12 bits */ 04256 i->daymask = 0x7fffffffU; /* 31 bits */ 04257 i->dowmask = 0x7f; /* 7 bits */ 04258 /* on each call, use strsep() to move info to the next argument */ 04259 get_timerange(i, strsep(&info, "|")); 04260 if (info) 04261 i->dowmask = get_range(strsep(&info, "|"), 7, days, "day of week"); 04262 if (info) 04263 i->daymask = get_range(strsep(&info, "|"), 31, NULL, "day"); 04264 if (info) 04265 i->monthmask = get_range(strsep(&info, "|"), 12, months, "month"); 04266 return 1; 04267 }
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 2305 of file pbx.c.
References E_CANMATCH, and pbx_extension_helper().
Referenced by background_detect_exec(), cb_events(), dp_lookup(), dundi_lookup_local(), get_also_info(), get_destination(), handle_link_data(), handle_link_phone_dtmf(), local_dtmf_helper(), loopback_canmatch(), mgcp_ss(), phone_check_exception(), skinny_ss(), ss_thread(), and valid_exit().
02306 { 02307 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH); 02308 }
ast_change_hint: Change hint for an extension
Definition at line 2217 of file pbx.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, and ast_hint::exten.
Referenced by add_pri().
02218 { 02219 struct ast_hint *hint; 02220 int res = -1; 02221 02222 AST_LIST_LOCK(&hints); 02223 AST_LIST_TRAVERSE(&hints, hint, list) { 02224 if (hint->exten == oe) { 02225 hint->exten = ne; 02226 res = 0; 02227 break; 02228 } 02229 } 02230 AST_LIST_UNLOCK(&hints); 02231 02232 return res; 02233 }
int ast_check_timing | ( | const struct ast_timing * | i | ) |
Definition at line 4269 of file pbx.c.
References ast_localtime(), ast_log(), ast_timing::daymask, ast_timing::dowmask, LOG_WARNING, ast_timing::minmask, ast_timing::monthmask, and t.
Referenced by iftime(), include_valid(), pbx_builtin_execiftime(), and pbx_builtin_gotoiftime().
04270 { 04271 struct tm tm; 04272 time_t t = time(NULL); 04273 04274 ast_localtime(&t, &tm, NULL); 04275 04276 /* If it's not the right month, return */ 04277 if (!(i->monthmask & (1 << tm.tm_mon))) 04278 return 0; 04279 04280 /* If it's not that time of the month.... */ 04281 /* Warning, tm_mday has range 1..31! */ 04282 if (!(i->daymask & (1 << (tm.tm_mday-1)))) 04283 return 0; 04284 04285 /* If it's not the right day of the week */ 04286 if (!(i->dowmask & (1 << tm.tm_wday))) 04287 return 0; 04288 04289 /* Sanity check the hour just to be safe */ 04290 if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) { 04291 ast_log(LOG_WARNING, "Insane time...\n"); 04292 return 0; 04293 } 04294 04295 /* Now the tough part, we calculate if it fits 04296 in the right time based on min/hour */ 04297 if (!(i->minmask[tm.tm_hour] & (1 << (tm.tm_min / 2)))) 04298 return 0; 04299 04300 /* If we got this far, then we're good */ 04301 return 1; 04302 }
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 4496 of file pbx.c.
References ast_context_add_ignorepat2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_context_add_ignorepat(), and handle_context_add_ignorepat_deprecated().
04497 { 04498 int ret = -1; 04499 struct ast_context *c = find_context_locked(context); 04500 04501 if (c) { 04502 ret = ast_context_add_ignorepat2(c, value, registrar); 04503 ast_unlock_contexts(); 04504 } 04505 return ret; 04506 }
int ast_context_add_ignorepat2 | ( | struct ast_context * | con, | |
const char * | value, | |||
const char * | registrar | |||
) |
Definition at line 4508 of file pbx.c.
References ast_calloc, ast_mutex_lock(), ast_mutex_unlock(), errno, ast_context::ignorepats, ast_context::lock, ast_ignorepat::next, ast_ignorepat::pattern, and ast_ignorepat::registrar.
Referenced by ast_context_add_ignorepat(), and pbx_load_config().
04509 { 04510 struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL; 04511 int length; 04512 length = sizeof(struct ast_ignorepat); 04513 length += strlen(value) + 1; 04514 if (!(ignorepat = ast_calloc(1, length))) 04515 return -1; 04516 /* The cast to char * is because we need to write the initial value. 04517 * The field is not supposed to be modified otherwise 04518 */ 04519 strcpy((char *)ignorepat->pattern, value); 04520 ignorepat->next = NULL; 04521 ignorepat->registrar = registrar; 04522 ast_mutex_lock(&con->lock); 04523 for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) { 04524 ignorepatl = ignorepatc; 04525 if (!strcasecmp(ignorepatc->pattern, value)) { 04526 /* Already there */ 04527 ast_mutex_unlock(&con->lock); 04528 errno = EEXIST; 04529 return -1; 04530 } 04531 } 04532 if (ignorepatl) 04533 ignorepatl->next = ignorepat; 04534 else 04535 con->ignorepats = ignorepat; 04536 ast_mutex_unlock(&con->lock); 04537 return 0; 04538 04539 }
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 4049 of file pbx.c.
References ast_context_add_include2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_context_add_include(), and handle_context_add_include_deprecated().
04050 { 04051 int ret = -1; 04052 struct ast_context *c = find_context_locked(context); 04053 04054 if (c) { 04055 ret = ast_context_add_include2(c, include, registrar); 04056 ast_unlock_contexts(); 04057 } 04058 return ret; 04059 }
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 4311 of file pbx.c.
References ast_build_timing(), ast_calloc, ast_get_context_name(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), errno, free, ast_include::hastime, ast_context::includes, ast_context::lock, ast_include::name, ast_include::next, option_verbose, ast_include::registrar, ast_include::rname, ast_include::stuff, ast_include::timing, and VERBOSE_PREFIX_3.
Referenced by ast_context_add_include(), and pbx_load_config().
04313 { 04314 struct ast_include *new_include; 04315 char *c; 04316 struct ast_include *i, *il = NULL; /* include, include_last */ 04317 int length; 04318 char *p; 04319 04320 length = sizeof(struct ast_include); 04321 length += 2 * (strlen(value) + 1); 04322 04323 /* allocate new include structure ... */ 04324 if (!(new_include = ast_calloc(1, length))) 04325 return -1; 04326 /* Fill in this structure. Use 'p' for assignments, as the fields 04327 * in the structure are 'const char *' 04328 */ 04329 p = new_include->stuff; 04330 new_include->name = p; 04331 strcpy(p, value); 04332 p += strlen(value) + 1; 04333 new_include->rname = p; 04334 strcpy(p, value); 04335 /* Strip off timing info, and process if it is there */ 04336 if ( (c = strchr(p, '|')) ) { 04337 *c++ = '\0'; 04338 new_include->hastime = ast_build_timing(&(new_include->timing), c); 04339 } 04340 new_include->next = NULL; 04341 new_include->registrar = registrar; 04342 04343 ast_mutex_lock(&con->lock); 04344 04345 /* ... go to last include and check if context is already included too... */ 04346 for (i = con->includes; i; i = i->next) { 04347 if (!strcasecmp(i->name, new_include->name)) { 04348 free(new_include); 04349 ast_mutex_unlock(&con->lock); 04350 errno = EEXIST; 04351 return -1; 04352 } 04353 il = i; 04354 } 04355 04356 /* ... include new context into context list, unlock, return */ 04357 if (il) 04358 il->next = new_include; 04359 else 04360 con->includes = new_include; 04361 if (option_verbose > 2) 04362 ast_verbose(VERBOSE_PREFIX_3 "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con)); 04363 ast_mutex_unlock(&con->lock); 04364 04365 return 0; 04366 }
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 4373 of file pbx.c.
References ast_context_add_switch2(), ast_unlock_contexts(), and find_context_locked().
04374 { 04375 int ret = -1; 04376 struct ast_context *c = find_context_locked(context); 04377 04378 if (c) { /* found, add switch to this context */ 04379 ret = ast_context_add_switch2(c, sw, data, eval, registrar); 04380 ast_unlock_contexts(); 04381 } 04382 return ret; 04383 }
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 4392 of file pbx.c.
References ast_calloc, ast_get_context_name(), AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), ast_sw::data, errno, ast_sw::eval, free, ast_context::lock, ast_sw::name, option_verbose, ast_sw::registrar, and VERBOSE_PREFIX_3.
Referenced by ast_context_add_switch(), and pbx_load_config().
04394 { 04395 struct ast_sw *new_sw; 04396 struct ast_sw *i; 04397 int length; 04398 char *p; 04399 04400 length = sizeof(struct ast_sw); 04401 length += strlen(value) + 1; 04402 if (data) 04403 length += strlen(data); 04404 length++; 04405 04406 /* allocate new sw structure ... */ 04407 if (!(new_sw = ast_calloc(1, length))) 04408 return -1; 04409 /* ... fill in this structure ... */ 04410 p = new_sw->stuff; 04411 new_sw->name = p; 04412 strcpy(new_sw->name, value); 04413 p += strlen(value) + 1; 04414 new_sw->data = p; 04415 if (data) { 04416 strcpy(new_sw->data, data); 04417 p += strlen(data) + 1; 04418 } else { 04419 strcpy(new_sw->data, ""); 04420 p++; 04421 } 04422 new_sw->eval = eval; 04423 new_sw->registrar = registrar; 04424 04425 /* ... try to lock this context ... */ 04426 ast_mutex_lock(&con->lock); 04427 04428 /* ... go to last sw and check if context is already swd too... */ 04429 AST_LIST_TRAVERSE(&con->alts, i, list) { 04430 if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) { 04431 free(new_sw); 04432 ast_mutex_unlock(&con->lock); 04433 errno = EEXIST; 04434 return -1; 04435 } 04436 } 04437 04438 /* ... sw new context into context list, unlock, return */ 04439 AST_LIST_INSERT_TAIL(&con->alts, new_sw, list); 04440 04441 if (option_verbose > 2) 04442 ast_verbose(VERBOSE_PREFIX_3 "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con)); 04443 04444 ast_mutex_unlock(&con->lock); 04445 04446 return 0; 04447 }
struct ast_context* ast_context_create | ( | struct ast_context ** | extcontexts, | |
const char * | name, | |||
const char * | registrar | |||
) |
Register a new context.
extcontexts | pointer to the ast_context structure pointer | |
name | name of the new context | |
registrar | registrar of the context |
Definition at line 3919 of file pbx.c.
References __ast_context_create().
Referenced by ast_autoanswer_login(), autoanswer_reregister_extensions(), do_parking_thread(), park_call_full(), and set_config().
03920 { 03921 return __ast_context_create(extcontexts, name, registrar, 0); 03922 }
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 5369 of file pbx.c.
References __ast_context_destroy(), ast_unlock_contexts(), and ast_wrlock_contexts().
Referenced by cleanup_stale_contexts(), sla_destroy(), and unload_module().
05370 { 05371 ast_wrlock_contexts(); 05372 __ast_context_destroy(con,registrar); 05373 ast_unlock_contexts(); 05374 }
struct ast_context* ast_context_find | ( | const char * | name | ) |
Find a context.
name | name of the context to find |
Definition at line 895 of file pbx.c.
References ast_rdlock_contexts(), ast_unlock_contexts(), and ast_walk_contexts().
Referenced by _macro_exec(), ast_autoanswer_login(), ast_context_verify_includes(), ast_ignore_pattern(), autoanswer_reregister_extensions(), cleanup_stale_contexts(), do_autoanswer_thread(), do_parking_thread(), park_call_full(), park_exec(), register_peer_exten(), and set_config().
00896 { 00897 struct ast_context *tmp = NULL; 00898 00899 ast_rdlock_contexts(); 00900 00901 while ( (tmp = ast_walk_contexts(tmp)) ) { 00902 if (!name || !strcasecmp(name, tmp->name)) 00903 break; 00904 } 00905 00906 ast_unlock_contexts(); 00907 00908 return tmp; 00909 }
struct ast_context* ast_context_find_or_create | ( | struct ast_context ** | extcontexts, | |
const char * | name, | |||
const char * | registrar | |||
) |
Definition at line 3924 of file pbx.c.
References __ast_context_create().
Referenced by pbx_load_config(), and pbx_load_users().
03925 { 03926 return __ast_context_create(extcontexts, name, registrar, 1); 03927 }
int ast_context_lockmacro | ( | const char * | context | ) |
locks the macrolock in the given given context
Definition at line 2920 of file pbx.c.
References ast_get_context_name(), ast_mutex_lock(), ast_rdlock_contexts(), ast_unlock_contexts(), and ast_walk_contexts().
Referenced by _macro_exec().
02921 { 02922 struct ast_context *c = NULL; 02923 int ret = -1; 02924 02925 ast_rdlock_contexts(); 02926 02927 while ((c = ast_walk_contexts(c))) { 02928 if (!strcmp(ast_get_context_name(c), context)) { 02929 ret = 0; 02930 break; 02931 } 02932 } 02933 02934 ast_unlock_contexts(); 02935 02936 /* if we found context, lock macrolock */ 02937 if (ret == 0) 02938 ret = ast_mutex_lock(&c->macrolock); 02939 02940 return ret; 02941 }
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 | |
registrar | registrar of the extension |
0 | on success | |
-1 | on failure |
Definition at line 2821 of file pbx.c.
References ast_context_remove_extension2(), ast_unlock_contexts(), and find_context_locked().
Referenced by destroy_station(), destroy_trunk(), handle_context_remove_extension(), handle_context_remove_extension_deprecated(), and register_peer_exten().
02822 { 02823 int ret = -1; /* default error return */ 02824 struct ast_context *c = find_context_locked(context); 02825 02826 if (c) { /* ... remove extension ... */ 02827 ret = ast_context_remove_extension2(c, extension, priority, registrar); 02828 ast_unlock_contexts(); 02829 } 02830 return ret; 02831 }
int ast_context_remove_extension2 | ( | struct ast_context * | con, | |
const char * | extension, | |||
int | priority, | |||
const char * | registrar | |||
) |
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 2843 of file pbx.c.
References ast_mutex_lock(), ast_mutex_unlock(), destroy_exten(), exten, ast_context::lock, ast_exten::next, ast_exten::peer, and ast_context::root.
Referenced by ast_context_remove_extension(), do_autoanswer_thread(), do_parking_thread(), and park_exec().
02844 { 02845 struct ast_exten *exten, *prev_exten = NULL; 02846 struct ast_exten *peer; 02847 02848 ast_mutex_lock(&con->lock); 02849 02850 /* scan the extension list to find matching extension-registrar */ 02851 for (exten = con->root; exten; prev_exten = exten, exten = exten->next) { 02852 if (!strcmp(exten->exten, extension) && 02853 (!registrar || !strcmp(exten->registrar, registrar))) 02854 break; 02855 } 02856 if (!exten) { 02857 /* we can't find right extension */ 02858 ast_mutex_unlock(&con->lock); 02859 return -1; 02860 } 02861 02862 /* should we free all peers in this extension? (priority == 0)? */ 02863 if (priority == 0) { 02864 /* remove this extension from context list */ 02865 if (prev_exten) 02866 prev_exten->next = exten->next; 02867 else 02868 con->root = exten->next; 02869 02870 /* fire out all peers */ 02871 while ( (peer = exten) ) { 02872 exten = peer->peer; /* prepare for next entry */ 02873 destroy_exten(peer); 02874 } 02875 } else { 02876 /* scan the priority list to remove extension with exten->priority == priority */ 02877 struct ast_exten *previous_peer = NULL; 02878 02879 for (peer = exten; peer; previous_peer = peer, peer = peer->peer) { 02880 if (peer->priority == priority && 02881 (!registrar || !strcmp(peer->registrar, registrar) )) 02882 break; /* found our priority */ 02883 } 02884 if (!peer) { /* not found */ 02885 ast_mutex_unlock(&con->lock); 02886 return -1; 02887 } 02888 /* we are first priority extension? */ 02889 if (!previous_peer) { 02890 /* 02891 * We are first in the priority chain, so must update the extension chain. 02892 * The next node is either the next priority or the next extension 02893 */ 02894 struct ast_exten *next_node = peer->peer ? peer->peer : peer->next; 02895 02896 if (!prev_exten) /* change the root... */ 02897 con->root = next_node; 02898 else 02899 prev_exten->next = next_node; /* unlink */ 02900 if (peer->peer) /* XXX update the new head of the pri list */ 02901 peer->peer->next = peer->next; 02902 } else { /* easy, we are not first priority in extension */ 02903 previous_peer->peer = peer->peer; 02904 } 02905 02906 /* now, free whole priority extension */ 02907 destroy_exten(peer); 02908 /* XXX should we return -1 ? */ 02909 } 02910 ast_mutex_unlock(&con->lock); 02911 return 0; 02912 }
int ast_context_remove_ignorepat | ( | const char * | context, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 4453 of file pbx.c.
References ast_context_remove_ignorepat2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_context_remove_ignorepat(), and handle_context_remove_ignorepat_deprecated().
04454 { 04455 int ret = -1; 04456 struct ast_context *c = find_context_locked(context); 04457 04458 if (c) { 04459 ret = ast_context_remove_ignorepat2(c, ignorepat, registrar); 04460 ast_unlock_contexts(); 04461 } 04462 return ret; 04463 }
int ast_context_remove_ignorepat2 | ( | struct ast_context * | con, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 4465 of file pbx.c.
References ast_mutex_lock(), ast_mutex_unlock(), errno, free, ast_context::ignorepats, ast_context::lock, ast_ignorepat::next, ast_ignorepat::pattern, and ast_ignorepat::registrar.
Referenced by ast_context_remove_ignorepat().
04466 { 04467 struct ast_ignorepat *ip, *ipl = NULL; 04468 04469 ast_mutex_lock(&con->lock); 04470 04471 for (ip = con->ignorepats; ip; ip = ip->next) { 04472 if (!strcmp(ip->pattern, ignorepat) && 04473 (!registrar || (registrar == ip->registrar))) { 04474 if (ipl) { 04475 ipl->next = ip->next; 04476 free(ip); 04477 } else { 04478 con->ignorepats = ip->next; 04479 free(ip); 04480 } 04481 ast_mutex_unlock(&con->lock); 04482 return 0; 04483 } 04484 ipl = ip; 04485 } 04486 04487 ast_mutex_unlock(&con->lock); 04488 errno = EINVAL; 04489 return -1; 04490 }
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 2717 of file pbx.c.
References ast_context_remove_include2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_context_dont_include_deprecated(), and handle_context_remove_include().
02718 { 02719 int ret = -1; 02720 struct ast_context *c = find_context_locked(context); 02721 02722 if (c) { 02723 /* found, remove include from this context ... */ 02724 ret = ast_context_remove_include2(c, include, registrar); 02725 ast_unlock_contexts(); 02726 } 02727 return ret; 02728 }
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 |
Definition at line 2738 of file pbx.c.
References ast_mutex_lock(), ast_mutex_unlock(), free, ast_context::includes, ast_context::lock, ast_include::name, ast_include::next, and ast_include::registrar.
Referenced by ast_context_remove_include().
02739 { 02740 struct ast_include *i, *pi = NULL; 02741 int ret = -1; 02742 02743 ast_mutex_lock(&con->lock); 02744 02745 /* find our include */ 02746 for (i = con->includes; i; pi = i, i = i->next) { 02747 if (!strcmp(i->name, include) && 02748 (!registrar || !strcmp(i->registrar, registrar))) { 02749 /* remove from list */ 02750 if (pi) 02751 pi->next = i->next; 02752 else 02753 con->includes = i->next; 02754 /* free include and return */ 02755 free(i); 02756 ret = 0; 02757 break; 02758 } 02759 } 02760 02761 ast_mutex_unlock(&con->lock); 02762 return ret; 02763 }
int ast_context_remove_switch | ( | const char * | context, | |
const char * | sw, | |||
const char * | data, | |||
const char * | registrar | |||
) |
Remove a switch.
Definition at line 2770 of file pbx.c.
References ast_context_remove_switch2(), ast_unlock_contexts(), and find_context_locked().
02771 { 02772 int ret = -1; /* default error return */ 02773 struct ast_context *c = find_context_locked(context); 02774 02775 if (c) { 02776 /* remove switch from this context ... */ 02777 ret = ast_context_remove_switch2(c, sw, data, registrar); 02778 ast_unlock_contexts(); 02779 } 02780 return ret; 02781 }
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 2791 of file pbx.c.
References AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_mutex_lock(), ast_mutex_unlock(), ast_sw::data, free, ast_context::lock, ast_sw::name, and ast_sw::registrar.
Referenced by ast_context_remove_switch().
02792 { 02793 struct ast_sw *i; 02794 int ret = -1; 02795 02796 ast_mutex_lock(&con->lock); 02797 02798 /* walk switches */ 02799 AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) { 02800 if (!strcmp(i->name, sw) && !strcmp(i->data, data) && 02801 (!registrar || !strcmp(i->registrar, registrar))) { 02802 /* found, remove from list */ 02803 AST_LIST_REMOVE_CURRENT(&con->alts, list); 02804 free(i); /* free switch and return */ 02805 ret = 0; 02806 break; 02807 } 02808 } 02809 AST_LIST_TRAVERSE_SAFE_END 02810 02811 ast_mutex_unlock(&con->lock); 02812 02813 return ret; 02814 }
int ast_context_unlockmacro | ( | const char * | context | ) |
Unlocks the macrolock in the given context.
Definition at line 2948 of file pbx.c.
References ast_get_context_name(), ast_mutex_unlock(), ast_rdlock_contexts(), ast_unlock_contexts(), and ast_walk_contexts().
Referenced by _macro_exec().
02949 { 02950 struct ast_context *c = NULL; 02951 int ret = -1; 02952 02953 ast_rdlock_contexts(); 02954 02955 while ((c = ast_walk_contexts(c))) { 02956 if (!strcmp(ast_get_context_name(c), context)) { 02957 ret = 0; 02958 break; 02959 } 02960 } 02961 02962 ast_unlock_contexts(); 02963 02964 /* if we found context, unlock macrolock */ 02965 if (ret == 0) 02966 ret = ast_mutex_unlock(&c->macrolock); 02967 02968 return ret; 02969 }
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 6342 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().
06343 { 06344 struct ast_include *inc = NULL; 06345 int res = 0; 06346 06347 while ( (inc = ast_walk_context_includes(con, inc)) ) { 06348 if (ast_context_find(inc->rname)) 06349 continue; 06350 06351 res = -1; 06352 ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n", 06353 ast_get_context_name(con), inc->rname); 06354 break; 06355 } 06356 06357 return res; 06358 }
struct ast_custom_function* ast_custom_function_find | ( | const char * | name | ) |
Definition at line 1454 of file pbx.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, and ast_custom_function::name.
Referenced by ast_custom_function_register(), ast_func_read(), ast_func_write(), handle_show_function(), and handle_show_function_deprecated().
01455 { 01456 struct ast_custom_function *acf = NULL; 01457 01458 AST_LIST_LOCK(&acf_root); 01459 AST_LIST_TRAVERSE(&acf_root, acf, acflist) { 01460 if (!strcmp(name, acf->name)) 01461 break; 01462 } 01463 AST_LIST_UNLOCK(&acf_root); 01464 01465 return acf; 01466 }
int ast_custom_function_register | ( | struct ast_custom_function * | acf | ) |
Reigster a custom function.
Definition at line 1490 of file pbx.c.
References ast_custom_function_find(), AST_LIST_INSERT_BEFORE_CURRENT, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), ast_verbose(), LOG_ERROR, ast_custom_function::name, option_verbose, and VERBOSE_PREFIX_2.
Referenced by load_module(), odbc_load_module(), and reload().
01491 { 01492 struct ast_custom_function *cur; 01493 01494 if (!acf) 01495 return -1; 01496 01497 AST_LIST_LOCK(&acf_root); 01498 01499 if (ast_custom_function_find(acf->name)) { 01500 ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name); 01501 AST_LIST_UNLOCK(&acf_root); 01502 return -1; 01503 } 01504 01505 /* Store in alphabetical order */ 01506 AST_LIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) { 01507 if (strcasecmp(acf->name, cur->name) < 0) { 01508 AST_LIST_INSERT_BEFORE_CURRENT(&acf_root, acf, acflist); 01509 break; 01510 } 01511 } 01512 AST_LIST_TRAVERSE_SAFE_END 01513 if (!cur) 01514 AST_LIST_INSERT_TAIL(&acf_root, acf, acflist); 01515 01516 AST_LIST_UNLOCK(&acf_root); 01517 01518 if (option_verbose > 1) 01519 ast_verbose(VERBOSE_PREFIX_2 "Registered custom function %s\n", acf->name); 01520 01521 return 0; 01522 }
int ast_custom_function_unregister | ( | struct ast_custom_function * | acf | ) |
Unregister a custom function.
Definition at line 1468 of file pbx.c.
References AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_verbose(), ast_custom_function::name, option_verbose, and VERBOSE_PREFIX_2.
Referenced by odbc_unload_module(), reload(), and unload_module().
01469 { 01470 struct ast_custom_function *cur; 01471 01472 if (!acf) 01473 return -1; 01474 01475 AST_LIST_LOCK(&acf_root); 01476 AST_LIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) { 01477 if (cur == acf) { 01478 AST_LIST_REMOVE_CURRENT(&acf_root, acflist); 01479 if (option_verbose > 1) 01480 ast_verbose(VERBOSE_PREFIX_2 "Unregistered custom function %s\n", acf->name); 01481 break; 01482 } 01483 } 01484 AST_LIST_TRAVERSE_SAFE_END 01485 AST_LIST_UNLOCK(&acf_root); 01486 01487 return acf ? 0 : -1; 01488 }
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 2290 of file pbx.c.
References E_MATCH, and pbx_extension_helper().
Referenced by __ast_goto_if_exists(), __ast_pbx_run(), __login_exec(), _macro_exec(), agentmonitoroutgoing_exec(), answer_call(), ast_app_dtget(), ast_pbx_outgoing_exten_uniqueid(), builtin_atxfer(), builtin_blindtransfer(), cb_events(), console_dial(), console_dial_deprecated(), console_transfer(), console_transfer_deprecated(), disa_exec(), dp_lookup(), dundi_lookup_local(), get_also_info(), get_destination(), get_refer_info(), handle_link_data(), handle_link_phone_dtmf(), handle_stimulus_message(), leave_voicemail(), local_alloc(), local_devicestate(), local_dtmf_helper(), loopback_exists(), metermaidstate(), mgcp_ss(), misdn_overlap_dial_task(), park_call_full(), parkandannounce_exec(), pbx_builtin_waitexten(), phone_check_exception(), process_ast_dsp(), register_peer_exten(), skinny_ss(), socket_process(), ss_thread(), waitstream_core(), and zt_handle_dtmfup().
02291 { 02292 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH); 02293 }
int ast_explicit_goto | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 4575 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, 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(), ast_parseable_goto(), builtin_atxfer(), disa_exec(), do_bridge_masquerade(), and handle_setpriority().
04576 { 04577 if (!chan) 04578 return -1; 04579 04580 ast_channel_lock(chan); 04581 04582 if (!ast_strlen_zero(context)) 04583 ast_copy_string(chan->context, context, sizeof(chan->context)); 04584 if (!ast_strlen_zero(exten)) 04585 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 04586 if (priority > -1) { 04587 chan->priority = priority; 04588 /* see flag description in channel.h for explanation */ 04589 if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP)) 04590 chan->priority--; 04591 } 04592 04593 ast_channel_unlock(chan); 04594 04595 return 0; 04596 }
int ast_extension_close | ( | const char * | pattern, | |
const char * | data, | |||
int | needmore | |||
) |
Definition at line 888 of file pbx.c.
References ast_log(), E_CANMATCH, E_MATCHMORE, extension_match_core(), and LOG_WARNING.
Referenced by realtime_switch_common().
00889 { 00890 if (needmore != E_MATCHMORE && needmore != E_CANMATCH) 00891 ast_log(LOG_WARNING, "invalid argument %d\n", needmore); 00892 return extension_match_core(pattern, data, needmore); 00893 }
int ast_extension_match | ( | const char * | pattern, | |
const char * | extension | |||
) |
Determine if a given extension matches a given pattern (in NXX format).
pattern | pattern to match | |
extension | extension to check against the pattern. |
1 | on match | |
0 | on failure |
Definition at line 883 of file pbx.c.
References E_MATCH, and extension_match_core().
Referenced by ast_ignore_pattern(), do_say(), find_matching_priority(), loopback_canmatch(), loopback_exists(), loopback_matchmore(), matchcid(), misdn_cfg_is_msn_valid(), realtime_switch_common(), and show_dialplan_helper().
00884 { 00885 return extension_match_core(pattern, data, E_MATCH); 00886 }
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 2014 of file pbx.c.
References ast_extension_state2(), and ast_hint_extension().
Referenced by action_extensionstate(), and handle_request_subscribe().
02015 { 02016 struct ast_exten *e; 02017 02018 e = ast_hint_extension(c, context, exten); /* Do we have a hint for this extension ? */ 02019 if (!e) 02020 return -1; /* No hint, return -1 */ 02021 02022 return ast_extension_state2(e); /* Check all devices in the hint */ 02023 }
static int ast_extension_state2 | ( | struct ast_exten * | e | ) | [static] |
ast_extensions_state2: Check state of extension by using hints
Definition at line 1917 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_state(), AST_DEVICE_UNAVAILABLE, AST_EXTENSION_BUSY, AST_EXTENSION_INUSE, AST_EXTENSION_NOT_INUSE, AST_EXTENSION_ONHOLD, AST_EXTENSION_RINGING, AST_EXTENSION_UNAVAILABLE, ast_get_extension_app(), AST_MAX_EXTENSION, busy, inuse, ring(), and strsep().
Referenced by ast_add_hint(), ast_extension_state(), and ast_hint_state_changed().
01918 { 01919 char hint[AST_MAX_EXTENSION]; 01920 char *cur, *rest; 01921 int allunavailable = 1, allbusy = 1, allfree = 1, allonhold = 1; 01922 int busy = 0, inuse = 0, ring = 0; 01923 01924 if (!e) 01925 return -1; 01926 01927 ast_copy_string(hint, ast_get_extension_app(e), sizeof(hint)); 01928 01929 rest = hint; /* One or more devices separated with a & character */ 01930 while ( (cur = strsep(&rest, "&")) ) { 01931 int res = ast_device_state(cur); 01932 switch (res) { 01933 case AST_DEVICE_NOT_INUSE: 01934 allunavailable = 0; 01935 allbusy = 0; 01936 allonhold = 0; 01937 break; 01938 case AST_DEVICE_INUSE: 01939 inuse = 1; 01940 allunavailable = 0; 01941 allfree = 0; 01942 allonhold = 0; 01943 break; 01944 case AST_DEVICE_RINGING: 01945 ring = 1; 01946 allunavailable = 0; 01947 allfree = 0; 01948 allonhold = 0; 01949 break; 01950 case AST_DEVICE_RINGINUSE: 01951 inuse = 1; 01952 ring = 1; 01953 allunavailable = 0; 01954 allfree = 0; 01955 allonhold = 0; 01956 break; 01957 case AST_DEVICE_ONHOLD: 01958 allunavailable = 0; 01959 allfree = 0; 01960 break; 01961 case AST_DEVICE_BUSY: 01962 allunavailable = 0; 01963 allfree = 0; 01964 allonhold = 0; 01965 busy = 1; 01966 break; 01967 case AST_DEVICE_UNAVAILABLE: 01968 case AST_DEVICE_INVALID: 01969 allbusy = 0; 01970 allfree = 0; 01971 allonhold = 0; 01972 break; 01973 default: 01974 allunavailable = 0; 01975 allbusy = 0; 01976 allfree = 0; 01977 allonhold = 0; 01978 } 01979 } 01980 01981 if (!inuse && ring) 01982 return AST_EXTENSION_RINGING; 01983 if (inuse && ring) 01984 return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING); 01985 if (inuse) 01986 return AST_EXTENSION_INUSE; 01987 if (allfree) 01988 return AST_EXTENSION_NOT_INUSE; 01989 if (allonhold) 01990 return AST_EXTENSION_ONHOLD; 01991 if (allbusy) 01992 return AST_EXTENSION_BUSY; 01993 if (allunavailable) 01994 return AST_EXTENSION_UNAVAILABLE; 01995 if (busy) 01996 return AST_EXTENSION_INUSE; 01997 01998 return AST_EXTENSION_NOT_INUSE; 01999 }
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 2002 of file pbx.c.
References extension_states.
Referenced by cb_extensionstate(), handle_request_subscribe(), and handle_show_hints().
02003 { 02004 int i; 02005 02006 for (i = 0; (i < (sizeof(extension_states) / sizeof(extension_states[0]))); i++) { 02007 if (extension_states[i].extension_state == extension_state) 02008 return extension_states[i].text; 02009 } 02010 return "Unknown"; 02011 }
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 2069 of file pbx.c.
References ast_calloc, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_state_cb::callback, ast_state_cb::data, ast_state_cb::next, and statecbs.
Referenced by handle_request_subscribe(), init_manager(), and load_module().
02071 { 02072 struct ast_hint *hint; 02073 struct ast_state_cb *cblist; 02074 struct ast_exten *e; 02075 02076 /* If there's no context and extension: add callback to statecbs list */ 02077 if (!context && !exten) { 02078 AST_LIST_LOCK(&hints); 02079 02080 for (cblist = statecbs; cblist; cblist = cblist->next) { 02081 if (cblist->callback == callback) { 02082 cblist->data = data; 02083 AST_LIST_UNLOCK(&hints); 02084 return 0; 02085 } 02086 } 02087 02088 /* Now insert the callback */ 02089 if (!(cblist = ast_calloc(1, sizeof(*cblist)))) { 02090 AST_LIST_UNLOCK(&hints); 02091 return -1; 02092 } 02093 cblist->id = 0; 02094 cblist->callback = callback; 02095 cblist->data = data; 02096 02097 cblist->next = statecbs; 02098 statecbs = cblist; 02099 02100 AST_LIST_UNLOCK(&hints); 02101 return 0; 02102 } 02103 02104 if (!context || !exten) 02105 return -1; 02106 02107 /* This callback type is for only one hint, so get the hint */ 02108 e = ast_hint_extension(NULL, context, exten); 02109 if (!e) { 02110 return -1; 02111 } 02112 02113 /* Find the hint in the list of hints */ 02114 AST_LIST_LOCK(&hints); 02115 02116 AST_LIST_TRAVERSE(&hints, hint, list) { 02117 if (hint->exten == e) 02118 break; 02119 } 02120 02121 if (!hint) { 02122 /* We have no hint, sorry */ 02123 AST_LIST_UNLOCK(&hints); 02124 return -1; 02125 } 02126 02127 /* Now insert the callback in the callback list */ 02128 if (!(cblist = ast_calloc(1, sizeof(*cblist)))) { 02129 AST_LIST_UNLOCK(&hints); 02130 return -1; 02131 } 02132 cblist->id = stateid++; /* Unique ID for this callback */ 02133 cblist->callback = callback; /* Pointer to callback routine */ 02134 cblist->data = data; /* Data for the callback */ 02135 02136 cblist->next = hint->callbacks; 02137 hint->callbacks = cblist; 02138 02139 AST_LIST_UNLOCK(&hints); 02140 return cblist->id; 02141 }
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 2144 of file pbx.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_hint::callbacks, free, ast_state_cb::next, and statecbs.
Referenced by __sip_destroy(), and handle_request_subscribe().
02145 { 02146 struct ast_state_cb **p_cur = NULL; /* address of pointer to us */ 02147 int ret = -1; 02148 02149 if (!id && !callback) 02150 return -1; 02151 02152 AST_LIST_LOCK(&hints); 02153 02154 if (!id) { /* id == 0 is a callback without extension */ 02155 for (p_cur = &statecbs; *p_cur; p_cur = &(*p_cur)->next) { 02156 if ((*p_cur)->callback == callback) 02157 break; 02158 } 02159 } else { /* callback with extension, find the callback based on ID */ 02160 struct ast_hint *hint; 02161 AST_LIST_TRAVERSE(&hints, hint, list) { 02162 for (p_cur = &hint->callbacks; *p_cur; p_cur = &(*p_cur)->next) { 02163 if ((*p_cur)->id == id) 02164 break; 02165 } 02166 if (*p_cur) /* found in the inner loop */ 02167 break; 02168 } 02169 } 02170 if (p_cur && *p_cur) { 02171 struct ast_state_cb *cur = *p_cur; 02172 *p_cur = cur->next; 02173 free(cur); 02174 ret = 0; 02175 } 02176 AST_LIST_UNLOCK(&hints); 02177 return ret; 02178 }
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 |
Definition at line 2295 of file pbx.c.
References E_FINDLABEL, and pbx_extension_helper().
Referenced by action_originate(), action_redirect(), ast_parseable_goto(), asyncgoto_exec(), and handle_setpriority().
02296 { 02297 return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL); 02298 }
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.
Definition at line 2300 of file pbx.c.
References E_FINDLABEL, and pbx_extension_helper().
Referenced by pbx_load_config().
02301 { 02302 return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL); 02303 }
int ast_func_read | ( | struct ast_channel * | chan, | |
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 |
Definition at line 1544 of file pbx.c.
References ast_custom_function_find(), ast_log(), func_args(), LOG_ERROR, and ast_custom_function::read.
Referenced by action_getvar(), handle_getvariable(), and pbx_substitute_variables_helper_full().
01545 { 01546 char *args = func_args(function); 01547 struct ast_custom_function *acfptr = ast_custom_function_find(function); 01548 01549 if (acfptr == NULL) 01550 ast_log(LOG_ERROR, "Function %s not registered\n", function); 01551 else if (!acfptr->read) 01552 ast_log(LOG_ERROR, "Function %s cannot be read\n", function); 01553 else 01554 return acfptr->read(chan, function, args, workspace, len); 01555 return -1; 01556 }
int ast_func_write | ( | struct ast_channel * | chan, | |
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 |
Definition at line 1558 of file pbx.c.
References ast_custom_function_find(), ast_log(), func_args(), LOG_ERROR, and ast_custom_function::write.
Referenced by pbx_builtin_pushvar_helper(), and pbx_builtin_setvar_helper().
01559 { 01560 char *args = func_args(function); 01561 struct ast_custom_function *acfptr = ast_custom_function_find(function); 01562 01563 if (acfptr == NULL) 01564 ast_log(LOG_ERROR, "Function %s not registered\n", function); 01565 else if (!acfptr->write) 01566 ast_log(LOG_ERROR, "Function %s cannot be written to\n", function); 01567 else 01568 return acfptr->write(chan, function, args, value); 01569 01570 return -1; 01571 }
const char* ast_get_context_name | ( | struct ast_context * | con | ) |
Definition at line 6199 of file pbx.c.
Referenced by _macro_exec(), ast_context_add_include2(), ast_context_add_switch2(), ast_context_lockmacro(), ast_context_unlockmacro(), ast_context_verify_includes(), complete_context_add_extension(), complete_context_add_extension_deprecated(), complete_context_add_ignorepat(), complete_context_add_ignorepat_deprecated(), complete_context_add_include(), complete_context_add_include_deprecated(), complete_context_dont_include_deprecated(), complete_context_remove_extension(), complete_context_remove_extension_deprecated(), complete_context_remove_ignorepat(), complete_context_remove_ignorepat_deprecated(), complete_context_remove_include(), complete_show_dialplan_context(), dundi_precache_full(), find_context_locked(), find_matching_endwhile(), find_matching_priority(), handle_save_dialplan(), handle_show_hints(), and show_dialplan_helper().
const char* ast_get_context_registrar | ( | struct ast_context * | c | ) |
Definition at line 6237 of file pbx.c.
References ast_context::registrar.
Referenced by handle_save_dialplan(), and show_dialplan_helper().
06238 { 06239 return c ? c->registrar : NULL; 06240 }
const char* ast_get_extension_app | ( | struct ast_exten * | e | ) |
Definition at line 6267 of file pbx.c.
References ast_exten::app.
Referenced by _macro_exec(), ast_add_hint(), ast_extension_state2(), ast_get_hint(), ast_hint_state_changed(), find_matching_endwhile(), handle_save_dialplan(), handle_show_hints(), and print_ext().
06268 { 06269 return e ? e->app : NULL; 06270 }
void* ast_get_extension_app_data | ( | struct ast_exten * | e | ) |
Definition at line 6272 of file pbx.c.
References ast_exten::data.
Referenced by _macro_exec(), ast_get_hint(), handle_save_dialplan(), and print_ext().
06273 { 06274 return e ? e->data : NULL; 06275 }
const char* ast_get_extension_cidmatch | ( | struct ast_exten * | e | ) |
Definition at line 6262 of file pbx.c.
References ast_exten::cidmatch.
Referenced by find_matching_priority(), and handle_save_dialplan().
06263 { 06264 return e ? e->cidmatch : NULL; 06265 }
struct ast_context* ast_get_extension_context | ( | struct ast_exten * | exten | ) |
const char* ast_get_extension_label | ( | struct ast_exten * | exten | ) |
Definition at line 6214 of file pbx.c.
References exten.
Referenced by handle_save_dialplan(), and show_dialplan_helper().
int ast_get_extension_matchcid | ( | struct ast_exten * | e | ) |
Definition at line 6257 of file pbx.c.
References ast_exten::matchcid.
Referenced by find_matching_priority(), and handle_save_dialplan().
06258 { 06259 return e ? e->matchcid : 0; 06260 }
const char* ast_get_extension_name | ( | struct ast_exten * | exten | ) |
Definition at line 6209 of file pbx.c.
References exten.
Referenced by ast_add_hint(), complete_context_remove_extension(), complete_context_remove_extension_deprecated(), dundi_precache_full(), find_matching_priority(), handle_save_dialplan(), handle_show_hints(), and show_dialplan_helper().
int ast_get_extension_priority | ( | struct ast_exten * | exten | ) |
Definition at line 6229 of file pbx.c.
References exten.
Referenced by complete_context_remove_extension(), complete_context_remove_extension_deprecated(), find_matching_priority(), handle_save_dialplan(), and print_ext().
const char* ast_get_extension_registrar | ( | struct ast_exten * | e | ) |
Definition at line 6242 of file pbx.c.
References ast_exten::registrar.
Referenced by handle_save_dialplan(), and show_dialplan_helper().
06243 { 06244 return e ? e->registrar : NULL; 06245 }
int ast_get_hint | ( | char * | hint, | |
int | maxlen, | |||
char * | name, | |||
int | maxnamelen, | |||
struct ast_channel * | c, | |||
const char * | context, | |||
const char * | exten | |||
) |
If an extension exists, return non-zero.
hint | buffer for hint | |
maxlen | size of hint buffer | |
name | buffer for name portion of hint | |
maxnamelen | size of name buffer | |
c | this is not important | |
context | which context to look in | |
exten | which extension to search for |
Definition at line 2273 of file pbx.c.
References ast_get_extension_app(), ast_get_extension_app_data(), and ast_hint_extension().
Referenced by action_extensionstate(), get_cid_name(), get_destination(), manager_state_cb(), pbx_retrieve_variable(), and transmit_state_notify().
02274 { 02275 struct ast_exten *e = ast_hint_extension(c, context, exten); 02276 02277 if (e) { 02278 if (hint) 02279 ast_copy_string(hint, ast_get_extension_app(e), hintsize); 02280 if (name) { 02281 const char *tmp = ast_get_extension_app_data(e); 02282 if (tmp) 02283 ast_copy_string(name, tmp, namesize); 02284 } 02285 return -1; 02286 } 02287 return 0; 02288 }
const char* ast_get_ignorepat_name | ( | struct ast_ignorepat * | ip | ) |
Definition at line 6224 of file pbx.c.
References ast_ignorepat::pattern.
Referenced by complete_context_remove_ignorepat(), complete_context_remove_ignorepat_deprecated(), handle_save_dialplan(), lookup_c_ip(), and show_dialplan_helper().
06225 { 06226 return ip ? ip->pattern : NULL; 06227 }
const char* ast_get_ignorepat_registrar | ( | struct ast_ignorepat * | ip | ) |
Definition at line 6252 of file pbx.c.
References ast_ignorepat::registrar.
Referenced by handle_save_dialplan(), and show_dialplan_helper().
06253 { 06254 return ip ? ip->registrar : NULL; 06255 }
const char* ast_get_include_name | ( | struct ast_include * | inc | ) |
Definition at line 6219 of file pbx.c.
References ast_include::name.
Referenced by complete_context_dont_include_deprecated(), complete_context_remove_include(), find_matching_priority(), handle_save_dialplan(), lookup_ci(), and show_dialplan_helper().
06220 { 06221 return inc ? inc->name : NULL; 06222 }
const char* ast_get_include_registrar | ( | struct ast_include * | i | ) |
Definition at line 6247 of file pbx.c.
References ast_include::registrar.
Referenced by handle_save_dialplan(), and show_dialplan_helper().
06248 { 06249 return i ? i->registrar : NULL; 06250 }
const char* ast_get_switch_data | ( | struct ast_sw * | sw | ) |
Definition at line 6282 of file pbx.c.
References ast_sw::data.
Referenced by handle_save_dialplan(), and show_dialplan_helper().
06283 { 06284 return sw ? sw->data : NULL; 06285 }
const char* ast_get_switch_name | ( | struct ast_sw * | sw | ) |
Definition at line 6277 of file pbx.c.
References ast_sw::name.
Referenced by handle_save_dialplan(), and show_dialplan_helper().
06278 { 06279 return sw ? sw->name : NULL; 06280 }
const char* ast_get_switch_registrar | ( | struct ast_sw * | sw | ) |
Definition at line 6287 of file pbx.c.
References ast_sw::registrar.
Referenced by handle_save_dialplan(), and show_dialplan_helper().
06288 { 06289 return sw ? sw->registrar : NULL; 06290 }
int ast_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 6380 of file pbx.c.
References __ast_goto_if_exists().
Referenced by aqm_exec(), background_detect_exec(), chanavail_exec(), conf_run(), controlplayback_exec(), do_directory(), hasvoicemail_exec(), leave_voicemail(), lookupblacklist_exec(), onedigit_goto(), ospauth_exec(), ospfinished_exec(), osplookup_exec(), ospnext_exec(), play_mailbox_owner(), playback_exec(), pqm_exec(), privacy_exec(), rqm_exec(), sendimage_exec(), sendtext_exec(), sendurl_exec(), system_exec_helper(), transfer_exec(), upqm_exec(), valid_exit(), vm_box_exists(), vm_exec(), and wait_for_answer().
06381 { 06382 return __ast_goto_if_exists(chan, context, exten, priority, 0); 06383 }
static struct ast_exten* ast_hint_extension | ( | struct ast_channel * | c, | |
const char * | context, | |||
const char * | exten | |||
) | [static] |
ast_hint_extension: Find hint for given extension in context
Definition at line 1904 of file pbx.c.
References ast_rdlock_contexts(), ast_unlock_contexts(), E_MATCH, pbx_find_extension(), PRIORITY_HINT, and pbx_find_info::stacklen.
Referenced by ast_extension_state(), and ast_get_hint().
01905 { 01906 struct ast_exten *e; 01907 struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */ 01908 01909 ast_rdlock_contexts(); 01910 e = pbx_find_extension(c, NULL, &q, context, exten, PRIORITY_HINT, NULL, "", E_MATCH); 01911 ast_unlock_contexts(); 01912 01913 return e; 01914 }
void ast_hint_state_changed | ( | const char * | device, | |
char * | cid_num, | |||
char * | cid_name | |||
) |
Definition at line 2025 of file pbx.c.
References ast_extension_state2(), ast_get_extension_app(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, AST_MAX_EXTENSION, ast_state_cb::callback, ast_hint::callbacks, ast_state_cb::data, ast_hint::exten, ast_exten::exten, ast_hint::laststate, ast_state_cb::next, ast_exten::parent, parse(), statecbs, and strsep().
Referenced by do_state_change().
02026 { 02027 struct ast_hint *hint; 02028 02029 AST_LIST_LOCK(&hints); 02030 02031 AST_LIST_TRAVERSE(&hints, hint, list) { 02032 struct ast_state_cb *cblist; 02033 char buf[AST_MAX_EXTENSION]; 02034 char *parse = buf; 02035 char *cur; 02036 int state; 02037 02038 ast_copy_string(buf, ast_get_extension_app(hint->exten), sizeof(buf)); 02039 while ( (cur = strsep(&parse, "&")) ) { 02040 if (!strcasecmp(cur, device)) 02041 break; 02042 } 02043 if (!cur) 02044 continue; 02045 02046 /* Get device state for this hint */ 02047 state = ast_extension_state2(hint->exten); 02048 02049 if ((state == -1) || (state == hint->laststate)) 02050 continue; 02051 02052 /* Device state changed since last check - notify the watchers */ 02053 02054 /* For general callbacks */ 02055 for (cblist = statecbs; cblist; cblist = cblist->next) 02056 cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data, cid_num, cid_name); 02057 02058 /* For extension callbacks */ 02059 for (cblist = hint->callbacks; cblist; cblist = cblist->next) 02060 cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data, cid_num, cid_name); 02061 02062 hint->laststate = state; /* record we saw the change */ 02063 } 02064 02065 AST_LIST_UNLOCK(&hints); 02066 }
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 4541 of file pbx.c.
References ast_context_find(), ast_extension_match(), ast_context::ignorepats, ast_ignorepat::next, and ast_ignorepat::pattern.
Referenced by ast_app_dtget(), disa_exec(), dp_lookup(), dundi_lookup_local(), handle_enbloc_call_message(), handle_soft_key_event_message(), handle_stimulus_message(), mgcp_ss(), skinny_ss(), and ss_thread().
04542 { 04543 struct ast_context *con = ast_context_find(context); 04544 if (con) { 04545 struct ast_ignorepat *pat; 04546 for (pat = con->ignorepats; pat; pat = pat->next) { 04547 if (ast_extension_match(pat->pattern, pattern)) 04548 return 1; 04549 } 04550 } 04551 04552 return 0; 04553 }
AST_LIST_HEAD | ( | store_hints | , | |
store_hint | ||||
) |
static AST_LIST_HEAD_STATIC | ( | hints | , | |
ast_hint | ||||
) | [static] |
static AST_LIST_HEAD_STATIC | ( | switches | , | |
ast_switch | ||||
) | [static] |
static AST_LIST_HEAD_STATIC | ( | apps | , | |
ast_app | ||||
) | [static] |
static AST_LIST_HEAD_STATIC | ( | acf_root | , | |
ast_custom_function | ||||
) | [static] |
int ast_lock_context | ( | struct ast_context * | con | ) |
Locks a given context.
con | context to lock |
0 | on success | |
-1 | on failure |
Definition at line 6186 of file pbx.c.
References ast_mutex_lock(), and ast_context::lock.
Referenced by _macro_exec(), complete_context_dont_include_deprecated(), complete_context_remove_ignorepat(), complete_context_remove_ignorepat_deprecated(), complete_context_remove_include(), dundi_precache_full(), find_matching_endwhile(), handle_save_dialplan(), lookup_c_ip(), lookup_ci(), and show_dialplan_helper().
06187 { 06188 return ast_mutex_lock(&con->lock); 06189 }
int ast_lock_contexts | ( | void | ) |
Locks the context list.
0 | on success | |
-1 | on error |
Definition at line 6163 of file pbx.c.
References ast_rwlock_wrlock().
Referenced by find_matching_endwhile().
06164 { 06165 return ast_rwlock_wrlock(&conlock); 06166 }
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 2310 of file pbx.c.
References E_MATCHMORE, and pbx_extension_helper().
Referenced by ast_app_dtget(), collect_digits(), disa_exec(), dp_lookup(), dundi_lookup_local(), handle_stimulus_message(), loopback_matchmore(), mgcp_ss(), skinny_ss(), and ss_thread().
02311 { 02312 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE); 02313 }
void ast_merge_contexts_and_delete | ( | struct ast_context ** | extcontexts, | |
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 pointer | |
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 3942 of file pbx.c.
References __ast_context_destroy(), ast_calloc, AST_EXTENSION_REMOVED, AST_LIST_HEAD_INIT_VALUE, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_unlock_contexts(), ast_wrlock_contexts(), ast_state_cb::callback, ast_hint::callbacks, store_hint::callbacks, store_hint::context, contexts, ast_state_cb::data, E_MATCH, store_hint::exten, ast_hint::exten, ast_exten::exten, free, store_hint::laststate, ast_hint::laststate, LOG_WARNING, ast_context::next, ast_state_cb::next, ast_exten::parent, pbx_find_extension(), PRIORITY_HINT, ast_context::registrar, and pbx_find_info::stacklen.
Referenced by pbx_load_module().
03943 { 03944 struct ast_context *tmp, *lasttmp = NULL; 03945 struct store_hints store = AST_LIST_HEAD_INIT_VALUE; 03946 struct store_hint *this; 03947 struct ast_hint *hint; 03948 struct ast_exten *exten; 03949 int length; 03950 struct ast_state_cb *thiscb, *prevcb; 03951 03952 /* it is very important that this function hold the hint list lock _and_ the conlock 03953 during its operation; not only do we need to ensure that the list of contexts 03954 and extensions does not change, but also that no hint callbacks (watchers) are 03955 added or removed during the merge/delete process 03956 03957 in addition, the locks _must_ be taken in this order, because there are already 03958 other code paths that use this order 03959 */ 03960 ast_wrlock_contexts(); 03961 AST_LIST_LOCK(&hints); 03962 03963 /* preserve all watchers for hints associated with this registrar */ 03964 AST_LIST_TRAVERSE(&hints, hint, list) { 03965 if (hint->callbacks && !strcmp(registrar, hint->exten->parent->registrar)) { 03966 length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2 + sizeof(*this); 03967 if (!(this = ast_calloc(1, length))) 03968 continue; 03969 this->callbacks = hint->callbacks; 03970 hint->callbacks = NULL; 03971 this->laststate = hint->laststate; 03972 this->context = this->data; 03973 strcpy(this->data, hint->exten->parent->name); 03974 this->exten = this->data + strlen(this->context) + 1; 03975 strcpy(this->exten, hint->exten->exten); 03976 AST_LIST_INSERT_HEAD(&store, this, list); 03977 } 03978 } 03979 03980 tmp = *extcontexts; 03981 if (registrar) { 03982 /* XXX remove previous contexts from same registrar */ 03983 if (option_debug) 03984 ast_log(LOG_DEBUG, "must remove any reg %s\n", registrar); 03985 __ast_context_destroy(NULL,registrar); 03986 while (tmp) { 03987 lasttmp = tmp; 03988 tmp = tmp->next; 03989 } 03990 } else { 03991 /* XXX remove contexts with the same name */ 03992 while (tmp) { 03993 ast_log(LOG_WARNING, "must remove %s reg %s\n", tmp->name, tmp->registrar); 03994 __ast_context_destroy(tmp,tmp->registrar); 03995 lasttmp = tmp; 03996 tmp = tmp->next; 03997 } 03998 } 03999 if (lasttmp) { 04000 lasttmp->next = contexts; 04001 contexts = *extcontexts; 04002 *extcontexts = NULL; 04003 } else 04004 ast_log(LOG_WARNING, "Requested contexts didn't get merged\n"); 04005 04006 /* restore the watchers for hints that can be found; notify those that 04007 cannot be restored 04008 */ 04009 while ((this = AST_LIST_REMOVE_HEAD(&store, list))) { 04010 struct pbx_find_info q = { .stacklen = 0 }; 04011 exten = pbx_find_extension(NULL, NULL, &q, this->context, this->exten, PRIORITY_HINT, NULL, "", E_MATCH); 04012 /* Find the hint in the list of hints */ 04013 AST_LIST_TRAVERSE(&hints, hint, list) { 04014 if (hint->exten == exten) 04015 break; 04016 } 04017 if (!exten || !hint) { 04018 /* this hint has been removed, notify the watchers */ 04019 prevcb = NULL; 04020 thiscb = this->callbacks; 04021 while (thiscb) { 04022 prevcb = thiscb; 04023 thiscb = thiscb->next; 04024 prevcb->callback(this->context, this->exten, AST_EXTENSION_REMOVED, prevcb->data, NULL, NULL); 04025 free(prevcb); 04026 } 04027 } else { 04028 thiscb = this->callbacks; 04029 while (thiscb->next) 04030 thiscb = thiscb->next; 04031 thiscb->next = hint->callbacks; 04032 hint->callbacks = this->callbacks; 04033 hint->laststate = this->laststate; 04034 } 04035 free(this); 04036 } 04037 04038 AST_LIST_UNLOCK(&hints); 04039 ast_unlock_contexts(); 04040 04041 return; 04042 }
AST_MUTEX_DEFINE_STATIC | ( | maxcalllock | ) |
AST_MUTEX_DEFINE_STATIC | ( | globalslock | ) |
int ast_parseable_goto | ( | struct ast_channel * | chan, | |
const char * | goto_string | |||
) |
This function will handle locking the channel as needed.
Definition at line 6390 of file pbx.c.
References ast_cdr_update(), ast_explicit_goto(), ast_findlabel_extension(), ast_log(), ast_strdupa, ast_strlen_zero(), ast_channel::cid, ast_callerid::cid_num, ast_channel::context, exten, ast_channel::exten, LOG_WARNING, ast_channel::priority, and strsep().
Referenced by _while_exec(), check_goto_on_transfer(), gosub_exec(), ivr_dispatch(), pbx_builtin_goto(), random_exec(), return_exec(), and while_continue_exec().
06391 { 06392 char *exten, *pri, *context; 06393 char *stringp; 06394 int ipri; 06395 int mode = 0; 06396 06397 if (ast_strlen_zero(goto_string)) { 06398 ast_log(LOG_WARNING, "Goto requires an argument (optional context|optional extension|priority)\n"); 06399 return -1; 06400 } 06401 stringp = ast_strdupa(goto_string); 06402 context = strsep(&stringp, "|"); /* guaranteed non-null */ 06403 exten = strsep(&stringp, "|"); 06404 pri = strsep(&stringp, "|"); 06405 if (!exten) { /* Only a priority in this one */ 06406 pri = context; 06407 exten = NULL; 06408 context = NULL; 06409 } else if (!pri) { /* Only an extension and priority in this one */ 06410 pri = exten; 06411 exten = context; 06412 context = NULL; 06413 } 06414 if (*pri == '+') { 06415 mode = 1; 06416 pri++; 06417 } else if (*pri == '-') { 06418 mode = -1; 06419 pri++; 06420 } 06421 if (sscanf(pri, "%d", &ipri) != 1) { 06422 if ((ipri = ast_findlabel_extension(chan, context ? context : chan->context, exten ? exten : chan->exten, 06423 pri, chan->cid.cid_num)) < 1) { 06424 ast_log(LOG_WARNING, "Priority '%s' must be a number > 0, or valid label\n", pri); 06425 return -1; 06426 } else 06427 mode = 0; 06428 } 06429 /* At this point we have a priority and maybe an extension and a context */ 06430 06431 if (mode) 06432 ipri = chan->priority + (ipri * mode); 06433 06434 ast_explicit_goto(chan, context, exten, ipri); 06435 ast_cdr_update(chan); 06436 return 0; 06437 06438 }
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 5306 of file pbx.c.
References ast_pbx_outgoing_app_uniqueid().
Referenced by attempt_thread(), and orig_app().
05307 { 05308 return ast_pbx_outgoing_app_uniqueid(type, format, data, timeout, app, appdata, reason, sync, 0, cid_num, cid_name, vars, account, locked_channel, NULL); 05309 }
int ast_pbx_outgoing_app_uniqueid | ( | const char * | type, | |
int | format, | |||
void * | data, | |||
int | timeout, | |||
const char * | app, | |||
const char * | appdata, | |||
int * | reason, | |||
int | sync, | |||
int | callingpres, | |||
const char * | cid_num, | |||
const char * | cid_name, | |||
struct ast_variable * | vars, | |||
const char * | account, | |||
struct ast_channel ** | locked_channel, | |||
char * | uniqueid | |||
) |
Synchronously or asynchronously make an outbound call and send it to a particular application with given extension (extended version with callinpres and uniqueid)
Definition at line 5165 of file pbx.c.
References __ast_request_and_dial_uniqueid(), ast_calloc, ast_cdr_alloc(), ast_cdr_disposition(), ast_cdr_failed(), ast_cdr_init(), ast_cdr_setaccount(), ast_cdr_start(), ast_channel_lock, ast_channel_unlock, ast_hangup(), ast_log(), ast_pbx_outgoing_cdr_failed(), ast_pbx_run_app(), ast_pthread_create, ast_set_variables(), AST_STATE_UP, ast_strlen_zero(), ast_variables_destroy(), ast_verbose(), async_wait(), ast_channel::cdr, async_stat::chan, errno, free, LOG_WARNING, option_verbose, ast_channel::pbx, outgoing_helper::vars, and VERBOSE_PREFIX_4.
Referenced by action_originate(), ast_pbx_outgoing_app(), and fast_originate().
05166 { 05167 struct ast_channel *chan; 05168 struct app_tmp *tmp; 05169 int res = -1, cdr_res = -1; 05170 struct outgoing_helper oh; 05171 pthread_attr_t attr; 05172 05173 memset(&oh, 0, sizeof(oh)); 05174 oh.vars = vars; 05175 oh.account = account; 05176 05177 if (locked_channel) 05178 *locked_channel = NULL; 05179 if (ast_strlen_zero(app)) { 05180 res = -1; 05181 goto outgoing_app_cleanup; 05182 } 05183 if (sync) { 05184 chan = __ast_request_and_dial_uniqueid(type, format, data, timeout, reason, callingpres, cid_num, cid_name, &oh, uniqueid); 05185 if (chan) { 05186 if (!chan->cdr) { /* check if the channel already has a cdr record, if not give it one */ 05187 chan->cdr = ast_cdr_alloc(); /* allocate a cdr for the channel */ 05188 if(!chan->cdr) { 05189 /* allocation of the cdr failed */ 05190 free(chan->pbx); 05191 res = -1; 05192 goto outgoing_app_cleanup; 05193 } 05194 /* allocation of the cdr was successful */ 05195 ast_cdr_init(chan->cdr, chan); /* initilize our channel's cdr */ 05196 ast_cdr_start(chan->cdr); 05197 } 05198 ast_set_variables(chan, vars); 05199 if (account) 05200 ast_cdr_setaccount(chan, account); 05201 if (chan->_state == AST_STATE_UP) { 05202 res = 0; 05203 if (option_verbose > 3) 05204 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", chan->name); 05205 tmp = ast_calloc(1, sizeof(*tmp)); 05206 if (!tmp) 05207 res = -1; 05208 else { 05209 ast_copy_string(tmp->app, app, sizeof(tmp->app)); 05210 if (appdata) 05211 ast_copy_string(tmp->data, appdata, sizeof(tmp->data)); 05212 tmp->chan = chan; 05213 if (sync > 1) { 05214 if (locked_channel) 05215 ast_channel_unlock(chan); 05216 ast_pbx_run_app(tmp); 05217 } else { 05218 pthread_attr_init(&attr); 05219 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 05220 if (locked_channel) 05221 ast_channel_lock(chan); 05222 if (ast_pthread_create(&tmp->t, &attr, ast_pbx_run_app, tmp)) { 05223 ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno)); 05224 free(tmp); 05225 if (locked_channel) 05226 ast_channel_unlock(chan); 05227 ast_hangup(chan); 05228 res = -1; 05229 } else { 05230 if (locked_channel) 05231 *locked_channel = chan; 05232 } 05233 pthread_attr_destroy(&attr); 05234 } 05235 } 05236 } else { 05237 if (option_verbose > 3) 05238 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", chan->name); 05239 if (chan->cdr) { /* update the cdr */ 05240 /* here we update the status of the call, which sould be busy. 05241 * if that fails then we set the status to failed */ 05242 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 05243 ast_cdr_failed(chan->cdr); 05244 } 05245 ast_hangup(chan); 05246 } 05247 } 05248 05249 if (res < 0) { /* the call failed for some reason */ 05250 if (*reason == 0) { /* if the call failed (not busy or no answer) 05251 * update the cdr with the failed message */ 05252 cdr_res = ast_pbx_outgoing_cdr_failed(); 05253 if (cdr_res != 0) { 05254 res = cdr_res; 05255 goto outgoing_app_cleanup; 05256 } 05257 } 05258 } 05259 05260 } else { 05261 struct async_stat *as; 05262 if (!(as = ast_calloc(1, sizeof(*as)))) { 05263 res = -1; 05264 goto outgoing_app_cleanup; 05265 } 05266 chan = __ast_request_and_dial_uniqueid(type, format, data, timeout, reason, callingpres, cid_num, cid_name, &oh, uniqueid); 05267 if (!chan) { 05268 free(as); 05269 res = -1; 05270 goto outgoing_app_cleanup; 05271 } 05272 as->chan = chan; 05273 ast_copy_string(as->app, app, sizeof(as->app)); 05274 if (appdata) 05275 ast_copy_string(as->appdata, appdata, sizeof(as->appdata)); 05276 as->timeout = timeout; 05277 ast_set_variables(chan, vars); 05278 if (account) 05279 ast_cdr_setaccount(chan, account); 05280 /* Start a new thread, and get something handling this channel. */ 05281 pthread_attr_init(&attr); 05282 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 05283 if (locked_channel) 05284 ast_channel_lock(chan); 05285 if (ast_pthread_create(&as->p, &attr, async_wait, as)) { 05286 ast_log(LOG_WARNING, "Failed to start async wait\n"); 05287 free(as); 05288 if (locked_channel) 05289 ast_channel_unlock(chan); 05290 ast_hangup(chan); 05291 res = -1; 05292 pthread_attr_destroy(&attr); 05293 goto outgoing_app_cleanup; 05294 } else { 05295 if (locked_channel) 05296 *locked_channel = chan; 05297 } 05298 pthread_attr_destroy(&attr); 05299 res = 0; 05300 } 05301 outgoing_app_cleanup: 05302 ast_variables_destroy(vars); 05303 return res; 05304 }
static int ast_pbx_outgoing_cdr_failed | ( | void | ) | [static] |
Function to post an empty cdr after a spool call fails.
This function posts an empty cdr for a failed spool call
Definition at line 4970 of file pbx.c.
References ast_cdr_detach(), ast_cdr_end(), ast_cdr_failed(), ast_cdr_init(), ast_cdr_start(), ast_channel_alloc(), ast_channel_free(), AST_STATE_DOWN, and ast_channel::cdr.
Referenced by ast_pbx_outgoing_app_uniqueid(), and ast_pbx_outgoing_exten_uniqueid().
04971 { 04972 /* allocate a channel */ 04973 struct ast_channel *chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, 0); 04974 04975 if (!chan) 04976 return -1; /* failure */ 04977 04978 if (!chan->cdr) { 04979 /* allocation of the cdr failed */ 04980 ast_channel_free(chan); /* free the channel */ 04981 return -1; /* return failure */ 04982 } 04983 04984 /* allocation of the cdr was successful */ 04985 ast_cdr_init(chan->cdr, chan); /* initilize our channel's cdr */ 04986 ast_cdr_start(chan->cdr); /* record the start and stop time */ 04987 ast_cdr_end(chan->cdr); 04988 ast_cdr_failed(chan->cdr); /* set the status to failed */ 04989 ast_cdr_detach(chan->cdr); /* post and free the record */ 04990 ast_channel_free(chan); /* free the channel */ 04991 04992 return 0; /* success */ 04993 }
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 5137 of file pbx.c.
References ast_pbx_outgoing_exten_uniqueid(), and outgoing_helper::vars.
Referenced by attempt_thread(), and orig_exten().
05138 { 05139 return ast_pbx_outgoing_exten_uniqueid(type, format, data, timeout, context, exten, priority, reason, sync, 0, cid_num, cid_name, vars, account, channel, NULL); 05140 }
int ast_pbx_outgoing_exten_uniqueid | ( | const char * | type, | |
int | format, | |||
void * | data, | |||
int | timeout, | |||
const char * | context, | |||
const char * | exten, | |||
int | priority, | |||
int * | reason, | |||
int | sync, | |||
int | callingpres, | |||
const char * | cid_num, | |||
const char * | cid_name, | |||
struct ast_variable * | vars, | |||
const char * | account, | |||
struct ast_channel ** | locked_channel, | |||
char * | uniqueid | |||
) |
Synchronously or asynchronously make an outbound call and send it to a particular extension (extended version with callinpres and uniqueid)
Definition at line 4995 of file pbx.c.
References __ast_request_and_dial_uniqueid(), ast_channel::_state, ast_calloc, ast_cdr_disposition(), ast_cdr_failed(), ast_cdr_setaccount(), ast_channel_alloc(), ast_channel_lock, ast_channel_unlock, ast_exists_extension(), ast_hangup(), ast_log(), ast_pbx_outgoing_cdr_failed(), ast_pbx_run(), ast_pbx_start(), ast_pthread_create, ast_request_and_dial_uniqueid(), ast_set_variables(), AST_STATE_DOWN, AST_STATE_UP, ast_strlen_zero(), ast_variables_destroy(), ast_verbose(), async_wait(), ast_channel::cdr, ast_channel::context, free, ast_channel::hangupcause, LOAD_OH, LOG_ERROR, LOG_WARNING, option_verbose, pbx_builtin_setvar_helper(), set_ext_pri(), outgoing_helper::vars, and VERBOSE_PREFIX_4.
Referenced by action_originate(), ast_pbx_outgoing_exten(), and fast_originate().
04996 { 04997 struct ast_channel *chan; 04998 struct async_stat *as; 04999 int res = -1, cdr_res = -1; 05000 struct outgoing_helper oh; 05001 pthread_attr_t attr; 05002 05003 if (sync) { 05004 LOAD_OH(oh); 05005 chan = __ast_request_and_dial_uniqueid(type, format, data, timeout, reason, callingpres, cid_num, cid_name, &oh, uniqueid); 05006 if (channel) { 05007 *channel = chan; 05008 if (chan) 05009 ast_channel_lock(chan); 05010 } 05011 if (chan) { 05012 if (chan->_state == AST_STATE_UP) { 05013 res = 0; 05014 if (option_verbose > 3) 05015 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", chan->name); 05016 05017 if (sync > 1) { 05018 if (channel) 05019 ast_channel_unlock(chan); 05020 if (ast_pbx_run(chan)) { 05021 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 05022 if (channel) 05023 *channel = NULL; 05024 ast_hangup(chan); 05025 chan = NULL; 05026 res = -1; 05027 } 05028 } else { 05029 if (ast_pbx_start(chan)) { 05030 ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name); 05031 if (channel) { 05032 *channel = NULL; 05033 ast_channel_unlock(chan); 05034 } 05035 ast_hangup(chan); 05036 res = -1; 05037 } 05038 chan = NULL; 05039 } 05040 } else { 05041 if (option_verbose > 3) 05042 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", chan->name); 05043 05044 if (chan->cdr) { /* update the cdr */ 05045 /* here we update the status of the call, which sould be busy. 05046 * if that fails then we set the status to failed */ 05047 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 05048 ast_cdr_failed(chan->cdr); 05049 } 05050 05051 if (channel) { 05052 *channel = NULL; 05053 ast_channel_unlock(chan); 05054 } 05055 ast_hangup(chan); 05056 chan = NULL; 05057 } 05058 } 05059 05060 if (res < 0) { /* the call failed for some reason */ 05061 if (*reason == 0) { /* if the call failed (not busy or no answer) 05062 * update the cdr with the failed message */ 05063 cdr_res = ast_pbx_outgoing_cdr_failed(); 05064 if (cdr_res != 0) { 05065 res = cdr_res; 05066 goto outgoing_exten_cleanup; 05067 } 05068 } 05069 05070 /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */ 05071 /* check if "failed" exists */ 05072 if (ast_exists_extension(chan, context, "failed", 1, NULL)) { 05073 chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "OutgoingSpoolFailed"); 05074 if (chan) { 05075 char failed_reason[4] = ""; 05076 if (!ast_strlen_zero(context)) 05077 ast_copy_string(chan->context, context, sizeof(chan->context)); 05078 set_ext_pri(chan, "failed", 1); 05079 ast_set_variables(chan, vars); 05080 snprintf(failed_reason, sizeof(failed_reason), "%d", *reason); 05081 pbx_builtin_setvar_helper(chan, "REASON", failed_reason); 05082 if (account) 05083 ast_cdr_setaccount(chan, account); 05084 if (ast_pbx_run(chan)) { 05085 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 05086 ast_hangup(chan); 05087 } 05088 chan = NULL; 05089 } 05090 } 05091 } 05092 } else { 05093 if (!(as = ast_calloc(1, sizeof(*as)))) { 05094 res = -1; 05095 goto outgoing_exten_cleanup; 05096 } 05097 chan = ast_request_and_dial_uniqueid(type, format, data, timeout, reason, callingpres, cid_num, cid_name, uniqueid); 05098 if (channel) { 05099 *channel = chan; 05100 if (chan) 05101 ast_channel_lock(chan); 05102 } 05103 if (!chan) { 05104 free(as); 05105 res = -1; 05106 goto outgoing_exten_cleanup; 05107 } 05108 as->chan = chan; 05109 ast_copy_string(as->context, context, sizeof(as->context)); 05110 set_ext_pri(as->chan, exten, priority); 05111 as->timeout = timeout; 05112 ast_set_variables(chan, vars); 05113 if (account) 05114 ast_cdr_setaccount(chan, account); 05115 pthread_attr_init(&attr); 05116 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 05117 if (ast_pthread_create(&as->p, &attr, async_wait, as)) { 05118 ast_log(LOG_WARNING, "Failed to start async wait\n"); 05119 free(as); 05120 if (channel) { 05121 *channel = NULL; 05122 ast_channel_unlock(chan); 05123 } 05124 ast_hangup(chan); 05125 res = -1; 05126 pthread_attr_destroy(&attr); 05127 goto outgoing_exten_cleanup; 05128 } 05129 pthread_attr_destroy(&attr); 05130 res = 0; 05131 } 05132 outgoing_exten_cleanup: 05133 ast_variables_destroy(vars); 05134 return res; 05135 }
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 |
Definition at line 2670 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_outgoing_exten_uniqueid(), async_wait(), mgcp_ss(), skinny_newcall(), and ss_thread().
02671 { 02672 enum ast_pbx_result res = AST_PBX_SUCCESS; 02673 02674 if (increase_call_count(c)) 02675 return AST_PBX_CALL_LIMIT; 02676 02677 res = __ast_pbx_run(c); 02678 decrease_call_count(); 02679 02680 return res; 02681 }
static void* ast_pbx_run_app | ( | void * | data | ) | [static] |
run the application and free the descriptor once done
Definition at line 5149 of file pbx.c.
References app_tmp::app, app, ast_hangup(), ast_log(), ast_verbose(), app_tmp::chan, app_tmp::data, free, LOG_WARNING, option_verbose, pbx_exec(), pbx_findapp(), and VERBOSE_PREFIX_4.
Referenced by ast_pbx_outgoing_app_uniqueid().
05150 { 05151 struct app_tmp *tmp = data; 05152 struct ast_app *app; 05153 app = pbx_findapp(tmp->app); 05154 if (app) { 05155 if (option_verbose > 3) 05156 ast_verbose(VERBOSE_PREFIX_4 "Launching %s(%s) on %s\n", tmp->app, tmp->data, tmp->chan->name); 05157 pbx_exec(tmp->chan, app, tmp->data); 05158 } else 05159 ast_log(LOG_WARNING, "No such application '%s'\n", tmp->app); 05160 ast_hangup(tmp->chan); 05161 free(tmp); 05162 return NULL; 05163 }
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 |
Definition at line 2644 of file pbx.c.
References ast_log(), AST_PBX_CALL_LIMIT, AST_PBX_FAILED, AST_PBX_SUCCESS, ast_pthread_create, increase_call_count(), LOG_WARNING, pbx_thread(), and t.
Referenced by __oh323_new(), alsa_new(), ast_async_goto(), ast_bridge_call_thread(), ast_iax2_new(), ast_pbx_outgoing_exten_uniqueid(), bridge_exec(), check_goto_on_transfer(), do_parking_thread(), gtalk_new(), gtalk_newcall(), handle_request_invite(), local_call(), mgcp_new(), nbs_new(), oss_new(), pbx_start_chan(), phone_new(), rpt_call(), sip_new(), skinny_new(), and zt_new().
02645 { 02646 pthread_t t; 02647 pthread_attr_t attr; 02648 02649 if (!c) { 02650 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n"); 02651 return AST_PBX_FAILED; 02652 } 02653 02654 if (increase_call_count(c)) 02655 return AST_PBX_CALL_LIMIT; 02656 02657 /* Start a new thread, and get something handling this channel. */ 02658 pthread_attr_init(&attr); 02659 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 02660 if (ast_pthread_create(&t, &attr, pbx_thread, c)) { 02661 ast_log(LOG_WARNING, "Failed to create new channel thread\n"); 02662 pthread_attr_destroy(&attr); 02663 return AST_PBX_FAILED; 02664 } 02665 pthread_attr_destroy(&attr); 02666 02667 return AST_PBX_SUCCESS; 02668 }
int ast_rdlock_contexts | ( | void | ) |
Definition at line 6168 of file pbx.c.
References ast_rwlock_rdlock().
Referenced by __ast_context_create(), _macro_exec(), ast_context_find(), ast_context_lockmacro(), ast_context_unlockmacro(), ast_hint_extension(), complete_context_add_extension(), complete_context_add_extension_deprecated(), complete_context_add_ignorepat(), complete_context_add_ignorepat_deprecated(), complete_context_add_include(), complete_context_add_include_deprecated(), complete_context_dont_include_deprecated(), complete_context_remove_extension(), complete_context_remove_extension_deprecated(), complete_context_remove_ignorepat(), complete_context_remove_ignorepat_deprecated(), complete_context_remove_include(), complete_show_dialplan_context(), dundi_precache_full(), find_context_locked(), handle_save_dialplan(), pbx_extension_helper(), and show_dialplan_helper().
06169 { 06170 return ast_rwlock_rdlock(&conlock); 06171 }
int ast_register_application | ( | const char * | app, | |
int(*)(struct ast_channel *, void *) | execute, | |||
const char * | synopsis, | |||
const char * | description | |||
) |
Register an application.
app | Short name of the application | |
execute | a function callback to execute the application. It should return non-zero if the channel needs to be hung up. | |
synopsis | a short description (one line synopsis) of the application | |
description | long description with all of the details about the use of the application |
0 | success | |
-1 | failure. |
Definition at line 2972 of file pbx.c.
References ast_calloc, AST_LIST_INSERT_BEFORE_CURRENT, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), ast_verbose(), COLOR_BRCYAN, ast_app::description, ast_app::execute, LOG_WARNING, option_verbose, ast_app::synopsis, term_color(), and VERBOSE_PREFIX_2.
Referenced by load_module(), and load_pbx().
02973 { 02974 struct ast_app *tmp, *cur = NULL; 02975 char tmps[80]; 02976 int length; 02977 02978 AST_LIST_LOCK(&apps); 02979 AST_LIST_TRAVERSE(&apps, tmp, list) { 02980 if (!strcasecmp(app, tmp->name)) { 02981 ast_log(LOG_WARNING, "Already have an application '%s'\n", app); 02982 AST_LIST_UNLOCK(&apps); 02983 return -1; 02984 } 02985 } 02986 02987 length = sizeof(*tmp) + strlen(app) + 1; 02988 02989 if (!(tmp = ast_calloc(1, length))) { 02990 AST_LIST_UNLOCK(&apps); 02991 return -1; 02992 } 02993 02994 strcpy(tmp->name, app); 02995 tmp->execute = execute; 02996 tmp->synopsis = synopsis; 02997 tmp->description = description; 02998 02999 /* Store in alphabetical order */ 03000 AST_LIST_TRAVERSE_SAFE_BEGIN(&apps, cur, list) { 03001 if (strcasecmp(tmp->name, cur->name) < 0) { 03002 AST_LIST_INSERT_BEFORE_CURRENT(&apps, tmp, list); 03003 break; 03004 } 03005 } 03006 AST_LIST_TRAVERSE_SAFE_END 03007 if (!cur) 03008 AST_LIST_INSERT_TAIL(&apps, tmp, list); 03009 03010 if (option_verbose > 1) 03011 ast_verbose( VERBOSE_PREFIX_2 "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps))); 03012 03013 AST_LIST_UNLOCK(&apps); 03014 03015 return 0; 03016 }
int ast_register_switch | ( | struct ast_switch * | sw | ) |
Register an alternative dialplan switch.
sw | switch to register |
Definition at line 3022 of file pbx.c.
References AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), LOG_WARNING, and ast_switch::name.
Referenced by load_module().
03023 { 03024 struct ast_switch *tmp; 03025 03026 AST_LIST_LOCK(&switches); 03027 AST_LIST_TRAVERSE(&switches, tmp, list) { 03028 if (!strcasecmp(tmp->name, sw->name)) { 03029 AST_LIST_UNLOCK(&switches); 03030 ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name); 03031 return -1; 03032 } 03033 } 03034 AST_LIST_INSERT_TAIL(&switches, sw, list); 03035 AST_LIST_UNLOCK(&switches); 03036 03037 return 0; 03038 }
static int ast_remove_hint | ( | struct ast_exten * | e | ) | [static] |
ast_remove_hint: Remove hint from extension
Definition at line 2236 of file pbx.c.
References AST_EXTENSION_DEACTIVATED, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_state_cb::callback, ast_hint::callbacks, ast_state_cb::data, ast_exten::exten, ast_hint::exten, free, ast_state_cb::next, and ast_exten::parent.
Referenced by destroy_exten().
02237 { 02238 /* Cleanup the Notifys if hint is removed */ 02239 struct ast_hint *hint; 02240 struct ast_state_cb *cblist, *cbprev; 02241 int res = -1; 02242 02243 if (!e) 02244 return -1; 02245 02246 AST_LIST_LOCK(&hints); 02247 AST_LIST_TRAVERSE_SAFE_BEGIN(&hints, hint, list) { 02248 if (hint->exten == e) { 02249 cbprev = NULL; 02250 cblist = hint->callbacks; 02251 while (cblist) { 02252 /* Notify with -1 and remove all callbacks */ 02253 cbprev = cblist; 02254 cblist = cblist->next; 02255 cbprev->callback(hint->exten->parent->name, hint->exten->exten, AST_EXTENSION_DEACTIVATED, cbprev->data, NULL, NULL); 02256 free(cbprev); 02257 } 02258 hint->callbacks = NULL; 02259 AST_LIST_REMOVE_CURRENT(&hints, list); 02260 free(hint); 02261 res = 0; 02262 break; 02263 } 02264 } 02265 AST_LIST_TRAVERSE_SAFE_END 02266 AST_LIST_UNLOCK(&hints); 02267 02268 return res; 02269 }
AST_RWLOCK_DEFINE_STATIC | ( | conlock | ) |
Lock for the ast_context list
int ast_spawn_extension | ( | struct ast_channel * | c, | |
const char * | context, | |||
const char * | exten, | |||
int | priority, | |||
const char * | callerid | |||
) |
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 |
0 | on success | |
-1 | on failure. |
Definition at line 2315 of file pbx.c.
References E_SPAWN, and pbx_extension_helper().
Referenced by __ast_pbx_run(), _macro_exec(), and loopback_exec().
02316 { 02317 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN); 02318 }
AST_THREADSTORAGE | ( | switch_data | , | |
switch_data_init | ||||
) |
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 6191 of file pbx.c.
References ast_mutex_unlock(), and ast_context::lock.
Referenced by _macro_exec(), complete_context_dont_include_deprecated(), complete_context_remove_ignorepat(), complete_context_remove_ignorepat_deprecated(), complete_context_remove_include(), dundi_precache_full(), find_matching_endwhile(), handle_save_dialplan(), lookup_c_ip(), lookup_ci(), and show_dialplan_helper().
06192 { 06193 return ast_mutex_unlock(&con->lock); 06194 }
int ast_unlock_contexts | ( | void | ) |
Unlocks contexts.
0 | on success | |
-1 | on failure |
Definition at line 6178 of file pbx.c.
References ast_rwlock_unlock().
Referenced by __ast_context_create(), _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_lockmacro(), ast_context_remove_extension(), ast_context_remove_ignorepat(), ast_context_remove_include(), ast_context_remove_switch(), ast_context_unlockmacro(), ast_hint_extension(), ast_merge_contexts_and_delete(), complete_context_add_extension(), complete_context_add_extension_deprecated(), complete_context_add_ignorepat(), complete_context_add_ignorepat_deprecated(), complete_context_add_include(), complete_context_add_include_deprecated(), complete_context_dont_include_deprecated(), complete_context_remove_extension(), complete_context_remove_extension_deprecated(), complete_context_remove_ignorepat(), complete_context_remove_ignorepat_deprecated(), complete_context_remove_include(), complete_show_dialplan_context(), dundi_precache_full(), find_context_locked(), find_matching_endwhile(), handle_save_dialplan(), pbx_extension_helper(), and show_dialplan_helper().
06179 { 06180 return ast_rwlock_unlock(&conlock); 06181 }
int ast_unregister_application | ( | const char * | app | ) |
Unregister an application.
app | name of the application (does not have to be the same string as the one that was registered) |
0 | success | |
-1 | failure |
Definition at line 3853 of file pbx.c.
References AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_verbose(), free, option_verbose, and VERBOSE_PREFIX_2.
Referenced by __unload_module(), and unload_module().
03854 { 03855 struct ast_app *tmp; 03856 03857 AST_LIST_LOCK(&apps); 03858 AST_LIST_TRAVERSE_SAFE_BEGIN(&apps, tmp, list) { 03859 if (!strcasecmp(app, tmp->name)) { 03860 AST_LIST_REMOVE_CURRENT(&apps, list); 03861 if (option_verbose > 1) 03862 ast_verbose( VERBOSE_PREFIX_2 "Unregistered application '%s'\n", tmp->name); 03863 free(tmp); 03864 break; 03865 } 03866 } 03867 AST_LIST_TRAVERSE_SAFE_END 03868 AST_LIST_UNLOCK(&apps); 03869 03870 return tmp ? 0 : -1; 03871 }
void ast_unregister_switch | ( | struct ast_switch * | sw | ) |
Unregister an alternative switch.
sw | switch to unregister |
Definition at line 3040 of file pbx.c.
References AST_LIST_LOCK, AST_LIST_REMOVE, and AST_LIST_UNLOCK.
Referenced by __unload_module(), and unload_module().
03041 { 03042 AST_LIST_LOCK(&switches); 03043 AST_LIST_REMOVE(&switches, sw, list); 03044 AST_LIST_UNLOCK(&switches); 03045 }
struct ast_exten* ast_walk_context_extensions | ( | struct ast_context * | con, | |
struct ast_exten * | exten | |||
) |
Definition at line 6300 of file pbx.c.
References exten, and ast_context::root.
Referenced by complete_context_remove_extension(), complete_context_remove_extension_deprecated(), dundi_precache_full(), find_matching_priority(), handle_save_dialplan(), pbx_find_extension(), and show_dialplan_helper().
06302 { 06303 if (!exten) 06304 return con ? con->root : NULL; 06305 else 06306 return exten->next; 06307 }
struct ast_ignorepat* ast_walk_context_ignorepats | ( | struct ast_context * | con, | |
struct ast_ignorepat * | ip | |||
) |
Definition at line 6333 of file pbx.c.
References ast_context::ignorepats, and ast_ignorepat::next.
Referenced by complete_context_remove_ignorepat(), complete_context_remove_ignorepat_deprecated(), handle_save_dialplan(), lookup_c_ip(), and show_dialplan_helper().
06335 { 06336 if (!ip) 06337 return con ? con->ignorepats : NULL; 06338 else 06339 return ip->next; 06340 }
struct ast_include* ast_walk_context_includes | ( | struct ast_context * | con, | |
struct ast_include * | inc | |||
) |
Definition at line 6324 of file pbx.c.
References ast_context::includes, and ast_include::next.
Referenced by ast_context_verify_includes(), complete_context_dont_include_deprecated(), complete_context_remove_include(), find_matching_priority(), handle_save_dialplan(), lookup_ci(), and show_dialplan_helper().
06326 { 06327 if (!inc) 06328 return con ? con->includes : NULL; 06329 else 06330 return inc->next; 06331 }
struct ast_sw* ast_walk_context_switches | ( | struct ast_context * | con, | |
struct ast_sw * | sw | |||
) |
Definition at line 6309 of file pbx.c.
References AST_LIST_FIRST, and AST_LIST_NEXT.
Referenced by handle_save_dialplan(), and show_dialplan_helper().
06311 { 06312 if (!sw) 06313 return con ? AST_LIST_FIRST(&con->alts) : NULL; 06314 else 06315 return AST_LIST_NEXT(sw, list); 06316 }
struct ast_context* ast_walk_contexts | ( | struct ast_context * | con | ) |
Definition at line 6295 of file pbx.c.
References contexts, and ast_context::next.
Referenced by _macro_exec(), ast_context_find(), ast_context_lockmacro(), ast_context_unlockmacro(), complete_context_add_extension(), complete_context_add_extension_deprecated(), complete_context_add_ignorepat(), complete_context_add_ignorepat_deprecated(), complete_context_add_include(), complete_context_add_include_deprecated(), complete_context_dont_include_deprecated(), complete_context_remove_extension(), complete_context_remove_extension_deprecated(), complete_context_remove_ignorepat(), complete_context_remove_ignorepat_deprecated(), complete_context_remove_include(), complete_show_dialplan_context(), dundi_precache_full(), find_context_locked(), find_matching_endwhile(), find_matching_priority(), handle_save_dialplan(), pbx_find_extension(), pbx_load_module(), and show_dialplan_helper().
struct ast_exten* ast_walk_extension_priorities | ( | struct ast_exten * | exten, | |
struct ast_exten * | priority | |||
) |
Definition at line 6318 of file pbx.c.
References exten, and ast_exten::priority.
Referenced by complete_context_remove_extension(), complete_context_remove_extension_deprecated(), find_matching_priority(), handle_save_dialplan(), pbx_find_extension(), and show_dialplan_helper().
int ast_wrlock_contexts | ( | void | ) |
Definition at line 6173 of file pbx.c.
References ast_rwlock_wrlock().
Referenced by ast_context_destroy(), ast_merge_contexts_and_delete(), and complete_context_dont_include_deprecated().
06174 { 06175 return ast_rwlock_wrlock(&conlock); 06176 }
static void* async_wait | ( | void * | data | ) | [static] |
Definition at line 4907 of file pbx.c.
References ast_channel::_state, app, async_stat::app, async_stat::appdata, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_FRAME_CONTROL, ast_frfree, ast_hangup(), ast_log(), ast_pbx_run(), ast_read(), AST_STATE_UP, ast_strlen_zero(), ast_verbose(), ast_waitfor(), async_stat::chan, ast_channel::context, async_stat::context, ast_channel::exten, async_stat::exten, f, free, LOG_ERROR, LOG_WARNING, option_verbose, pbx_exec(), pbx_findapp(), ast_channel::priority, async_stat::priority, async_stat::timeout, and VERBOSE_PREFIX_3.
Referenced by ast_pbx_outgoing_app_uniqueid(), and ast_pbx_outgoing_exten_uniqueid().
04908 { 04909 struct async_stat *as = data; 04910 struct ast_channel *chan = as->chan; 04911 int timeout = as->timeout; 04912 int res; 04913 struct ast_frame *f; 04914 struct ast_app *app; 04915 04916 while (timeout && (chan->_state != AST_STATE_UP)) { 04917 res = ast_waitfor(chan, timeout); 04918 if (res < 1) 04919 break; 04920 if (timeout > -1) 04921 timeout = res; 04922 f = ast_read(chan); 04923 if (!f) 04924 break; 04925 if (f->frametype == AST_FRAME_CONTROL) { 04926 if ((f->subclass == AST_CONTROL_BUSY) || 04927 (f->subclass == AST_CONTROL_CONGESTION) ) { 04928 ast_frfree(f); 04929 break; 04930 } 04931 } 04932 ast_frfree(f); 04933 } 04934 if (chan->_state == AST_STATE_UP) { 04935 if (!ast_strlen_zero(as->app)) { 04936 app = pbx_findapp(as->app); 04937 if (app) { 04938 if (option_verbose > 2) 04939 ast_verbose(VERBOSE_PREFIX_3 "Launching %s(%s) on %s\n", as->app, as->appdata, chan->name); 04940 pbx_exec(chan, app, as->appdata); 04941 } else 04942 ast_log(LOG_WARNING, "No such application '%s'\n", as->app); 04943 } else { 04944 if (!ast_strlen_zero(as->context)) 04945 ast_copy_string(chan->context, as->context, sizeof(chan->context)); 04946 if (!ast_strlen_zero(as->exten)) 04947 ast_copy_string(chan->exten, as->exten, sizeof(chan->exten)); 04948 if (as->priority > 0) 04949 chan->priority = as->priority; 04950 /* Run the PBX */ 04951 if (ast_pbx_run(chan)) { 04952 ast_log(LOG_ERROR, "Failed to start PBX on %s\n", chan->name); 04953 } else { 04954 /* PBX will have taken care of this */ 04955 chan = NULL; 04956 } 04957 } 04958 } 04959 free(as); 04960 if (chan) 04961 ast_hangup(chan); 04962 return NULL; 04963 }
static int collect_digits | ( | struct ast_channel * | c, | |
int | waittime, | |||
char * | buf, | |||
int | buflen, | |||
int | pos | |||
) | [static] |
collect digits from the channel into the buffer, return -1 on error, 0 on timeout or done.
Definition at line 2333 of file pbx.c.
References ast_channel::_softhangup, ast_matchmore_extension(), AST_SOFTHANGUP_ASYNCGOTO, ast_waitfordigit(), ast_channel::cid, ast_callerid::cid_num, ast_channel::context, ast_pbx::dtimeout, and ast_channel::pbx.
02334 { 02335 int digit; 02336 02337 buf[pos] = '\0'; /* make sure it is properly terminated */ 02338 while (ast_matchmore_extension(c, c->context, buf, 1, c->cid.cid_num)) { 02339 /* As long as we're willing to wait, and as long as it's not defined, 02340 keep reading digits until we can't possibly get a right answer anymore. */ 02341 digit = ast_waitfordigit(c, waittime * 1000); 02342 if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) { 02343 c->_softhangup = 0; 02344 } else { 02345 if (!digit) /* No entry */ 02346 break; 02347 if (digit < 0) /* Error, maybe a hangup */ 02348 return -1; 02349 if (pos < buflen - 1) { /* XXX maybe error otherwise ? */ 02350 buf[pos++] = digit; 02351 buf[pos] = '\0'; 02352 } 02353 waittime = c->pbx->dtimeout; 02354 } 02355 } 02356 return 0; 02357 }
static char* complete_show_application | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 3098 of file pbx.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, and strdup.
03099 { 03100 struct ast_app *a; 03101 char *ret = NULL; 03102 int which = 0; 03103 int wordlen = strlen(word); 03104 03105 /* return the n-th [partial] matching entry */ 03106 AST_LIST_LOCK(&apps); 03107 AST_LIST_TRAVERSE(&apps, a, list) { 03108 if (!strncasecmp(word, a->name, wordlen) && ++which > state) { 03109 ret = strdup(a->name); 03110 break; 03111 } 03112 } 03113 AST_LIST_UNLOCK(&apps); 03114 03115 return ret; 03116 }
static char* complete_show_applications | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 3459 of file pbx.c.
References ast_cli_complete().
03460 { 03461 static char* choices[] = { "like", "describing", NULL }; 03462 03463 return (pos != 3) ? NULL : ast_cli_complete(word, choices, state); 03464 }
static char* complete_show_applications_deprecated | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 3452 of file pbx.c.
References ast_cli_complete().
03453 { 03454 static char* choices[] = { "like", "describing", NULL }; 03455 03456 return (pos != 2) ? NULL : ast_cli_complete(word, choices, state); 03457 }
static char* complete_show_dialplan_context | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 3469 of file pbx.c.
References ast_get_context_name(), ast_rdlock_contexts(), ast_strdup, ast_unlock_contexts(), and ast_walk_contexts().
03471 { 03472 struct ast_context *c = NULL; 03473 char *ret = NULL; 03474 int which = 0; 03475 int wordlen; 03476 03477 /* we are do completion of [exten@]context on second position only */ 03478 if (pos != 2) 03479 return NULL; 03480 03481 ast_rdlock_contexts(); 03482 03483 wordlen = strlen(word); 03484 03485 /* walk through all contexts and return the n-th match */ 03486 while ( (c = ast_walk_contexts(c)) ) { 03487 if (!strncasecmp(word, ast_get_context_name(c), wordlen) && ++which > state) { 03488 ret = ast_strdup(ast_get_context_name(c)); 03489 break; 03490 } 03491 } 03492 03493 ast_unlock_contexts(); 03494 03495 return ret; 03496 }
static char* complete_show_function | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 1434 of file pbx.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_custom_function::name, and strdup.
01435 { 01436 struct ast_custom_function *acf; 01437 char *ret = NULL; 01438 int which = 0; 01439 int wordlen = strlen(word); 01440 01441 /* case-insensitive for convenience in this 'complete' function */ 01442 AST_LIST_LOCK(&acf_root); 01443 AST_LIST_TRAVERSE(&acf_root, acf, acflist) { 01444 if (!strncasecmp(word, acf->name, wordlen) && ++which > state) { 01445 ret = strdup(acf->name); 01446 break; 01447 } 01448 } 01449 AST_LIST_UNLOCK(&acf_root); 01450 01451 return ret; 01452 }
static void decrease_call_count | ( | void | ) | [static] |
Definition at line 2606 of file pbx.c.
References ast_mutex_lock(), ast_mutex_unlock(), and countcalls.
Referenced by ast_pbx_run(), and pbx_thread().
02607 { 02608 ast_mutex_lock(&maxcalllock); 02609 if (countcalls > 0) 02610 countcalls--; 02611 ast_mutex_unlock(&maxcalllock); 02612 }
static void destroy_exten | ( | struct ast_exten * | e | ) | [static] |
Definition at line 2614 of file pbx.c.
References ast_remove_hint(), free, ast_exten::priority, and PRIORITY_HINT.
Referenced by __ast_context_destroy(), and ast_context_remove_extension2().
02615 { 02616 if (e->priority == PRIORITY_HINT) 02617 ast_remove_hint(e); 02618 02619 if (e->datad) 02620 e->datad(e->data); 02621 free(e); 02622 }
static int ext_cmp | ( | const char * | a, | |
const char * | b | |||
) | [static] |
the full routine to compare extensions in rules.
Definition at line 722 of file pbx.c.
References ext_cmp1().
Referenced by ast_add_extension2().
00723 { 00724 /* make sure non-patterns come first. 00725 * If a is not a pattern, it either comes first or 00726 * we use strcmp to compare the strings. 00727 */ 00728 int ret = 0; 00729 00730 if (a[0] != '_') 00731 return (b[0] == '_') ? -1 : strcmp(a, b); 00732 00733 /* Now we know a is a pattern; if b is not, a comes first */ 00734 if (b[0] != '_') 00735 return 1; 00736 #if 0 /* old mode for ext matching */ 00737 return strcmp(a, b); 00738 #endif 00739 /* ok we need full pattern sorting routine */ 00740 while (!ret && a && b) 00741 ret = ext_cmp1(&a) - ext_cmp1(&b); 00742 if (ret == 0) 00743 return 0; 00744 else 00745 return (ret > 0) ? 1 : -1; 00746 }
static int ext_cmp1 | ( | const char ** | p | ) | [static] |
helper functions to sort extensions and patterns in the desired way, so that more specific patterns appear first.
ext_cmp1 compares individual characters (or sets of), returning an int where bits 0-7 are the ASCII code of the first char in the set, while bit 8-15 are the cardinality of the set minus 1. This way more specific patterns (smaller cardinality) appear first. Wildcards have a special value, so that we can directly compare them to sets by subtracting the two values. In particular: 0x000xx one character, xx 0x0yyxx yy character set starting with xx 0x10000 '.' (one or more of anything) 0x20000 '!' (zero or more of anything) 0x30000 NUL (end of string) 0x40000 error in set. The pointer to the string is advanced according to needs. NOTES: 1. the empty set is equivalent to NUL. 2. given that a full set has always 0 as the first element, we could encode the special cases as 0xffXX where XX is 1, 2, 3, 4 as used above.
Definition at line 650 of file pbx.c.
References ast_log(), and LOG_WARNING.
Referenced by ext_cmp().
00651 { 00652 uint32_t chars[8]; 00653 int c, cmin = 0xff, count = 0; 00654 const char *end; 00655 00656 /* load, sign extend and advance pointer until we find 00657 * a valid character. 00658 */ 00659 while ( (c = *(*p)++) && (c == ' ' || c == '-') ) 00660 ; /* ignore some characters */ 00661 00662 /* always return unless we have a set of chars */ 00663 switch (c) { 00664 default: /* ordinary character */ 00665 return 0x0000 | (c & 0xff); 00666 00667 case 'N': /* 2..9 */ 00668 return 0x0700 | '2' ; 00669 00670 case 'X': /* 0..9 */ 00671 return 0x0900 | '0'; 00672 00673 case 'Z': /* 1..9 */ 00674 return 0x0800 | '1'; 00675 00676 case '.': /* wildcard */ 00677 return 0x10000; 00678 00679 case '!': /* earlymatch */ 00680 return 0x20000; /* less specific than NULL */ 00681 00682 case '\0': /* empty string */ 00683 *p = NULL; 00684 return 0x30000; 00685 00686 case '[': /* pattern */ 00687 break; 00688 } 00689 /* locate end of set */ 00690 end = strchr(*p, ']'); 00691 00692 if (end == NULL) { 00693 ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n"); 00694 return 0x40000; /* XXX make this entry go last... */ 00695 } 00696 00697 bzero(chars, sizeof(chars)); /* clear all chars in the set */ 00698 for (; *p < end ; (*p)++) { 00699 unsigned char c1, c2; /* first-last char in range */ 00700 c1 = (unsigned char)((*p)[0]); 00701 if (*p + 2 < end && (*p)[1] == '-') { /* this is a range */ 00702 c2 = (unsigned char)((*p)[2]); 00703 *p += 2; /* skip a total of 3 chars */ 00704 } else /* individual character */ 00705 c2 = c1; 00706 if (c1 < cmin) 00707 cmin = c1; 00708 for (; c1 <= c2; c1++) { 00709 uint32_t mask = 1 << (c1 % 32); 00710 if ( (chars[ c1 / 32 ] & mask) == 0) 00711 count += 0x100; 00712 chars[ c1 / 32 ] |= mask; 00713 } 00714 } 00715 (*p)++; 00716 return count == 0 ? 0x30000 : (count | cmin); 00717 }
static int ext_strncpy | ( | char * | dst, | |
const char * | src, | |||
int | len | |||
) | [static] |
copy a string skipping whitespace
Definition at line 4659 of file pbx.c.
Referenced by ast_add_extension2().
04660 { 04661 int count=0; 04662 04663 while (*src && (count < len - 1)) { 04664 switch(*src) { 04665 case ' ': 04666 /* otherwise exten => [a-b],1,... doesn't work */ 04667 /* case '-': */ 04668 /* Ignore */ 04669 break; 04670 default: 04671 *dst = *src; 04672 dst++; 04673 } 04674 src++; 04675 count++; 04676 } 04677 *dst = '\0'; 04678 04679 return count; 04680 }
static int extension_match_core | ( | const char * | pattern, | |
const char * | data, | |||
enum ext_match_t | mode | |||
) | [static] |
Definition at line 871 of file pbx.c.
References _extension_match_core(), ast_add_profile(), and ast_mark().
Referenced by ast_extension_close(), ast_extension_match(), and pbx_find_extension().
00872 { 00873 int i; 00874 static int prof_id = -2; /* marker for 'unallocated' id */ 00875 if (prof_id == -2) 00876 prof_id = ast_add_profile("ext_match", 0); 00877 ast_mark(prof_id, 1); 00878 i = _extension_match_core(pattern, data, mode); 00879 ast_mark(prof_id, 0); 00880 return i; 00881 }
static struct ast_context* find_context_locked | ( | const char * | context | ) | [static] |
Definition at line 2698 of file pbx.c.
References ast_get_context_name(), ast_rdlock_contexts(), ast_unlock_contexts(), and ast_walk_contexts().
Referenced by ast_add_extension(), ast_context_add_ignorepat(), ast_context_add_include(), ast_context_add_switch(), ast_context_remove_extension(), ast_context_remove_ignorepat(), ast_context_remove_include(), and ast_context_remove_switch().
02699 { 02700 struct ast_context *c = NULL; 02701 02702 ast_rdlock_contexts(); 02703 while ( (c = ast_walk_contexts(c)) ) { 02704 if (!strcmp(ast_get_context_name(c), context)) 02705 return c; 02706 } 02707 ast_unlock_contexts(); 02708 02709 return NULL; 02710 }
static char* func_args | ( | char * | function | ) | [static] |
return a pointer to the arguments of the function, and terminates the function name with '\0'
Definition at line 1527 of file pbx.c.
References ast_log(), and LOG_WARNING.
Referenced by ast_func_read(), and ast_func_write().
01528 { 01529 char *args = strchr(function, '('); 01530 01531 if (!args) 01532 ast_log(LOG_WARNING, "Function doesn't contain parentheses. Assuming null argument.\n"); 01533 else { 01534 char *p; 01535 *args++ = '\0'; 01536 if ((p = strrchr(args, ')')) ) 01537 *p = '\0'; 01538 else 01539 ast_log(LOG_WARNING, "Can't find trailing parenthesis?\n"); 01540 } 01541 return args; 01542 }
static unsigned get_range | ( | char * | src, | |
int | max, | |||
char *const | names[], | |||
const char * | msg | |||
) | [static] |
helper function to return a range up to max (7, 12, 31 respectively). names, if supplied, is an array of names that should be mapped to numbers.
Definition at line 4083 of file pbx.c.
References ast_log(), ast_strlen_zero(), LOG_WARNING, lookup_name(), and s.
Referenced by ast_build_timing().
04084 { 04085 int s, e; /* start and ending position */ 04086 unsigned int mask = 0; 04087 04088 /* Check for whole range */ 04089 if (ast_strlen_zero(src) || !strcmp(src, "*")) { 04090 s = 0; 04091 e = max - 1; 04092 } else { 04093 /* Get start and ending position */ 04094 char *c = strchr(src, '-'); 04095 if (c) 04096 *c++ = '\0'; 04097 /* Find the start */ 04098 s = lookup_name(src, names, max); 04099 if (!s) { 04100 ast_log(LOG_WARNING, "Invalid %s '%s', assuming none\n", msg, src); 04101 return 0; 04102 } 04103 s--; 04104 if (c) { /* find end of range */ 04105 e = lookup_name(c, names, max); 04106 if (!e) { 04107 ast_log(LOG_WARNING, "Invalid end %s '%s', assuming none\n", msg, c); 04108 return 0; 04109 } 04110 e--; 04111 } else 04112 e = s; 04113 } 04114 /* Fill the mask. Remember that ranges are cyclic */ 04115 mask = 1 << e; /* initialize with last element */ 04116 while (s != e) { 04117 if (s >= max) { 04118 s = 0; 04119 mask |= (1 << s); 04120 } else { 04121 mask |= (1 << s); 04122 s++; 04123 } 04124 } 04125 return mask; 04126 }
static void get_timerange | ( | struct ast_timing * | i, | |
char * | times | |||
) | [static] |
store a bitmask of valid times, one bit each 2 minute
Definition at line 4129 of file pbx.c.
References ast_log(), ast_strlen_zero(), LOG_WARNING, and ast_timing::minmask.
Referenced by ast_build_timing().
04130 { 04131 char *e; 04132 int x; 04133 int s1, s2; 04134 int e1, e2; 04135 /* int cth, ctm; */ 04136 04137 /* start disabling all times, fill the fields with 0's, as they may contain garbage */ 04138 memset(i->minmask, 0, sizeof(i->minmask)); 04139 04140 /* 2-minutes per bit, since the mask has only 32 bits :( */ 04141 /* Star is all times */ 04142 if (ast_strlen_zero(times) || !strcmp(times, "*")) { 04143 for (x=0; x<24; x++) 04144 i->minmask[x] = 0x3fffffff; /* 30 bits */ 04145 return; 04146 } 04147 /* Otherwise expect a range */ 04148 e = strchr(times, '-'); 04149 if (!e) { 04150 ast_log(LOG_WARNING, "Time range is not valid. Assuming no restrictions based on time.\n"); 04151 return; 04152 } 04153 *e++ = '\0'; 04154 /* XXX why skip non digits ? */ 04155 while (*e && !isdigit(*e)) 04156 e++; 04157 if (!*e) { 04158 ast_log(LOG_WARNING, "Invalid time range. Assuming no restrictions based on time.\n"); 04159 return; 04160 } 04161 if (sscanf(times, "%d:%d", &s1, &s2) != 2) { 04162 ast_log(LOG_WARNING, "%s isn't a time. Assuming no restrictions based on time.\n", times); 04163 return; 04164 } 04165 if (sscanf(e, "%d:%d", &e1, &e2) != 2) { 04166 ast_log(LOG_WARNING, "%s isn't a time. Assuming no restrictions based on time.\n", e); 04167 return; 04168 } 04169 /* XXX this needs to be optimized */ 04170 #if 1 04171 s1 = s1 * 30 + s2/2; 04172 if ((s1 < 0) || (s1 >= 24*30)) { 04173 ast_log(LOG_WARNING, "%s isn't a valid start time. Assuming no time.\n", times); 04174 return; 04175 } 04176 e1 = e1 * 30 + e2/2; 04177 if ((e1 < 0) || (e1 >= 24*30)) { 04178 ast_log(LOG_WARNING, "%s isn't a valid end time. Assuming no time.\n", e); 04179 return; 04180 } 04181 /* Go through the time and enable each appropriate bit */ 04182 for (x=s1;x != e1;x = (x + 1) % (24 * 30)) { 04183 i->minmask[x/30] |= (1 << (x % 30)); 04184 } 04185 /* Do the last one */ 04186 i->minmask[x/30] |= (1 << (x % 30)); 04187 #else 04188 for (cth=0; cth<24; cth++) { 04189 /* Initialize masks to blank */ 04190 i->minmask[cth] = 0; 04191 for (ctm=0; ctm<30; ctm++) { 04192 if ( 04193 /* First hour with more than one hour */ 04194 (((cth == s1) && (ctm >= s2)) && 04195 ((cth < e1))) 04196 /* Only one hour */ 04197 || (((cth == s1) && (ctm >= s2)) && 04198 ((cth == e1) && (ctm <= e2))) 04199 /* In between first and last hours (more than 2 hours) */ 04200 || ((cth > s1) && 04201 (cth < e1)) 04202 /* Last hour with more than one hour */ 04203 || ((cth > s1) && 04204 ((cth == e1) && (ctm <= e2))) 04205 ) 04206 i->minmask[cth] |= (1 << (ctm / 2)); 04207 } 04208 } 04209 #endif 04210 /* All done */ 04211 return; 04212 }
static int handle_set_global | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3754 of file pbx.c.
References ast_cli(), pbx_builtin_setvar_helper(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03755 { 03756 if (argc != 5) 03757 return RESULT_SHOWUSAGE; 03758 03759 pbx_builtin_setvar_helper(NULL, argv[3], argv[4]); 03760 ast_cli(fd, "\n -- Global variable %s set to %s\n", argv[3], argv[4]); 03761 03762 return RESULT_SUCCESS; 03763 }
static int handle_set_global_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
CLI support for setting global variables.
Definition at line 3742 of file pbx.c.
References ast_cli(), pbx_builtin_setvar_helper(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03743 { 03744 if (argc != 4) 03745 return RESULT_SHOWUSAGE; 03746 03747 pbx_builtin_setvar_helper(NULL, argv[2], argv[3]); 03748 ast_cli(fd, "\n -- Global variable %s set to %s\n", argv[2], argv[3]); 03749 03750 return RESULT_SUCCESS; 03751 }
static int handle_show_application | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3188 of file pbx.c.
References ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_MAX_APP, COLOR_CYAN, COLOR_MAGENTA, ast_app::description, RESULT_SHOWUSAGE, ast_app::synopsis, and term_color().
03189 { 03190 struct ast_app *a; 03191 int app, no_registered_app = 1; 03192 03193 if (argc < 4) 03194 return RESULT_SHOWUSAGE; 03195 03196 /* ... go through all applications ... */ 03197 AST_LIST_LOCK(&apps); 03198 AST_LIST_TRAVERSE(&apps, a, list) { 03199 /* ... compare this application name with all arguments given 03200 * to 'show application' command ... */ 03201 for (app = 3; app < argc; app++) { 03202 if (!strcasecmp(a->name, argv[app])) { 03203 /* Maximum number of characters added by terminal coloring is 22 */ 03204 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40]; 03205 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL; 03206 int synopsis_size, description_size; 03207 03208 no_registered_app = 0; 03209 03210 if (a->synopsis) 03211 synopsis_size = strlen(a->synopsis) + 23; 03212 else 03213 synopsis_size = strlen("Not available") + 23; 03214 synopsis = alloca(synopsis_size); 03215 03216 if (a->description) 03217 description_size = strlen(a->description) + 23; 03218 else 03219 description_size = strlen("Not available") + 23; 03220 description = alloca(description_size); 03221 03222 if (synopsis && description) { 03223 snprintf(info, 64 + AST_MAX_APP, "\n -= Info about application '%s' =- \n\n", a->name); 03224 term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22); 03225 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 03226 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40); 03227 term_color(synopsis, 03228 a->synopsis ? a->synopsis : "Not available", 03229 COLOR_CYAN, 0, synopsis_size); 03230 term_color(description, 03231 a->description ? a->description : "Not available", 03232 COLOR_CYAN, 0, description_size); 03233 03234 ast_cli(fd,"%s%s%s\n\n%s%s\n", infotitle, syntitle, synopsis, destitle, description); 03235 } else { 03236 /* ... one of our applications, show info ...*/ 03237 ast_cli(fd,"\n -= Info about application '%s' =- \n\n" 03238 "[Synopsis]\n %s\n\n" 03239 "[Description]\n%s\n", 03240 a->name, 03241 a->synopsis ? a->synopsis : "Not available", 03242 a->description ? a->description : "Not available"); 03243 } 03244 } 03245 } 03246 } 03247 AST_LIST_UNLOCK(&apps); 03248 03249 /* we found at least one app? no? */ 03250 if (no_registered_app) { 03251 ast_cli(fd, "Your application(s) is (are) not registered\n"); 03252 return RESULT_FAILURE; 03253 } 03254 03255 return RESULT_SUCCESS; 03256 }
static int handle_show_application_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3118 of file pbx.c.
References ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_MAX_APP, COLOR_CYAN, COLOR_MAGENTA, ast_app::description, RESULT_SHOWUSAGE, ast_app::synopsis, and term_color().
03119 { 03120 struct ast_app *a; 03121 int app, no_registered_app = 1; 03122 03123 if (argc < 3) 03124 return RESULT_SHOWUSAGE; 03125 03126 /* ... go through all applications ... */ 03127 AST_LIST_LOCK(&apps); 03128 AST_LIST_TRAVERSE(&apps, a, list) { 03129 /* ... compare this application name with all arguments given 03130 * to 'show application' command ... */ 03131 for (app = 2; app < argc; app++) { 03132 if (!strcasecmp(a->name, argv[app])) { 03133 /* Maximum number of characters added by terminal coloring is 22 */ 03134 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40]; 03135 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL; 03136 int synopsis_size, description_size; 03137 03138 no_registered_app = 0; 03139 03140 if (a->synopsis) 03141 synopsis_size = strlen(a->synopsis) + 23; 03142 else 03143 synopsis_size = strlen("Not available") + 23; 03144 synopsis = alloca(synopsis_size); 03145 03146 if (a->description) 03147 description_size = strlen(a->description) + 23; 03148 else 03149 description_size = strlen("Not available") + 23; 03150 description = alloca(description_size); 03151 03152 if (synopsis && description) { 03153 snprintf(info, 64 + AST_MAX_APP, "\n -= Info about application '%s' =- \n\n", a->name); 03154 term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22); 03155 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 03156 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40); 03157 term_color(synopsis, 03158 a->synopsis ? a->synopsis : "Not available", 03159 COLOR_CYAN, 0, synopsis_size); 03160 term_color(description, 03161 a->description ? a->description : "Not available", 03162 COLOR_CYAN, 0, description_size); 03163 03164 ast_cli(fd,"%s%s%s\n\n%s%s\n", infotitle, syntitle, synopsis, destitle, description); 03165 } else { 03166 /* ... one of our applications, show info ...*/ 03167 ast_cli(fd,"\n -= Info about application '%s' =- \n\n" 03168 "[Synopsis]\n %s\n\n" 03169 "[Description]\n%s\n", 03170 a->name, 03171 a->synopsis ? a->synopsis : "Not available", 03172 a->description ? a->description : "Not available"); 03173 } 03174 } 03175 } 03176 } 03177 AST_LIST_UNLOCK(&apps); 03178 03179 /* we found at least one app? no? */ 03180 if (no_registered_app) { 03181 ast_cli(fd, "Your application(s) is (are) not registered\n"); 03182 return RESULT_FAILURE; 03183 } 03184 03185 return RESULT_SUCCESS; 03186 }
static int handle_show_applications | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3383 of file pbx.c.
References ast_cli(), AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_app::description, strcasestr(), and ast_app::synopsis.
03384 { 03385 struct ast_app *a; 03386 int like = 0, describing = 0; 03387 int total_match = 0; /* Number of matches in like clause */ 03388 int total_apps = 0; /* Number of apps registered */ 03389 03390 AST_LIST_LOCK(&apps); 03391 03392 if (AST_LIST_EMPTY(&apps)) { 03393 ast_cli(fd, "There are no registered applications\n"); 03394 AST_LIST_UNLOCK(&apps); 03395 return -1; 03396 } 03397 03398 /* core list applications like <keyword> */ 03399 if ((argc == 5) && (!strcmp(argv[3], "like"))) { 03400 like = 1; 03401 } else if ((argc > 4) && (!strcmp(argv[3], "describing"))) { 03402 describing = 1; 03403 } 03404 03405 /* core list applications describing <keyword1> [<keyword2>] [...] */ 03406 if ((!like) && (!describing)) { 03407 ast_cli(fd, " -= Registered Asterisk Applications =-\n"); 03408 } else { 03409 ast_cli(fd, " -= Matching Asterisk Applications =-\n"); 03410 } 03411 03412 AST_LIST_TRAVERSE(&apps, a, list) { 03413 int printapp = 0; 03414 total_apps++; 03415 if (like) { 03416 if (strcasestr(a->name, argv[4])) { 03417 printapp = 1; 03418 total_match++; 03419 } 03420 } else if (describing) { 03421 if (a->description) { 03422 /* Match all words on command line */ 03423 int i; 03424 printapp = 1; 03425 for (i = 4; i < argc; i++) { 03426 if (!strcasestr(a->description, argv[i])) { 03427 printapp = 0; 03428 } else { 03429 total_match++; 03430 } 03431 } 03432 } 03433 } else { 03434 printapp = 1; 03435 } 03436 03437 if (printapp) { 03438 ast_cli(fd," %20s: %s\n", a->name, a->synopsis ? a->synopsis : "<Synopsis not available>"); 03439 } 03440 } 03441 if ((!like) && (!describing)) { 03442 ast_cli(fd, " -= %d Applications Registered =-\n",total_apps); 03443 } else { 03444 ast_cli(fd, " -= %d Applications Matching =-\n",total_match); 03445 } 03446 03447 AST_LIST_UNLOCK(&apps); 03448 03449 return RESULT_SUCCESS; 03450 }
static int handle_show_applications_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3315 of file pbx.c.
References ast_cli(), AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_app::description, strcasestr(), and ast_app::synopsis.
03316 { 03317 struct ast_app *a; 03318 int like = 0, describing = 0; 03319 int total_match = 0; /* Number of matches in like clause */ 03320 int total_apps = 0; /* Number of apps registered */ 03321 03322 AST_LIST_LOCK(&apps); 03323 03324 if (AST_LIST_EMPTY(&apps)) { 03325 ast_cli(fd, "There are no registered applications\n"); 03326 AST_LIST_UNLOCK(&apps); 03327 return -1; 03328 } 03329 03330 /* show applications like <keyword> */ 03331 if ((argc == 4) && (!strcmp(argv[2], "like"))) { 03332 like = 1; 03333 } else if ((argc > 3) && (!strcmp(argv[2], "describing"))) { 03334 describing = 1; 03335 } 03336 03337 /* show applications describing <keyword1> [<keyword2>] [...] */ 03338 if ((!like) && (!describing)) { 03339 ast_cli(fd, " -= Registered Asterisk Applications =-\n"); 03340 } else { 03341 ast_cli(fd, " -= Matching Asterisk Applications =-\n"); 03342 } 03343 03344 AST_LIST_TRAVERSE(&apps, a, list) { 03345 int printapp = 0; 03346 total_apps++; 03347 if (like) { 03348 if (strcasestr(a->name, argv[3])) { 03349 printapp = 1; 03350 total_match++; 03351 } 03352 } else if (describing) { 03353 if (a->description) { 03354 /* Match all words on command line */ 03355 int i; 03356 printapp = 1; 03357 for (i = 3; i < argc; i++) { 03358 if (!strcasestr(a->description, argv[i])) { 03359 printapp = 0; 03360 } else { 03361 total_match++; 03362 } 03363 } 03364 } 03365 } else { 03366 printapp = 1; 03367 } 03368 03369 if (printapp) { 03370 ast_cli(fd," %20s: %s\n", a->name, a->synopsis ? a->synopsis : "<Synopsis not available>"); 03371 } 03372 } 03373 if ((!like) && (!describing)) { 03374 ast_cli(fd, " -= %d Applications Registered =-\n",total_apps); 03375 } else { 03376 ast_cli(fd, " -= %d Applications Matching =-\n",total_match); 03377 } 03378 03379 AST_LIST_UNLOCK(&apps); 03380 03381 return RESULT_SUCCESS; 03382 }
static int handle_show_dialplan | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3669 of file pbx.c.
References ast_cli(), AST_PBX_MAX_STACK, ast_strdupa, ast_strlen_zero(), context, exten, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, show_dialplan_helper(), and strsep().
03670 { 03671 char *exten = NULL, *context = NULL; 03672 /* Variables used for different counters */ 03673 struct dialplan_counters counters; 03674 03675 const char *incstack[AST_PBX_MAX_STACK]; 03676 memset(&counters, 0, sizeof(counters)); 03677 03678 if (argc != 2 && argc != 3) 03679 return RESULT_SHOWUSAGE; 03680 03681 /* we obtain [exten@]context? if yes, split them ... */ 03682 if (argc == 3) { 03683 if (strchr(argv[2], '@')) { /* split into exten & context */ 03684 context = ast_strdupa(argv[2]); 03685 exten = strsep(&context, "@"); 03686 /* change empty strings to NULL */ 03687 if (ast_strlen_zero(exten)) 03688 exten = NULL; 03689 } else { /* no '@' char, only context given */ 03690 context = argv[2]; 03691 } 03692 if (ast_strlen_zero(context)) 03693 context = NULL; 03694 } 03695 /* else Show complete dial plan, context and exten are NULL */ 03696 show_dialplan_helper(fd, context, exten, &counters, NULL, 0, incstack); 03697 03698 /* check for input failure and throw some error messages */ 03699 if (context && !counters.context_existence) { 03700 ast_cli(fd, "There is no existence of '%s' context\n", context); 03701 return RESULT_FAILURE; 03702 } 03703 03704 if (exten && !counters.extension_existence) { 03705 if (context) 03706 ast_cli(fd, "There is no existence of %s@%s extension\n", 03707 exten, context); 03708 else 03709 ast_cli(fd, 03710 "There is no existence of '%s' extension in all contexts\n", 03711 exten); 03712 return RESULT_FAILURE; 03713 } 03714 03715 ast_cli(fd,"-= %d %s (%d %s) in %d %s. =-\n", 03716 counters.total_exten, counters.total_exten == 1 ? "extension" : "extensions", 03717 counters.total_prio, counters.total_prio == 1 ? "priority" : "priorities", 03718 counters.total_context, counters.total_context == 1 ? "context" : "contexts"); 03719 03720 /* everything ok */ 03721 return RESULT_SUCCESS; 03722 }
static int handle_show_function | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1378 of file pbx.c.
References ast_cli(), ast_custom_function_find(), AST_MAX_APP, COLOR_CYAN, COLOR_MAGENTA, ast_custom_function::desc, ast_custom_function::name, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, ast_custom_function::synopsis, ast_custom_function::syntax, and term_color().
01379 { 01380 struct ast_custom_function *acf; 01381 /* Maximum number of characters added by terminal coloring is 22 */ 01382 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40]; 01383 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL; 01384 char stxtitle[40], *syntax = NULL; 01385 int synopsis_size, description_size, syntax_size; 01386 01387 if (argc < 4) 01388 return RESULT_SHOWUSAGE; 01389 01390 if (!(acf = ast_custom_function_find(argv[3]))) { 01391 ast_cli(fd, "No function by that name registered.\n"); 01392 return RESULT_FAILURE; 01393 01394 } 01395 01396 if (acf->synopsis) 01397 synopsis_size = strlen(acf->synopsis) + 23; 01398 else 01399 synopsis_size = strlen("Not available") + 23; 01400 synopsis = alloca(synopsis_size); 01401 01402 if (acf->desc) 01403 description_size = strlen(acf->desc) + 23; 01404 else 01405 description_size = strlen("Not available") + 23; 01406 description = alloca(description_size); 01407 01408 if (acf->syntax) 01409 syntax_size = strlen(acf->syntax) + 23; 01410 else 01411 syntax_size = strlen("Not available") + 23; 01412 syntax = alloca(syntax_size); 01413 01414 snprintf(info, 64 + AST_MAX_APP, "\n -= Info about function '%s' =- \n\n", acf->name); 01415 term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22); 01416 term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40); 01417 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 01418 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40); 01419 term_color(syntax, 01420 acf->syntax ? acf->syntax : "Not available", 01421 COLOR_CYAN, 0, syntax_size); 01422 term_color(synopsis, 01423 acf->synopsis ? acf->synopsis : "Not available", 01424 COLOR_CYAN, 0, synopsis_size); 01425 term_color(description, 01426 acf->desc ? acf->desc : "Not available", 01427 COLOR_CYAN, 0, description_size); 01428 01429 ast_cli(fd,"%s%s%s\n\n%s%s\n\n%s%s\n", infotitle, stxtitle, syntax, syntitle, synopsis, destitle, description); 01430 01431 return RESULT_SUCCESS; 01432 }
static int handle_show_function_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1322 of file pbx.c.
References ast_cli(), ast_custom_function_find(), AST_MAX_APP, COLOR_CYAN, COLOR_MAGENTA, ast_custom_function::desc, ast_custom_function::name, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, ast_custom_function::synopsis, ast_custom_function::syntax, and term_color().
01323 { 01324 struct ast_custom_function *acf; 01325 /* Maximum number of characters added by terminal coloring is 22 */ 01326 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40]; 01327 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL; 01328 char stxtitle[40], *syntax = NULL; 01329 int synopsis_size, description_size, syntax_size; 01330 01331 if (argc < 3) 01332 return RESULT_SHOWUSAGE; 01333 01334 if (!(acf = ast_custom_function_find(argv[2]))) { 01335 ast_cli(fd, "No function by that name registered.\n"); 01336 return RESULT_FAILURE; 01337 01338 } 01339 01340 if (acf->synopsis) 01341 synopsis_size = strlen(acf->synopsis) + 23; 01342 else 01343 synopsis_size = strlen("Not available") + 23; 01344 synopsis = alloca(synopsis_size); 01345 01346 if (acf->desc) 01347 description_size = strlen(acf->desc) + 23; 01348 else 01349 description_size = strlen("Not available") + 23; 01350 description = alloca(description_size); 01351 01352 if (acf->syntax) 01353 syntax_size = strlen(acf->syntax) + 23; 01354 else 01355 syntax_size = strlen("Not available") + 23; 01356 syntax = alloca(syntax_size); 01357 01358 snprintf(info, 64 + AST_MAX_APP, "\n -= Info about function '%s' =- \n\n", acf->name); 01359 term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22); 01360 term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40); 01361 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 01362 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40); 01363 term_color(syntax, 01364 acf->syntax ? acf->syntax : "Not available", 01365 COLOR_CYAN, 0, syntax_size); 01366 term_color(synopsis, 01367 acf->synopsis ? acf->synopsis : "Not available", 01368 COLOR_CYAN, 0, synopsis_size); 01369 term_color(description, 01370 acf->desc ? acf->desc : "Not available", 01371 COLOR_CYAN, 0, description_size); 01372 01373 ast_cli(fd,"%s%s%s\n\n%s%s\n\n%s%s\n", infotitle, stxtitle, syntax, syntitle, synopsis, destitle, description); 01374 01375 return RESULT_SUCCESS; 01376 }
static int handle_show_functions | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1294 of file pbx.c.
References ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_custom_function::name, RESULT_SHOWUSAGE, RESULT_SUCCESS, ast_custom_function::synopsis, and ast_custom_function::syntax.
01295 { 01296 struct ast_custom_function *acf; 01297 int count_acf = 0; 01298 int like = 0; 01299 01300 if (argc == 5 && (!strcmp(argv[3], "like")) ) { 01301 like = 1; 01302 } else if (argc != 3) { 01303 return RESULT_SHOWUSAGE; 01304 } 01305 01306 ast_cli(fd, "%s Custom Functions:\n--------------------------------------------------------------------------------\n", like ? "Matching" : "Installed"); 01307 01308 AST_LIST_LOCK(&acf_root); 01309 AST_LIST_TRAVERSE(&acf_root, acf, acflist) { 01310 if (!like || strstr(acf->name, argv[4])) { 01311 count_acf++; 01312 ast_cli(fd, "%-20.20s %-35.35s %s\n", acf->name, acf->syntax, acf->synopsis); 01313 } 01314 } 01315 AST_LIST_UNLOCK(&acf_root); 01316 01317 ast_cli(fd, "%d %scustom functions installed.\n", count_acf, like ? "matching " : ""); 01318 01319 return RESULT_SUCCESS; 01320 }
static int handle_show_functions_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1267 of file pbx.c.
References ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_custom_function::name, RESULT_SHOWUSAGE, RESULT_SUCCESS, ast_custom_function::synopsis, and ast_custom_function::syntax.
01268 { 01269 struct ast_custom_function *acf; 01270 int count_acf = 0; 01271 int like = 0; 01272 01273 if (argc == 4 && (!strcmp(argv[2], "like")) ) { 01274 like = 1; 01275 } else if (argc != 2) { 01276 return RESULT_SHOWUSAGE; 01277 } 01278 01279 ast_cli(fd, "%s Custom Functions:\n--------------------------------------------------------------------------------\n", like ? "Matching" : "Installed"); 01280 01281 AST_LIST_LOCK(&acf_root); 01282 AST_LIST_TRAVERSE(&acf_root, acf, acflist) { 01283 if (!like || strstr(acf->name, argv[3])) { 01284 count_acf++; 01285 ast_cli(fd, "%-20.20s %-35.35s %s\n", acf->name, acf->syntax, acf->synopsis); 01286 } 01287 } 01288 AST_LIST_UNLOCK(&acf_root); 01289 01290 ast_cli(fd, "%d %scustom functions installed.\n", count_acf, like ? "matching " : ""); 01291 01292 return RESULT_SUCCESS; 01293 }
static int handle_show_globals | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
CLI support for listing global variables in a parseable way.
Definition at line 3725 of file pbx.c.
References ast_cli(), AST_LIST_TRAVERSE, ast_mutex_lock(), ast_mutex_unlock(), ast_var_name(), ast_var_value(), and RESULT_SUCCESS.
03726 { 03727 int i = 0; 03728 struct ast_var_t *newvariable; 03729 03730 ast_mutex_lock(&globalslock); 03731 AST_LIST_TRAVERSE (&globals, newvariable, entries) { 03732 i++; 03733 ast_cli(fd, " %s=%s\n", ast_var_name(newvariable), ast_var_value(newvariable)); 03734 } 03735 ast_mutex_unlock(&globalslock); 03736 ast_cli(fd, "\n -- %d variables\n", i); 03737 03738 return RESULT_SUCCESS; 03739 }
static int handle_show_hints | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
handle_show_hints: CLI support for listing registred dial plan hints
Definition at line 3259 of file pbx.c.
References ast_cli(), ast_extension_state2str(), ast_get_context_name(), ast_get_extension_app(), ast_get_extension_context(), ast_get_extension_name(), AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_hint::callbacks, ast_hint::exten, ast_hint::laststate, ast_state_cb::next, and RESULT_SUCCESS.
03260 { 03261 struct ast_hint *hint; 03262 int num = 0; 03263 int watchers; 03264 struct ast_state_cb *watcher; 03265 03266 if (AST_LIST_EMPTY(&hints)) { 03267 ast_cli(fd, "There are no registered dialplan hints\n"); 03268 return RESULT_SUCCESS; 03269 } 03270 /* ... we have hints ... */ 03271 ast_cli(fd, "\n -= Registered Asterisk Dial Plan Hints =-\n"); 03272 AST_LIST_LOCK(&hints); 03273 AST_LIST_TRAVERSE(&hints, hint, list) { 03274 watchers = 0; 03275 for (watcher = hint->callbacks; watcher; watcher = watcher->next) 03276 watchers++; 03277 ast_cli(fd, " %20s@%-20.20s: %-20.20s State:%-15.15s Watchers %2d\n", 03278 ast_get_extension_name(hint->exten), 03279 ast_get_context_name(ast_get_extension_context(hint->exten)), 03280 ast_get_extension_app(hint->exten), 03281 ast_extension_state2str(hint->laststate), watchers); 03282 num++; 03283 } 03284 ast_cli(fd, "----------------\n"); 03285 ast_cli(fd, "- %d hints registered\n", num); 03286 AST_LIST_UNLOCK(&hints); 03287 return RESULT_SUCCESS; 03288 }
static int handle_show_switches | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
handle_show_switches: CLI support for listing registred dial plan switches
Definition at line 3291 of file pbx.c.
References ast_cli(), AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_switch::description, ast_switch::name, and RESULT_SUCCESS.
03292 { 03293 struct ast_switch *sw; 03294 03295 AST_LIST_LOCK(&switches); 03296 03297 if (AST_LIST_EMPTY(&switches)) { 03298 AST_LIST_UNLOCK(&switches); 03299 ast_cli(fd, "There are no registered alternative switches\n"); 03300 return RESULT_SUCCESS; 03301 } 03302 03303 ast_cli(fd, "\n -= Registered Asterisk Alternative Switches =-\n"); 03304 AST_LIST_TRAVERSE(&switches, sw, list) 03305 ast_cli(fd, "%s: %s\n", sw->name, sw->description); 03306 03307 AST_LIST_UNLOCK(&switches); 03308 03309 return RESULT_SUCCESS; 03310 }
static int include_valid | ( | struct ast_include * | i | ) | [inline, static] |
Definition at line 581 of file pbx.c.
References ast_check_timing(), ast_include::hastime, and ast_include::timing.
00582 { 00583 if (!i->hastime) 00584 return 1; 00585 00586 return ast_check_timing(&(i->timing)); 00587 }
static int increase_call_count | ( | const struct ast_channel * | c | ) | [static] |
Definition at line 2581 of file pbx.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), countcalls, getloadavg(), LOG_NOTICE, option_maxcalls, and option_maxload.
Referenced by ast_pbx_run(), and ast_pbx_start().
02582 { 02583 int failed = 0; 02584 double curloadavg; 02585 ast_mutex_lock(&maxcalllock); 02586 if (option_maxcalls) { 02587 if (countcalls >= option_maxcalls) { 02588 ast_log(LOG_NOTICE, "Maximum call limit of %d calls exceeded by '%s'!\n", option_maxcalls, c->name); 02589 failed = -1; 02590 } 02591 } 02592 if (option_maxload) { 02593 getloadavg(&curloadavg, 1); 02594 if (curloadavg >= option_maxload) { 02595 ast_log(LOG_NOTICE, "Maximum loadavg limit of %f load exceeded by '%s' (currently %f)!\n", option_maxload, c->name, curloadavg); 02596 failed = -1; 02597 } 02598 } 02599 if (!failed) 02600 countcalls++; 02601 ast_mutex_unlock(&maxcalllock); 02602 02603 return failed; 02604 }
int load_pbx | ( | void | ) |
Provided by pbx.c
Definition at line 6137 of file pbx.c.
References ast_cli_register_multiple(), ast_log(), ast_register_application(), ast_verbose(), builtins, LOG_ERROR, option_verbose, pbx_cli, and VERBOSE_PREFIX_1.
Referenced by main().
06138 { 06139 int x; 06140 06141 /* Initialize the PBX */ 06142 if (option_verbose) { 06143 ast_verbose( "Asterisk PBX Core Initializing\n"); 06144 ast_verbose( "Registering builtin applications:\n"); 06145 } 06146 ast_cli_register_multiple(pbx_cli, sizeof(pbx_cli) / sizeof(struct ast_cli_entry)); 06147 06148 /* Register builtin applications */ 06149 for (x=0; x<sizeof(builtins) / sizeof(struct pbx_builtin); x++) { 06150 if (option_verbose) 06151 ast_verbose( VERBOSE_PREFIX_1 "[%s]\n", builtins[x].name); 06152 if (ast_register_application(builtins[x].name, builtins[x].execute, builtins[x].synopsis, builtins[x].description)) { 06153 ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name); 06154 return -1; 06155 } 06156 } 06157 return 0; 06158 }
static int lookup_name | ( | const char * | s, | |
char *const | names[], | |||
int | max | |||
) | [static] |
Helper for get_range. return the index of the matching entry, starting from 1. If names is not supplied, try numeric values.
Definition at line 4065 of file pbx.c.
Referenced by get_range().
04066 { 04067 int i; 04068 04069 if (names) { 04070 for (i = 0; names[i]; i++) { 04071 if (!strcasecmp(s, names[i])) 04072 return i+1; 04073 } 04074 } else if (sscanf(s, "%d", &i) == 1 && i >= 1 && i <= max) { 04075 return i; 04076 } 04077 return 0; /* error return */ 04078 }
static int matchcid | ( | const char * | cidpattern, | |
const char * | callerid | |||
) | [static] |
Definition at line 917 of file pbx.c.
References ast_extension_match(), and ast_strlen_zero().
Referenced by pbx_find_extension().
00918 { 00919 /* If the Caller*ID pattern is empty, then we're matching NO Caller*ID, so 00920 failing to get a number should count as a match, otherwise not */ 00921 00922 if (ast_strlen_zero(callerid)) 00923 return ast_strlen_zero(cidpattern) ? 1 : 0; 00924 00925 return ast_extension_match(cidpattern, callerid); 00926 }
static int parse_variable_name | ( | char * | var, | |
int * | offset, | |||
int * | length, | |||
int * | isfunc | |||
) | [static] |
extract offset:length from variable name. Returns 1 if there is a offset:length part, which is trimmed off (values go into variables)
Definition at line 1083 of file pbx.c.
Referenced by pbx_retrieve_variable(), and pbx_substitute_variables_helper_full().
01084 { 01085 int parens=0; 01086 01087 *offset = 0; 01088 *length = INT_MAX; 01089 *isfunc = 0; 01090 for (; *var; var++) { 01091 if (*var == '(') { 01092 (*isfunc)++; 01093 parens++; 01094 } else if (*var == ')') { 01095 parens--; 01096 } else if (*var == ':' && parens == 0) { 01097 *var++ = '\0'; 01098 sscanf(var, "%d:%d", offset, length); 01099 return 1; /* offset:length valid */ 01100 } 01101 } 01102 return 0; 01103 }
void pbx_builtin_clear_globals | ( | void | ) |
Definition at line 6019 of file pbx.c.
References AST_LIST_REMOVE_HEAD, ast_mutex_lock(), ast_mutex_unlock(), and ast_var_delete().
Referenced by handle_reload_extensions(), and reload().
06020 { 06021 struct ast_var_t *vardata; 06022 06023 ast_mutex_lock(&globalslock); 06024 while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries))) 06025 ast_var_delete(vardata); 06026 ast_mutex_unlock(&globalslock); 06027 }
const char* pbx_builtin_getvar_helper | ( | struct ast_channel * | chan, | |
const char * | name | |||
) |
Definition at line 5796 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, AST_LIST_TRAVERSE, ast_mutex_lock(), ast_mutex_unlock(), ast_var_name(), and ast_var_value().
Referenced by __login_exec(), _macro_exec(), _while_exec(), agent_hangup(), agent_read(), agentmonitoroutgoing_exec(), ast_bridge_call(), ast_channel_bridge(), ast_feature_interpret(), ast_monitor_stop(), builtin_automonitor(), check_goto_on_transfer(), common_exec(), conf_exec(), conf_run(), dundi_exec(), dundi_helper(), get_also_info(), get_index(), get_refer_info(), global_read(), iax2_exec(), import_ch(), leave_voicemail(), local_hangup(), misdn_answer(), misdn_hangup(), morsecode_exec(), notify_new_message(), oh323_call(), oh323_hangup(), park_call_full(), pickup_by_mark(), queue_exec(), real_ctx(), retrydial_exec(), return_exec(), ring_entry(), set_config_flags(), sip_addheader(), sla_trunk_exec(), speech_background(), try_calling(), try_suggested_sip_codec(), wait_for_answer(), zt_call(), and zt_hangup().
05797 { 05798 struct ast_var_t *variables; 05799 const char *ret = NULL; 05800 int i; 05801 struct varshead *places[2] = { NULL, &globals }; 05802 05803 if (!name) 05804 return NULL; 05805 05806 if (chan) { 05807 ast_channel_lock(chan); 05808 places[0] = &chan->varshead; 05809 } 05810 05811 for (i = 0; i < 2; i++) { 05812 if (!places[i]) 05813 continue; 05814 if (places[i] == &globals) 05815 ast_mutex_lock(&globalslock); 05816 AST_LIST_TRAVERSE(places[i], variables, entries) { 05817 if (!strcmp(name, ast_var_name(variables))) { 05818 ret = ast_var_value(variables); 05819 break; 05820 } 05821 } 05822 if (places[i] == &globals) 05823 ast_mutex_unlock(&globalslock); 05824 if (ret) 05825 break; 05826 } 05827 05828 if (chan) 05829 ast_channel_unlock(chan); 05830 05831 return ret; 05832 }
static int pbx_builtin_gotoif | ( | struct ast_channel * | , | |
void * | ||||
) | [static] |
Definition at line 6039 of file pbx.c.
References ast_log(), ast_strdupa, ast_strlen_zero(), LOG_WARNING, pbx_builtin_goto(), pbx_checkcondition(), and strsep().
06040 { 06041 char *condition, *branch1, *branch2, *branch; 06042 int rc; 06043 char *stringp; 06044 06045 if (ast_strlen_zero(data)) { 06046 ast_log(LOG_WARNING, "Ignoring, since there is no variable to check\n"); 06047 return 0; 06048 } 06049 06050 stringp = ast_strdupa(data); 06051 condition = strsep(&stringp,"?"); 06052 branch1 = strsep(&stringp,":"); 06053 branch2 = strsep(&stringp,""); 06054 branch = pbx_checkcondition(condition) ? branch1 : branch2; 06055 06056 if (ast_strlen_zero(branch)) { 06057 if (option_debug) 06058 ast_log(LOG_DEBUG, "Not taking any branch\n"); 06059 return 0; 06060 } 06061 06062 rc = pbx_builtin_goto(chan, branch); 06063 06064 return rc; 06065 }
int pbx_builtin_importvar | ( | struct ast_channel * | , | |
void * | ||||
) | [static] |
Definition at line 5958 of file pbx.c.
References ast_channel_unlock, ast_get_channel_by_name_locked(), ast_log(), ast_strdupa, ast_strlen_zero(), LOG_WARNING, pbx_builtin_setvar_helper(), pbx_substitute_variables_helper(), s, strsep(), and VAR_BUF_SIZE.
05959 { 05960 char *name; 05961 char *value; 05962 char *channel; 05963 char tmp[VAR_BUF_SIZE]=""; 05964 05965 if (ast_strlen_zero(data)) { 05966 ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n"); 05967 return 0; 05968 } 05969 05970 value = ast_strdupa(data); 05971 name = strsep(&value,"="); 05972 channel = strsep(&value,"|"); 05973 if (channel && value && name) { /*! \todo XXX should do !ast_strlen_zero(..) of the args ? */ 05974 struct ast_channel *chan2 = ast_get_channel_by_name_locked(channel); 05975 if (chan2) { 05976 char *s = alloca(strlen(value) + 4); 05977 if (s) { 05978 sprintf(s, "${%s}", value); 05979 pbx_substitute_variables_helper(chan2, s, tmp, sizeof(tmp) - 1); 05980 } 05981 ast_channel_unlock(chan2); 05982 } 05983 pbx_builtin_setvar_helper(chan, name, tmp); 05984 } 05985 05986 return(0); 05987 }
static int pbx_builtin_noop | ( | struct ast_channel * | , | |
void * | ||||
) | [static] |
void pbx_builtin_pushvar_helper | ( | struct ast_channel * | chan, | |
const char * | name, | |||
const char * | value | |||
) |
Definition at line 5834 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, ast_func_write(), AST_LIST_INSERT_HEAD, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_strdupa, ast_var_assign(), ast_verbose(), LOG_WARNING, option_verbose, and VERBOSE_PREFIX_2.
Referenced by acf_odbc_read(), acf_odbc_write(), and gosub_exec().
05835 { 05836 struct ast_var_t *newvariable; 05837 struct varshead *headp; 05838 05839 if (name[strlen(name)-1] == ')') { 05840 char *function = ast_strdupa(name); 05841 05842 ast_log(LOG_WARNING, "Cannot push a value onto a function\n"); 05843 ast_func_write(chan, function, value); 05844 return; 05845 } 05846 05847 if (chan) { 05848 ast_channel_lock(chan); 05849 headp = &chan->varshead; 05850 } else { 05851 ast_mutex_lock(&globalslock); 05852 headp = &globals; 05853 } 05854 05855 if (value) { 05856 if ((option_verbose > 1) && (headp == &globals)) 05857 ast_verbose(VERBOSE_PREFIX_2 "Setting global variable '%s' to '%s'\n", name, value); 05858 newvariable = ast_var_assign(name, value); 05859 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 05860 } 05861 05862 if (chan) 05863 ast_channel_unlock(chan); 05864 else 05865 ast_mutex_unlock(&globalslock); 05866 }
static int pbx_builtin_saycharacters | ( | struct ast_channel * | , | |
void * | ||||
) | [static] |
Definition at line 6111 of file pbx.c.
References ast_channel::_state, ast_answer(), ast_say_character_str(), and AST_STATE_UP.
06112 { 06113 int res = 0; 06114 06115 if (data) { 06116 if (chan->_state != AST_STATE_UP) { 06117 ast_answer(chan); 06118 } 06119 res = ast_say_character_str(chan, data, "", chan->language); 06120 } 06121 return res; 06122 }
static int pbx_builtin_saydigits | ( | struct ast_channel * | , | |
void * | ||||
) | [static] |
Definition at line 6098 of file pbx.c.
References ast_channel::_state, ast_answer(), ast_say_digit_str(), and AST_STATE_UP.
06099 { 06100 int res = 0; 06101 06102 if (data) { 06103 if (chan->_state != AST_STATE_UP) { 06104 ast_answer(chan); 06105 } 06106 res = ast_say_digit_str(chan, data, "", chan->language); 06107 } 06108 return res; 06109 }
static int pbx_builtin_saynumber | ( | struct ast_channel * | , | |
void * | ||||
) | [static] |
Definition at line 6067 of file pbx.c.
References ast_channel::_state, ast_answer(), ast_log(), ast_say_number(), AST_STATE_UP, ast_strlen_zero(), LOG_WARNING, and strsep().
06068 { 06069 char tmp[256]; 06070 char *number = tmp; 06071 char *options; 06072 06073 if (ast_strlen_zero(data)) { 06074 ast_log(LOG_WARNING, "SayNumber requires an argument (number)\n"); 06075 return -1; 06076 } 06077 ast_copy_string(tmp, data, sizeof(tmp)); 06078 strsep(&number, "|"); 06079 options = strsep(&number, "|"); 06080 if (options) { 06081 if ( strcasecmp(options, "f") && strcasecmp(options,"m") && 06082 strcasecmp(options, "c") && strcasecmp(options, "n") ) { 06083 ast_log(LOG_WARNING, "SayNumber gender option is either 'f', 'm', 'c' or 'n'\n"); 06084 return -1; 06085 } 06086 } 06087 if (chan->_state != AST_STATE_UP) { 06088 ast_answer(chan); 06089 } 06090 06091 if (ast_say_number(chan, atoi(tmp), "", chan->language, options)) { 06092 ast_log(LOG_WARNING, "We were unable to say the number %s, is it too large?\n", tmp); 06093 } 06094 06095 return 0; 06096 }
static int pbx_builtin_sayphonetic | ( | struct ast_channel * | , | |
void * | ||||
) | [static] |
Definition at line 6124 of file pbx.c.
References ast_channel::_state, ast_answer(), ast_say_phonetic_str(), and AST_STATE_UP.
06125 { 06126 int res = 0; 06127 06128 if (data) { 06129 if (chan->_state != AST_STATE_UP) { 06130 ast_answer(chan); 06131 } 06132 res = ast_say_phonetic_str(chan, data, "", chan->language); 06133 } 06134 return res; 06135 }
int pbx_builtin_serialize_variables | ( | struct ast_channel * | chan, | |
char * | buf, | |||
size_t | size | |||
) |
Definition at line 5765 of file pbx.c.
References ast_build_string(), ast_channel_lock, ast_channel_unlock, AST_LIST_TRAVERSE, ast_log(), ast_var_name(), ast_var_value(), LOG_ERROR, total, var, and ast_channel::varshead.
Referenced by dumpchan_exec(), handle_showchan(), handle_showchan_deprecated(), and vars2manager().
05766 { 05767 struct ast_var_t *variables; 05768 const char *var, *val; 05769 int total = 0; 05770 05771 if (!chan) 05772 return 0; 05773 05774 memset(buf, 0, size); 05775 05776 ast_channel_lock(chan); 05777 05778 AST_LIST_TRAVERSE(&chan->varshead, variables, entries) { 05779 if ((var=ast_var_name(variables)) && (val=ast_var_value(variables)) 05780 /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */ 05781 ) { 05782 if (ast_build_string(&buf, &size, "%s=%s\n", var, val)) { 05783 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n"); 05784 break; 05785 } else 05786 total++; 05787 } else 05788 break; 05789 } 05790 05791 ast_channel_unlock(chan); 05792 05793 return total; 05794 }
static int pbx_builtin_setglobalvar | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 5990 of file pbx.c.
References ast_log(), ast_strlen_zero(), LOG_WARNING, pbx_builtin_setvar_helper(), and strsep().
05991 { 05992 char *name; 05993 char *stringp = data; 05994 static int dep_warning = 0; 05995 05996 if (ast_strlen_zero(data)) { 05997 ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n"); 05998 return 0; 05999 } 06000 06001 name = strsep(&stringp, "="); 06002 06003 if (!dep_warning) { 06004 dep_warning = 1; 06005 ast_log(LOG_WARNING, "SetGlobalVar is deprecated. Please use Set(GLOBAL(%s)=%s) instead.\n", name, stringp); 06006 } 06007 06008 /*! \todo XXX watch out, leading whitespace ? */ 06009 pbx_builtin_setvar_helper(NULL, name, stringp); 06010 06011 return(0); 06012 }
int pbx_builtin_setvar | ( | struct ast_channel * | , | |
void * | ||||
) |
Definition at line 5918 of file pbx.c.
References ast_app_separate_args(), ast_log(), ast_strdupa, ast_strlen_zero(), LOG_WARNING, and pbx_builtin_setvar_helper().
Referenced by ast_compile_ael2().
05919 { 05920 char *name, *value, *mydata; 05921 int argc; 05922 char *argv[24]; /* this will only support a maximum of 24 variables being set in a single operation */ 05923 int global = 0; 05924 int x; 05925 05926 if (ast_strlen_zero(data)) { 05927 ast_log(LOG_WARNING, "Set requires at least one variable name/value pair.\n"); 05928 return 0; 05929 } 05930 05931 mydata = ast_strdupa(data); 05932 argc = ast_app_separate_args(mydata, '|', argv, sizeof(argv) / sizeof(argv[0])); 05933 05934 /* check for a trailing flags argument */ 05935 if ((argc > 1) && !strchr(argv[argc-1], '=')) { 05936 argc--; 05937 if (strchr(argv[argc], 'g')) { 05938 ast_log(LOG_WARNING, "The use of the 'g' flag is deprecated. Please use Set(GLOBAL(foo)=bar) instead\n"); 05939 global = 1; 05940 } 05941 } 05942 05943 if (argc > 1) 05944 ast_log(LOG_WARNING, "Setting multiple variables at once within Set is deprecated. Please separate each name/value pair into its own line.\n"); 05945 05946 for (x = 0; x < argc; x++) { 05947 name = argv[x]; 05948 if ((value = strchr(name, '='))) { 05949 *value++ = '\0'; 05950 pbx_builtin_setvar_helper((global) ? NULL : chan, name, value); 05951 } else 05952 ast_log(LOG_WARNING, "Ignoring entry '%s' with no = (and not last 'options' entry)\n", name); 05953 } 05954 05955 return(0); 05956 }
void pbx_builtin_setvar_helper | ( | struct ast_channel * | chan, | |
const char * | name, | |||
const char * | value | |||
) |
Definition at line 5868 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_mutex_lock(), ast_mutex_unlock(), ast_strdupa, ast_var_assign(), ast_var_delete(), ast_var_name(), ast_verbose(), option_verbose, and VERBOSE_PREFIX_2.
Referenced by __oh323_new(), _macro_exec(), _while_exec(), acf_odbc_read(), acf_odbc_write(), action_setvar(), agi_exec_full(), aji_status_exec(), app_exec(), aqm_exec(), array(), ast_bridge_call(), ast_channel_bridge(), ast_feature_request_and_dial(), ast_iax2_new(), ast_monitor_start(), ast_pbx_outgoing_exten_uniqueid(), ast_set_variables(), background_detect_exec(), bridge_exec(), builtin_automonitor(), builtin_blindtransfer(), cb_events(), chanavail_exec(), controlplayback_exec(), count_exec(), disa_exec(), do_waiting(), export_aoc_vars(), export_ch(), function_db_delete(), function_db_exists(), function_db_read(), global_write(), handle_request_bye(), handle_request_refer(), handle_set_global(), handle_set_global_deprecated(), handle_setvariable(), hasvoicemail_exec(), isAnsweringMachine(), leave_voicemail(), local_hangup(), lookupblacklist_exec(), misdn_call(), mixmonitor_exec(), ospauth_exec(), ospfinished_exec(), osplookup_exec(), ospnext_exec(), park_exec(), parse_moved_contact(), pbx_builtin_importvar(), pbx_builtin_setglobalvar(), pbx_builtin_setvar(), pbx_load_config(), play_message_datetime(), playback_exec(), pop_exec(), pqm_exec(), prep_email_sub_vars(), privacy_exec(), process_ast_dsp(), read_exec(), readfile_exec(), realtime_exec(), realtime_update_exec(), record_exec(), return_exec(), rqm_exec(), sendimage_exec(), sendtext_exec(), sendurl_exec(), set(), set_agentbycallerid(), set_queue_result(), sip_addheader(), sip_hangup(), sip_new(), sla_calc_trunk_timeouts(), sla_station_exec(), sla_trunk_exec(), socket_process(), speech_create(), ss_thread(), start_monitor_exec(), system_exec_helper(), transfer_exec(), try_calling(), tryexec_exec(), upqm_exec(), vm_box_exists(), vm_exec(), vmauthenticate(), zt_handle_dtmfup(), and zt_new().
05869 { 05870 struct ast_var_t *newvariable; 05871 struct varshead *headp; 05872 const char *nametail = name; 05873 05874 if (name[strlen(name)-1] == ')') { 05875 char *function = ast_strdupa(name); 05876 05877 ast_func_write(chan, function, value); 05878 return; 05879 } 05880 05881 if (chan) { 05882 ast_channel_lock(chan); 05883 headp = &chan->varshead; 05884 } else { 05885 ast_mutex_lock(&globalslock); 05886 headp = &globals; 05887 } 05888 05889 /* For comparison purposes, we have to strip leading underscores */ 05890 if (*nametail == '_') { 05891 nametail++; 05892 if (*nametail == '_') 05893 nametail++; 05894 } 05895 05896 AST_LIST_TRAVERSE (headp, newvariable, entries) { 05897 if (strcasecmp(ast_var_name(newvariable), nametail) == 0) { 05898 /* there is already such a variable, delete it */ 05899 AST_LIST_REMOVE(headp, newvariable, entries); 05900 ast_var_delete(newvariable); 05901 break; 05902 } 05903 } 05904 05905 if (value) { 05906 if ((option_verbose > 1) && (headp == &globals)) 05907 ast_verbose(VERBOSE_PREFIX_2 "Setting global variable '%s' to '%s'\n", name, value); 05908 newvariable = ast_var_assign(name, value); 05909 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 05910 } 05911 05912 if (chan) 05913 ast_channel_unlock(chan); 05914 else 05915 ast_mutex_unlock(&globalslock); 05916 }
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 6029 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().
06030 { 06031 if (ast_strlen_zero(condition)) /* NULL or empty strings are false */ 06032 return 0; 06033 else if (*condition >= '0' && *condition <= '9') /* Numbers are evaluated for truth */ 06034 return atoi(condition); 06035 else /* Strings are true */ 06036 return 1; 06037 }
static void pbx_destroy | ( | struct ast_pbx * | p | ) | [static] |
int pbx_exec | ( | struct ast_channel * | c, | |
struct ast_app * | app, | |||
void * | data | |||
) |
Execute an application.
c | channel to execute on | |
app | which app to execute | |
data | the data passed into the app |
c | Channel |
app | Application |
data | Data for execution |
Definition at line 515 of file pbx.c.
References app, ast_channel::appl, ast_cdr_setapp(), ast_check_hangup(), ast_channel::cdr, ast_channel::data, and S_OR.
Referenced by answer_exec_run(), ast_bridge_call(), ast_pbx_run_app(), async_wait(), builtin_automonitor(), conf_run(), dundi_exec(), exec_exec(), execif_exec(), feature_exec_app(), forward_message(), handle_exec(), iax2_exec(), milliwatt_exec(), page_exec(), pbx_builtin_execiftime(), pbx_extension_helper(), realtime_exec(), try_calling(), and tryexec_exec().
00518 { 00519 int res; 00520 00521 const char *saved_c_appl; 00522 const char *saved_c_data; 00523 00524 if (c->cdr && !ast_check_hangup(c)) 00525 ast_cdr_setapp(c->cdr, app->name, data); 00526 00527 /* save channel values */ 00528 saved_c_appl= c->appl; 00529 saved_c_data= c->data; 00530 00531 c->appl = app->name; 00532 c->data = data; 00533 /* XXX remember what to to when we have linked apps to modules */ 00534 if (app->module) { 00535 /* XXX LOCAL_USER_ADD(app->module) */ 00536 } 00537 res = app->execute(c, S_OR(data, "")); 00538 if (app->module) { 00539 /* XXX LOCAL_USER_REMOVE(app->module) */ 00540 } 00541 /* restore channel values */ 00542 c->appl = saved_c_appl; 00543 c->data = saved_c_data; 00544 return res; 00545 }
static int pbx_extension_helper | ( | struct ast_channel * | c, | |
struct ast_context * | con, | |||
const char * | context, | |||
const char * | exten, | |||
int | priority, | |||
const char * | label, | |||
const char * | callerid, | |||
enum ext_match_t | action | |||
) | [static] |
The return value depends on the action:.
E_MATCH, E_CANMATCH, E_MATCHMORE require a real match, and return 0 on failure, -1 on match; E_FINDLABEL maps the label to a priority, and returns the priority on success, ... XXX E_SPAWN, spawn an application, and return 0 on success, -1 on failure.
Definition at line 1806 of file pbx.c.
References ast_exten::app, app, ast_log(), ast_rdlock_contexts(), ast_unlock_contexts(), ast_verbose(), COLOR_BRCYAN, COLOR_BRMAGENTA, ast_channel::context, pbx_find_info::data, E_CANMATCH, E_FINDLABEL, E_MATCH, E_MATCHMORE, EVENT_FLAG_CALL, ast_switch::exec, EXT_DATA_SIZE, ast_channel::exten, pbx_find_info::foundcontext, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, manager_event(), ast_switch::name, option_debug, option_verbose, pbx_exec(), pbx_find_extension(), pbx_findapp(), pbx_substitute_variables(), ast_channel::priority, ast_exten::priority, pbx_find_info::stacklen, pbx_find_info::status, STATUS_NO_CONTEXT, STATUS_NO_EXTENSION, STATUS_NO_LABEL, STATUS_NO_PRIORITY, pbx_find_info::swo, term_color(), and VERBOSE_PREFIX_3.
Referenced by ast_canmatch_extension(), ast_exists_extension(), ast_findlabel_extension(), ast_findlabel_extension2(), ast_matchmore_extension(), and ast_spawn_extension().
01809 { 01810 struct ast_exten *e; 01811 struct ast_app *app; 01812 int res; 01813 struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */ 01814 char passdata[EXT_DATA_SIZE]; 01815 01816 int matching_action = (action == E_MATCH || action == E_CANMATCH || action == E_MATCHMORE); 01817 01818 ast_rdlock_contexts(); 01819 e = pbx_find_extension(c, con, &q, context, exten, priority, label, callerid, action); 01820 if (e) { 01821 if (matching_action) { 01822 ast_unlock_contexts(); 01823 return -1; /* success, we found it */ 01824 } else if (action == E_FINDLABEL) { /* map the label to a priority */ 01825 res = e->priority; 01826 ast_unlock_contexts(); 01827 return res; /* the priority we were looking for */ 01828 } else { /* spawn */ 01829 app = pbx_findapp(e->app); 01830 ast_unlock_contexts(); 01831 if (!app) { 01832 ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority); 01833 return -1; 01834 } 01835 if (c->context != context) 01836 ast_copy_string(c->context, context, sizeof(c->context)); 01837 if (c->exten != exten) 01838 ast_copy_string(c->exten, exten, sizeof(c->exten)); 01839 c->priority = priority; 01840 pbx_substitute_variables(passdata, sizeof(passdata), c, e); 01841 if (option_debug) { 01842 ast_log(LOG_DEBUG, "Launching '%s'\n", app->name); 01843 } 01844 if (option_verbose > 2) { 01845 char tmp[80], tmp2[80], tmp3[EXT_DATA_SIZE]; 01846 ast_verbose( VERBOSE_PREFIX_3 "Executing [%s@%s:%d] %s(\"%s\", \"%s\") %s\n", 01847 exten, context, priority, 01848 term_color(tmp, app->name, COLOR_BRCYAN, 0, sizeof(tmp)), 01849 term_color(tmp2, c->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)), 01850 term_color(tmp3, passdata, COLOR_BRMAGENTA, 0, sizeof(tmp3)), 01851 "in new stack"); 01852 } 01853 manager_event(EVENT_FLAG_CALL, "Newexten", 01854 "Channel: %s\r\n" 01855 "Context: %s\r\n" 01856 "Extension: %s\r\n" 01857 "Priority: %d\r\n" 01858 "Application: %s\r\n" 01859 "AppData: %s\r\n" 01860 "Uniqueid: %s\r\n", 01861 c->name, c->context, c->exten, c->priority, app->name, passdata, c->uniqueid); 01862 return pbx_exec(c, app, passdata); /* 0 on success, -1 on failure */ 01863 } 01864 } else if (q.swo) { /* not found here, but in another switch */ 01865 ast_unlock_contexts(); 01866 if (matching_action) { 01867 return -1; 01868 } else { 01869 if (!q.swo->exec) { 01870 ast_log(LOG_WARNING, "No execution engine for switch %s\n", q.swo->name); 01871 res = -1; 01872 } 01873 return q.swo->exec(c, q.foundcontext ? q.foundcontext : context, exten, priority, callerid, q.data); 01874 } 01875 } else { /* not found anywhere, see what happened */ 01876 ast_unlock_contexts(); 01877 switch (q.status) { 01878 case STATUS_NO_CONTEXT: 01879 if (!matching_action) 01880 ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", context); 01881 break; 01882 case STATUS_NO_EXTENSION: 01883 if (!matching_action) 01884 ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, context); 01885 break; 01886 case STATUS_NO_PRIORITY: 01887 if (!matching_action) 01888 ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, context); 01889 break; 01890 case STATUS_NO_LABEL: 01891 if (context) 01892 ast_log(LOG_NOTICE, "No such label '%s' in extension '%s' in context '%s'\n", label, exten, context); 01893 break; 01894 default: 01895 if (option_debug) 01896 ast_log(LOG_DEBUG, "Shouldn't happen!\n"); 01897 } 01898 01899 return (matching_action) ? 0 : -1; 01900 } 01901 }
static 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 | |||
) | [static] |
Definition at line 944 of file pbx.c.
References ast_log(), AST_PBX_MAX_STACK, ast_walk_context_extensions(), ast_walk_contexts(), ast_walk_extension_priorities(), ast_exten::cidmatch, pbx_find_info::data, E_FINDLABEL, E_MATCHMORE, ast_exten::exten, extension_match_core(), pbx_find_info::foundcontext, pbx_find_info::incstack, ast_exten::label, LOG_WARNING, match(), matchcid(), ast_exten::matchcid, ast_exten::priority, pbx_find_info::stacklen, pbx_find_info::status, STATUS_NO_CONTEXT, STATUS_NO_EXTENSION, STATUS_NO_LABEL, STATUS_NO_PRIORITY, STATUS_SUCCESS, and pbx_find_info::swo.
Referenced by ast_hint_extension(), ast_merge_contexts_and_delete(), and pbx_extension_helper().
00948 { 00949 int x, res; 00950 struct ast_context *tmp; 00951 struct ast_exten *e, *eroot; 00952 struct ast_include *i; 00953 struct ast_sw *sw; 00954 char *tmpdata = NULL; 00955 00956 /* Initialize status if appropriate */ 00957 if (q->stacklen == 0) { 00958 q->status = STATUS_NO_CONTEXT; 00959 q->swo = NULL; 00960 q->data = NULL; 00961 q->foundcontext = NULL; 00962 } 00963 /* Check for stack overflow */ 00964 if (q->stacklen >= AST_PBX_MAX_STACK) { 00965 ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n"); 00966 return NULL; 00967 } 00968 /* Check first to see if we've already been checked */ 00969 for (x = 0; x < q->stacklen; x++) { 00970 if (!strcasecmp(q->incstack[x], context)) 00971 return NULL; 00972 } 00973 if (bypass) /* bypass means we only look there */ 00974 tmp = bypass; 00975 else { /* look in contexts */ 00976 tmp = NULL; 00977 while ((tmp = ast_walk_contexts(tmp)) ) { 00978 if (!strcmp(tmp->name, context)) 00979 break; 00980 } 00981 if (!tmp) 00982 return NULL; 00983 } 00984 if (q->status < STATUS_NO_EXTENSION) 00985 q->status = STATUS_NO_EXTENSION; 00986 00987 /* scan the list trying to match extension and CID */ 00988 eroot = NULL; 00989 while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) { 00990 int match = extension_match_core(eroot->exten, exten, action); 00991 /* 0 on fail, 1 on match, 2 on earlymatch */ 00992 00993 if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid))) 00994 continue; /* keep trying */ 00995 if (match == 2 && action == E_MATCHMORE) { 00996 /* We match an extension ending in '!'. 00997 * The decision in this case is final and is NULL (no match). 00998 */ 00999 return NULL; 01000 } 01001 /* found entry, now look for the right priority */ 01002 if (q->status < STATUS_NO_PRIORITY) 01003 q->status = STATUS_NO_PRIORITY; 01004 e = NULL; 01005 while ( (e = ast_walk_extension_priorities(eroot, e)) ) { 01006 /* Match label or priority */ 01007 if (action == E_FINDLABEL) { 01008 if (q->status < STATUS_NO_LABEL) 01009 q->status = STATUS_NO_LABEL; 01010 if (label && e->label && !strcmp(label, e->label)) 01011 break; /* found it */ 01012 } else if (e->priority == priority) { 01013 break; /* found it */ 01014 } /* else keep searching */ 01015 } 01016 if (e) { /* found a valid match */ 01017 q->status = STATUS_SUCCESS; 01018 q->foundcontext = context; 01019 return e; 01020 } 01021 } 01022 /* Check alternative switches */ 01023 AST_LIST_TRAVERSE(&tmp->alts, sw, list) { 01024 struct ast_switch *asw = pbx_findswitch(sw->name); 01025 ast_switch_f *aswf = NULL; 01026 char *datap; 01027 01028 if (!asw) { 01029 ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name); 01030 continue; 01031 } 01032 /* Substitute variables now */ 01033 if (sw->eval) { 01034 if (!(tmpdata = ast_threadstorage_get(&switch_data, 512))) { 01035 ast_log(LOG_WARNING, "Can't evaluate switch?!"); 01036 continue; 01037 } 01038 pbx_substitute_variables_helper(chan, sw->data, tmpdata, 512); 01039 } 01040 01041 /* equivalent of extension_match_core() at the switch level */ 01042 if (action == E_CANMATCH) 01043 aswf = asw->canmatch; 01044 else if (action == E_MATCHMORE) 01045 aswf = asw->matchmore; 01046 else /* action == E_MATCH */ 01047 aswf = asw->exists; 01048 datap = sw->eval ? tmpdata : sw->data; 01049 if (!aswf) 01050 res = 0; 01051 else { 01052 if (chan) 01053 ast_autoservice_start(chan); 01054 res = aswf(chan, context, exten, priority, callerid, datap); 01055 if (chan) 01056 ast_autoservice_stop(chan); 01057 } 01058 if (res) { /* Got a match */ 01059 q->swo = asw; 01060 q->data = datap; 01061 q->foundcontext = context; 01062 /* XXX keep status = STATUS_NO_CONTEXT ? */ 01063 return NULL; 01064 } 01065 } 01066 q->incstack[q->stacklen++] = tmp->name; /* Setup the stack */ 01067 /* Now try any includes we have in this context */ 01068 for (i = tmp->includes; i; i = i->next) { 01069 if (include_valid(i)) { 01070 if ((e = pbx_find_extension(chan, bypass, q, i->rname, exten, priority, label, callerid, action))) 01071 return e; 01072 if (q->swo) 01073 return NULL; 01074 } 01075 } 01076 return NULL; 01077 }
struct ast_app* pbx_findapp | ( | const char * | app | ) |
Look up an application.
app | name of the app |
Definition at line 553 of file pbx.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, and AST_LIST_UNLOCK.
Referenced by answer_exec_run(), ast_bridge_call(), ast_pbx_run_app(), async_wait(), builtin_automonitor(), conf_run(), dundi_exec(), exec_exec(), execif_exec(), feature_exec_app(), forward_message(), handle_exec(), iax2_exec(), milliwatt_exec(), page_exec(), pbx_builtin_execiftime(), pbx_extension_helper(), realtime_exec(), try_calling(), and tryexec_exec().
00554 { 00555 struct ast_app *tmp; 00556 00557 AST_LIST_LOCK(&apps); 00558 AST_LIST_TRAVERSE(&apps, tmp, list) { 00559 if (!strcasecmp(tmp->name, app)) 00560 break; 00561 } 00562 AST_LIST_UNLOCK(&apps); 00563 00564 return tmp; 00565 }
static struct ast_switch* pbx_findswitch | ( | const char * | sw | ) | [static] |
Definition at line 567 of file pbx.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, and ast_switch::name.
00568 { 00569 struct ast_switch *asw; 00570 00571 AST_LIST_LOCK(&switches); 00572 AST_LIST_TRAVERSE(&switches, asw, list) { 00573 if (!strcasecmp(asw->name, sw)) 00574 break; 00575 } 00576 AST_LIST_UNLOCK(&switches); 00577 00578 return asw; 00579 }
void pbx_retrieve_variable | ( | struct ast_channel * | c, | |
const char * | var, | |||
char ** | ret, | |||
char * | workspace, | |||
int | workspacelen, | |||
struct varshead * | headp | |||
) |
pbx_retrieve_variable: Support for Asterisk built-in variables ---
Definition at line 1151 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, ast_config_AST_SYSTEM_NAME, ast_get_hint(), AST_LIST_TRAVERSE, ast_mutex_lock(), ast_mutex_unlock(), 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_channel::exten, ast_channel::hangupcause, offset, parse_variable_name(), ast_channel::priority, s, and substring().
Referenced by action_getvar(), handle_getvariable(), and pbx_substitute_variables_helper_full().
01152 { 01153 const char not_found = '\0'; 01154 char *tmpvar; 01155 const char *s; /* the result */ 01156 int offset, length; 01157 int i, need_substring; 01158 struct varshead *places[2] = { headp, &globals }; /* list of places where we may look */ 01159 01160 if (c) { 01161 ast_channel_lock(c); 01162 places[0] = &c->varshead; 01163 } 01164 /* 01165 * Make a copy of var because parse_variable_name() modifies the string. 01166 * Then if called directly, we might need to run substring() on the result; 01167 * remember this for later in 'need_substring', 'offset' and 'length' 01168 */ 01169 tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */ 01170 need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */); 01171 01172 /* 01173 * Look first into predefined variables, then into variable lists. 01174 * Variable 's' points to the result, according to the following rules: 01175 * s == ¬_found (set at the beginning) means that we did not find a 01176 * matching variable and need to look into more places. 01177 * If s != ¬_found, s is a valid result string as follows: 01178 * s = NULL if the variable does not have a value; 01179 * you typically do this when looking for an unset predefined variable. 01180 * s = workspace if the result has been assembled there; 01181 * typically done when the result is built e.g. with an snprintf(), 01182 * so we don't need to do an additional copy. 01183 * s != workspace in case we have a string, that needs to be copied 01184 * (the ast_copy_string is done once for all at the end). 01185 * Typically done when the result is already available in some string. 01186 */ 01187 s = ¬_found; /* default value */ 01188 if (c) { /* This group requires a valid channel */ 01189 /* Names with common parts are looked up a piece at a time using strncmp. */ 01190 if (!strncmp(var, "CALL", 4)) { 01191 if (!strncmp(var + 4, "ING", 3)) { 01192 if (!strcmp(var + 7, "PRES")) { /* CALLINGPRES */ 01193 snprintf(workspace, workspacelen, "%d", c->cid.cid_pres); 01194 s = workspace; 01195 } else if (!strcmp(var + 7, "ANI2")) { /* CALLINGANI2 */ 01196 snprintf(workspace, workspacelen, "%d", c->cid.cid_ani2); 01197 s = workspace; 01198 } else if (!strcmp(var + 7, "TON")) { /* CALLINGTON */ 01199 snprintf(workspace, workspacelen, "%d", c->cid.cid_ton); 01200 s = workspace; 01201 } else if (!strcmp(var + 7, "TNS")) { /* CALLINGTNS */ 01202 snprintf(workspace, workspacelen, "%d", c->cid.cid_tns); 01203 s = workspace; 01204 } 01205 } 01206 } else if (!strcmp(var, "HINT")) { 01207 s = ast_get_hint(workspace, workspacelen, NULL, 0, c, c->context, c->exten) ? workspace : NULL; 01208 } else if (!strcmp(var, "HINTNAME")) { 01209 s = ast_get_hint(NULL, 0, workspace, workspacelen, c, c->context, c->exten) ? workspace : NULL; 01210 } else if (!strcmp(var, "EXTEN")) { 01211 s = c->exten; 01212 } else if (!strcmp(var, "CONTEXT")) { 01213 s = c->context; 01214 } else if (!strcmp(var, "PRIORITY")) { 01215 snprintf(workspace, workspacelen, "%d", c->priority); 01216 s = workspace; 01217 } else if (!strcmp(var, "CHANNEL")) { 01218 s = c->name; 01219 } else if (!strcmp(var, "UNIQUEID")) { 01220 s = c->uniqueid; 01221 } else if (!strcmp(var, "HANGUPCAUSE")) { 01222 snprintf(workspace, workspacelen, "%d", c->hangupcause); 01223 s = workspace; 01224 } 01225 } 01226 if (s == ¬_found) { /* look for more */ 01227 if (!strcmp(var, "EPOCH")) { 01228 snprintf(workspace, workspacelen, "%u",(int)time(NULL)); 01229 s = workspace; 01230 } else if (!strcmp(var, "SYSTEMNAME")) { 01231 s = ast_config_AST_SYSTEM_NAME; 01232 } 01233 } 01234 /* if not found, look into chanvars or global vars */ 01235 for (i = 0; s == ¬_found && i < (sizeof(places) / sizeof(places[0])); i++) { 01236 struct ast_var_t *variables; 01237 if (!places[i]) 01238 continue; 01239 if (places[i] == &globals) 01240 ast_mutex_lock(&globalslock); 01241 AST_LIST_TRAVERSE(places[i], variables, entries) { 01242 if (strcasecmp(ast_var_name(variables), var)==0) { 01243 s = ast_var_value(variables); 01244 break; 01245 } 01246 } 01247 if (places[i] == &globals) 01248 ast_mutex_unlock(&globalslock); 01249 } 01250 if (s == ¬_found || s == NULL) 01251 *ret = NULL; 01252 else { 01253 if (s != workspace) 01254 ast_copy_string(workspace, s, workspacelen); 01255 *ret = workspace; 01256 if (need_substring) 01257 *ret = substring(*ret, offset, length, workspace, workspacelen); 01258 } 01259 01260 if (c) 01261 ast_channel_unlock(c); 01262 }
int pbx_set_autofallthrough | ( | int | newval | ) |
Set "autofallthrough" flag, if newval is <0, does not acutally 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 2688 of file pbx.c.
References autofallthrough.
Referenced by pbx_load_module().
02689 { 02690 int oldval = autofallthrough; 02691 autofallthrough = newval; 02692 return oldval; 02693 }
static void pbx_substitute_variables | ( | char * | passdata, | |
int | datalen, | |||
struct ast_channel * | c, | |||
struct ast_exten * | e | |||
) | [static] |
Definition at line 1777 of file pbx.c.
References ast_exten::data, and pbx_substitute_variables_helper().
Referenced by pbx_extension_helper().
01778 { 01779 memset(passdata, 0, datalen); 01780 01781 /* No variables or expressions in e->data, so why scan it? */ 01782 if (e->data && !strchr(e->data, '$') && !strstr(e->data,"${") && !strstr(e->data,"$[") && !strstr(e->data,"$(")) { 01783 ast_copy_string(passdata, e->data, datalen); 01784 return; 01785 } 01786 01787 pbx_substitute_variables_helper(c, e->data, passdata, datalen - 1); 01788 }
void pbx_substitute_variables_helper | ( | struct ast_channel * | c, | |
const char * | cp1, | |||
char * | cp2, | |||
int | count | |||
) |
Definition at line 1767 of file pbx.c.
References pbx_substitute_variables_helper_full(), and ast_channel::varshead.
Referenced by _macro_exec(), acf_odbc_read(), acf_odbc_write(), add_extensions(), custom_log(), cut_internal(), exec_exec(), function_eval(), function_fieldqty(), handle_getvariablefull(), launch_monitor_thread(), make_email_file(), pbx_builtin_importvar(), pbx_load_config(), pbx_substitute_variables(), realtime_exec(), rpt_do_lstats(), sendpage(), try_calling(), and tryexec_exec().
01768 { 01769 pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count); 01770 }
static void pbx_substitute_variables_helper_full | ( | struct ast_channel * | c, | |
struct varshead * | headp, | |||
const char * | cp1, | |||
char * | cp2, | |||
int | count | |||
) | [static] |
Definition at line 1573 of file pbx.c.
References ast_channel_alloc(), ast_channel_free(), ast_expr(), ast_func_read(), ast_log(), ast_strlen_zero(), len, LOG_DEBUG, LOG_ERROR, LOG_NOTICE, offset, option_debug, parse_variable_name(), pbx_retrieve_variable(), substring(), var, VAR_BUF_SIZE, and ast_channel::varshead.
Referenced by pbx_substitute_variables_helper(), and pbx_substitute_variables_varshead().
01574 { 01575 /* Substitutes variables into cp2, based on string cp1, and assuming cp2 to be 01576 zero-filled */ 01577 char *cp4; 01578 const char *tmp, *whereweare; 01579 int length, offset, offset2, isfunction; 01580 char *workspace = NULL; 01581 char *ltmp = NULL, *var = NULL; 01582 char *nextvar, *nextexp, *nextthing; 01583 char *vars, *vare; 01584 int pos, brackets, needsub, len; 01585 01586 whereweare=tmp=cp1; 01587 while (!ast_strlen_zero(whereweare) && count) { 01588 /* Assume we're copying the whole remaining string */ 01589 pos = strlen(whereweare); 01590 nextvar = NULL; 01591 nextexp = NULL; 01592 nextthing = strchr(whereweare, '$'); 01593 if (nextthing) { 01594 switch(nextthing[1]) { 01595 case '{': 01596 nextvar = nextthing; 01597 pos = nextvar - whereweare; 01598 break; 01599 case '[': 01600 nextexp = nextthing; 01601 pos = nextexp - whereweare; 01602 break; 01603 default: 01604 pos = 1; 01605 } 01606 } 01607 01608 if (pos) { 01609 /* Can't copy more than 'count' bytes */ 01610 if (pos > count) 01611 pos = count; 01612 01613 /* Copy that many bytes */ 01614 memcpy(cp2, whereweare, pos); 01615 01616 count -= pos; 01617 cp2 += pos; 01618 whereweare += pos; 01619 } 01620 01621 if (nextvar) { 01622 /* We have a variable. Find the start and end, and determine 01623 if we are going to have to recursively call ourselves on the 01624 contents */ 01625 vars = vare = nextvar + 2; 01626 brackets = 1; 01627 needsub = 0; 01628 01629 /* Find the end of it */ 01630 while (brackets && *vare) { 01631 if ((vare[0] == '$') && (vare[1] == '{')) { 01632 needsub++; 01633 } else if (vare[0] == '{') { 01634 brackets++; 01635 } else if (vare[0] == '}') { 01636 brackets--; 01637 } else if ((vare[0] == '$') && (vare[1] == '[')) 01638 needsub++; 01639 vare++; 01640 } 01641 if (brackets) 01642 ast_log(LOG_NOTICE, "Error in extension logic (missing '}')\n"); 01643 len = vare - vars - 1; 01644 01645 /* Skip totally over variable string */ 01646 whereweare += (len + 3); 01647 01648 if (!var) 01649 var = alloca(VAR_BUF_SIZE); 01650 01651 /* Store variable name (and truncate) */ 01652 ast_copy_string(var, vars, len + 1); 01653 01654 /* Substitute if necessary */ 01655 if (needsub) { 01656 if (!ltmp) 01657 ltmp = alloca(VAR_BUF_SIZE); 01658 01659 memset(ltmp, 0, VAR_BUF_SIZE); 01660 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1); 01661 vars = ltmp; 01662 } else { 01663 vars = var; 01664 } 01665 01666 if (!workspace) 01667 workspace = alloca(VAR_BUF_SIZE); 01668 01669 workspace[0] = '\0'; 01670 01671 parse_variable_name(vars, &offset, &offset2, &isfunction); 01672 if (isfunction) { 01673 /* Evaluate function */ 01674 if (c || !headp) 01675 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 01676 else { 01677 struct varshead old; 01678 struct ast_channel *c = ast_channel_alloc(0, 0, "", "", "", "", "", 0, "Bogus/%p", vars); 01679 if (c) { 01680 memcpy(&old, &c->varshead, sizeof(old)); 01681 memcpy(&c->varshead, headp, sizeof(c->varshead)); 01682 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 01683 /* Don't deallocate the varshead that was passed in */ 01684 memcpy(&c->varshead, &old, sizeof(c->varshead)); 01685 ast_channel_free(c); 01686 } else 01687 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n"); 01688 } 01689 01690 if (option_debug) 01691 ast_log(LOG_DEBUG, "Function result is '%s'\n", cp4 ? cp4 : "(null)"); 01692 } else { 01693 /* Retrieve variable value */ 01694 pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp); 01695 } 01696 if (cp4) { 01697 cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE); 01698 01699 length = strlen(cp4); 01700 if (length > count) 01701 length = count; 01702 memcpy(cp2, cp4, length); 01703 count -= length; 01704 cp2 += length; 01705 } 01706 } else if (nextexp) { 01707 /* We have an expression. Find the start and end, and determine 01708 if we are going to have to recursively call ourselves on the 01709 contents */ 01710 vars = vare = nextexp + 2; 01711 brackets = 1; 01712 needsub = 0; 01713 01714 /* Find the end of it */ 01715 while(brackets && *vare) { 01716 if ((vare[0] == '$') && (vare[1] == '[')) { 01717 needsub++; 01718 brackets++; 01719 vare++; 01720 } else if (vare[0] == '[') { 01721 brackets++; 01722 } else if (vare[0] == ']') { 01723 brackets--; 01724 } else if ((vare[0] == '$') && (vare[1] == '{')) { 01725 needsub++; 01726 vare++; 01727 } 01728 vare++; 01729 } 01730 if (brackets) 01731 ast_log(LOG_NOTICE, "Error in extension logic (missing ']')\n"); 01732 len = vare - vars - 1; 01733 01734 /* Skip totally over expression */ 01735 whereweare += (len + 3); 01736 01737 if (!var) 01738 var = alloca(VAR_BUF_SIZE); 01739 01740 /* Store variable name (and truncate) */ 01741 ast_copy_string(var, vars, len + 1); 01742 01743 /* Substitute if necessary */ 01744 if (needsub) { 01745 if (!ltmp) 01746 ltmp = alloca(VAR_BUF_SIZE); 01747 01748 memset(ltmp, 0, VAR_BUF_SIZE); 01749 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1); 01750 vars = ltmp; 01751 } else { 01752 vars = var; 01753 } 01754 01755 length = ast_expr(vars, cp2, count); 01756 01757 if (length) { 01758 if (option_debug) 01759 ast_log(LOG_DEBUG, "Expression result is '%s'\n", cp2); 01760 count -= length; 01761 cp2 += length; 01762 } 01763 } 01764 } 01765 }
void pbx_substitute_variables_varshead | ( | struct varshead * | headp, | |
const char * | cp1, | |||
char * | cp2, | |||
int | count | |||
) |
Definition at line 1772 of file pbx.c.
References pbx_substitute_variables_helper_full().
Referenced by ast_add_extension2(), dundi_lookup_local(), and loopback_subst().
01773 { 01774 pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count); 01775 }
static void* pbx_thread | ( | void * | data | ) | [static] |
Definition at line 2624 of file pbx.c.
References __ast_pbx_run(), and decrease_call_count().
Referenced by ast_pbx_start().
02625 { 02626 /* Oh joyeous kernel, we're a new thread, with nothing to do but 02627 answer this channel and get it going. 02628 */ 02629 /* NOTE: 02630 The launcher of this function _MUST_ increment 'countcalls' 02631 before invoking the function; it will be decremented when the 02632 PBX has finished running on the channel 02633 */ 02634 struct ast_channel *c = data; 02635 02636 __ast_pbx_run(c); 02637 decrease_call_count(); 02638 02639 pthread_exit(NULL); 02640 02641 return NULL; 02642 }
static void print_ext | ( | struct ast_exten * | e, | |
char * | buf, | |||
int | buflen | |||
) | [static] |
helper function to print an extension
Definition at line 3507 of file pbx.c.
References ast_get_extension_app(), ast_get_extension_app_data(), ast_get_extension_priority(), ast_strlen_zero(), and PRIORITY_HINT.
Referenced by show_dialplan_helper().
03508 { 03509 int prio = ast_get_extension_priority(e); 03510 if (prio == PRIORITY_HINT) { 03511 snprintf(buf, buflen, "hint: %s", 03512 ast_get_extension_app(e)); 03513 } else { 03514 snprintf(buf, buflen, "%d. %s(%s)", 03515 prio, ast_get_extension_app(e), 03516 (!ast_strlen_zero(ast_get_extension_app_data(e)) ? (char *)ast_get_extension_app_data(e) : "")); 03517 } 03518 }
static void set_ext_pri | ( | struct ast_channel * | c, | |
const char * | exten, | |||
int | pri | |||
) | [static] |
Definition at line 2321 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, ast_channel::exten, and ast_channel::priority.
Referenced by __ast_pbx_run(), ast_pbx_outgoing_exten_uniqueid(), and pbx_builtin_waitexten().
02322 { 02323 ast_channel_lock(c); 02324 ast_copy_string(c->exten, exten, sizeof(c->exten)); 02325 c->priority = pri; 02326 ast_channel_unlock(c); 02327 }
static int show_dialplan_helper | ( | int | fd, | |
const char * | context, | |||
const char * | exten, | |||
struct dialplan_counters * | dpc, | |||
struct ast_include * | rinclude, | |||
int | includecount, | |||
const char * | includes[] | |||
) | [static] |
Definition at line 3521 of file pbx.c.
References ast_cli(), ast_extension_match(), ast_get_context_name(), ast_get_context_registrar(), ast_get_extension_label(), ast_get_extension_name(), ast_get_extension_registrar(), ast_get_ignorepat_name(), ast_get_ignorepat_registrar(), ast_get_include_name(), ast_get_include_registrar(), ast_get_switch_data(), ast_get_switch_name(), ast_get_switch_registrar(), ast_lock_context(), ast_log(), AST_MAX_EXTENSION, AST_PBX_MAX_STACK, ast_rdlock_contexts(), ast_unlock_context(), ast_unlock_contexts(), ast_walk_context_extensions(), ast_walk_context_ignorepats(), ast_walk_context_includes(), ast_walk_context_switches(), ast_walk_contexts(), ast_walk_extension_priorities(), dialplan_counters::context_existence, el, dialplan_counters::extension_existence, LOG_NOTICE, LOG_WARNING, print_ext(), dialplan_counters::total_context, dialplan_counters::total_exten, and dialplan_counters::total_prio.
Referenced by handle_show_dialplan().
03522 { 03523 struct ast_context *c = NULL; 03524 int res = 0, old_total_exten = dpc->total_exten; 03525 03526 ast_rdlock_contexts(); 03527 03528 /* walk all contexts ... */ 03529 while ( (c = ast_walk_contexts(c)) ) { 03530 struct ast_exten *e; 03531 struct ast_include *i; 03532 struct ast_ignorepat *ip; 03533 char buf[256], buf2[256]; 03534 int context_info_printed = 0; 03535 03536 if (context && strcmp(ast_get_context_name(c), context)) 03537 continue; /* skip this one, name doesn't match */ 03538 03539 dpc->context_existence = 1; 03540 03541 ast_lock_context(c); 03542 03543 /* are we looking for exten too? if yes, we print context 03544 * only if we find our extension. 03545 * Otherwise print context even if empty ? 03546 * XXX i am not sure how the rinclude is handled. 03547 * I think it ought to go inside. 03548 */ 03549 if (!exten) { 03550 dpc->total_context++; 03551 ast_cli(fd, "[ Context '%s' created by '%s' ]\n", 03552 ast_get_context_name(c), ast_get_context_registrar(c)); 03553 context_info_printed = 1; 03554 } 03555 03556 /* walk extensions ... */ 03557 e = NULL; 03558 while ( (e = ast_walk_context_extensions(c, e)) ) { 03559 struct ast_exten *p; 03560 03561 if (exten && !ast_extension_match(ast_get_extension_name(e), exten)) 03562 continue; /* skip, extension match failed */ 03563 03564 dpc->extension_existence = 1; 03565 03566 /* may we print context info? */ 03567 if (!context_info_printed) { 03568 dpc->total_context++; 03569 if (rinclude) { /* TODO Print more info about rinclude */ 03570 ast_cli(fd, "[ Included context '%s' created by '%s' ]\n", 03571 ast_get_context_name(c), ast_get_context_registrar(c)); 03572 } else { 03573 ast_cli(fd, "[ Context '%s' created by '%s' ]\n", 03574 ast_get_context_name(c), ast_get_context_registrar(c)); 03575 } 03576 context_info_printed = 1; 03577 } 03578 dpc->total_prio++; 03579 03580 /* write extension name and first peer */ 03581 snprintf(buf, sizeof(buf), "'%s' =>", ast_get_extension_name(e)); 03582 03583 print_ext(e, buf2, sizeof(buf2)); 03584 03585 ast_cli(fd, " %-17s %-45s [%s]\n", buf, buf2, 03586 ast_get_extension_registrar(e)); 03587 03588 dpc->total_exten++; 03589 /* walk next extension peers */ 03590 p = e; /* skip the first one, we already got it */ 03591 while ( (p = ast_walk_extension_priorities(e, p)) ) { 03592 const char *el = ast_get_extension_label(p); 03593 dpc->total_prio++; 03594 if (el) 03595 snprintf(buf, sizeof(buf), " [%s]", el); 03596 else 03597 buf[0] = '\0'; 03598 print_ext(p, buf2, sizeof(buf2)); 03599 03600 ast_cli(fd," %-17s %-45s [%s]\n", buf, buf2, 03601 ast_get_extension_registrar(p)); 03602 } 03603 } 03604 03605 /* walk included and write info ... */ 03606 i = NULL; 03607 while ( (i = ast_walk_context_includes(c, i)) ) { 03608 snprintf(buf, sizeof(buf), "'%s'", ast_get_include_name(i)); 03609 if (exten) { 03610 /* Check all includes for the requested extension */ 03611 if (includecount >= AST_PBX_MAX_STACK) { 03612 ast_log(LOG_NOTICE, "Maximum include depth exceeded!\n"); 03613 } else { 03614 int dupe=0; 03615 int x; 03616 for (x=0;x<includecount;x++) { 03617 if (!strcasecmp(includes[x], ast_get_include_name(i))) { 03618 dupe++; 03619 break; 03620 } 03621 } 03622 if (!dupe) { 03623 includes[includecount] = ast_get_include_name(i); 03624 show_dialplan_helper(fd, ast_get_include_name(i), exten, dpc, i, includecount + 1, includes); 03625 } else { 03626 ast_log(LOG_WARNING, "Avoiding circular include of %s within %s\n", ast_get_include_name(i), context); 03627 } 03628 } 03629 } else { 03630 ast_cli(fd, " Include => %-45s [%s]\n", 03631 buf, ast_get_include_registrar(i)); 03632 } 03633 } 03634 03635 /* walk ignore patterns and write info ... */ 03636 ip = NULL; 03637 while ( (ip = ast_walk_context_ignorepats(c, ip)) ) { 03638 const char *ipname = ast_get_ignorepat_name(ip); 03639 char ignorepat[AST_MAX_EXTENSION]; 03640 snprintf(buf, sizeof(buf), "'%s'", ipname); 03641 snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname); 03642 if (!exten || ast_extension_match(ignorepat, exten)) { 03643 ast_cli(fd, " Ignore pattern => %-45s [%s]\n", 03644 buf, ast_get_ignorepat_registrar(ip)); 03645 } 03646 } 03647 if (!rinclude) { 03648 struct ast_sw *sw = NULL; 03649 while ( (sw = ast_walk_context_switches(c, sw)) ) { 03650 snprintf(buf, sizeof(buf), "'%s/%s'", 03651 ast_get_switch_name(sw), 03652 ast_get_switch_data(sw)); 03653 ast_cli(fd, " Alt. Switch => %-45s [%s]\n", 03654 buf, ast_get_switch_registrar(sw)); 03655 } 03656 } 03657 03658 ast_unlock_context(c); 03659 03660 /* if we print something in context, make an empty line */ 03661 if (context_info_printed) 03662 ast_cli(fd, "\r\n"); 03663 } 03664 ast_unlock_contexts(); 03665 03666 return (dpc->total_exten == old_total_exten) ? -1 : res; 03667 }
static char* substring | ( | const char * | value, | |
int | offset, | |||
int | length, | |||
char * | workspace, | |||
size_t | workspace_len | |||
) | [static] |
takes a substring. It is ok to call with value == workspace.
offset < 0 means start from the end of the string and set the beginning to be that many characters back. length is the length of the substring. A value less than 0 means to leave that many off the end. Always return a copy in workspace.
Definition at line 1113 of file pbx.c.
Referenced by pbx_retrieve_variable(), and pbx_substitute_variables_helper_full().
01114 { 01115 char *ret = workspace; 01116 int lr; /* length of the input string after the copy */ 01117 01118 ast_copy_string(workspace, value, workspace_len); /* always make a copy */ 01119 01120 lr = strlen(ret); /* compute length after copy, so we never go out of the workspace */ 01121 01122 /* Quick check if no need to do anything */ 01123 if (offset == 0 && length >= lr) /* take the whole string */ 01124 return ret; 01125 01126 if (offset < 0) { /* translate negative offset into positive ones */ 01127 offset = lr + offset; 01128 if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */ 01129 offset = 0; 01130 } 01131 01132 /* too large offset result in empty string so we know what to return */ 01133 if (offset >= lr) 01134 return ret + lr; /* the final '\0' */ 01135 01136 ret += offset; /* move to the start position */ 01137 if (length >= 0 && length < lr - offset) /* truncate if necessary */ 01138 ret[length] = '\0'; 01139 else if (length < 0) { 01140 if (lr > offset - length) /* After we remove from the front and from the rear, is there anything left? */ 01141 ret[lr + length - offset] = '\0'; 01142 else 01143 ret[0] = '\0'; 01144 } 01145 01146 return ret; 01147 }
static void wait_for_hangup | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 5376 of file pbx.c.
References ast_frfree, ast_read(), ast_safe_sleep(), ast_strlen_zero(), ast_waitfor(), and f.
Referenced by pbx_builtin_busy(), and pbx_builtin_congestion().
05377 { 05378 int res; 05379 struct ast_frame *f; 05380 int waittime; 05381 05382 if (ast_strlen_zero(data) || (sscanf(data, "%d", &waittime) != 1) || (waittime < 0)) 05383 waittime = -1; 05384 if (waittime > -1) { 05385 ast_safe_sleep(chan, waittime * 1000); 05386 } else do { 05387 res = ast_waitfor(chan, -1); 05388 if (res < 0) 05389 return; 05390 f = ast_read(chan); 05391 if (f) 05392 ast_frfree(f); 05393 } while(f); 05394 }
int autofallthrough = 1 [static] |
struct pbx_builtin builtins[] [static] |
Declaration of builtin applications.
struct ast_cli_entry cli_set_global_deprecated [static] |
Initial value:
{ { "set", "global", NULL }, handle_set_global_deprecated, NULL, NULL }
struct ast_cli_entry cli_show_application_deprecated [static] |
Initial value:
{ { "show", "application", NULL }, handle_show_application_deprecated, NULL, NULL, complete_show_application }
struct ast_cli_entry cli_show_applications_deprecated [static] |
Initial value:
{ { "show", "applications", NULL }, handle_show_applications_deprecated, NULL, NULL, complete_show_applications_deprecated }
struct ast_cli_entry cli_show_dialplan_deprecated [static] |
Initial value:
{ { "show", "dialplan", NULL }, handle_show_dialplan, NULL, NULL, complete_show_dialplan_context }
struct ast_cli_entry cli_show_function_deprecated [static] |
Initial value:
{ { "show" , "function", NULL }, handle_show_function_deprecated, NULL, NULL, complete_show_function }
struct ast_cli_entry cli_show_functions_deprecated [static] |
Initial value:
{ { "show", "functions", NULL }, handle_show_functions_deprecated, NULL, NULL }
struct ast_cli_entry cli_show_globals_deprecated [static] |
Initial value:
{ { "show", "globals", NULL }, handle_show_globals, NULL, NULL }
struct ast_cli_entry cli_show_hints_deprecated [static] |
Initial value:
{ { "show", "hints", NULL }, handle_show_hints, NULL, NULL }
struct ast_cli_entry cli_show_switches_deprecated [static] |
Initial value:
{ { "show", "switches", NULL }, handle_show_switches, NULL, NULL }
struct ast_context* contexts [static] |
Definition at line 495 of file pbx.c.
Referenced by __ast_context_create(), __ast_context_destroy(), ast_merge_contexts_and_delete(), and ast_walk_contexts().
int countcalls [static] |
Definition at line 248 of file pbx.c.
Referenced by ast_active_calls(), decrease_call_count(), and increase_call_count().
char* days[] [static] |
struct cfextension_states extension_states[] [static] |
Referenced by ast_extension_state2str().
struct varshead globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE [static] |
char* months[] [static] |
struct ast_cli_entry pbx_cli[] [static] |
char set_global_help[] [static] |
char show_application_help[] [static] |
char show_applications_help[] [static] |
char show_dialplan_help[] [static] |
char show_function_help[] [static] |
char show_functions_help[] [static] |
char show_globals_help[] [static] |
char show_hints_help[] [static] |
char show_switches_help[] [static] |
struct ast_state_cb* statecbs |
Definition at line 510 of file pbx.c.
Referenced by ast_extension_state_add(), ast_extension_state_del(), and ast_hint_state_changed().