#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) |
Register a new context or find an existing one. | |
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 hint 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) |
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) |
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) |
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 registered dial plan hints | |
static int | handle_show_switches (int fd, int argc, char *argv[]) |
handle_show_switches: CLI support for listing registered 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) |
Support for Asterisk built-in variables and functions in the dialplan. | |
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 551 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 913 of file pbx.c.
Referenced by pbx_extension_helper(), and pbx_find_extension().
#define STATUS_NO_EXTENSION 2 |
Definition at line 914 of file pbx.c.
Referenced by pbx_extension_helper(), and pbx_find_extension().
#define STATUS_NO_LABEL 4 |
Definition at line 916 of file pbx.c.
Referenced by pbx_extension_helper(), and pbx_find_extension().
#define STATUS_NO_PRIORITY 3 |
Definition at line 915 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 756 of file pbx.c.
00756 { 00757 E_MATCHMORE = 0x00, /* extension can match but only with more 'digits' */ 00758 E_CANMATCH = 0x01, /* extension can match with or without more 'digits' */ 00759 E_MATCH = 0x02, /* extension is an exact match */ 00760 E_MATCH_MASK = 0x03, /* mask for the argument to extension_match_core() */ 00761 E_SPAWN = 0x12, /* want to spawn an extension. Requires exact match */ 00762 E_FINDLABEL = 0x22 /* returns the priority for a given label. Requires exact match */ 00763 };
static struct ast_context* __ast_context_create | ( | struct ast_context ** | extcontexts, | |
const char * | name, | |||
const char * | registrar, | |||
int | existsokay | |||
) | [static] |
Definition at line 3877 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().
03878 { 03879 struct ast_context *tmp, **local_contexts; 03880 int length = sizeof(struct ast_context) + strlen(name) + 1; 03881 03882 if (!extcontexts) { 03883 ast_rdlock_contexts(); 03884 local_contexts = &contexts; 03885 } else 03886 local_contexts = extcontexts; 03887 03888 for (tmp = *local_contexts; tmp; tmp = tmp->next) { 03889 if (!strcasecmp(tmp->name, name)) { 03890 if (!existsokay) { 03891 ast_log(LOG_WARNING, "Tried to register context '%s', already in use\n", name); 03892 tmp = NULL; 03893 } 03894 if (!extcontexts) 03895 ast_unlock_contexts(); 03896 return tmp; 03897 } 03898 } 03899 03900 if (!extcontexts) 03901 ast_unlock_contexts(); 03902 03903 if ((tmp = ast_calloc(1, length))) { 03904 ast_mutex_init(&tmp->lock); 03905 ast_mutex_init(&tmp->macrolock); 03906 strcpy(tmp->name, name); 03907 tmp->registrar = registrar; 03908 if (!extcontexts) 03909 ast_wrlock_contexts(); 03910 tmp->next = *local_contexts; 03911 *local_contexts = tmp; 03912 if (!extcontexts) 03913 ast_unlock_contexts(); 03914 if (option_debug) 03915 ast_log(LOG_DEBUG, "Registered context '%s'\n", tmp->name); 03916 if (option_verbose > 2) 03917 ast_verbose( VERBOSE_PREFIX_3 "Registered extension context '%s'\n", tmp->name); 03918 } 03919 03920 return tmp; 03921 }
void __ast_context_destroy | ( | struct ast_context * | con, | |
const char * | registrar | |||
) |
Definition at line 5306 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().
05307 { 05308 struct ast_context *tmp, *tmpl=NULL; 05309 struct ast_include *tmpi; 05310 struct ast_sw *sw; 05311 struct ast_exten *e, *el, *en; 05312 struct ast_ignorepat *ipi; 05313 05314 for (tmp = contexts; tmp; ) { 05315 struct ast_context *next; /* next starting point */ 05316 for (; tmp; tmpl = tmp, tmp = tmp->next) { 05317 if (option_debug) 05318 ast_log(LOG_DEBUG, "check ctx %s %s\n", tmp->name, tmp->registrar); 05319 if ( (!registrar || !strcasecmp(registrar, tmp->registrar)) && 05320 (!con || !strcasecmp(tmp->name, con->name)) ) 05321 break; /* found it */ 05322 } 05323 if (!tmp) /* not found, we are done */ 05324 break; 05325 ast_mutex_lock(&tmp->lock); 05326 if (option_debug) 05327 ast_log(LOG_DEBUG, "delete ctx %s %s\n", tmp->name, tmp->registrar); 05328 next = tmp->next; 05329 if (tmpl) 05330 tmpl->next = next; 05331 else 05332 contexts = next; 05333 /* Okay, now we're safe to let it go -- in a sense, we were 05334 ready to let it go as soon as we locked it. */ 05335 ast_mutex_unlock(&tmp->lock); 05336 for (tmpi = tmp->includes; tmpi; ) { /* Free includes */ 05337 struct ast_include *tmpil = tmpi; 05338 tmpi = tmpi->next; 05339 free(tmpil); 05340 } 05341 for (ipi = tmp->ignorepats; ipi; ) { /* Free ignorepats */ 05342 struct ast_ignorepat *ipl = ipi; 05343 ipi = ipi->next; 05344 free(ipl); 05345 } 05346 while ((sw = AST_LIST_REMOVE_HEAD(&tmp->alts, list))) 05347 free(sw); 05348 for (e = tmp->root; e;) { 05349 for (en = e->peer; en;) { 05350 el = en; 05351 en = en->peer; 05352 destroy_exten(el); 05353 } 05354 el = e; 05355 e = e->next; 05356 destroy_exten(el); 05357 } 05358 ast_mutex_destroy(&tmp->lock); 05359 free(tmp); 05360 /* if we have a specific match, we are done, otherwise continue */ 05361 tmp = con ? NULL : next; 05362 } 05363 }
static int __ast_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority, | |||
int | async | |||
) | [static] |
Definition at line 6343 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().
06344 { 06345 int (*goto_func)(struct ast_channel *chan, const char *context, const char *exten, int priority); 06346 06347 if (!chan) 06348 return -2; 06349 06350 if (context == NULL) 06351 context = chan->context; 06352 if (exten == NULL) 06353 exten = chan->exten; 06354 06355 goto_func = (async) ? ast_async_goto : ast_explicit_goto; 06356 if (ast_exists_extension(chan, context, exten, priority, chan->cid.cid_num)) 06357 return goto_func(chan, context, exten, priority); 06358 else 06359 return -3; 06360 }
static int __ast_pbx_run | ( | struct ast_channel * | c | ) | [static] |
Definition at line 2365 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().
02366 { 02367 int found = 0; /* set if we find at least one match */ 02368 int res = 0; 02369 int autoloopflag; 02370 int error = 0; /* set an error conditions */ 02371 02372 /* A little initial setup here */ 02373 if (c->pbx) { 02374 ast_log(LOG_WARNING, "%s already has PBX structure??\n", c->name); 02375 /* XXX and now what ? */ 02376 free(c->pbx); 02377 } 02378 if (!(c->pbx = ast_calloc(1, sizeof(*c->pbx)))) 02379 return -1; 02380 if (c->amaflags) { 02381 if (!c->cdr) { 02382 c->cdr = ast_cdr_alloc(); 02383 if (!c->cdr) { 02384 ast_log(LOG_WARNING, "Unable to create Call Detail Record\n"); 02385 free(c->pbx); 02386 return -1; 02387 } 02388 ast_cdr_init(c->cdr, c); 02389 } 02390 } 02391 /* Set reasonable defaults */ 02392 c->pbx->rtimeout = 10; 02393 c->pbx->dtimeout = 5; 02394 02395 autoloopflag = ast_test_flag(c, AST_FLAG_IN_AUTOLOOP); /* save value to restore at the end */ 02396 ast_set_flag(c, AST_FLAG_IN_AUTOLOOP); 02397 02398 /* Start by trying whatever the channel is set to */ 02399 if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) { 02400 /* If not successful fall back to 's' */ 02401 if (option_verbose > 1) 02402 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); 02403 /* XXX the original code used the existing priority in the call to 02404 * ast_exists_extension(), and reset it to 1 afterwards. 02405 * I believe the correct thing is to set it to 1 immediately. 02406 */ 02407 set_ext_pri(c, "s", 1); 02408 if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) { 02409 /* JK02: And finally back to default if everything else failed */ 02410 if (option_verbose > 1) 02411 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); 02412 ast_copy_string(c->context, "default", sizeof(c->context)); 02413 } 02414 } 02415 if (c->cdr && ast_tvzero(c->cdr->start)) 02416 ast_cdr_start(c->cdr); 02417 for (;;) { 02418 char dst_exten[256]; /* buffer to accumulate digits */ 02419 int pos = 0; /* XXX should check bounds */ 02420 int digit = 0; 02421 02422 /* loop on priorities in this context/exten */ 02423 while (ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) { 02424 found = 1; 02425 if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num))) { 02426 /* Something bad happened, or a hangup has been requested. */ 02427 if (strchr("0123456789ABCDEF*#", res)) { 02428 if (option_debug) 02429 ast_log(LOG_DEBUG, "Oooh, got something to jump out with ('%c')!\n", res); 02430 pos = 0; 02431 dst_exten[pos++] = digit = res; 02432 dst_exten[pos] = '\0'; 02433 break; 02434 } 02435 if (res == AST_PBX_KEEPALIVE) { 02436 if (option_debug) 02437 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name); 02438 if (option_verbose > 1) 02439 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name); 02440 error = 1; 02441 break; 02442 } 02443 if (option_debug) 02444 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 02445 if (option_verbose > 1) 02446 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 02447 if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) { 02448 c->_softhangup =0; 02449 } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) { 02450 /* atimeout, nothing bad */ 02451 } else { 02452 if (c->cdr) 02453 ast_cdr_update(c); 02454 error = 1; 02455 break; 02456 } 02457 } 02458 if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT && ast_exists_extension(c,c->context,"T",1,c->cid.cid_num)) { 02459 set_ext_pri(c, "T", 0); /* 0 will become 1 with the c->priority++; at the end */ 02460 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 02461 c->whentohangup = 0; 02462 c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT; 02463 } else if (c->_softhangup) { 02464 if (option_debug) 02465 ast_log(LOG_DEBUG, "Extension %s, priority %d returned normally even though call was hung up\n", 02466 c->exten, c->priority); 02467 error = 1; 02468 break; 02469 } 02470 c->priority++; 02471 } /* end while - from here on we can use 'break' to go out */ 02472 if (error) 02473 break; 02474 02475 /* XXX we get here on non-existing extension or a keypress or hangup ? */ 02476 02477 if (!ast_exists_extension(c, c->context, c->exten, 1, c->cid.cid_num)) { 02478 /* If there is no match at priority 1, it is not a valid extension anymore. 02479 * Try to continue at "i", 1 or exit if the latter does not exist. 02480 */ 02481 if (ast_exists_extension(c, c->context, "i", 1, c->cid.cid_num)) { 02482 if (option_verbose > 2) 02483 ast_verbose(VERBOSE_PREFIX_3 "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, c->name); 02484 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", c->exten); 02485 set_ext_pri(c, "i", 1); 02486 } else { 02487 ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n", 02488 c->name, c->exten, c->context); 02489 error = 1; /* we know what to do with it */ 02490 break; 02491 } 02492 } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) { 02493 /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */ 02494 c->_softhangup = 0; 02495 } else { /* keypress received, get more digits for a full extension */ 02496 int waittime = 0; 02497 if (digit) 02498 waittime = c->pbx->dtimeout; 02499 else if (!autofallthrough) 02500 waittime = c->pbx->rtimeout; 02501 if (!waittime) { 02502 const char *status = pbx_builtin_getvar_helper(c, "DIALSTATUS"); 02503 if (!status) 02504 status = "UNKNOWN"; 02505 if (option_verbose > 2) 02506 ast_verbose(VERBOSE_PREFIX_2 "Auto fallthrough, channel '%s' status is '%s'\n", c->name, status); 02507 if (!strcasecmp(status, "CONGESTION")) 02508 res = pbx_builtin_congestion(c, "10"); 02509 else if (!strcasecmp(status, "CHANUNAVAIL")) 02510 res = pbx_builtin_congestion(c, "10"); 02511 else if (!strcasecmp(status, "BUSY")) 02512 res = pbx_builtin_busy(c, "10"); 02513 error = 1; /* XXX disable message */ 02514 break; /* exit from the 'for' loop */ 02515 } 02516 02517 if (collect_digits(c, waittime, dst_exten, sizeof(dst_exten), pos)) 02518 break; 02519 if (ast_exists_extension(c, c->context, dst_exten, 1, c->cid.cid_num)) /* Prepare the next cycle */ 02520 set_ext_pri(c, dst_exten, 1); 02521 else { 02522 /* No such extension */ 02523 if (!ast_strlen_zero(dst_exten)) { 02524 /* An invalid extension */ 02525 if (ast_exists_extension(c, c->context, "i", 1, c->cid.cid_num)) { 02526 if (option_verbose > 2) 02527 ast_verbose( VERBOSE_PREFIX_3 "Invalid extension '%s' in context '%s' on %s\n", dst_exten, c->context, c->name); 02528 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", dst_exten); 02529 set_ext_pri(c, "i", 1); 02530 } else { 02531 ast_log(LOG_WARNING, "Invalid extension '%s', but no rule 'i' in context '%s'\n", dst_exten, c->context); 02532 found = 1; /* XXX disable message */ 02533 break; 02534 } 02535 } else { 02536 /* A simple timeout */ 02537 if (ast_exists_extension(c, c->context, "t", 1, c->cid.cid_num)) { 02538 if (option_verbose > 2) 02539 ast_verbose( VERBOSE_PREFIX_3 "Timeout on %s\n", c->name); 02540 set_ext_pri(c, "t", 1); 02541 } else { 02542 ast_log(LOG_WARNING, "Timeout, but no rule 't' in context '%s'\n", c->context); 02543 found = 1; /* XXX disable message */ 02544 break; 02545 } 02546 } 02547 } 02548 if (c->cdr) { 02549 if (option_verbose > 2) 02550 ast_verbose(VERBOSE_PREFIX_2 "CDR updated on %s\n",c->name); 02551 ast_cdr_update(c); 02552 } 02553 } 02554 } 02555 if (!found && !error) 02556 ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name); 02557 if (res != AST_PBX_KEEPALIVE) 02558 ast_softhangup(c, c->hangupcause ? c->hangupcause : AST_CAUSE_NORMAL_CLEARING); 02559 if ((res != AST_PBX_KEEPALIVE) && ast_exists_extension(c, c->context, "h", 1, c->cid.cid_num)) { 02560 if (c->cdr && ast_opt_end_cdr_before_h_exten) 02561 ast_cdr_end(c->cdr); 02562 set_ext_pri(c, "h", 1); 02563 while(ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) { 02564 if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num))) { 02565 /* Something bad happened, or a hangup has been requested. */ 02566 if (option_debug) 02567 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 02568 if (option_verbose > 1) 02569 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 02570 break; 02571 } 02572 c->priority++; 02573 } 02574 } 02575 ast_set2_flag(c, autoloopflag, AST_FLAG_IN_AUTOLOOP); 02576 02577 pbx_destroy(c->pbx); 02578 c->pbx = NULL; 02579 if (res != AST_PBX_KEEPALIVE) 02580 ast_hangup(c); 02581 return 0; 02582 }
static int _extension_match_core | ( | const char * | pattern, | |
const char * | data, | |||
enum ext_match_t | mode | |||
) | [static] |
Definition at line 774 of file pbx.c.
References ast_log(), E_MATCH, E_MATCH_MASK, E_MATCHMORE, and LOG_WARNING.
Referenced by extension_match_core().
00775 { 00776 mode &= E_MATCH_MASK; /* only consider the relevant bits */ 00777 00778 if ( (mode == E_MATCH) && (pattern[0] == '_') && (strcasecmp(pattern,data)==0) ) /* note: if this test is left out, then _x. will not match _x. !!! */ 00779 return 1; 00780 00781 if (pattern[0] != '_') { /* not a pattern, try exact or partial match */ 00782 int ld = strlen(data), lp = strlen(pattern); 00783 00784 if (lp < ld) /* pattern too short, cannot match */ 00785 return 0; 00786 /* depending on the mode, accept full or partial match or both */ 00787 if (mode == E_MATCH) 00788 return !strcmp(pattern, data); /* 1 on match, 0 on fail */ 00789 if (ld == 0 || !strncasecmp(pattern, data, ld)) /* partial or full match */ 00790 return (mode == E_MATCHMORE) ? lp > ld : 1; /* XXX should consider '!' and '/' ? */ 00791 else 00792 return 0; 00793 } 00794 pattern++; /* skip leading _ */ 00795 /* 00796 * XXX below we stop at '/' which is a separator for the CID info. However we should 00797 * not store '/' in the pattern at all. When we insure it, we can remove the checks. 00798 */ 00799 while (*data && *pattern && *pattern != '/') { 00800 const char *end; 00801 00802 if (*data == '-') { /* skip '-' in data (just a separator) */ 00803 data++; 00804 continue; 00805 } 00806 switch (toupper(*pattern)) { 00807 case '[': /* a range */ 00808 end = strchr(pattern+1, ']'); /* XXX should deal with escapes ? */ 00809 if (end == NULL) { 00810 ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n"); 00811 return 0; /* unconditional failure */ 00812 } 00813 for (pattern++; pattern != end; pattern++) { 00814 if (pattern+2 < end && pattern[1] == '-') { /* this is a range */ 00815 if (*data >= pattern[0] && *data <= pattern[2]) 00816 break; /* match found */ 00817 else { 00818 pattern += 2; /* skip a total of 3 chars */ 00819 continue; 00820 } 00821 } else if (*data == pattern[0]) 00822 break; /* match found */ 00823 } 00824 if (pattern == end) 00825 return 0; 00826 pattern = end; /* skip and continue */ 00827 break; 00828 case 'N': 00829 if (*data < '2' || *data > '9') 00830 return 0; 00831 break; 00832 case 'X': 00833 if (*data < '0' || *data > '9') 00834 return 0; 00835 break; 00836 case 'Z': 00837 if (*data < '1' || *data > '9') 00838 return 0; 00839 break; 00840 case '.': /* Must match, even with more digits */ 00841 return 1; 00842 case '!': /* Early match */ 00843 return 2; 00844 case ' ': 00845 case '-': /* Ignore these in patterns */ 00846 data--; /* compensate the final data++ */ 00847 break; 00848 default: 00849 if (*data != *pattern) 00850 return 0; 00851 } 00852 data++; 00853 pattern++; 00854 } 00855 if (*data) /* data longer than pattern, no match */ 00856 return 0; 00857 /* 00858 * match so far, but ran off the end of the data. 00859 * Depending on what is next, determine match or not. 00860 */ 00861 if (*pattern == '\0' || *pattern == '/') /* exact match */ 00862 return (mode == E_MATCHMORE) ? 0 : 1; /* this is a failure for E_MATCHMORE */ 00863 else if (*pattern == '!') /* early match */ 00864 return 2; 00865 else /* partial match */ 00866 return (mode == E_MATCH) ? 0 : 1; /* this is a failure for E_MATCH */ 00867 }
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 4689 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().
04691 { 04692 struct ast_exten *ep; 04693 04694 for (ep = NULL; e ; ep = e, e = e->peer) { 04695 if (e->priority >= tmp->priority) 04696 break; 04697 } 04698 if (!e) { /* go at the end, and ep is surely set because the list is not empty */ 04699 ep->peer = tmp; 04700 return 0; /* success */ 04701 } 04702 if (e->priority == tmp->priority) { 04703 /* Can't have something exactly the same. Is this a 04704 replacement? If so, replace, otherwise, bonk. */ 04705 if (!replace) { 04706 ast_log(LOG_WARNING, "Unable to register extension '%s', priority %d in '%s', already in use\n", tmp->exten, tmp->priority, con->name); 04707 if (tmp->datad) 04708 tmp->datad(tmp->data); 04709 free(tmp); 04710 return -1; 04711 } 04712 /* we are replacing e, so copy the link fields and then update 04713 * whoever pointed to e to point to us 04714 */ 04715 tmp->next = e->next; /* not meaningful if we are not first in the peer list */ 04716 tmp->peer = e->peer; /* always meaningful */ 04717 if (ep) /* We're in the peer list, just insert ourselves */ 04718 ep->peer = tmp; 04719 else if (el) /* We're the first extension. Take over e's functions */ 04720 el->next = tmp; 04721 else /* We're the very first extension. */ 04722 con->root = tmp; 04723 if (tmp->priority == PRIORITY_HINT) 04724 ast_change_hint(e,tmp); 04725 /* Destroy the old one */ 04726 if (e->datad) 04727 e->datad(e->data); 04728 free(e); 04729 } else { /* Slip ourselves in just before e */ 04730 tmp->peer = e; 04731 tmp->next = e->next; /* extension chain, or NULL if e is not the first extension */ 04732 if (ep) /* Easy enough, we're just in the peer list */ 04733 ep->peer = tmp; 04734 else { /* we are the first in some peer list, so link in the ext list */ 04735 if (el) 04736 el->next = tmp; /* in the middle... */ 04737 else 04738 con->root = tmp; /* ... or at the head */ 04739 e->next = NULL; /* e is no more at the head, so e->next must be reset */ 04740 } 04741 /* And immediately return success. */ 04742 if (tmp->priority == PRIORITY_HINT) 04743 ast_add_hint(tmp); 04744 } 04745 return 0; 04746 }
int ast_active_calls | ( | void | ) |
Retrieve the number of active calls.
Definition at line 2687 of file pbx.c.
References countcalls.
Referenced by handle_chanlist(), and handle_chanlist_deprecated().
02688 { 02689 return countcalls; 02690 }
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 4564 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().
04567 { 04568 int ret = -1; 04569 struct ast_context *c = find_context_locked(context); 04570 04571 if (c) { 04572 ret = ast_add_extension2(c, replace, extension, priority, label, callerid, 04573 application, data, datad, registrar); 04574 ast_unlock_contexts(); 04575 } 04576 return ret; 04577 }
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 4773 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(), do_parking_thread(), park_call_full(), pbx_load_config(), and pbx_load_users().
04777 { 04778 /* 04779 * Sort extensions (or patterns) according to the rules indicated above. 04780 * These are implemented by the function ext_cmp()). 04781 * All priorities for the same ext/pattern/cid are kept in a list, 04782 * using the 'peer' field as a link field.. 04783 */ 04784 struct ast_exten *tmp, *e, *el = NULL; 04785 int res; 04786 int length; 04787 char *p; 04788 char expand_buf[VAR_BUF_SIZE] = { 0, }; 04789 04790 /* if we are adding a hint, and there are global variables, and the hint 04791 contains variable references, then expand them 04792 */ 04793 ast_mutex_lock(&globalslock); 04794 if (priority == PRIORITY_HINT && AST_LIST_FIRST(&globals) && strstr(application, "${")) { 04795 pbx_substitute_variables_varshead(&globals, application, expand_buf, sizeof(expand_buf)); 04796 application = expand_buf; 04797 } 04798 ast_mutex_unlock(&globalslock); 04799 04800 length = sizeof(struct ast_exten); 04801 length += strlen(extension) + 1; 04802 length += strlen(application) + 1; 04803 if (label) 04804 length += strlen(label) + 1; 04805 if (callerid) 04806 length += strlen(callerid) + 1; 04807 else 04808 length ++; /* just the '\0' */ 04809 04810 /* Be optimistic: Build the extension structure first */ 04811 if (!(tmp = ast_calloc(1, length))) 04812 return -1; 04813 04814 /* use p as dst in assignments, as the fields are const char * */ 04815 p = tmp->stuff; 04816 if (label) { 04817 tmp->label = p; 04818 strcpy(p, label); 04819 p += strlen(label) + 1; 04820 } 04821 tmp->exten = p; 04822 p += ext_strncpy(p, extension, strlen(extension) + 1) + 1; 04823 tmp->priority = priority; 04824 tmp->cidmatch = p; /* but use p for assignments below */ 04825 if (callerid) { 04826 p += ext_strncpy(p, callerid, strlen(callerid) + 1) + 1; 04827 tmp->matchcid = 1; 04828 } else { 04829 *p++ = '\0'; 04830 tmp->matchcid = 0; 04831 } 04832 tmp->app = p; 04833 strcpy(p, application); 04834 tmp->parent = con; 04835 tmp->data = data; 04836 tmp->datad = datad; 04837 tmp->registrar = registrar; 04838 04839 ast_mutex_lock(&con->lock); 04840 res = 0; /* some compilers will think it is uninitialized otherwise */ 04841 for (e = con->root; e; el = e, e = e->next) { /* scan the extension list */ 04842 res = ext_cmp(e->exten, extension); 04843 if (res == 0) { /* extension match, now look at cidmatch */ 04844 if (!e->matchcid && !tmp->matchcid) 04845 res = 0; 04846 else if (tmp->matchcid && !e->matchcid) 04847 res = 1; 04848 else if (e->matchcid && !tmp->matchcid) 04849 res = -1; 04850 else 04851 res = strcasecmp(e->cidmatch, tmp->cidmatch); 04852 } 04853 if (res >= 0) 04854 break; 04855 } 04856 if (e && res == 0) { /* exact match, insert in the pri chain */ 04857 res = add_pri(con, tmp, el, e, replace); 04858 ast_mutex_unlock(&con->lock); 04859 if (res < 0) { 04860 errno = EEXIST; /* XXX do we care ? */ 04861 return 0; /* XXX should we return -1 maybe ? */ 04862 } 04863 } else { 04864 /* 04865 * not an exact match, this is the first entry with this pattern, 04866 * so insert in the main list right before 'e' (if any) 04867 */ 04868 tmp->next = e; 04869 if (el) 04870 el->next = tmp; 04871 else 04872 con->root = tmp; 04873 ast_mutex_unlock(&con->lock); 04874 if (tmp->priority == PRIORITY_HINT) 04875 ast_add_hint(tmp); 04876 } 04877 if (option_debug) { 04878 if (tmp->matchcid) { 04879 if (option_debug) 04880 ast_log(LOG_DEBUG, "Added extension '%s' priority %d (CID match '%s') to %s\n", 04881 tmp->exten, tmp->priority, tmp->cidmatch, con->name); 04882 } else { 04883 if (option_debug) 04884 ast_log(LOG_DEBUG, "Added extension '%s' priority %d to %s\n", 04885 tmp->exten, tmp->priority, con->name); 04886 } 04887 } 04888 if (option_verbose > 2) { 04889 if (tmp->matchcid) { 04890 ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d (CID match '%s')to %s\n", 04891 tmp->exten, tmp->priority, tmp->cidmatch, con->name); 04892 } else { 04893 ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d to %s\n", 04894 tmp->exten, tmp->priority, con->name); 04895 } 04896 } 04897 return 0; 04898 }
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 2187 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().
02188 { 02189 struct ast_hint *hint; 02190 02191 if (!e) 02192 return -1; 02193 02194 AST_LIST_LOCK(&hints); 02195 02196 /* Search if hint exists, do nothing */ 02197 AST_LIST_TRAVERSE(&hints, hint, list) { 02198 if (hint->exten == e) { 02199 AST_LIST_UNLOCK(&hints); 02200 if (option_debug > 1) 02201 ast_log(LOG_DEBUG, "HINTS: Not re-adding existing hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e)); 02202 return -1; 02203 } 02204 } 02205 02206 if (option_debug > 1) 02207 ast_log(LOG_DEBUG, "HINTS: Adding hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e)); 02208 02209 if (!(hint = ast_calloc(1, sizeof(*hint)))) { 02210 AST_LIST_UNLOCK(&hints); 02211 return -1; 02212 } 02213 /* Initialize and insert new item at the top */ 02214 hint->exten = e; 02215 hint->laststate = ast_extension_state2(e); 02216 AST_LIST_INSERT_HEAD(&hints, hint, list); 02217 02218 AST_LIST_UNLOCK(&hints); 02219 return 0; 02220 }
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 4602 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().
04603 { 04604 int res = 0; 04605 04606 ast_channel_lock(chan); 04607 04608 if (chan->pbx) { /* This channel is currently in the PBX */ 04609 ast_explicit_goto(chan, context, exten, priority); 04610 ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO); 04611 } else { 04612 /* In order to do it when the channel doesn't really exist within 04613 the PBX, we have to make a new channel, masquerade, and start the PBX 04614 at the new location */ 04615 struct ast_channel *tmpchan = ast_channel_alloc(0, chan->_state, 0, 0, chan->accountcode, chan->exten, chan->context, chan->amaflags, "AsyncGoto/%s", chan->name); 04616 if (chan->cdr) { 04617 ast_cdr_discard(tmpchan->cdr); 04618 tmpchan->cdr = ast_cdr_dup(chan->cdr); /* share the love */ 04619 } 04620 if (!tmpchan) 04621 res = -1; 04622 else { 04623 /* Make formats okay */ 04624 tmpchan->readformat = chan->readformat; 04625 tmpchan->writeformat = chan->writeformat; 04626 /* Setup proper location */ 04627 ast_explicit_goto(tmpchan, 04628 S_OR(context, chan->context), S_OR(exten, chan->exten), priority); 04629 04630 /* Masquerade into temp channel */ 04631 ast_channel_masquerade(tmpchan, chan); 04632 04633 /* Grab the locks and get going */ 04634 ast_channel_lock(tmpchan); 04635 ast_do_masquerade(tmpchan); 04636 ast_channel_unlock(tmpchan); 04637 /* Start the PBX going on our stolen channel */ 04638 if (ast_pbx_start(tmpchan)) { 04639 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name); 04640 ast_hangup(tmpchan); 04641 res = -1; 04642 } 04643 } 04644 } 04645 ast_channel_unlock(chan); 04646 return res; 04647 }
int ast_async_goto_by_name | ( | const char * | channame, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 4649 of file pbx.c.
References ast_async_goto(), ast_channel_unlock, and ast_get_channel_by_name_locked().
04650 { 04651 struct ast_channel *chan; 04652 int res = -1; 04653 04654 chan = ast_get_channel_by_name_locked(channame); 04655 if (chan) { 04656 res = ast_async_goto(chan, context, exten, priority); 04657 ast_channel_unlock(chan); 04658 } 04659 return res; 04660 }
int ast_async_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 6367 of file pbx.c.
References __ast_goto_if_exists().
Referenced by asyncgoto_exec().
06368 { 06369 return __ast_goto_if_exists(chan, context, exten, priority, 1); 06370 }
int ast_build_timing | ( | struct ast_timing * | i, | |
const char * | info_in | |||
) |
Definition at line 4247 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().
04248 { 04249 char info_save[256]; 04250 char *info; 04251 04252 /* Check for empty just in case */ 04253 if (ast_strlen_zero(info_in)) 04254 return 0; 04255 /* make a copy just in case we were passed a static string */ 04256 ast_copy_string(info_save, info_in, sizeof(info_save)); 04257 info = info_save; 04258 /* Assume everything except time */ 04259 i->monthmask = 0xfff; /* 12 bits */ 04260 i->daymask = 0x7fffffffU; /* 31 bits */ 04261 i->dowmask = 0x7f; /* 7 bits */ 04262 /* on each call, use strsep() to move info to the next argument */ 04263 get_timerange(i, strsep(&info, "|")); 04264 if (info) 04265 i->dowmask = get_range(strsep(&info, "|"), 7, days, "day of week"); 04266 if (info) 04267 i->daymask = get_range(strsep(&info, "|"), 31, NULL, "day"); 04268 if (info) 04269 i->monthmask = get_range(strsep(&info, "|"), 12, months, "month"); 04270 return 1; 04271 }
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 2311 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(), nv_background_detect_exec(), nv_detectfax_exec(), phone_check_exception(), skinny_ss(), ss_thread(), and valid_exit().
02312 { 02313 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH); 02314 }
ast_change_hint: Change hint for an extension
Definition at line 2223 of file pbx.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, and ast_hint::exten.
Referenced by add_pri().
02224 { 02225 struct ast_hint *hint; 02226 int res = -1; 02227 02228 AST_LIST_LOCK(&hints); 02229 AST_LIST_TRAVERSE(&hints, hint, list) { 02230 if (hint->exten == oe) { 02231 hint->exten = ne; 02232 res = 0; 02233 break; 02234 } 02235 } 02236 AST_LIST_UNLOCK(&hints); 02237 02238 return res; 02239 }
int ast_check_timing | ( | const struct ast_timing * | i | ) |
Definition at line 4273 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().
04274 { 04275 struct tm tm; 04276 time_t t = time(NULL); 04277 04278 ast_localtime(&t, &tm, NULL); 04279 04280 /* If it's not the right month, return */ 04281 if (!(i->monthmask & (1 << tm.tm_mon))) 04282 return 0; 04283 04284 /* If it's not that time of the month.... */ 04285 /* Warning, tm_mday has range 1..31! */ 04286 if (!(i->daymask & (1 << (tm.tm_mday-1)))) 04287 return 0; 04288 04289 /* If it's not the right day of the week */ 04290 if (!(i->dowmask & (1 << tm.tm_wday))) 04291 return 0; 04292 04293 /* Sanity check the hour just to be safe */ 04294 if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) { 04295 ast_log(LOG_WARNING, "Insane time...\n"); 04296 return 0; 04297 } 04298 04299 /* Now the tough part, we calculate if it fits 04300 in the right time based on min/hour */ 04301 if (!(i->minmask[tm.tm_hour] & (1 << (tm.tm_min / 2)))) 04302 return 0; 04303 04304 /* If we got this far, then we're good */ 04305 return 1; 04306 }
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 4500 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().
04501 { 04502 int ret = -1; 04503 struct ast_context *c = find_context_locked(context); 04504 04505 if (c) { 04506 ret = ast_context_add_ignorepat2(c, value, registrar); 04507 ast_unlock_contexts(); 04508 } 04509 return ret; 04510 }
int ast_context_add_ignorepat2 | ( | struct ast_context * | con, | |
const char * | value, | |||
const char * | registrar | |||
) |
Definition at line 4512 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().
04513 { 04514 struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL; 04515 int length; 04516 length = sizeof(struct ast_ignorepat); 04517 length += strlen(value) + 1; 04518 if (!(ignorepat = ast_calloc(1, length))) 04519 return -1; 04520 /* The cast to char * is because we need to write the initial value. 04521 * The field is not supposed to be modified otherwise 04522 */ 04523 strcpy((char *)ignorepat->pattern, value); 04524 ignorepat->next = NULL; 04525 ignorepat->registrar = registrar; 04526 ast_mutex_lock(&con->lock); 04527 for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) { 04528 ignorepatl = ignorepatc; 04529 if (!strcasecmp(ignorepatc->pattern, value)) { 04530 /* Already there */ 04531 ast_mutex_unlock(&con->lock); 04532 errno = EEXIST; 04533 return -1; 04534 } 04535 } 04536 if (ignorepatl) 04537 ignorepatl->next = ignorepat; 04538 else 04539 con->ignorepats = ignorepat; 04540 ast_mutex_unlock(&con->lock); 04541 return 0; 04542 04543 }
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 4053 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().
04054 { 04055 int ret = -1; 04056 struct ast_context *c = find_context_locked(context); 04057 04058 if (c) { 04059 ret = ast_context_add_include2(c, include, registrar); 04060 ast_unlock_contexts(); 04061 } 04062 return ret; 04063 }
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 4315 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().
04317 { 04318 struct ast_include *new_include; 04319 char *c; 04320 struct ast_include *i, *il = NULL; /* include, include_last */ 04321 int length; 04322 char *p; 04323 04324 length = sizeof(struct ast_include); 04325 length += 2 * (strlen(value) + 1); 04326 04327 /* allocate new include structure ... */ 04328 if (!(new_include = ast_calloc(1, length))) 04329 return -1; 04330 /* Fill in this structure. Use 'p' for assignments, as the fields 04331 * in the structure are 'const char *' 04332 */ 04333 p = new_include->stuff; 04334 new_include->name = p; 04335 strcpy(p, value); 04336 p += strlen(value) + 1; 04337 new_include->rname = p; 04338 strcpy(p, value); 04339 /* Strip off timing info, and process if it is there */ 04340 if ( (c = strchr(p, '|')) ) { 04341 *c++ = '\0'; 04342 new_include->hastime = ast_build_timing(&(new_include->timing), c); 04343 } 04344 new_include->next = NULL; 04345 new_include->registrar = registrar; 04346 04347 ast_mutex_lock(&con->lock); 04348 04349 /* ... go to last include and check if context is already included too... */ 04350 for (i = con->includes; i; i = i->next) { 04351 if (!strcasecmp(i->name, new_include->name)) { 04352 free(new_include); 04353 ast_mutex_unlock(&con->lock); 04354 errno = EEXIST; 04355 return -1; 04356 } 04357 il = i; 04358 } 04359 04360 /* ... include new context into context list, unlock, return */ 04361 if (il) 04362 il->next = new_include; 04363 else 04364 con->includes = new_include; 04365 if (option_verbose > 2) 04366 ast_verbose(VERBOSE_PREFIX_3 "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con)); 04367 ast_mutex_unlock(&con->lock); 04368 04369 return 0; 04370 }
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 4377 of file pbx.c.
References ast_context_add_switch2(), ast_unlock_contexts(), and find_context_locked().
04378 { 04379 int ret = -1; 04380 struct ast_context *c = find_context_locked(context); 04381 04382 if (c) { /* found, add switch to this context */ 04383 ret = ast_context_add_switch2(c, sw, data, eval, registrar); 04384 ast_unlock_contexts(); 04385 } 04386 return ret; 04387 }
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 4396 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().
04398 { 04399 struct ast_sw *new_sw; 04400 struct ast_sw *i; 04401 int length; 04402 char *p; 04403 04404 length = sizeof(struct ast_sw); 04405 length += strlen(value) + 1; 04406 if (data) 04407 length += strlen(data); 04408 length++; 04409 04410 /* allocate new sw structure ... */ 04411 if (!(new_sw = ast_calloc(1, length))) 04412 return -1; 04413 /* ... fill in this structure ... */ 04414 p = new_sw->stuff; 04415 new_sw->name = p; 04416 strcpy(new_sw->name, value); 04417 p += strlen(value) + 1; 04418 new_sw->data = p; 04419 if (data) { 04420 strcpy(new_sw->data, data); 04421 p += strlen(data) + 1; 04422 } else { 04423 strcpy(new_sw->data, ""); 04424 p++; 04425 } 04426 new_sw->eval = eval; 04427 new_sw->registrar = registrar; 04428 04429 /* ... try to lock this context ... */ 04430 ast_mutex_lock(&con->lock); 04431 04432 /* ... go to last sw and check if context is already swd too... */ 04433 AST_LIST_TRAVERSE(&con->alts, i, list) { 04434 if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) { 04435 free(new_sw); 04436 ast_mutex_unlock(&con->lock); 04437 errno = EEXIST; 04438 return -1; 04439 } 04440 } 04441 04442 /* ... sw new context into context list, unlock, return */ 04443 AST_LIST_INSERT_TAIL(&con->alts, new_sw, list); 04444 04445 if (option_verbose > 2) 04446 ast_verbose(VERBOSE_PREFIX_3 "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con)); 04447 04448 ast_mutex_unlock(&con->lock); 04449 04450 return 0; 04451 }
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 3923 of file pbx.c.
References __ast_context_create().
Referenced by do_parking_thread(), park_call_full(), and set_config().
03924 { 03925 return __ast_context_create(extcontexts, name, registrar, 0); 03926 }
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 5365 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().
05366 { 05367 ast_wrlock_contexts(); 05368 __ast_context_destroy(con,registrar); 05369 ast_unlock_contexts(); 05370 }
struct ast_context* ast_context_find | ( | const char * | name | ) |
Find a context.
name | name of the context to find |
Definition at line 897 of file pbx.c.
References ast_rdlock_contexts(), ast_unlock_contexts(), and ast_walk_contexts().
Referenced by _macro_exec(), ast_context_verify_includes(), ast_ignore_pattern(), cleanup_stale_contexts(), do_parking_thread(), park_call_full(), park_exec(), register_peer_exten(), and set_config().
00898 { 00899 struct ast_context *tmp = NULL; 00900 00901 ast_rdlock_contexts(); 00902 00903 while ( (tmp = ast_walk_contexts(tmp)) ) { 00904 if (!name || !strcasecmp(name, tmp->name)) 00905 break; 00906 } 00907 00908 ast_unlock_contexts(); 00909 00910 return tmp; 00911 }
struct ast_context* ast_context_find_or_create | ( | struct ast_context ** | extcontexts, | |
const char * | name, | |||
const char * | registrar | |||
) |
Register a new context or find an existing one.
extcontexts | pointer to the ast_context structure pointer | |
name | name of the new context | |
registrar | registrar of the context |
Definition at line 3928 of file pbx.c.
References __ast_context_create().
Referenced by pbx_load_config(), and pbx_load_users().
03929 { 03930 return __ast_context_create(extcontexts, name, registrar, 1); 03931 }
int ast_context_lockmacro | ( | const char * | context | ) |
locks the macrolock in the given given context
Definition at line 2924 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().
02925 { 02926 struct ast_context *c = NULL; 02927 int ret = -1; 02928 02929 ast_rdlock_contexts(); 02930 02931 while ((c = ast_walk_contexts(c))) { 02932 if (!strcmp(ast_get_context_name(c), context)) { 02933 ret = 0; 02934 break; 02935 } 02936 } 02937 02938 ast_unlock_contexts(); 02939 02940 /* if we found context, lock macrolock */ 02941 if (ret == 0) 02942 ret = ast_mutex_lock(&c->macrolock); 02943 02944 return ret; 02945 }
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 2825 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().
02826 { 02827 int ret = -1; /* default error return */ 02828 struct ast_context *c = find_context_locked(context); 02829 02830 if (c) { /* ... remove extension ... */ 02831 ret = ast_context_remove_extension2(c, extension, priority, registrar); 02832 ast_unlock_contexts(); 02833 } 02834 return ret; 02835 }
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 2847 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_parking_thread(), and park_exec().
02848 { 02849 struct ast_exten *exten, *prev_exten = NULL; 02850 struct ast_exten *peer; 02851 02852 ast_mutex_lock(&con->lock); 02853 02854 /* scan the extension list to find matching extension-registrar */ 02855 for (exten = con->root; exten; prev_exten = exten, exten = exten->next) { 02856 if (!strcmp(exten->exten, extension) && 02857 (!registrar || !strcmp(exten->registrar, registrar))) 02858 break; 02859 } 02860 if (!exten) { 02861 /* we can't find right extension */ 02862 ast_mutex_unlock(&con->lock); 02863 return -1; 02864 } 02865 02866 /* should we free all peers in this extension? (priority == 0)? */ 02867 if (priority == 0) { 02868 /* remove this extension from context list */ 02869 if (prev_exten) 02870 prev_exten->next = exten->next; 02871 else 02872 con->root = exten->next; 02873 02874 /* fire out all peers */ 02875 while ( (peer = exten) ) { 02876 exten = peer->peer; /* prepare for next entry */ 02877 destroy_exten(peer); 02878 } 02879 } else { 02880 /* scan the priority list to remove extension with exten->priority == priority */ 02881 struct ast_exten *previous_peer = NULL; 02882 02883 for (peer = exten; peer; previous_peer = peer, peer = peer->peer) { 02884 if (peer->priority == priority && 02885 (!registrar || !strcmp(peer->registrar, registrar) )) 02886 break; /* found our priority */ 02887 } 02888 if (!peer) { /* not found */ 02889 ast_mutex_unlock(&con->lock); 02890 return -1; 02891 } 02892 /* we are first priority extension? */ 02893 if (!previous_peer) { 02894 /* 02895 * We are first in the priority chain, so must update the extension chain. 02896 * The next node is either the next priority or the next extension 02897 */ 02898 struct ast_exten *next_node = peer->peer ? peer->peer : peer->next; 02899 02900 if (!prev_exten) /* change the root... */ 02901 con->root = next_node; 02902 else 02903 prev_exten->next = next_node; /* unlink */ 02904 if (peer->peer) /* XXX update the new head of the pri list */ 02905 peer->peer->next = peer->next; 02906 } else { /* easy, we are not first priority in extension */ 02907 previous_peer->peer = peer->peer; 02908 } 02909 02910 /* now, free whole priority extension */ 02911 destroy_exten(peer); 02912 /* XXX should we return -1 ? */ 02913 } 02914 ast_mutex_unlock(&con->lock); 02915 return 0; 02916 }
int ast_context_remove_ignorepat | ( | const char * | context, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 4457 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().
04458 { 04459 int ret = -1; 04460 struct ast_context *c = find_context_locked(context); 04461 04462 if (c) { 04463 ret = ast_context_remove_ignorepat2(c, ignorepat, registrar); 04464 ast_unlock_contexts(); 04465 } 04466 return ret; 04467 }
int ast_context_remove_ignorepat2 | ( | struct ast_context * | con, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 4469 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().
04470 { 04471 struct ast_ignorepat *ip, *ipl = NULL; 04472 04473 ast_mutex_lock(&con->lock); 04474 04475 for (ip = con->ignorepats; ip; ip = ip->next) { 04476 if (!strcmp(ip->pattern, ignorepat) && 04477 (!registrar || (registrar == ip->registrar))) { 04478 if (ipl) { 04479 ipl->next = ip->next; 04480 free(ip); 04481 } else { 04482 con->ignorepats = ip->next; 04483 free(ip); 04484 } 04485 ast_mutex_unlock(&con->lock); 04486 return 0; 04487 } 04488 ipl = ip; 04489 } 04490 04491 ast_mutex_unlock(&con->lock); 04492 errno = EINVAL; 04493 return -1; 04494 }
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 2721 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().
02722 { 02723 int ret = -1; 02724 struct ast_context *c = find_context_locked(context); 02725 02726 if (c) { 02727 /* found, remove include from this context ... */ 02728 ret = ast_context_remove_include2(c, include, registrar); 02729 ast_unlock_contexts(); 02730 } 02731 return ret; 02732 }
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 2742 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().
02743 { 02744 struct ast_include *i, *pi = NULL; 02745 int ret = -1; 02746 02747 ast_mutex_lock(&con->lock); 02748 02749 /* find our include */ 02750 for (i = con->includes; i; pi = i, i = i->next) { 02751 if (!strcmp(i->name, include) && 02752 (!registrar || !strcmp(i->registrar, registrar))) { 02753 /* remove from list */ 02754 if (pi) 02755 pi->next = i->next; 02756 else 02757 con->includes = i->next; 02758 /* free include and return */ 02759 free(i); 02760 ret = 0; 02761 break; 02762 } 02763 } 02764 02765 ast_mutex_unlock(&con->lock); 02766 return ret; 02767 }
int ast_context_remove_switch | ( | const char * | context, | |
const char * | sw, | |||
const char * | data, | |||
const char * | registrar | |||
) |
Remove a switch.
Definition at line 2774 of file pbx.c.
References ast_context_remove_switch2(), ast_unlock_contexts(), and find_context_locked().
02775 { 02776 int ret = -1; /* default error return */ 02777 struct ast_context *c = find_context_locked(context); 02778 02779 if (c) { 02780 /* remove switch from this context ... */ 02781 ret = ast_context_remove_switch2(c, sw, data, registrar); 02782 ast_unlock_contexts(); 02783 } 02784 return ret; 02785 }
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 2795 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().
02796 { 02797 struct ast_sw *i; 02798 int ret = -1; 02799 02800 ast_mutex_lock(&con->lock); 02801 02802 /* walk switches */ 02803 AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) { 02804 if (!strcmp(i->name, sw) && !strcmp(i->data, data) && 02805 (!registrar || !strcmp(i->registrar, registrar))) { 02806 /* found, remove from list */ 02807 AST_LIST_REMOVE_CURRENT(&con->alts, list); 02808 free(i); /* free switch and return */ 02809 ret = 0; 02810 break; 02811 } 02812 } 02813 AST_LIST_TRAVERSE_SAFE_END 02814 02815 ast_mutex_unlock(&con->lock); 02816 02817 return ret; 02818 }
int ast_context_unlockmacro | ( | const char * | context | ) |
Unlocks the macrolock in the given context.
Definition at line 2952 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().
02953 { 02954 struct ast_context *c = NULL; 02955 int ret = -1; 02956 02957 ast_rdlock_contexts(); 02958 02959 while ((c = ast_walk_contexts(c))) { 02960 if (!strcmp(ast_get_context_name(c), context)) { 02961 ret = 0; 02962 break; 02963 } 02964 } 02965 02966 ast_unlock_contexts(); 02967 02968 /* if we found context, unlock macrolock */ 02969 if (ret == 0) 02970 ret = ast_mutex_unlock(&c->macrolock); 02971 02972 return ret; 02973 }
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 6324 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().
06325 { 06326 struct ast_include *inc = NULL; 06327 int res = 0; 06328 06329 while ( (inc = ast_walk_context_includes(con, inc)) ) { 06330 if (ast_context_find(inc->rname)) 06331 continue; 06332 06333 res = -1; 06334 ast_log(LOG_WARNING, "Context '%s' tries includes nonexistent context '%s'\n", 06335 ast_get_context_name(con), inc->rname); 06336 break; 06337 } 06338 06339 return res; 06340 }
struct ast_custom_function* ast_custom_function_find | ( | const char * | name | ) |
Definition at line 1460 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().
01461 { 01462 struct ast_custom_function *acf = NULL; 01463 01464 AST_LIST_LOCK(&acf_root); 01465 AST_LIST_TRAVERSE(&acf_root, acf, acflist) { 01466 if (!strcmp(name, acf->name)) 01467 break; 01468 } 01469 AST_LIST_UNLOCK(&acf_root); 01470 01471 return acf; 01472 }
int ast_custom_function_register | ( | struct ast_custom_function * | acf | ) |
Reigster a custom function.
Definition at line 1496 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().
01497 { 01498 struct ast_custom_function *cur; 01499 01500 if (!acf) 01501 return -1; 01502 01503 AST_LIST_LOCK(&acf_root); 01504 01505 if (ast_custom_function_find(acf->name)) { 01506 ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name); 01507 AST_LIST_UNLOCK(&acf_root); 01508 return -1; 01509 } 01510 01511 /* Store in alphabetical order */ 01512 AST_LIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) { 01513 if (strcasecmp(acf->name, cur->name) < 0) { 01514 AST_LIST_INSERT_BEFORE_CURRENT(&acf_root, acf, acflist); 01515 break; 01516 } 01517 } 01518 AST_LIST_TRAVERSE_SAFE_END 01519 if (!cur) 01520 AST_LIST_INSERT_TAIL(&acf_root, acf, acflist); 01521 01522 AST_LIST_UNLOCK(&acf_root); 01523 01524 if (option_verbose > 1) 01525 ast_verbose(VERBOSE_PREFIX_2 "Registered custom function %s\n", acf->name); 01526 01527 return 0; 01528 }
int ast_custom_function_unregister | ( | struct ast_custom_function * | acf | ) |
Unregister a custom function.
Definition at line 1474 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().
01475 { 01476 struct ast_custom_function *cur; 01477 01478 if (!acf) 01479 return -1; 01480 01481 AST_LIST_LOCK(&acf_root); 01482 AST_LIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) { 01483 if (cur == acf) { 01484 AST_LIST_REMOVE_CURRENT(&acf_root, acflist); 01485 if (option_verbose > 1) 01486 ast_verbose(VERBOSE_PREFIX_2 "Unregistered custom function %s\n", acf->name); 01487 break; 01488 } 01489 } 01490 AST_LIST_TRAVERSE_SAFE_END 01491 AST_LIST_UNLOCK(&acf_root); 01492 01493 return acf ? 0 : -1; 01494 }
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 2296 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(), 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(), nv_background_detect_exec(), nv_detectfax_exec(), 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().
02297 { 02298 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH); 02299 }
int ast_explicit_goto | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 4579 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().
04580 { 04581 if (!chan) 04582 return -1; 04583 04584 ast_channel_lock(chan); 04585 04586 if (!ast_strlen_zero(context)) 04587 ast_copy_string(chan->context, context, sizeof(chan->context)); 04588 if (!ast_strlen_zero(exten)) 04589 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 04590 if (priority > -1) { 04591 chan->priority = priority; 04592 /* see flag description in channel.h for explanation */ 04593 if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP)) 04594 chan->priority--; 04595 } 04596 04597 ast_channel_unlock(chan); 04598 04599 return 0; 04600 }
int ast_extension_close | ( | const char * | pattern, | |
const char * | data, | |||
int | needmore | |||
) |
Definition at line 890 of file pbx.c.
References ast_log(), E_CANMATCH, E_MATCHMORE, extension_match_core(), and LOG_WARNING.
Referenced by realtime_switch_common().
00891 { 00892 if (needmore != E_MATCHMORE && needmore != E_CANMATCH) 00893 ast_log(LOG_WARNING, "invalid argument %d\n", needmore); 00894 return extension_match_core(pattern, data, needmore); 00895 }
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 885 of file pbx.c.
References E_MATCH, and extension_match_core().
Referenced by ast_ignore_pattern(), do_say(), find_matching_priority(), loopback_canmatch(), loopback_exec(), loopback_exists(), loopback_matchmore(), matchcid(), misdn_cfg_is_msn_valid(), realtime_switch_common(), and show_dialplan_helper().
00886 { 00887 return extension_match_core(pattern, data, E_MATCH); 00888 }
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 2020 of file pbx.c.
References ast_extension_state2(), and ast_hint_extension().
Referenced by action_extensionstate(), and handle_request_subscribe().
02021 { 02022 struct ast_exten *e; 02023 02024 e = ast_hint_extension(c, context, exten); /* Do we have a hint for this extension ? */ 02025 if (!e) 02026 return -1; /* No hint, return -1 */ 02027 02028 return ast_extension_state2(e); /* Check all devices in the hint */ 02029 }
static int ast_extension_state2 | ( | struct ast_exten * | e | ) | [static] |
ast_extensions_state2: Check state of extension by using hints
Definition at line 1923 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, inuse, ring(), and strsep().
Referenced by ast_add_hint(), ast_extension_state(), and ast_hint_state_changed().
01924 { 01925 char hint[AST_MAX_EXTENSION]; 01926 char *cur, *rest; 01927 int allunavailable = 1, allbusy = 1, allfree = 1, allonhold = 1; 01928 int busy = 0, inuse = 0, ring = 0; 01929 01930 if (!e) 01931 return -1; 01932 01933 ast_copy_string(hint, ast_get_extension_app(e), sizeof(hint)); 01934 01935 rest = hint; /* One or more devices separated with a & character */ 01936 while ( (cur = strsep(&rest, "&")) ) { 01937 int res = ast_device_state(cur); 01938 switch (res) { 01939 case AST_DEVICE_NOT_INUSE: 01940 allunavailable = 0; 01941 allbusy = 0; 01942 allonhold = 0; 01943 break; 01944 case AST_DEVICE_INUSE: 01945 inuse = 1; 01946 allunavailable = 0; 01947 allfree = 0; 01948 allonhold = 0; 01949 break; 01950 case AST_DEVICE_RINGING: 01951 ring = 1; 01952 allunavailable = 0; 01953 allfree = 0; 01954 allonhold = 0; 01955 break; 01956 case AST_DEVICE_RINGINUSE: 01957 inuse = 1; 01958 ring = 1; 01959 allunavailable = 0; 01960 allfree = 0; 01961 allonhold = 0; 01962 break; 01963 case AST_DEVICE_ONHOLD: 01964 allunavailable = 0; 01965 allfree = 0; 01966 break; 01967 case AST_DEVICE_BUSY: 01968 allunavailable = 0; 01969 allfree = 0; 01970 allonhold = 0; 01971 busy = 1; 01972 break; 01973 case AST_DEVICE_UNAVAILABLE: 01974 case AST_DEVICE_INVALID: 01975 allbusy = 0; 01976 allfree = 0; 01977 allonhold = 0; 01978 break; 01979 default: 01980 allunavailable = 0; 01981 allbusy = 0; 01982 allfree = 0; 01983 allonhold = 0; 01984 } 01985 } 01986 01987 if (!inuse && ring) 01988 return AST_EXTENSION_RINGING; 01989 if (inuse && ring) 01990 return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING); 01991 if (inuse) 01992 return AST_EXTENSION_INUSE; 01993 if (allfree) 01994 return AST_EXTENSION_NOT_INUSE; 01995 if (allonhold) 01996 return AST_EXTENSION_ONHOLD; 01997 if (allbusy) 01998 return AST_EXTENSION_BUSY; 01999 if (allunavailable) 02000 return AST_EXTENSION_UNAVAILABLE; 02001 if (busy) 02002 return AST_EXTENSION_INUSE; 02003 02004 return AST_EXTENSION_NOT_INUSE; 02005 }
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 2008 of file pbx.c.
References extension_states.
Referenced by cb_extensionstate(), handle_request_subscribe(), and handle_show_hints().
02009 { 02010 int i; 02011 02012 for (i = 0; (i < (sizeof(extension_states) / sizeof(extension_states[0]))); i++) { 02013 if (extension_states[i].extension_state == extension_state) 02014 return extension_states[i].text; 02015 } 02016 return "Unknown"; 02017 }
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 2075 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(), and init_manager().
02077 { 02078 struct ast_hint *hint; 02079 struct ast_state_cb *cblist; 02080 struct ast_exten *e; 02081 02082 /* If there's no context and extension: add callback to statecbs list */ 02083 if (!context && !exten) { 02084 AST_LIST_LOCK(&hints); 02085 02086 for (cblist = statecbs; cblist; cblist = cblist->next) { 02087 if (cblist->callback == callback) { 02088 cblist->data = data; 02089 AST_LIST_UNLOCK(&hints); 02090 return 0; 02091 } 02092 } 02093 02094 /* Now insert the callback */ 02095 if (!(cblist = ast_calloc(1, sizeof(*cblist)))) { 02096 AST_LIST_UNLOCK(&hints); 02097 return -1; 02098 } 02099 cblist->id = 0; 02100 cblist->callback = callback; 02101 cblist->data = data; 02102 02103 cblist->next = statecbs; 02104 statecbs = cblist; 02105 02106 AST_LIST_UNLOCK(&hints); 02107 return 0; 02108 } 02109 02110 if (!context || !exten) 02111 return -1; 02112 02113 /* This callback type is for only one hint, so get the hint */ 02114 e = ast_hint_extension(NULL, context, exten); 02115 if (!e) { 02116 return -1; 02117 } 02118 02119 /* Find the hint in the list of hints */ 02120 AST_LIST_LOCK(&hints); 02121 02122 AST_LIST_TRAVERSE(&hints, hint, list) { 02123 if (hint->exten == e) 02124 break; 02125 } 02126 02127 if (!hint) { 02128 /* We have no hint, sorry */ 02129 AST_LIST_UNLOCK(&hints); 02130 return -1; 02131 } 02132 02133 /* Now insert the callback in the callback list */ 02134 if (!(cblist = ast_calloc(1, sizeof(*cblist)))) { 02135 AST_LIST_UNLOCK(&hints); 02136 return -1; 02137 } 02138 cblist->id = stateid++; /* Unique ID for this callback */ 02139 cblist->callback = callback; /* Pointer to callback routine */ 02140 cblist->data = data; /* Data for the callback */ 02141 02142 cblist->next = hint->callbacks; 02143 hint->callbacks = cblist; 02144 02145 AST_LIST_UNLOCK(&hints); 02146 return cblist->id; 02147 }
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 2150 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().
02151 { 02152 struct ast_state_cb **p_cur = NULL; /* address of pointer to us */ 02153 int ret = -1; 02154 02155 if (!id && !callback) 02156 return -1; 02157 02158 AST_LIST_LOCK(&hints); 02159 02160 if (!id) { /* id == 0 is a callback without extension */ 02161 for (p_cur = &statecbs; *p_cur; p_cur = &(*p_cur)->next) { 02162 if ((*p_cur)->callback == callback) 02163 break; 02164 } 02165 } else { /* callback with extension, find the callback based on ID */ 02166 struct ast_hint *hint; 02167 AST_LIST_TRAVERSE(&hints, hint, list) { 02168 for (p_cur = &hint->callbacks; *p_cur; p_cur = &(*p_cur)->next) { 02169 if ((*p_cur)->id == id) 02170 break; 02171 } 02172 if (*p_cur) /* found in the inner loop */ 02173 break; 02174 } 02175 } 02176 if (p_cur && *p_cur) { 02177 struct ast_state_cb *cur = *p_cur; 02178 *p_cur = cur->next; 02179 free(cur); 02180 ret = 0; 02181 } 02182 AST_LIST_UNLOCK(&hints); 02183 return ret; 02184 }
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 2301 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().
02302 { 02303 return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL); 02304 }
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 2306 of file pbx.c.
References E_FINDLABEL, and pbx_extension_helper().
Referenced by pbx_load_config().
02307 { 02308 return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL); 02309 }
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 1550 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().
01551 { 01552 char *args = func_args(function); 01553 struct ast_custom_function *acfptr = ast_custom_function_find(function); 01554 01555 if (acfptr == NULL) 01556 ast_log(LOG_ERROR, "Function %s not registered\n", function); 01557 else if (!acfptr->read) 01558 ast_log(LOG_ERROR, "Function %s cannot be read\n", function); 01559 else 01560 return acfptr->read(chan, function, args, workspace, len); 01561 return -1; 01562 }
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 1564 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().
01565 { 01566 char *args = func_args(function); 01567 struct ast_custom_function *acfptr = ast_custom_function_find(function); 01568 01569 if (acfptr == NULL) 01570 ast_log(LOG_ERROR, "Function %s not registered\n", function); 01571 else if (!acfptr->write) 01572 ast_log(LOG_ERROR, "Function %s cannot be written to\n", function); 01573 else 01574 return acfptr->write(chan, function, args, value); 01575 01576 return -1; 01577 }
const char* ast_get_context_name | ( | struct ast_context * | con | ) |
Definition at line 6181 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 6219 of file pbx.c.
References ast_context::registrar.
Referenced by handle_save_dialplan(), and show_dialplan_helper().
06220 { 06221 return c ? c->registrar : NULL; 06222 }
const char* ast_get_extension_app | ( | struct ast_exten * | e | ) |
Definition at line 6249 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().
06250 { 06251 return e ? e->app : NULL; 06252 }
void* ast_get_extension_app_data | ( | struct ast_exten * | e | ) |
Definition at line 6254 of file pbx.c.
References ast_exten::data.
Referenced by _macro_exec(), ast_get_hint(), handle_save_dialplan(), and print_ext().
06255 { 06256 return e ? e->data : NULL; 06257 }
const char* ast_get_extension_cidmatch | ( | struct ast_exten * | e | ) |
Definition at line 6244 of file pbx.c.
References ast_exten::cidmatch.
Referenced by find_matching_priority(), and handle_save_dialplan().
06245 { 06246 return e ? e->cidmatch : NULL; 06247 }
struct ast_context* ast_get_extension_context | ( | struct ast_exten * | exten | ) |
const char* ast_get_extension_label | ( | struct ast_exten * | exten | ) |
Definition at line 6196 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 6239 of file pbx.c.
References ast_exten::matchcid.
Referenced by find_matching_priority(), and handle_save_dialplan().
06240 { 06241 return e ? e->matchcid : 0; 06242 }
const char* ast_get_extension_name | ( | struct ast_exten * | exten | ) |
Definition at line 6191 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 6211 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 6224 of file pbx.c.
References ast_exten::registrar.
Referenced by handle_save_dialplan(), and show_dialplan_helper().
06225 { 06226 return e ? e->registrar : NULL; 06227 }
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 hint 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 2279 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(), pbx_retrieve_variable(), and transmit_state_notify().
02280 { 02281 struct ast_exten *e = ast_hint_extension(c, context, exten); 02282 02283 if (e) { 02284 if (hint) 02285 ast_copy_string(hint, ast_get_extension_app(e), hintsize); 02286 if (name) { 02287 const char *tmp = ast_get_extension_app_data(e); 02288 if (tmp) 02289 ast_copy_string(name, tmp, namesize); 02290 } 02291 return -1; 02292 } 02293 return 0; 02294 }
const char* ast_get_ignorepat_name | ( | struct ast_ignorepat * | ip | ) |
Definition at line 6206 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().
06207 { 06208 return ip ? ip->pattern : NULL; 06209 }
const char* ast_get_ignorepat_registrar | ( | struct ast_ignorepat * | ip | ) |
Definition at line 6234 of file pbx.c.
References ast_ignorepat::registrar.
Referenced by handle_save_dialplan(), and show_dialplan_helper().
06235 { 06236 return ip ? ip->registrar : NULL; 06237 }
const char* ast_get_include_name | ( | struct ast_include * | inc | ) |
Definition at line 6201 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().
06202 { 06203 return inc ? inc->name : NULL; 06204 }
const char* ast_get_include_registrar | ( | struct ast_include * | i | ) |
Definition at line 6229 of file pbx.c.
References ast_include::registrar.
Referenced by handle_save_dialplan(), and show_dialplan_helper().
06230 { 06231 return i ? i->registrar : NULL; 06232 }
const char* ast_get_switch_data | ( | struct ast_sw * | sw | ) |
Definition at line 6264 of file pbx.c.
References ast_sw::data.
Referenced by handle_save_dialplan(), and show_dialplan_helper().
06265 { 06266 return sw ? sw->data : NULL; 06267 }
const char* ast_get_switch_name | ( | struct ast_sw * | sw | ) |
Definition at line 6259 of file pbx.c.
References ast_sw::name.
Referenced by handle_save_dialplan(), and show_dialplan_helper().
06260 { 06261 return sw ? sw->name : NULL; 06262 }
const char* ast_get_switch_registrar | ( | struct ast_sw * | sw | ) |
Definition at line 6269 of file pbx.c.
References ast_sw::registrar.
Referenced by handle_save_dialplan(), and show_dialplan_helper().
06270 { 06271 return sw ? sw->registrar : NULL; 06272 }
int ast_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 6362 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().
06363 { 06364 return __ast_goto_if_exists(chan, context, exten, priority, 0); 06365 }
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 1910 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().
01911 { 01912 struct ast_exten *e; 01913 struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */ 01914 01915 ast_rdlock_contexts(); 01916 e = pbx_find_extension(c, NULL, &q, context, exten, PRIORITY_HINT, NULL, "", E_MATCH); 01917 ast_unlock_contexts(); 01918 01919 return e; 01920 }
void ast_hint_state_changed | ( | const char * | device | ) |
Definition at line 2031 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().
02032 { 02033 struct ast_hint *hint; 02034 02035 AST_LIST_LOCK(&hints); 02036 02037 AST_LIST_TRAVERSE(&hints, hint, list) { 02038 struct ast_state_cb *cblist; 02039 char buf[AST_MAX_EXTENSION]; 02040 char *parse = buf; 02041 char *cur; 02042 int state; 02043 02044 ast_copy_string(buf, ast_get_extension_app(hint->exten), sizeof(buf)); 02045 while ( (cur = strsep(&parse, "&")) ) { 02046 if (!strcasecmp(cur, device)) 02047 break; 02048 } 02049 if (!cur) 02050 continue; 02051 02052 /* Get device state for this hint */ 02053 state = ast_extension_state2(hint->exten); 02054 02055 if ((state == -1) || (state == hint->laststate)) 02056 continue; 02057 02058 /* Device state changed since last check - notify the watchers */ 02059 02060 /* For general callbacks */ 02061 for (cblist = statecbs; cblist; cblist = cblist->next) 02062 cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data); 02063 02064 /* For extension callbacks */ 02065 for (cblist = hint->callbacks; cblist; cblist = cblist->next) 02066 cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data); 02067 02068 hint->laststate = state; /* record we saw the change */ 02069 } 02070 02071 AST_LIST_UNLOCK(&hints); 02072 }
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 4545 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().
04546 { 04547 struct ast_context *con = ast_context_find(context); 04548 if (con) { 04549 struct ast_ignorepat *pat; 04550 for (pat = con->ignorepats; pat; pat = pat->next) { 04551 if (ast_extension_match(pat->pattern, pattern)) 04552 return 1; 04553 } 04554 } 04555 04556 return 0; 04557 }
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 6168 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().
06169 { 06170 return ast_mutex_lock(&con->lock); 06171 }
int ast_lock_contexts | ( | void | ) |
Locks the context list.
0 | on success | |
-1 | on error |
Definition at line 6145 of file pbx.c.
References ast_rwlock_wrlock().
Referenced by find_matching_endwhile().
06146 { 06147 return ast_rwlock_wrlock(&conlock); 06148 }
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 2316 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().
02317 { 02318 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE); 02319 }
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 3946 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().
03947 { 03948 struct ast_context *tmp, *lasttmp = NULL; 03949 struct store_hints store = AST_LIST_HEAD_INIT_VALUE; 03950 struct store_hint *this; 03951 struct ast_hint *hint; 03952 struct ast_exten *exten; 03953 int length; 03954 struct ast_state_cb *thiscb, *prevcb; 03955 03956 /* it is very important that this function hold the hint list lock _and_ the conlock 03957 during its operation; not only do we need to ensure that the list of contexts 03958 and extensions does not change, but also that no hint callbacks (watchers) are 03959 added or removed during the merge/delete process 03960 03961 in addition, the locks _must_ be taken in this order, because there are already 03962 other code paths that use this order 03963 */ 03964 ast_wrlock_contexts(); 03965 AST_LIST_LOCK(&hints); 03966 03967 /* preserve all watchers for hints associated with this registrar */ 03968 AST_LIST_TRAVERSE(&hints, hint, list) { 03969 if (hint->callbacks && !strcmp(registrar, hint->exten->parent->registrar)) { 03970 length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2 + sizeof(*this); 03971 if (!(this = ast_calloc(1, length))) 03972 continue; 03973 this->callbacks = hint->callbacks; 03974 hint->callbacks = NULL; 03975 this->laststate = hint->laststate; 03976 this->context = this->data; 03977 strcpy(this->data, hint->exten->parent->name); 03978 this->exten = this->data + strlen(this->context) + 1; 03979 strcpy(this->exten, hint->exten->exten); 03980 AST_LIST_INSERT_HEAD(&store, this, list); 03981 } 03982 } 03983 03984 tmp = *extcontexts; 03985 if (registrar) { 03986 /* XXX remove previous contexts from same registrar */ 03987 if (option_debug) 03988 ast_log(LOG_DEBUG, "must remove any reg %s\n", registrar); 03989 __ast_context_destroy(NULL,registrar); 03990 while (tmp) { 03991 lasttmp = tmp; 03992 tmp = tmp->next; 03993 } 03994 } else { 03995 /* XXX remove contexts with the same name */ 03996 while (tmp) { 03997 ast_log(LOG_WARNING, "must remove %s reg %s\n", tmp->name, tmp->registrar); 03998 __ast_context_destroy(tmp,tmp->registrar); 03999 lasttmp = tmp; 04000 tmp = tmp->next; 04001 } 04002 } 04003 if (lasttmp) { 04004 lasttmp->next = contexts; 04005 contexts = *extcontexts; 04006 *extcontexts = NULL; 04007 } else 04008 ast_log(LOG_WARNING, "Requested contexts didn't get merged\n"); 04009 04010 /* restore the watchers for hints that can be found; notify those that 04011 cannot be restored 04012 */ 04013 while ((this = AST_LIST_REMOVE_HEAD(&store, list))) { 04014 struct pbx_find_info q = { .stacklen = 0 }; 04015 exten = pbx_find_extension(NULL, NULL, &q, this->context, this->exten, PRIORITY_HINT, NULL, "", E_MATCH); 04016 /* Find the hint in the list of hints */ 04017 AST_LIST_TRAVERSE(&hints, hint, list) { 04018 if (hint->exten == exten) 04019 break; 04020 } 04021 if (!exten || !hint) { 04022 /* this hint has been removed, notify the watchers */ 04023 prevcb = NULL; 04024 thiscb = this->callbacks; 04025 while (thiscb) { 04026 prevcb = thiscb; 04027 thiscb = thiscb->next; 04028 prevcb->callback(this->context, this->exten, AST_EXTENSION_REMOVED, prevcb->data); 04029 free(prevcb); 04030 } 04031 } else { 04032 thiscb = this->callbacks; 04033 while (thiscb->next) 04034 thiscb = thiscb->next; 04035 thiscb->next = hint->callbacks; 04036 hint->callbacks = this->callbacks; 04037 hint->laststate = this->laststate; 04038 } 04039 free(this); 04040 } 04041 04042 AST_LIST_UNLOCK(&hints); 04043 ast_unlock_contexts(); 04044 04045 return; 04046 }
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 6372 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().
06373 { 06374 char *exten, *pri, *context; 06375 char *stringp; 06376 int ipri; 06377 int mode = 0; 06378 06379 if (ast_strlen_zero(goto_string)) { 06380 ast_log(LOG_WARNING, "Goto requires an argument (optional context|optional extension|priority)\n"); 06381 return -1; 06382 } 06383 stringp = ast_strdupa(goto_string); 06384 context = strsep(&stringp, "|"); /* guaranteed non-null */ 06385 exten = strsep(&stringp, "|"); 06386 pri = strsep(&stringp, "|"); 06387 if (!exten) { /* Only a priority in this one */ 06388 pri = context; 06389 exten = NULL; 06390 context = NULL; 06391 } else if (!pri) { /* Only an extension and priority in this one */ 06392 pri = exten; 06393 exten = context; 06394 context = NULL; 06395 } 06396 if (*pri == '+') { 06397 mode = 1; 06398 pri++; 06399 } else if (*pri == '-') { 06400 mode = -1; 06401 pri++; 06402 } 06403 if (sscanf(pri, "%d", &ipri) != 1) { 06404 if ((ipri = ast_findlabel_extension(chan, context ? context : chan->context, exten ? exten : chan->exten, 06405 pri, chan->cid.cid_num)) < 1) { 06406 ast_log(LOG_WARNING, "Priority '%s' must be a number > 0, or valid label\n", pri); 06407 return -1; 06408 } else 06409 mode = 0; 06410 } 06411 /* At this point we have a priority and maybe an extension and a context */ 06412 06413 if (mode) 06414 ipri = chan->priority + (ipri * mode); 06415 06416 ast_explicit_goto(chan, context, exten, ipri); 06417 ast_cdr_update(chan); 06418 return 0; 06419 06420 }
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 5165 of file pbx.c.
References __ast_request_and_dial(), 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(), attempt_thread(), fast_originate(), and orig_app().
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(type, format, data, timeout, reason, cid_num, cid_name, &oh); 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); /* initialize 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(type, format, data, timeout, reason, cid_num, cid_name, &oh); 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 4974 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(), and ast_pbx_outgoing_exten().
04975 { 04976 /* allocate a channel */ 04977 struct ast_channel *chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, 0); 04978 04979 if (!chan) 04980 return -1; /* failure */ 04981 04982 if (!chan->cdr) { 04983 /* allocation of the cdr failed */ 04984 ast_channel_free(chan); /* free the channel */ 04985 return -1; /* return failure */ 04986 } 04987 04988 /* allocation of the cdr was successful */ 04989 ast_cdr_init(chan->cdr, chan); /* initialize our channel's cdr */ 04990 ast_cdr_start(chan->cdr); /* record the start and stop time */ 04991 ast_cdr_end(chan->cdr); 04992 ast_cdr_failed(chan->cdr); /* set the status to failed */ 04993 ast_cdr_detach(chan->cdr); /* post and free the record */ 04994 ast_channel_free(chan); /* free the channel */ 04995 04996 return 0; /* success */ 04997 }
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 4999 of file pbx.c.
References __ast_request_and_dial(), 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(), 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(), attempt_thread(), fast_originate(), and orig_exten().
05000 { 05001 struct ast_channel *chan; 05002 struct async_stat *as; 05003 int res = -1, cdr_res = -1; 05004 struct outgoing_helper oh; 05005 pthread_attr_t attr; 05006 05007 if (sync) { 05008 LOAD_OH(oh); 05009 chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh); 05010 if (channel) { 05011 *channel = chan; 05012 if (chan) 05013 ast_channel_lock(chan); 05014 } 05015 if (chan) { 05016 if (chan->_state == AST_STATE_UP) { 05017 res = 0; 05018 if (option_verbose > 3) 05019 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", chan->name); 05020 05021 if (sync > 1) { 05022 if (channel) 05023 ast_channel_unlock(chan); 05024 if (ast_pbx_run(chan)) { 05025 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 05026 if (channel) 05027 *channel = NULL; 05028 ast_hangup(chan); 05029 chan = NULL; 05030 res = -1; 05031 } 05032 } else { 05033 if (ast_pbx_start(chan)) { 05034 ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name); 05035 if (channel) { 05036 *channel = NULL; 05037 ast_channel_unlock(chan); 05038 } 05039 ast_hangup(chan); 05040 res = -1; 05041 } 05042 chan = NULL; 05043 } 05044 } else { 05045 if (option_verbose > 3) 05046 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", chan->name); 05047 05048 if (chan->cdr) { /* update the cdr */ 05049 /* here we update the status of the call, which sould be busy. 05050 * if that fails then we set the status to failed */ 05051 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 05052 ast_cdr_failed(chan->cdr); 05053 } 05054 05055 if (channel) { 05056 *channel = NULL; 05057 ast_channel_unlock(chan); 05058 } 05059 ast_hangup(chan); 05060 chan = NULL; 05061 } 05062 } 05063 05064 if (res < 0) { /* the call failed for some reason */ 05065 if (*reason == 0) { /* if the call failed (not busy or no answer) 05066 * update the cdr with the failed message */ 05067 cdr_res = ast_pbx_outgoing_cdr_failed(); 05068 if (cdr_res != 0) { 05069 res = cdr_res; 05070 goto outgoing_exten_cleanup; 05071 } 05072 } 05073 05074 /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */ 05075 /* check if "failed" exists */ 05076 if (ast_exists_extension(chan, context, "failed", 1, NULL)) { 05077 chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "OutgoingSpoolFailed"); 05078 if (chan) { 05079 char failed_reason[4] = ""; 05080 if (!ast_strlen_zero(context)) 05081 ast_copy_string(chan->context, context, sizeof(chan->context)); 05082 set_ext_pri(chan, "failed", 1); 05083 ast_set_variables(chan, vars); 05084 snprintf(failed_reason, sizeof(failed_reason), "%d", *reason); 05085 pbx_builtin_setvar_helper(chan, "REASON", failed_reason); 05086 if (account) 05087 ast_cdr_setaccount(chan, account); 05088 if (ast_pbx_run(chan)) { 05089 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 05090 ast_hangup(chan); 05091 } 05092 chan = NULL; 05093 } 05094 } 05095 } 05096 } else { 05097 if (!(as = ast_calloc(1, sizeof(*as)))) { 05098 res = -1; 05099 goto outgoing_exten_cleanup; 05100 } 05101 chan = ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name); 05102 if (channel) { 05103 *channel = chan; 05104 if (chan) 05105 ast_channel_lock(chan); 05106 } 05107 if (!chan) { 05108 free(as); 05109 res = -1; 05110 goto outgoing_exten_cleanup; 05111 } 05112 as->chan = chan; 05113 ast_copy_string(as->context, context, sizeof(as->context)); 05114 set_ext_pri(as->chan, exten, priority); 05115 as->timeout = timeout; 05116 ast_set_variables(chan, vars); 05117 if (account) 05118 ast_cdr_setaccount(chan, account); 05119 pthread_attr_init(&attr); 05120 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 05121 if (ast_pthread_create(&as->p, &attr, async_wait, as)) { 05122 ast_log(LOG_WARNING, "Failed to start async wait\n"); 05123 free(as); 05124 if (channel) { 05125 *channel = NULL; 05126 ast_channel_unlock(chan); 05127 } 05128 ast_hangup(chan); 05129 res = -1; 05130 pthread_attr_destroy(&attr); 05131 goto outgoing_exten_cleanup; 05132 } 05133 pthread_attr_destroy(&attr); 05134 res = 0; 05135 } 05136 outgoing_exten_cleanup: 05137 ast_variables_destroy(vars); 05138 return res; 05139 }
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 2674 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(), async_wait(), mgcp_ss(), skinny_newcall(), and ss_thread().
02675 { 02676 enum ast_pbx_result res = AST_PBX_SUCCESS; 02677 02678 if (increase_call_count(c)) 02679 return AST_PBX_CALL_LIMIT; 02680 02681 res = __ast_pbx_run(c); 02682 decrease_call_count(); 02683 02684 return res; 02685 }
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().
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 2648 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(), 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().
02649 { 02650 pthread_t t; 02651 pthread_attr_t attr; 02652 02653 if (!c) { 02654 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n"); 02655 return AST_PBX_FAILED; 02656 } 02657 02658 if (increase_call_count(c)) 02659 return AST_PBX_CALL_LIMIT; 02660 02661 /* Start a new thread, and get something handling this channel. */ 02662 pthread_attr_init(&attr); 02663 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 02664 if (ast_pthread_create(&t, &attr, pbx_thread, c)) { 02665 ast_log(LOG_WARNING, "Failed to create new channel thread\n"); 02666 pthread_attr_destroy(&attr); 02667 return AST_PBX_FAILED; 02668 } 02669 pthread_attr_destroy(&attr); 02670 02671 return AST_PBX_SUCCESS; 02672 }
int ast_rdlock_contexts | ( | void | ) |
Definition at line 6150 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().
06151 { 06152 return ast_rwlock_rdlock(&conlock); 06153 }
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 2976 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().
02977 { 02978 struct ast_app *tmp, *cur = NULL; 02979 char tmps[80]; 02980 int length; 02981 02982 AST_LIST_LOCK(&apps); 02983 AST_LIST_TRAVERSE(&apps, tmp, list) { 02984 if (!strcasecmp(app, tmp->name)) { 02985 ast_log(LOG_WARNING, "Already have an application '%s'\n", app); 02986 AST_LIST_UNLOCK(&apps); 02987 return -1; 02988 } 02989 } 02990 02991 length = sizeof(*tmp) + strlen(app) + 1; 02992 02993 if (!(tmp = ast_calloc(1, length))) { 02994 AST_LIST_UNLOCK(&apps); 02995 return -1; 02996 } 02997 02998 strcpy(tmp->name, app); 02999 tmp->execute = execute; 03000 tmp->synopsis = synopsis; 03001 tmp->description = description; 03002 03003 /* Store in alphabetical order */ 03004 AST_LIST_TRAVERSE_SAFE_BEGIN(&apps, cur, list) { 03005 if (strcasecmp(tmp->name, cur->name) < 0) { 03006 AST_LIST_INSERT_BEFORE_CURRENT(&apps, tmp, list); 03007 break; 03008 } 03009 } 03010 AST_LIST_TRAVERSE_SAFE_END 03011 if (!cur) 03012 AST_LIST_INSERT_TAIL(&apps, tmp, list); 03013 03014 if (option_verbose > 1) 03015 ast_verbose( VERBOSE_PREFIX_2 "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps))); 03016 03017 AST_LIST_UNLOCK(&apps); 03018 03019 return 0; 03020 }
int ast_register_switch | ( | struct ast_switch * | sw | ) |
Register an alternative dialplan switch.
sw | switch to register |
Definition at line 3026 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().
03027 { 03028 struct ast_switch *tmp; 03029 03030 AST_LIST_LOCK(&switches); 03031 AST_LIST_TRAVERSE(&switches, tmp, list) { 03032 if (!strcasecmp(tmp->name, sw->name)) { 03033 AST_LIST_UNLOCK(&switches); 03034 ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name); 03035 return -1; 03036 } 03037 } 03038 AST_LIST_INSERT_TAIL(&switches, sw, list); 03039 AST_LIST_UNLOCK(&switches); 03040 03041 return 0; 03042 }
static int ast_remove_hint | ( | struct ast_exten * | e | ) | [static] |
ast_remove_hint: Remove hint from extension
Definition at line 2242 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().
02243 { 02244 /* Cleanup the Notifys if hint is removed */ 02245 struct ast_hint *hint; 02246 struct ast_state_cb *cblist, *cbprev; 02247 int res = -1; 02248 02249 if (!e) 02250 return -1; 02251 02252 AST_LIST_LOCK(&hints); 02253 AST_LIST_TRAVERSE_SAFE_BEGIN(&hints, hint, list) { 02254 if (hint->exten == e) { 02255 cbprev = NULL; 02256 cblist = hint->callbacks; 02257 while (cblist) { 02258 /* Notify with -1 and remove all callbacks */ 02259 cbprev = cblist; 02260 cblist = cblist->next; 02261 cbprev->callback(hint->exten->parent->name, hint->exten->exten, AST_EXTENSION_DEACTIVATED, cbprev->data); 02262 free(cbprev); 02263 } 02264 hint->callbacks = NULL; 02265 AST_LIST_REMOVE_CURRENT(&hints, list); 02266 free(hint); 02267 res = 0; 02268 break; 02269 } 02270 } 02271 AST_LIST_TRAVERSE_SAFE_END 02272 AST_LIST_UNLOCK(&hints); 02273 02274 return res; 02275 }
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 2321 of file pbx.c.
References E_SPAWN, and pbx_extension_helper().
Referenced by __ast_pbx_run(), _macro_exec(), and loopback_exec().
02322 { 02323 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN); 02324 }
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 6173 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().
06174 { 06175 return ast_mutex_unlock(&con->lock); 06176 }
int ast_unlock_contexts | ( | void | ) |
Unlocks contexts.
0 | on success | |
-1 | on failure |
Definition at line 6160 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().
06161 { 06162 return ast_rwlock_unlock(&conlock); 06163 }
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 3857 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().
03858 { 03859 struct ast_app *tmp; 03860 03861 AST_LIST_LOCK(&apps); 03862 AST_LIST_TRAVERSE_SAFE_BEGIN(&apps, tmp, list) { 03863 if (!strcasecmp(app, tmp->name)) { 03864 AST_LIST_REMOVE_CURRENT(&apps, list); 03865 if (option_verbose > 1) 03866 ast_verbose( VERBOSE_PREFIX_2 "Unregistered application '%s'\n", tmp->name); 03867 free(tmp); 03868 break; 03869 } 03870 } 03871 AST_LIST_TRAVERSE_SAFE_END 03872 AST_LIST_UNLOCK(&apps); 03873 03874 return tmp ? 0 : -1; 03875 }
void ast_unregister_switch | ( | struct ast_switch * | sw | ) |
Unregister an alternative switch.
sw | switch to unregister |
Definition at line 3044 of file pbx.c.
References AST_LIST_LOCK, AST_LIST_REMOVE, and AST_LIST_UNLOCK.
Referenced by __unload_module(), and unload_module().
03045 { 03046 AST_LIST_LOCK(&switches); 03047 AST_LIST_REMOVE(&switches, sw, list); 03048 AST_LIST_UNLOCK(&switches); 03049 }
struct ast_exten* ast_walk_context_extensions | ( | struct ast_context * | con, | |
struct ast_exten * | exten | |||
) |
Definition at line 6282 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().
06284 { 06285 if (!exten) 06286 return con ? con->root : NULL; 06287 else 06288 return exten->next; 06289 }
struct ast_ignorepat* ast_walk_context_ignorepats | ( | struct ast_context * | con, | |
struct ast_ignorepat * | ip | |||
) |
Definition at line 6315 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().
06317 { 06318 if (!ip) 06319 return con ? con->ignorepats : NULL; 06320 else 06321 return ip->next; 06322 }
struct ast_include* ast_walk_context_includes | ( | struct ast_context * | con, | |
struct ast_include * | inc | |||
) |
Definition at line 6306 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().
06308 { 06309 if (!inc) 06310 return con ? con->includes : NULL; 06311 else 06312 return inc->next; 06313 }
struct ast_sw* ast_walk_context_switches | ( | struct ast_context * | con, | |
struct ast_sw * | sw | |||
) |
Definition at line 6291 of file pbx.c.
References AST_LIST_FIRST, and AST_LIST_NEXT.
Referenced by handle_save_dialplan(), and show_dialplan_helper().
06293 { 06294 if (!sw) 06295 return con ? AST_LIST_FIRST(&con->alts) : NULL; 06296 else 06297 return AST_LIST_NEXT(sw, list); 06298 }
struct ast_context* ast_walk_contexts | ( | struct ast_context * | con | ) |
Definition at line 6277 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 6300 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 6155 of file pbx.c.
References ast_rwlock_wrlock().
Referenced by ast_context_destroy(), ast_merge_contexts_and_delete(), and complete_context_dont_include_deprecated().
06156 { 06157 return ast_rwlock_wrlock(&conlock); 06158 }
static void* async_wait | ( | void * | data | ) | [static] |
Definition at line 4911 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, timeout, and VERBOSE_PREFIX_3.
Referenced by ast_pbx_outgoing_app(), and ast_pbx_outgoing_exten().
04912 { 04913 struct async_stat *as = data; 04914 struct ast_channel *chan = as->chan; 04915 int timeout = as->timeout; 04916 int res; 04917 struct ast_frame *f; 04918 struct ast_app *app; 04919 04920 while (timeout && (chan->_state != AST_STATE_UP)) { 04921 res = ast_waitfor(chan, timeout); 04922 if (res < 1) 04923 break; 04924 if (timeout > -1) 04925 timeout = res; 04926 f = ast_read(chan); 04927 if (!f) 04928 break; 04929 if (f->frametype == AST_FRAME_CONTROL) { 04930 if ((f->subclass == AST_CONTROL_BUSY) || 04931 (f->subclass == AST_CONTROL_CONGESTION) ) { 04932 ast_frfree(f); 04933 break; 04934 } 04935 } 04936 ast_frfree(f); 04937 } 04938 if (chan->_state == AST_STATE_UP) { 04939 if (!ast_strlen_zero(as->app)) { 04940 app = pbx_findapp(as->app); 04941 if (app) { 04942 if (option_verbose > 2) 04943 ast_verbose(VERBOSE_PREFIX_3 "Launching %s(%s) on %s\n", as->app, as->appdata, chan->name); 04944 pbx_exec(chan, app, as->appdata); 04945 } else 04946 ast_log(LOG_WARNING, "No such application '%s'\n", as->app); 04947 } else { 04948 if (!ast_strlen_zero(as->context)) 04949 ast_copy_string(chan->context, as->context, sizeof(chan->context)); 04950 if (!ast_strlen_zero(as->exten)) 04951 ast_copy_string(chan->exten, as->exten, sizeof(chan->exten)); 04952 if (as->priority > 0) 04953 chan->priority = as->priority; 04954 /* Run the PBX */ 04955 if (ast_pbx_run(chan)) { 04956 ast_log(LOG_ERROR, "Failed to start PBX on %s\n", chan->name); 04957 } else { 04958 /* PBX will have taken care of this */ 04959 chan = NULL; 04960 } 04961 } 04962 } 04963 free(as); 04964 if (chan) 04965 ast_hangup(chan); 04966 return NULL; 04967 }
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 2339 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.
02340 { 02341 int digit; 02342 02343 buf[pos] = '\0'; /* make sure it is properly terminated */ 02344 while (ast_matchmore_extension(c, c->context, buf, 1, c->cid.cid_num)) { 02345 /* As long as we're willing to wait, and as long as it's not defined, 02346 keep reading digits until we can't possibly get a right answer anymore. */ 02347 digit = ast_waitfordigit(c, waittime * 1000); 02348 if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) { 02349 c->_softhangup = 0; 02350 } else { 02351 if (!digit) /* No entry */ 02352 break; 02353 if (digit < 0) /* Error, maybe a hangup */ 02354 return -1; 02355 if (pos < buflen - 1) { /* XXX maybe error otherwise ? */ 02356 buf[pos++] = digit; 02357 buf[pos] = '\0'; 02358 } 02359 waittime = c->pbx->dtimeout; 02360 } 02361 } 02362 return 0; 02363 }
static char* complete_show_application | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 3102 of file pbx.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, and strdup.
03103 { 03104 struct ast_app *a; 03105 char *ret = NULL; 03106 int which = 0; 03107 int wordlen = strlen(word); 03108 03109 /* return the n-th [partial] matching entry */ 03110 AST_LIST_LOCK(&apps); 03111 AST_LIST_TRAVERSE(&apps, a, list) { 03112 if (!strncasecmp(word, a->name, wordlen) && ++which > state) { 03113 ret = strdup(a->name); 03114 break; 03115 } 03116 } 03117 AST_LIST_UNLOCK(&apps); 03118 03119 return ret; 03120 }
static char* complete_show_applications | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 3463 of file pbx.c.
References ast_cli_complete().
03464 { 03465 static char* choices[] = { "like", "describing", NULL }; 03466 03467 return (pos != 3) ? NULL : ast_cli_complete(word, choices, state); 03468 }
static char* complete_show_applications_deprecated | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 3456 of file pbx.c.
References ast_cli_complete().
03457 { 03458 static char* choices[] = { "like", "describing", NULL }; 03459 03460 return (pos != 2) ? NULL : ast_cli_complete(word, choices, state); 03461 }
static char* complete_show_dialplan_context | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 3473 of file pbx.c.
References ast_get_context_name(), ast_rdlock_contexts(), ast_strdup, ast_unlock_contexts(), and ast_walk_contexts().
03475 { 03476 struct ast_context *c = NULL; 03477 char *ret = NULL; 03478 int which = 0; 03479 int wordlen; 03480 03481 /* we are do completion of [exten@]context on second position only */ 03482 if (pos != 2) 03483 return NULL; 03484 03485 ast_rdlock_contexts(); 03486 03487 wordlen = strlen(word); 03488 03489 /* walk through all contexts and return the n-th match */ 03490 while ( (c = ast_walk_contexts(c)) ) { 03491 if (!strncasecmp(word, ast_get_context_name(c), wordlen) && ++which > state) { 03492 ret = ast_strdup(ast_get_context_name(c)); 03493 break; 03494 } 03495 } 03496 03497 ast_unlock_contexts(); 03498 03499 return ret; 03500 }
static char* complete_show_function | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 1440 of file pbx.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_custom_function::name, and strdup.
01441 { 01442 struct ast_custom_function *acf; 01443 char *ret = NULL; 01444 int which = 0; 01445 int wordlen = strlen(word); 01446 01447 /* case-insensitive for convenience in this 'complete' function */ 01448 AST_LIST_LOCK(&acf_root); 01449 AST_LIST_TRAVERSE(&acf_root, acf, acflist) { 01450 if (!strncasecmp(word, acf->name, wordlen) && ++which > state) { 01451 ret = strdup(acf->name); 01452 break; 01453 } 01454 } 01455 AST_LIST_UNLOCK(&acf_root); 01456 01457 return ret; 01458 }
static void decrease_call_count | ( | void | ) | [static] |
Definition at line 2610 of file pbx.c.
References ast_mutex_lock(), ast_mutex_unlock(), and countcalls.
Referenced by ast_pbx_run(), and pbx_thread().
02611 { 02612 ast_mutex_lock(&maxcalllock); 02613 if (countcalls > 0) 02614 countcalls--; 02615 ast_mutex_unlock(&maxcalllock); 02616 }
static void destroy_exten | ( | struct ast_exten * | e | ) | [static] |
Definition at line 2618 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().
02619 { 02620 if (e->priority == PRIORITY_HINT) 02621 ast_remove_hint(e); 02622 02623 if (e->datad) 02624 e->datad(e->data); 02625 free(e); 02626 }
static int ext_cmp | ( | const char * | a, | |
const char * | b | |||
) | [static] |
the full routine to compare extensions in rules.
Definition at line 724 of file pbx.c.
References ext_cmp1().
Referenced by ast_add_extension2().
00725 { 00726 /* make sure non-patterns come first. 00727 * If a is not a pattern, it either comes first or 00728 * we use strcmp to compare the strings. 00729 */ 00730 int ret = 0; 00731 00732 if (a[0] != '_') 00733 return (b[0] == '_') ? -1 : strcmp(a, b); 00734 00735 /* Now we know a is a pattern; if b is not, a comes first */ 00736 if (b[0] != '_') 00737 return 1; 00738 #if 0 /* old mode for ext matching */ 00739 return strcmp(a, b); 00740 #endif 00741 /* ok we need full pattern sorting routine */ 00742 while (!ret && a && b) 00743 ret = ext_cmp1(&a) - ext_cmp1(&b); 00744 if (ret == 0) 00745 return 0; 00746 else 00747 return (ret > 0) ? 1 : -1; 00748 }
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 652 of file pbx.c.
References ast_log(), and LOG_WARNING.
Referenced by ext_cmp().
00653 { 00654 uint32_t chars[8]; 00655 int c, cmin = 0xff, count = 0; 00656 const char *end; 00657 00658 /* load, sign extend and advance pointer until we find 00659 * a valid character. 00660 */ 00661 while ( (c = *(*p)++) && (c == ' ' || c == '-') ) 00662 ; /* ignore some characters */ 00663 00664 /* always return unless we have a set of chars */ 00665 switch (c) { 00666 default: /* ordinary character */ 00667 return 0x0000 | (c & 0xff); 00668 00669 case 'N': /* 2..9 */ 00670 return 0x0700 | '2' ; 00671 00672 case 'X': /* 0..9 */ 00673 return 0x0900 | '0'; 00674 00675 case 'Z': /* 1..9 */ 00676 return 0x0800 | '1'; 00677 00678 case '.': /* wildcard */ 00679 return 0x10000; 00680 00681 case '!': /* earlymatch */ 00682 return 0x20000; /* less specific than NULL */ 00683 00684 case '\0': /* empty string */ 00685 *p = NULL; 00686 return 0x30000; 00687 00688 case '[': /* pattern */ 00689 break; 00690 } 00691 /* locate end of set */ 00692 end = strchr(*p, ']'); 00693 00694 if (end == NULL) { 00695 ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n"); 00696 return 0x40000; /* XXX make this entry go last... */ 00697 } 00698 00699 bzero(chars, sizeof(chars)); /* clear all chars in the set */ 00700 for (; *p < end ; (*p)++) { 00701 unsigned char c1, c2; /* first-last char in range */ 00702 c1 = (unsigned char)((*p)[0]); 00703 if (*p + 2 < end && (*p)[1] == '-') { /* this is a range */ 00704 c2 = (unsigned char)((*p)[2]); 00705 *p += 2; /* skip a total of 3 chars */ 00706 } else /* individual character */ 00707 c2 = c1; 00708 if (c1 < cmin) 00709 cmin = c1; 00710 for (; c1 <= c2; c1++) { 00711 uint32_t mask = 1 << (c1 % 32); 00712 if ( (chars[ c1 / 32 ] & mask) == 0) 00713 count += 0x100; 00714 chars[ c1 / 32 ] |= mask; 00715 } 00716 } 00717 (*p)++; 00718 return count == 0 ? 0x30000 : (count | cmin); 00719 }
static int ext_strncpy | ( | char * | dst, | |
const char * | src, | |||
int | len | |||
) | [static] |
copy a string skipping whitespace
Definition at line 4663 of file pbx.c.
Referenced by ast_add_extension2().
04664 { 04665 int count=0; 04666 04667 while (*src && (count < len - 1)) { 04668 switch(*src) { 04669 case ' ': 04670 /* otherwise exten => [a-b],1,... doesn't work */ 04671 /* case '-': */ 04672 /* Ignore */ 04673 break; 04674 default: 04675 *dst = *src; 04676 dst++; 04677 } 04678 src++; 04679 count++; 04680 } 04681 *dst = '\0'; 04682 04683 return count; 04684 }
static int extension_match_core | ( | const char * | pattern, | |
const char * | data, | |||
enum ext_match_t | mode | |||
) | [static] |
Definition at line 873 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().
00874 { 00875 int i; 00876 static int prof_id = -2; /* marker for 'unallocated' id */ 00877 if (prof_id == -2) 00878 prof_id = ast_add_profile("ext_match", 0); 00879 ast_mark(prof_id, 1); 00880 i = _extension_match_core(pattern, data, mode); 00881 ast_mark(prof_id, 0); 00882 return i; 00883 }
static struct ast_context* find_context_locked | ( | const char * | context | ) | [static] |
Definition at line 2702 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().
02703 { 02704 struct ast_context *c = NULL; 02705 02706 ast_rdlock_contexts(); 02707 while ( (c = ast_walk_contexts(c)) ) { 02708 if (!strcmp(ast_get_context_name(c), context)) 02709 return c; 02710 } 02711 ast_unlock_contexts(); 02712 02713 return NULL; 02714 }
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 1533 of file pbx.c.
References ast_log(), and LOG_WARNING.
Referenced by ast_func_read(), and ast_func_write().
01534 { 01535 char *args = strchr(function, '('); 01536 01537 if (!args) 01538 ast_log(LOG_WARNING, "Function doesn't contain parentheses. Assuming null argument.\n"); 01539 else { 01540 char *p; 01541 *args++ = '\0'; 01542 if ((p = strrchr(args, ')')) ) 01543 *p = '\0'; 01544 else 01545 ast_log(LOG_WARNING, "Can't find trailing parenthesis?\n"); 01546 } 01547 return args; 01548 }
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 4087 of file pbx.c.
References ast_log(), ast_strlen_zero(), LOG_WARNING, lookup_name(), and s.
Referenced by ast_build_timing().
04088 { 04089 int s, e; /* start and ending position */ 04090 unsigned int mask = 0; 04091 04092 /* Check for whole range */ 04093 if (ast_strlen_zero(src) || !strcmp(src, "*")) { 04094 s = 0; 04095 e = max - 1; 04096 } else { 04097 /* Get start and ending position */ 04098 char *c = strchr(src, '-'); 04099 if (c) 04100 *c++ = '\0'; 04101 /* Find the start */ 04102 s = lookup_name(src, names, max); 04103 if (!s) { 04104 ast_log(LOG_WARNING, "Invalid %s '%s', assuming none\n", msg, src); 04105 return 0; 04106 } 04107 s--; 04108 if (c) { /* find end of range */ 04109 e = lookup_name(c, names, max); 04110 if (!e) { 04111 ast_log(LOG_WARNING, "Invalid end %s '%s', assuming none\n", msg, c); 04112 return 0; 04113 } 04114 e--; 04115 } else 04116 e = s; 04117 } 04118 /* Fill the mask. Remember that ranges are cyclic */ 04119 mask = 1 << e; /* initialize with last element */ 04120 while (s != e) { 04121 if (s >= max) { 04122 s = 0; 04123 mask |= (1 << s); 04124 } else { 04125 mask |= (1 << s); 04126 s++; 04127 } 04128 } 04129 return mask; 04130 }
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 4133 of file pbx.c.
References ast_log(), ast_strlen_zero(), LOG_WARNING, and ast_timing::minmask.
Referenced by ast_build_timing().
04134 { 04135 char *e; 04136 int x; 04137 int s1, s2; 04138 int e1, e2; 04139 /* int cth, ctm; */ 04140 04141 /* start disabling all times, fill the fields with 0's, as they may contain garbage */ 04142 memset(i->minmask, 0, sizeof(i->minmask)); 04143 04144 /* 2-minutes per bit, since the mask has only 32 bits :( */ 04145 /* Star is all times */ 04146 if (ast_strlen_zero(times) || !strcmp(times, "*")) { 04147 for (x=0; x<24; x++) 04148 i->minmask[x] = 0x3fffffff; /* 30 bits */ 04149 return; 04150 } 04151 /* Otherwise expect a range */ 04152 e = strchr(times, '-'); 04153 if (!e) { 04154 ast_log(LOG_WARNING, "Time range is not valid. Assuming no restrictions based on time.\n"); 04155 return; 04156 } 04157 *e++ = '\0'; 04158 /* XXX why skip non digits ? */ 04159 while (*e && !isdigit(*e)) 04160 e++; 04161 if (!*e) { 04162 ast_log(LOG_WARNING, "Invalid time range. Assuming no restrictions based on time.\n"); 04163 return; 04164 } 04165 if (sscanf(times, "%d:%d", &s1, &s2) != 2) { 04166 ast_log(LOG_WARNING, "%s isn't a time. Assuming no restrictions based on time.\n", times); 04167 return; 04168 } 04169 if (sscanf(e, "%d:%d", &e1, &e2) != 2) { 04170 ast_log(LOG_WARNING, "%s isn't a time. Assuming no restrictions based on time.\n", e); 04171 return; 04172 } 04173 /* XXX this needs to be optimized */ 04174 #if 1 04175 s1 = s1 * 30 + s2/2; 04176 if ((s1 < 0) || (s1 >= 24*30)) { 04177 ast_log(LOG_WARNING, "%s isn't a valid start time. Assuming no time.\n", times); 04178 return; 04179 } 04180 e1 = e1 * 30 + e2/2; 04181 if ((e1 < 0) || (e1 >= 24*30)) { 04182 ast_log(LOG_WARNING, "%s isn't a valid end time. Assuming no time.\n", e); 04183 return; 04184 } 04185 /* Go through the time and enable each appropriate bit */ 04186 for (x=s1;x != e1;x = (x + 1) % (24 * 30)) { 04187 i->minmask[x/30] |= (1 << (x % 30)); 04188 } 04189 /* Do the last one */ 04190 i->minmask[x/30] |= (1 << (x % 30)); 04191 #else 04192 for (cth=0; cth<24; cth++) { 04193 /* Initialize masks to blank */ 04194 i->minmask[cth] = 0; 04195 for (ctm=0; ctm<30; ctm++) { 04196 if ( 04197 /* First hour with more than one hour */ 04198 (((cth == s1) && (ctm >= s2)) && 04199 ((cth < e1))) 04200 /* Only one hour */ 04201 || (((cth == s1) && (ctm >= s2)) && 04202 ((cth == e1) && (ctm <= e2))) 04203 /* In between first and last hours (more than 2 hours) */ 04204 || ((cth > s1) && 04205 (cth < e1)) 04206 /* Last hour with more than one hour */ 04207 || ((cth > s1) && 04208 ((cth == e1) && (ctm <= e2))) 04209 ) 04210 i->minmask[cth] |= (1 << (ctm / 2)); 04211 } 04212 } 04213 #endif 04214 /* All done */ 04215 return; 04216 }
static int handle_set_global | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3758 of file pbx.c.
References ast_cli(), pbx_builtin_setvar_helper(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03759 { 03760 if (argc != 5) 03761 return RESULT_SHOWUSAGE; 03762 03763 pbx_builtin_setvar_helper(NULL, argv[3], argv[4]); 03764 ast_cli(fd, "\n -- Global variable %s set to %s\n", argv[3], argv[4]); 03765 03766 return RESULT_SUCCESS; 03767 }
static int handle_set_global_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
CLI support for setting global variables.
Definition at line 3746 of file pbx.c.
References ast_cli(), pbx_builtin_setvar_helper(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03747 { 03748 if (argc != 4) 03749 return RESULT_SHOWUSAGE; 03750 03751 pbx_builtin_setvar_helper(NULL, argv[2], argv[3]); 03752 ast_cli(fd, "\n -- Global variable %s set to %s\n", argv[2], argv[3]); 03753 03754 return RESULT_SUCCESS; 03755 }
static int handle_show_application | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3192 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().
03193 { 03194 struct ast_app *a; 03195 int app, no_registered_app = 1; 03196 03197 if (argc < 4) 03198 return RESULT_SHOWUSAGE; 03199 03200 /* ... go through all applications ... */ 03201 AST_LIST_LOCK(&apps); 03202 AST_LIST_TRAVERSE(&apps, a, list) { 03203 /* ... compare this application name with all arguments given 03204 * to 'show application' command ... */ 03205 for (app = 3; app < argc; app++) { 03206 if (!strcasecmp(a->name, argv[app])) { 03207 /* Maximum number of characters added by terminal coloring is 22 */ 03208 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40]; 03209 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL; 03210 int synopsis_size, description_size; 03211 03212 no_registered_app = 0; 03213 03214 if (a->synopsis) 03215 synopsis_size = strlen(a->synopsis) + 23; 03216 else 03217 synopsis_size = strlen("Not available") + 23; 03218 synopsis = alloca(synopsis_size); 03219 03220 if (a->description) 03221 description_size = strlen(a->description) + 23; 03222 else 03223 description_size = strlen("Not available") + 23; 03224 description = alloca(description_size); 03225 03226 if (synopsis && description) { 03227 snprintf(info, 64 + AST_MAX_APP, "\n -= Info about application '%s' =- \n\n", a->name); 03228 term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22); 03229 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 03230 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40); 03231 term_color(synopsis, 03232 a->synopsis ? a->synopsis : "Not available", 03233 COLOR_CYAN, 0, synopsis_size); 03234 term_color(description, 03235 a->description ? a->description : "Not available", 03236 COLOR_CYAN, 0, description_size); 03237 03238 ast_cli(fd,"%s%s%s\n\n%s%s\n", infotitle, syntitle, synopsis, destitle, description); 03239 } else { 03240 /* ... one of our applications, show info ...*/ 03241 ast_cli(fd,"\n -= Info about application '%s' =- \n\n" 03242 "[Synopsis]\n %s\n\n" 03243 "[Description]\n%s\n", 03244 a->name, 03245 a->synopsis ? a->synopsis : "Not available", 03246 a->description ? a->description : "Not available"); 03247 } 03248 } 03249 } 03250 } 03251 AST_LIST_UNLOCK(&apps); 03252 03253 /* we found at least one app? no? */ 03254 if (no_registered_app) { 03255 ast_cli(fd, "Your application(s) is (are) not registered\n"); 03256 return RESULT_FAILURE; 03257 } 03258 03259 return RESULT_SUCCESS; 03260 }
static int handle_show_application_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3122 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().
03123 { 03124 struct ast_app *a; 03125 int app, no_registered_app = 1; 03126 03127 if (argc < 3) 03128 return RESULT_SHOWUSAGE; 03129 03130 /* ... go through all applications ... */ 03131 AST_LIST_LOCK(&apps); 03132 AST_LIST_TRAVERSE(&apps, a, list) { 03133 /* ... compare this application name with all arguments given 03134 * to 'show application' command ... */ 03135 for (app = 2; app < argc; app++) { 03136 if (!strcasecmp(a->name, argv[app])) { 03137 /* Maximum number of characters added by terminal coloring is 22 */ 03138 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40]; 03139 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL; 03140 int synopsis_size, description_size; 03141 03142 no_registered_app = 0; 03143 03144 if (a->synopsis) 03145 synopsis_size = strlen(a->synopsis) + 23; 03146 else 03147 synopsis_size = strlen("Not available") + 23; 03148 synopsis = alloca(synopsis_size); 03149 03150 if (a->description) 03151 description_size = strlen(a->description) + 23; 03152 else 03153 description_size = strlen("Not available") + 23; 03154 description = alloca(description_size); 03155 03156 if (synopsis && description) { 03157 snprintf(info, 64 + AST_MAX_APP, "\n -= Info about application '%s' =- \n\n", a->name); 03158 term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22); 03159 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 03160 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40); 03161 term_color(synopsis, 03162 a->synopsis ? a->synopsis : "Not available", 03163 COLOR_CYAN, 0, synopsis_size); 03164 term_color(description, 03165 a->description ? a->description : "Not available", 03166 COLOR_CYAN, 0, description_size); 03167 03168 ast_cli(fd,"%s%s%s\n\n%s%s\n", infotitle, syntitle, synopsis, destitle, description); 03169 } else { 03170 /* ... one of our applications, show info ...*/ 03171 ast_cli(fd,"\n -= Info about application '%s' =- \n\n" 03172 "[Synopsis]\n %s\n\n" 03173 "[Description]\n%s\n", 03174 a->name, 03175 a->synopsis ? a->synopsis : "Not available", 03176 a->description ? a->description : "Not available"); 03177 } 03178 } 03179 } 03180 } 03181 AST_LIST_UNLOCK(&apps); 03182 03183 /* we found at least one app? no? */ 03184 if (no_registered_app) { 03185 ast_cli(fd, "Your application(s) is (are) not registered\n"); 03186 return RESULT_FAILURE; 03187 } 03188 03189 return RESULT_SUCCESS; 03190 }
static int handle_show_applications | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3387 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.
03388 { 03389 struct ast_app *a; 03390 int like = 0, describing = 0; 03391 int total_match = 0; /* Number of matches in like clause */ 03392 int total_apps = 0; /* Number of apps registered */ 03393 03394 AST_LIST_LOCK(&apps); 03395 03396 if (AST_LIST_EMPTY(&apps)) { 03397 ast_cli(fd, "There are no registered applications\n"); 03398 AST_LIST_UNLOCK(&apps); 03399 return -1; 03400 } 03401 03402 /* core list applications like <keyword> */ 03403 if ((argc == 5) && (!strcmp(argv[3], "like"))) { 03404 like = 1; 03405 } else if ((argc > 4) && (!strcmp(argv[3], "describing"))) { 03406 describing = 1; 03407 } 03408 03409 /* core list applications describing <keyword1> [<keyword2>] [...] */ 03410 if ((!like) && (!describing)) { 03411 ast_cli(fd, " -= Registered Asterisk Applications =-\n"); 03412 } else { 03413 ast_cli(fd, " -= Matching Asterisk Applications =-\n"); 03414 } 03415 03416 AST_LIST_TRAVERSE(&apps, a, list) { 03417 int printapp = 0; 03418 total_apps++; 03419 if (like) { 03420 if (strcasestr(a->name, argv[4])) { 03421 printapp = 1; 03422 total_match++; 03423 } 03424 } else if (describing) { 03425 if (a->description) { 03426 /* Match all words on command line */ 03427 int i; 03428 printapp = 1; 03429 for (i = 4; i < argc; i++) { 03430 if (!strcasestr(a->description, argv[i])) { 03431 printapp = 0; 03432 } else { 03433 total_match++; 03434 } 03435 } 03436 } 03437 } else { 03438 printapp = 1; 03439 } 03440 03441 if (printapp) { 03442 ast_cli(fd," %20s: %s\n", a->name, a->synopsis ? a->synopsis : "<Synopsis not available>"); 03443 } 03444 } 03445 if ((!like) && (!describing)) { 03446 ast_cli(fd, " -= %d Applications Registered =-\n",total_apps); 03447 } else { 03448 ast_cli(fd, " -= %d Applications Matching =-\n",total_match); 03449 } 03450 03451 AST_LIST_UNLOCK(&apps); 03452 03453 return RESULT_SUCCESS; 03454 }
static int handle_show_applications_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3319 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.
03320 { 03321 struct ast_app *a; 03322 int like = 0, describing = 0; 03323 int total_match = 0; /* Number of matches in like clause */ 03324 int total_apps = 0; /* Number of apps registered */ 03325 03326 AST_LIST_LOCK(&apps); 03327 03328 if (AST_LIST_EMPTY(&apps)) { 03329 ast_cli(fd, "There are no registered applications\n"); 03330 AST_LIST_UNLOCK(&apps); 03331 return -1; 03332 } 03333 03334 /* show applications like <keyword> */ 03335 if ((argc == 4) && (!strcmp(argv[2], "like"))) { 03336 like = 1; 03337 } else if ((argc > 3) && (!strcmp(argv[2], "describing"))) { 03338 describing = 1; 03339 } 03340 03341 /* show applications describing <keyword1> [<keyword2>] [...] */ 03342 if ((!like) && (!describing)) { 03343 ast_cli(fd, " -= Registered Asterisk Applications =-\n"); 03344 } else { 03345 ast_cli(fd, " -= Matching Asterisk Applications =-\n"); 03346 } 03347 03348 AST_LIST_TRAVERSE(&apps, a, list) { 03349 int printapp = 0; 03350 total_apps++; 03351 if (like) { 03352 if (strcasestr(a->name, argv[3])) { 03353 printapp = 1; 03354 total_match++; 03355 } 03356 } else if (describing) { 03357 if (a->description) { 03358 /* Match all words on command line */ 03359 int i; 03360 printapp = 1; 03361 for (i = 3; i < argc; i++) { 03362 if (!strcasestr(a->description, argv[i])) { 03363 printapp = 0; 03364 } else { 03365 total_match++; 03366 } 03367 } 03368 } 03369 } else { 03370 printapp = 1; 03371 } 03372 03373 if (printapp) { 03374 ast_cli(fd," %20s: %s\n", a->name, a->synopsis ? a->synopsis : "<Synopsis not available>"); 03375 } 03376 } 03377 if ((!like) && (!describing)) { 03378 ast_cli(fd, " -= %d Applications Registered =-\n",total_apps); 03379 } else { 03380 ast_cli(fd, " -= %d Applications Matching =-\n",total_match); 03381 } 03382 03383 AST_LIST_UNLOCK(&apps); 03384 03385 return RESULT_SUCCESS; 03386 }
static int handle_show_dialplan | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3673 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().
03674 { 03675 char *exten = NULL, *context = NULL; 03676 /* Variables used for different counters */ 03677 struct dialplan_counters counters; 03678 03679 const char *incstack[AST_PBX_MAX_STACK]; 03680 memset(&counters, 0, sizeof(counters)); 03681 03682 if (argc != 2 && argc != 3) 03683 return RESULT_SHOWUSAGE; 03684 03685 /* we obtain [exten@]context? if yes, split them ... */ 03686 if (argc == 3) { 03687 if (strchr(argv[2], '@')) { /* split into exten & context */ 03688 context = ast_strdupa(argv[2]); 03689 exten = strsep(&context, "@"); 03690 /* change empty strings to NULL */ 03691 if (ast_strlen_zero(exten)) 03692 exten = NULL; 03693 } else { /* no '@' char, only context given */ 03694 context = argv[2]; 03695 } 03696 if (ast_strlen_zero(context)) 03697 context = NULL; 03698 } 03699 /* else Show complete dial plan, context and exten are NULL */ 03700 show_dialplan_helper(fd, context, exten, &counters, NULL, 0, incstack); 03701 03702 /* check for input failure and throw some error messages */ 03703 if (context && !counters.context_existence) { 03704 ast_cli(fd, "There is no existence of '%s' context\n", context); 03705 return RESULT_FAILURE; 03706 } 03707 03708 if (exten && !counters.extension_existence) { 03709 if (context) 03710 ast_cli(fd, "There is no existence of %s@%s extension\n", 03711 exten, context); 03712 else 03713 ast_cli(fd, 03714 "There is no existence of '%s' extension in all contexts\n", 03715 exten); 03716 return RESULT_FAILURE; 03717 } 03718 03719 ast_cli(fd,"-= %d %s (%d %s) in %d %s. =-\n", 03720 counters.total_exten, counters.total_exten == 1 ? "extension" : "extensions", 03721 counters.total_prio, counters.total_prio == 1 ? "priority" : "priorities", 03722 counters.total_context, counters.total_context == 1 ? "context" : "contexts"); 03723 03724 /* everything ok */ 03725 return RESULT_SUCCESS; 03726 }
static int handle_show_function | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1384 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().
01385 { 01386 struct ast_custom_function *acf; 01387 /* Maximum number of characters added by terminal coloring is 22 */ 01388 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40]; 01389 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL; 01390 char stxtitle[40], *syntax = NULL; 01391 int synopsis_size, description_size, syntax_size; 01392 01393 if (argc < 4) 01394 return RESULT_SHOWUSAGE; 01395 01396 if (!(acf = ast_custom_function_find(argv[3]))) { 01397 ast_cli(fd, "No function by that name registered.\n"); 01398 return RESULT_FAILURE; 01399 01400 } 01401 01402 if (acf->synopsis) 01403 synopsis_size = strlen(acf->synopsis) + 23; 01404 else 01405 synopsis_size = strlen("Not available") + 23; 01406 synopsis = alloca(synopsis_size); 01407 01408 if (acf->desc) 01409 description_size = strlen(acf->desc) + 23; 01410 else 01411 description_size = strlen("Not available") + 23; 01412 description = alloca(description_size); 01413 01414 if (acf->syntax) 01415 syntax_size = strlen(acf->syntax) + 23; 01416 else 01417 syntax_size = strlen("Not available") + 23; 01418 syntax = alloca(syntax_size); 01419 01420 snprintf(info, 64 + AST_MAX_APP, "\n -= Info about function '%s' =- \n\n", acf->name); 01421 term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22); 01422 term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40); 01423 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 01424 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40); 01425 term_color(syntax, 01426 acf->syntax ? acf->syntax : "Not available", 01427 COLOR_CYAN, 0, syntax_size); 01428 term_color(synopsis, 01429 acf->synopsis ? acf->synopsis : "Not available", 01430 COLOR_CYAN, 0, synopsis_size); 01431 term_color(description, 01432 acf->desc ? acf->desc : "Not available", 01433 COLOR_CYAN, 0, description_size); 01434 01435 ast_cli(fd,"%s%s%s\n\n%s%s\n\n%s%s\n", infotitle, stxtitle, syntax, syntitle, synopsis, destitle, description); 01436 01437 return RESULT_SUCCESS; 01438 }
static int handle_show_function_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1328 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().
01329 { 01330 struct ast_custom_function *acf; 01331 /* Maximum number of characters added by terminal coloring is 22 */ 01332 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40]; 01333 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL; 01334 char stxtitle[40], *syntax = NULL; 01335 int synopsis_size, description_size, syntax_size; 01336 01337 if (argc < 3) 01338 return RESULT_SHOWUSAGE; 01339 01340 if (!(acf = ast_custom_function_find(argv[2]))) { 01341 ast_cli(fd, "No function by that name registered.\n"); 01342 return RESULT_FAILURE; 01343 01344 } 01345 01346 if (acf->synopsis) 01347 synopsis_size = strlen(acf->synopsis) + 23; 01348 else 01349 synopsis_size = strlen("Not available") + 23; 01350 synopsis = alloca(synopsis_size); 01351 01352 if (acf->desc) 01353 description_size = strlen(acf->desc) + 23; 01354 else 01355 description_size = strlen("Not available") + 23; 01356 description = alloca(description_size); 01357 01358 if (acf->syntax) 01359 syntax_size = strlen(acf->syntax) + 23; 01360 else 01361 syntax_size = strlen("Not available") + 23; 01362 syntax = alloca(syntax_size); 01363 01364 snprintf(info, 64 + AST_MAX_APP, "\n -= Info about function '%s' =- \n\n", acf->name); 01365 term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22); 01366 term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40); 01367 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 01368 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40); 01369 term_color(syntax, 01370 acf->syntax ? acf->syntax : "Not available", 01371 COLOR_CYAN, 0, syntax_size); 01372 term_color(synopsis, 01373 acf->synopsis ? acf->synopsis : "Not available", 01374 COLOR_CYAN, 0, synopsis_size); 01375 term_color(description, 01376 acf->desc ? acf->desc : "Not available", 01377 COLOR_CYAN, 0, description_size); 01378 01379 ast_cli(fd,"%s%s%s\n\n%s%s\n\n%s%s\n", infotitle, stxtitle, syntax, syntitle, synopsis, destitle, description); 01380 01381 return RESULT_SUCCESS; 01382 }
static int handle_show_functions | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1300 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.
01301 { 01302 struct ast_custom_function *acf; 01303 int count_acf = 0; 01304 int like = 0; 01305 01306 if (argc == 5 && (!strcmp(argv[3], "like")) ) { 01307 like = 1; 01308 } else if (argc != 3) { 01309 return RESULT_SHOWUSAGE; 01310 } 01311 01312 ast_cli(fd, "%s Custom Functions:\n--------------------------------------------------------------------------------\n", like ? "Matching" : "Installed"); 01313 01314 AST_LIST_LOCK(&acf_root); 01315 AST_LIST_TRAVERSE(&acf_root, acf, acflist) { 01316 if (!like || strstr(acf->name, argv[4])) { 01317 count_acf++; 01318 ast_cli(fd, "%-20.20s %-35.35s %s\n", acf->name, acf->syntax, acf->synopsis); 01319 } 01320 } 01321 AST_LIST_UNLOCK(&acf_root); 01322 01323 ast_cli(fd, "%d %scustom functions installed.\n", count_acf, like ? "matching " : ""); 01324 01325 return RESULT_SUCCESS; 01326 }
static int handle_show_functions_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1273 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.
01274 { 01275 struct ast_custom_function *acf; 01276 int count_acf = 0; 01277 int like = 0; 01278 01279 if (argc == 4 && (!strcmp(argv[2], "like")) ) { 01280 like = 1; 01281 } else if (argc != 2) { 01282 return RESULT_SHOWUSAGE; 01283 } 01284 01285 ast_cli(fd, "%s Custom Functions:\n--------------------------------------------------------------------------------\n", like ? "Matching" : "Installed"); 01286 01287 AST_LIST_LOCK(&acf_root); 01288 AST_LIST_TRAVERSE(&acf_root, acf, acflist) { 01289 if (!like || strstr(acf->name, argv[3])) { 01290 count_acf++; 01291 ast_cli(fd, "%-20.20s %-35.35s %s\n", acf->name, acf->syntax, acf->synopsis); 01292 } 01293 } 01294 AST_LIST_UNLOCK(&acf_root); 01295 01296 ast_cli(fd, "%d %scustom functions installed.\n", count_acf, like ? "matching " : ""); 01297 01298 return RESULT_SUCCESS; 01299 }
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 3729 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.
03730 { 03731 int i = 0; 03732 struct ast_var_t *newvariable; 03733 03734 ast_mutex_lock(&globalslock); 03735 AST_LIST_TRAVERSE (&globals, newvariable, entries) { 03736 i++; 03737 ast_cli(fd, " %s=%s\n", ast_var_name(newvariable), ast_var_value(newvariable)); 03738 } 03739 ast_mutex_unlock(&globalslock); 03740 ast_cli(fd, "\n -- %d variables\n", i); 03741 03742 return RESULT_SUCCESS; 03743 }
static int handle_show_hints | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
handle_show_hints: CLI support for listing registered dial plan hints
Definition at line 3263 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.
03264 { 03265 struct ast_hint *hint; 03266 int num = 0; 03267 int watchers; 03268 struct ast_state_cb *watcher; 03269 03270 if (AST_LIST_EMPTY(&hints)) { 03271 ast_cli(fd, "There are no registered dialplan hints\n"); 03272 return RESULT_SUCCESS; 03273 } 03274 /* ... we have hints ... */ 03275 ast_cli(fd, "\n -= Registered Asterisk Dial Plan Hints =-\n"); 03276 AST_LIST_LOCK(&hints); 03277 AST_LIST_TRAVERSE(&hints, hint, list) { 03278 watchers = 0; 03279 for (watcher = hint->callbacks; watcher; watcher = watcher->next) 03280 watchers++; 03281 ast_cli(fd, " %20s@%-20.20s: %-20.20s State:%-15.15s Watchers %2d\n", 03282 ast_get_extension_name(hint->exten), 03283 ast_get_context_name(ast_get_extension_context(hint->exten)), 03284 ast_get_extension_app(hint->exten), 03285 ast_extension_state2str(hint->laststate), watchers); 03286 num++; 03287 } 03288 ast_cli(fd, "----------------\n"); 03289 ast_cli(fd, "- %d hints registered\n", num); 03290 AST_LIST_UNLOCK(&hints); 03291 return RESULT_SUCCESS; 03292 }
static int handle_show_switches | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
handle_show_switches: CLI support for listing registered dial plan switches
Definition at line 3295 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.
03296 { 03297 struct ast_switch *sw; 03298 03299 AST_LIST_LOCK(&switches); 03300 03301 if (AST_LIST_EMPTY(&switches)) { 03302 AST_LIST_UNLOCK(&switches); 03303 ast_cli(fd, "There are no registered alternative switches\n"); 03304 return RESULT_SUCCESS; 03305 } 03306 03307 ast_cli(fd, "\n -= Registered Asterisk Alternative Switches =-\n"); 03308 AST_LIST_TRAVERSE(&switches, sw, list) 03309 ast_cli(fd, "%s: %s\n", sw->name, sw->description); 03310 03311 AST_LIST_UNLOCK(&switches); 03312 03313 return RESULT_SUCCESS; 03314 }
static int include_valid | ( | struct ast_include * | i | ) | [inline, static] |
Definition at line 583 of file pbx.c.
References ast_check_timing(), ast_include::hastime, and ast_include::timing.
00584 { 00585 if (!i->hastime) 00586 return 1; 00587 00588 return ast_check_timing(&(i->timing)); 00589 }
static int increase_call_count | ( | const struct ast_channel * | c | ) | [static] |
Definition at line 2585 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().
02586 { 02587 int failed = 0; 02588 double curloadavg; 02589 ast_mutex_lock(&maxcalllock); 02590 if (option_maxcalls) { 02591 if (countcalls >= option_maxcalls) { 02592 ast_log(LOG_NOTICE, "Maximum call limit of %d calls exceeded by '%s'!\n", option_maxcalls, c->name); 02593 failed = -1; 02594 } 02595 } 02596 if (option_maxload) { 02597 getloadavg(&curloadavg, 1); 02598 if (curloadavg >= option_maxload) { 02599 ast_log(LOG_NOTICE, "Maximum loadavg limit of %f load exceeded by '%s' (currently %f)!\n", option_maxload, c->name, curloadavg); 02600 failed = -1; 02601 } 02602 } 02603 if (!failed) 02604 countcalls++; 02605 ast_mutex_unlock(&maxcalllock); 02606 02607 return failed; 02608 }
int load_pbx | ( | void | ) |
Provided by pbx.c
Definition at line 6119 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().
06120 { 06121 int x; 06122 06123 /* Initialize the PBX */ 06124 if (option_verbose) { 06125 ast_verbose( "Asterisk PBX Core Initializing\n"); 06126 ast_verbose( "Registering builtin applications:\n"); 06127 } 06128 ast_cli_register_multiple(pbx_cli, sizeof(pbx_cli) / sizeof(struct ast_cli_entry)); 06129 06130 /* Register builtin applications */ 06131 for (x=0; x<sizeof(builtins) / sizeof(struct pbx_builtin); x++) { 06132 if (option_verbose) 06133 ast_verbose( VERBOSE_PREFIX_1 "[%s]\n", builtins[x].name); 06134 if (ast_register_application(builtins[x].name, builtins[x].execute, builtins[x].synopsis, builtins[x].description)) { 06135 ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name); 06136 return -1; 06137 } 06138 } 06139 return 0; 06140 }
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 4069 of file pbx.c.
Referenced by get_range().
04070 { 04071 int i; 04072 04073 if (names) { 04074 for (i = 0; names[i]; i++) { 04075 if (!strcasecmp(s, names[i])) 04076 return i+1; 04077 } 04078 } else if (sscanf(s, "%d", &i) == 1 && i >= 1 && i <= max) { 04079 return i; 04080 } 04081 return 0; /* error return */ 04082 }
static int matchcid | ( | const char * | cidpattern, | |
const char * | callerid | |||
) | [static] |
Definition at line 919 of file pbx.c.
References ast_extension_match(), and ast_strlen_zero().
Referenced by pbx_find_extension().
00920 { 00921 /* If the Caller*ID pattern is empty, then we're matching NO Caller*ID, so 00922 failing to get a number should count as a match, otherwise not */ 00923 00924 if (ast_strlen_zero(callerid)) 00925 return ast_strlen_zero(cidpattern) ? 1 : 0; 00926 00927 return ast_extension_match(cidpattern, callerid); 00928 }
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 1085 of file pbx.c.
Referenced by pbx_retrieve_variable(), and pbx_substitute_variables_helper_full().
01086 { 01087 int parens=0; 01088 01089 *offset = 0; 01090 *length = INT_MAX; 01091 *isfunc = 0; 01092 for (; *var; var++) { 01093 if (*var == '(') { 01094 (*isfunc)++; 01095 parens++; 01096 } else if (*var == ')') { 01097 parens--; 01098 } else if (*var == ':' && parens == 0) { 01099 *var++ = '\0'; 01100 sscanf(var, "%d:%d", offset, length); 01101 return 1; /* offset:length valid */ 01102 } 01103 } 01104 return 0; 01105 }
void pbx_builtin_clear_globals | ( | void | ) |
Definition at line 6021 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().
06022 { 06023 struct ast_var_t *vardata; 06024 06025 ast_mutex_lock(&globalslock); 06026 while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries))) 06027 ast_var_delete(vardata); 06028 ast_mutex_unlock(&globalslock); 06029 }
const char* pbx_builtin_getvar_helper | ( | struct ast_channel * | chan, | |
const char * | name | |||
) |
Definition at line 5798 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(), pop_exec(), queue_exec(), real_ctx(), retrydial_exec(), return_exec(), run_agi(), rxfax_exec(), set_config_flags(), sip_addheader(), sla_trunk_exec(), speech_background(), try_calling(), try_suggested_sip_codec(), txfax_exec(), wait_for_answer(), zt_call(), and zt_hangup().
05799 { 05800 struct ast_var_t *variables; 05801 const char *ret = NULL; 05802 int i; 05803 struct varshead *places[2] = { NULL, &globals }; 05804 05805 if (!name) 05806 return NULL; 05807 05808 if (chan) { 05809 ast_channel_lock(chan); 05810 places[0] = &chan->varshead; 05811 } 05812 05813 for (i = 0; i < 2; i++) { 05814 if (!places[i]) 05815 continue; 05816 if (places[i] == &globals) 05817 ast_mutex_lock(&globalslock); 05818 AST_LIST_TRAVERSE(places[i], variables, entries) { 05819 if (!strcmp(name, ast_var_name(variables))) { 05820 ret = ast_var_value(variables); 05821 break; 05822 } 05823 } 05824 if (places[i] == &globals) 05825 ast_mutex_unlock(&globalslock); 05826 if (ret) 05827 break; 05828 } 05829 05830 if (chan) 05831 ast_channel_unlock(chan); 05832 05833 return ret; 05834 }
static int pbx_builtin_gotoif | ( | struct ast_channel * | , | |
void * | ||||
) | [static] |
Definition at line 6041 of file pbx.c.
References ast_log(), ast_strdupa, ast_strlen_zero(), LOG_WARNING, pbx_builtin_goto(), pbx_checkcondition(), and strsep().
06042 { 06043 char *condition, *branch1, *branch2, *branch; 06044 int rc; 06045 char *stringp; 06046 06047 if (ast_strlen_zero(data)) { 06048 ast_log(LOG_WARNING, "Ignoring, since there is no variable to check\n"); 06049 return 0; 06050 } 06051 06052 stringp = ast_strdupa(data); 06053 condition = strsep(&stringp,"?"); 06054 branch1 = strsep(&stringp,":"); 06055 branch2 = strsep(&stringp,""); 06056 branch = pbx_checkcondition(condition) ? branch1 : branch2; 06057 06058 if (ast_strlen_zero(branch)) { 06059 if (option_debug) 06060 ast_log(LOG_DEBUG, "Not taking any branch\n"); 06061 return 0; 06062 } 06063 06064 rc = pbx_builtin_goto(chan, branch); 06065 06066 return rc; 06067 }
int pbx_builtin_importvar | ( | struct ast_channel * | , | |
void * | ||||
) | [static] |
Definition at line 5960 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.
05961 { 05962 char *name; 05963 char *value; 05964 char *channel; 05965 char tmp[VAR_BUF_SIZE]=""; 05966 05967 if (ast_strlen_zero(data)) { 05968 ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n"); 05969 return 0; 05970 } 05971 05972 value = ast_strdupa(data); 05973 name = strsep(&value,"="); 05974 channel = strsep(&value,"|"); 05975 if (channel && value && name) { /*! \todo XXX should do !ast_strlen_zero(..) of the args ? */ 05976 struct ast_channel *chan2 = ast_get_channel_by_name_locked(channel); 05977 if (chan2) { 05978 char *s = alloca(strlen(value) + 4); 05979 if (s) { 05980 sprintf(s, "${%s}", value); 05981 pbx_substitute_variables_helper(chan2, s, tmp, sizeof(tmp) - 1); 05982 } 05983 ast_channel_unlock(chan2); 05984 } 05985 pbx_builtin_setvar_helper(chan, name, tmp); 05986 } 05987 05988 return(0); 05989 }
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 5836 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().
05837 { 05838 struct ast_var_t *newvariable; 05839 struct varshead *headp; 05840 05841 if (name[strlen(name)-1] == ')') { 05842 char *function = ast_strdupa(name); 05843 05844 ast_log(LOG_WARNING, "Cannot push a value onto a function\n"); 05845 ast_func_write(chan, function, value); 05846 return; 05847 } 05848 05849 if (chan) { 05850 ast_channel_lock(chan); 05851 headp = &chan->varshead; 05852 } else { 05853 ast_mutex_lock(&globalslock); 05854 headp = &globals; 05855 } 05856 05857 if (value) { 05858 if ((option_verbose > 1) && (headp == &globals)) 05859 ast_verbose(VERBOSE_PREFIX_2 "Setting global variable '%s' to '%s'\n", name, value); 05860 newvariable = ast_var_assign(name, value); 05861 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 05862 } 05863 05864 if (chan) 05865 ast_channel_unlock(chan); 05866 else 05867 ast_mutex_unlock(&globalslock); 05868 }
static int pbx_builtin_saycharacters | ( | struct ast_channel * | , | |
void * | ||||
) | [static] |
Definition at line 6101 of file pbx.c.
References ast_say_character_str().
06102 { 06103 int res = 0; 06104 06105 if (data) 06106 res = ast_say_character_str(chan, data, "", chan->language); 06107 return res; 06108 }
static int pbx_builtin_saydigits | ( | struct ast_channel * | , | |
void * | ||||
) | [static] |
Definition at line 6092 of file pbx.c.
References ast_say_digit_str().
06093 { 06094 int res = 0; 06095 06096 if (data) 06097 res = ast_say_digit_str(chan, data, "", chan->language); 06098 return res; 06099 }
static int pbx_builtin_saynumber | ( | struct ast_channel * | , | |
void * | ||||
) | [static] |
Definition at line 6069 of file pbx.c.
References ast_log(), ast_say_number(), ast_strlen_zero(), LOG_WARNING, and strsep().
06070 { 06071 char tmp[256]; 06072 char *number = tmp; 06073 char *options; 06074 06075 if (ast_strlen_zero(data)) { 06076 ast_log(LOG_WARNING, "SayNumber requires an argument (number)\n"); 06077 return -1; 06078 } 06079 ast_copy_string(tmp, data, sizeof(tmp)); 06080 strsep(&number, "|"); 06081 options = strsep(&number, "|"); 06082 if (options) { 06083 if ( strcasecmp(options, "f") && strcasecmp(options,"m") && 06084 strcasecmp(options, "c") && strcasecmp(options, "n") ) { 06085 ast_log(LOG_WARNING, "SayNumber gender option is either 'f', 'm', 'c' or 'n'\n"); 06086 return -1; 06087 } 06088 } 06089 return ast_say_number(chan, atoi(tmp), "", chan->language, options); 06090 }
static int pbx_builtin_sayphonetic | ( | struct ast_channel * | , | |
void * | ||||
) | [static] |
Definition at line 6110 of file pbx.c.
References ast_say_phonetic_str().
06111 { 06112 int res = 0; 06113 06114 if (data) 06115 res = ast_say_phonetic_str(chan, data, "", chan->language); 06116 return res; 06117 }
int pbx_builtin_serialize_variables | ( | struct ast_channel * | chan, | |
char * | buf, | |||
size_t | size | |||
) |
Definition at line 5767 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().
05768 { 05769 struct ast_var_t *variables; 05770 const char *var, *val; 05771 int total = 0; 05772 05773 if (!chan) 05774 return 0; 05775 05776 memset(buf, 0, size); 05777 05778 ast_channel_lock(chan); 05779 05780 AST_LIST_TRAVERSE(&chan->varshead, variables, entries) { 05781 if ((var=ast_var_name(variables)) && (val=ast_var_value(variables)) 05782 /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */ 05783 ) { 05784 if (ast_build_string(&buf, &size, "%s=%s\n", var, val)) { 05785 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n"); 05786 break; 05787 } else 05788 total++; 05789 } else 05790 break; 05791 } 05792 05793 ast_channel_unlock(chan); 05794 05795 return total; 05796 }
static int pbx_builtin_setglobalvar | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 5992 of file pbx.c.
References ast_log(), ast_strlen_zero(), LOG_WARNING, pbx_builtin_setvar_helper(), and strsep().
05993 { 05994 char *name; 05995 char *stringp = data; 05996 static int dep_warning = 0; 05997 05998 if (ast_strlen_zero(data)) { 05999 ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n"); 06000 return 0; 06001 } 06002 06003 name = strsep(&stringp, "="); 06004 06005 if (!dep_warning) { 06006 dep_warning = 1; 06007 ast_log(LOG_WARNING, "SetGlobalVar is deprecated. Please use Set(GLOBAL(%s)=%s) instead.\n", name, stringp); 06008 } 06009 06010 /*! \todo XXX watch out, leading whitespace ? */ 06011 pbx_builtin_setvar_helper(NULL, name, stringp); 06012 06013 return(0); 06014 }
int pbx_builtin_setvar | ( | struct ast_channel * | , | |
void * | ||||
) |
Definition at line 5920 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().
05921 { 05922 char *name, *value, *mydata; 05923 int argc; 05924 char *argv[24]; /* this will only support a maximum of 24 variables being set in a single operation */ 05925 int global = 0; 05926 int x; 05927 05928 if (ast_strlen_zero(data)) { 05929 ast_log(LOG_WARNING, "Set requires at least one variable name/value pair.\n"); 05930 return 0; 05931 } 05932 05933 mydata = ast_strdupa(data); 05934 argc = ast_app_separate_args(mydata, '|', argv, sizeof(argv) / sizeof(argv[0])); 05935 05936 /* check for a trailing flags argument */ 05937 if ((argc > 1) && !strchr(argv[argc-1], '=')) { 05938 argc--; 05939 if (strchr(argv[argc], 'g')) { 05940 ast_log(LOG_WARNING, "The use of the 'g' flag is deprecated. Please use Set(GLOBAL(foo)=bar) instead\n"); 05941 global = 1; 05942 } 05943 } 05944 05945 if (argc > 1) 05946 ast_log(LOG_WARNING, "Setting multiple variables at once within Set is deprecated. Please separate each name/value pair into its own line.\n"); 05947 05948 for (x = 0; x < argc; x++) { 05949 name = argv[x]; 05950 if ((value = strchr(name, '='))) { 05951 *value++ = '\0'; 05952 pbx_builtin_setvar_helper((global) ? NULL : chan, name, value); 05953 } else 05954 ast_log(LOG_WARNING, "Ignoring entry '%s' with no = (and not last 'options' entry)\n", name); 05955 } 05956 05957 return(0); 05958 }
void pbx_builtin_setvar_helper | ( | struct ast_channel * | chan, | |
const char * | name, | |||
const char * | value | |||
) |
Definition at line 5870 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(), aMYSQL_fetch(), 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(), 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(), mwanalyze_exec(), MYSQL_exec(), nv_background_detect_exec(), nv_detectfax_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(), phase_e_handler(), pickdown_channel(), pickup_channel(), 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_asterisk_int(), 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(), steal_channel(), system_exec_helper(), transfer_exec(), try_calling(), tryexec_exec(), upqm_exec(), vm_box_exists(), vm_exec(), vmauthenticate(), zt_handle_dtmfup(), and zt_new().
05871 { 05872 struct ast_var_t *newvariable; 05873 struct varshead *headp; 05874 const char *nametail = name; 05875 05876 if (name[strlen(name)-1] == ')') { 05877 char *function = ast_strdupa(name); 05878 05879 ast_func_write(chan, function, value); 05880 return; 05881 } 05882 05883 if (chan) { 05884 ast_channel_lock(chan); 05885 headp = &chan->varshead; 05886 } else { 05887 ast_mutex_lock(&globalslock); 05888 headp = &globals; 05889 } 05890 05891 /* For comparison purposes, we have to strip leading underscores */ 05892 if (*nametail == '_') { 05893 nametail++; 05894 if (*nametail == '_') 05895 nametail++; 05896 } 05897 05898 AST_LIST_TRAVERSE (headp, newvariable, entries) { 05899 if (strcasecmp(ast_var_name(newvariable), nametail) == 0) { 05900 /* there is already such a variable, delete it */ 05901 AST_LIST_REMOVE(headp, newvariable, entries); 05902 ast_var_delete(newvariable); 05903 break; 05904 } 05905 } 05906 05907 if (value) { 05908 if ((option_verbose > 1) && (headp == &globals)) 05909 ast_verbose(VERBOSE_PREFIX_2 "Setting global variable '%s' to '%s'\n", name, value); 05910 newvariable = ast_var_assign(name, value); 05911 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 05912 } 05913 05914 if (chan) 05915 ast_channel_unlock(chan); 05916 else 05917 ast_mutex_unlock(&globalslock); 05918 }
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 6031 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().
06032 { 06033 if (ast_strlen_zero(condition)) /* NULL or empty strings are false */ 06034 return 0; 06035 else if (*condition >= '0' && *condition <= '9') /* Numbers are evaluated for truth */ 06036 return atoi(condition); 06037 else /* Strings are true */ 06038 return 1; 06039 }
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 517 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(), page_exec(), pbx_builtin_execiftime(), pbx_extension_helper(), realtime_exec(), try_calling(), and tryexec_exec().
00520 { 00521 int res; 00522 00523 const char *saved_c_appl; 00524 const char *saved_c_data; 00525 00526 if (c->cdr && !ast_check_hangup(c)) 00527 ast_cdr_setapp(c->cdr, app->name, data); 00528 00529 /* save channel values */ 00530 saved_c_appl= c->appl; 00531 saved_c_data= c->data; 00532 00533 c->appl = app->name; 00534 c->data = data; 00535 /* XXX remember what to to when we have linked apps to modules */ 00536 if (app->module) { 00537 /* XXX LOCAL_USER_ADD(app->module) */ 00538 } 00539 res = app->execute(c, S_OR(data, "")); 00540 if (app->module) { 00541 /* XXX LOCAL_USER_REMOVE(app->module) */ 00542 } 00543 /* restore channel values */ 00544 c->appl = saved_c_appl; 00545 c->data = saved_c_data; 00546 return res; 00547 }
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 1812 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().
01815 { 01816 struct ast_exten *e; 01817 struct ast_app *app; 01818 int res; 01819 struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */ 01820 char passdata[EXT_DATA_SIZE]; 01821 01822 int matching_action = (action == E_MATCH || action == E_CANMATCH || action == E_MATCHMORE); 01823 01824 ast_rdlock_contexts(); 01825 e = pbx_find_extension(c, con, &q, context, exten, priority, label, callerid, action); 01826 if (e) { 01827 if (matching_action) { 01828 ast_unlock_contexts(); 01829 return -1; /* success, we found it */ 01830 } else if (action == E_FINDLABEL) { /* map the label to a priority */ 01831 res = e->priority; 01832 ast_unlock_contexts(); 01833 return res; /* the priority we were looking for */ 01834 } else { /* spawn */ 01835 app = pbx_findapp(e->app); 01836 ast_unlock_contexts(); 01837 if (!app) { 01838 ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority); 01839 return -1; 01840 } 01841 if (c->context != context) 01842 ast_copy_string(c->context, context, sizeof(c->context)); 01843 if (c->exten != exten) 01844 ast_copy_string(c->exten, exten, sizeof(c->exten)); 01845 c->priority = priority; 01846 pbx_substitute_variables(passdata, sizeof(passdata), c, e); 01847 if (option_debug) { 01848 ast_log(LOG_DEBUG, "Launching '%s'\n", app->name); 01849 } 01850 if (option_verbose > 2) { 01851 char tmp[80], tmp2[80], tmp3[EXT_DATA_SIZE]; 01852 ast_verbose( VERBOSE_PREFIX_3 "Executing [%s@%s:%d] %s(\"%s\", \"%s\") %s\n", 01853 exten, context, priority, 01854 term_color(tmp, app->name, COLOR_BRCYAN, 0, sizeof(tmp)), 01855 term_color(tmp2, c->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)), 01856 term_color(tmp3, passdata, COLOR_BRMAGENTA, 0, sizeof(tmp3)), 01857 "in new stack"); 01858 } 01859 manager_event(EVENT_FLAG_CALL, "Newexten", 01860 "Channel: %s\r\n" 01861 "Context: %s\r\n" 01862 "Extension: %s\r\n" 01863 "Priority: %d\r\n" 01864 "Application: %s\r\n" 01865 "AppData: %s\r\n" 01866 "Uniqueid: %s\r\n", 01867 c->name, c->context, c->exten, c->priority, app->name, passdata, c->uniqueid); 01868 return pbx_exec(c, app, passdata); /* 0 on success, -1 on failure */ 01869 } 01870 } else if (q.swo) { /* not found here, but in another switch */ 01871 ast_unlock_contexts(); 01872 if (matching_action) { 01873 return -1; 01874 } else { 01875 if (!q.swo->exec) { 01876 ast_log(LOG_WARNING, "No execution engine for switch %s\n", q.swo->name); 01877 res = -1; 01878 } 01879 return q.swo->exec(c, q.foundcontext ? q.foundcontext : context, exten, priority, callerid, q.data); 01880 } 01881 } else { /* not found anywhere, see what happened */ 01882 ast_unlock_contexts(); 01883 switch (q.status) { 01884 case STATUS_NO_CONTEXT: 01885 if (!matching_action) 01886 ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", context); 01887 break; 01888 case STATUS_NO_EXTENSION: 01889 if (!matching_action) 01890 ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, context); 01891 break; 01892 case STATUS_NO_PRIORITY: 01893 if (!matching_action) 01894 ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, context); 01895 break; 01896 case STATUS_NO_LABEL: 01897 if (context) 01898 ast_log(LOG_NOTICE, "No such label '%s' in extension '%s' in context '%s'\n", label, exten, context); 01899 break; 01900 default: 01901 if (option_debug) 01902 ast_log(LOG_DEBUG, "Shouldn't happen!\n"); 01903 } 01904 01905 return (matching_action) ? 0 : -1; 01906 } 01907 }
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 946 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().
00950 { 00951 int x, res; 00952 struct ast_context *tmp; 00953 struct ast_exten *e, *eroot; 00954 struct ast_include *i; 00955 struct ast_sw *sw; 00956 char *tmpdata = NULL; 00957 00958 /* Initialize status if appropriate */ 00959 if (q->stacklen == 0) { 00960 q->status = STATUS_NO_CONTEXT; 00961 q->swo = NULL; 00962 q->data = NULL; 00963 q->foundcontext = NULL; 00964 } 00965 /* Check for stack overflow */ 00966 if (q->stacklen >= AST_PBX_MAX_STACK) { 00967 ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n"); 00968 return NULL; 00969 } 00970 /* Check first to see if we've already been checked */ 00971 for (x = 0; x < q->stacklen; x++) { 00972 if (!strcasecmp(q->incstack[x], context)) 00973 return NULL; 00974 } 00975 if (bypass) /* bypass means we only look there */ 00976 tmp = bypass; 00977 else { /* look in contexts */ 00978 tmp = NULL; 00979 while ((tmp = ast_walk_contexts(tmp)) ) { 00980 if (!strcmp(tmp->name, context)) 00981 break; 00982 } 00983 if (!tmp) 00984 return NULL; 00985 } 00986 if (q->status < STATUS_NO_EXTENSION) 00987 q->status = STATUS_NO_EXTENSION; 00988 00989 /* scan the list trying to match extension and CID */ 00990 eroot = NULL; 00991 while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) { 00992 int match = extension_match_core(eroot->exten, exten, action); 00993 /* 0 on fail, 1 on match, 2 on earlymatch */ 00994 00995 if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid))) 00996 continue; /* keep trying */ 00997 if (match == 2 && action == E_MATCHMORE) { 00998 /* We match an extension ending in '!'. 00999 * The decision in this case is final and is NULL (no match). 01000 */ 01001 return NULL; 01002 } 01003 /* found entry, now look for the right priority */ 01004 if (q->status < STATUS_NO_PRIORITY) 01005 q->status = STATUS_NO_PRIORITY; 01006 e = NULL; 01007 while ( (e = ast_walk_extension_priorities(eroot, e)) ) { 01008 /* Match label or priority */ 01009 if (action == E_FINDLABEL) { 01010 if (q->status < STATUS_NO_LABEL) 01011 q->status = STATUS_NO_LABEL; 01012 if (label && e->label && !strcmp(label, e->label)) 01013 break; /* found it */ 01014 } else if (e->priority == priority) { 01015 break; /* found it */ 01016 } /* else keep searching */ 01017 } 01018 if (e) { /* found a valid match */ 01019 q->status = STATUS_SUCCESS; 01020 q->foundcontext = context; 01021 return e; 01022 } 01023 } 01024 /* Check alternative switches */ 01025 AST_LIST_TRAVERSE(&tmp->alts, sw, list) { 01026 struct ast_switch *asw = pbx_findswitch(sw->name); 01027 ast_switch_f *aswf = NULL; 01028 char *datap; 01029 01030 if (!asw) { 01031 ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name); 01032 continue; 01033 } 01034 /* Substitute variables now */ 01035 if (sw->eval) { 01036 if (!(tmpdata = ast_threadstorage_get(&switch_data, 512))) { 01037 ast_log(LOG_WARNING, "Can't evaluate switch?!"); 01038 continue; 01039 } 01040 pbx_substitute_variables_helper(chan, sw->data, tmpdata, 512); 01041 } 01042 01043 /* equivalent of extension_match_core() at the switch level */ 01044 if (action == E_CANMATCH) 01045 aswf = asw->canmatch; 01046 else if (action == E_MATCHMORE) 01047 aswf = asw->matchmore; 01048 else /* action == E_MATCH */ 01049 aswf = asw->exists; 01050 datap = sw->eval ? tmpdata : sw->data; 01051 if (!aswf) 01052 res = 0; 01053 else { 01054 if (chan) 01055 ast_autoservice_start(chan); 01056 res = aswf(chan, context, exten, priority, callerid, datap); 01057 if (chan) 01058 ast_autoservice_stop(chan); 01059 } 01060 if (res) { /* Got a match */ 01061 q->swo = asw; 01062 q->data = datap; 01063 q->foundcontext = context; 01064 /* XXX keep status = STATUS_NO_CONTEXT ? */ 01065 return NULL; 01066 } 01067 } 01068 q->incstack[q->stacklen++] = tmp->name; /* Setup the stack */ 01069 /* Now try any includes we have in this context */ 01070 for (i = tmp->includes; i; i = i->next) { 01071 if (include_valid(i)) { 01072 if ((e = pbx_find_extension(chan, bypass, q, i->rname, exten, priority, label, callerid, action))) 01073 return e; 01074 if (q->swo) 01075 return NULL; 01076 } 01077 } 01078 return NULL; 01079 }
struct ast_app* pbx_findapp | ( | const char * | app | ) |
Look up an application.
app | name of the app |
Definition at line 555 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(), page_exec(), pbx_builtin_execiftime(), pbx_extension_helper(), realtime_exec(), try_calling(), and tryexec_exec().
00556 { 00557 struct ast_app *tmp; 00558 00559 AST_LIST_LOCK(&apps); 00560 AST_LIST_TRAVERSE(&apps, tmp, list) { 00561 if (!strcasecmp(tmp->name, app)) 00562 break; 00563 } 00564 AST_LIST_UNLOCK(&apps); 00565 00566 return tmp; 00567 }
static struct ast_switch* pbx_findswitch | ( | const char * | sw | ) | [static] |
Definition at line 569 of file pbx.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, and ast_switch::name.
00570 { 00571 struct ast_switch *asw; 00572 00573 AST_LIST_LOCK(&switches); 00574 AST_LIST_TRAVERSE(&switches, asw, list) { 00575 if (!strcasecmp(asw->name, sw)) 00576 break; 00577 } 00578 AST_LIST_UNLOCK(&switches); 00579 00580 return asw; 00581 }
void pbx_retrieve_variable | ( | struct ast_channel * | c, | |
const char * | var, | |||
char ** | ret, | |||
char * | workspace, | |||
int | workspacelen, | |||
struct varshead * | headp | |||
) |
Support for Asterisk built-in variables and functions in the dialplan.
Definition at line 1157 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(), function_fieldqty(), handle_getvariable(), and pbx_substitute_variables_helper_full().
01158 { 01159 const char not_found = '\0'; 01160 char *tmpvar; 01161 const char *s; /* the result */ 01162 int offset, length; 01163 int i, need_substring; 01164 struct varshead *places[2] = { headp, &globals }; /* list of places where we may look */ 01165 01166 if (c) { 01167 ast_channel_lock(c); 01168 places[0] = &c->varshead; 01169 } 01170 /* 01171 * Make a copy of var because parse_variable_name() modifies the string. 01172 * Then if called directly, we might need to run substring() on the result; 01173 * remember this for later in 'need_substring', 'offset' and 'length' 01174 */ 01175 tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */ 01176 need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */); 01177 01178 /* 01179 * Look first into predefined variables, then into variable lists. 01180 * Variable 's' points to the result, according to the following rules: 01181 * s == ¬_found (set at the beginning) means that we did not find a 01182 * matching variable and need to look into more places. 01183 * If s != ¬_found, s is a valid result string as follows: 01184 * s = NULL if the variable does not have a value; 01185 * you typically do this when looking for an unset predefined variable. 01186 * s = workspace if the result has been assembled there; 01187 * typically done when the result is built e.g. with an snprintf(), 01188 * so we don't need to do an additional copy. 01189 * s != workspace in case we have a string, that needs to be copied 01190 * (the ast_copy_string is done once for all at the end). 01191 * Typically done when the result is already available in some string. 01192 */ 01193 s = ¬_found; /* default value */ 01194 if (c) { /* This group requires a valid channel */ 01195 /* Names with common parts are looked up a piece at a time using strncmp. */ 01196 if (!strncmp(var, "CALL", 4)) { 01197 if (!strncmp(var + 4, "ING", 3)) { 01198 if (!strcmp(var + 7, "PRES")) { /* CALLINGPRES */ 01199 snprintf(workspace, workspacelen, "%d", c->cid.cid_pres); 01200 s = workspace; 01201 } else if (!strcmp(var + 7, "ANI2")) { /* CALLINGANI2 */ 01202 snprintf(workspace, workspacelen, "%d", c->cid.cid_ani2); 01203 s = workspace; 01204 } else if (!strcmp(var + 7, "TON")) { /* CALLINGTON */ 01205 snprintf(workspace, workspacelen, "%d", c->cid.cid_ton); 01206 s = workspace; 01207 } else if (!strcmp(var + 7, "TNS")) { /* CALLINGTNS */ 01208 snprintf(workspace, workspacelen, "%d", c->cid.cid_tns); 01209 s = workspace; 01210 } 01211 } 01212 } else if (!strcmp(var, "HINT")) { 01213 s = ast_get_hint(workspace, workspacelen, NULL, 0, c, c->context, c->exten) ? workspace : NULL; 01214 } else if (!strcmp(var, "HINTNAME")) { 01215 s = ast_get_hint(NULL, 0, workspace, workspacelen, c, c->context, c->exten) ? workspace : NULL; 01216 } else if (!strcmp(var, "EXTEN")) { 01217 s = c->exten; 01218 } else if (!strcmp(var, "CONTEXT")) { 01219 s = c->context; 01220 } else if (!strcmp(var, "PRIORITY")) { 01221 snprintf(workspace, workspacelen, "%d", c->priority); 01222 s = workspace; 01223 } else if (!strcmp(var, "CHANNEL")) { 01224 s = c->name; 01225 } else if (!strcmp(var, "UNIQUEID")) { 01226 s = c->uniqueid; 01227 } else if (!strcmp(var, "HANGUPCAUSE")) { 01228 snprintf(workspace, workspacelen, "%d", c->hangupcause); 01229 s = workspace; 01230 } 01231 } 01232 if (s == ¬_found) { /* look for more */ 01233 if (!strcmp(var, "EPOCH")) { 01234 snprintf(workspace, workspacelen, "%u",(int)time(NULL)); 01235 s = workspace; 01236 } else if (!strcmp(var, "SYSTEMNAME")) { 01237 s = ast_config_AST_SYSTEM_NAME; 01238 } 01239 } 01240 /* if not found, look into chanvars or global vars */ 01241 for (i = 0; s == ¬_found && i < (sizeof(places) / sizeof(places[0])); i++) { 01242 struct ast_var_t *variables; 01243 if (!places[i]) 01244 continue; 01245 if (places[i] == &globals) 01246 ast_mutex_lock(&globalslock); 01247 AST_LIST_TRAVERSE(places[i], variables, entries) { 01248 if (strcasecmp(ast_var_name(variables), var)==0) { 01249 s = ast_var_value(variables); 01250 break; 01251 } 01252 } 01253 if (places[i] == &globals) 01254 ast_mutex_unlock(&globalslock); 01255 } 01256 if (s == ¬_found || s == NULL) 01257 *ret = NULL; 01258 else { 01259 if (s != workspace) 01260 ast_copy_string(workspace, s, workspacelen); 01261 *ret = workspace; 01262 if (need_substring) 01263 *ret = substring(*ret, offset, length, workspace, workspacelen); 01264 } 01265 01266 if (c) 01267 ast_channel_unlock(c); 01268 }
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 2692 of file pbx.c.
References autofallthrough.
Referenced by pbx_load_module().
02693 { 02694 int oldval = autofallthrough; 02695 autofallthrough = newval; 02696 return oldval; 02697 }
static void pbx_substitute_variables | ( | char * | passdata, | |
int | datalen, | |||
struct ast_channel * | c, | |||
struct ast_exten * | e | |||
) | [static] |
Definition at line 1783 of file pbx.c.
References ast_exten::data, and pbx_substitute_variables_helper().
Referenced by pbx_extension_helper().
01784 { 01785 memset(passdata, 0, datalen); 01786 01787 /* No variables or expressions in e->data, so why scan it? */ 01788 if (e->data && !strchr(e->data, '$') && !strstr(e->data,"${") && !strstr(e->data,"$[") && !strstr(e->data,"$(")) { 01789 ast_copy_string(passdata, e->data, datalen); 01790 return; 01791 } 01792 01793 pbx_substitute_variables_helper(c, e->data, passdata, datalen - 1); 01794 }
void pbx_substitute_variables_helper | ( | struct ast_channel * | c, | |
const char * | cp1, | |||
char * | cp2, | |||
int | count | |||
) |
Definition at line 1773 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(), 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().
01774 { 01775 pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count); 01776 }
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 1579 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().
01580 { 01581 /* Substitutes variables into cp2, based on string cp1, and assuming cp2 to be 01582 zero-filled */ 01583 char *cp4; 01584 const char *tmp, *whereweare; 01585 int length, offset, offset2, isfunction; 01586 char *workspace = NULL; 01587 char *ltmp = NULL, *var = NULL; 01588 char *nextvar, *nextexp, *nextthing; 01589 char *vars, *vare; 01590 int pos, brackets, needsub, len; 01591 01592 whereweare=tmp=cp1; 01593 while (!ast_strlen_zero(whereweare) && count) { 01594 /* Assume we're copying the whole remaining string */ 01595 pos = strlen(whereweare); 01596 nextvar = NULL; 01597 nextexp = NULL; 01598 nextthing = strchr(whereweare, '$'); 01599 if (nextthing) { 01600 switch(nextthing[1]) { 01601 case '{': 01602 nextvar = nextthing; 01603 pos = nextvar - whereweare; 01604 break; 01605 case '[': 01606 nextexp = nextthing; 01607 pos = nextexp - whereweare; 01608 break; 01609 default: 01610 pos = 1; 01611 } 01612 } 01613 01614 if (pos) { 01615 /* Can't copy more than 'count' bytes */ 01616 if (pos > count) 01617 pos = count; 01618 01619 /* Copy that many bytes */ 01620 memcpy(cp2, whereweare, pos); 01621 01622 count -= pos; 01623 cp2 += pos; 01624 whereweare += pos; 01625 } 01626 01627 if (nextvar) { 01628 /* We have a variable. Find the start and end, and determine 01629 if we are going to have to recursively call ourselves on the 01630 contents */ 01631 vars = vare = nextvar + 2; 01632 brackets = 1; 01633 needsub = 0; 01634 01635 /* Find the end of it */ 01636 while (brackets && *vare) { 01637 if ((vare[0] == '$') && (vare[1] == '{')) { 01638 needsub++; 01639 } else if (vare[0] == '{') { 01640 brackets++; 01641 } else if (vare[0] == '}') { 01642 brackets--; 01643 } else if ((vare[0] == '$') && (vare[1] == '[')) 01644 needsub++; 01645 vare++; 01646 } 01647 if (brackets) 01648 ast_log(LOG_NOTICE, "Error in extension logic (missing '}')\n"); 01649 len = vare - vars - 1; 01650 01651 /* Skip totally over variable string */ 01652 whereweare += (len + 3); 01653 01654 if (!var) 01655 var = alloca(VAR_BUF_SIZE); 01656 01657 /* Store variable name (and truncate) */ 01658 ast_copy_string(var, vars, len + 1); 01659 01660 /* Substitute if necessary */ 01661 if (needsub) { 01662 if (!ltmp) 01663 ltmp = alloca(VAR_BUF_SIZE); 01664 01665 memset(ltmp, 0, VAR_BUF_SIZE); 01666 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1); 01667 vars = ltmp; 01668 } else { 01669 vars = var; 01670 } 01671 01672 if (!workspace) 01673 workspace = alloca(VAR_BUF_SIZE); 01674 01675 workspace[0] = '\0'; 01676 01677 parse_variable_name(vars, &offset, &offset2, &isfunction); 01678 if (isfunction) { 01679 /* Evaluate function */ 01680 if (c || !headp) 01681 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 01682 else { 01683 struct varshead old; 01684 struct ast_channel *c = ast_channel_alloc(0, 0, "", "", "", "", "", 0, "Bogus/%p", vars); 01685 if (c) { 01686 memcpy(&old, &c->varshead, sizeof(old)); 01687 memcpy(&c->varshead, headp, sizeof(c->varshead)); 01688 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 01689 /* Don't deallocate the varshead that was passed in */ 01690 memcpy(&c->varshead, &old, sizeof(c->varshead)); 01691 ast_channel_free(c); 01692 } else 01693 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n"); 01694 } 01695 01696 if (option_debug) 01697 ast_log(LOG_DEBUG, "Function result is '%s'\n", cp4 ? cp4 : "(null)"); 01698 } else { 01699 /* Retrieve variable value */ 01700 pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp); 01701 } 01702 if (cp4) { 01703 cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE); 01704 01705 length = strlen(cp4); 01706 if (length > count) 01707 length = count; 01708 memcpy(cp2, cp4, length); 01709 count -= length; 01710 cp2 += length; 01711 } 01712 } else if (nextexp) { 01713 /* We have an expression. Find the start and end, and determine 01714 if we are going to have to recursively call ourselves on the 01715 contents */ 01716 vars = vare = nextexp + 2; 01717 brackets = 1; 01718 needsub = 0; 01719 01720 /* Find the end of it */ 01721 while(brackets && *vare) { 01722 if ((vare[0] == '$') && (vare[1] == '[')) { 01723 needsub++; 01724 brackets++; 01725 vare++; 01726 } else if (vare[0] == '[') { 01727 brackets++; 01728 } else if (vare[0] == ']') { 01729 brackets--; 01730 } else if ((vare[0] == '$') && (vare[1] == '{')) { 01731 needsub++; 01732 vare++; 01733 } 01734 vare++; 01735 } 01736 if (brackets) 01737 ast_log(LOG_NOTICE, "Error in extension logic (missing ']')\n"); 01738 len = vare - vars - 1; 01739 01740 /* Skip totally over expression */ 01741 whereweare += (len + 3); 01742 01743 if (!var) 01744 var = alloca(VAR_BUF_SIZE); 01745 01746 /* Store variable name (and truncate) */ 01747 ast_copy_string(var, vars, len + 1); 01748 01749 /* Substitute if necessary */ 01750 if (needsub) { 01751 if (!ltmp) 01752 ltmp = alloca(VAR_BUF_SIZE); 01753 01754 memset(ltmp, 0, VAR_BUF_SIZE); 01755 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1); 01756 vars = ltmp; 01757 } else { 01758 vars = var; 01759 } 01760 01761 length = ast_expr(vars, cp2, count); 01762 01763 if (length) { 01764 if (option_debug) 01765 ast_log(LOG_DEBUG, "Expression result is '%s'\n", cp2); 01766 count -= length; 01767 cp2 += length; 01768 } 01769 } 01770 } 01771 }
void pbx_substitute_variables_varshead | ( | struct varshead * | headp, | |
const char * | cp1, | |||
char * | cp2, | |||
int | count | |||
) |
Definition at line 1778 of file pbx.c.
References pbx_substitute_variables_helper_full().
Referenced by ast_add_extension2(), dundi_lookup_local(), and loopback_helper().
01779 { 01780 pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count); 01781 }
static void* pbx_thread | ( | void * | data | ) | [static] |
Definition at line 2628 of file pbx.c.
References __ast_pbx_run(), and decrease_call_count().
Referenced by ast_pbx_start().
02629 { 02630 /* Oh joyeous kernel, we're a new thread, with nothing to do but 02631 answer this channel and get it going. 02632 */ 02633 /* NOTE: 02634 The launcher of this function _MUST_ increment 'countcalls' 02635 before invoking the function; it will be decremented when the 02636 PBX has finished running on the channel 02637 */ 02638 struct ast_channel *c = data; 02639 02640 __ast_pbx_run(c); 02641 decrease_call_count(); 02642 02643 pthread_exit(NULL); 02644 02645 return NULL; 02646 }
static void print_ext | ( | struct ast_exten * | e, | |
char * | buf, | |||
int | buflen | |||
) | [static] |
helper function to print an extension
Definition at line 3511 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().
03512 { 03513 int prio = ast_get_extension_priority(e); 03514 if (prio == PRIORITY_HINT) { 03515 snprintf(buf, buflen, "hint: %s", 03516 ast_get_extension_app(e)); 03517 } else { 03518 snprintf(buf, buflen, "%d. %s(%s)", 03519 prio, ast_get_extension_app(e), 03520 (!ast_strlen_zero(ast_get_extension_app_data(e)) ? (char *)ast_get_extension_app_data(e) : "")); 03521 } 03522 }
static void set_ext_pri | ( | struct ast_channel * | c, | |
const char * | exten, | |||
int | pri | |||
) | [static] |
Definition at line 2327 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(), and pbx_builtin_waitexten().
02328 { 02329 ast_channel_lock(c); 02330 ast_copy_string(c->exten, exten, sizeof(c->exten)); 02331 c->priority = pri; 02332 ast_channel_unlock(c); 02333 }
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 3525 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().
03526 { 03527 struct ast_context *c = NULL; 03528 int res = 0, old_total_exten = dpc->total_exten; 03529 03530 ast_rdlock_contexts(); 03531 03532 /* walk all contexts ... */ 03533 while ( (c = ast_walk_contexts(c)) ) { 03534 struct ast_exten *e; 03535 struct ast_include *i; 03536 struct ast_ignorepat *ip; 03537 char buf[256], buf2[256]; 03538 int context_info_printed = 0; 03539 03540 if (context && strcmp(ast_get_context_name(c), context)) 03541 continue; /* skip this one, name doesn't match */ 03542 03543 dpc->context_existence = 1; 03544 03545 ast_lock_context(c); 03546 03547 /* are we looking for exten too? if yes, we print context 03548 * only if we find our extension. 03549 * Otherwise print context even if empty ? 03550 * XXX i am not sure how the rinclude is handled. 03551 * I think it ought to go inside. 03552 */ 03553 if (!exten) { 03554 dpc->total_context++; 03555 ast_cli(fd, "[ Context '%s' created by '%s' ]\n", 03556 ast_get_context_name(c), ast_get_context_registrar(c)); 03557 context_info_printed = 1; 03558 } 03559 03560 /* walk extensions ... */ 03561 e = NULL; 03562 while ( (e = ast_walk_context_extensions(c, e)) ) { 03563 struct ast_exten *p; 03564 03565 if (exten && !ast_extension_match(ast_get_extension_name(e), exten)) 03566 continue; /* skip, extension match failed */ 03567 03568 dpc->extension_existence = 1; 03569 03570 /* may we print context info? */ 03571 if (!context_info_printed) { 03572 dpc->total_context++; 03573 if (rinclude) { /* TODO Print more info about rinclude */ 03574 ast_cli(fd, "[ Included context '%s' created by '%s' ]\n", 03575 ast_get_context_name(c), ast_get_context_registrar(c)); 03576 } else { 03577 ast_cli(fd, "[ Context '%s' created by '%s' ]\n", 03578 ast_get_context_name(c), ast_get_context_registrar(c)); 03579 } 03580 context_info_printed = 1; 03581 } 03582 dpc->total_prio++; 03583 03584 /* write extension name and first peer */ 03585 snprintf(buf, sizeof(buf), "'%s' =>", ast_get_extension_name(e)); 03586 03587 print_ext(e, buf2, sizeof(buf2)); 03588 03589 ast_cli(fd, " %-17s %-45s [%s]\n", buf, buf2, 03590 ast_get_extension_registrar(e)); 03591 03592 dpc->total_exten++; 03593 /* walk next extension peers */ 03594 p = e; /* skip the first one, we already got it */ 03595 while ( (p = ast_walk_extension_priorities(e, p)) ) { 03596 const char *el = ast_get_extension_label(p); 03597 dpc->total_prio++; 03598 if (el) 03599 snprintf(buf, sizeof(buf), " [%s]", el); 03600 else 03601 buf[0] = '\0'; 03602 print_ext(p, buf2, sizeof(buf2)); 03603 03604 ast_cli(fd," %-17s %-45s [%s]\n", buf, buf2, 03605 ast_get_extension_registrar(p)); 03606 } 03607 } 03608 03609 /* walk included and write info ... */ 03610 i = NULL; 03611 while ( (i = ast_walk_context_includes(c, i)) ) { 03612 snprintf(buf, sizeof(buf), "'%s'", ast_get_include_name(i)); 03613 if (exten) { 03614 /* Check all includes for the requested extension */ 03615 if (includecount >= AST_PBX_MAX_STACK) { 03616 ast_log(LOG_NOTICE, "Maximum include depth exceeded!\n"); 03617 } else { 03618 int dupe=0; 03619 int x; 03620 for (x=0;x<includecount;x++) { 03621 if (!strcasecmp(includes[x], ast_get_include_name(i))) { 03622 dupe++; 03623 break; 03624 } 03625 } 03626 if (!dupe) { 03627 includes[includecount] = ast_get_include_name(i); 03628 show_dialplan_helper(fd, ast_get_include_name(i), exten, dpc, i, includecount + 1, includes); 03629 } else { 03630 ast_log(LOG_WARNING, "Avoiding circular include of %s within %s\n", ast_get_include_name(i), context); 03631 } 03632 } 03633 } else { 03634 ast_cli(fd, " Include => %-45s [%s]\n", 03635 buf, ast_get_include_registrar(i)); 03636 } 03637 } 03638 03639 /* walk ignore patterns and write info ... */ 03640 ip = NULL; 03641 while ( (ip = ast_walk_context_ignorepats(c, ip)) ) { 03642 const char *ipname = ast_get_ignorepat_name(ip); 03643 char ignorepat[AST_MAX_EXTENSION]; 03644 snprintf(buf, sizeof(buf), "'%s'", ipname); 03645 snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname); 03646 if (!exten || ast_extension_match(ignorepat, exten)) { 03647 ast_cli(fd, " Ignore pattern => %-45s [%s]\n", 03648 buf, ast_get_ignorepat_registrar(ip)); 03649 } 03650 } 03651 if (!rinclude) { 03652 struct ast_sw *sw = NULL; 03653 while ( (sw = ast_walk_context_switches(c, sw)) ) { 03654 snprintf(buf, sizeof(buf), "'%s/%s'", 03655 ast_get_switch_name(sw), 03656 ast_get_switch_data(sw)); 03657 ast_cli(fd, " Alt. Switch => %-45s [%s]\n", 03658 buf, ast_get_switch_registrar(sw)); 03659 } 03660 } 03661 03662 ast_unlock_context(c); 03663 03664 /* if we print something in context, make an empty line */ 03665 if (context_info_printed) 03666 ast_cli(fd, "\r\n"); 03667 } 03668 ast_unlock_contexts(); 03669 03670 return (dpc->total_exten == old_total_exten) ? -1 : res; 03671 }
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 1115 of file pbx.c.
Referenced by pbx_retrieve_variable(), and pbx_substitute_variables_helper_full().
01116 { 01117 char *ret = workspace; 01118 int lr; /* length of the input string after the copy */ 01119 01120 ast_copy_string(workspace, value, workspace_len); /* always make a copy */ 01121 01122 lr = strlen(ret); /* compute length after copy, so we never go out of the workspace */ 01123 01124 /* Quick check if no need to do anything */ 01125 if (offset == 0 && length >= lr) /* take the whole string */ 01126 return ret; 01127 01128 if (offset < 0) { /* translate negative offset into positive ones */ 01129 offset = lr + offset; 01130 if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */ 01131 offset = 0; 01132 } 01133 01134 /* too large offset result in empty string so we know what to return */ 01135 if (offset >= lr) 01136 return ret + lr; /* the final '\0' */ 01137 01138 ret += offset; /* move to the start position */ 01139 if (length >= 0 && length < lr - offset) /* truncate if necessary */ 01140 ret[length] = '\0'; 01141 else if (length < 0) { 01142 if (lr > offset - length) /* After we remove from the front and from the rear, is there anything left? */ 01143 ret[lr + length - offset] = '\0'; 01144 else 01145 ret[0] = '\0'; 01146 } 01147 01148 return ret; 01149 }
static void wait_for_hangup | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 5372 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().
05373 { 05374 int res; 05375 struct ast_frame *f; 05376 int waittime; 05377 05378 if (ast_strlen_zero(data) || (sscanf(data, "%d", &waittime) != 1) || (waittime < 0)) 05379 waittime = -1; 05380 if (waittime > -1) { 05381 ast_safe_sleep(chan, waittime * 1000); 05382 } else do { 05383 res = ast_waitfor(chan, -1); 05384 if (res < 0) 05385 return; 05386 f = ast_read(chan); 05387 if (f) 05388 ast_frfree(f); 05389 } while(f); 05390 }
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 497 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 250 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 512 of file pbx.c.
Referenced by ast_extension_state_add(), ast_extension_state_del(), and ast_hint_state_changed().