#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 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 (conlock) | |
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_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 | |
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). | |
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) |
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 546 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 77 of file pbx.c.
Referenced by pbx_extension_helper(), and realtime_exec().
#define STATUS_NO_CONTEXT 1 |
Definition at line 904 of file pbx.c.
Referenced by pbx_extension_helper(), and pbx_find_extension().
#define STATUS_NO_EXTENSION 2 |
Definition at line 905 of file pbx.c.
Referenced by pbx_extension_helper(), and pbx_find_extension().
#define STATUS_NO_LABEL 4 |
Definition at line 907 of file pbx.c.
Referenced by pbx_extension_helper(), and pbx_find_extension().
#define STATUS_NO_PRIORITY 3 |
Definition at line 906 of file pbx.c.
Referenced by pbx_extension_helper(), and pbx_find_extension().
#define STATUS_SUCCESS 5 |
#define SWITCH_DATA_LENGTH 256 |
#define VAR_BUF_SIZE 4096 |
Definition at line 82 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 751 of file pbx.c.
00751 { 00752 E_MATCHMORE = 0x00, /* extension can match but only with more 'digits' */ 00753 E_CANMATCH = 0x01, /* extension can match with or without more 'digits' */ 00754 E_MATCH = 0x02, /* extension is an exact match */ 00755 E_MATCH_MASK = 0x03, /* mask for the argument to extension_match_core() */ 00756 E_SPAWN = 0x12, /* want to spawn an extension. Requires exact match */ 00757 E_FINDLABEL = 0x22 /* returns the priority for a given label. Requires exact match */ 00758 };
static struct ast_context* __ast_context_create | ( | struct ast_context ** | extcontexts, | |
const char * | name, | |||
const char * | registrar, | |||
int | existsokay | |||
) | [static] |
Definition at line 3844 of file pbx.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), contexts, local_contexts, LOG_WARNING, name, and ast_context::next.
Referenced by ast_context_create(), and ast_context_find_or_create().
03845 { 03846 struct ast_context *tmp, **local_contexts; 03847 int length = sizeof(struct ast_context) + strlen(name) + 1; 03848 03849 if (!extcontexts) { 03850 ast_mutex_lock(&conlock); 03851 local_contexts = &contexts; 03852 } else 03853 local_contexts = extcontexts; 03854 03855 for (tmp = *local_contexts; tmp; tmp = tmp->next) { 03856 if (!strcasecmp(tmp->name, name)) { 03857 if (!existsokay) { 03858 ast_log(LOG_WARNING, "Tried to register context '%s', already in use\n", name); 03859 tmp = NULL; 03860 } 03861 if (!extcontexts) 03862 ast_mutex_unlock(&conlock); 03863 return tmp; 03864 } 03865 } 03866 if ((tmp = ast_calloc(1, length))) { 03867 ast_mutex_init(&tmp->lock); 03868 ast_mutex_init(&tmp->macrolock); 03869 strcpy(tmp->name, name); 03870 tmp->root = NULL; 03871 tmp->registrar = registrar; 03872 tmp->next = *local_contexts; 03873 tmp->includes = NULL; 03874 tmp->ignorepats = NULL; 03875 *local_contexts = tmp; 03876 if (option_debug) 03877 ast_log(LOG_DEBUG, "Registered context '%s'\n", tmp->name); 03878 if (option_verbose > 2) 03879 ast_verbose( VERBOSE_PREFIX_3 "Registered extension context '%s'\n", tmp->name); 03880 } 03881 03882 if (!extcontexts) 03883 ast_mutex_unlock(&conlock); 03884 return tmp; 03885 }
void __ast_context_destroy | ( | struct ast_context * | con, | |
const char * | registrar | |||
) |
Definition at line 5277 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().
05278 { 05279 struct ast_context *tmp, *tmpl=NULL; 05280 struct ast_include *tmpi; 05281 struct ast_sw *sw; 05282 struct ast_exten *e, *el, *en; 05283 struct ast_ignorepat *ipi; 05284 05285 ast_mutex_lock(&conlock); 05286 for (tmp = contexts; tmp; ) { 05287 struct ast_context *next; /* next starting point */ 05288 for (; tmp; tmpl = tmp, tmp = tmp->next) { 05289 if (option_debug) 05290 ast_log(LOG_DEBUG, "check ctx %s %s\n", tmp->name, tmp->registrar); 05291 if ( (!registrar || !strcasecmp(registrar, tmp->registrar)) && 05292 (!con || !strcasecmp(tmp->name, con->name)) ) 05293 break; /* found it */ 05294 } 05295 if (!tmp) /* not found, we are done */ 05296 break; 05297 ast_mutex_lock(&tmp->lock); 05298 if (option_debug) 05299 ast_log(LOG_DEBUG, "delete ctx %s %s\n", tmp->name, tmp->registrar); 05300 next = tmp->next; 05301 if (tmpl) 05302 tmpl->next = next; 05303 else 05304 contexts = next; 05305 /* Okay, now we're safe to let it go -- in a sense, we were 05306 ready to let it go as soon as we locked it. */ 05307 ast_mutex_unlock(&tmp->lock); 05308 for (tmpi = tmp->includes; tmpi; ) { /* Free includes */ 05309 struct ast_include *tmpil = tmpi; 05310 tmpi = tmpi->next; 05311 free(tmpil); 05312 } 05313 for (ipi = tmp->ignorepats; ipi; ) { /* Free ignorepats */ 05314 struct ast_ignorepat *ipl = ipi; 05315 ipi = ipi->next; 05316 free(ipl); 05317 } 05318 while ((sw = AST_LIST_REMOVE_HEAD(&tmp->alts, list))) 05319 free(sw); 05320 for (e = tmp->root; e;) { 05321 for (en = e->peer; en;) { 05322 el = en; 05323 en = en->peer; 05324 destroy_exten(el); 05325 } 05326 el = e; 05327 e = e->next; 05328 destroy_exten(el); 05329 } 05330 ast_mutex_destroy(&tmp->lock); 05331 free(tmp); 05332 /* if we have a specific match, we are done, otherwise continue */ 05333 tmp = con ? NULL : next; 05334 } 05335 ast_mutex_unlock(&conlock); 05336 }
static int __ast_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority, | |||
int | async | |||
) | [static] |
Definition at line 6269 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().
06270 { 06271 int (*goto_func)(struct ast_channel *chan, const char *context, const char *exten, int priority); 06272 06273 if (!chan) 06274 return -2; 06275 06276 if (context == NULL) 06277 context = chan->context; 06278 if (exten == NULL) 06279 exten = chan->exten; 06280 06281 goto_func = (async) ? ast_async_goto : ast_explicit_goto; 06282 if (ast_exists_extension(chan, context, exten, priority, chan->cid.cid_num)) 06283 return goto_func(chan, context, exten, priority); 06284 else 06285 return -3; 06286 }
static int __ast_pbx_run | ( | struct ast_channel * | c | ) | [static] |
Definition at line 2334 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().
02335 { 02336 int found = 0; /* set if we find at least one match */ 02337 int res = 0; 02338 int autoloopflag; 02339 int error = 0; /* set an error conditions */ 02340 02341 /* A little initial setup here */ 02342 if (c->pbx) { 02343 ast_log(LOG_WARNING, "%s already has PBX structure??\n", c->name); 02344 /* XXX and now what ? */ 02345 free(c->pbx); 02346 } 02347 if (!(c->pbx = ast_calloc(1, sizeof(*c->pbx)))) 02348 return -1; 02349 if (c->amaflags) { 02350 if (!c->cdr) { 02351 c->cdr = ast_cdr_alloc(); 02352 if (!c->cdr) { 02353 ast_log(LOG_WARNING, "Unable to create Call Detail Record\n"); 02354 free(c->pbx); 02355 return -1; 02356 } 02357 ast_cdr_init(c->cdr, c); 02358 } 02359 } 02360 /* Set reasonable defaults */ 02361 c->pbx->rtimeout = 10; 02362 c->pbx->dtimeout = 5; 02363 02364 autoloopflag = ast_test_flag(c, AST_FLAG_IN_AUTOLOOP); /* save value to restore at the end */ 02365 ast_set_flag(c, AST_FLAG_IN_AUTOLOOP); 02366 02367 /* Start by trying whatever the channel is set to */ 02368 if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) { 02369 /* If not successful fall back to 's' */ 02370 if (option_verbose > 1) 02371 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); 02372 /* XXX the original code used the existing priority in the call to 02373 * ast_exists_extension(), and reset it to 1 afterwards. 02374 * I believe the correct thing is to set it to 1 immediately. 02375 */ 02376 set_ext_pri(c, "s", 1); 02377 if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) { 02378 /* JK02: And finally back to default if everything else failed */ 02379 if (option_verbose > 1) 02380 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); 02381 ast_copy_string(c->context, "default", sizeof(c->context)); 02382 } 02383 } 02384 if (c->cdr && ast_tvzero(c->cdr->start)) 02385 ast_cdr_start(c->cdr); 02386 for (;;) { 02387 char dst_exten[256]; /* buffer to accumulate digits */ 02388 int pos = 0; /* XXX should check bounds */ 02389 int digit = 0; 02390 02391 /* loop on priorities in this context/exten */ 02392 while (ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) { 02393 found = 1; 02394 if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num))) { 02395 /* Something bad happened, or a hangup has been requested. */ 02396 if (strchr("0123456789ABCDEF*#", res)) { 02397 if (option_debug) 02398 ast_log(LOG_DEBUG, "Oooh, got something to jump out with ('%c')!\n", res); 02399 pos = 0; 02400 dst_exten[pos++] = digit = res; 02401 dst_exten[pos] = '\0'; 02402 break; 02403 } 02404 if (res == AST_PBX_KEEPALIVE) { 02405 if (option_debug) 02406 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name); 02407 if (option_verbose > 1) 02408 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name); 02409 error = 1; 02410 break; 02411 } 02412 if (option_debug) 02413 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 02414 if (option_verbose > 1) 02415 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 02416 if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) { 02417 c->_softhangup =0; 02418 } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) { 02419 /* atimeout, nothing bad */ 02420 } else { 02421 if (c->cdr) 02422 ast_cdr_update(c); 02423 error = 1; 02424 break; 02425 } 02426 } 02427 if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT && ast_exists_extension(c,c->context,"T",1,c->cid.cid_num)) { 02428 set_ext_pri(c, "T", 0); /* 0 will become 1 with the c->priority++; at the end */ 02429 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 02430 c->whentohangup = 0; 02431 c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT; 02432 } else if (c->_softhangup) { 02433 if (option_debug) 02434 ast_log(LOG_DEBUG, "Extension %s, priority %d returned normally even though call was hung up\n", 02435 c->exten, c->priority); 02436 error = 1; 02437 break; 02438 } 02439 c->priority++; 02440 } /* end while - from here on we can use 'break' to go out */ 02441 if (error) 02442 break; 02443 02444 /* XXX we get here on non-existing extension or a keypress or hangup ? */ 02445 02446 if (!ast_exists_extension(c, c->context, c->exten, 1, c->cid.cid_num)) { 02447 /* If there is no match at priority 1, it is not a valid extension anymore. 02448 * Try to continue at "i", 1 or exit if the latter does not exist. 02449 */ 02450 if (ast_exists_extension(c, c->context, "i", 1, c->cid.cid_num)) { 02451 if (option_verbose > 2) 02452 ast_verbose(VERBOSE_PREFIX_3 "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, c->name); 02453 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", c->exten); 02454 set_ext_pri(c, "i", 1); 02455 } else { 02456 ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n", 02457 c->name, c->exten, c->context); 02458 error = 1; /* we know what to do with it */ 02459 break; 02460 } 02461 } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) { 02462 /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */ 02463 c->_softhangup = 0; 02464 } else { /* keypress received, get more digits for a full extension */ 02465 int waittime = 0; 02466 if (digit) 02467 waittime = c->pbx->dtimeout; 02468 else if (!autofallthrough) 02469 waittime = c->pbx->rtimeout; 02470 if (!waittime) { 02471 const char *status = pbx_builtin_getvar_helper(c, "DIALSTATUS"); 02472 if (!status) 02473 status = "UNKNOWN"; 02474 if (option_verbose > 2) 02475 ast_verbose(VERBOSE_PREFIX_2 "Auto fallthrough, channel '%s' status is '%s'\n", c->name, status); 02476 if (!strcasecmp(status, "CONGESTION")) 02477 res = pbx_builtin_congestion(c, "10"); 02478 else if (!strcasecmp(status, "CHANUNAVAIL")) 02479 res = pbx_builtin_congestion(c, "10"); 02480 else if (!strcasecmp(status, "BUSY")) 02481 res = pbx_builtin_busy(c, "10"); 02482 error = 1; /* XXX disable message */ 02483 break; /* exit from the 'for' loop */ 02484 } 02485 02486 if (collect_digits(c, waittime, dst_exten, sizeof(dst_exten), pos)) 02487 break; 02488 if (ast_exists_extension(c, c->context, dst_exten, 1, c->cid.cid_num)) /* Prepare the next cycle */ 02489 set_ext_pri(c, dst_exten, 1); 02490 else { 02491 /* No such extension */ 02492 if (!ast_strlen_zero(dst_exten)) { 02493 /* An invalid extension */ 02494 if (ast_exists_extension(c, c->context, "i", 1, c->cid.cid_num)) { 02495 if (option_verbose > 2) 02496 ast_verbose( VERBOSE_PREFIX_3 "Invalid extension '%s' in context '%s' on %s\n", dst_exten, c->context, c->name); 02497 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", dst_exten); 02498 set_ext_pri(c, "i", 1); 02499 } else { 02500 ast_log(LOG_WARNING, "Invalid extension '%s', but no rule 'i' in context '%s'\n", dst_exten, c->context); 02501 found = 1; /* XXX disable message */ 02502 break; 02503 } 02504 } else { 02505 /* A simple timeout */ 02506 if (ast_exists_extension(c, c->context, "t", 1, c->cid.cid_num)) { 02507 if (option_verbose > 2) 02508 ast_verbose( VERBOSE_PREFIX_3 "Timeout on %s\n", c->name); 02509 set_ext_pri(c, "t", 1); 02510 } else { 02511 ast_log(LOG_WARNING, "Timeout, but no rule 't' in context '%s'\n", c->context); 02512 found = 1; /* XXX disable message */ 02513 break; 02514 } 02515 } 02516 } 02517 if (c->cdr) { 02518 if (option_verbose > 2) 02519 ast_verbose(VERBOSE_PREFIX_2 "CDR updated on %s\n",c->name); 02520 ast_cdr_update(c); 02521 } 02522 } 02523 } 02524 if (!found && !error) 02525 ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name); 02526 if ((res != AST_PBX_KEEPALIVE) && ast_exists_extension(c, c->context, "h", 1, c->cid.cid_num)) { 02527 if (c->cdr && ast_opt_end_cdr_before_h_exten) 02528 ast_cdr_end(c->cdr); 02529 set_ext_pri(c, "h", 1); 02530 while(ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) { 02531 if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num))) { 02532 /* Something bad happened, or a hangup has been requested. */ 02533 if (option_debug) 02534 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 02535 if (option_verbose > 1) 02536 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 02537 break; 02538 } 02539 c->priority++; 02540 } 02541 } 02542 ast_set2_flag(c, autoloopflag, AST_FLAG_IN_AUTOLOOP); 02543 02544 pbx_destroy(c->pbx); 02545 c->pbx = NULL; 02546 if (res != AST_PBX_KEEPALIVE) 02547 ast_hangup(c); 02548 return 0; 02549 }
static int _extension_match_core | ( | const char * | pattern, | |
const char * | data, | |||
enum ext_match_t | mode | |||
) | [static] |
Definition at line 769 of file pbx.c.
References ast_log(), E_MATCH, E_MATCH_MASK, E_MATCHMORE, and LOG_WARNING.
Referenced by extension_match_core().
00770 { 00771 mode &= E_MATCH_MASK; /* only consider the relevant bits */ 00772 00773 if ( (mode == E_MATCH) && (pattern[0] == '_') && (strcasecmp(pattern,data)==0) ) /* note: if this test is left out, then _x. will not match _x. !!! */ 00774 return 1; 00775 00776 if (pattern[0] != '_') { /* not a pattern, try exact or partial match */ 00777 int ld = strlen(data), lp = strlen(pattern); 00778 00779 if (lp < ld) /* pattern too short, cannot match */ 00780 return 0; 00781 /* depending on the mode, accept full or partial match or both */ 00782 if (mode == E_MATCH) 00783 return !strcmp(pattern, data); /* 1 on match, 0 on fail */ 00784 if (ld == 0 || !strncasecmp(pattern, data, ld)) /* partial or full match */ 00785 return (mode == E_MATCHMORE) ? lp > ld : 1; /* XXX should consider '!' and '/' ? */ 00786 else 00787 return 0; 00788 } 00789 pattern++; /* skip leading _ */ 00790 /* 00791 * XXX below we stop at '/' which is a separator for the CID info. However we should 00792 * not store '/' in the pattern at all. When we insure it, we can remove the checks. 00793 */ 00794 while (*data && *pattern && *pattern != '/') { 00795 const char *end; 00796 00797 if (*data == '-') { /* skip '-' in data (just a separator) */ 00798 data++; 00799 continue; 00800 } 00801 switch (toupper(*pattern)) { 00802 case '[': /* a range */ 00803 end = strchr(pattern+1, ']'); /* XXX should deal with escapes ? */ 00804 if (end == NULL) { 00805 ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n"); 00806 return 0; /* unconditional failure */ 00807 } 00808 for (pattern++; pattern != end; pattern++) { 00809 if (pattern+2 < end && pattern[1] == '-') { /* this is a range */ 00810 if (*data >= pattern[0] && *data <= pattern[2]) 00811 break; /* match found */ 00812 else { 00813 pattern += 2; /* skip a total of 3 chars */ 00814 continue; 00815 } 00816 } else if (*data == pattern[0]) 00817 break; /* match found */ 00818 } 00819 if (pattern == end) 00820 return 0; 00821 pattern = end; /* skip and continue */ 00822 break; 00823 case 'N': 00824 if (*data < '2' || *data > '9') 00825 return 0; 00826 break; 00827 case 'X': 00828 if (*data < '0' || *data > '9') 00829 return 0; 00830 break; 00831 case 'Z': 00832 if (*data < '1' || *data > '9') 00833 return 0; 00834 break; 00835 case '.': /* Must match, even with more digits */ 00836 return 1; 00837 case '!': /* Early match */ 00838 return 2; 00839 case ' ': 00840 case '-': /* Ignore these in patterns */ 00841 data--; /* compensate the final data++ */ 00842 break; 00843 default: 00844 if (*data != *pattern) 00845 return 0; 00846 } 00847 data++; 00848 pattern++; 00849 } 00850 if (*data) /* data longer than pattern, no match */ 00851 return 0; 00852 /* 00853 * match so far, but ran off the end of the data. 00854 * Depending on what is next, determine match or not. 00855 */ 00856 if (*pattern == '\0' || *pattern == '/') /* exact match */ 00857 return (mode == E_MATCHMORE) ? 0 : 1; /* this is a failure for E_MATCHMORE */ 00858 else if (*pattern == '!') /* early match */ 00859 return 2; 00860 else /* partial match */ 00861 return (mode == E_MATCH) ? 0 : 1; /* this is a failure for E_MATCH */ 00862 }
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 4654 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().
04656 { 04657 struct ast_exten *ep; 04658 04659 for (ep = NULL; e ; ep = e, e = e->peer) { 04660 if (e->priority >= tmp->priority) 04661 break; 04662 } 04663 if (!e) { /* go at the end, and ep is surely set because the list is not empty */ 04664 ep->peer = tmp; 04665 return 0; /* success */ 04666 } 04667 if (e->priority == tmp->priority) { 04668 /* Can't have something exactly the same. Is this a 04669 replacement? If so, replace, otherwise, bonk. */ 04670 if (!replace) { 04671 ast_log(LOG_WARNING, "Unable to register extension '%s', priority %d in '%s', already in use\n", tmp->exten, tmp->priority, con->name); 04672 if (tmp->datad) 04673 tmp->datad(tmp->data); 04674 free(tmp); 04675 return -1; 04676 } 04677 /* we are replacing e, so copy the link fields and then update 04678 * whoever pointed to e to point to us 04679 */ 04680 tmp->next = e->next; /* not meaningful if we are not first in the peer list */ 04681 tmp->peer = e->peer; /* always meaningful */ 04682 if (ep) /* We're in the peer list, just insert ourselves */ 04683 ep->peer = tmp; 04684 else if (el) /* We're the first extension. Take over e's functions */ 04685 el->next = tmp; 04686 else /* We're the very first extension. */ 04687 con->root = tmp; 04688 if (tmp->priority == PRIORITY_HINT) 04689 ast_change_hint(e,tmp); 04690 /* Destroy the old one */ 04691 if (e->datad) 04692 e->datad(e->data); 04693 free(e); 04694 } else { /* Slip ourselves in just before e */ 04695 tmp->peer = e; 04696 tmp->next = e->next; /* extension chain, or NULL if e is not the first extension */ 04697 if (ep) /* Easy enough, we're just in the peer list */ 04698 ep->peer = tmp; 04699 else { /* we are the first in some peer list, so link in the ext list */ 04700 if (el) 04701 el->next = tmp; /* in the middle... */ 04702 else 04703 con->root = tmp; /* ... or at the head */ 04704 e->next = NULL; /* e is no more at the head, so e->next must be reset */ 04705 } 04706 /* And immediately return success. */ 04707 if (tmp->priority == PRIORITY_HINT) 04708 ast_add_hint(tmp); 04709 } 04710 return 0; 04711 }
int ast_active_calls | ( | void | ) |
Retrieve the number of active calls.
Definition at line 2654 of file pbx.c.
References countcalls.
Referenced by handle_chanlist(), and handle_chanlist_deprecated().
02655 { 02656 return countcalls; 02657 }
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 4534 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().
04537 { 04538 int ret = -1; 04539 struct ast_context *c = find_context_locked(context); 04540 04541 if (c) { 04542 ret = ast_add_extension2(c, replace, extension, priority, label, callerid, 04543 application, data, datad, registrar); 04544 ast_unlock_contexts(); 04545 } 04546 return ret; 04547 }
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 4738 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, ext_cmp(), ext_strncpy(), ast_exten::exten, ast_exten::label, ast_context::lock, ast_exten::matchcid, ast_exten::next, option_verbose, ast_exten::parent, pbx_substitute_variables_varshead(), ast_exten::priority, PRIORITY_HINT, ast_exten::registrar, ast_context::root, ast_exten::stuff, VAR_BUF_SIZE, and VERBOSE_PREFIX_3.
Referenced by add_extensions(), ast_add_extension(), ast_park_call(), do_parking_thread(), pbx_load_config(), and pbx_load_users().
04742 { 04743 /* 04744 * Sort extensions (or patterns) according to the rules indicated above. 04745 * These are implemented by the function ext_cmp()). 04746 * All priorities for the same ext/pattern/cid are kept in a list, 04747 * using the 'peer' field as a link field.. 04748 */ 04749 struct ast_exten *tmp, *e, *el = NULL; 04750 int res; 04751 int length; 04752 char *p; 04753 char expand_buf[VAR_BUF_SIZE] = { 0, }; 04754 04755 /* if we are adding a hint, and there are global variables, and the hint 04756 contains variable references, then expand them 04757 */ 04758 ast_mutex_lock(&globalslock); 04759 if (priority == PRIORITY_HINT && AST_LIST_FIRST(&globals) && strstr(application, "${")) { 04760 pbx_substitute_variables_varshead(&globals, application, expand_buf, sizeof(expand_buf)); 04761 application = expand_buf; 04762 } 04763 ast_mutex_unlock(&globalslock); 04764 04765 length = sizeof(struct ast_exten); 04766 length += strlen(extension) + 1; 04767 length += strlen(application) + 1; 04768 if (label) 04769 length += strlen(label) + 1; 04770 if (callerid) 04771 length += strlen(callerid) + 1; 04772 else 04773 length ++; /* just the '\0' */ 04774 04775 /* Be optimistic: Build the extension structure first */ 04776 if (!(tmp = ast_calloc(1, length))) 04777 return -1; 04778 04779 /* use p as dst in assignments, as the fields are const char * */ 04780 p = tmp->stuff; 04781 if (label) { 04782 tmp->label = p; 04783 strcpy(p, label); 04784 p += strlen(label) + 1; 04785 } 04786 tmp->exten = p; 04787 p += ext_strncpy(p, extension, strlen(extension) + 1) + 1; 04788 tmp->priority = priority; 04789 tmp->cidmatch = p; /* but use p for assignments below */ 04790 if (callerid) { 04791 p += ext_strncpy(p, callerid, strlen(callerid) + 1) + 1; 04792 tmp->matchcid = 1; 04793 } else { 04794 *p++ = '\0'; 04795 tmp->matchcid = 0; 04796 } 04797 tmp->app = p; 04798 strcpy(p, application); 04799 tmp->parent = con; 04800 tmp->data = data; 04801 tmp->datad = datad; 04802 tmp->registrar = registrar; 04803 04804 ast_mutex_lock(&con->lock); 04805 res = 0; /* some compilers will think it is uninitialized otherwise */ 04806 for (e = con->root; e; el = e, e = e->next) { /* scan the extension list */ 04807 res = ext_cmp(e->exten, extension); 04808 if (res == 0) { /* extension match, now look at cidmatch */ 04809 if (!e->matchcid && !tmp->matchcid) 04810 res = 0; 04811 else if (tmp->matchcid && !e->matchcid) 04812 res = 1; 04813 else if (e->matchcid && !tmp->matchcid) 04814 res = -1; 04815 else 04816 res = strcasecmp(e->cidmatch, tmp->cidmatch); 04817 } 04818 if (res >= 0) 04819 break; 04820 } 04821 if (e && res == 0) { /* exact match, insert in the pri chain */ 04822 res = add_pri(con, tmp, el, e, replace); 04823 ast_mutex_unlock(&con->lock); 04824 if (res < 0) { 04825 errno = EEXIST; /* XXX do we care ? */ 04826 return 0; /* XXX should we return -1 maybe ? */ 04827 } 04828 } else { 04829 /* 04830 * not an exact match, this is the first entry with this pattern, 04831 * so insert in the main list right before 'e' (if any) 04832 */ 04833 tmp->next = e; 04834 if (el) 04835 el->next = tmp; 04836 else 04837 con->root = tmp; 04838 ast_mutex_unlock(&con->lock); 04839 if (tmp->priority == PRIORITY_HINT) 04840 ast_add_hint(tmp); 04841 } 04842 if (option_debug) { 04843 if (tmp->matchcid) { 04844 if (option_debug) 04845 ast_log(LOG_DEBUG, "Added extension '%s' priority %d (CID match '%s') to %s\n", 04846 tmp->exten, tmp->priority, tmp->cidmatch, con->name); 04847 } else { 04848 if (option_debug) 04849 ast_log(LOG_DEBUG, "Added extension '%s' priority %d to %s\n", 04850 tmp->exten, tmp->priority, con->name); 04851 } 04852 } 04853 if (option_verbose > 2) { 04854 if (tmp->matchcid) { 04855 ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d (CID match '%s')to %s\n", 04856 tmp->exten, tmp->priority, tmp->cidmatch, con->name); 04857 } else { 04858 ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d to %s\n", 04859 tmp->exten, tmp->priority, con->name); 04860 } 04861 } 04862 return 0; 04863 }
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 2158 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().
02159 { 02160 struct ast_hint *hint; 02161 02162 if (!e) 02163 return -1; 02164 02165 AST_LIST_LOCK(&hints); 02166 02167 /* Search if hint exists, do nothing */ 02168 AST_LIST_TRAVERSE(&hints, hint, list) { 02169 if (hint->exten == e) { 02170 AST_LIST_UNLOCK(&hints); 02171 if (option_debug > 1) 02172 ast_log(LOG_DEBUG, "HINTS: Not re-adding existing hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e)); 02173 return -1; 02174 } 02175 } 02176 02177 if (option_debug > 1) 02178 ast_log(LOG_DEBUG, "HINTS: Adding hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e)); 02179 02180 if (!(hint = ast_calloc(1, sizeof(*hint)))) { 02181 AST_LIST_UNLOCK(&hints); 02182 return -1; 02183 } 02184 /* Initialize and insert new item at the top */ 02185 hint->exten = e; 02186 hint->laststate = ast_extension_state2(e); 02187 AST_LIST_INSERT_HEAD(&hints, hint, list); 02188 02189 AST_LIST_UNLOCK(&hints); 02190 return 0; 02191 }
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 4568 of file pbx.c.
References ast_channel::_state, ast_channel::amaflags, 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().
04569 { 04570 int res = 0; 04571 04572 ast_channel_lock(chan); 04573 04574 if (chan->pbx) { /* This channel is currently in the PBX */ 04575 ast_explicit_goto(chan, context, exten, priority); 04576 ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO); 04577 } else { 04578 /* In order to do it when the channel doesn't really exist within 04579 the PBX, we have to make a new channel, masquerade, and start the PBX 04580 at the new location */ 04581 struct ast_channel *tmpchan = ast_channel_alloc(0, chan->_state, 0, 0, chan->accountcode, chan->exten, chan->context, chan->amaflags, "AsyncGoto/%s", chan->name); 04582 if (chan->cdr) { 04583 tmpchan->cdr = ast_cdr_dup(chan->cdr); 04584 } 04585 if (!tmpchan) 04586 res = -1; 04587 else { 04588 /* Make formats okay */ 04589 tmpchan->readformat = chan->readformat; 04590 tmpchan->writeformat = chan->writeformat; 04591 /* Setup proper location */ 04592 ast_explicit_goto(tmpchan, 04593 S_OR(context, chan->context), S_OR(exten, chan->exten), priority); 04594 04595 /* Masquerade into temp channel */ 04596 ast_channel_masquerade(tmpchan, chan); 04597 04598 /* Grab the locks and get going */ 04599 ast_channel_lock(tmpchan); 04600 ast_do_masquerade(tmpchan); 04601 ast_channel_unlock(tmpchan); 04602 /* Start the PBX going on our stolen channel */ 04603 if (ast_pbx_start(tmpchan)) { 04604 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name); 04605 ast_hangup(tmpchan); 04606 res = -1; 04607 } 04608 } 04609 } 04610 ast_channel_unlock(chan); 04611 return res; 04612 }
int ast_async_goto_by_name | ( | const char * | channame, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 4614 of file pbx.c.
References ast_async_goto(), ast_channel_unlock, and ast_get_channel_by_name_locked().
04615 { 04616 struct ast_channel *chan; 04617 int res = -1; 04618 04619 chan = ast_get_channel_by_name_locked(channame); 04620 if (chan) { 04621 res = ast_async_goto(chan, context, exten, priority); 04622 ast_channel_unlock(chan); 04623 } 04624 return res; 04625 }
int ast_async_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 6293 of file pbx.c.
References __ast_goto_if_exists().
Referenced by asyncgoto_exec().
06294 { 06295 return __ast_goto_if_exists(chan, context, exten, priority, 1); 06296 }
int ast_build_timing | ( | struct ast_timing * | i, | |
const char * | info_in | |||
) |
Definition at line 4210 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().
04211 { 04212 char info_save[256]; 04213 char *info; 04214 04215 /* Check for empty just in case */ 04216 if (ast_strlen_zero(info_in)) 04217 return 0; 04218 /* make a copy just in case we were passed a static string */ 04219 ast_copy_string(info_save, info_in, sizeof(info_save)); 04220 info = info_save; 04221 /* Assume everything except time */ 04222 i->monthmask = 0xfff; /* 12 bits */ 04223 i->daymask = 0x7fffffffU; /* 31 bits */ 04224 i->dowmask = 0x7f; /* 7 bits */ 04225 /* on each call, use strsep() to move info to the next argument */ 04226 get_timerange(i, strsep(&info, "|")); 04227 if (info) 04228 i->dowmask = get_range(strsep(&info, "|"), 7, days, "day of week"); 04229 if (info) 04230 i->daymask = get_range(strsep(&info, "|"), 31, NULL, "day"); 04231 if (info) 04232 i->monthmask = get_range(strsep(&info, "|"), 12, months, "month"); 04233 return 1; 04234 }
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 2282 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().
02283 { 02284 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH); 02285 }
ast_change_hint: Change hint for an extension
Definition at line 2194 of file pbx.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, and ast_hint::exten.
Referenced by add_pri().
02195 { 02196 struct ast_hint *hint; 02197 int res = -1; 02198 02199 AST_LIST_LOCK(&hints); 02200 AST_LIST_TRAVERSE(&hints, hint, list) { 02201 if (hint->exten == oe) { 02202 hint->exten = ne; 02203 res = 0; 02204 break; 02205 } 02206 } 02207 AST_LIST_UNLOCK(&hints); 02208 02209 return res; 02210 }
int ast_check_timing | ( | const struct ast_timing * | i | ) |
Definition at line 4236 of file pbx.c.
References 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().
04237 { 04238 struct tm tm; 04239 time_t t = time(NULL); 04240 04241 localtime_r(&t,&tm); 04242 04243 /* If it's not the right month, return */ 04244 if (!(i->monthmask & (1 << tm.tm_mon))) 04245 return 0; 04246 04247 /* If it's not that time of the month.... */ 04248 /* Warning, tm_mday has range 1..31! */ 04249 if (!(i->daymask & (1 << (tm.tm_mday-1)))) 04250 return 0; 04251 04252 /* If it's not the right day of the week */ 04253 if (!(i->dowmask & (1 << tm.tm_wday))) 04254 return 0; 04255 04256 /* Sanity check the hour just to be safe */ 04257 if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) { 04258 ast_log(LOG_WARNING, "Insane time...\n"); 04259 return 0; 04260 } 04261 04262 /* Now the tough part, we calculate if it fits 04263 in the right time based on min/hour */ 04264 if (!(i->minmask[tm.tm_hour] & (1 << (tm.tm_min / 2)))) 04265 return 0; 04266 04267 /* If we got this far, then we're good */ 04268 return 1; 04269 }
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 4470 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().
04471 { 04472 int ret = -1; 04473 struct ast_context *c = find_context_locked(context); 04474 04475 if (c) { 04476 ret = ast_context_add_ignorepat2(c, value, registrar); 04477 ast_unlock_contexts(); 04478 } 04479 return ret; 04480 }
int ast_context_add_ignorepat2 | ( | struct ast_context * | con, | |
const char * | value, | |||
const char * | registrar | |||
) |
Definition at line 4482 of file pbx.c.
References ast_calloc, ast_mutex_lock(), ast_mutex_unlock(), ast_context::ignorepats, ast_context::lock, ast_ignorepat::next, ast_ignorepat::pattern, and ast_ignorepat::registrar.
Referenced by ast_compile_ael2(), ast_context_add_ignorepat(), and pbx_load_config().
04483 { 04484 struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL; 04485 int length; 04486 length = sizeof(struct ast_ignorepat); 04487 length += strlen(value) + 1; 04488 if (!(ignorepat = ast_calloc(1, length))) 04489 return -1; 04490 /* The cast to char * is because we need to write the initial value. 04491 * The field is not supposed to be modified otherwise 04492 */ 04493 strcpy((char *)ignorepat->pattern, value); 04494 ignorepat->next = NULL; 04495 ignorepat->registrar = registrar; 04496 ast_mutex_lock(&con->lock); 04497 for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) { 04498 ignorepatl = ignorepatc; 04499 if (!strcasecmp(ignorepatc->pattern, value)) { 04500 /* Already there */ 04501 ast_mutex_unlock(&con->lock); 04502 errno = EEXIST; 04503 return -1; 04504 } 04505 } 04506 if (ignorepatl) 04507 ignorepatl->next = ignorepat; 04508 else 04509 con->ignorepats = ignorepat; 04510 ast_mutex_unlock(&con->lock); 04511 return 0; 04512 04513 }
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 4016 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().
04017 { 04018 int ret = -1; 04019 struct ast_context *c = find_context_locked(context); 04020 04021 if (c) { 04022 ret = ast_context_add_include2(c, include, registrar); 04023 ast_unlock_contexts(); 04024 } 04025 return ret; 04026 }
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 4278 of file pbx.c.
References ast_build_timing(), ast_calloc, ast_get_context_name(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), 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_compile_ael2(), ast_context_add_include(), and pbx_load_config().
04280 { 04281 struct ast_include *new_include; 04282 char *c; 04283 struct ast_include *i, *il = NULL; /* include, include_last */ 04284 int length; 04285 char *p; 04286 04287 length = sizeof(struct ast_include); 04288 length += 2 * (strlen(value) + 1); 04289 04290 /* allocate new include structure ... */ 04291 if (!(new_include = ast_calloc(1, length))) 04292 return -1; 04293 /* Fill in this structure. Use 'p' for assignments, as the fields 04294 * in the structure are 'const char *' 04295 */ 04296 p = new_include->stuff; 04297 new_include->name = p; 04298 strcpy(p, value); 04299 p += strlen(value) + 1; 04300 new_include->rname = p; 04301 strcpy(p, value); 04302 /* Strip off timing info, and process if it is there */ 04303 if ( (c = strchr(p, '|')) ) { 04304 *c++ = '\0'; 04305 new_include->hastime = ast_build_timing(&(new_include->timing), c); 04306 } 04307 new_include->next = NULL; 04308 new_include->registrar = registrar; 04309 04310 ast_mutex_lock(&con->lock); 04311 04312 /* ... go to last include and check if context is already included too... */ 04313 for (i = con->includes; i; i = i->next) { 04314 if (!strcasecmp(i->name, new_include->name)) { 04315 free(new_include); 04316 ast_mutex_unlock(&con->lock); 04317 errno = EEXIST; 04318 return -1; 04319 } 04320 il = i; 04321 } 04322 04323 /* ... include new context into context list, unlock, return */ 04324 if (il) 04325 il->next = new_include; 04326 else 04327 con->includes = new_include; 04328 if (option_verbose > 2) 04329 ast_verbose(VERBOSE_PREFIX_3 "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con)); 04330 ast_mutex_unlock(&con->lock); 04331 04332 return 0; 04333 }
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 4340 of file pbx.c.
References ast_context_add_switch2(), ast_unlock_contexts(), and find_context_locked().
04341 { 04342 int ret = -1; 04343 struct ast_context *c = find_context_locked(context); 04344 04345 if (c) { /* found, add switch to this context */ 04346 ret = ast_context_add_switch2(c, sw, data, eval, registrar); 04347 ast_unlock_contexts(); 04348 } 04349 return ret; 04350 }
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 4359 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, ast_sw::eval, free, ast_context::lock, ast_sw::name, option_verbose, ast_sw::registrar, SWITCH_DATA_LENGTH, and VERBOSE_PREFIX_3.
Referenced by ast_compile_ael2(), ast_context_add_switch(), and pbx_load_config().
04361 { 04362 struct ast_sw *new_sw; 04363 struct ast_sw *i; 04364 int length; 04365 char *p; 04366 04367 length = sizeof(struct ast_sw); 04368 length += strlen(value) + 1; 04369 if (data) 04370 length += strlen(data); 04371 length++; 04372 if (eval) { 04373 /* Create buffer for evaluation of variables */ 04374 length += SWITCH_DATA_LENGTH; 04375 length++; 04376 } 04377 04378 /* allocate new sw structure ... */ 04379 if (!(new_sw = ast_calloc(1, length))) 04380 return -1; 04381 /* ... fill in this structure ... */ 04382 p = new_sw->stuff; 04383 new_sw->name = p; 04384 strcpy(new_sw->name, value); 04385 p += strlen(value) + 1; 04386 new_sw->data = p; 04387 if (data) { 04388 strcpy(new_sw->data, data); 04389 p += strlen(data) + 1; 04390 } else { 04391 strcpy(new_sw->data, ""); 04392 p++; 04393 } 04394 if (eval) 04395 new_sw->tmpdata = p; 04396 new_sw->eval = eval; 04397 new_sw->registrar = registrar; 04398 04399 /* ... try to lock this context ... */ 04400 ast_mutex_lock(&con->lock); 04401 04402 /* ... go to last sw and check if context is already swd too... */ 04403 AST_LIST_TRAVERSE(&con->alts, i, list) { 04404 if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) { 04405 free(new_sw); 04406 ast_mutex_unlock(&con->lock); 04407 errno = EEXIST; 04408 return -1; 04409 } 04410 } 04411 04412 /* ... sw new context into context list, unlock, return */ 04413 AST_LIST_INSERT_TAIL(&con->alts, new_sw, list); 04414 04415 if (option_verbose > 2) 04416 ast_verbose(VERBOSE_PREFIX_3 "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con)); 04417 04418 ast_mutex_unlock(&con->lock); 04419 04420 return 0; 04421 }
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 3887 of file pbx.c.
References __ast_context_create().
Referenced by ast_compile_ael2(), ast_park_call(), do_parking_thread(), and set_config().
03888 { 03889 return __ast_context_create(extcontexts, name, registrar, 0); 03890 }
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 5338 of file pbx.c.
References __ast_context_destroy().
Referenced by cleanup_stale_contexts(), and unload_module().
05339 { 05340 __ast_context_destroy(con,registrar); 05341 }
struct ast_context* ast_context_find | ( | const char * | name | ) |
Find a context.
name | name of the context to find |
Definition at line 892 of file pbx.c.
References ast_mutex_lock(), ast_mutex_unlock(), and ast_walk_contexts().
Referenced by _macro_exec(), ast_context_verify_includes(), ast_ignore_pattern(), ast_park_call(), cleanup_stale_contexts(), do_parking_thread(), park_exec(), register_peer_exten(), and set_config().
00893 { 00894 struct ast_context *tmp = NULL; 00895 ast_mutex_lock(&conlock); 00896 while ( (tmp = ast_walk_contexts(tmp)) ) { 00897 if (!name || !strcasecmp(name, tmp->name)) 00898 break; 00899 } 00900 ast_mutex_unlock(&conlock); 00901 return tmp; 00902 }
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 3892 of file pbx.c.
References __ast_context_create().
Referenced by pbx_load_config(), and pbx_load_users().
03893 { 03894 return __ast_context_create(extcontexts, name, registrar, 1); 03895 }
int ast_context_lockmacro | ( | const char * | context | ) |
locks the macrolock in the given given context
Definition at line 2891 of file pbx.c.
References ast_get_context_name(), ast_lock_contexts(), ast_mutex_lock(), ast_unlock_contexts(), and ast_walk_contexts().
Referenced by _macro_exec().
02892 { 02893 struct ast_context *c = NULL; 02894 int ret = -1; 02895 02896 ast_lock_contexts(); 02897 02898 while ((c = ast_walk_contexts(c))) { 02899 if (!strcmp(ast_get_context_name(c), context)) { 02900 ret = 0; 02901 break; 02902 } 02903 } 02904 02905 ast_unlock_contexts(); 02906 02907 /* if we found context, lock macrolock */ 02908 if (ret == 0) 02909 ret = ast_mutex_lock(&c->macrolock); 02910 02911 return ret; 02912 }
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 2792 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().
02793 { 02794 int ret = -1; /* default error return */ 02795 struct ast_context *c = find_context_locked(context); 02796 02797 if (c) { /* ... remove extension ... */ 02798 ret = ast_context_remove_extension2(c, extension, priority, registrar); 02799 ast_unlock_contexts(); 02800 } 02801 return ret; 02802 }
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 2814 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().
02815 { 02816 struct ast_exten *exten, *prev_exten = NULL; 02817 struct ast_exten *peer; 02818 02819 ast_mutex_lock(&con->lock); 02820 02821 /* scan the extension list to find matching extension-registrar */ 02822 for (exten = con->root; exten; prev_exten = exten, exten = exten->next) { 02823 if (!strcmp(exten->exten, extension) && 02824 (!registrar || !strcmp(exten->registrar, registrar))) 02825 break; 02826 } 02827 if (!exten) { 02828 /* we can't find right extension */ 02829 ast_mutex_unlock(&con->lock); 02830 return -1; 02831 } 02832 02833 /* should we free all peers in this extension? (priority == 0)? */ 02834 if (priority == 0) { 02835 /* remove this extension from context list */ 02836 if (prev_exten) 02837 prev_exten->next = exten->next; 02838 else 02839 con->root = exten->next; 02840 02841 /* fire out all peers */ 02842 while ( (peer = exten) ) { 02843 exten = peer->peer; /* prepare for next entry */ 02844 destroy_exten(peer); 02845 } 02846 } else { 02847 /* scan the priority list to remove extension with exten->priority == priority */ 02848 struct ast_exten *previous_peer = NULL; 02849 02850 for (peer = exten; peer; previous_peer = peer, peer = peer->peer) { 02851 if (peer->priority == priority && 02852 (!registrar || !strcmp(peer->registrar, registrar) )) 02853 break; /* found our priority */ 02854 } 02855 if (!peer) { /* not found */ 02856 ast_mutex_unlock(&con->lock); 02857 return -1; 02858 } 02859 /* we are first priority extension? */ 02860 if (!previous_peer) { 02861 /* 02862 * We are first in the priority chain, so must update the extension chain. 02863 * The next node is either the next priority or the next extension 02864 */ 02865 struct ast_exten *next_node = peer->peer ? peer->peer : peer->next; 02866 02867 if (!prev_exten) /* change the root... */ 02868 con->root = next_node; 02869 else 02870 prev_exten->next = next_node; /* unlink */ 02871 if (peer->peer) /* XXX update the new head of the pri list */ 02872 peer->peer->next = peer->next; 02873 } else { /* easy, we are not first priority in extension */ 02874 previous_peer->peer = peer->peer; 02875 } 02876 02877 /* now, free whole priority extension */ 02878 destroy_exten(peer); 02879 /* XXX should we return -1 ? */ 02880 } 02881 ast_mutex_unlock(&con->lock); 02882 return 0; 02883 }
int ast_context_remove_ignorepat | ( | const char * | context, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 4427 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().
04428 { 04429 int ret = -1; 04430 struct ast_context *c = find_context_locked(context); 04431 04432 if (c) { 04433 ret = ast_context_remove_ignorepat2(c, ignorepat, registrar); 04434 ast_unlock_contexts(); 04435 } 04436 return ret; 04437 }
int ast_context_remove_ignorepat2 | ( | struct ast_context * | con, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 4439 of file pbx.c.
References ast_mutex_lock(), ast_mutex_unlock(), free, ast_context::ignorepats, ast_context::lock, ast_ignorepat::next, ast_ignorepat::pattern, and ast_ignorepat::registrar.
Referenced by ast_context_remove_ignorepat().
04440 { 04441 struct ast_ignorepat *ip, *ipl = NULL; 04442 04443 ast_mutex_lock(&con->lock); 04444 04445 for (ip = con->ignorepats; ip; ip = ip->next) { 04446 if (!strcmp(ip->pattern, ignorepat) && 04447 (!registrar || (registrar == ip->registrar))) { 04448 if (ipl) { 04449 ipl->next = ip->next; 04450 free(ip); 04451 } else { 04452 con->ignorepats = ip->next; 04453 free(ip); 04454 } 04455 ast_mutex_unlock(&con->lock); 04456 return 0; 04457 } 04458 ipl = ip; 04459 } 04460 04461 ast_mutex_unlock(&con->lock); 04462 errno = EINVAL; 04463 return -1; 04464 }
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 2688 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().
02689 { 02690 int ret = -1; 02691 struct ast_context *c = find_context_locked(context); 02692 02693 if (c) { 02694 /* found, remove include from this context ... */ 02695 ret = ast_context_remove_include2(c, include, registrar); 02696 ast_unlock_contexts(); 02697 } 02698 return ret; 02699 }
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 2709 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().
02710 { 02711 struct ast_include *i, *pi = NULL; 02712 int ret = -1; 02713 02714 ast_mutex_lock(&con->lock); 02715 02716 /* find our include */ 02717 for (i = con->includes; i; pi = i, i = i->next) { 02718 if (!strcmp(i->name, include) && 02719 (!registrar || !strcmp(i->registrar, registrar))) { 02720 /* remove from list */ 02721 if (pi) 02722 pi->next = i->next; 02723 else 02724 con->includes = i->next; 02725 /* free include and return */ 02726 free(i); 02727 ret = 0; 02728 break; 02729 } 02730 } 02731 02732 ast_mutex_unlock(&con->lock); 02733 return ret; 02734 }
int ast_context_remove_switch | ( | const char * | context, | |
const char * | sw, | |||
const char * | data, | |||
const char * | registrar | |||
) |
Remove a switch.
Definition at line 2741 of file pbx.c.
References ast_context_remove_switch2(), ast_unlock_contexts(), and find_context_locked().
02742 { 02743 int ret = -1; /* default error return */ 02744 struct ast_context *c = find_context_locked(context); 02745 02746 if (c) { 02747 /* remove switch from this context ... */ 02748 ret = ast_context_remove_switch2(c, sw, data, registrar); 02749 ast_unlock_contexts(); 02750 } 02751 return ret; 02752 }
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 2762 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().
02763 { 02764 struct ast_sw *i; 02765 int ret = -1; 02766 02767 ast_mutex_lock(&con->lock); 02768 02769 /* walk switches */ 02770 AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) { 02771 if (!strcmp(i->name, sw) && !strcmp(i->data, data) && 02772 (!registrar || !strcmp(i->registrar, registrar))) { 02773 /* found, remove from list */ 02774 AST_LIST_REMOVE_CURRENT(&con->alts, list); 02775 free(i); /* free switch and return */ 02776 ret = 0; 02777 break; 02778 } 02779 } 02780 AST_LIST_TRAVERSE_SAFE_END 02781 02782 ast_mutex_unlock(&con->lock); 02783 02784 return ret; 02785 }
int ast_context_unlockmacro | ( | const char * | context | ) |
Unlocks the macrolock in the given context.
Definition at line 2919 of file pbx.c.
References ast_get_context_name(), ast_lock_contexts(), ast_mutex_unlock(), ast_unlock_contexts(), and ast_walk_contexts().
Referenced by _macro_exec().
02920 { 02921 struct ast_context *c = NULL; 02922 int ret = -1; 02923 02924 ast_lock_contexts(); 02925 02926 while ((c = ast_walk_contexts(c))) { 02927 if (!strcmp(ast_get_context_name(c), context)) { 02928 ret = 0; 02929 break; 02930 } 02931 } 02932 02933 ast_unlock_contexts(); 02934 02935 /* if we found context, unlock macrolock */ 02936 if (ret == 0) 02937 ret = ast_mutex_unlock(&c->macrolock); 02938 02939 return ret; 02940 }
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 6254 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().
06255 { 06256 struct ast_include *inc = NULL; 06257 int res = 0; 06258 06259 while ( (inc = ast_walk_context_includes(con, inc)) ) 06260 if (!ast_context_find(inc->rname)) { 06261 res = -1; 06262 ast_log(LOG_WARNING, "Context '%s' tries includes nonexistent context '%s'\n", 06263 ast_get_context_name(con), inc->rname); 06264 } 06265 return res; 06266 }
struct ast_custom_function* ast_custom_function_find | ( | const char * | name | ) |
Definition at line 1433 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().
01434 { 01435 struct ast_custom_function *acf = NULL; 01436 01437 AST_LIST_LOCK(&acf_root); 01438 AST_LIST_TRAVERSE(&acf_root, acf, acflist) { 01439 if (!strcmp(name, acf->name)) 01440 break; 01441 } 01442 AST_LIST_UNLOCK(&acf_root); 01443 01444 return acf; 01445 }
int ast_custom_function_register | ( | struct ast_custom_function * | acf | ) |
Reigster a custom function.
Definition at line 1469 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(), and reload().
01470 { 01471 struct ast_custom_function *cur; 01472 01473 if (!acf) 01474 return -1; 01475 01476 AST_LIST_LOCK(&acf_root); 01477 01478 if (ast_custom_function_find(acf->name)) { 01479 ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name); 01480 AST_LIST_UNLOCK(&acf_root); 01481 return -1; 01482 } 01483 01484 /* Store in alphabetical order */ 01485 AST_LIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) { 01486 if (strcasecmp(acf->name, cur->name) < 0) { 01487 AST_LIST_INSERT_BEFORE_CURRENT(&acf_root, acf, acflist); 01488 break; 01489 } 01490 } 01491 AST_LIST_TRAVERSE_SAFE_END 01492 if (!cur) 01493 AST_LIST_INSERT_TAIL(&acf_root, acf, acflist); 01494 01495 AST_LIST_UNLOCK(&acf_root); 01496 01497 if (option_verbose > 1) 01498 ast_verbose(VERBOSE_PREFIX_2 "Registered custom function %s\n", acf->name); 01499 01500 return 0; 01501 }
int ast_custom_function_unregister | ( | struct ast_custom_function * | acf | ) |
Unregister a custom function.
Definition at line 1447 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 reload(), and unload_module().
01448 { 01449 struct ast_custom_function *cur; 01450 01451 if (!acf) 01452 return -1; 01453 01454 AST_LIST_LOCK(&acf_root); 01455 AST_LIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) { 01456 if (cur == acf) { 01457 AST_LIST_REMOVE_CURRENT(&acf_root, acflist); 01458 if (option_verbose > 1) 01459 ast_verbose(VERBOSE_PREFIX_2 "Unregistered custom function %s\n", acf->name); 01460 break; 01461 } 01462 } 01463 AST_LIST_TRAVERSE_SAFE_END 01464 AST_LIST_UNLOCK(&acf_root); 01465 01466 return acf ? 0 : -1; 01467 }
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 2267 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_park_call(), 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(), parkandannounce_exec(), pbx_builtin_waitexten(), phone_check_exception(), process_ast_dsp(), register_peer_exten(), rpt_exec(), skinny_ss(), socket_process(), ss_thread(), waitstream_core(), and zt_handle_dtmfup().
02268 { 02269 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH); 02270 }
int ast_explicit_goto | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 4549 of file pbx.c.
References 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(), and handle_setpriority().
04550 { 04551 if (!chan) 04552 return -1; 04553 04554 if (!ast_strlen_zero(context)) 04555 ast_copy_string(chan->context, context, sizeof(chan->context)); 04556 if (!ast_strlen_zero(exten)) 04557 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 04558 if (priority > -1) { 04559 chan->priority = priority; 04560 /* see flag description in channel.h for explanation */ 04561 if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP)) 04562 chan->priority--; 04563 } 04564 04565 return 0; 04566 }
int ast_extension_close | ( | const char * | pattern, | |
const char * | data, | |||
int | needmore | |||
) |
Definition at line 885 of file pbx.c.
References ast_log(), E_CANMATCH, E_MATCHMORE, extension_match_core(), and LOG_WARNING.
Referenced by realtime_switch_common().
00886 { 00887 if (needmore != E_MATCHMORE && needmore != E_CANMATCH) 00888 ast_log(LOG_WARNING, "invalid argument %d\n", needmore); 00889 return extension_match_core(pattern, data, needmore); 00890 }
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 880 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().
00881 { 00882 return extension_match_core(pattern, data, E_MATCH); 00883 }
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 1991 of file pbx.c.
References ast_extension_state2(), and ast_hint_extension().
Referenced by action_extensionstate(), and handle_request_subscribe().
01992 { 01993 struct ast_exten *e; 01994 01995 e = ast_hint_extension(c, context, exten); /* Do we have a hint for this extension ? */ 01996 if (!e) 01997 return -1; /* No hint, return -1 */ 01998 01999 return ast_extension_state2(e); /* Check all devices in the hint */ 02000 }
static int ast_extension_state2 | ( | struct ast_exten * | e | ) | [static] |
ast_extensions_state2: Check state of extension by using hints
Definition at line 1894 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().
01895 { 01896 char hint[AST_MAX_EXTENSION]; 01897 char *cur, *rest; 01898 int allunavailable = 1, allbusy = 1, allfree = 1, allonhold = 1; 01899 int busy = 0, inuse = 0, ring = 0; 01900 01901 if (!e) 01902 return -1; 01903 01904 ast_copy_string(hint, ast_get_extension_app(e), sizeof(hint)); 01905 01906 rest = hint; /* One or more devices separated with a & character */ 01907 while ( (cur = strsep(&rest, "&")) ) { 01908 int res = ast_device_state(cur); 01909 switch (res) { 01910 case AST_DEVICE_NOT_INUSE: 01911 allunavailable = 0; 01912 allbusy = 0; 01913 allonhold = 0; 01914 break; 01915 case AST_DEVICE_INUSE: 01916 inuse = 1; 01917 allunavailable = 0; 01918 allfree = 0; 01919 allonhold = 0; 01920 break; 01921 case AST_DEVICE_RINGING: 01922 ring = 1; 01923 allunavailable = 0; 01924 allfree = 0; 01925 allonhold = 0; 01926 break; 01927 case AST_DEVICE_RINGINUSE: 01928 inuse = 1; 01929 ring = 1; 01930 allunavailable = 0; 01931 allfree = 0; 01932 allonhold = 0; 01933 break; 01934 case AST_DEVICE_ONHOLD: 01935 allunavailable = 0; 01936 allfree = 0; 01937 break; 01938 case AST_DEVICE_BUSY: 01939 allunavailable = 0; 01940 allfree = 0; 01941 allonhold = 0; 01942 busy = 1; 01943 break; 01944 case AST_DEVICE_UNAVAILABLE: 01945 case AST_DEVICE_INVALID: 01946 allbusy = 0; 01947 allfree = 0; 01948 allonhold = 0; 01949 break; 01950 default: 01951 allunavailable = 0; 01952 allbusy = 0; 01953 allfree = 0; 01954 allonhold = 0; 01955 } 01956 } 01957 01958 if (!inuse && ring) 01959 return AST_EXTENSION_RINGING; 01960 if (inuse && ring) 01961 return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING); 01962 if (inuse) 01963 return AST_EXTENSION_INUSE; 01964 if (allfree) 01965 return AST_EXTENSION_NOT_INUSE; 01966 if (allonhold) 01967 return AST_EXTENSION_ONHOLD; 01968 if (allbusy) 01969 return AST_EXTENSION_BUSY; 01970 if (allunavailable) 01971 return AST_EXTENSION_UNAVAILABLE; 01972 if (busy) 01973 return AST_EXTENSION_INUSE; 01974 01975 return AST_EXTENSION_NOT_INUSE; 01976 }
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 1979 of file pbx.c.
References extension_states.
Referenced by cb_extensionstate(), handle_request_subscribe(), and handle_show_hints().
01980 { 01981 int i; 01982 01983 for (i = 0; (i < (sizeof(extension_states) / sizeof(extension_states[0]))); i++) { 01984 if (extension_states[i].extension_state == extension_state) 01985 return extension_states[i].text; 01986 } 01987 return "Unknown"; 01988 }
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 2046 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().
02048 { 02049 struct ast_hint *hint; 02050 struct ast_state_cb *cblist; 02051 struct ast_exten *e; 02052 02053 /* If there's no context and extension: add callback to statecbs list */ 02054 if (!context && !exten) { 02055 AST_LIST_LOCK(&hints); 02056 02057 for (cblist = statecbs; cblist; cblist = cblist->next) { 02058 if (cblist->callback == callback) { 02059 cblist->data = data; 02060 AST_LIST_UNLOCK(&hints); 02061 return 0; 02062 } 02063 } 02064 02065 /* Now insert the callback */ 02066 if (!(cblist = ast_calloc(1, sizeof(*cblist)))) { 02067 AST_LIST_UNLOCK(&hints); 02068 return -1; 02069 } 02070 cblist->id = 0; 02071 cblist->callback = callback; 02072 cblist->data = data; 02073 02074 cblist->next = statecbs; 02075 statecbs = cblist; 02076 02077 AST_LIST_UNLOCK(&hints); 02078 return 0; 02079 } 02080 02081 if (!context || !exten) 02082 return -1; 02083 02084 /* This callback type is for only one hint, so get the hint */ 02085 e = ast_hint_extension(NULL, context, exten); 02086 if (!e) { 02087 return -1; 02088 } 02089 02090 /* Find the hint in the list of hints */ 02091 AST_LIST_LOCK(&hints); 02092 02093 AST_LIST_TRAVERSE(&hints, hint, list) { 02094 if (hint->exten == e) 02095 break; 02096 } 02097 02098 if (!hint) { 02099 /* We have no hint, sorry */ 02100 AST_LIST_UNLOCK(&hints); 02101 return -1; 02102 } 02103 02104 /* Now insert the callback in the callback list */ 02105 if (!(cblist = ast_calloc(1, sizeof(*cblist)))) { 02106 AST_LIST_UNLOCK(&hints); 02107 return -1; 02108 } 02109 cblist->id = stateid++; /* Unique ID for this callback */ 02110 cblist->callback = callback; /* Pointer to callback routine */ 02111 cblist->data = data; /* Data for the callback */ 02112 02113 cblist->next = hint->callbacks; 02114 hint->callbacks = cblist; 02115 02116 AST_LIST_UNLOCK(&hints); 02117 return cblist->id; 02118 }
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 2121 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().
02122 { 02123 struct ast_state_cb **p_cur = NULL; /* address of pointer to us */ 02124 int ret = -1; 02125 02126 if (!id && !callback) 02127 return -1; 02128 02129 AST_LIST_LOCK(&hints); 02130 02131 if (!id) { /* id == 0 is a callback without extension */ 02132 for (p_cur = &statecbs; *p_cur; p_cur = &(*p_cur)->next) { 02133 if ((*p_cur)->callback == callback) 02134 break; 02135 } 02136 } else { /* callback with extension, find the callback based on ID */ 02137 struct ast_hint *hint; 02138 AST_LIST_TRAVERSE(&hints, hint, list) { 02139 for (p_cur = &hint->callbacks; *p_cur; p_cur = &(*p_cur)->next) { 02140 if ((*p_cur)->id == id) 02141 break; 02142 } 02143 if (*p_cur) /* found in the inner loop */ 02144 break; 02145 } 02146 } 02147 if (p_cur && *p_cur) { 02148 struct ast_state_cb *cur = *p_cur; 02149 *p_cur = cur->next; 02150 free(cur); 02151 ret = 0; 02152 } 02153 AST_LIST_UNLOCK(&hints); 02154 return ret; 02155 }
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 2272 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().
02273 { 02274 return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL); 02275 }
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 2277 of file pbx.c.
References E_FINDLABEL, and pbx_extension_helper().
Referenced by pbx_load_config().
02278 { 02279 return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL); 02280 }
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 1523 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().
01524 { 01525 char *args = func_args(function); 01526 struct ast_custom_function *acfptr = ast_custom_function_find(function); 01527 01528 if (acfptr == NULL) 01529 ast_log(LOG_ERROR, "Function %s not registered\n", function); 01530 else if (!acfptr->read) 01531 ast_log(LOG_ERROR, "Function %s cannot be read\n", function); 01532 else 01533 return acfptr->read(chan, function, args, workspace, len); 01534 return -1; 01535 }
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 1537 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().
01538 { 01539 char *args = func_args(function); 01540 struct ast_custom_function *acfptr = ast_custom_function_find(function); 01541 01542 if (acfptr == NULL) 01543 ast_log(LOG_ERROR, "Function %s not registered\n", function); 01544 else if (!acfptr->write) 01545 ast_log(LOG_ERROR, "Function %s cannot be written to\n", function); 01546 else 01547 return acfptr->write(chan, function, args, value); 01548 01549 return -1; 01550 }
const char* ast_get_context_name | ( | struct ast_context * | con | ) |
Definition at line 6111 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 6149 of file pbx.c.
References ast_context::registrar.
Referenced by handle_save_dialplan(), and show_dialplan_helper().
06150 { 06151 return c ? c->registrar : NULL; 06152 }
const char* ast_get_extension_app | ( | struct ast_exten * | e | ) |
Definition at line 6179 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().
06180 { 06181 return e ? e->app : NULL; 06182 }
void* ast_get_extension_app_data | ( | struct ast_exten * | e | ) |
Definition at line 6184 of file pbx.c.
References ast_exten::data.
Referenced by _macro_exec(), ast_get_hint(), handle_save_dialplan(), and print_ext().
06185 { 06186 return e ? e->data : NULL; 06187 }
const char* ast_get_extension_cidmatch | ( | struct ast_exten * | e | ) |
Definition at line 6174 of file pbx.c.
References ast_exten::cidmatch.
Referenced by find_matching_priority(), and handle_save_dialplan().
06175 { 06176 return e ? e->cidmatch : NULL; 06177 }
struct ast_context* ast_get_extension_context | ( | struct ast_exten * | exten | ) |
const char* ast_get_extension_label | ( | struct ast_exten * | exten | ) |
Definition at line 6126 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 6169 of file pbx.c.
References ast_exten::matchcid.
Referenced by find_matching_priority(), and handle_save_dialplan().
06170 { 06171 return e ? e->matchcid : 0; 06172 }
const char* ast_get_extension_name | ( | struct ast_exten * | exten | ) |
Definition at line 6121 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 6141 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 6154 of file pbx.c.
References ast_exten::registrar.
Referenced by handle_save_dialplan(), and show_dialplan_helper().
06155 { 06156 return e ? e->registrar : NULL; 06157 }
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 2250 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(), pbx_retrieve_variable(), and transmit_state_notify().
02251 { 02252 struct ast_exten *e = ast_hint_extension(c, context, exten); 02253 02254 if (e) { 02255 if (hint) 02256 ast_copy_string(hint, ast_get_extension_app(e), hintsize); 02257 if (name) { 02258 const char *tmp = ast_get_extension_app_data(e); 02259 if (tmp) 02260 ast_copy_string(name, tmp, namesize); 02261 } 02262 return -1; 02263 } 02264 return 0; 02265 }
const char* ast_get_ignorepat_name | ( | struct ast_ignorepat * | ip | ) |
Definition at line 6136 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().
06137 { 06138 return ip ? ip->pattern : NULL; 06139 }
const char* ast_get_ignorepat_registrar | ( | struct ast_ignorepat * | ip | ) |
Definition at line 6164 of file pbx.c.
References ast_ignorepat::registrar.
Referenced by handle_save_dialplan(), and show_dialplan_helper().
06165 { 06166 return ip ? ip->registrar : NULL; 06167 }
const char* ast_get_include_name | ( | struct ast_include * | inc | ) |
Definition at line 6131 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().
06132 { 06133 return inc ? inc->name : NULL; 06134 }
const char* ast_get_include_registrar | ( | struct ast_include * | i | ) |
Definition at line 6159 of file pbx.c.
References ast_include::registrar.
Referenced by handle_save_dialplan(), and show_dialplan_helper().
06160 { 06161 return i ? i->registrar : NULL; 06162 }
const char* ast_get_switch_data | ( | struct ast_sw * | sw | ) |
Definition at line 6194 of file pbx.c.
References ast_sw::data.
Referenced by handle_save_dialplan(), and show_dialplan_helper().
06195 { 06196 return sw ? sw->data : NULL; 06197 }
const char* ast_get_switch_name | ( | struct ast_sw * | sw | ) |
Definition at line 6189 of file pbx.c.
References ast_sw::name.
Referenced by handle_save_dialplan(), and show_dialplan_helper().
06190 { 06191 return sw ? sw->name : NULL; 06192 }
const char* ast_get_switch_registrar | ( | struct ast_sw * | sw | ) |
Definition at line 6199 of file pbx.c.
References ast_sw::registrar.
Referenced by handle_save_dialplan(), and show_dialplan_helper().
06200 { 06201 return sw ? sw->registrar : NULL; 06202 }
int ast_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 6288 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().
06289 { 06290 return __ast_goto_if_exists(chan, context, exten, priority, 0); 06291 }
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 1881 of file pbx.c.
References ast_mutex_lock(), ast_mutex_unlock(), E_MATCH, pbx_find_extension(), PRIORITY_HINT, and pbx_find_info::stacklen.
Referenced by ast_extension_state(), ast_get_hint(), and ast_merge_contexts_and_delete().
01882 { 01883 struct ast_exten *e; 01884 struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */ 01885 01886 ast_mutex_lock(&conlock); 01887 e = pbx_find_extension(c, NULL, &q, context, exten, PRIORITY_HINT, NULL, "", E_MATCH); 01888 ast_mutex_unlock(&conlock); 01889 01890 return e; 01891 }
void ast_hint_state_changed | ( | const char * | device | ) |
Definition at line 2002 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().
02003 { 02004 struct ast_hint *hint; 02005 02006 AST_LIST_LOCK(&hints); 02007 02008 AST_LIST_TRAVERSE(&hints, hint, list) { 02009 struct ast_state_cb *cblist; 02010 char buf[AST_MAX_EXTENSION]; 02011 char *parse = buf; 02012 char *cur; 02013 int state; 02014 02015 ast_copy_string(buf, ast_get_extension_app(hint->exten), sizeof(buf)); 02016 while ( (cur = strsep(&parse, "&")) ) { 02017 if (!strcasecmp(cur, device)) 02018 break; 02019 } 02020 if (!cur) 02021 continue; 02022 02023 /* Get device state for this hint */ 02024 state = ast_extension_state2(hint->exten); 02025 02026 if ((state == -1) || (state == hint->laststate)) 02027 continue; 02028 02029 /* Device state changed since last check - notify the watchers */ 02030 02031 /* For general callbacks */ 02032 for (cblist = statecbs; cblist; cblist = cblist->next) 02033 cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data); 02034 02035 /* For extension callbacks */ 02036 for (cblist = hint->callbacks; cblist; cblist = cblist->next) 02037 cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data); 02038 02039 hint->laststate = state; /* record we saw the change */ 02040 } 02041 02042 AST_LIST_UNLOCK(&hints); 02043 }
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 4515 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_soft_key_event_message(), handle_stimulus_message(), mgcp_ss(), skinny_ss(), and ss_thread().
04516 { 04517 struct ast_context *con = ast_context_find(context); 04518 if (con) { 04519 struct ast_ignorepat *pat; 04520 for (pat = con->ignorepats; pat; pat = pat->next) { 04521 if (ast_extension_match(pat->pattern, pattern)) 04522 return 1; 04523 } 04524 } 04525 04526 return 0; 04527 }
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 6098 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().
06099 { 06100 return ast_mutex_lock(&con->lock); 06101 }
int ast_lock_contexts | ( | void | ) |
Locks the context list.
0 | on success | |
-1 | on error |
Definition at line 6085 of file pbx.c.
References ast_mutex_lock().
Referenced by _macro_exec(), 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(), handle_save_dialplan(), and show_dialplan_helper().
06086 { 06087 return ast_mutex_lock(&conlock); 06088 }
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 2287 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().
02288 { 02289 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE); 02290 }
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 3910 of file pbx.c.
References __ast_context_destroy(), ast_calloc, AST_EXTENSION_REMOVED, ast_hint_extension(), 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_mutex_lock(), ast_mutex_unlock(), ast_state_cb::callback, ast_hint::callbacks, store_hint::callbacks, store_hint::context, contexts, ast_state_cb::data, 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, and ast_context::registrar.
Referenced by pbx_load_module().
03911 { 03912 struct ast_context *tmp, *lasttmp = NULL; 03913 struct store_hints store = AST_LIST_HEAD_INIT_VALUE; 03914 struct store_hint *this; 03915 struct ast_hint *hint; 03916 struct ast_exten *exten; 03917 int length; 03918 struct ast_state_cb *thiscb, *prevcb; 03919 03920 /* it is very important that this function hold the hint list lock _and_ the conlock 03921 during its operation; not only do we need to ensure that the list of contexts 03922 and extensions does not change, but also that no hint callbacks (watchers) are 03923 added or removed during the merge/delete process 03924 03925 in addition, the locks _must_ be taken in this order, because there are already 03926 other code paths that use this order 03927 */ 03928 ast_mutex_lock(&conlock); 03929 AST_LIST_LOCK(&hints); 03930 03931 /* preserve all watchers for hints associated with this registrar */ 03932 AST_LIST_TRAVERSE(&hints, hint, list) { 03933 if (hint->callbacks && !strcmp(registrar, hint->exten->parent->registrar)) { 03934 length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2 + sizeof(*this); 03935 if (!(this = ast_calloc(1, length))) 03936 continue; 03937 this->callbacks = hint->callbacks; 03938 hint->callbacks = NULL; 03939 this->laststate = hint->laststate; 03940 this->context = this->data; 03941 strcpy(this->data, hint->exten->parent->name); 03942 this->exten = this->data + strlen(this->context) + 1; 03943 strcpy(this->exten, hint->exten->exten); 03944 AST_LIST_INSERT_HEAD(&store, this, list); 03945 } 03946 } 03947 03948 tmp = *extcontexts; 03949 if (registrar) { 03950 /* XXX remove previous contexts from same registrar */ 03951 if (option_debug) 03952 ast_log(LOG_DEBUG, "must remove any reg %s\n", registrar); 03953 __ast_context_destroy(NULL,registrar); 03954 while (tmp) { 03955 lasttmp = tmp; 03956 tmp = tmp->next; 03957 } 03958 } else { 03959 /* XXX remove contexts with the same name */ 03960 while (tmp) { 03961 ast_log(LOG_WARNING, "must remove %s reg %s\n", tmp->name, tmp->registrar); 03962 __ast_context_destroy(tmp,tmp->registrar); 03963 lasttmp = tmp; 03964 tmp = tmp->next; 03965 } 03966 } 03967 if (lasttmp) { 03968 lasttmp->next = contexts; 03969 contexts = *extcontexts; 03970 *extcontexts = NULL; 03971 } else 03972 ast_log(LOG_WARNING, "Requested contexts didn't get merged\n"); 03973 03974 /* restore the watchers for hints that can be found; notify those that 03975 cannot be restored 03976 */ 03977 while ((this = AST_LIST_REMOVE_HEAD(&store, list))) { 03978 exten = ast_hint_extension(NULL, this->context, this->exten); 03979 /* Find the hint in the list of hints */ 03980 AST_LIST_TRAVERSE(&hints, hint, list) { 03981 if (hint->exten == exten) 03982 break; 03983 } 03984 if (!exten || !hint) { 03985 /* this hint has been removed, notify the watchers */ 03986 prevcb = NULL; 03987 thiscb = this->callbacks; 03988 while (thiscb) { 03989 prevcb = thiscb; 03990 thiscb = thiscb->next; 03991 prevcb->callback(this->context, this->exten, AST_EXTENSION_REMOVED, prevcb->data); 03992 free(prevcb); 03993 } 03994 } else { 03995 thiscb = this->callbacks; 03996 while (thiscb->next) 03997 thiscb = thiscb->next; 03998 thiscb->next = hint->callbacks; 03999 hint->callbacks = this->callbacks; 04000 hint->laststate = this->laststate; 04001 } 04002 free(this); 04003 } 04004 04005 AST_LIST_UNLOCK(&hints); 04006 ast_mutex_unlock(&conlock); 04007 04008 return; 04009 }
AST_MUTEX_DEFINE_STATIC | ( | conlock | ) |
Lock for the ast_context list
AST_MUTEX_DEFINE_STATIC | ( | maxcalllock | ) |
AST_MUTEX_DEFINE_STATIC | ( | globalslock | ) |
int ast_parseable_goto | ( | struct ast_channel * | chan, | |
const char * | goto_string | |||
) |
Definition at line 6298 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().
06299 { 06300 char *exten, *pri, *context; 06301 char *stringp; 06302 int ipri; 06303 int mode = 0; 06304 06305 if (ast_strlen_zero(goto_string)) { 06306 ast_log(LOG_WARNING, "Goto requires an argument (optional context|optional extension|priority)\n"); 06307 return -1; 06308 } 06309 stringp = ast_strdupa(goto_string); 06310 context = strsep(&stringp, "|"); /* guaranteed non-null */ 06311 exten = strsep(&stringp, "|"); 06312 pri = strsep(&stringp, "|"); 06313 if (!exten) { /* Only a priority in this one */ 06314 pri = context; 06315 exten = NULL; 06316 context = NULL; 06317 } else if (!pri) { /* Only an extension and priority in this one */ 06318 pri = exten; 06319 exten = context; 06320 context = NULL; 06321 } 06322 if (*pri == '+') { 06323 mode = 1; 06324 pri++; 06325 } else if (*pri == '-') { 06326 mode = -1; 06327 pri++; 06328 } 06329 if (sscanf(pri, "%d", &ipri) != 1) { 06330 if ((ipri = ast_findlabel_extension(chan, context ? context : chan->context, exten ? exten : chan->exten, 06331 pri, chan->cid.cid_num)) < 1) { 06332 ast_log(LOG_WARNING, "Priority '%s' must be a number > 0, or valid label\n", pri); 06333 return -1; 06334 } else 06335 mode = 0; 06336 } 06337 /* At this point we have a priority and maybe an extension and a context */ 06338 06339 if (mode) 06340 ipri = chan->priority + (ipri * mode); 06341 06342 ast_explicit_goto(chan, context, exten, ipri); 06343 ast_cdr_update(chan); 06344 return 0; 06345 06346 }
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 5134 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, 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().
05135 { 05136 struct ast_channel *chan; 05137 struct app_tmp *tmp; 05138 int res = -1, cdr_res = -1; 05139 struct outgoing_helper oh; 05140 pthread_attr_t attr; 05141 05142 memset(&oh, 0, sizeof(oh)); 05143 oh.vars = vars; 05144 oh.account = account; 05145 05146 if (locked_channel) 05147 *locked_channel = NULL; 05148 if (ast_strlen_zero(app)) { 05149 res = -1; 05150 goto outgoing_app_cleanup; 05151 } 05152 if (sync) { 05153 chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh); 05154 if (chan) { 05155 if (chan->cdr) { /* check if the channel already has a cdr record, if not give it one */ 05156 ast_log(LOG_WARNING, "%s already has a call record??\n", chan->name); 05157 } else { 05158 chan->cdr = ast_cdr_alloc(); /* allocate a cdr for the channel */ 05159 if(!chan->cdr) { 05160 /* allocation of the cdr failed */ 05161 free(chan->pbx); 05162 res = -1; 05163 goto outgoing_app_cleanup; 05164 } 05165 /* allocation of the cdr was successful */ 05166 ast_cdr_init(chan->cdr, chan); /* initialize our channel's cdr */ 05167 ast_cdr_start(chan->cdr); 05168 } 05169 ast_set_variables(chan, vars); 05170 if (account) 05171 ast_cdr_setaccount(chan, account); 05172 if (chan->_state == AST_STATE_UP) { 05173 res = 0; 05174 if (option_verbose > 3) 05175 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", chan->name); 05176 tmp = ast_calloc(1, sizeof(*tmp)); 05177 if (!tmp) 05178 res = -1; 05179 else { 05180 ast_copy_string(tmp->app, app, sizeof(tmp->app)); 05181 if (appdata) 05182 ast_copy_string(tmp->data, appdata, sizeof(tmp->data)); 05183 tmp->chan = chan; 05184 if (sync > 1) { 05185 if (locked_channel) 05186 ast_channel_unlock(chan); 05187 ast_pbx_run_app(tmp); 05188 } else { 05189 pthread_attr_init(&attr); 05190 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 05191 if (locked_channel) 05192 ast_channel_lock(chan); 05193 if (ast_pthread_create(&tmp->t, &attr, ast_pbx_run_app, tmp)) { 05194 ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno)); 05195 free(tmp); 05196 if (locked_channel) 05197 ast_channel_unlock(chan); 05198 ast_hangup(chan); 05199 res = -1; 05200 } else { 05201 if (locked_channel) 05202 *locked_channel = chan; 05203 } 05204 pthread_attr_destroy(&attr); 05205 } 05206 } 05207 } else { 05208 if (option_verbose > 3) 05209 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", chan->name); 05210 if (chan->cdr) { /* update the cdr */ 05211 /* here we update the status of the call, which sould be busy. 05212 * if that fails then we set the status to failed */ 05213 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 05214 ast_cdr_failed(chan->cdr); 05215 } 05216 ast_hangup(chan); 05217 } 05218 } 05219 05220 if (res < 0) { /* the call failed for some reason */ 05221 if (*reason == 0) { /* if the call failed (not busy or no answer) 05222 * update the cdr with the failed message */ 05223 cdr_res = ast_pbx_outgoing_cdr_failed(); 05224 if (cdr_res != 0) { 05225 res = cdr_res; 05226 goto outgoing_app_cleanup; 05227 } 05228 } 05229 } 05230 05231 } else { 05232 struct async_stat *as; 05233 if (!(as = ast_calloc(1, sizeof(*as)))) { 05234 res = -1; 05235 goto outgoing_app_cleanup; 05236 } 05237 chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh); 05238 if (!chan) { 05239 free(as); 05240 res = -1; 05241 goto outgoing_app_cleanup; 05242 } 05243 as->chan = chan; 05244 ast_copy_string(as->app, app, sizeof(as->app)); 05245 if (appdata) 05246 ast_copy_string(as->appdata, appdata, sizeof(as->appdata)); 05247 as->timeout = timeout; 05248 ast_set_variables(chan, vars); 05249 if (account) 05250 ast_cdr_setaccount(chan, account); 05251 /* Start a new thread, and get something handling this channel. */ 05252 pthread_attr_init(&attr); 05253 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 05254 if (locked_channel) 05255 ast_channel_lock(chan); 05256 if (ast_pthread_create(&as->p, &attr, async_wait, as)) { 05257 ast_log(LOG_WARNING, "Failed to start async wait\n"); 05258 free(as); 05259 if (locked_channel) 05260 ast_channel_unlock(chan); 05261 ast_hangup(chan); 05262 res = -1; 05263 pthread_attr_destroy(&attr); 05264 goto outgoing_app_cleanup; 05265 } else { 05266 if (locked_channel) 05267 *locked_channel = chan; 05268 } 05269 pthread_attr_destroy(&attr); 05270 res = 0; 05271 } 05272 outgoing_app_cleanup: 05273 ast_variables_destroy(vars); 05274 return res; 05275 }
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 4939 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().
04940 { 04941 /* allocate a channel */ 04942 struct ast_channel *chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, 0); 04943 04944 if (!chan) 04945 return -1; /* failure */ 04946 04947 if (!chan->cdr) { 04948 /* allocation of the cdr failed */ 04949 ast_channel_free(chan); /* free the channel */ 04950 return -1; /* return failure */ 04951 } 04952 04953 /* allocation of the cdr was successful */ 04954 ast_cdr_init(chan->cdr, chan); /* initialize our channel's cdr */ 04955 ast_cdr_start(chan->cdr); /* record the start and stop time */ 04956 ast_cdr_end(chan->cdr); 04957 ast_cdr_failed(chan->cdr); /* set the status to failed */ 04958 ast_cdr_detach(chan->cdr); /* post and free the record */ 04959 ast_channel_free(chan); /* free the channel */ 04960 04961 return 0; /* success */ 04962 }
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 4964 of file pbx.c.
References __ast_request_and_dial(), ast_channel::_state, ast_calloc, ast_cdr_alloc(), ast_cdr_disposition(), ast_cdr_failed(), ast_cdr_init(), ast_cdr_setaccount(), ast_cdr_start(), 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, ast_channel::pbx, set_ext_pri(), outgoing_helper::vars, and VERBOSE_PREFIX_4.
Referenced by action_originate(), attempt_thread(), fast_originate(), and orig_exten().
04965 { 04966 struct ast_channel *chan; 04967 struct async_stat *as; 04968 int res = -1, cdr_res = -1; 04969 struct outgoing_helper oh; 04970 pthread_attr_t attr; 04971 04972 if (sync) { 04973 LOAD_OH(oh); 04974 chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh); 04975 if (channel) { 04976 *channel = chan; 04977 if (chan) 04978 ast_channel_lock(chan); 04979 } 04980 if (chan) { 04981 if (chan->cdr) { /* check if the channel already has a cdr record, if not give it one */ 04982 ast_log(LOG_WARNING, "%s already has a call record??\n", chan->name); 04983 } else { 04984 chan->cdr = ast_cdr_alloc(); /* allocate a cdr for the channel */ 04985 if (!chan->cdr) { 04986 /* allocation of the cdr failed */ 04987 free(chan->pbx); 04988 res = -1; 04989 goto outgoing_exten_cleanup; 04990 } 04991 /* allocation of the cdr was successful */ 04992 ast_cdr_init(chan->cdr, chan); /* initialize our channel's cdr */ 04993 ast_cdr_start(chan->cdr); 04994 } 04995 if (chan->_state == AST_STATE_UP) { 04996 res = 0; 04997 if (option_verbose > 3) 04998 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", chan->name); 04999 05000 if (sync > 1) { 05001 if (channel) 05002 ast_channel_unlock(chan); 05003 if (ast_pbx_run(chan)) { 05004 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 05005 if (channel) 05006 *channel = NULL; 05007 ast_hangup(chan); 05008 res = -1; 05009 } 05010 } else { 05011 if (ast_pbx_start(chan)) { 05012 ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name); 05013 if (channel) { 05014 *channel = NULL; 05015 ast_channel_unlock(chan); 05016 } 05017 ast_hangup(chan); 05018 res = -1; 05019 } 05020 } 05021 } else { 05022 if (option_verbose > 3) 05023 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", chan->name); 05024 05025 if(chan->cdr) { /* update the cdr */ 05026 /* here we update the status of the call, which sould be busy. 05027 * if that fails then we set the status to failed */ 05028 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 05029 ast_cdr_failed(chan->cdr); 05030 } 05031 05032 if (channel) { 05033 *channel = NULL; 05034 ast_channel_unlock(chan); 05035 } 05036 ast_hangup(chan); 05037 } 05038 } 05039 05040 if (res < 0) { /* the call failed for some reason */ 05041 if (*reason == 0) { /* if the call failed (not busy or no answer) 05042 * update the cdr with the failed message */ 05043 cdr_res = ast_pbx_outgoing_cdr_failed(); 05044 if (cdr_res != 0) { 05045 res = cdr_res; 05046 goto outgoing_exten_cleanup; 05047 } 05048 } 05049 05050 /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */ 05051 /* check if "failed" exists */ 05052 if (ast_exists_extension(chan, context, "failed", 1, NULL)) { 05053 chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "OutgoingSpoolFailed"); 05054 if (chan) { 05055 if (!ast_strlen_zero(context)) 05056 ast_copy_string(chan->context, context, sizeof(chan->context)); 05057 set_ext_pri(chan, "failed", 1); 05058 ast_set_variables(chan, vars); 05059 if (account) 05060 ast_cdr_setaccount(chan, account); 05061 ast_pbx_run(chan); 05062 } 05063 } 05064 } 05065 } else { 05066 if (!(as = ast_calloc(1, sizeof(*as)))) { 05067 res = -1; 05068 goto outgoing_exten_cleanup; 05069 } 05070 chan = ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name); 05071 if (channel) { 05072 *channel = chan; 05073 if (chan) 05074 ast_channel_lock(chan); 05075 } 05076 if (!chan) { 05077 free(as); 05078 res = -1; 05079 goto outgoing_exten_cleanup; 05080 } 05081 as->chan = chan; 05082 ast_copy_string(as->context, context, sizeof(as->context)); 05083 set_ext_pri(as->chan, exten, priority); 05084 as->timeout = timeout; 05085 ast_set_variables(chan, vars); 05086 if (account) 05087 ast_cdr_setaccount(chan, account); 05088 pthread_attr_init(&attr); 05089 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 05090 if (ast_pthread_create(&as->p, &attr, async_wait, as)) { 05091 ast_log(LOG_WARNING, "Failed to start async wait\n"); 05092 free(as); 05093 if (channel) { 05094 *channel = NULL; 05095 ast_channel_unlock(chan); 05096 } 05097 ast_hangup(chan); 05098 res = -1; 05099 pthread_attr_destroy(&attr); 05100 goto outgoing_exten_cleanup; 05101 } 05102 pthread_attr_destroy(&attr); 05103 res = 0; 05104 } 05105 outgoing_exten_cleanup: 05106 ast_variables_destroy(vars); 05107 return res; 05108 }
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 2641 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().
02642 { 02643 enum ast_pbx_result res = AST_PBX_SUCCESS; 02644 02645 if (increase_call_count(c)) 02646 return AST_PBX_CALL_LIMIT; 02647 02648 res = __ast_pbx_run(c); 02649 decrease_call_count(); 02650 02651 return res; 02652 }
static void* ast_pbx_run_app | ( | void * | data | ) | [static] |
run the application and free the descriptor once done
Definition at line 5118 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().
05119 { 05120 struct app_tmp *tmp = data; 05121 struct ast_app *app; 05122 app = pbx_findapp(tmp->app); 05123 if (app) { 05124 if (option_verbose > 3) 05125 ast_verbose(VERBOSE_PREFIX_4 "Launching %s(%s) on %s\n", tmp->app, tmp->data, tmp->chan->name); 05126 pbx_exec(tmp->chan, app, tmp->data); 05127 } else 05128 ast_log(LOG_WARNING, "No such application '%s'\n", tmp->app); 05129 ast_hangup(tmp->chan); 05130 free(tmp); 05131 return NULL; 05132 }
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 2615 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_iax2_new(), ast_pbx_outgoing_exten(), 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().
02616 { 02617 pthread_t t; 02618 pthread_attr_t attr; 02619 02620 if (!c) { 02621 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n"); 02622 return AST_PBX_FAILED; 02623 } 02624 02625 if (increase_call_count(c)) 02626 return AST_PBX_CALL_LIMIT; 02627 02628 /* Start a new thread, and get something handling this channel. */ 02629 pthread_attr_init(&attr); 02630 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 02631 if (ast_pthread_create(&t, &attr, pbx_thread, c)) { 02632 ast_log(LOG_WARNING, "Failed to create new channel thread\n"); 02633 pthread_attr_destroy(&attr); 02634 return AST_PBX_FAILED; 02635 } 02636 pthread_attr_destroy(&attr); 02637 02638 return AST_PBX_SUCCESS; 02639 }
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 2943 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().
02944 { 02945 struct ast_app *tmp, *cur = NULL; 02946 char tmps[80]; 02947 int length; 02948 02949 AST_LIST_LOCK(&apps); 02950 AST_LIST_TRAVERSE(&apps, tmp, list) { 02951 if (!strcasecmp(app, tmp->name)) { 02952 ast_log(LOG_WARNING, "Already have an application '%s'\n", app); 02953 AST_LIST_UNLOCK(&apps); 02954 return -1; 02955 } 02956 } 02957 02958 length = sizeof(*tmp) + strlen(app) + 1; 02959 02960 if (!(tmp = ast_calloc(1, length))) { 02961 AST_LIST_UNLOCK(&apps); 02962 return -1; 02963 } 02964 02965 strcpy(tmp->name, app); 02966 tmp->execute = execute; 02967 tmp->synopsis = synopsis; 02968 tmp->description = description; 02969 02970 /* Store in alphabetical order */ 02971 AST_LIST_TRAVERSE_SAFE_BEGIN(&apps, cur, list) { 02972 if (strcasecmp(tmp->name, cur->name) < 0) { 02973 AST_LIST_INSERT_BEFORE_CURRENT(&apps, tmp, list); 02974 break; 02975 } 02976 } 02977 AST_LIST_TRAVERSE_SAFE_END 02978 if (!cur) 02979 AST_LIST_INSERT_TAIL(&apps, tmp, list); 02980 02981 if (option_verbose > 1) 02982 ast_verbose( VERBOSE_PREFIX_2 "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps))); 02983 02984 AST_LIST_UNLOCK(&apps); 02985 02986 return 0; 02987 }
int ast_register_switch | ( | struct ast_switch * | sw | ) |
Register an alternative dialplan switch.
sw | switch to register |
Definition at line 2993 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().
02994 { 02995 struct ast_switch *tmp; 02996 02997 AST_LIST_LOCK(&switches); 02998 AST_LIST_TRAVERSE(&switches, tmp, list) { 02999 if (!strcasecmp(tmp->name, sw->name)) { 03000 AST_LIST_UNLOCK(&switches); 03001 ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name); 03002 return -1; 03003 } 03004 } 03005 AST_LIST_INSERT_TAIL(&switches, sw, list); 03006 AST_LIST_UNLOCK(&switches); 03007 03008 return 0; 03009 }
static int ast_remove_hint | ( | struct ast_exten * | e | ) | [static] |
ast_remove_hint: Remove hint from extension
Definition at line 2213 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().
02214 { 02215 /* Cleanup the Notifys if hint is removed */ 02216 struct ast_hint *hint; 02217 struct ast_state_cb *cblist, *cbprev; 02218 int res = -1; 02219 02220 if (!e) 02221 return -1; 02222 02223 AST_LIST_LOCK(&hints); 02224 AST_LIST_TRAVERSE_SAFE_BEGIN(&hints, hint, list) { 02225 if (hint->exten == e) { 02226 cbprev = NULL; 02227 cblist = hint->callbacks; 02228 while (cblist) { 02229 /* Notify with -1 and remove all callbacks */ 02230 cbprev = cblist; 02231 cblist = cblist->next; 02232 cbprev->callback(hint->exten->parent->name, hint->exten->exten, AST_EXTENSION_DEACTIVATED, cbprev->data); 02233 free(cbprev); 02234 } 02235 hint->callbacks = NULL; 02236 AST_LIST_REMOVE_CURRENT(&hints, list); 02237 free(hint); 02238 res = 0; 02239 break; 02240 } 02241 } 02242 AST_LIST_TRAVERSE_SAFE_END 02243 AST_LIST_UNLOCK(&hints); 02244 02245 return res; 02246 }
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 2292 of file pbx.c.
References E_SPAWN, and pbx_extension_helper().
Referenced by __ast_pbx_run(), _macro_exec(), and loopback_exec().
02293 { 02294 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN); 02295 }
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 6103 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().
06104 { 06105 return ast_mutex_unlock(&con->lock); 06106 }
int ast_unlock_contexts | ( | void | ) |
Unlocks contexts.
0 | on success | |
-1 | on failure |
Definition at line 6090 of file pbx.c.
References ast_mutex_unlock().
Referenced by _macro_exec(), ast_add_extension(), ast_context_add_ignorepat(), ast_context_add_include(), ast_context_add_switch(), ast_context_lockmacro(), ast_context_remove_extension(), ast_context_remove_ignorepat(), ast_context_remove_include(), ast_context_remove_switch(), 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(), handle_save_dialplan(), and show_dialplan_helper().
06091 { 06092 return ast_mutex_unlock(&conlock); 06093 }
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 3824 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().
03825 { 03826 struct ast_app *tmp; 03827 03828 AST_LIST_LOCK(&apps); 03829 AST_LIST_TRAVERSE_SAFE_BEGIN(&apps, tmp, list) { 03830 if (!strcasecmp(app, tmp->name)) { 03831 AST_LIST_REMOVE_CURRENT(&apps, list); 03832 if (option_verbose > 1) 03833 ast_verbose( VERBOSE_PREFIX_2 "Unregistered application '%s'\n", tmp->name); 03834 free(tmp); 03835 break; 03836 } 03837 } 03838 AST_LIST_TRAVERSE_SAFE_END 03839 AST_LIST_UNLOCK(&apps); 03840 03841 return tmp ? 0 : -1; 03842 }
void ast_unregister_switch | ( | struct ast_switch * | sw | ) |
Unregister an alternative switch.
sw | switch to unregister |
Definition at line 3011 of file pbx.c.
References AST_LIST_LOCK, AST_LIST_REMOVE, and AST_LIST_UNLOCK.
Referenced by __unload_module(), and unload_module().
03012 { 03013 AST_LIST_LOCK(&switches); 03014 AST_LIST_REMOVE(&switches, sw, list); 03015 AST_LIST_UNLOCK(&switches); 03016 }
struct ast_exten* ast_walk_context_extensions | ( | struct ast_context * | con, | |
struct ast_exten * | exten | |||
) |
Definition at line 6212 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().
06214 { 06215 if (!exten) 06216 return con ? con->root : NULL; 06217 else 06218 return exten->next; 06219 }
struct ast_ignorepat* ast_walk_context_ignorepats | ( | struct ast_context * | con, | |
struct ast_ignorepat * | ip | |||
) |
Definition at line 6245 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().
06247 { 06248 if (!ip) 06249 return con ? con->ignorepats : NULL; 06250 else 06251 return ip->next; 06252 }
struct ast_include* ast_walk_context_includes | ( | struct ast_context * | con, | |
struct ast_include * | inc | |||
) |
Definition at line 6236 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().
06238 { 06239 if (!inc) 06240 return con ? con->includes : NULL; 06241 else 06242 return inc->next; 06243 }
struct ast_sw* ast_walk_context_switches | ( | struct ast_context * | con, | |
struct ast_sw * | sw | |||
) |
Definition at line 6221 of file pbx.c.
References AST_LIST_FIRST, and AST_LIST_NEXT.
Referenced by handle_save_dialplan(), and show_dialplan_helper().
06223 { 06224 if (!sw) 06225 return con ? AST_LIST_FIRST(&con->alts) : NULL; 06226 else 06227 return AST_LIST_NEXT(sw, list); 06228 }
struct ast_context* ast_walk_contexts | ( | struct ast_context * | con | ) |
Definition at line 6207 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 6230 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().
static void* async_wait | ( | void * | data | ) | [static] |
Definition at line 4876 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().
04877 { 04878 struct async_stat *as = data; 04879 struct ast_channel *chan = as->chan; 04880 int timeout = as->timeout; 04881 int res; 04882 struct ast_frame *f; 04883 struct ast_app *app; 04884 04885 while (timeout && (chan->_state != AST_STATE_UP)) { 04886 res = ast_waitfor(chan, timeout); 04887 if (res < 1) 04888 break; 04889 if (timeout > -1) 04890 timeout = res; 04891 f = ast_read(chan); 04892 if (!f) 04893 break; 04894 if (f->frametype == AST_FRAME_CONTROL) { 04895 if ((f->subclass == AST_CONTROL_BUSY) || 04896 (f->subclass == AST_CONTROL_CONGESTION) ) { 04897 ast_frfree(f); 04898 break; 04899 } 04900 } 04901 ast_frfree(f); 04902 } 04903 if (chan->_state == AST_STATE_UP) { 04904 if (!ast_strlen_zero(as->app)) { 04905 app = pbx_findapp(as->app); 04906 if (app) { 04907 if (option_verbose > 2) 04908 ast_verbose(VERBOSE_PREFIX_3 "Launching %s(%s) on %s\n", as->app, as->appdata, chan->name); 04909 pbx_exec(chan, app, as->appdata); 04910 } else 04911 ast_log(LOG_WARNING, "No such application '%s'\n", as->app); 04912 } else { 04913 if (!ast_strlen_zero(as->context)) 04914 ast_copy_string(chan->context, as->context, sizeof(chan->context)); 04915 if (!ast_strlen_zero(as->exten)) 04916 ast_copy_string(chan->exten, as->exten, sizeof(chan->exten)); 04917 if (as->priority > 0) 04918 chan->priority = as->priority; 04919 /* Run the PBX */ 04920 if (ast_pbx_run(chan)) { 04921 ast_log(LOG_ERROR, "Failed to start PBX on %s\n", chan->name); 04922 } else { 04923 /* PBX will have taken care of this */ 04924 chan = NULL; 04925 } 04926 } 04927 } 04928 free(as); 04929 if (chan) 04930 ast_hangup(chan); 04931 return NULL; 04932 }
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 2308 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.
02309 { 02310 int digit; 02311 02312 buf[pos] = '\0'; /* make sure it is properly terminated */ 02313 while (ast_matchmore_extension(c, c->context, buf, 1, c->cid.cid_num)) { 02314 /* As long as we're willing to wait, and as long as it's not defined, 02315 keep reading digits until we can't possibly get a right answer anymore. */ 02316 digit = ast_waitfordigit(c, waittime * 1000); 02317 if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) { 02318 c->_softhangup = 0; 02319 } else { 02320 if (!digit) /* No entry */ 02321 break; 02322 if (digit < 0) /* Error, maybe a hangup */ 02323 return -1; 02324 if (pos < buflen - 1) { /* XXX maybe error otherwise ? */ 02325 buf[pos++] = digit; 02326 buf[pos] = '\0'; 02327 } 02328 waittime = c->pbx->dtimeout; 02329 } 02330 } 02331 return 0; 02332 }
static char* complete_show_application | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 3069 of file pbx.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, and strdup.
03070 { 03071 struct ast_app *a; 03072 char *ret = NULL; 03073 int which = 0; 03074 int wordlen = strlen(word); 03075 03076 /* return the n-th [partial] matching entry */ 03077 AST_LIST_LOCK(&apps); 03078 AST_LIST_TRAVERSE(&apps, a, list) { 03079 if (!strncasecmp(word, a->name, wordlen) && ++which > state) { 03080 ret = strdup(a->name); 03081 break; 03082 } 03083 } 03084 AST_LIST_UNLOCK(&apps); 03085 03086 return ret; 03087 }
static char* complete_show_applications | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 3430 of file pbx.c.
References ast_cli_complete().
03431 { 03432 static char* choices[] = { "like", "describing", NULL }; 03433 03434 return (pos != 3) ? NULL : ast_cli_complete(word, choices, state); 03435 }
static char* complete_show_applications_deprecated | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 3423 of file pbx.c.
References ast_cli_complete().
03424 { 03425 static char* choices[] = { "like", "describing", NULL }; 03426 03427 return (pos != 2) ? NULL : ast_cli_complete(word, choices, state); 03428 }
static char* complete_show_dialplan_context | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 3440 of file pbx.c.
References ast_get_context_name(), ast_lock_contexts(), ast_strdup, ast_unlock_contexts(), and ast_walk_contexts().
03442 { 03443 struct ast_context *c = NULL; 03444 char *ret = NULL; 03445 int which = 0; 03446 int wordlen; 03447 03448 /* we are do completion of [exten@]context on second position only */ 03449 if (pos != 2) 03450 return NULL; 03451 03452 ast_lock_contexts(); 03453 03454 wordlen = strlen(word); 03455 03456 /* walk through all contexts and return the n-th match */ 03457 while ( (c = ast_walk_contexts(c)) ) { 03458 if (!strncasecmp(word, ast_get_context_name(c), wordlen) && ++which > state) { 03459 ret = ast_strdup(ast_get_context_name(c)); 03460 break; 03461 } 03462 } 03463 03464 ast_unlock_contexts(); 03465 03466 return ret; 03467 }
static char* complete_show_function | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 1413 of file pbx.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_custom_function::name, and strdup.
01414 { 01415 struct ast_custom_function *acf; 01416 char *ret = NULL; 01417 int which = 0; 01418 int wordlen = strlen(word); 01419 01420 /* case-insensitive for convenience in this 'complete' function */ 01421 AST_LIST_LOCK(&acf_root); 01422 AST_LIST_TRAVERSE(&acf_root, acf, acflist) { 01423 if (!strncasecmp(word, acf->name, wordlen) && ++which > state) { 01424 ret = strdup(acf->name); 01425 break; 01426 } 01427 } 01428 AST_LIST_UNLOCK(&acf_root); 01429 01430 return ret; 01431 }
static void decrease_call_count | ( | void | ) | [static] |
Definition at line 2577 of file pbx.c.
References ast_mutex_lock(), ast_mutex_unlock(), and countcalls.
Referenced by ast_pbx_run(), and pbx_thread().
02578 { 02579 ast_mutex_lock(&maxcalllock); 02580 if (countcalls > 0) 02581 countcalls--; 02582 ast_mutex_unlock(&maxcalllock); 02583 }
static void destroy_exten | ( | struct ast_exten * | e | ) | [static] |
Definition at line 2585 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().
02586 { 02587 if (e->priority == PRIORITY_HINT) 02588 ast_remove_hint(e); 02589 02590 if (e->datad) 02591 e->datad(e->data); 02592 free(e); 02593 }
static int ext_cmp | ( | const char * | a, | |
const char * | b | |||
) | [static] |
the full routine to compare extensions in rules.
Definition at line 719 of file pbx.c.
References ext_cmp1().
Referenced by ast_add_extension2().
00720 { 00721 /* make sure non-patterns come first. 00722 * If a is not a pattern, it either comes first or 00723 * we use strcmp to compare the strings. 00724 */ 00725 int ret = 0; 00726 00727 if (a[0] != '_') 00728 return (b[0] == '_') ? -1 : strcmp(a, b); 00729 00730 /* Now we know a is a pattern; if b is not, a comes first */ 00731 if (b[0] != '_') 00732 return 1; 00733 #if 0 /* old mode for ext matching */ 00734 return strcmp(a, b); 00735 #endif 00736 /* ok we need full pattern sorting routine */ 00737 while (!ret && a && b) 00738 ret = ext_cmp1(&a) - ext_cmp1(&b); 00739 if (ret == 0) 00740 return 0; 00741 else 00742 return (ret > 0) ? 1 : -1; 00743 }
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 647 of file pbx.c.
References ast_log(), and LOG_WARNING.
Referenced by ext_cmp().
00648 { 00649 uint32_t chars[8]; 00650 int c, cmin = 0xff, count = 0; 00651 const char *end; 00652 00653 /* load, sign extend and advance pointer until we find 00654 * a valid character. 00655 */ 00656 while ( (c = *(*p)++) && (c == ' ' || c == '-') ) 00657 ; /* ignore some characters */ 00658 00659 /* always return unless we have a set of chars */ 00660 switch (c) { 00661 default: /* ordinary character */ 00662 return 0x0000 | (c & 0xff); 00663 00664 case 'N': /* 2..9 */ 00665 return 0x0700 | '2' ; 00666 00667 case 'X': /* 0..9 */ 00668 return 0x0900 | '0'; 00669 00670 case 'Z': /* 1..9 */ 00671 return 0x0800 | '1'; 00672 00673 case '.': /* wildcard */ 00674 return 0x10000; 00675 00676 case '!': /* earlymatch */ 00677 return 0x20000; /* less specific than NULL */ 00678 00679 case '\0': /* empty string */ 00680 *p = NULL; 00681 return 0x30000; 00682 00683 case '[': /* pattern */ 00684 break; 00685 } 00686 /* locate end of set */ 00687 end = strchr(*p, ']'); 00688 00689 if (end == NULL) { 00690 ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n"); 00691 return 0x40000; /* XXX make this entry go last... */ 00692 } 00693 00694 bzero(chars, sizeof(chars)); /* clear all chars in the set */ 00695 for (; *p < end ; (*p)++) { 00696 unsigned char c1, c2; /* first-last char in range */ 00697 c1 = (unsigned char)((*p)[0]); 00698 if (*p + 2 < end && (*p)[1] == '-') { /* this is a range */ 00699 c2 = (unsigned char)((*p)[2]); 00700 *p += 2; /* skip a total of 3 chars */ 00701 } else /* individual character */ 00702 c2 = c1; 00703 if (c1 < cmin) 00704 cmin = c1; 00705 for (; c1 <= c2; c1++) { 00706 uint32_t mask = 1 << (c1 % 32); 00707 if ( (chars[ c1 / 32 ] & mask) == 0) 00708 count += 0x100; 00709 chars[ c1 / 32 ] |= mask; 00710 } 00711 } 00712 (*p)++; 00713 return count == 0 ? 0x30000 : (count | cmin); 00714 }
static int ext_strncpy | ( | char * | dst, | |
const char * | src, | |||
int | len | |||
) | [static] |
copy a string skipping whitespace
Definition at line 4628 of file pbx.c.
Referenced by ast_add_extension2().
04629 { 04630 int count=0; 04631 04632 while (*src && (count < len - 1)) { 04633 switch(*src) { 04634 case ' ': 04635 /* otherwise exten => [a-b],1,... doesn't work */ 04636 /* case '-': */ 04637 /* Ignore */ 04638 break; 04639 default: 04640 *dst = *src; 04641 dst++; 04642 } 04643 src++; 04644 count++; 04645 } 04646 *dst = '\0'; 04647 04648 return count; 04649 }
static int extension_match_core | ( | const char * | pattern, | |
const char * | data, | |||
enum ext_match_t | mode | |||
) | [static] |
Definition at line 868 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().
00869 { 00870 int i; 00871 static int prof_id = -2; /* marker for 'unallocated' id */ 00872 if (prof_id == -2) 00873 prof_id = ast_add_profile("ext_match", 0); 00874 ast_mark(prof_id, 1); 00875 i = _extension_match_core(pattern, data, mode); 00876 ast_mark(prof_id, 0); 00877 return i; 00878 }
static struct ast_context* find_context_locked | ( | const char * | context | ) | [static] |
Definition at line 2669 of file pbx.c.
References ast_get_context_name(), ast_lock_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().
02670 { 02671 struct ast_context *c = NULL; 02672 02673 ast_lock_contexts(); 02674 while ( (c = ast_walk_contexts(c)) ) { 02675 if (!strcmp(ast_get_context_name(c), context)) 02676 return c; 02677 } 02678 ast_unlock_contexts(); 02679 02680 return NULL; 02681 }
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 1506 of file pbx.c.
References ast_log(), and LOG_WARNING.
Referenced by ast_func_read(), and ast_func_write().
01507 { 01508 char *args = strchr(function, '('); 01509 01510 if (!args) 01511 ast_log(LOG_WARNING, "Function doesn't contain parentheses. Assuming null argument.\n"); 01512 else { 01513 char *p; 01514 *args++ = '\0'; 01515 if ((p = strrchr(args, ')')) ) 01516 *p = '\0'; 01517 else 01518 ast_log(LOG_WARNING, "Can't find trailing parenthesis?\n"); 01519 } 01520 return args; 01521 }
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 4050 of file pbx.c.
References ast_log(), ast_strlen_zero(), LOG_WARNING, lookup_name(), and s.
Referenced by ast_build_timing().
04051 { 04052 int s, e; /* start and ending position */ 04053 unsigned int mask = 0; 04054 04055 /* Check for whole range */ 04056 if (ast_strlen_zero(src) || !strcmp(src, "*")) { 04057 s = 0; 04058 e = max - 1; 04059 } else { 04060 /* Get start and ending position */ 04061 char *c = strchr(src, '-'); 04062 if (c) 04063 *c++ = '\0'; 04064 /* Find the start */ 04065 s = lookup_name(src, names, max); 04066 if (!s) { 04067 ast_log(LOG_WARNING, "Invalid %s '%s', assuming none\n", msg, src); 04068 return 0; 04069 } 04070 s--; 04071 if (c) { /* find end of range */ 04072 e = lookup_name(c, names, max); 04073 if (!e) { 04074 ast_log(LOG_WARNING, "Invalid end %s '%s', assuming none\n", msg, c); 04075 return 0; 04076 } 04077 e--; 04078 } else 04079 e = s; 04080 } 04081 /* Fill the mask. Remember that ranges are cyclic */ 04082 mask = 1 << e; /* initialize with last element */ 04083 while (s != e) { 04084 if (s >= max) { 04085 s = 0; 04086 mask |= (1 << s); 04087 } else { 04088 mask |= (1 << s); 04089 s++; 04090 } 04091 } 04092 return mask; 04093 }
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 4096 of file pbx.c.
References ast_log(), ast_strlen_zero(), LOG_WARNING, and ast_timing::minmask.
Referenced by ast_build_timing().
04097 { 04098 char *e; 04099 int x; 04100 int s1, s2; 04101 int e1, e2; 04102 /* int cth, ctm; */ 04103 04104 /* start disabling all times, fill the fields with 0's, as they may contain garbage */ 04105 memset(i->minmask, 0, sizeof(i->minmask)); 04106 04107 /* 2-minutes per bit, since the mask has only 32 bits :( */ 04108 /* Star is all times */ 04109 if (ast_strlen_zero(times) || !strcmp(times, "*")) { 04110 for (x=0; x<24; x++) 04111 i->minmask[x] = 0x3fffffff; /* 30 bits */ 04112 return; 04113 } 04114 /* Otherwise expect a range */ 04115 e = strchr(times, '-'); 04116 if (!e) { 04117 ast_log(LOG_WARNING, "Time range is not valid. Assuming no restrictions based on time.\n"); 04118 return; 04119 } 04120 *e++ = '\0'; 04121 /* XXX why skip non digits ? */ 04122 while (*e && !isdigit(*e)) 04123 e++; 04124 if (!*e) { 04125 ast_log(LOG_WARNING, "Invalid time range. Assuming no restrictions based on time.\n"); 04126 return; 04127 } 04128 if (sscanf(times, "%d:%d", &s1, &s2) != 2) { 04129 ast_log(LOG_WARNING, "%s isn't a time. Assuming no restrictions based on time.\n", times); 04130 return; 04131 } 04132 if (sscanf(e, "%d:%d", &e1, &e2) != 2) { 04133 ast_log(LOG_WARNING, "%s isn't a time. Assuming no restrictions based on time.\n", e); 04134 return; 04135 } 04136 /* XXX this needs to be optimized */ 04137 #if 1 04138 s1 = s1 * 30 + s2/2; 04139 if ((s1 < 0) || (s1 >= 24*30)) { 04140 ast_log(LOG_WARNING, "%s isn't a valid start time. Assuming no time.\n", times); 04141 return; 04142 } 04143 e1 = e1 * 30 + e2/2; 04144 if ((e1 < 0) || (e1 >= 24*30)) { 04145 ast_log(LOG_WARNING, "%s isn't a valid end time. Assuming no time.\n", e); 04146 return; 04147 } 04148 /* Go through the time and enable each appropriate bit */ 04149 for (x=s1;x != e1;x = (x + 1) % (24 * 30)) { 04150 i->minmask[x/30] |= (1 << (x % 30)); 04151 } 04152 /* Do the last one */ 04153 i->minmask[x/30] |= (1 << (x % 30)); 04154 #else 04155 for (cth=0; cth<24; cth++) { 04156 /* Initialize masks to blank */ 04157 i->minmask[cth] = 0; 04158 for (ctm=0; ctm<30; ctm++) { 04159 if ( 04160 /* First hour with more than one hour */ 04161 (((cth == s1) && (ctm >= s2)) && 04162 ((cth < e1))) 04163 /* Only one hour */ 04164 || (((cth == s1) && (ctm >= s2)) && 04165 ((cth == e1) && (ctm <= e2))) 04166 /* In between first and last hours (more than 2 hours) */ 04167 || ((cth > s1) && 04168 (cth < e1)) 04169 /* Last hour with more than one hour */ 04170 || ((cth > s1) && 04171 ((cth == e1) && (ctm <= e2))) 04172 ) 04173 i->minmask[cth] |= (1 << (ctm / 2)); 04174 } 04175 } 04176 #endif 04177 /* All done */ 04178 return; 04179 }
static int handle_set_global | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3725 of file pbx.c.
References ast_cli(), pbx_builtin_setvar_helper(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03726 { 03727 if (argc != 5) 03728 return RESULT_SHOWUSAGE; 03729 03730 pbx_builtin_setvar_helper(NULL, argv[3], argv[4]); 03731 ast_cli(fd, "\n -- Global variable %s set to %s\n", argv[3], argv[4]); 03732 03733 return RESULT_SUCCESS; 03734 }
static int handle_set_global_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
CLI support for setting global variables.
Definition at line 3713 of file pbx.c.
References ast_cli(), pbx_builtin_setvar_helper(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03714 { 03715 if (argc != 4) 03716 return RESULT_SHOWUSAGE; 03717 03718 pbx_builtin_setvar_helper(NULL, argv[2], argv[3]); 03719 ast_cli(fd, "\n -- Global variable %s set to %s\n", argv[2], argv[3]); 03720 03721 return RESULT_SUCCESS; 03722 }
static int handle_show_application | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3159 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().
03160 { 03161 struct ast_app *a; 03162 int app, no_registered_app = 1; 03163 03164 if (argc < 4) 03165 return RESULT_SHOWUSAGE; 03166 03167 /* ... go through all applications ... */ 03168 AST_LIST_LOCK(&apps); 03169 AST_LIST_TRAVERSE(&apps, a, list) { 03170 /* ... compare this application name with all arguments given 03171 * to 'show application' command ... */ 03172 for (app = 3; app < argc; app++) { 03173 if (!strcasecmp(a->name, argv[app])) { 03174 /* Maximum number of characters added by terminal coloring is 22 */ 03175 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40]; 03176 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL; 03177 int synopsis_size, description_size; 03178 03179 no_registered_app = 0; 03180 03181 if (a->synopsis) 03182 synopsis_size = strlen(a->synopsis) + 23; 03183 else 03184 synopsis_size = strlen("Not available") + 23; 03185 synopsis = alloca(synopsis_size); 03186 03187 if (a->description) 03188 description_size = strlen(a->description) + 23; 03189 else 03190 description_size = strlen("Not available") + 23; 03191 description = alloca(description_size); 03192 03193 if (synopsis && description) { 03194 snprintf(info, 64 + AST_MAX_APP, "\n -= Info about application '%s' =- \n\n", a->name); 03195 term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22); 03196 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 03197 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40); 03198 term_color(synopsis, 03199 a->synopsis ? a->synopsis : "Not available", 03200 COLOR_CYAN, 0, synopsis_size); 03201 term_color(description, 03202 a->description ? a->description : "Not available", 03203 COLOR_CYAN, 0, description_size); 03204 03205 ast_cli(fd,"%s%s%s\n\n%s%s\n", infotitle, syntitle, synopsis, destitle, description); 03206 } else { 03207 /* ... one of our applications, show info ...*/ 03208 ast_cli(fd,"\n -= Info about application '%s' =- \n\n" 03209 "[Synopsis]\n %s\n\n" 03210 "[Description]\n%s\n", 03211 a->name, 03212 a->synopsis ? a->synopsis : "Not available", 03213 a->description ? a->description : "Not available"); 03214 } 03215 } 03216 } 03217 } 03218 AST_LIST_UNLOCK(&apps); 03219 03220 /* we found at least one app? no? */ 03221 if (no_registered_app) { 03222 ast_cli(fd, "Your application(s) is (are) not registered\n"); 03223 return RESULT_FAILURE; 03224 } 03225 03226 return RESULT_SUCCESS; 03227 }
static int handle_show_application_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3089 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().
03090 { 03091 struct ast_app *a; 03092 int app, no_registered_app = 1; 03093 03094 if (argc < 3) 03095 return RESULT_SHOWUSAGE; 03096 03097 /* ... go through all applications ... */ 03098 AST_LIST_LOCK(&apps); 03099 AST_LIST_TRAVERSE(&apps, a, list) { 03100 /* ... compare this application name with all arguments given 03101 * to 'show application' command ... */ 03102 for (app = 2; app < argc; app++) { 03103 if (!strcasecmp(a->name, argv[app])) { 03104 /* Maximum number of characters added by terminal coloring is 22 */ 03105 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40]; 03106 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL; 03107 int synopsis_size, description_size; 03108 03109 no_registered_app = 0; 03110 03111 if (a->synopsis) 03112 synopsis_size = strlen(a->synopsis) + 23; 03113 else 03114 synopsis_size = strlen("Not available") + 23; 03115 synopsis = alloca(synopsis_size); 03116 03117 if (a->description) 03118 description_size = strlen(a->description) + 23; 03119 else 03120 description_size = strlen("Not available") + 23; 03121 description = alloca(description_size); 03122 03123 if (synopsis && description) { 03124 snprintf(info, 64 + AST_MAX_APP, "\n -= Info about application '%s' =- \n\n", a->name); 03125 term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22); 03126 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 03127 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40); 03128 term_color(synopsis, 03129 a->synopsis ? a->synopsis : "Not available", 03130 COLOR_CYAN, 0, synopsis_size); 03131 term_color(description, 03132 a->description ? a->description : "Not available", 03133 COLOR_CYAN, 0, description_size); 03134 03135 ast_cli(fd,"%s%s%s\n\n%s%s\n", infotitle, syntitle, synopsis, destitle, description); 03136 } else { 03137 /* ... one of our applications, show info ...*/ 03138 ast_cli(fd,"\n -= Info about application '%s' =- \n\n" 03139 "[Synopsis]\n %s\n\n" 03140 "[Description]\n%s\n", 03141 a->name, 03142 a->synopsis ? a->synopsis : "Not available", 03143 a->description ? a->description : "Not available"); 03144 } 03145 } 03146 } 03147 } 03148 AST_LIST_UNLOCK(&apps); 03149 03150 /* we found at least one app? no? */ 03151 if (no_registered_app) { 03152 ast_cli(fd, "Your application(s) is (are) not registered\n"); 03153 return RESULT_FAILURE; 03154 } 03155 03156 return RESULT_SUCCESS; 03157 }
static int handle_show_applications | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3354 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.
03355 { 03356 struct ast_app *a; 03357 int like = 0, describing = 0; 03358 int total_match = 0; /* Number of matches in like clause */ 03359 int total_apps = 0; /* Number of apps registered */ 03360 03361 AST_LIST_LOCK(&apps); 03362 03363 if (AST_LIST_EMPTY(&apps)) { 03364 ast_cli(fd, "There are no registered applications\n"); 03365 AST_LIST_UNLOCK(&apps); 03366 return -1; 03367 } 03368 03369 /* core list applications like <keyword> */ 03370 if ((argc == 5) && (!strcmp(argv[3], "like"))) { 03371 like = 1; 03372 } else if ((argc > 4) && (!strcmp(argv[3], "describing"))) { 03373 describing = 1; 03374 } 03375 03376 /* core list applications describing <keyword1> [<keyword2>] [...] */ 03377 if ((!like) && (!describing)) { 03378 ast_cli(fd, " -= Registered Asterisk Applications =-\n"); 03379 } else { 03380 ast_cli(fd, " -= Matching Asterisk Applications =-\n"); 03381 } 03382 03383 AST_LIST_TRAVERSE(&apps, a, list) { 03384 int printapp = 0; 03385 total_apps++; 03386 if (like) { 03387 if (strcasestr(a->name, argv[4])) { 03388 printapp = 1; 03389 total_match++; 03390 } 03391 } else if (describing) { 03392 if (a->description) { 03393 /* Match all words on command line */ 03394 int i; 03395 printapp = 1; 03396 for (i = 4; i < argc; i++) { 03397 if (!strcasestr(a->description, argv[i])) { 03398 printapp = 0; 03399 } else { 03400 total_match++; 03401 } 03402 } 03403 } 03404 } else { 03405 printapp = 1; 03406 } 03407 03408 if (printapp) { 03409 ast_cli(fd," %20s: %s\n", a->name, a->synopsis ? a->synopsis : "<Synopsis not available>"); 03410 } 03411 } 03412 if ((!like) && (!describing)) { 03413 ast_cli(fd, " -= %d Applications Registered =-\n",total_apps); 03414 } else { 03415 ast_cli(fd, " -= %d Applications Matching =-\n",total_match); 03416 } 03417 03418 AST_LIST_UNLOCK(&apps); 03419 03420 return RESULT_SUCCESS; 03421 }
static int handle_show_applications_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3286 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.
03287 { 03288 struct ast_app *a; 03289 int like = 0, describing = 0; 03290 int total_match = 0; /* Number of matches in like clause */ 03291 int total_apps = 0; /* Number of apps registered */ 03292 03293 AST_LIST_LOCK(&apps); 03294 03295 if (AST_LIST_EMPTY(&apps)) { 03296 ast_cli(fd, "There are no registered applications\n"); 03297 AST_LIST_UNLOCK(&apps); 03298 return -1; 03299 } 03300 03301 /* show applications like <keyword> */ 03302 if ((argc == 4) && (!strcmp(argv[2], "like"))) { 03303 like = 1; 03304 } else if ((argc > 3) && (!strcmp(argv[2], "describing"))) { 03305 describing = 1; 03306 } 03307 03308 /* show applications describing <keyword1> [<keyword2>] [...] */ 03309 if ((!like) && (!describing)) { 03310 ast_cli(fd, " -= Registered Asterisk Applications =-\n"); 03311 } else { 03312 ast_cli(fd, " -= Matching Asterisk Applications =-\n"); 03313 } 03314 03315 AST_LIST_TRAVERSE(&apps, a, list) { 03316 int printapp = 0; 03317 total_apps++; 03318 if (like) { 03319 if (strcasestr(a->name, argv[3])) { 03320 printapp = 1; 03321 total_match++; 03322 } 03323 } else if (describing) { 03324 if (a->description) { 03325 /* Match all words on command line */ 03326 int i; 03327 printapp = 1; 03328 for (i = 3; i < argc; i++) { 03329 if (!strcasestr(a->description, argv[i])) { 03330 printapp = 0; 03331 } else { 03332 total_match++; 03333 } 03334 } 03335 } 03336 } else { 03337 printapp = 1; 03338 } 03339 03340 if (printapp) { 03341 ast_cli(fd," %20s: %s\n", a->name, a->synopsis ? a->synopsis : "<Synopsis not available>"); 03342 } 03343 } 03344 if ((!like) && (!describing)) { 03345 ast_cli(fd, " -= %d Applications Registered =-\n",total_apps); 03346 } else { 03347 ast_cli(fd, " -= %d Applications Matching =-\n",total_match); 03348 } 03349 03350 AST_LIST_UNLOCK(&apps); 03351 03352 return RESULT_SUCCESS; 03353 }
static int handle_show_dialplan | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3640 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().
03641 { 03642 char *exten = NULL, *context = NULL; 03643 /* Variables used for different counters */ 03644 struct dialplan_counters counters; 03645 03646 const char *incstack[AST_PBX_MAX_STACK]; 03647 memset(&counters, 0, sizeof(counters)); 03648 03649 if (argc != 2 && argc != 3) 03650 return RESULT_SHOWUSAGE; 03651 03652 /* we obtain [exten@]context? if yes, split them ... */ 03653 if (argc == 3) { 03654 if (strchr(argv[2], '@')) { /* split into exten & context */ 03655 context = ast_strdupa(argv[2]); 03656 exten = strsep(&context, "@"); 03657 /* change empty strings to NULL */ 03658 if (ast_strlen_zero(exten)) 03659 exten = NULL; 03660 } else { /* no '@' char, only context given */ 03661 context = argv[2]; 03662 } 03663 if (ast_strlen_zero(context)) 03664 context = NULL; 03665 } 03666 /* else Show complete dial plan, context and exten are NULL */ 03667 show_dialplan_helper(fd, context, exten, &counters, NULL, 0, incstack); 03668 03669 /* check for input failure and throw some error messages */ 03670 if (context && !counters.context_existence) { 03671 ast_cli(fd, "There is no existence of '%s' context\n", context); 03672 return RESULT_FAILURE; 03673 } 03674 03675 if (exten && !counters.extension_existence) { 03676 if (context) 03677 ast_cli(fd, "There is no existence of %s@%s extension\n", 03678 exten, context); 03679 else 03680 ast_cli(fd, 03681 "There is no existence of '%s' extension in all contexts\n", 03682 exten); 03683 return RESULT_FAILURE; 03684 } 03685 03686 ast_cli(fd,"-= %d %s (%d %s) in %d %s. =-\n", 03687 counters.total_exten, counters.total_exten == 1 ? "extension" : "extensions", 03688 counters.total_prio, counters.total_prio == 1 ? "priority" : "priorities", 03689 counters.total_context, counters.total_context == 1 ? "context" : "contexts"); 03690 03691 /* everything ok */ 03692 return RESULT_SUCCESS; 03693 }
static int handle_show_function | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1357 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().
01358 { 01359 struct ast_custom_function *acf; 01360 /* Maximum number of characters added by terminal coloring is 22 */ 01361 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40]; 01362 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL; 01363 char stxtitle[40], *syntax = NULL; 01364 int synopsis_size, description_size, syntax_size; 01365 01366 if (argc < 4) 01367 return RESULT_SHOWUSAGE; 01368 01369 if (!(acf = ast_custom_function_find(argv[3]))) { 01370 ast_cli(fd, "No function by that name registered.\n"); 01371 return RESULT_FAILURE; 01372 01373 } 01374 01375 if (acf->synopsis) 01376 synopsis_size = strlen(acf->synopsis) + 23; 01377 else 01378 synopsis_size = strlen("Not available") + 23; 01379 synopsis = alloca(synopsis_size); 01380 01381 if (acf->desc) 01382 description_size = strlen(acf->desc) + 23; 01383 else 01384 description_size = strlen("Not available") + 23; 01385 description = alloca(description_size); 01386 01387 if (acf->syntax) 01388 syntax_size = strlen(acf->syntax) + 23; 01389 else 01390 syntax_size = strlen("Not available") + 23; 01391 syntax = alloca(syntax_size); 01392 01393 snprintf(info, 64 + AST_MAX_APP, "\n -= Info about function '%s' =- \n\n", acf->name); 01394 term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22); 01395 term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40); 01396 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 01397 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40); 01398 term_color(syntax, 01399 acf->syntax ? acf->syntax : "Not available", 01400 COLOR_CYAN, 0, syntax_size); 01401 term_color(synopsis, 01402 acf->synopsis ? acf->synopsis : "Not available", 01403 COLOR_CYAN, 0, synopsis_size); 01404 term_color(description, 01405 acf->desc ? acf->desc : "Not available", 01406 COLOR_CYAN, 0, description_size); 01407 01408 ast_cli(fd,"%s%s%s\n\n%s%s\n\n%s%s\n", infotitle, stxtitle, syntax, syntitle, synopsis, destitle, description); 01409 01410 return RESULT_SUCCESS; 01411 }
static int handle_show_function_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1301 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().
01302 { 01303 struct ast_custom_function *acf; 01304 /* Maximum number of characters added by terminal coloring is 22 */ 01305 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40]; 01306 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL; 01307 char stxtitle[40], *syntax = NULL; 01308 int synopsis_size, description_size, syntax_size; 01309 01310 if (argc < 3) 01311 return RESULT_SHOWUSAGE; 01312 01313 if (!(acf = ast_custom_function_find(argv[2]))) { 01314 ast_cli(fd, "No function by that name registered.\n"); 01315 return RESULT_FAILURE; 01316 01317 } 01318 01319 if (acf->synopsis) 01320 synopsis_size = strlen(acf->synopsis) + 23; 01321 else 01322 synopsis_size = strlen("Not available") + 23; 01323 synopsis = alloca(synopsis_size); 01324 01325 if (acf->desc) 01326 description_size = strlen(acf->desc) + 23; 01327 else 01328 description_size = strlen("Not available") + 23; 01329 description = alloca(description_size); 01330 01331 if (acf->syntax) 01332 syntax_size = strlen(acf->syntax) + 23; 01333 else 01334 syntax_size = strlen("Not available") + 23; 01335 syntax = alloca(syntax_size); 01336 01337 snprintf(info, 64 + AST_MAX_APP, "\n -= Info about function '%s' =- \n\n", acf->name); 01338 term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22); 01339 term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40); 01340 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 01341 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40); 01342 term_color(syntax, 01343 acf->syntax ? acf->syntax : "Not available", 01344 COLOR_CYAN, 0, syntax_size); 01345 term_color(synopsis, 01346 acf->synopsis ? acf->synopsis : "Not available", 01347 COLOR_CYAN, 0, synopsis_size); 01348 term_color(description, 01349 acf->desc ? acf->desc : "Not available", 01350 COLOR_CYAN, 0, description_size); 01351 01352 ast_cli(fd,"%s%s%s\n\n%s%s\n\n%s%s\n", infotitle, stxtitle, syntax, syntitle, synopsis, destitle, description); 01353 01354 return RESULT_SUCCESS; 01355 }
static int handle_show_functions | ( | 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 == 5 && (!strcmp(argv[3], "like")) ) { 01280 like = 1; 01281 } else if (argc != 3) { 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[4])) { 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_functions_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1246 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.
01247 { 01248 struct ast_custom_function *acf; 01249 int count_acf = 0; 01250 int like = 0; 01251 01252 if (argc == 4 && (!strcmp(argv[2], "like")) ) { 01253 like = 1; 01254 } else if (argc != 2) { 01255 return RESULT_SHOWUSAGE; 01256 } 01257 01258 ast_cli(fd, "%s Custom Functions:\n--------------------------------------------------------------------------------\n", like ? "Matching" : "Installed"); 01259 01260 AST_LIST_LOCK(&acf_root); 01261 AST_LIST_TRAVERSE(&acf_root, acf, acflist) { 01262 if (!like || strstr(acf->name, argv[3])) { 01263 count_acf++; 01264 ast_cli(fd, "%-20.20s %-35.35s %s\n", acf->name, acf->syntax, acf->synopsis); 01265 } 01266 } 01267 AST_LIST_UNLOCK(&acf_root); 01268 01269 ast_cli(fd, "%d %scustom functions installed.\n", count_acf, like ? "matching " : ""); 01270 01271 return RESULT_SUCCESS; 01272 }
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 3696 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.
03697 { 03698 int i = 0; 03699 struct ast_var_t *newvariable; 03700 03701 ast_mutex_lock(&globalslock); 03702 AST_LIST_TRAVERSE (&globals, newvariable, entries) { 03703 i++; 03704 ast_cli(fd, " %s=%s\n", ast_var_name(newvariable), ast_var_value(newvariable)); 03705 } 03706 ast_mutex_unlock(&globalslock); 03707 ast_cli(fd, "\n -- %d variables\n", i); 03708 03709 return RESULT_SUCCESS; 03710 }
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 3230 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.
03231 { 03232 struct ast_hint *hint; 03233 int num = 0; 03234 int watchers; 03235 struct ast_state_cb *watcher; 03236 03237 if (AST_LIST_EMPTY(&hints)) { 03238 ast_cli(fd, "There are no registered dialplan hints\n"); 03239 return RESULT_SUCCESS; 03240 } 03241 /* ... we have hints ... */ 03242 ast_cli(fd, "\n -= Registered Asterisk Dial Plan Hints =-\n"); 03243 AST_LIST_LOCK(&hints); 03244 AST_LIST_TRAVERSE(&hints, hint, list) { 03245 watchers = 0; 03246 for (watcher = hint->callbacks; watcher; watcher = watcher->next) 03247 watchers++; 03248 ast_cli(fd, " %20s@%-20.20s: %-20.20s State:%-15.15s Watchers %2d\n", 03249 ast_get_extension_name(hint->exten), 03250 ast_get_context_name(ast_get_extension_context(hint->exten)), 03251 ast_get_extension_app(hint->exten), 03252 ast_extension_state2str(hint->laststate), watchers); 03253 num++; 03254 } 03255 ast_cli(fd, "----------------\n"); 03256 ast_cli(fd, "- %d hints registered\n", num); 03257 AST_LIST_UNLOCK(&hints); 03258 return RESULT_SUCCESS; 03259 }
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 3262 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.
03263 { 03264 struct ast_switch *sw; 03265 03266 AST_LIST_LOCK(&switches); 03267 03268 if (AST_LIST_EMPTY(&switches)) { 03269 AST_LIST_UNLOCK(&switches); 03270 ast_cli(fd, "There are no registered alternative switches\n"); 03271 return RESULT_SUCCESS; 03272 } 03273 03274 ast_cli(fd, "\n -= Registered Asterisk Alternative Switches =-\n"); 03275 AST_LIST_TRAVERSE(&switches, sw, list) 03276 ast_cli(fd, "%s: %s\n", sw->name, sw->description); 03277 03278 AST_LIST_UNLOCK(&switches); 03279 03280 return RESULT_SUCCESS; 03281 }
static int include_valid | ( | struct ast_include * | i | ) | [inline, static] |
Definition at line 578 of file pbx.c.
References ast_check_timing(), ast_include::hastime, and ast_include::timing.
00579 { 00580 if (!i->hastime) 00581 return 1; 00582 00583 return ast_check_timing(&(i->timing)); 00584 }
static int increase_call_count | ( | const struct ast_channel * | c | ) | [static] |
Definition at line 2552 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().
02553 { 02554 int failed = 0; 02555 double curloadavg; 02556 ast_mutex_lock(&maxcalllock); 02557 if (option_maxcalls) { 02558 if (countcalls >= option_maxcalls) { 02559 ast_log(LOG_NOTICE, "Maximum call limit of %d calls exceeded by '%s'!\n", option_maxcalls, c->name); 02560 failed = -1; 02561 } 02562 } 02563 if (option_maxload) { 02564 getloadavg(&curloadavg, 1); 02565 if (curloadavg >= option_maxload) { 02566 ast_log(LOG_NOTICE, "Maximum loadavg limit of %f load exceeded by '%s' (currently %f)!\n", option_maxload, c->name, curloadavg); 02567 failed = -1; 02568 } 02569 } 02570 if (!failed) 02571 countcalls++; 02572 ast_mutex_unlock(&maxcalllock); 02573 02574 return failed; 02575 }
int load_pbx | ( | void | ) |
Provided by pbx.c
Definition at line 6059 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().
06060 { 06061 int x; 06062 06063 /* Initialize the PBX */ 06064 if (option_verbose) { 06065 ast_verbose( "Asterisk PBX Core Initializing\n"); 06066 ast_verbose( "Registering builtin applications:\n"); 06067 } 06068 ast_cli_register_multiple(pbx_cli, sizeof(pbx_cli) / sizeof(struct ast_cli_entry)); 06069 06070 /* Register builtin applications */ 06071 for (x=0; x<sizeof(builtins) / sizeof(struct pbx_builtin); x++) { 06072 if (option_verbose) 06073 ast_verbose( VERBOSE_PREFIX_1 "[%s]\n", builtins[x].name); 06074 if (ast_register_application(builtins[x].name, builtins[x].execute, builtins[x].synopsis, builtins[x].description)) { 06075 ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name); 06076 return -1; 06077 } 06078 } 06079 return 0; 06080 }
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 4032 of file pbx.c.
Referenced by get_range().
04033 { 04034 int i; 04035 04036 if (names) { 04037 for (i = 0; names[i]; i++) { 04038 if (!strcasecmp(s, names[i])) 04039 return i+1; 04040 } 04041 } else if (sscanf(s, "%d", &i) == 1 && i >= 1 && i <= max) { 04042 return i; 04043 } 04044 return 0; /* error return */ 04045 }
static int matchcid | ( | const char * | cidpattern, | |
const char * | callerid | |||
) | [static] |
Definition at line 910 of file pbx.c.
References ast_extension_match(), and ast_strlen_zero().
Referenced by pbx_find_extension().
00911 { 00912 /* If the Caller*ID pattern is empty, then we're matching NO Caller*ID, so 00913 failing to get a number should count as a match, otherwise not */ 00914 00915 if (ast_strlen_zero(callerid)) 00916 return ast_strlen_zero(cidpattern) ? 1 : 0; 00917 00918 return ast_extension_match(cidpattern, callerid); 00919 }
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 1062 of file pbx.c.
Referenced by pbx_retrieve_variable(), and pbx_substitute_variables_helper_full().
01063 { 01064 int parens=0; 01065 01066 *offset = 0; 01067 *length = INT_MAX; 01068 *isfunc = 0; 01069 for (; *var; var++) { 01070 if (*var == '(') { 01071 (*isfunc)++; 01072 parens++; 01073 } else if (*var == ')') { 01074 parens--; 01075 } else if (*var == ':' && parens == 0) { 01076 *var++ = '\0'; 01077 sscanf(var, "%d:%d", offset, length); 01078 return 1; /* offset:length valid */ 01079 } 01080 } 01081 return 0; 01082 }
void pbx_builtin_clear_globals | ( | void | ) |
Definition at line 5961 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().
05962 { 05963 struct ast_var_t *vardata; 05964 05965 ast_mutex_lock(&globalslock); 05966 while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries))) 05967 ast_var_delete(vardata); 05968 ast_mutex_unlock(&globalslock); 05969 }
const char* pbx_builtin_getvar_helper | ( | struct ast_channel * | chan, | |
const char * | name | |||
) |
Definition at line 5761 of file pbx.c.
References AST_LIST_TRAVERSE, ast_mutex_lock(), ast_mutex_unlock(), ast_var_name(), ast_var_value(), and ast_channel::varshead.
Referenced by __login_exec(), _macro_exec(), _while_exec(), acf_iaxvar_read(), agent_hangup(), agent_read(), agentmonitoroutgoing_exec(), array(), ast_bridge_call(), ast_feature_interpret(), ast_monitor_stop(), ast_park_call(), 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(), hash_read(), iax2_exec(), import_ch(), leave_voicemail(), local_hangup(), misdn_answer(), misdn_hangup(), morsecode_exec(), notify_new_message(), oh323_call(), oh323_hangup(), pickup_by_mark(), pop_exec(), queue_exec(), real_ctx(), retrydial_exec(), return_exec(), run_agi(), rxfax_exec(), set_config_flags(), sip_addheader(), try_calling(), try_suggested_sip_codec(), txfax_exec(), wait_for_answer(), zt_call(), and zt_hangup().
05762 { 05763 struct ast_var_t *variables; 05764 const char *ret = NULL; 05765 int i; 05766 struct varshead *places[2] = { NULL, &globals }; 05767 05768 if (!name) 05769 return NULL; 05770 if (chan) 05771 places[0] = &chan->varshead; 05772 05773 for (i = 0; i < 2; i++) { 05774 if (!places[i]) 05775 continue; 05776 if (places[i] == &globals) 05777 ast_mutex_lock(&globalslock); 05778 AST_LIST_TRAVERSE(places[i], variables, entries) { 05779 if (!strcmp(name, ast_var_name(variables))) { 05780 ret = ast_var_value(variables); 05781 break; 05782 } 05783 } 05784 if (places[i] == &globals) 05785 ast_mutex_unlock(&globalslock); 05786 if (ret) 05787 break; 05788 } 05789 05790 return ret; 05791 }
static int pbx_builtin_gotoif | ( | struct ast_channel * | , | |
void * | ||||
) | [static] |
Definition at line 5981 of file pbx.c.
References ast_log(), ast_strdupa, ast_strlen_zero(), LOG_WARNING, pbx_builtin_goto(), pbx_checkcondition(), and strsep().
05982 { 05983 char *condition, *branch1, *branch2, *branch; 05984 int rc; 05985 char *stringp; 05986 05987 if (ast_strlen_zero(data)) { 05988 ast_log(LOG_WARNING, "Ignoring, since there is no variable to check\n"); 05989 return 0; 05990 } 05991 05992 stringp = ast_strdupa(data); 05993 condition = strsep(&stringp,"?"); 05994 branch1 = strsep(&stringp,":"); 05995 branch2 = strsep(&stringp,""); 05996 branch = pbx_checkcondition(condition) ? branch1 : branch2; 05997 05998 if (ast_strlen_zero(branch)) { 05999 if (option_debug) 06000 ast_log(LOG_DEBUG, "Not taking any branch\n"); 06001 return 0; 06002 } 06003 06004 rc = pbx_builtin_goto(chan, branch); 06005 06006 return rc; 06007 }
int pbx_builtin_importvar | ( | struct ast_channel * | , | |
void * | ||||
) | [static] |
Definition at line 5900 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.
05901 { 05902 char *name; 05903 char *value; 05904 char *channel; 05905 char tmp[VAR_BUF_SIZE]=""; 05906 05907 if (ast_strlen_zero(data)) { 05908 ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n"); 05909 return 0; 05910 } 05911 05912 value = ast_strdupa(data); 05913 name = strsep(&value,"="); 05914 channel = strsep(&value,"|"); 05915 if (channel && value && name) { /*! \todo XXX should do !ast_strlen_zero(..) of the args ? */ 05916 struct ast_channel *chan2 = ast_get_channel_by_name_locked(channel); 05917 if (chan2) { 05918 char *s = alloca(strlen(value) + 4); 05919 if (s) { 05920 sprintf(s, "${%s}", value); 05921 pbx_substitute_variables_helper(chan2, s, tmp, sizeof(tmp) - 1); 05922 } 05923 ast_channel_unlock(chan2); 05924 } 05925 pbx_builtin_setvar_helper(chan, name, tmp); 05926 } 05927 05928 return(0); 05929 }
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 5793 of file pbx.c.
References 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, ast_channel::varshead, and VERBOSE_PREFIX_2.
Referenced by acf_odbc_read(), acf_odbc_write(), and gosub_exec().
05794 { 05795 struct ast_var_t *newvariable; 05796 struct varshead *headp; 05797 05798 if (name[strlen(name)-1] == ')') { 05799 char *function = ast_strdupa(name); 05800 05801 ast_log(LOG_WARNING, "Cannot push a value onto a function\n"); 05802 ast_func_write(chan, function, value); 05803 return; 05804 } 05805 05806 headp = (chan) ? &chan->varshead : &globals; 05807 05808 if (value) { 05809 if ((option_verbose > 1) && (headp == &globals)) 05810 ast_verbose(VERBOSE_PREFIX_2 "Setting global variable '%s' to '%s'\n", name, value); 05811 newvariable = ast_var_assign(name, value); 05812 if (headp == &globals) 05813 ast_mutex_lock(&globalslock); 05814 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 05815 if (headp == &globals) 05816 ast_mutex_unlock(&globalslock); 05817 } 05818 }
static int pbx_builtin_saycharacters | ( | struct ast_channel * | , | |
void * | ||||
) | [static] |
Definition at line 6041 of file pbx.c.
References ast_say_character_str().
06042 { 06043 int res = 0; 06044 06045 if (data) 06046 res = ast_say_character_str(chan, data, "", chan->language); 06047 return res; 06048 }
static int pbx_builtin_saydigits | ( | struct ast_channel * | , | |
void * | ||||
) | [static] |
Definition at line 6032 of file pbx.c.
References ast_say_digit_str().
06033 { 06034 int res = 0; 06035 06036 if (data) 06037 res = ast_say_digit_str(chan, data, "", chan->language); 06038 return res; 06039 }
static int pbx_builtin_saynumber | ( | struct ast_channel * | , | |
void * | ||||
) | [static] |
Definition at line 6009 of file pbx.c.
References ast_log(), ast_say_number(), ast_strlen_zero(), LOG_WARNING, and strsep().
06010 { 06011 char tmp[256]; 06012 char *number = tmp; 06013 char *options; 06014 06015 if (ast_strlen_zero(data)) { 06016 ast_log(LOG_WARNING, "SayNumber requires an argument (number)\n"); 06017 return -1; 06018 } 06019 ast_copy_string(tmp, data, sizeof(tmp)); 06020 strsep(&number, "|"); 06021 options = strsep(&number, "|"); 06022 if (options) { 06023 if ( strcasecmp(options, "f") && strcasecmp(options,"m") && 06024 strcasecmp(options, "c") && strcasecmp(options, "n") ) { 06025 ast_log(LOG_WARNING, "SayNumber gender option is either 'f', 'm', 'c' or 'n'\n"); 06026 return -1; 06027 } 06028 } 06029 return ast_say_number(chan, atoi(tmp), "", chan->language, options); 06030 }
static int pbx_builtin_sayphonetic | ( | struct ast_channel * | , | |
void * | ||||
) | [static] |
Definition at line 6050 of file pbx.c.
References ast_say_phonetic_str().
06051 { 06052 int res = 0; 06053 06054 if (data) 06055 res = ast_say_phonetic_str(chan, data, "", chan->language); 06056 return res; 06057 }
int pbx_builtin_serialize_variables | ( | struct ast_channel * | chan, | |
char * | buf, | |||
size_t | size | |||
) |
Definition at line 5734 of file pbx.c.
References ast_build_string(), 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().
05735 { 05736 struct ast_var_t *variables; 05737 const char *var, *val; 05738 int total = 0; 05739 05740 if (!chan) 05741 return 0; 05742 05743 memset(buf, 0, size); 05744 05745 AST_LIST_TRAVERSE(&chan->varshead, variables, entries) { 05746 if ((var=ast_var_name(variables)) && (val=ast_var_value(variables)) 05747 /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */ 05748 ) { 05749 if (ast_build_string(&buf, &size, "%s=%s\n", var, val)) { 05750 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n"); 05751 break; 05752 } else 05753 total++; 05754 } else 05755 break; 05756 } 05757 05758 return total; 05759 }
static int pbx_builtin_setglobalvar | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 5932 of file pbx.c.
References ast_log(), ast_strlen_zero(), LOG_WARNING, pbx_builtin_setvar_helper(), and strsep().
05933 { 05934 char *name; 05935 char *stringp = data; 05936 static int dep_warning = 0; 05937 05938 if (ast_strlen_zero(data)) { 05939 ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n"); 05940 return 0; 05941 } 05942 05943 name = strsep(&stringp, "="); 05944 05945 if (!dep_warning) { 05946 dep_warning = 1; 05947 ast_log(LOG_WARNING, "SetGlobalVar is deprecated. Please use Set(GLOBAL(%s)=%s) instead.\n", name, stringp); 05948 } 05949 05950 /*! \todo XXX watch out, leading whitespace ? */ 05951 pbx_builtin_setvar_helper(NULL, name, stringp); 05952 05953 return(0); 05954 }
int pbx_builtin_setvar | ( | struct ast_channel * | , | |
void * | ||||
) |
Definition at line 5865 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().
05866 { 05867 char *name, *value, *mydata; 05868 int argc; 05869 char *argv[24]; /* this will only support a maximum of 24 variables being set in a single operation */ 05870 int global = 0; 05871 int x; 05872 05873 if (ast_strlen_zero(data)) { 05874 ast_log(LOG_WARNING, "Set requires at least one variable name/value pair.\n"); 05875 return 0; 05876 } 05877 05878 mydata = ast_strdupa(data); 05879 argc = ast_app_separate_args(mydata, '|', argv, sizeof(argv) / sizeof(argv[0])); 05880 05881 /* check for a trailing flags argument */ 05882 if ((argc > 1) && !strchr(argv[argc-1], '=')) { 05883 argc--; 05884 if (strchr(argv[argc], 'g')) 05885 global = 1; 05886 } 05887 05888 for (x = 0; x < argc; x++) { 05889 name = argv[x]; 05890 if ((value = strchr(name, '='))) { 05891 *value++ = '\0'; 05892 pbx_builtin_setvar_helper((global) ? NULL : chan, name, value); 05893 } else 05894 ast_log(LOG_WARNING, "Ignoring entry '%s' with no = (and not last 'options' entry)\n", name); 05895 } 05896 05897 return(0); 05898 }
void pbx_builtin_setvar_helper | ( | struct ast_channel * | chan, | |
const char * | name, | |||
const char * | value | |||
) |
Definition at line 5820 of file pbx.c.
References 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, ast_channel::varshead, and VERBOSE_PREFIX_2.
Referenced by __oh323_new(), _macro_exec(), _while_exec(), acf_iaxvar_write(), 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_feature_request_and_dial(), ast_iax2_new(), ast_monitor_start(), ast_set_variables(), background_detect_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(), hash_read(), hash_write(), 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_extension_helper(), pbx_load_config(), phase_e_handler(), 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_station_exec(), sla_trunk_exec(), socket_process(), speech_create(), ss_thread(), start_monitor_exec(), system_exec_helper(), transfer_exec(), try_calling(), tryexec_exec(), upqm_exec(), vm_box_exists(), vm_exec(), vmauthenticate(), zt_handle_dtmfup(), and zt_new().
05821 { 05822 struct ast_var_t *newvariable; 05823 struct varshead *headp; 05824 const char *nametail = name; 05825 05826 /* XXX may need locking on the channel ? */ 05827 if (name[strlen(name)-1] == ')') { 05828 char *function = ast_strdupa(name); 05829 05830 ast_func_write(chan, function, value); 05831 return; 05832 } 05833 05834 headp = (chan) ? &chan->varshead : &globals; 05835 05836 /* For comparison purposes, we have to strip leading underscores */ 05837 if (*nametail == '_') { 05838 nametail++; 05839 if (*nametail == '_') 05840 nametail++; 05841 } 05842 05843 if (headp == &globals) 05844 ast_mutex_lock(&globalslock); 05845 AST_LIST_TRAVERSE (headp, newvariable, entries) { 05846 if (strcasecmp(ast_var_name(newvariable), nametail) == 0) { 05847 /* there is already such a variable, delete it */ 05848 AST_LIST_REMOVE(headp, newvariable, entries); 05849 ast_var_delete(newvariable); 05850 break; 05851 } 05852 } 05853 05854 if (value) { 05855 if ((option_verbose > 1) && (headp == &globals)) 05856 ast_verbose(VERBOSE_PREFIX_2 "Setting global variable '%s' to '%s'\n", name, value); 05857 newvariable = ast_var_assign(name, value); 05858 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 05859 } 05860 05861 if (headp == &globals) 05862 ast_mutex_unlock(&globalslock); 05863 }
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 5971 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().
05972 { 05973 if (ast_strlen_zero(condition)) /* NULL or empty strings are false */ 05974 return 0; 05975 else if (*condition >= '0' && *condition <= '9') /* Numbers are evaluated for truth */ 05976 return atoi(condition); 05977 else /* Strings are true */ 05978 return 1; 05979 }
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 512 of file pbx.c.
References app, ast_channel::appl, ast_cdr_setapp(), ast_check_hangup(), ast_channel::cdr, and ast_channel::data.
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().
00515 { 00516 int res; 00517 00518 const char *saved_c_appl; 00519 const char *saved_c_data; 00520 00521 if (c->cdr && !ast_check_hangup(c)) 00522 ast_cdr_setapp(c->cdr, app->name, data); 00523 00524 /* save channel values */ 00525 saved_c_appl= c->appl; 00526 saved_c_data= c->data; 00527 00528 c->appl = app->name; 00529 c->data = data; 00530 /* XXX remember what to to when we have linked apps to modules */ 00531 if (app->module) { 00532 /* XXX LOCAL_USER_ADD(app->module) */ 00533 } 00534 res = app->execute(c, data); 00535 if (app->module) { 00536 /* XXX LOCAL_USER_REMOVE(app->module) */ 00537 } 00538 /* restore channel values */ 00539 c->appl = saved_c_appl; 00540 c->data = saved_c_data; 00541 return res; 00542 }
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 1777 of file pbx.c.
References ast_exten::app, app, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), 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_builtin_setvar_helper(), 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().
01780 { 01781 struct ast_exten *e; 01782 struct ast_app *app; 01783 int res; 01784 struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */ 01785 char passdata[EXT_DATA_SIZE]; 01786 01787 int matching_action = (action == E_MATCH || action == E_CANMATCH || action == E_MATCHMORE); 01788 01789 ast_mutex_lock(&conlock); 01790 e = pbx_find_extension(c, con, &q, context, exten, priority, label, callerid, action); 01791 if (e) { 01792 if (matching_action) { 01793 ast_mutex_unlock(&conlock); 01794 return -1; /* success, we found it */ 01795 } else if (action == E_FINDLABEL) { /* map the label to a priority */ 01796 res = e->priority; 01797 ast_mutex_unlock(&conlock); 01798 return res; /* the priority we were looking for */ 01799 } else { /* spawn */ 01800 app = pbx_findapp(e->app); 01801 ast_mutex_unlock(&conlock); 01802 if (!app) { 01803 ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority); 01804 return -1; 01805 } 01806 if (c->context != context) 01807 ast_copy_string(c->context, context, sizeof(c->context)); 01808 if (c->exten != exten) 01809 ast_copy_string(c->exten, exten, sizeof(c->exten)); 01810 c->priority = priority; 01811 pbx_substitute_variables(passdata, sizeof(passdata), c, e); 01812 if (option_debug) { 01813 char atmp[80]; 01814 char atmp2[EXT_DATA_SIZE+100]; 01815 ast_log(LOG_DEBUG, "Launching '%s'\n", app->name); 01816 snprintf(atmp, sizeof(atmp), "STACK-%s-%s-%d", context, exten, priority); 01817 snprintf(atmp2, sizeof(atmp2), "%s(\"%s\", \"%s\") %s", 01818 app->name, c->name, passdata, "in new stack"); 01819 pbx_builtin_setvar_helper(c, atmp, atmp2); 01820 } 01821 if (option_verbose > 2) { 01822 char tmp[80], tmp2[80], tmp3[EXT_DATA_SIZE]; 01823 ast_verbose( VERBOSE_PREFIX_3 "Executing [%s@%s:%d] %s(\"%s\", \"%s\") %s\n", 01824 exten, context, priority, 01825 term_color(tmp, app->name, COLOR_BRCYAN, 0, sizeof(tmp)), 01826 term_color(tmp2, c->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)), 01827 term_color(tmp3, passdata, COLOR_BRMAGENTA, 0, sizeof(tmp3)), 01828 "in new stack"); 01829 } 01830 manager_event(EVENT_FLAG_CALL, "Newexten", 01831 "Channel: %s\r\n" 01832 "Context: %s\r\n" 01833 "Extension: %s\r\n" 01834 "Priority: %d\r\n" 01835 "Application: %s\r\n" 01836 "AppData: %s\r\n" 01837 "Uniqueid: %s\r\n", 01838 c->name, c->context, c->exten, c->priority, app->name, passdata, c->uniqueid); 01839 return pbx_exec(c, app, passdata); /* 0 on success, -1 on failure */ 01840 } 01841 } else if (q.swo) { /* not found here, but in another switch */ 01842 ast_mutex_unlock(&conlock); 01843 if (matching_action) 01844 return -1; 01845 else { 01846 if (!q.swo->exec) { 01847 ast_log(LOG_WARNING, "No execution engine for switch %s\n", q.swo->name); 01848 res = -1; 01849 } 01850 return q.swo->exec(c, q.foundcontext ? q.foundcontext : context, exten, priority, callerid, q.data); 01851 } 01852 } else { /* not found anywhere, see what happened */ 01853 ast_mutex_unlock(&conlock); 01854 switch (q.status) { 01855 case STATUS_NO_CONTEXT: 01856 if (!matching_action) 01857 ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", context); 01858 break; 01859 case STATUS_NO_EXTENSION: 01860 if (!matching_action) 01861 ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, context); 01862 break; 01863 case STATUS_NO_PRIORITY: 01864 if (!matching_action) 01865 ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, context); 01866 break; 01867 case STATUS_NO_LABEL: 01868 if (context) 01869 ast_log(LOG_NOTICE, "No such label '%s' in extension '%s' in context '%s'\n", label, exten, context); 01870 break; 01871 default: 01872 if (option_debug) 01873 ast_log(LOG_DEBUG, "Shouldn't happen!\n"); 01874 } 01875 01876 return (matching_action) ? 0 : -1; 01877 } 01878 }
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 937 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(), and pbx_extension_helper().
00941 { 00942 int x, res; 00943 struct ast_context *tmp; 00944 struct ast_exten *e, *eroot; 00945 struct ast_include *i; 00946 struct ast_sw *sw; 00947 00948 /* Initialize status if appropriate */ 00949 if (q->stacklen == 0) { 00950 q->status = STATUS_NO_CONTEXT; 00951 q->swo = NULL; 00952 q->data = NULL; 00953 q->foundcontext = NULL; 00954 } 00955 /* Check for stack overflow */ 00956 if (q->stacklen >= AST_PBX_MAX_STACK) { 00957 ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n"); 00958 return NULL; 00959 } 00960 /* Check first to see if we've already been checked */ 00961 for (x = 0; x < q->stacklen; x++) { 00962 if (!strcasecmp(q->incstack[x], context)) 00963 return NULL; 00964 } 00965 if (bypass) /* bypass means we only look there */ 00966 tmp = bypass; 00967 else { /* look in contexts */ 00968 tmp = NULL; 00969 while ((tmp = ast_walk_contexts(tmp)) ) { 00970 if (!strcmp(tmp->name, context)) 00971 break; 00972 } 00973 if (!tmp) 00974 return NULL; 00975 } 00976 if (q->status < STATUS_NO_EXTENSION) 00977 q->status = STATUS_NO_EXTENSION; 00978 00979 /* scan the list trying to match extension and CID */ 00980 eroot = NULL; 00981 while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) { 00982 int match = extension_match_core(eroot->exten, exten, action); 00983 /* 0 on fail, 1 on match, 2 on earlymatch */ 00984 00985 if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid))) 00986 continue; /* keep trying */ 00987 if (match == 2 && action == E_MATCHMORE) { 00988 /* We match an extension ending in '!'. 00989 * The decision in this case is final and is NULL (no match). 00990 */ 00991 return NULL; 00992 } 00993 /* found entry, now look for the right priority */ 00994 if (q->status < STATUS_NO_PRIORITY) 00995 q->status = STATUS_NO_PRIORITY; 00996 e = NULL; 00997 while ( (e = ast_walk_extension_priorities(eroot, e)) ) { 00998 /* Match label or priority */ 00999 if (action == E_FINDLABEL) { 01000 if (q->status < STATUS_NO_LABEL) 01001 q->status = STATUS_NO_LABEL; 01002 if (label && e->label && !strcmp(label, e->label)) 01003 break; /* found it */ 01004 } else if (e->priority == priority) { 01005 break; /* found it */ 01006 } /* else keep searching */ 01007 } 01008 if (e) { /* found a valid match */ 01009 q->status = STATUS_SUCCESS; 01010 q->foundcontext = context; 01011 return e; 01012 } 01013 } 01014 /* Check alternative switches */ 01015 AST_LIST_TRAVERSE(&tmp->alts, sw, list) { 01016 struct ast_switch *asw = pbx_findswitch(sw->name); 01017 ast_switch_f *aswf = NULL; 01018 char *datap; 01019 01020 if (!asw) { 01021 ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name); 01022 continue; 01023 } 01024 /* Substitute variables now */ 01025 if (sw->eval) 01026 pbx_substitute_variables_helper(chan, sw->data, sw->tmpdata, SWITCH_DATA_LENGTH - 1); 01027 01028 /* equivalent of extension_match_core() at the switch level */ 01029 if (action == E_CANMATCH) 01030 aswf = asw->canmatch; 01031 else if (action == E_MATCHMORE) 01032 aswf = asw->matchmore; 01033 else /* action == E_MATCH */ 01034 aswf = asw->exists; 01035 datap = sw->eval ? sw->tmpdata : sw->data; 01036 res = !aswf ? 0 : aswf(chan, context, exten, priority, callerid, datap); 01037 if (res) { /* Got a match */ 01038 q->swo = asw; 01039 q->data = datap; 01040 q->foundcontext = context; 01041 /* XXX keep status = STATUS_NO_CONTEXT ? */ 01042 return NULL; 01043 } 01044 } 01045 q->incstack[q->stacklen++] = tmp->name; /* Setup the stack */ 01046 /* Now try any includes we have in this context */ 01047 for (i = tmp->includes; i; i = i->next) { 01048 if (include_valid(i)) { 01049 if ((e = pbx_find_extension(chan, bypass, q, i->rname, exten, priority, label, callerid, action))) 01050 return e; 01051 if (q->swo) 01052 return NULL; 01053 } 01054 } 01055 return NULL; 01056 }
struct ast_app* pbx_findapp | ( | const char * | app | ) |
Look up an application.
app | name of the app |
Definition at line 550 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().
00551 { 00552 struct ast_app *tmp; 00553 00554 AST_LIST_LOCK(&apps); 00555 AST_LIST_TRAVERSE(&apps, tmp, list) { 00556 if (!strcasecmp(tmp->name, app)) 00557 break; 00558 } 00559 AST_LIST_UNLOCK(&apps); 00560 00561 return tmp; 00562 }
static struct ast_switch* pbx_findswitch | ( | const char * | sw | ) | [static] |
Definition at line 564 of file pbx.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, and ast_switch::name.
00565 { 00566 struct ast_switch *asw; 00567 00568 AST_LIST_LOCK(&switches); 00569 AST_LIST_TRAVERSE(&switches, asw, list) { 00570 if (!strcasecmp(asw->name, sw)) 00571 break; 00572 } 00573 AST_LIST_UNLOCK(&switches); 00574 00575 return asw; 00576 }
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 1134 of file pbx.c.
References 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, substring(), and ast_channel::varshead.
Referenced by action_getvar(), function_fieldqty(), handle_getvariable(), and pbx_substitute_variables_helper_full().
01135 { 01136 const char not_found = '\0'; 01137 char *tmpvar; 01138 const char *s; /* the result */ 01139 int offset, length; 01140 int i, need_substring; 01141 struct varshead *places[2] = { headp, &globals }; /* list of places where we may look */ 01142 01143 if (c) { 01144 places[0] = &c->varshead; 01145 } 01146 /* 01147 * Make a copy of var because parse_variable_name() modifies the string. 01148 * Then if called directly, we might need to run substring() on the result; 01149 * remember this for later in 'need_substring', 'offset' and 'length' 01150 */ 01151 tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */ 01152 need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */); 01153 01154 /* 01155 * Look first into predefined variables, then into variable lists. 01156 * Variable 's' points to the result, according to the following rules: 01157 * s == ¬_found (set at the beginning) means that we did not find a 01158 * matching variable and need to look into more places. 01159 * If s != ¬_found, s is a valid result string as follows: 01160 * s = NULL if the variable does not have a value; 01161 * you typically do this when looking for an unset predefined variable. 01162 * s = workspace if the result has been assembled there; 01163 * typically done when the result is built e.g. with an snprintf(), 01164 * so we don't need to do an additional copy. 01165 * s != workspace in case we have a string, that needs to be copied 01166 * (the ast_copy_string is done once for all at the end). 01167 * Typically done when the result is already available in some string. 01168 */ 01169 s = ¬_found; /* default value */ 01170 if (c) { /* This group requires a valid channel */ 01171 /* Names with common parts are looked up a piece at a time using strncmp. */ 01172 if (!strncmp(var, "CALL", 4)) { 01173 if (!strncmp(var + 4, "ING", 3)) { 01174 if (!strcmp(var + 7, "PRES")) { /* CALLINGPRES */ 01175 snprintf(workspace, workspacelen, "%d", c->cid.cid_pres); 01176 s = workspace; 01177 } else if (!strcmp(var + 7, "ANI2")) { /* CALLINGANI2 */ 01178 snprintf(workspace, workspacelen, "%d", c->cid.cid_ani2); 01179 s = workspace; 01180 } else if (!strcmp(var + 7, "TON")) { /* CALLINGTON */ 01181 snprintf(workspace, workspacelen, "%d", c->cid.cid_ton); 01182 s = workspace; 01183 } else if (!strcmp(var + 7, "TNS")) { /* CALLINGTNS */ 01184 snprintf(workspace, workspacelen, "%d", c->cid.cid_tns); 01185 s = workspace; 01186 } 01187 } 01188 } else if (!strcmp(var, "HINT")) { 01189 s = ast_get_hint(workspace, workspacelen, NULL, 0, c, c->context, c->exten) ? workspace : NULL; 01190 } else if (!strcmp(var, "HINTNAME")) { 01191 s = ast_get_hint(NULL, 0, workspace, workspacelen, c, c->context, c->exten) ? workspace : NULL; 01192 } else if (!strcmp(var, "EXTEN")) { 01193 s = c->exten; 01194 } else if (!strcmp(var, "CONTEXT")) { 01195 s = c->context; 01196 } else if (!strcmp(var, "PRIORITY")) { 01197 snprintf(workspace, workspacelen, "%d", c->priority); 01198 s = workspace; 01199 } else if (!strcmp(var, "CHANNEL")) { 01200 s = c->name; 01201 } else if (!strcmp(var, "UNIQUEID")) { 01202 s = c->uniqueid; 01203 } else if (!strcmp(var, "HANGUPCAUSE")) { 01204 snprintf(workspace, workspacelen, "%d", c->hangupcause); 01205 s = workspace; 01206 } 01207 } 01208 if (s == ¬_found) { /* look for more */ 01209 if (!strcmp(var, "EPOCH")) { 01210 snprintf(workspace, workspacelen, "%u",(int)time(NULL)); 01211 s = workspace; 01212 } else if (!strcmp(var, "SYSTEMNAME")) { 01213 s = ast_config_AST_SYSTEM_NAME; 01214 } 01215 } 01216 /* if not found, look into chanvars or global vars */ 01217 for (i = 0; s == ¬_found && i < (sizeof(places) / sizeof(places[0])); i++) { 01218 struct ast_var_t *variables; 01219 if (!places[i]) 01220 continue; 01221 if (places[i] == &globals) 01222 ast_mutex_lock(&globalslock); 01223 AST_LIST_TRAVERSE(places[i], variables, entries) { 01224 if (strcasecmp(ast_var_name(variables), var)==0) { 01225 s = ast_var_value(variables); 01226 break; 01227 } 01228 } 01229 if (places[i] == &globals) 01230 ast_mutex_unlock(&globalslock); 01231 } 01232 if (s == ¬_found || s == NULL) 01233 *ret = NULL; 01234 else { 01235 if (s != workspace) 01236 ast_copy_string(workspace, s, workspacelen); 01237 *ret = workspace; 01238 if (need_substring) 01239 *ret = substring(*ret, offset, length, workspace, workspacelen); 01240 } 01241 }
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 2659 of file pbx.c.
References autofallthrough.
Referenced by pbx_load_module().
02660 { 02661 int oldval = autofallthrough; 02662 autofallthrough = newval; 02663 return oldval; 02664 }
static void pbx_substitute_variables | ( | char * | passdata, | |
int | datalen, | |||
struct ast_channel * | c, | |||
struct ast_exten * | e | |||
) | [static] |
Definition at line 1755 of file pbx.c.
References ast_exten::data, and pbx_substitute_variables_helper().
Referenced by pbx_extension_helper().
01756 { 01757 memset(passdata, 0, datalen); 01758 01759 /* No variables or expressions in e->data, so why scan it? */ 01760 if (e->data && !strchr(e->data, '$') && !strstr(e->data,"${") && !strstr(e->data,"$[") && !strstr(e->data,"$(")) { 01761 ast_copy_string(passdata, e->data, datalen); 01762 return; 01763 } 01764 01765 pbx_substitute_variables_helper(c, e->data, passdata, datalen - 1); 01766 }
void pbx_substitute_variables_helper | ( | struct ast_channel * | c, | |
const char * | cp1, | |||
char * | cp2, | |||
int | count | |||
) |
Definition at line 1745 of file pbx.c.
References pbx_substitute_variables_helper_full(), and ast_channel::varshead.
Referenced by _macro_exec(), acf_odbc_read(), acf_odbc_write(), 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(), rpt_exec(), sendpage(), try_calling(), and tryexec_exec().
01746 { 01747 pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count); 01748 }
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 1552 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().
01553 { 01554 /* Substitutes variables into cp2, based on string cp1, and assuming cp2 to be 01555 zero-filled */ 01556 char *cp4; 01557 const char *tmp, *whereweare; 01558 int length, offset, offset2, isfunction; 01559 char *workspace = NULL; 01560 char *ltmp = NULL, *var = NULL; 01561 char *nextvar, *nextexp, *nextthing; 01562 char *vars, *vare; 01563 int pos, brackets, needsub, len; 01564 01565 whereweare=tmp=cp1; 01566 while (!ast_strlen_zero(whereweare) && count) { 01567 /* Assume we're copying the whole remaining string */ 01568 pos = strlen(whereweare); 01569 nextvar = NULL; 01570 nextexp = NULL; 01571 nextthing = strchr(whereweare, '$'); 01572 if (nextthing) { 01573 switch(nextthing[1]) { 01574 case '{': 01575 nextvar = nextthing; 01576 pos = nextvar - whereweare; 01577 break; 01578 case '[': 01579 nextexp = nextthing; 01580 pos = nextexp - whereweare; 01581 break; 01582 } 01583 } 01584 01585 if (pos) { 01586 /* Can't copy more than 'count' bytes */ 01587 if (pos > count) 01588 pos = count; 01589 01590 /* Copy that many bytes */ 01591 memcpy(cp2, whereweare, pos); 01592 01593 count -= pos; 01594 cp2 += pos; 01595 whereweare += pos; 01596 } 01597 01598 if (nextvar) { 01599 /* We have a variable. Find the start and end, and determine 01600 if we are going to have to recursively call ourselves on the 01601 contents */ 01602 vars = vare = nextvar + 2; 01603 brackets = 1; 01604 needsub = 0; 01605 01606 /* Find the end of it */ 01607 while (brackets && *vare) { 01608 if ((vare[0] == '$') && (vare[1] == '{')) { 01609 needsub++; 01610 } else if (vare[0] == '{') { 01611 brackets++; 01612 } else if (vare[0] == '}') { 01613 brackets--; 01614 } else if ((vare[0] == '$') && (vare[1] == '[')) 01615 needsub++; 01616 vare++; 01617 } 01618 if (brackets) 01619 ast_log(LOG_NOTICE, "Error in extension logic (missing '}')\n"); 01620 len = vare - vars - 1; 01621 01622 /* Skip totally over variable string */ 01623 whereweare += (len + 3); 01624 01625 if (!var) 01626 var = alloca(VAR_BUF_SIZE); 01627 01628 /* Store variable name (and truncate) */ 01629 ast_copy_string(var, vars, len + 1); 01630 01631 /* Substitute if necessary */ 01632 if (needsub) { 01633 if (!ltmp) 01634 ltmp = alloca(VAR_BUF_SIZE); 01635 01636 memset(ltmp, 0, VAR_BUF_SIZE); 01637 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1); 01638 vars = ltmp; 01639 } else { 01640 vars = var; 01641 } 01642 01643 if (!workspace) 01644 workspace = alloca(VAR_BUF_SIZE); 01645 01646 workspace[0] = '\0'; 01647 01648 parse_variable_name(vars, &offset, &offset2, &isfunction); 01649 if (isfunction) { 01650 /* Evaluate function */ 01651 if (c || !headp) 01652 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 01653 else { 01654 struct varshead old; 01655 struct ast_channel *c = ast_channel_alloc(0, 0, "", "", "", "", "", 0, "Bogus/%p", vars); 01656 if (c) { 01657 memcpy(&old, &c->varshead, sizeof(old)); 01658 memcpy(&c->varshead, headp, sizeof(c->varshead)); 01659 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 01660 /* Don't deallocate the varshead that was passed in */ 01661 memcpy(&c->varshead, &old, sizeof(c->varshead)); 01662 ast_channel_free(c); 01663 } else 01664 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n"); 01665 } 01666 01667 if (option_debug) 01668 ast_log(LOG_DEBUG, "Function result is '%s'\n", cp4 ? cp4 : "(null)"); 01669 } else { 01670 /* Retrieve variable value */ 01671 pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp); 01672 } 01673 if (cp4) { 01674 cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE); 01675 01676 length = strlen(cp4); 01677 if (length > count) 01678 length = count; 01679 memcpy(cp2, cp4, length); 01680 count -= length; 01681 cp2 += length; 01682 } 01683 } else if (nextexp) { 01684 /* We have an expression. Find the start and end, and determine 01685 if we are going to have to recursively call ourselves on the 01686 contents */ 01687 vars = vare = nextexp + 2; 01688 brackets = 1; 01689 needsub = 0; 01690 01691 /* Find the end of it */ 01692 while(brackets && *vare) { 01693 if ((vare[0] == '$') && (vare[1] == '[')) { 01694 needsub++; 01695 brackets++; 01696 vare++; 01697 } else if (vare[0] == '[') { 01698 brackets++; 01699 } else if (vare[0] == ']') { 01700 brackets--; 01701 } else if ((vare[0] == '$') && (vare[1] == '{')) { 01702 needsub++; 01703 vare++; 01704 } 01705 vare++; 01706 } 01707 if (brackets) 01708 ast_log(LOG_NOTICE, "Error in extension logic (missing ']')\n"); 01709 len = vare - vars - 1; 01710 01711 /* Skip totally over expression */ 01712 whereweare += (len + 3); 01713 01714 if (!var) 01715 var = alloca(VAR_BUF_SIZE); 01716 01717 /* Store variable name (and truncate) */ 01718 ast_copy_string(var, vars, len + 1); 01719 01720 /* Substitute if necessary */ 01721 if (needsub) { 01722 if (!ltmp) 01723 ltmp = alloca(VAR_BUF_SIZE); 01724 01725 memset(ltmp, 0, VAR_BUF_SIZE); 01726 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1); 01727 vars = ltmp; 01728 } else { 01729 vars = var; 01730 } 01731 01732 length = ast_expr(vars, cp2, count); 01733 01734 if (length) { 01735 if (option_debug) 01736 ast_log(LOG_DEBUG, "Expression result is '%s'\n", cp2); 01737 count -= length; 01738 cp2 += length; 01739 } 01740 } else 01741 break; 01742 } 01743 }
void pbx_substitute_variables_varshead | ( | struct varshead * | headp, | |
const char * | cp1, | |||
char * | cp2, | |||
int | count | |||
) |
Definition at line 1750 of file pbx.c.
References pbx_substitute_variables_helper_full().
Referenced by ast_add_extension2(), dundi_lookup_local(), and loopback_helper().
01751 { 01752 pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count); 01753 }
static void* pbx_thread | ( | void * | data | ) | [static] |
Definition at line 2595 of file pbx.c.
References __ast_pbx_run(), and decrease_call_count().
Referenced by ast_pbx_start().
02596 { 02597 /* Oh joyeous kernel, we're a new thread, with nothing to do but 02598 answer this channel and get it going. 02599 */ 02600 /* NOTE: 02601 The launcher of this function _MUST_ increment 'countcalls' 02602 before invoking the function; it will be decremented when the 02603 PBX has finished running on the channel 02604 */ 02605 struct ast_channel *c = data; 02606 02607 __ast_pbx_run(c); 02608 decrease_call_count(); 02609 02610 pthread_exit(NULL); 02611 02612 return NULL; 02613 }
static void print_ext | ( | struct ast_exten * | e, | |
char * | buf, | |||
int | buflen | |||
) | [static] |
helper function to print an extension
Definition at line 3478 of file pbx.c.
References ast_get_extension_app(), ast_get_extension_app_data(), ast_get_extension_priority(), and PRIORITY_HINT.
Referenced by show_dialplan_helper().
03479 { 03480 int prio = ast_get_extension_priority(e); 03481 if (prio == PRIORITY_HINT) { 03482 snprintf(buf, buflen, "hint: %s", 03483 ast_get_extension_app(e)); 03484 } else { 03485 snprintf(buf, buflen, "%d. %s(%s)", 03486 prio, ast_get_extension_app(e), 03487 (char *)ast_get_extension_app_data(e)); 03488 } 03489 }
static void set_ext_pri | ( | struct ast_channel * | c, | |
const char * | exten, | |||
int | pri | |||
) | [static] |
Definition at line 2298 of file pbx.c.
References ast_channel::exten, and ast_channel::priority.
Referenced by __ast_pbx_run(), ast_pbx_outgoing_exten(), and pbx_builtin_waitexten().
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 3492 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_lock_contexts(), ast_log(), AST_MAX_EXTENSION, AST_PBX_MAX_STACK, 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().
03493 { 03494 struct ast_context *c = NULL; 03495 int res = 0, old_total_exten = dpc->total_exten; 03496 03497 ast_lock_contexts(); 03498 03499 /* walk all contexts ... */ 03500 while ( (c = ast_walk_contexts(c)) ) { 03501 struct ast_exten *e; 03502 struct ast_include *i; 03503 struct ast_ignorepat *ip; 03504 char buf[256], buf2[256]; 03505 int context_info_printed = 0; 03506 03507 if (context && strcmp(ast_get_context_name(c), context)) 03508 continue; /* skip this one, name doesn't match */ 03509 03510 dpc->context_existence = 1; 03511 03512 ast_lock_context(c); 03513 03514 /* are we looking for exten too? if yes, we print context 03515 * only if we find our extension. 03516 * Otherwise print context even if empty ? 03517 * XXX i am not sure how the rinclude is handled. 03518 * I think it ought to go inside. 03519 */ 03520 if (!exten) { 03521 dpc->total_context++; 03522 ast_cli(fd, "[ Context '%s' created by '%s' ]\n", 03523 ast_get_context_name(c), ast_get_context_registrar(c)); 03524 context_info_printed = 1; 03525 } 03526 03527 /* walk extensions ... */ 03528 e = NULL; 03529 while ( (e = ast_walk_context_extensions(c, e)) ) { 03530 struct ast_exten *p; 03531 03532 if (exten && !ast_extension_match(ast_get_extension_name(e), exten)) 03533 continue; /* skip, extension match failed */ 03534 03535 dpc->extension_existence = 1; 03536 03537 /* may we print context info? */ 03538 if (!context_info_printed) { 03539 dpc->total_context++; 03540 if (rinclude) { /* TODO Print more info about rinclude */ 03541 ast_cli(fd, "[ Included context '%s' created by '%s' ]\n", 03542 ast_get_context_name(c), ast_get_context_registrar(c)); 03543 } else { 03544 ast_cli(fd, "[ Context '%s' created by '%s' ]\n", 03545 ast_get_context_name(c), ast_get_context_registrar(c)); 03546 } 03547 context_info_printed = 1; 03548 } 03549 dpc->total_prio++; 03550 03551 /* write extension name and first peer */ 03552 snprintf(buf, sizeof(buf), "'%s' =>", ast_get_extension_name(e)); 03553 03554 print_ext(e, buf2, sizeof(buf2)); 03555 03556 ast_cli(fd, " %-17s %-45s [%s]\n", buf, buf2, 03557 ast_get_extension_registrar(e)); 03558 03559 dpc->total_exten++; 03560 /* walk next extension peers */ 03561 p = e; /* skip the first one, we already got it */ 03562 while ( (p = ast_walk_extension_priorities(e, p)) ) { 03563 const char *el = ast_get_extension_label(p); 03564 dpc->total_prio++; 03565 if (el) 03566 snprintf(buf, sizeof(buf), " [%s]", el); 03567 else 03568 buf[0] = '\0'; 03569 print_ext(p, buf2, sizeof(buf2)); 03570 03571 ast_cli(fd," %-17s %-45s [%s]\n", buf, buf2, 03572 ast_get_extension_registrar(p)); 03573 } 03574 } 03575 03576 /* walk included and write info ... */ 03577 i = NULL; 03578 while ( (i = ast_walk_context_includes(c, i)) ) { 03579 snprintf(buf, sizeof(buf), "'%s'", ast_get_include_name(i)); 03580 if (exten) { 03581 /* Check all includes for the requested extension */ 03582 if (includecount >= AST_PBX_MAX_STACK) { 03583 ast_log(LOG_NOTICE, "Maximum include depth exceeded!\n"); 03584 } else { 03585 int dupe=0; 03586 int x; 03587 for (x=0;x<includecount;x++) { 03588 if (!strcasecmp(includes[x], ast_get_include_name(i))) { 03589 dupe++; 03590 break; 03591 } 03592 } 03593 if (!dupe) { 03594 includes[includecount] = ast_get_include_name(i); 03595 show_dialplan_helper(fd, ast_get_include_name(i), exten, dpc, i, includecount + 1, includes); 03596 } else { 03597 ast_log(LOG_WARNING, "Avoiding circular include of %s within %s\n", ast_get_include_name(i), context); 03598 } 03599 } 03600 } else { 03601 ast_cli(fd, " Include => %-45s [%s]\n", 03602 buf, ast_get_include_registrar(i)); 03603 } 03604 } 03605 03606 /* walk ignore patterns and write info ... */ 03607 ip = NULL; 03608 while ( (ip = ast_walk_context_ignorepats(c, ip)) ) { 03609 const char *ipname = ast_get_ignorepat_name(ip); 03610 char ignorepat[AST_MAX_EXTENSION]; 03611 snprintf(buf, sizeof(buf), "'%s'", ipname); 03612 snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname); 03613 if (!exten || ast_extension_match(ignorepat, exten)) { 03614 ast_cli(fd, " Ignore pattern => %-45s [%s]\n", 03615 buf, ast_get_ignorepat_registrar(ip)); 03616 } 03617 } 03618 if (!rinclude) { 03619 struct ast_sw *sw = NULL; 03620 while ( (sw = ast_walk_context_switches(c, sw)) ) { 03621 snprintf(buf, sizeof(buf), "'%s/%s'", 03622 ast_get_switch_name(sw), 03623 ast_get_switch_data(sw)); 03624 ast_cli(fd, " Alt. Switch => %-45s [%s]\n", 03625 buf, ast_get_switch_registrar(sw)); 03626 } 03627 } 03628 03629 ast_unlock_context(c); 03630 03631 /* if we print something in context, make an empty line */ 03632 if (context_info_printed) 03633 ast_cli(fd, "\r\n"); 03634 } 03635 ast_unlock_contexts(); 03636 03637 return (dpc->total_exten == old_total_exten) ? -1 : res; 03638 }
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 1092 of file pbx.c.
Referenced by pbx_retrieve_variable(), and pbx_substitute_variables_helper_full().
01093 { 01094 char *ret = workspace; 01095 int lr; /* length of the input string after the copy */ 01096 01097 ast_copy_string(workspace, value, workspace_len); /* always make a copy */ 01098 01099 lr = strlen(ret); /* compute length after copy, so we never go out of the workspace */ 01100 01101 /* Quick check if no need to do anything */ 01102 if (offset == 0 && length >= lr) /* take the whole string */ 01103 return ret; 01104 01105 if (offset < 0) { /* translate negative offset into positive ones */ 01106 offset = lr + offset; 01107 if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */ 01108 offset = 0; 01109 } 01110 01111 /* too large offset result in empty string so we know what to return */ 01112 if (offset >= lr) 01113 return ret + lr; /* the final '\0' */ 01114 01115 ret += offset; /* move to the start position */ 01116 if (length >= 0 && length < lr - offset) /* truncate if necessary */ 01117 ret[length] = '\0'; 01118 else if (length < 0) { 01119 if (lr > offset - length) /* After we remove from the front and from the rear, is there anything left? */ 01120 ret[lr + length - offset] = '\0'; 01121 else 01122 ret[0] = '\0'; 01123 } 01124 01125 return ret; 01126 }
static void wait_for_hangup | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 5343 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().
05344 { 05345 int res; 05346 struct ast_frame *f; 05347 int waittime; 05348 05349 if (ast_strlen_zero(data) || (sscanf(data, "%d", &waittime) != 1) || (waittime < 0)) 05350 waittime = -1; 05351 if (waittime > -1) { 05352 ast_safe_sleep(chan, waittime * 1000); 05353 } else do { 05354 res = ast_waitfor(chan, -1); 05355 if (res < 0) 05356 return; 05357 f = ast_read(chan); 05358 if (f) 05359 ast_frfree(f); 05360 } while(f); 05361 }
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 492 of file pbx.c.
Referenced by __ast_context_create(), __ast_context_destroy(), ast_merge_contexts_and_delete(), and ast_walk_contexts().
int countcalls [static] |
Definition at line 248 of file pbx.c.
Referenced by ast_active_calls(), decrease_call_count(), and increase_call_count().
char* days[] [static] |
struct cfextension_states extension_states[] [static] |
Referenced by ast_extension_state2str().
struct varshead globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE [static] |
char* months[] [static] |
struct ast_cli_entry pbx_cli[] [static] |
char set_global_help[] [static] |
char show_application_help[] [static] |
char show_applications_help[] [static] |
char show_dialplan_help[] [static] |
char show_function_help[] [static] |
char show_functions_help[] [static] |
char show_globals_help[] [static] |
char show_hints_help[] [static] |
char show_switches_help[] [static] |
struct ast_state_cb* statecbs |
Definition at line 507 of file pbx.c.
Referenced by ast_extension_state_add(), ast_extension_state_del(), and ast_hint_state_changed().