#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 3846 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().
03847 { 03848 struct ast_context *tmp, **local_contexts; 03849 int length = sizeof(struct ast_context) + strlen(name) + 1; 03850 03851 if (!extcontexts) { 03852 ast_mutex_lock(&conlock); 03853 local_contexts = &contexts; 03854 } else 03855 local_contexts = extcontexts; 03856 03857 for (tmp = *local_contexts; tmp; tmp = tmp->next) { 03858 if (!strcasecmp(tmp->name, name)) { 03859 if (!existsokay) { 03860 ast_log(LOG_WARNING, "Tried to register context '%s', already in use\n", name); 03861 tmp = NULL; 03862 } 03863 if (!extcontexts) 03864 ast_mutex_unlock(&conlock); 03865 return tmp; 03866 } 03867 } 03868 if ((tmp = ast_calloc(1, length))) { 03869 ast_mutex_init(&tmp->lock); 03870 ast_mutex_init(&tmp->macrolock); 03871 strcpy(tmp->name, name); 03872 tmp->root = NULL; 03873 tmp->registrar = registrar; 03874 tmp->next = *local_contexts; 03875 tmp->includes = NULL; 03876 tmp->ignorepats = NULL; 03877 *local_contexts = tmp; 03878 if (option_debug) 03879 ast_log(LOG_DEBUG, "Registered context '%s'\n", tmp->name); 03880 if (option_verbose > 2) 03881 ast_verbose( VERBOSE_PREFIX_3 "Registered extension context '%s'\n", tmp->name); 03882 } 03883 03884 if (!extcontexts) 03885 ast_mutex_unlock(&conlock); 03886 return tmp; 03887 }
void __ast_context_destroy | ( | struct ast_context * | con, | |
const char * | registrar | |||
) |
Definition at line 5265 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().
05266 { 05267 struct ast_context *tmp, *tmpl=NULL; 05268 struct ast_include *tmpi; 05269 struct ast_sw *sw; 05270 struct ast_exten *e, *el, *en; 05271 struct ast_ignorepat *ipi; 05272 05273 ast_mutex_lock(&conlock); 05274 for (tmp = contexts; tmp; ) { 05275 struct ast_context *next; /* next starting point */ 05276 for (; tmp; tmpl = tmp, tmp = tmp->next) { 05277 if (option_debug) 05278 ast_log(LOG_DEBUG, "check ctx %s %s\n", tmp->name, tmp->registrar); 05279 if ( (!registrar || !strcasecmp(registrar, tmp->registrar)) && 05280 (!con || !strcasecmp(tmp->name, con->name)) ) 05281 break; /* found it */ 05282 } 05283 if (!tmp) /* not found, we are done */ 05284 break; 05285 ast_mutex_lock(&tmp->lock); 05286 if (option_debug) 05287 ast_log(LOG_DEBUG, "delete ctx %s %s\n", tmp->name, tmp->registrar); 05288 next = tmp->next; 05289 if (tmpl) 05290 tmpl->next = next; 05291 else 05292 contexts = next; 05293 /* Okay, now we're safe to let it go -- in a sense, we were 05294 ready to let it go as soon as we locked it. */ 05295 ast_mutex_unlock(&tmp->lock); 05296 for (tmpi = tmp->includes; tmpi; ) { /* Free includes */ 05297 struct ast_include *tmpil = tmpi; 05298 tmpi = tmpi->next; 05299 free(tmpil); 05300 } 05301 for (ipi = tmp->ignorepats; ipi; ) { /* Free ignorepats */ 05302 struct ast_ignorepat *ipl = ipi; 05303 ipi = ipi->next; 05304 free(ipl); 05305 } 05306 while ((sw = AST_LIST_REMOVE_HEAD(&tmp->alts, list))) 05307 free(sw); 05308 for (e = tmp->root; e;) { 05309 for (en = e->peer; en;) { 05310 el = en; 05311 en = en->peer; 05312 destroy_exten(el); 05313 } 05314 el = e; 05315 e = e->next; 05316 destroy_exten(el); 05317 } 05318 ast_mutex_destroy(&tmp->lock); 05319 free(tmp); 05320 /* if we have a specific match, we are done, otherwise continue */ 05321 tmp = con ? NULL : next; 05322 } 05323 ast_mutex_unlock(&conlock); 05324 }
static int __ast_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority, | |||
int | async | |||
) | [static] |
Definition at line 6257 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().
06258 { 06259 int (*goto_func)(struct ast_channel *chan, const char *context, const char *exten, int priority); 06260 06261 if (!chan) 06262 return -2; 06263 06264 if (context == NULL) 06265 context = chan->context; 06266 if (exten == NULL) 06267 exten = chan->exten; 06268 06269 goto_func = (async) ? ast_async_goto : ast_explicit_goto; 06270 if (ast_exists_extension(chan, context, exten, priority, chan->cid.cid_num)) 06271 return goto_func(chan, context, exten, priority); 06272 else 06273 return -3; 06274 }
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) 02527 ast_softhangup(c, c->hangupcause ? c->hangupcause : AST_CAUSE_NORMAL_CLEARING); 02528 if ((res != AST_PBX_KEEPALIVE) && ast_exists_extension(c, c->context, "h", 1, c->cid.cid_num)) { 02529 if (c->cdr && ast_opt_end_cdr_before_h_exten) 02530 ast_cdr_end(c->cdr); 02531 set_ext_pri(c, "h", 1); 02532 while(ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) { 02533 if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num))) { 02534 /* Something bad happened, or a hangup has been requested. */ 02535 if (option_debug) 02536 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 02537 if (option_verbose > 1) 02538 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 02539 break; 02540 } 02541 c->priority++; 02542 } 02543 } 02544 ast_set2_flag(c, autoloopflag, AST_FLAG_IN_AUTOLOOP); 02545 02546 pbx_destroy(c->pbx); 02547 c->pbx = NULL; 02548 if (res != AST_PBX_KEEPALIVE) 02549 ast_hangup(c); 02550 return 0; 02551 }
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 4656 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().
04658 { 04659 struct ast_exten *ep; 04660 04661 for (ep = NULL; e ; ep = e, e = e->peer) { 04662 if (e->priority >= tmp->priority) 04663 break; 04664 } 04665 if (!e) { /* go at the end, and ep is surely set because the list is not empty */ 04666 ep->peer = tmp; 04667 return 0; /* success */ 04668 } 04669 if (e->priority == tmp->priority) { 04670 /* Can't have something exactly the same. Is this a 04671 replacement? If so, replace, otherwise, bonk. */ 04672 if (!replace) { 04673 ast_log(LOG_WARNING, "Unable to register extension '%s', priority %d in '%s', already in use\n", tmp->exten, tmp->priority, con->name); 04674 if (tmp->datad) 04675 tmp->datad(tmp->data); 04676 free(tmp); 04677 return -1; 04678 } 04679 /* we are replacing e, so copy the link fields and then update 04680 * whoever pointed to e to point to us 04681 */ 04682 tmp->next = e->next; /* not meaningful if we are not first in the peer list */ 04683 tmp->peer = e->peer; /* always meaningful */ 04684 if (ep) /* We're in the peer list, just insert ourselves */ 04685 ep->peer = tmp; 04686 else if (el) /* We're the first extension. Take over e's functions */ 04687 el->next = tmp; 04688 else /* We're the very first extension. */ 04689 con->root = tmp; 04690 if (tmp->priority == PRIORITY_HINT) 04691 ast_change_hint(e,tmp); 04692 /* Destroy the old one */ 04693 if (e->datad) 04694 e->datad(e->data); 04695 free(e); 04696 } else { /* Slip ourselves in just before e */ 04697 tmp->peer = e; 04698 tmp->next = e->next; /* extension chain, or NULL if e is not the first extension */ 04699 if (ep) /* Easy enough, we're just in the peer list */ 04700 ep->peer = tmp; 04701 else { /* we are the first in some peer list, so link in the ext list */ 04702 if (el) 04703 el->next = tmp; /* in the middle... */ 04704 else 04705 con->root = tmp; /* ... or at the head */ 04706 e->next = NULL; /* e is no more at the head, so e->next must be reset */ 04707 } 04708 /* And immediately return success. */ 04709 if (tmp->priority == PRIORITY_HINT) 04710 ast_add_hint(tmp); 04711 } 04712 return 0; 04713 }
int ast_active_calls | ( | void | ) |
Retrieve the number of active calls.
Definition at line 2656 of file pbx.c.
References countcalls.
Referenced by handle_chanlist(), and handle_chanlist_deprecated().
02657 { 02658 return countcalls; 02659 }
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 4536 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().
04539 { 04540 int ret = -1; 04541 struct ast_context *c = find_context_locked(context); 04542 04543 if (c) { 04544 ret = ast_add_extension2(c, replace, extension, priority, label, callerid, 04545 application, data, datad, registrar); 04546 ast_unlock_contexts(); 04547 } 04548 return ret; 04549 }
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 4740 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().
04744 { 04745 /* 04746 * Sort extensions (or patterns) according to the rules indicated above. 04747 * These are implemented by the function ext_cmp()). 04748 * All priorities for the same ext/pattern/cid are kept in a list, 04749 * using the 'peer' field as a link field.. 04750 */ 04751 struct ast_exten *tmp, *e, *el = NULL; 04752 int res; 04753 int length; 04754 char *p; 04755 char expand_buf[VAR_BUF_SIZE] = { 0, }; 04756 04757 /* if we are adding a hint, and there are global variables, and the hint 04758 contains variable references, then expand them 04759 */ 04760 ast_mutex_lock(&globalslock); 04761 if (priority == PRIORITY_HINT && AST_LIST_FIRST(&globals) && strstr(application, "${")) { 04762 pbx_substitute_variables_varshead(&globals, application, expand_buf, sizeof(expand_buf)); 04763 application = expand_buf; 04764 } 04765 ast_mutex_unlock(&globalslock); 04766 04767 length = sizeof(struct ast_exten); 04768 length += strlen(extension) + 1; 04769 length += strlen(application) + 1; 04770 if (label) 04771 length += strlen(label) + 1; 04772 if (callerid) 04773 length += strlen(callerid) + 1; 04774 else 04775 length ++; /* just the '\0' */ 04776 04777 /* Be optimistic: Build the extension structure first */ 04778 if (!(tmp = ast_calloc(1, length))) 04779 return -1; 04780 04781 /* use p as dst in assignments, as the fields are const char * */ 04782 p = tmp->stuff; 04783 if (label) { 04784 tmp->label = p; 04785 strcpy(p, label); 04786 p += strlen(label) + 1; 04787 } 04788 tmp->exten = p; 04789 p += ext_strncpy(p, extension, strlen(extension) + 1) + 1; 04790 tmp->priority = priority; 04791 tmp->cidmatch = p; /* but use p for assignments below */ 04792 if (callerid) { 04793 p += ext_strncpy(p, callerid, strlen(callerid) + 1) + 1; 04794 tmp->matchcid = 1; 04795 } else { 04796 *p++ = '\0'; 04797 tmp->matchcid = 0; 04798 } 04799 tmp->app = p; 04800 strcpy(p, application); 04801 tmp->parent = con; 04802 tmp->data = data; 04803 tmp->datad = datad; 04804 tmp->registrar = registrar; 04805 04806 ast_mutex_lock(&con->lock); 04807 res = 0; /* some compilers will think it is uninitialized otherwise */ 04808 for (e = con->root; e; el = e, e = e->next) { /* scan the extension list */ 04809 res = ext_cmp(e->exten, extension); 04810 if (res == 0) { /* extension match, now look at cidmatch */ 04811 if (!e->matchcid && !tmp->matchcid) 04812 res = 0; 04813 else if (tmp->matchcid && !e->matchcid) 04814 res = 1; 04815 else if (e->matchcid && !tmp->matchcid) 04816 res = -1; 04817 else 04818 res = strcasecmp(e->cidmatch, tmp->cidmatch); 04819 } 04820 if (res >= 0) 04821 break; 04822 } 04823 if (e && res == 0) { /* exact match, insert in the pri chain */ 04824 res = add_pri(con, tmp, el, e, replace); 04825 ast_mutex_unlock(&con->lock); 04826 if (res < 0) { 04827 errno = EEXIST; /* XXX do we care ? */ 04828 return 0; /* XXX should we return -1 maybe ? */ 04829 } 04830 } else { 04831 /* 04832 * not an exact match, this is the first entry with this pattern, 04833 * so insert in the main list right before 'e' (if any) 04834 */ 04835 tmp->next = e; 04836 if (el) 04837 el->next = tmp; 04838 else 04839 con->root = tmp; 04840 ast_mutex_unlock(&con->lock); 04841 if (tmp->priority == PRIORITY_HINT) 04842 ast_add_hint(tmp); 04843 } 04844 if (option_debug) { 04845 if (tmp->matchcid) { 04846 if (option_debug) 04847 ast_log(LOG_DEBUG, "Added extension '%s' priority %d (CID match '%s') to %s\n", 04848 tmp->exten, tmp->priority, tmp->cidmatch, con->name); 04849 } else { 04850 if (option_debug) 04851 ast_log(LOG_DEBUG, "Added extension '%s' priority %d to %s\n", 04852 tmp->exten, tmp->priority, con->name); 04853 } 04854 } 04855 if (option_verbose > 2) { 04856 if (tmp->matchcid) { 04857 ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d (CID match '%s')to %s\n", 04858 tmp->exten, tmp->priority, tmp->cidmatch, con->name); 04859 } else { 04860 ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d to %s\n", 04861 tmp->exten, tmp->priority, con->name); 04862 } 04863 } 04864 return 0; 04865 }
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 4570 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().
04571 { 04572 int res = 0; 04573 04574 ast_channel_lock(chan); 04575 04576 if (chan->pbx) { /* This channel is currently in the PBX */ 04577 ast_explicit_goto(chan, context, exten, priority); 04578 ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO); 04579 } else { 04580 /* In order to do it when the channel doesn't really exist within 04581 the PBX, we have to make a new channel, masquerade, and start the PBX 04582 at the new location */ 04583 struct ast_channel *tmpchan = ast_channel_alloc(0, chan->_state, 0, 0, chan->accountcode, chan->exten, chan->context, chan->amaflags, "AsyncGoto/%s", chan->name); 04584 if (chan->cdr) { 04585 tmpchan->cdr = ast_cdr_dup(chan->cdr); 04586 } 04587 if (!tmpchan) 04588 res = -1; 04589 else { 04590 /* Make formats okay */ 04591 tmpchan->readformat = chan->readformat; 04592 tmpchan->writeformat = chan->writeformat; 04593 /* Setup proper location */ 04594 ast_explicit_goto(tmpchan, 04595 S_OR(context, chan->context), S_OR(exten, chan->exten), priority); 04596 04597 /* Masquerade into temp channel */ 04598 ast_channel_masquerade(tmpchan, chan); 04599 04600 /* Grab the locks and get going */ 04601 ast_channel_lock(tmpchan); 04602 ast_do_masquerade(tmpchan); 04603 ast_channel_unlock(tmpchan); 04604 /* Start the PBX going on our stolen channel */ 04605 if (ast_pbx_start(tmpchan)) { 04606 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name); 04607 ast_hangup(tmpchan); 04608 res = -1; 04609 } 04610 } 04611 } 04612 ast_channel_unlock(chan); 04613 return res; 04614 }
int ast_async_goto_by_name | ( | const char * | channame, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 4616 of file pbx.c.
References ast_async_goto(), ast_channel_unlock, and ast_get_channel_by_name_locked().
04617 { 04618 struct ast_channel *chan; 04619 int res = -1; 04620 04621 chan = ast_get_channel_by_name_locked(channame); 04622 if (chan) { 04623 res = ast_async_goto(chan, context, exten, priority); 04624 ast_channel_unlock(chan); 04625 } 04626 return res; 04627 }
int ast_async_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 6281 of file pbx.c.
References __ast_goto_if_exists().
Referenced by asyncgoto_exec().
06282 { 06283 return __ast_goto_if_exists(chan, context, exten, priority, 1); 06284 }
int ast_build_timing | ( | struct ast_timing * | i, | |
const char * | info_in | |||
) |
Definition at line 4212 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().
04213 { 04214 char info_save[256]; 04215 char *info; 04216 04217 /* Check for empty just in case */ 04218 if (ast_strlen_zero(info_in)) 04219 return 0; 04220 /* make a copy just in case we were passed a static string */ 04221 ast_copy_string(info_save, info_in, sizeof(info_save)); 04222 info = info_save; 04223 /* Assume everything except time */ 04224 i->monthmask = 0xfff; /* 12 bits */ 04225 i->daymask = 0x7fffffffU; /* 31 bits */ 04226 i->dowmask = 0x7f; /* 7 bits */ 04227 /* on each call, use strsep() to move info to the next argument */ 04228 get_timerange(i, strsep(&info, "|")); 04229 if (info) 04230 i->dowmask = get_range(strsep(&info, "|"), 7, days, "day of week"); 04231 if (info) 04232 i->daymask = get_range(strsep(&info, "|"), 31, NULL, "day"); 04233 if (info) 04234 i->monthmask = get_range(strsep(&info, "|"), 12, months, "month"); 04235 return 1; 04236 }
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 4238 of file pbx.c.
References ast_localtime(), ast_log(), ast_timing::daymask, ast_timing::dowmask, LOG_WARNING, ast_timing::minmask, ast_timing::monthmask, and t.
Referenced by iftime(), include_valid(), pbx_builtin_execiftime(), and pbx_builtin_gotoiftime().
04239 { 04240 struct tm tm; 04241 time_t t = time(NULL); 04242 04243 ast_localtime(&t, &tm, NULL); 04244 04245 /* If it's not the right month, return */ 04246 if (!(i->monthmask & (1 << tm.tm_mon))) 04247 return 0; 04248 04249 /* If it's not that time of the month.... */ 04250 /* Warning, tm_mday has range 1..31! */ 04251 if (!(i->daymask & (1 << (tm.tm_mday-1)))) 04252 return 0; 04253 04254 /* If it's not the right day of the week */ 04255 if (!(i->dowmask & (1 << tm.tm_wday))) 04256 return 0; 04257 04258 /* Sanity check the hour just to be safe */ 04259 if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) { 04260 ast_log(LOG_WARNING, "Insane time...\n"); 04261 return 0; 04262 } 04263 04264 /* Now the tough part, we calculate if it fits 04265 in the right time based on min/hour */ 04266 if (!(i->minmask[tm.tm_hour] & (1 << (tm.tm_min / 2)))) 04267 return 0; 04268 04269 /* If we got this far, then we're good */ 04270 return 1; 04271 }
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 4472 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().
04473 { 04474 int ret = -1; 04475 struct ast_context *c = find_context_locked(context); 04476 04477 if (c) { 04478 ret = ast_context_add_ignorepat2(c, value, registrar); 04479 ast_unlock_contexts(); 04480 } 04481 return ret; 04482 }
int ast_context_add_ignorepat2 | ( | struct ast_context * | con, | |
const char * | value, | |||
const char * | registrar | |||
) |
Definition at line 4484 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_context_add_ignorepat(), and pbx_load_config().
04485 { 04486 struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL; 04487 int length; 04488 length = sizeof(struct ast_ignorepat); 04489 length += strlen(value) + 1; 04490 if (!(ignorepat = ast_calloc(1, length))) 04491 return -1; 04492 /* The cast to char * is because we need to write the initial value. 04493 * The field is not supposed to be modified otherwise 04494 */ 04495 strcpy((char *)ignorepat->pattern, value); 04496 ignorepat->next = NULL; 04497 ignorepat->registrar = registrar; 04498 ast_mutex_lock(&con->lock); 04499 for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) { 04500 ignorepatl = ignorepatc; 04501 if (!strcasecmp(ignorepatc->pattern, value)) { 04502 /* Already there */ 04503 ast_mutex_unlock(&con->lock); 04504 errno = EEXIST; 04505 return -1; 04506 } 04507 } 04508 if (ignorepatl) 04509 ignorepatl->next = ignorepat; 04510 else 04511 con->ignorepats = ignorepat; 04512 ast_mutex_unlock(&con->lock); 04513 return 0; 04514 04515 }
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 4018 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().
04019 { 04020 int ret = -1; 04021 struct ast_context *c = find_context_locked(context); 04022 04023 if (c) { 04024 ret = ast_context_add_include2(c, include, registrar); 04025 ast_unlock_contexts(); 04026 } 04027 return ret; 04028 }
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 4280 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_context_add_include(), and pbx_load_config().
04282 { 04283 struct ast_include *new_include; 04284 char *c; 04285 struct ast_include *i, *il = NULL; /* include, include_last */ 04286 int length; 04287 char *p; 04288 04289 length = sizeof(struct ast_include); 04290 length += 2 * (strlen(value) + 1); 04291 04292 /* allocate new include structure ... */ 04293 if (!(new_include = ast_calloc(1, length))) 04294 return -1; 04295 /* Fill in this structure. Use 'p' for assignments, as the fields 04296 * in the structure are 'const char *' 04297 */ 04298 p = new_include->stuff; 04299 new_include->name = p; 04300 strcpy(p, value); 04301 p += strlen(value) + 1; 04302 new_include->rname = p; 04303 strcpy(p, value); 04304 /* Strip off timing info, and process if it is there */ 04305 if ( (c = strchr(p, '|')) ) { 04306 *c++ = '\0'; 04307 new_include->hastime = ast_build_timing(&(new_include->timing), c); 04308 } 04309 new_include->next = NULL; 04310 new_include->registrar = registrar; 04311 04312 ast_mutex_lock(&con->lock); 04313 04314 /* ... go to last include and check if context is already included too... */ 04315 for (i = con->includes; i; i = i->next) { 04316 if (!strcasecmp(i->name, new_include->name)) { 04317 free(new_include); 04318 ast_mutex_unlock(&con->lock); 04319 errno = EEXIST; 04320 return -1; 04321 } 04322 il = i; 04323 } 04324 04325 /* ... include new context into context list, unlock, return */ 04326 if (il) 04327 il->next = new_include; 04328 else 04329 con->includes = new_include; 04330 if (option_verbose > 2) 04331 ast_verbose(VERBOSE_PREFIX_3 "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con)); 04332 ast_mutex_unlock(&con->lock); 04333 04334 return 0; 04335 }
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 4342 of file pbx.c.
References ast_context_add_switch2(), ast_unlock_contexts(), and find_context_locked().
04343 { 04344 int ret = -1; 04345 struct ast_context *c = find_context_locked(context); 04346 04347 if (c) { /* found, add switch to this context */ 04348 ret = ast_context_add_switch2(c, sw, data, eval, registrar); 04349 ast_unlock_contexts(); 04350 } 04351 return ret; 04352 }
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 4361 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_context_add_switch(), and pbx_load_config().
04363 { 04364 struct ast_sw *new_sw; 04365 struct ast_sw *i; 04366 int length; 04367 char *p; 04368 04369 length = sizeof(struct ast_sw); 04370 length += strlen(value) + 1; 04371 if (data) 04372 length += strlen(data); 04373 length++; 04374 if (eval) { 04375 /* Create buffer for evaluation of variables */ 04376 length += SWITCH_DATA_LENGTH; 04377 length++; 04378 } 04379 04380 /* allocate new sw structure ... */ 04381 if (!(new_sw = ast_calloc(1, length))) 04382 return -1; 04383 /* ... fill in this structure ... */ 04384 p = new_sw->stuff; 04385 new_sw->name = p; 04386 strcpy(new_sw->name, value); 04387 p += strlen(value) + 1; 04388 new_sw->data = p; 04389 if (data) { 04390 strcpy(new_sw->data, data); 04391 p += strlen(data) + 1; 04392 } else { 04393 strcpy(new_sw->data, ""); 04394 p++; 04395 } 04396 if (eval) 04397 new_sw->tmpdata = p; 04398 new_sw->eval = eval; 04399 new_sw->registrar = registrar; 04400 04401 /* ... try to lock this context ... */ 04402 ast_mutex_lock(&con->lock); 04403 04404 /* ... go to last sw and check if context is already swd too... */ 04405 AST_LIST_TRAVERSE(&con->alts, i, list) { 04406 if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) { 04407 free(new_sw); 04408 ast_mutex_unlock(&con->lock); 04409 errno = EEXIST; 04410 return -1; 04411 } 04412 } 04413 04414 /* ... sw new context into context list, unlock, return */ 04415 AST_LIST_INSERT_TAIL(&con->alts, new_sw, list); 04416 04417 if (option_verbose > 2) 04418 ast_verbose(VERBOSE_PREFIX_3 "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con)); 04419 04420 ast_mutex_unlock(&con->lock); 04421 04422 return 0; 04423 }
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 3889 of file pbx.c.
References __ast_context_create().
Referenced by ast_park_call(), do_parking_thread(), and set_config().
03890 { 03891 return __ast_context_create(extcontexts, name, registrar, 0); 03892 }
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 5326 of file pbx.c.
References __ast_context_destroy().
Referenced by cleanup_stale_contexts(), and unload_module().
05327 { 05328 __ast_context_destroy(con,registrar); 05329 }
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 3894 of file pbx.c.
References __ast_context_create().
Referenced by pbx_load_config(), and pbx_load_users().
03895 { 03896 return __ast_context_create(extcontexts, name, registrar, 1); 03897 }
int ast_context_lockmacro | ( | const char * | context | ) |
locks the macrolock in the given given context
Definition at line 2893 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().
02894 { 02895 struct ast_context *c = NULL; 02896 int ret = -1; 02897 02898 ast_lock_contexts(); 02899 02900 while ((c = ast_walk_contexts(c))) { 02901 if (!strcmp(ast_get_context_name(c), context)) { 02902 ret = 0; 02903 break; 02904 } 02905 } 02906 02907 ast_unlock_contexts(); 02908 02909 /* if we found context, lock macrolock */ 02910 if (ret == 0) 02911 ret = ast_mutex_lock(&c->macrolock); 02912 02913 return ret; 02914 }
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 2794 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().
02795 { 02796 int ret = -1; /* default error return */ 02797 struct ast_context *c = find_context_locked(context); 02798 02799 if (c) { /* ... remove extension ... */ 02800 ret = ast_context_remove_extension2(c, extension, priority, registrar); 02801 ast_unlock_contexts(); 02802 } 02803 return ret; 02804 }
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 2816 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().
02817 { 02818 struct ast_exten *exten, *prev_exten = NULL; 02819 struct ast_exten *peer; 02820 02821 ast_mutex_lock(&con->lock); 02822 02823 /* scan the extension list to find matching extension-registrar */ 02824 for (exten = con->root; exten; prev_exten = exten, exten = exten->next) { 02825 if (!strcmp(exten->exten, extension) && 02826 (!registrar || !strcmp(exten->registrar, registrar))) 02827 break; 02828 } 02829 if (!exten) { 02830 /* we can't find right extension */ 02831 ast_mutex_unlock(&con->lock); 02832 return -1; 02833 } 02834 02835 /* should we free all peers in this extension? (priority == 0)? */ 02836 if (priority == 0) { 02837 /* remove this extension from context list */ 02838 if (prev_exten) 02839 prev_exten->next = exten->next; 02840 else 02841 con->root = exten->next; 02842 02843 /* fire out all peers */ 02844 while ( (peer = exten) ) { 02845 exten = peer->peer; /* prepare for next entry */ 02846 destroy_exten(peer); 02847 } 02848 } else { 02849 /* scan the priority list to remove extension with exten->priority == priority */ 02850 struct ast_exten *previous_peer = NULL; 02851 02852 for (peer = exten; peer; previous_peer = peer, peer = peer->peer) { 02853 if (peer->priority == priority && 02854 (!registrar || !strcmp(peer->registrar, registrar) )) 02855 break; /* found our priority */ 02856 } 02857 if (!peer) { /* not found */ 02858 ast_mutex_unlock(&con->lock); 02859 return -1; 02860 } 02861 /* we are first priority extension? */ 02862 if (!previous_peer) { 02863 /* 02864 * We are first in the priority chain, so must update the extension chain. 02865 * The next node is either the next priority or the next extension 02866 */ 02867 struct ast_exten *next_node = peer->peer ? peer->peer : peer->next; 02868 02869 if (!prev_exten) /* change the root... */ 02870 con->root = next_node; 02871 else 02872 prev_exten->next = next_node; /* unlink */ 02873 if (peer->peer) /* XXX update the new head of the pri list */ 02874 peer->peer->next = peer->next; 02875 } else { /* easy, we are not first priority in extension */ 02876 previous_peer->peer = peer->peer; 02877 } 02878 02879 /* now, free whole priority extension */ 02880 destroy_exten(peer); 02881 /* XXX should we return -1 ? */ 02882 } 02883 ast_mutex_unlock(&con->lock); 02884 return 0; 02885 }
int ast_context_remove_ignorepat | ( | const char * | context, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 4429 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().
04430 { 04431 int ret = -1; 04432 struct ast_context *c = find_context_locked(context); 04433 04434 if (c) { 04435 ret = ast_context_remove_ignorepat2(c, ignorepat, registrar); 04436 ast_unlock_contexts(); 04437 } 04438 return ret; 04439 }
int ast_context_remove_ignorepat2 | ( | struct ast_context * | con, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 4441 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().
04442 { 04443 struct ast_ignorepat *ip, *ipl = NULL; 04444 04445 ast_mutex_lock(&con->lock); 04446 04447 for (ip = con->ignorepats; ip; ip = ip->next) { 04448 if (!strcmp(ip->pattern, ignorepat) && 04449 (!registrar || (registrar == ip->registrar))) { 04450 if (ipl) { 04451 ipl->next = ip->next; 04452 free(ip); 04453 } else { 04454 con->ignorepats = ip->next; 04455 free(ip); 04456 } 04457 ast_mutex_unlock(&con->lock); 04458 return 0; 04459 } 04460 ipl = ip; 04461 } 04462 04463 ast_mutex_unlock(&con->lock); 04464 errno = EINVAL; 04465 return -1; 04466 }
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 2690 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().
02691 { 02692 int ret = -1; 02693 struct ast_context *c = find_context_locked(context); 02694 02695 if (c) { 02696 /* found, remove include from this context ... */ 02697 ret = ast_context_remove_include2(c, include, registrar); 02698 ast_unlock_contexts(); 02699 } 02700 return ret; 02701 }
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 2711 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().
02712 { 02713 struct ast_include *i, *pi = NULL; 02714 int ret = -1; 02715 02716 ast_mutex_lock(&con->lock); 02717 02718 /* find our include */ 02719 for (i = con->includes; i; pi = i, i = i->next) { 02720 if (!strcmp(i->name, include) && 02721 (!registrar || !strcmp(i->registrar, registrar))) { 02722 /* remove from list */ 02723 if (pi) 02724 pi->next = i->next; 02725 else 02726 con->includes = i->next; 02727 /* free include and return */ 02728 free(i); 02729 ret = 0; 02730 break; 02731 } 02732 } 02733 02734 ast_mutex_unlock(&con->lock); 02735 return ret; 02736 }
int ast_context_remove_switch | ( | const char * | context, | |
const char * | sw, | |||
const char * | data, | |||
const char * | registrar | |||
) |
Remove a switch.
Definition at line 2743 of file pbx.c.
References ast_context_remove_switch2(), ast_unlock_contexts(), and find_context_locked().
02744 { 02745 int ret = -1; /* default error return */ 02746 struct ast_context *c = find_context_locked(context); 02747 02748 if (c) { 02749 /* remove switch from this context ... */ 02750 ret = ast_context_remove_switch2(c, sw, data, registrar); 02751 ast_unlock_contexts(); 02752 } 02753 return ret; 02754 }
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 2764 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().
02765 { 02766 struct ast_sw *i; 02767 int ret = -1; 02768 02769 ast_mutex_lock(&con->lock); 02770 02771 /* walk switches */ 02772 AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) { 02773 if (!strcmp(i->name, sw) && !strcmp(i->data, data) && 02774 (!registrar || !strcmp(i->registrar, registrar))) { 02775 /* found, remove from list */ 02776 AST_LIST_REMOVE_CURRENT(&con->alts, list); 02777 free(i); /* free switch and return */ 02778 ret = 0; 02779 break; 02780 } 02781 } 02782 AST_LIST_TRAVERSE_SAFE_END 02783 02784 ast_mutex_unlock(&con->lock); 02785 02786 return ret; 02787 }
int ast_context_unlockmacro | ( | const char * | context | ) |
Unlocks the macrolock in the given context.
Definition at line 2921 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().
02922 { 02923 struct ast_context *c = NULL; 02924 int ret = -1; 02925 02926 ast_lock_contexts(); 02927 02928 while ((c = ast_walk_contexts(c))) { 02929 if (!strcmp(ast_get_context_name(c), context)) { 02930 ret = 0; 02931 break; 02932 } 02933 } 02934 02935 ast_unlock_contexts(); 02936 02937 /* if we found context, unlock macrolock */ 02938 if (ret == 0) 02939 ret = ast_mutex_unlock(&c->macrolock); 02940 02941 return ret; 02942 }
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 6242 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().
06243 { 06244 struct ast_include *inc = NULL; 06245 int res = 0; 06246 06247 while ( (inc = ast_walk_context_includes(con, inc)) ) 06248 if (!ast_context_find(inc->rname)) { 06249 res = -1; 06250 ast_log(LOG_WARNING, "Context '%s' tries includes nonexistent context '%s'\n", 06251 ast_get_context_name(con), inc->rname); 06252 } 06253 return res; 06254 }
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(), odbc_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 odbc_unload_module(), 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(), 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 4551 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().
04552 { 04553 if (!chan) 04554 return -1; 04555 04556 if (!ast_strlen_zero(context)) 04557 ast_copy_string(chan->context, context, sizeof(chan->context)); 04558 if (!ast_strlen_zero(exten)) 04559 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 04560 if (priority > -1) { 04561 chan->priority = priority; 04562 /* see flag description in channel.h for explanation */ 04563 if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP)) 04564 chan->priority--; 04565 } 04566 04567 return 0; 04568 }
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(), and handle_request_subscribe().
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 6099 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 6137 of file pbx.c.
References ast_context::registrar.
Referenced by handle_save_dialplan(), and show_dialplan_helper().
06138 { 06139 return c ? c->registrar : NULL; 06140 }
const char* ast_get_extension_app | ( | struct ast_exten * | e | ) |
Definition at line 6167 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().
06168 { 06169 return e ? e->app : NULL; 06170 }
void* ast_get_extension_app_data | ( | struct ast_exten * | e | ) |
Definition at line 6172 of file pbx.c.
References ast_exten::data.
Referenced by _macro_exec(), ast_get_hint(), handle_save_dialplan(), and print_ext().
06173 { 06174 return e ? e->data : NULL; 06175 }
const char* ast_get_extension_cidmatch | ( | struct ast_exten * | e | ) |
Definition at line 6162 of file pbx.c.
References ast_exten::cidmatch.
Referenced by find_matching_priority(), and handle_save_dialplan().
06163 { 06164 return e ? e->cidmatch : NULL; 06165 }
struct ast_context* ast_get_extension_context | ( | struct ast_exten * | exten | ) |
const char* ast_get_extension_label | ( | struct ast_exten * | exten | ) |
Definition at line 6114 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 6157 of file pbx.c.
References ast_exten::matchcid.
Referenced by find_matching_priority(), and handle_save_dialplan().
06158 { 06159 return e ? e->matchcid : 0; 06160 }
const char* ast_get_extension_name | ( | struct ast_exten * | exten | ) |
Definition at line 6109 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 6129 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 6142 of file pbx.c.
References ast_exten::registrar.
Referenced by handle_save_dialplan(), and show_dialplan_helper().
06143 { 06144 return e ? e->registrar : NULL; 06145 }
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 6124 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().
06125 { 06126 return ip ? ip->pattern : NULL; 06127 }
const char* ast_get_ignorepat_registrar | ( | struct ast_ignorepat * | ip | ) |
Definition at line 6152 of file pbx.c.
References ast_ignorepat::registrar.
Referenced by handle_save_dialplan(), and show_dialplan_helper().
06153 { 06154 return ip ? ip->registrar : NULL; 06155 }
const char* ast_get_include_name | ( | struct ast_include * | inc | ) |
Definition at line 6119 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().
06120 { 06121 return inc ? inc->name : NULL; 06122 }
const char* ast_get_include_registrar | ( | struct ast_include * | i | ) |
Definition at line 6147 of file pbx.c.
References ast_include::registrar.
Referenced by handle_save_dialplan(), and show_dialplan_helper().
06148 { 06149 return i ? i->registrar : NULL; 06150 }
const char* ast_get_switch_data | ( | struct ast_sw * | sw | ) |
Definition at line 6182 of file pbx.c.
References ast_sw::data.
Referenced by handle_save_dialplan(), and show_dialplan_helper().
06183 { 06184 return sw ? sw->data : NULL; 06185 }
const char* ast_get_switch_name | ( | struct ast_sw * | sw | ) |
Definition at line 6177 of file pbx.c.
References ast_sw::name.
Referenced by handle_save_dialplan(), and show_dialplan_helper().
06178 { 06179 return sw ? sw->name : NULL; 06180 }
const char* ast_get_switch_registrar | ( | struct ast_sw * | sw | ) |
Definition at line 6187 of file pbx.c.
References ast_sw::registrar.
Referenced by handle_save_dialplan(), and show_dialplan_helper().
06188 { 06189 return sw ? sw->registrar : NULL; 06190 }
int ast_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 6276 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().
06277 { 06278 return __ast_goto_if_exists(chan, context, exten, priority, 0); 06279 }
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 4517 of file pbx.c.
References ast_context_find(), ast_extension_match(), ast_context::ignorepats, ast_ignorepat::next, and ast_ignorepat::pattern.
Referenced by ast_app_dtget(), disa_exec(), dp_lookup(), dundi_lookup_local(), handle_enbloc_call_message(), handle_soft_key_event_message(), handle_stimulus_message(), mgcp_ss(), skinny_ss(), and ss_thread().
04518 { 04519 struct ast_context *con = ast_context_find(context); 04520 if (con) { 04521 struct ast_ignorepat *pat; 04522 for (pat = con->ignorepats; pat; pat = pat->next) { 04523 if (ast_extension_match(pat->pattern, pattern)) 04524 return 1; 04525 } 04526 } 04527 04528 return 0; 04529 }
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 6086 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().
06087 { 06088 return ast_mutex_lock(&con->lock); 06089 }
int ast_lock_contexts | ( | void | ) |
Locks the context list.
0 | on success | |
-1 | on error |
Definition at line 6073 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().
06074 { 06075 return ast_mutex_lock(&conlock); 06076 }
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 3912 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().
03913 { 03914 struct ast_context *tmp, *lasttmp = NULL; 03915 struct store_hints store = AST_LIST_HEAD_INIT_VALUE; 03916 struct store_hint *this; 03917 struct ast_hint *hint; 03918 struct ast_exten *exten; 03919 int length; 03920 struct ast_state_cb *thiscb, *prevcb; 03921 03922 /* it is very important that this function hold the hint list lock _and_ the conlock 03923 during its operation; not only do we need to ensure that the list of contexts 03924 and extensions does not change, but also that no hint callbacks (watchers) are 03925 added or removed during the merge/delete process 03926 03927 in addition, the locks _must_ be taken in this order, because there are already 03928 other code paths that use this order 03929 */ 03930 ast_mutex_lock(&conlock); 03931 AST_LIST_LOCK(&hints); 03932 03933 /* preserve all watchers for hints associated with this registrar */ 03934 AST_LIST_TRAVERSE(&hints, hint, list) { 03935 if (hint->callbacks && !strcmp(registrar, hint->exten->parent->registrar)) { 03936 length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2 + sizeof(*this); 03937 if (!(this = ast_calloc(1, length))) 03938 continue; 03939 this->callbacks = hint->callbacks; 03940 hint->callbacks = NULL; 03941 this->laststate = hint->laststate; 03942 this->context = this->data; 03943 strcpy(this->data, hint->exten->parent->name); 03944 this->exten = this->data + strlen(this->context) + 1; 03945 strcpy(this->exten, hint->exten->exten); 03946 AST_LIST_INSERT_HEAD(&store, this, list); 03947 } 03948 } 03949 03950 tmp = *extcontexts; 03951 if (registrar) { 03952 /* XXX remove previous contexts from same registrar */ 03953 if (option_debug) 03954 ast_log(LOG_DEBUG, "must remove any reg %s\n", registrar); 03955 __ast_context_destroy(NULL,registrar); 03956 while (tmp) { 03957 lasttmp = tmp; 03958 tmp = tmp->next; 03959 } 03960 } else { 03961 /* XXX remove contexts with the same name */ 03962 while (tmp) { 03963 ast_log(LOG_WARNING, "must remove %s reg %s\n", tmp->name, tmp->registrar); 03964 __ast_context_destroy(tmp,tmp->registrar); 03965 lasttmp = tmp; 03966 tmp = tmp->next; 03967 } 03968 } 03969 if (lasttmp) { 03970 lasttmp->next = contexts; 03971 contexts = *extcontexts; 03972 *extcontexts = NULL; 03973 } else 03974 ast_log(LOG_WARNING, "Requested contexts didn't get merged\n"); 03975 03976 /* restore the watchers for hints that can be found; notify those that 03977 cannot be restored 03978 */ 03979 while ((this = AST_LIST_REMOVE_HEAD(&store, list))) { 03980 exten = ast_hint_extension(NULL, this->context, this->exten); 03981 /* Find the hint in the list of hints */ 03982 AST_LIST_TRAVERSE(&hints, hint, list) { 03983 if (hint->exten == exten) 03984 break; 03985 } 03986 if (!exten || !hint) { 03987 /* this hint has been removed, notify the watchers */ 03988 prevcb = NULL; 03989 thiscb = this->callbacks; 03990 while (thiscb) { 03991 prevcb = thiscb; 03992 thiscb = thiscb->next; 03993 prevcb->callback(this->context, this->exten, AST_EXTENSION_REMOVED, prevcb->data); 03994 free(prevcb); 03995 } 03996 } else { 03997 thiscb = this->callbacks; 03998 while (thiscb->next) 03999 thiscb = thiscb->next; 04000 thiscb->next = hint->callbacks; 04001 hint->callbacks = this->callbacks; 04002 hint->laststate = this->laststate; 04003 } 04004 free(this); 04005 } 04006 04007 AST_LIST_UNLOCK(&hints); 04008 ast_mutex_unlock(&conlock); 04009 04010 return; 04011 }
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 6286 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().
06287 { 06288 char *exten, *pri, *context; 06289 char *stringp; 06290 int ipri; 06291 int mode = 0; 06292 06293 if (ast_strlen_zero(goto_string)) { 06294 ast_log(LOG_WARNING, "Goto requires an argument (optional context|optional extension|priority)\n"); 06295 return -1; 06296 } 06297 stringp = ast_strdupa(goto_string); 06298 context = strsep(&stringp, "|"); /* guaranteed non-null */ 06299 exten = strsep(&stringp, "|"); 06300 pri = strsep(&stringp, "|"); 06301 if (!exten) { /* Only a priority in this one */ 06302 pri = context; 06303 exten = NULL; 06304 context = NULL; 06305 } else if (!pri) { /* Only an extension and priority in this one */ 06306 pri = exten; 06307 exten = context; 06308 context = NULL; 06309 } 06310 if (*pri == '+') { 06311 mode = 1; 06312 pri++; 06313 } else if (*pri == '-') { 06314 mode = -1; 06315 pri++; 06316 } 06317 if (sscanf(pri, "%d", &ipri) != 1) { 06318 if ((ipri = ast_findlabel_extension(chan, context ? context : chan->context, exten ? exten : chan->exten, 06319 pri, chan->cid.cid_num)) < 1) { 06320 ast_log(LOG_WARNING, "Priority '%s' must be a number > 0, or valid label\n", pri); 06321 return -1; 06322 } else 06323 mode = 0; 06324 } 06325 /* At this point we have a priority and maybe an extension and a context */ 06326 06327 if (mode) 06328 ipri = chan->priority + (ipri * mode); 06329 06330 ast_explicit_goto(chan, context, exten, ipri); 06331 ast_cdr_update(chan); 06332 return 0; 06333 06334 }
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 5122 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().
05123 { 05124 struct ast_channel *chan; 05125 struct app_tmp *tmp; 05126 int res = -1, cdr_res = -1; 05127 struct outgoing_helper oh; 05128 pthread_attr_t attr; 05129 05130 memset(&oh, 0, sizeof(oh)); 05131 oh.vars = vars; 05132 oh.account = account; 05133 05134 if (locked_channel) 05135 *locked_channel = NULL; 05136 if (ast_strlen_zero(app)) { 05137 res = -1; 05138 goto outgoing_app_cleanup; 05139 } 05140 if (sync) { 05141 chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh); 05142 if (chan) { 05143 if (chan->cdr) { /* check if the channel already has a cdr record, if not give it one */ 05144 ast_log(LOG_WARNING, "%s already has a call record??\n", chan->name); 05145 } else { 05146 chan->cdr = ast_cdr_alloc(); /* allocate a cdr for the channel */ 05147 if(!chan->cdr) { 05148 /* allocation of the cdr failed */ 05149 free(chan->pbx); 05150 res = -1; 05151 goto outgoing_app_cleanup; 05152 } 05153 /* allocation of the cdr was successful */ 05154 ast_cdr_init(chan->cdr, chan); /* initialize our channel's cdr */ 05155 ast_cdr_start(chan->cdr); 05156 } 05157 ast_set_variables(chan, vars); 05158 if (account) 05159 ast_cdr_setaccount(chan, account); 05160 if (chan->_state == AST_STATE_UP) { 05161 res = 0; 05162 if (option_verbose > 3) 05163 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", chan->name); 05164 tmp = ast_calloc(1, sizeof(*tmp)); 05165 if (!tmp) 05166 res = -1; 05167 else { 05168 ast_copy_string(tmp->app, app, sizeof(tmp->app)); 05169 if (appdata) 05170 ast_copy_string(tmp->data, appdata, sizeof(tmp->data)); 05171 tmp->chan = chan; 05172 if (sync > 1) { 05173 if (locked_channel) 05174 ast_channel_unlock(chan); 05175 ast_pbx_run_app(tmp); 05176 } else { 05177 pthread_attr_init(&attr); 05178 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 05179 if (locked_channel) 05180 ast_channel_lock(chan); 05181 if (ast_pthread_create(&tmp->t, &attr, ast_pbx_run_app, tmp)) { 05182 ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno)); 05183 free(tmp); 05184 if (locked_channel) 05185 ast_channel_unlock(chan); 05186 ast_hangup(chan); 05187 res = -1; 05188 } else { 05189 if (locked_channel) 05190 *locked_channel = chan; 05191 } 05192 pthread_attr_destroy(&attr); 05193 } 05194 } 05195 } else { 05196 if (option_verbose > 3) 05197 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", chan->name); 05198 if (chan->cdr) { /* update the cdr */ 05199 /* here we update the status of the call, which sould be busy. 05200 * if that fails then we set the status to failed */ 05201 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 05202 ast_cdr_failed(chan->cdr); 05203 } 05204 ast_hangup(chan); 05205 } 05206 } 05207 05208 if (res < 0) { /* the call failed for some reason */ 05209 if (*reason == 0) { /* if the call failed (not busy or no answer) 05210 * update the cdr with the failed message */ 05211 cdr_res = ast_pbx_outgoing_cdr_failed(); 05212 if (cdr_res != 0) { 05213 res = cdr_res; 05214 goto outgoing_app_cleanup; 05215 } 05216 } 05217 } 05218 05219 } else { 05220 struct async_stat *as; 05221 if (!(as = ast_calloc(1, sizeof(*as)))) { 05222 res = -1; 05223 goto outgoing_app_cleanup; 05224 } 05225 chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh); 05226 if (!chan) { 05227 free(as); 05228 res = -1; 05229 goto outgoing_app_cleanup; 05230 } 05231 as->chan = chan; 05232 ast_copy_string(as->app, app, sizeof(as->app)); 05233 if (appdata) 05234 ast_copy_string(as->appdata, appdata, sizeof(as->appdata)); 05235 as->timeout = timeout; 05236 ast_set_variables(chan, vars); 05237 if (account) 05238 ast_cdr_setaccount(chan, account); 05239 /* Start a new thread, and get something handling this channel. */ 05240 pthread_attr_init(&attr); 05241 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 05242 if (locked_channel) 05243 ast_channel_lock(chan); 05244 if (ast_pthread_create(&as->p, &attr, async_wait, as)) { 05245 ast_log(LOG_WARNING, "Failed to start async wait\n"); 05246 free(as); 05247 if (locked_channel) 05248 ast_channel_unlock(chan); 05249 ast_hangup(chan); 05250 res = -1; 05251 pthread_attr_destroy(&attr); 05252 goto outgoing_app_cleanup; 05253 } else { 05254 if (locked_channel) 05255 *locked_channel = chan; 05256 } 05257 pthread_attr_destroy(&attr); 05258 res = 0; 05259 } 05260 outgoing_app_cleanup: 05261 ast_variables_destroy(vars); 05262 return res; 05263 }
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 4941 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().
04942 { 04943 /* allocate a channel */ 04944 struct ast_channel *chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, 0); 04945 04946 if (!chan) 04947 return -1; /* failure */ 04948 04949 if (!chan->cdr) { 04950 /* allocation of the cdr failed */ 04951 ast_channel_free(chan); /* free the channel */ 04952 return -1; /* return failure */ 04953 } 04954 04955 /* allocation of the cdr was successful */ 04956 ast_cdr_init(chan->cdr, chan); /* initialize our channel's cdr */ 04957 ast_cdr_start(chan->cdr); /* record the start and stop time */ 04958 ast_cdr_end(chan->cdr); 04959 ast_cdr_failed(chan->cdr); /* set the status to failed */ 04960 ast_cdr_detach(chan->cdr); /* post and free the record */ 04961 ast_channel_free(chan); /* free the channel */ 04962 04963 return 0; /* success */ 04964 }
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 4966 of file pbx.c.
References __ast_request_and_dial(), ast_channel::_state, ast_calloc, ast_cdr_disposition(), ast_cdr_failed(), ast_cdr_setaccount(), ast_channel_alloc(), ast_channel_lock, ast_channel_unlock, ast_exists_extension(), ast_hangup(), ast_log(), ast_pbx_outgoing_cdr_failed(), ast_pbx_run(), ast_pbx_start(), ast_pthread_create, ast_request_and_dial(), ast_set_variables(), AST_STATE_DOWN, AST_STATE_UP, ast_strlen_zero(), ast_variables_destroy(), ast_verbose(), async_wait(), ast_channel::cdr, ast_channel::context, free, ast_channel::hangupcause, LOAD_OH, LOG_ERROR, LOG_WARNING, option_verbose, set_ext_pri(), outgoing_helper::vars, and VERBOSE_PREFIX_4.
Referenced by action_originate(), attempt_thread(), fast_originate(), and orig_exten().
04967 { 04968 struct ast_channel *chan; 04969 struct async_stat *as; 04970 int res = -1, cdr_res = -1; 04971 struct outgoing_helper oh; 04972 pthread_attr_t attr; 04973 04974 if (sync) { 04975 LOAD_OH(oh); 04976 chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh); 04977 if (channel) { 04978 *channel = chan; 04979 if (chan) 04980 ast_channel_lock(chan); 04981 } 04982 if (chan) { 04983 if (chan->_state == AST_STATE_UP) { 04984 res = 0; 04985 if (option_verbose > 3) 04986 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", chan->name); 04987 04988 if (sync > 1) { 04989 if (channel) 04990 ast_channel_unlock(chan); 04991 if (ast_pbx_run(chan)) { 04992 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 04993 if (channel) 04994 *channel = NULL; 04995 ast_hangup(chan); 04996 res = -1; 04997 } 04998 } else { 04999 if (ast_pbx_start(chan)) { 05000 ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name); 05001 if (channel) { 05002 *channel = NULL; 05003 ast_channel_unlock(chan); 05004 } 05005 ast_hangup(chan); 05006 res = -1; 05007 } 05008 } 05009 } else { 05010 if (option_verbose > 3) 05011 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", chan->name); 05012 05013 if (chan->cdr) { /* update the cdr */ 05014 /* here we update the status of the call, which sould be busy. 05015 * if that fails then we set the status to failed */ 05016 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 05017 ast_cdr_failed(chan->cdr); 05018 } 05019 05020 if (channel) { 05021 *channel = NULL; 05022 ast_channel_unlock(chan); 05023 } 05024 ast_hangup(chan); 05025 } 05026 } 05027 05028 if (res < 0) { /* the call failed for some reason */ 05029 if (*reason == 0) { /* if the call failed (not busy or no answer) 05030 * update the cdr with the failed message */ 05031 cdr_res = ast_pbx_outgoing_cdr_failed(); 05032 if (cdr_res != 0) { 05033 res = cdr_res; 05034 goto outgoing_exten_cleanup; 05035 } 05036 } 05037 05038 /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */ 05039 /* check if "failed" exists */ 05040 if (ast_exists_extension(chan, context, "failed", 1, NULL)) { 05041 chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "OutgoingSpoolFailed"); 05042 if (chan) { 05043 if (!ast_strlen_zero(context)) 05044 ast_copy_string(chan->context, context, sizeof(chan->context)); 05045 set_ext_pri(chan, "failed", 1); 05046 ast_set_variables(chan, vars); 05047 if (account) 05048 ast_cdr_setaccount(chan, account); 05049 ast_pbx_run(chan); 05050 } 05051 } 05052 } 05053 } else { 05054 if (!(as = ast_calloc(1, sizeof(*as)))) { 05055 res = -1; 05056 goto outgoing_exten_cleanup; 05057 } 05058 chan = ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name); 05059 if (channel) { 05060 *channel = chan; 05061 if (chan) 05062 ast_channel_lock(chan); 05063 } 05064 if (!chan) { 05065 free(as); 05066 res = -1; 05067 goto outgoing_exten_cleanup; 05068 } 05069 as->chan = chan; 05070 ast_copy_string(as->context, context, sizeof(as->context)); 05071 set_ext_pri(as->chan, exten, priority); 05072 as->timeout = timeout; 05073 ast_set_variables(chan, vars); 05074 if (account) 05075 ast_cdr_setaccount(chan, account); 05076 pthread_attr_init(&attr); 05077 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 05078 if (ast_pthread_create(&as->p, &attr, async_wait, as)) { 05079 ast_log(LOG_WARNING, "Failed to start async wait\n"); 05080 free(as); 05081 if (channel) { 05082 *channel = NULL; 05083 ast_channel_unlock(chan); 05084 } 05085 ast_hangup(chan); 05086 res = -1; 05087 pthread_attr_destroy(&attr); 05088 goto outgoing_exten_cleanup; 05089 } 05090 pthread_attr_destroy(&attr); 05091 res = 0; 05092 } 05093 outgoing_exten_cleanup: 05094 ast_variables_destroy(vars); 05095 return res; 05096 }
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 2643 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().
02644 { 02645 enum ast_pbx_result res = AST_PBX_SUCCESS; 02646 02647 if (increase_call_count(c)) 02648 return AST_PBX_CALL_LIMIT; 02649 02650 res = __ast_pbx_run(c); 02651 decrease_call_count(); 02652 02653 return res; 02654 }
static void* ast_pbx_run_app | ( | void * | data | ) | [static] |
run the application and free the descriptor once done
Definition at line 5106 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().
05107 { 05108 struct app_tmp *tmp = data; 05109 struct ast_app *app; 05110 app = pbx_findapp(tmp->app); 05111 if (app) { 05112 if (option_verbose > 3) 05113 ast_verbose(VERBOSE_PREFIX_4 "Launching %s(%s) on %s\n", tmp->app, tmp->data, tmp->chan->name); 05114 pbx_exec(tmp->chan, app, tmp->data); 05115 } else 05116 ast_log(LOG_WARNING, "No such application '%s'\n", tmp->app); 05117 ast_hangup(tmp->chan); 05118 free(tmp); 05119 return NULL; 05120 }
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 2617 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().
02618 { 02619 pthread_t t; 02620 pthread_attr_t attr; 02621 02622 if (!c) { 02623 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n"); 02624 return AST_PBX_FAILED; 02625 } 02626 02627 if (increase_call_count(c)) 02628 return AST_PBX_CALL_LIMIT; 02629 02630 /* Start a new thread, and get something handling this channel. */ 02631 pthread_attr_init(&attr); 02632 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 02633 if (ast_pthread_create(&t, &attr, pbx_thread, c)) { 02634 ast_log(LOG_WARNING, "Failed to create new channel thread\n"); 02635 pthread_attr_destroy(&attr); 02636 return AST_PBX_FAILED; 02637 } 02638 pthread_attr_destroy(&attr); 02639 02640 return AST_PBX_SUCCESS; 02641 }
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 2945 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().
02946 { 02947 struct ast_app *tmp, *cur = NULL; 02948 char tmps[80]; 02949 int length; 02950 02951 AST_LIST_LOCK(&apps); 02952 AST_LIST_TRAVERSE(&apps, tmp, list) { 02953 if (!strcasecmp(app, tmp->name)) { 02954 ast_log(LOG_WARNING, "Already have an application '%s'\n", app); 02955 AST_LIST_UNLOCK(&apps); 02956 return -1; 02957 } 02958 } 02959 02960 length = sizeof(*tmp) + strlen(app) + 1; 02961 02962 if (!(tmp = ast_calloc(1, length))) { 02963 AST_LIST_UNLOCK(&apps); 02964 return -1; 02965 } 02966 02967 strcpy(tmp->name, app); 02968 tmp->execute = execute; 02969 tmp->synopsis = synopsis; 02970 tmp->description = description; 02971 02972 /* Store in alphabetical order */ 02973 AST_LIST_TRAVERSE_SAFE_BEGIN(&apps, cur, list) { 02974 if (strcasecmp(tmp->name, cur->name) < 0) { 02975 AST_LIST_INSERT_BEFORE_CURRENT(&apps, tmp, list); 02976 break; 02977 } 02978 } 02979 AST_LIST_TRAVERSE_SAFE_END 02980 if (!cur) 02981 AST_LIST_INSERT_TAIL(&apps, tmp, list); 02982 02983 if (option_verbose > 1) 02984 ast_verbose( VERBOSE_PREFIX_2 "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps))); 02985 02986 AST_LIST_UNLOCK(&apps); 02987 02988 return 0; 02989 }
int ast_register_switch | ( | struct ast_switch * | sw | ) |
Register an alternative dialplan switch.
sw | switch to register |
Definition at line 2995 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().
02996 { 02997 struct ast_switch *tmp; 02998 02999 AST_LIST_LOCK(&switches); 03000 AST_LIST_TRAVERSE(&switches, tmp, list) { 03001 if (!strcasecmp(tmp->name, sw->name)) { 03002 AST_LIST_UNLOCK(&switches); 03003 ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name); 03004 return -1; 03005 } 03006 } 03007 AST_LIST_INSERT_TAIL(&switches, sw, list); 03008 AST_LIST_UNLOCK(&switches); 03009 03010 return 0; 03011 }
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 6091 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().
06092 { 06093 return ast_mutex_unlock(&con->lock); 06094 }
int ast_unlock_contexts | ( | void | ) |
Unlocks contexts.
0 | on success | |
-1 | on failure |
Definition at line 6078 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().
06079 { 06080 return ast_mutex_unlock(&conlock); 06081 }
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 3826 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().
03827 { 03828 struct ast_app *tmp; 03829 03830 AST_LIST_LOCK(&apps); 03831 AST_LIST_TRAVERSE_SAFE_BEGIN(&apps, tmp, list) { 03832 if (!strcasecmp(app, tmp->name)) { 03833 AST_LIST_REMOVE_CURRENT(&apps, list); 03834 if (option_verbose > 1) 03835 ast_verbose( VERBOSE_PREFIX_2 "Unregistered application '%s'\n", tmp->name); 03836 free(tmp); 03837 break; 03838 } 03839 } 03840 AST_LIST_TRAVERSE_SAFE_END 03841 AST_LIST_UNLOCK(&apps); 03842 03843 return tmp ? 0 : -1; 03844 }
void ast_unregister_switch | ( | struct ast_switch * | sw | ) |
Unregister an alternative switch.
sw | switch to unregister |
Definition at line 3013 of file pbx.c.
References AST_LIST_LOCK, AST_LIST_REMOVE, and AST_LIST_UNLOCK.
Referenced by __unload_module(), and unload_module().
03014 { 03015 AST_LIST_LOCK(&switches); 03016 AST_LIST_REMOVE(&switches, sw, list); 03017 AST_LIST_UNLOCK(&switches); 03018 }
struct ast_exten* ast_walk_context_extensions | ( | struct ast_context * | con, | |
struct ast_exten * | exten | |||
) |
Definition at line 6200 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().
06202 { 06203 if (!exten) 06204 return con ? con->root : NULL; 06205 else 06206 return exten->next; 06207 }
struct ast_ignorepat* ast_walk_context_ignorepats | ( | struct ast_context * | con, | |
struct ast_ignorepat * | ip | |||
) |
Definition at line 6233 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().
06235 { 06236 if (!ip) 06237 return con ? con->ignorepats : NULL; 06238 else 06239 return ip->next; 06240 }
struct ast_include* ast_walk_context_includes | ( | struct ast_context * | con, | |
struct ast_include * | inc | |||
) |
Definition at line 6224 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().
06226 { 06227 if (!inc) 06228 return con ? con->includes : NULL; 06229 else 06230 return inc->next; 06231 }
struct ast_sw* ast_walk_context_switches | ( | struct ast_context * | con, | |
struct ast_sw * | sw | |||
) |
Definition at line 6209 of file pbx.c.
References AST_LIST_FIRST, and AST_LIST_NEXT.
Referenced by handle_save_dialplan(), and show_dialplan_helper().
06211 { 06212 if (!sw) 06213 return con ? AST_LIST_FIRST(&con->alts) : NULL; 06214 else 06215 return AST_LIST_NEXT(sw, list); 06216 }
struct ast_context* ast_walk_contexts | ( | struct ast_context * | con | ) |
Definition at line 6195 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 6218 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 4878 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().
04879 { 04880 struct async_stat *as = data; 04881 struct ast_channel *chan = as->chan; 04882 int timeout = as->timeout; 04883 int res; 04884 struct ast_frame *f; 04885 struct ast_app *app; 04886 04887 while (timeout && (chan->_state != AST_STATE_UP)) { 04888 res = ast_waitfor(chan, timeout); 04889 if (res < 1) 04890 break; 04891 if (timeout > -1) 04892 timeout = res; 04893 f = ast_read(chan); 04894 if (!f) 04895 break; 04896 if (f->frametype == AST_FRAME_CONTROL) { 04897 if ((f->subclass == AST_CONTROL_BUSY) || 04898 (f->subclass == AST_CONTROL_CONGESTION) ) { 04899 ast_frfree(f); 04900 break; 04901 } 04902 } 04903 ast_frfree(f); 04904 } 04905 if (chan->_state == AST_STATE_UP) { 04906 if (!ast_strlen_zero(as->app)) { 04907 app = pbx_findapp(as->app); 04908 if (app) { 04909 if (option_verbose > 2) 04910 ast_verbose(VERBOSE_PREFIX_3 "Launching %s(%s) on %s\n", as->app, as->appdata, chan->name); 04911 pbx_exec(chan, app, as->appdata); 04912 } else 04913 ast_log(LOG_WARNING, "No such application '%s'\n", as->app); 04914 } else { 04915 if (!ast_strlen_zero(as->context)) 04916 ast_copy_string(chan->context, as->context, sizeof(chan->context)); 04917 if (!ast_strlen_zero(as->exten)) 04918 ast_copy_string(chan->exten, as->exten, sizeof(chan->exten)); 04919 if (as->priority > 0) 04920 chan->priority = as->priority; 04921 /* Run the PBX */ 04922 if (ast_pbx_run(chan)) { 04923 ast_log(LOG_ERROR, "Failed to start PBX on %s\n", chan->name); 04924 } else { 04925 /* PBX will have taken care of this */ 04926 chan = NULL; 04927 } 04928 } 04929 } 04930 free(as); 04931 if (chan) 04932 ast_hangup(chan); 04933 return NULL; 04934 }
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 3071 of file pbx.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, and strdup.
03072 { 03073 struct ast_app *a; 03074 char *ret = NULL; 03075 int which = 0; 03076 int wordlen = strlen(word); 03077 03078 /* return the n-th [partial] matching entry */ 03079 AST_LIST_LOCK(&apps); 03080 AST_LIST_TRAVERSE(&apps, a, list) { 03081 if (!strncasecmp(word, a->name, wordlen) && ++which > state) { 03082 ret = strdup(a->name); 03083 break; 03084 } 03085 } 03086 AST_LIST_UNLOCK(&apps); 03087 03088 return ret; 03089 }
static char* complete_show_applications | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 3432 of file pbx.c.
References ast_cli_complete().
03433 { 03434 static char* choices[] = { "like", "describing", NULL }; 03435 03436 return (pos != 3) ? NULL : ast_cli_complete(word, choices, state); 03437 }
static char* complete_show_applications_deprecated | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 3425 of file pbx.c.
References ast_cli_complete().
03426 { 03427 static char* choices[] = { "like", "describing", NULL }; 03428 03429 return (pos != 2) ? NULL : ast_cli_complete(word, choices, state); 03430 }
static char* complete_show_dialplan_context | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 3442 of file pbx.c.
References ast_get_context_name(), ast_lock_contexts(), ast_strdup, ast_unlock_contexts(), and ast_walk_contexts().
03444 { 03445 struct ast_context *c = NULL; 03446 char *ret = NULL; 03447 int which = 0; 03448 int wordlen; 03449 03450 /* we are do completion of [exten@]context on second position only */ 03451 if (pos != 2) 03452 return NULL; 03453 03454 ast_lock_contexts(); 03455 03456 wordlen = strlen(word); 03457 03458 /* walk through all contexts and return the n-th match */ 03459 while ( (c = ast_walk_contexts(c)) ) { 03460 if (!strncasecmp(word, ast_get_context_name(c), wordlen) && ++which > state) { 03461 ret = ast_strdup(ast_get_context_name(c)); 03462 break; 03463 } 03464 } 03465 03466 ast_unlock_contexts(); 03467 03468 return ret; 03469 }
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 2579 of file pbx.c.
References ast_mutex_lock(), ast_mutex_unlock(), and countcalls.
Referenced by ast_pbx_run(), and pbx_thread().
02580 { 02581 ast_mutex_lock(&maxcalllock); 02582 if (countcalls > 0) 02583 countcalls--; 02584 ast_mutex_unlock(&maxcalllock); 02585 }
static void destroy_exten | ( | struct ast_exten * | e | ) | [static] |
Definition at line 2587 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().
02588 { 02589 if (e->priority == PRIORITY_HINT) 02590 ast_remove_hint(e); 02591 02592 if (e->datad) 02593 e->datad(e->data); 02594 free(e); 02595 }
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 4630 of file pbx.c.
Referenced by ast_add_extension2().
04631 { 04632 int count=0; 04633 04634 while (*src && (count < len - 1)) { 04635 switch(*src) { 04636 case ' ': 04637 /* otherwise exten => [a-b],1,... doesn't work */ 04638 /* case '-': */ 04639 /* Ignore */ 04640 break; 04641 default: 04642 *dst = *src; 04643 dst++; 04644 } 04645 src++; 04646 count++; 04647 } 04648 *dst = '\0'; 04649 04650 return count; 04651 }
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 2671 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().
02672 { 02673 struct ast_context *c = NULL; 02674 02675 ast_lock_contexts(); 02676 while ( (c = ast_walk_contexts(c)) ) { 02677 if (!strcmp(ast_get_context_name(c), context)) 02678 return c; 02679 } 02680 ast_unlock_contexts(); 02681 02682 return NULL; 02683 }
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 4052 of file pbx.c.
References ast_log(), ast_strlen_zero(), LOG_WARNING, lookup_name(), and s.
Referenced by ast_build_timing().
04053 { 04054 int s, e; /* start and ending position */ 04055 unsigned int mask = 0; 04056 04057 /* Check for whole range */ 04058 if (ast_strlen_zero(src) || !strcmp(src, "*")) { 04059 s = 0; 04060 e = max - 1; 04061 } else { 04062 /* Get start and ending position */ 04063 char *c = strchr(src, '-'); 04064 if (c) 04065 *c++ = '\0'; 04066 /* Find the start */ 04067 s = lookup_name(src, names, max); 04068 if (!s) { 04069 ast_log(LOG_WARNING, "Invalid %s '%s', assuming none\n", msg, src); 04070 return 0; 04071 } 04072 s--; 04073 if (c) { /* find end of range */ 04074 e = lookup_name(c, names, max); 04075 if (!e) { 04076 ast_log(LOG_WARNING, "Invalid end %s '%s', assuming none\n", msg, c); 04077 return 0; 04078 } 04079 e--; 04080 } else 04081 e = s; 04082 } 04083 /* Fill the mask. Remember that ranges are cyclic */ 04084 mask = 1 << e; /* initialize with last element */ 04085 while (s != e) { 04086 if (s >= max) { 04087 s = 0; 04088 mask |= (1 << s); 04089 } else { 04090 mask |= (1 << s); 04091 s++; 04092 } 04093 } 04094 return mask; 04095 }
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 4098 of file pbx.c.
References ast_log(), ast_strlen_zero(), LOG_WARNING, and ast_timing::minmask.
Referenced by ast_build_timing().
04099 { 04100 char *e; 04101 int x; 04102 int s1, s2; 04103 int e1, e2; 04104 /* int cth, ctm; */ 04105 04106 /* start disabling all times, fill the fields with 0's, as they may contain garbage */ 04107 memset(i->minmask, 0, sizeof(i->minmask)); 04108 04109 /* 2-minutes per bit, since the mask has only 32 bits :( */ 04110 /* Star is all times */ 04111 if (ast_strlen_zero(times) || !strcmp(times, "*")) { 04112 for (x=0; x<24; x++) 04113 i->minmask[x] = 0x3fffffff; /* 30 bits */ 04114 return; 04115 } 04116 /* Otherwise expect a range */ 04117 e = strchr(times, '-'); 04118 if (!e) { 04119 ast_log(LOG_WARNING, "Time range is not valid. Assuming no restrictions based on time.\n"); 04120 return; 04121 } 04122 *e++ = '\0'; 04123 /* XXX why skip non digits ? */ 04124 while (*e && !isdigit(*e)) 04125 e++; 04126 if (!*e) { 04127 ast_log(LOG_WARNING, "Invalid time range. Assuming no restrictions based on time.\n"); 04128 return; 04129 } 04130 if (sscanf(times, "%d:%d", &s1, &s2) != 2) { 04131 ast_log(LOG_WARNING, "%s isn't a time. Assuming no restrictions based on time.\n", times); 04132 return; 04133 } 04134 if (sscanf(e, "%d:%d", &e1, &e2) != 2) { 04135 ast_log(LOG_WARNING, "%s isn't a time. Assuming no restrictions based on time.\n", e); 04136 return; 04137 } 04138 /* XXX this needs to be optimized */ 04139 #if 1 04140 s1 = s1 * 30 + s2/2; 04141 if ((s1 < 0) || (s1 >= 24*30)) { 04142 ast_log(LOG_WARNING, "%s isn't a valid start time. Assuming no time.\n", times); 04143 return; 04144 } 04145 e1 = e1 * 30 + e2/2; 04146 if ((e1 < 0) || (e1 >= 24*30)) { 04147 ast_log(LOG_WARNING, "%s isn't a valid end time. Assuming no time.\n", e); 04148 return; 04149 } 04150 /* Go through the time and enable each appropriate bit */ 04151 for (x=s1;x != e1;x = (x + 1) % (24 * 30)) { 04152 i->minmask[x/30] |= (1 << (x % 30)); 04153 } 04154 /* Do the last one */ 04155 i->minmask[x/30] |= (1 << (x % 30)); 04156 #else 04157 for (cth=0; cth<24; cth++) { 04158 /* Initialize masks to blank */ 04159 i->minmask[cth] = 0; 04160 for (ctm=0; ctm<30; ctm++) { 04161 if ( 04162 /* First hour with more than one hour */ 04163 (((cth == s1) && (ctm >= s2)) && 04164 ((cth < e1))) 04165 /* Only one hour */ 04166 || (((cth == s1) && (ctm >= s2)) && 04167 ((cth == e1) && (ctm <= e2))) 04168 /* In between first and last hours (more than 2 hours) */ 04169 || ((cth > s1) && 04170 (cth < e1)) 04171 /* Last hour with more than one hour */ 04172 || ((cth > s1) && 04173 ((cth == e1) && (ctm <= e2))) 04174 ) 04175 i->minmask[cth] |= (1 << (ctm / 2)); 04176 } 04177 } 04178 #endif 04179 /* All done */ 04180 return; 04181 }
static int handle_set_global | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3727 of file pbx.c.
References ast_cli(), pbx_builtin_setvar_helper(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03728 { 03729 if (argc != 5) 03730 return RESULT_SHOWUSAGE; 03731 03732 pbx_builtin_setvar_helper(NULL, argv[3], argv[4]); 03733 ast_cli(fd, "\n -- Global variable %s set to %s\n", argv[3], argv[4]); 03734 03735 return RESULT_SUCCESS; 03736 }
static int handle_set_global_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
CLI support for setting global variables.
Definition at line 3715 of file pbx.c.
References ast_cli(), pbx_builtin_setvar_helper(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03716 { 03717 if (argc != 4) 03718 return RESULT_SHOWUSAGE; 03719 03720 pbx_builtin_setvar_helper(NULL, argv[2], argv[3]); 03721 ast_cli(fd, "\n -- Global variable %s set to %s\n", argv[2], argv[3]); 03722 03723 return RESULT_SUCCESS; 03724 }
static int handle_show_application | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3161 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().
03162 { 03163 struct ast_app *a; 03164 int app, no_registered_app = 1; 03165 03166 if (argc < 4) 03167 return RESULT_SHOWUSAGE; 03168 03169 /* ... go through all applications ... */ 03170 AST_LIST_LOCK(&apps); 03171 AST_LIST_TRAVERSE(&apps, a, list) { 03172 /* ... compare this application name with all arguments given 03173 * to 'show application' command ... */ 03174 for (app = 3; app < argc; app++) { 03175 if (!strcasecmp(a->name, argv[app])) { 03176 /* Maximum number of characters added by terminal coloring is 22 */ 03177 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40]; 03178 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL; 03179 int synopsis_size, description_size; 03180 03181 no_registered_app = 0; 03182 03183 if (a->synopsis) 03184 synopsis_size = strlen(a->synopsis) + 23; 03185 else 03186 synopsis_size = strlen("Not available") + 23; 03187 synopsis = alloca(synopsis_size); 03188 03189 if (a->description) 03190 description_size = strlen(a->description) + 23; 03191 else 03192 description_size = strlen("Not available") + 23; 03193 description = alloca(description_size); 03194 03195 if (synopsis && description) { 03196 snprintf(info, 64 + AST_MAX_APP, "\n -= Info about application '%s' =- \n\n", a->name); 03197 term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22); 03198 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 03199 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40); 03200 term_color(synopsis, 03201 a->synopsis ? a->synopsis : "Not available", 03202 COLOR_CYAN, 0, synopsis_size); 03203 term_color(description, 03204 a->description ? a->description : "Not available", 03205 COLOR_CYAN, 0, description_size); 03206 03207 ast_cli(fd,"%s%s%s\n\n%s%s\n", infotitle, syntitle, synopsis, destitle, description); 03208 } else { 03209 /* ... one of our applications, show info ...*/ 03210 ast_cli(fd,"\n -= Info about application '%s' =- \n\n" 03211 "[Synopsis]\n %s\n\n" 03212 "[Description]\n%s\n", 03213 a->name, 03214 a->synopsis ? a->synopsis : "Not available", 03215 a->description ? a->description : "Not available"); 03216 } 03217 } 03218 } 03219 } 03220 AST_LIST_UNLOCK(&apps); 03221 03222 /* we found at least one app? no? */ 03223 if (no_registered_app) { 03224 ast_cli(fd, "Your application(s) is (are) not registered\n"); 03225 return RESULT_FAILURE; 03226 } 03227 03228 return RESULT_SUCCESS; 03229 }
static int handle_show_application_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3091 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().
03092 { 03093 struct ast_app *a; 03094 int app, no_registered_app = 1; 03095 03096 if (argc < 3) 03097 return RESULT_SHOWUSAGE; 03098 03099 /* ... go through all applications ... */ 03100 AST_LIST_LOCK(&apps); 03101 AST_LIST_TRAVERSE(&apps, a, list) { 03102 /* ... compare this application name with all arguments given 03103 * to 'show application' command ... */ 03104 for (app = 2; app < argc; app++) { 03105 if (!strcasecmp(a->name, argv[app])) { 03106 /* Maximum number of characters added by terminal coloring is 22 */ 03107 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40]; 03108 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL; 03109 int synopsis_size, description_size; 03110 03111 no_registered_app = 0; 03112 03113 if (a->synopsis) 03114 synopsis_size = strlen(a->synopsis) + 23; 03115 else 03116 synopsis_size = strlen("Not available") + 23; 03117 synopsis = alloca(synopsis_size); 03118 03119 if (a->description) 03120 description_size = strlen(a->description) + 23; 03121 else 03122 description_size = strlen("Not available") + 23; 03123 description = alloca(description_size); 03124 03125 if (synopsis && description) { 03126 snprintf(info, 64 + AST_MAX_APP, "\n -= Info about application '%s' =- \n\n", a->name); 03127 term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22); 03128 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 03129 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40); 03130 term_color(synopsis, 03131 a->synopsis ? a->synopsis : "Not available", 03132 COLOR_CYAN, 0, synopsis_size); 03133 term_color(description, 03134 a->description ? a->description : "Not available", 03135 COLOR_CYAN, 0, description_size); 03136 03137 ast_cli(fd,"%s%s%s\n\n%s%s\n", infotitle, syntitle, synopsis, destitle, description); 03138 } else { 03139 /* ... one of our applications, show info ...*/ 03140 ast_cli(fd,"\n -= Info about application '%s' =- \n\n" 03141 "[Synopsis]\n %s\n\n" 03142 "[Description]\n%s\n", 03143 a->name, 03144 a->synopsis ? a->synopsis : "Not available", 03145 a->description ? a->description : "Not available"); 03146 } 03147 } 03148 } 03149 } 03150 AST_LIST_UNLOCK(&apps); 03151 03152 /* we found at least one app? no? */ 03153 if (no_registered_app) { 03154 ast_cli(fd, "Your application(s) is (are) not registered\n"); 03155 return RESULT_FAILURE; 03156 } 03157 03158 return RESULT_SUCCESS; 03159 }
static int handle_show_applications | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3356 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.
03357 { 03358 struct ast_app *a; 03359 int like = 0, describing = 0; 03360 int total_match = 0; /* Number of matches in like clause */ 03361 int total_apps = 0; /* Number of apps registered */ 03362 03363 AST_LIST_LOCK(&apps); 03364 03365 if (AST_LIST_EMPTY(&apps)) { 03366 ast_cli(fd, "There are no registered applications\n"); 03367 AST_LIST_UNLOCK(&apps); 03368 return -1; 03369 } 03370 03371 /* core list applications like <keyword> */ 03372 if ((argc == 5) && (!strcmp(argv[3], "like"))) { 03373 like = 1; 03374 } else if ((argc > 4) && (!strcmp(argv[3], "describing"))) { 03375 describing = 1; 03376 } 03377 03378 /* core list applications describing <keyword1> [<keyword2>] [...] */ 03379 if ((!like) && (!describing)) { 03380 ast_cli(fd, " -= Registered Asterisk Applications =-\n"); 03381 } else { 03382 ast_cli(fd, " -= Matching Asterisk Applications =-\n"); 03383 } 03384 03385 AST_LIST_TRAVERSE(&apps, a, list) { 03386 int printapp = 0; 03387 total_apps++; 03388 if (like) { 03389 if (strcasestr(a->name, argv[4])) { 03390 printapp = 1; 03391 total_match++; 03392 } 03393 } else if (describing) { 03394 if (a->description) { 03395 /* Match all words on command line */ 03396 int i; 03397 printapp = 1; 03398 for (i = 4; i < argc; i++) { 03399 if (!strcasestr(a->description, argv[i])) { 03400 printapp = 0; 03401 } else { 03402 total_match++; 03403 } 03404 } 03405 } 03406 } else { 03407 printapp = 1; 03408 } 03409 03410 if (printapp) { 03411 ast_cli(fd," %20s: %s\n", a->name, a->synopsis ? a->synopsis : "<Synopsis not available>"); 03412 } 03413 } 03414 if ((!like) && (!describing)) { 03415 ast_cli(fd, " -= %d Applications Registered =-\n",total_apps); 03416 } else { 03417 ast_cli(fd, " -= %d Applications Matching =-\n",total_match); 03418 } 03419 03420 AST_LIST_UNLOCK(&apps); 03421 03422 return RESULT_SUCCESS; 03423 }
static int handle_show_applications_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3288 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.
03289 { 03290 struct ast_app *a; 03291 int like = 0, describing = 0; 03292 int total_match = 0; /* Number of matches in like clause */ 03293 int total_apps = 0; /* Number of apps registered */ 03294 03295 AST_LIST_LOCK(&apps); 03296 03297 if (AST_LIST_EMPTY(&apps)) { 03298 ast_cli(fd, "There are no registered applications\n"); 03299 AST_LIST_UNLOCK(&apps); 03300 return -1; 03301 } 03302 03303 /* show applications like <keyword> */ 03304 if ((argc == 4) && (!strcmp(argv[2], "like"))) { 03305 like = 1; 03306 } else if ((argc > 3) && (!strcmp(argv[2], "describing"))) { 03307 describing = 1; 03308 } 03309 03310 /* show applications describing <keyword1> [<keyword2>] [...] */ 03311 if ((!like) && (!describing)) { 03312 ast_cli(fd, " -= Registered Asterisk Applications =-\n"); 03313 } else { 03314 ast_cli(fd, " -= Matching Asterisk Applications =-\n"); 03315 } 03316 03317 AST_LIST_TRAVERSE(&apps, a, list) { 03318 int printapp = 0; 03319 total_apps++; 03320 if (like) { 03321 if (strcasestr(a->name, argv[3])) { 03322 printapp = 1; 03323 total_match++; 03324 } 03325 } else if (describing) { 03326 if (a->description) { 03327 /* Match all words on command line */ 03328 int i; 03329 printapp = 1; 03330 for (i = 3; i < argc; i++) { 03331 if (!strcasestr(a->description, argv[i])) { 03332 printapp = 0; 03333 } else { 03334 total_match++; 03335 } 03336 } 03337 } 03338 } else { 03339 printapp = 1; 03340 } 03341 03342 if (printapp) { 03343 ast_cli(fd," %20s: %s\n", a->name, a->synopsis ? a->synopsis : "<Synopsis not available>"); 03344 } 03345 } 03346 if ((!like) && (!describing)) { 03347 ast_cli(fd, " -= %d Applications Registered =-\n",total_apps); 03348 } else { 03349 ast_cli(fd, " -= %d Applications Matching =-\n",total_match); 03350 } 03351 03352 AST_LIST_UNLOCK(&apps); 03353 03354 return RESULT_SUCCESS; 03355 }
static int handle_show_dialplan | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3642 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().
03643 { 03644 char *exten = NULL, *context = NULL; 03645 /* Variables used for different counters */ 03646 struct dialplan_counters counters; 03647 03648 const char *incstack[AST_PBX_MAX_STACK]; 03649 memset(&counters, 0, sizeof(counters)); 03650 03651 if (argc != 2 && argc != 3) 03652 return RESULT_SHOWUSAGE; 03653 03654 /* we obtain [exten@]context? if yes, split them ... */ 03655 if (argc == 3) { 03656 if (strchr(argv[2], '@')) { /* split into exten & context */ 03657 context = ast_strdupa(argv[2]); 03658 exten = strsep(&context, "@"); 03659 /* change empty strings to NULL */ 03660 if (ast_strlen_zero(exten)) 03661 exten = NULL; 03662 } else { /* no '@' char, only context given */ 03663 context = argv[2]; 03664 } 03665 if (ast_strlen_zero(context)) 03666 context = NULL; 03667 } 03668 /* else Show complete dial plan, context and exten are NULL */ 03669 show_dialplan_helper(fd, context, exten, &counters, NULL, 0, incstack); 03670 03671 /* check for input failure and throw some error messages */ 03672 if (context && !counters.context_existence) { 03673 ast_cli(fd, "There is no existence of '%s' context\n", context); 03674 return RESULT_FAILURE; 03675 } 03676 03677 if (exten && !counters.extension_existence) { 03678 if (context) 03679 ast_cli(fd, "There is no existence of %s@%s extension\n", 03680 exten, context); 03681 else 03682 ast_cli(fd, 03683 "There is no existence of '%s' extension in all contexts\n", 03684 exten); 03685 return RESULT_FAILURE; 03686 } 03687 03688 ast_cli(fd,"-= %d %s (%d %s) in %d %s. =-\n", 03689 counters.total_exten, counters.total_exten == 1 ? "extension" : "extensions", 03690 counters.total_prio, counters.total_prio == 1 ? "priority" : "priorities", 03691 counters.total_context, counters.total_context == 1 ? "context" : "contexts"); 03692 03693 /* everything ok */ 03694 return RESULT_SUCCESS; 03695 }
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 3698 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.
03699 { 03700 int i = 0; 03701 struct ast_var_t *newvariable; 03702 03703 ast_mutex_lock(&globalslock); 03704 AST_LIST_TRAVERSE (&globals, newvariable, entries) { 03705 i++; 03706 ast_cli(fd, " %s=%s\n", ast_var_name(newvariable), ast_var_value(newvariable)); 03707 } 03708 ast_mutex_unlock(&globalslock); 03709 ast_cli(fd, "\n -- %d variables\n", i); 03710 03711 return RESULT_SUCCESS; 03712 }
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 3232 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.
03233 { 03234 struct ast_hint *hint; 03235 int num = 0; 03236 int watchers; 03237 struct ast_state_cb *watcher; 03238 03239 if (AST_LIST_EMPTY(&hints)) { 03240 ast_cli(fd, "There are no registered dialplan hints\n"); 03241 return RESULT_SUCCESS; 03242 } 03243 /* ... we have hints ... */ 03244 ast_cli(fd, "\n -= Registered Asterisk Dial Plan Hints =-\n"); 03245 AST_LIST_LOCK(&hints); 03246 AST_LIST_TRAVERSE(&hints, hint, list) { 03247 watchers = 0; 03248 for (watcher = hint->callbacks; watcher; watcher = watcher->next) 03249 watchers++; 03250 ast_cli(fd, " %20s@%-20.20s: %-20.20s State:%-15.15s Watchers %2d\n", 03251 ast_get_extension_name(hint->exten), 03252 ast_get_context_name(ast_get_extension_context(hint->exten)), 03253 ast_get_extension_app(hint->exten), 03254 ast_extension_state2str(hint->laststate), watchers); 03255 num++; 03256 } 03257 ast_cli(fd, "----------------\n"); 03258 ast_cli(fd, "- %d hints registered\n", num); 03259 AST_LIST_UNLOCK(&hints); 03260 return RESULT_SUCCESS; 03261 }
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 3264 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.
03265 { 03266 struct ast_switch *sw; 03267 03268 AST_LIST_LOCK(&switches); 03269 03270 if (AST_LIST_EMPTY(&switches)) { 03271 AST_LIST_UNLOCK(&switches); 03272 ast_cli(fd, "There are no registered alternative switches\n"); 03273 return RESULT_SUCCESS; 03274 } 03275 03276 ast_cli(fd, "\n -= Registered Asterisk Alternative Switches =-\n"); 03277 AST_LIST_TRAVERSE(&switches, sw, list) 03278 ast_cli(fd, "%s: %s\n", sw->name, sw->description); 03279 03280 AST_LIST_UNLOCK(&switches); 03281 03282 return RESULT_SUCCESS; 03283 }
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 2554 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().
02555 { 02556 int failed = 0; 02557 double curloadavg; 02558 ast_mutex_lock(&maxcalllock); 02559 if (option_maxcalls) { 02560 if (countcalls >= option_maxcalls) { 02561 ast_log(LOG_NOTICE, "Maximum call limit of %d calls exceeded by '%s'!\n", option_maxcalls, c->name); 02562 failed = -1; 02563 } 02564 } 02565 if (option_maxload) { 02566 getloadavg(&curloadavg, 1); 02567 if (curloadavg >= option_maxload) { 02568 ast_log(LOG_NOTICE, "Maximum loadavg limit of %f load exceeded by '%s' (currently %f)!\n", option_maxload, c->name, curloadavg); 02569 failed = -1; 02570 } 02571 } 02572 if (!failed) 02573 countcalls++; 02574 ast_mutex_unlock(&maxcalllock); 02575 02576 return failed; 02577 }
int load_pbx | ( | void | ) |
Provided by pbx.c
Definition at line 6047 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().
06048 { 06049 int x; 06050 06051 /* Initialize the PBX */ 06052 if (option_verbose) { 06053 ast_verbose( "Asterisk PBX Core Initializing\n"); 06054 ast_verbose( "Registering builtin applications:\n"); 06055 } 06056 ast_cli_register_multiple(pbx_cli, sizeof(pbx_cli) / sizeof(struct ast_cli_entry)); 06057 06058 /* Register builtin applications */ 06059 for (x=0; x<sizeof(builtins) / sizeof(struct pbx_builtin); x++) { 06060 if (option_verbose) 06061 ast_verbose( VERBOSE_PREFIX_1 "[%s]\n", builtins[x].name); 06062 if (ast_register_application(builtins[x].name, builtins[x].execute, builtins[x].synopsis, builtins[x].description)) { 06063 ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name); 06064 return -1; 06065 } 06066 } 06067 return 0; 06068 }
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 4034 of file pbx.c.
Referenced by get_range().
04035 { 04036 int i; 04037 04038 if (names) { 04039 for (i = 0; names[i]; i++) { 04040 if (!strcasecmp(s, names[i])) 04041 return i+1; 04042 } 04043 } else if (sscanf(s, "%d", &i) == 1 && i >= 1 && i <= max) { 04044 return i; 04045 } 04046 return 0; /* error return */ 04047 }
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 5949 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().
05950 { 05951 struct ast_var_t *vardata; 05952 05953 ast_mutex_lock(&globalslock); 05954 while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries))) 05955 ast_var_delete(vardata); 05956 ast_mutex_unlock(&globalslock); 05957 }
const char* pbx_builtin_getvar_helper | ( | struct ast_channel * | chan, | |
const char * | name | |||
) |
Definition at line 5749 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(), agent_hangup(), agent_read(), agentmonitoroutgoing_exec(), ast_bridge_call(), ast_channel_bridge(), 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(), 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(), sla_trunk_exec(), speech_background(), try_calling(), try_suggested_sip_codec(), txfax_exec(), wait_for_answer(), zt_call(), and zt_hangup().
05750 { 05751 struct ast_var_t *variables; 05752 const char *ret = NULL; 05753 int i; 05754 struct varshead *places[2] = { NULL, &globals }; 05755 05756 if (!name) 05757 return NULL; 05758 if (chan) 05759 places[0] = &chan->varshead; 05760 05761 for (i = 0; i < 2; i++) { 05762 if (!places[i]) 05763 continue; 05764 if (places[i] == &globals) 05765 ast_mutex_lock(&globalslock); 05766 AST_LIST_TRAVERSE(places[i], variables, entries) { 05767 if (!strcmp(name, ast_var_name(variables))) { 05768 ret = ast_var_value(variables); 05769 break; 05770 } 05771 } 05772 if (places[i] == &globals) 05773 ast_mutex_unlock(&globalslock); 05774 if (ret) 05775 break; 05776 } 05777 05778 return ret; 05779 }
static int pbx_builtin_gotoif | ( | struct ast_channel * | , | |
void * | ||||
) | [static] |
Definition at line 5969 of file pbx.c.
References ast_log(), ast_strdupa, ast_strlen_zero(), LOG_WARNING, pbx_builtin_goto(), pbx_checkcondition(), and strsep().
05970 { 05971 char *condition, *branch1, *branch2, *branch; 05972 int rc; 05973 char *stringp; 05974 05975 if (ast_strlen_zero(data)) { 05976 ast_log(LOG_WARNING, "Ignoring, since there is no variable to check\n"); 05977 return 0; 05978 } 05979 05980 stringp = ast_strdupa(data); 05981 condition = strsep(&stringp,"?"); 05982 branch1 = strsep(&stringp,":"); 05983 branch2 = strsep(&stringp,""); 05984 branch = pbx_checkcondition(condition) ? branch1 : branch2; 05985 05986 if (ast_strlen_zero(branch)) { 05987 if (option_debug) 05988 ast_log(LOG_DEBUG, "Not taking any branch\n"); 05989 return 0; 05990 } 05991 05992 rc = pbx_builtin_goto(chan, branch); 05993 05994 return rc; 05995 }
int pbx_builtin_importvar | ( | struct ast_channel * | , | |
void * | ||||
) | [static] |
Definition at line 5888 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.
05889 { 05890 char *name; 05891 char *value; 05892 char *channel; 05893 char tmp[VAR_BUF_SIZE]=""; 05894 05895 if (ast_strlen_zero(data)) { 05896 ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n"); 05897 return 0; 05898 } 05899 05900 value = ast_strdupa(data); 05901 name = strsep(&value,"="); 05902 channel = strsep(&value,"|"); 05903 if (channel && value && name) { /*! \todo XXX should do !ast_strlen_zero(..) of the args ? */ 05904 struct ast_channel *chan2 = ast_get_channel_by_name_locked(channel); 05905 if (chan2) { 05906 char *s = alloca(strlen(value) + 4); 05907 if (s) { 05908 sprintf(s, "${%s}", value); 05909 pbx_substitute_variables_helper(chan2, s, tmp, sizeof(tmp) - 1); 05910 } 05911 ast_channel_unlock(chan2); 05912 } 05913 pbx_builtin_setvar_helper(chan, name, tmp); 05914 } 05915 05916 return(0); 05917 }
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 5781 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().
05782 { 05783 struct ast_var_t *newvariable; 05784 struct varshead *headp; 05785 05786 if (name[strlen(name)-1] == ')') { 05787 char *function = ast_strdupa(name); 05788 05789 ast_log(LOG_WARNING, "Cannot push a value onto a function\n"); 05790 ast_func_write(chan, function, value); 05791 return; 05792 } 05793 05794 headp = (chan) ? &chan->varshead : &globals; 05795 05796 if (value) { 05797 if ((option_verbose > 1) && (headp == &globals)) 05798 ast_verbose(VERBOSE_PREFIX_2 "Setting global variable '%s' to '%s'\n", name, value); 05799 newvariable = ast_var_assign(name, value); 05800 if (headp == &globals) 05801 ast_mutex_lock(&globalslock); 05802 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 05803 if (headp == &globals) 05804 ast_mutex_unlock(&globalslock); 05805 } 05806 }
static int pbx_builtin_saycharacters | ( | struct ast_channel * | , | |
void * | ||||
) | [static] |
Definition at line 6029 of file pbx.c.
References ast_say_character_str().
06030 { 06031 int res = 0; 06032 06033 if (data) 06034 res = ast_say_character_str(chan, data, "", chan->language); 06035 return res; 06036 }
static int pbx_builtin_saydigits | ( | struct ast_channel * | , | |
void * | ||||
) | [static] |
Definition at line 6020 of file pbx.c.
References ast_say_digit_str().
06021 { 06022 int res = 0; 06023 06024 if (data) 06025 res = ast_say_digit_str(chan, data, "", chan->language); 06026 return res; 06027 }
static int pbx_builtin_saynumber | ( | struct ast_channel * | , | |
void * | ||||
) | [static] |
Definition at line 5997 of file pbx.c.
References ast_log(), ast_say_number(), ast_strlen_zero(), LOG_WARNING, and strsep().
05998 { 05999 char tmp[256]; 06000 char *number = tmp; 06001 char *options; 06002 06003 if (ast_strlen_zero(data)) { 06004 ast_log(LOG_WARNING, "SayNumber requires an argument (number)\n"); 06005 return -1; 06006 } 06007 ast_copy_string(tmp, data, sizeof(tmp)); 06008 strsep(&number, "|"); 06009 options = strsep(&number, "|"); 06010 if (options) { 06011 if ( strcasecmp(options, "f") && strcasecmp(options,"m") && 06012 strcasecmp(options, "c") && strcasecmp(options, "n") ) { 06013 ast_log(LOG_WARNING, "SayNumber gender option is either 'f', 'm', 'c' or 'n'\n"); 06014 return -1; 06015 } 06016 } 06017 return ast_say_number(chan, atoi(tmp), "", chan->language, options); 06018 }
static int pbx_builtin_sayphonetic | ( | struct ast_channel * | , | |
void * | ||||
) | [static] |
Definition at line 6038 of file pbx.c.
References ast_say_phonetic_str().
06039 { 06040 int res = 0; 06041 06042 if (data) 06043 res = ast_say_phonetic_str(chan, data, "", chan->language); 06044 return res; 06045 }
int pbx_builtin_serialize_variables | ( | struct ast_channel * | chan, | |
char * | buf, | |||
size_t | size | |||
) |
Definition at line 5722 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().
05723 { 05724 struct ast_var_t *variables; 05725 const char *var, *val; 05726 int total = 0; 05727 05728 if (!chan) 05729 return 0; 05730 05731 memset(buf, 0, size); 05732 05733 AST_LIST_TRAVERSE(&chan->varshead, variables, entries) { 05734 if ((var=ast_var_name(variables)) && (val=ast_var_value(variables)) 05735 /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */ 05736 ) { 05737 if (ast_build_string(&buf, &size, "%s=%s\n", var, val)) { 05738 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n"); 05739 break; 05740 } else 05741 total++; 05742 } else 05743 break; 05744 } 05745 05746 return total; 05747 }
static int pbx_builtin_setglobalvar | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 5920 of file pbx.c.
References ast_log(), ast_strlen_zero(), LOG_WARNING, pbx_builtin_setvar_helper(), and strsep().
05921 { 05922 char *name; 05923 char *stringp = data; 05924 static int dep_warning = 0; 05925 05926 if (ast_strlen_zero(data)) { 05927 ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n"); 05928 return 0; 05929 } 05930 05931 name = strsep(&stringp, "="); 05932 05933 if (!dep_warning) { 05934 dep_warning = 1; 05935 ast_log(LOG_WARNING, "SetGlobalVar is deprecated. Please use Set(GLOBAL(%s)=%s) instead.\n", name, stringp); 05936 } 05937 05938 /*! \todo XXX watch out, leading whitespace ? */ 05939 pbx_builtin_setvar_helper(NULL, name, stringp); 05940 05941 return(0); 05942 }
int pbx_builtin_setvar | ( | struct ast_channel * | , | |
void * | ||||
) |
Definition at line 5853 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().
05854 { 05855 char *name, *value, *mydata; 05856 int argc; 05857 char *argv[24]; /* this will only support a maximum of 24 variables being set in a single operation */ 05858 int global = 0; 05859 int x; 05860 05861 if (ast_strlen_zero(data)) { 05862 ast_log(LOG_WARNING, "Set requires at least one variable name/value pair.\n"); 05863 return 0; 05864 } 05865 05866 mydata = ast_strdupa(data); 05867 argc = ast_app_separate_args(mydata, '|', argv, sizeof(argv) / sizeof(argv[0])); 05868 05869 /* check for a trailing flags argument */ 05870 if ((argc > 1) && !strchr(argv[argc-1], '=')) { 05871 argc--; 05872 if (strchr(argv[argc], 'g')) 05873 global = 1; 05874 } 05875 05876 for (x = 0; x < argc; x++) { 05877 name = argv[x]; 05878 if ((value = strchr(name, '='))) { 05879 *value++ = '\0'; 05880 pbx_builtin_setvar_helper((global) ? NULL : chan, name, value); 05881 } else 05882 ast_log(LOG_WARNING, "Ignoring entry '%s' with no = (and not last 'options' entry)\n", name); 05883 } 05884 05885 return(0); 05886 }
void pbx_builtin_setvar_helper | ( | struct ast_channel * | chan, | |
const char * | name, | |||
const char * | value | |||
) |
Definition at line 5808 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_odbc_read(), acf_odbc_write(), action_setvar(), agi_exec_full(), aji_status_exec(), aMYSQL_fetch(), app_exec(), aqm_exec(), array(), ast_bridge_call(), ast_channel_bridge(), ast_feature_request_and_dial(), ast_iax2_new(), ast_monitor_start(), ast_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(), 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_calc_trunk_timeouts(), sla_station_exec(), sla_trunk_exec(), socket_process(), speech_create(), ss_thread(), start_monitor_exec(), system_exec_helper(), transfer_exec(), try_calling(), tryexec_exec(), upqm_exec(), vm_box_exists(), vm_exec(), vmauthenticate(), zt_handle_dtmfup(), and zt_new().
05809 { 05810 struct ast_var_t *newvariable; 05811 struct varshead *headp; 05812 const char *nametail = name; 05813 05814 /* XXX may need locking on the channel ? */ 05815 if (name[strlen(name)-1] == ')') { 05816 char *function = ast_strdupa(name); 05817 05818 ast_func_write(chan, function, value); 05819 return; 05820 } 05821 05822 headp = (chan) ? &chan->varshead : &globals; 05823 05824 /* For comparison purposes, we have to strip leading underscores */ 05825 if (*nametail == '_') { 05826 nametail++; 05827 if (*nametail == '_') 05828 nametail++; 05829 } 05830 05831 if (headp == &globals) 05832 ast_mutex_lock(&globalslock); 05833 AST_LIST_TRAVERSE (headp, newvariable, entries) { 05834 if (strcasecmp(ast_var_name(newvariable), nametail) == 0) { 05835 /* there is already such a variable, delete it */ 05836 AST_LIST_REMOVE(headp, newvariable, entries); 05837 ast_var_delete(newvariable); 05838 break; 05839 } 05840 } 05841 05842 if (value) { 05843 if ((option_verbose > 1) && (headp == &globals)) 05844 ast_verbose(VERBOSE_PREFIX_2 "Setting global variable '%s' to '%s'\n", name, value); 05845 newvariable = ast_var_assign(name, value); 05846 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 05847 } 05848 05849 if (headp == &globals) 05850 ast_mutex_unlock(&globalslock); 05851 }
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 5959 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().
05960 { 05961 if (ast_strlen_zero(condition)) /* NULL or empty strings are false */ 05962 return 0; 05963 else if (*condition >= '0' && *condition <= '9') /* Numbers are evaluated for truth */ 05964 return atoi(condition); 05965 else /* Strings are true */ 05966 return 1; 05967 }
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 2661 of file pbx.c.
References autofallthrough.
Referenced by pbx_load_module().
02662 { 02663 int oldval = autofallthrough; 02664 autofallthrough = newval; 02665 return oldval; 02666 }
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(), add_extensions(), custom_log(), cut_internal(), exec_exec(), function_eval(), handle_getvariablefull(), launch_monitor_thread(), make_email_file(), pbx_builtin_importvar(), pbx_load_config(), pbx_substitute_variables(), realtime_exec(), rpt_do_lstats(), sendpage(), try_calling(), and tryexec_exec().
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 2597 of file pbx.c.
References __ast_pbx_run(), and decrease_call_count().
Referenced by ast_pbx_start().
02598 { 02599 /* Oh joyeous kernel, we're a new thread, with nothing to do but 02600 answer this channel and get it going. 02601 */ 02602 /* NOTE: 02603 The launcher of this function _MUST_ increment 'countcalls' 02604 before invoking the function; it will be decremented when the 02605 PBX has finished running on the channel 02606 */ 02607 struct ast_channel *c = data; 02608 02609 __ast_pbx_run(c); 02610 decrease_call_count(); 02611 02612 pthread_exit(NULL); 02613 02614 return NULL; 02615 }
static void print_ext | ( | struct ast_exten * | e, | |
char * | buf, | |||
int | buflen | |||
) | [static] |
helper function to print an extension
Definition at line 3480 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().
03481 { 03482 int prio = ast_get_extension_priority(e); 03483 if (prio == PRIORITY_HINT) { 03484 snprintf(buf, buflen, "hint: %s", 03485 ast_get_extension_app(e)); 03486 } else { 03487 snprintf(buf, buflen, "%d. %s(%s)", 03488 prio, ast_get_extension_app(e), 03489 (char *)ast_get_extension_app_data(e)); 03490 } 03491 }
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 3494 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().
03495 { 03496 struct ast_context *c = NULL; 03497 int res = 0, old_total_exten = dpc->total_exten; 03498 03499 ast_lock_contexts(); 03500 03501 /* walk all contexts ... */ 03502 while ( (c = ast_walk_contexts(c)) ) { 03503 struct ast_exten *e; 03504 struct ast_include *i; 03505 struct ast_ignorepat *ip; 03506 char buf[256], buf2[256]; 03507 int context_info_printed = 0; 03508 03509 if (context && strcmp(ast_get_context_name(c), context)) 03510 continue; /* skip this one, name doesn't match */ 03511 03512 dpc->context_existence = 1; 03513 03514 ast_lock_context(c); 03515 03516 /* are we looking for exten too? if yes, we print context 03517 * only if we find our extension. 03518 * Otherwise print context even if empty ? 03519 * XXX i am not sure how the rinclude is handled. 03520 * I think it ought to go inside. 03521 */ 03522 if (!exten) { 03523 dpc->total_context++; 03524 ast_cli(fd, "[ Context '%s' created by '%s' ]\n", 03525 ast_get_context_name(c), ast_get_context_registrar(c)); 03526 context_info_printed = 1; 03527 } 03528 03529 /* walk extensions ... */ 03530 e = NULL; 03531 while ( (e = ast_walk_context_extensions(c, e)) ) { 03532 struct ast_exten *p; 03533 03534 if (exten && !ast_extension_match(ast_get_extension_name(e), exten)) 03535 continue; /* skip, extension match failed */ 03536 03537 dpc->extension_existence = 1; 03538 03539 /* may we print context info? */ 03540 if (!context_info_printed) { 03541 dpc->total_context++; 03542 if (rinclude) { /* TODO Print more info about rinclude */ 03543 ast_cli(fd, "[ Included context '%s' created by '%s' ]\n", 03544 ast_get_context_name(c), ast_get_context_registrar(c)); 03545 } else { 03546 ast_cli(fd, "[ Context '%s' created by '%s' ]\n", 03547 ast_get_context_name(c), ast_get_context_registrar(c)); 03548 } 03549 context_info_printed = 1; 03550 } 03551 dpc->total_prio++; 03552 03553 /* write extension name and first peer */ 03554 snprintf(buf, sizeof(buf), "'%s' =>", ast_get_extension_name(e)); 03555 03556 print_ext(e, buf2, sizeof(buf2)); 03557 03558 ast_cli(fd, " %-17s %-45s [%s]\n", buf, buf2, 03559 ast_get_extension_registrar(e)); 03560 03561 dpc->total_exten++; 03562 /* walk next extension peers */ 03563 p = e; /* skip the first one, we already got it */ 03564 while ( (p = ast_walk_extension_priorities(e, p)) ) { 03565 const char *el = ast_get_extension_label(p); 03566 dpc->total_prio++; 03567 if (el) 03568 snprintf(buf, sizeof(buf), " [%s]", el); 03569 else 03570 buf[0] = '\0'; 03571 print_ext(p, buf2, sizeof(buf2)); 03572 03573 ast_cli(fd," %-17s %-45s [%s]\n", buf, buf2, 03574 ast_get_extension_registrar(p)); 03575 } 03576 } 03577 03578 /* walk included and write info ... */ 03579 i = NULL; 03580 while ( (i = ast_walk_context_includes(c, i)) ) { 03581 snprintf(buf, sizeof(buf), "'%s'", ast_get_include_name(i)); 03582 if (exten) { 03583 /* Check all includes for the requested extension */ 03584 if (includecount >= AST_PBX_MAX_STACK) { 03585 ast_log(LOG_NOTICE, "Maximum include depth exceeded!\n"); 03586 } else { 03587 int dupe=0; 03588 int x; 03589 for (x=0;x<includecount;x++) { 03590 if (!strcasecmp(includes[x], ast_get_include_name(i))) { 03591 dupe++; 03592 break; 03593 } 03594 } 03595 if (!dupe) { 03596 includes[includecount] = ast_get_include_name(i); 03597 show_dialplan_helper(fd, ast_get_include_name(i), exten, dpc, i, includecount + 1, includes); 03598 } else { 03599 ast_log(LOG_WARNING, "Avoiding circular include of %s within %s\n", ast_get_include_name(i), context); 03600 } 03601 } 03602 } else { 03603 ast_cli(fd, " Include => %-45s [%s]\n", 03604 buf, ast_get_include_registrar(i)); 03605 } 03606 } 03607 03608 /* walk ignore patterns and write info ... */ 03609 ip = NULL; 03610 while ( (ip = ast_walk_context_ignorepats(c, ip)) ) { 03611 const char *ipname = ast_get_ignorepat_name(ip); 03612 char ignorepat[AST_MAX_EXTENSION]; 03613 snprintf(buf, sizeof(buf), "'%s'", ipname); 03614 snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname); 03615 if (!exten || ast_extension_match(ignorepat, exten)) { 03616 ast_cli(fd, " Ignore pattern => %-45s [%s]\n", 03617 buf, ast_get_ignorepat_registrar(ip)); 03618 } 03619 } 03620 if (!rinclude) { 03621 struct ast_sw *sw = NULL; 03622 while ( (sw = ast_walk_context_switches(c, sw)) ) { 03623 snprintf(buf, sizeof(buf), "'%s/%s'", 03624 ast_get_switch_name(sw), 03625 ast_get_switch_data(sw)); 03626 ast_cli(fd, " Alt. Switch => %-45s [%s]\n", 03627 buf, ast_get_switch_registrar(sw)); 03628 } 03629 } 03630 03631 ast_unlock_context(c); 03632 03633 /* if we print something in context, make an empty line */ 03634 if (context_info_printed) 03635 ast_cli(fd, "\r\n"); 03636 } 03637 ast_unlock_contexts(); 03638 03639 return (dpc->total_exten == old_total_exten) ? -1 : res; 03640 }
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 5331 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().
05332 { 05333 int res; 05334 struct ast_frame *f; 05335 int waittime; 05336 05337 if (ast_strlen_zero(data) || (sscanf(data, "%d", &waittime) != 1) || (waittime < 0)) 05338 waittime = -1; 05339 if (waittime > -1) { 05340 ast_safe_sleep(chan, waittime * 1000); 05341 } else do { 05342 res = ast_waitfor(chan, -1); 05343 if (res < 0) 05344 return; 05345 f = ast_read(chan); 05346 if (f) 05347 ast_frfree(f); 05348 } while(f); 05349 }
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().