#include "asterisk.h"
#include <sys/types.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include <time.h>
#include <sys/time.h>
#include <limits.h>
#include "asterisk/lock.h"
#include "asterisk/cli.h"
#include "asterisk/pbx.h"
#include "asterisk/channel.h"
#include "asterisk/options.h"
#include "asterisk/logger.h"
#include "asterisk/file.h"
#include "asterisk/callerid.h"
#include "asterisk/cdr.h"
#include "asterisk/config.h"
#include "asterisk/term.h"
#include "asterisk/manager.h"
#include "asterisk/ast_expr.h"
#include "asterisk/linkedlists.h"
#include "asterisk/say.h"
#include "asterisk/utils.h"
#include "asterisk/causes.h"
#include "asterisk/musiconhold.h"
#include "asterisk/app.h"
#include "asterisk/devicestate.h"
#include "asterisk/stringfields.h"
#include "asterisk/threadstorage.h"
Go to the source code of this file.
Data Structures | |
struct | app_tmp |
struct | ast_app |
ast_app: A registered application More... | |
struct | ast_context |
ast_context: An extension context More... | |
struct | ast_exten |
ast_exten: An extension The dialplan is saved as a linked list with each context having it's own linked list of extensions - one item per priority. More... | |
struct | ast_hint |
Structure for dial plan hints. More... | |
struct | ast_ignorepat |
ast_ignorepat: Ignore patterns in dial plan More... | |
struct | ast_include |
ast_include: include= support in extensions.conf More... | |
struct | ast_state_cb |
ast_state_cb: An extension state notify register item More... | |
struct | ast_sw |
ast_sw: Switch statement in extensions.conf More... | |
struct | async_stat |
struct | cfextension_states |
struct | dialplan_counters |
struct | pbx_builtin |
Declaration of builtin applications. More... | |
struct | pbx_find_info |
struct | store_hint |
Defines | |
#define | AST_PBX_MAX_STACK 128 |
#define | BACKGROUND_MATCHEXTEN (1 << 2) |
#define | BACKGROUND_NOANSWER (1 << 1) |
#define | BACKGROUND_PLAYBACK (1 << 3) |
#define | BACKGROUND_SKIP (1 << 0) |
#define | EXT_DATA_SIZE 8192 |
#define | SAY_STUBS |
#define | STATUS_NO_CONTEXT 1 |
#define | STATUS_NO_EXTENSION 2 |
#define | STATUS_NO_LABEL 4 |
#define | STATUS_NO_PRIORITY 3 |
#define | STATUS_SUCCESS 5 |
#define | SWITCH_DATA_LENGTH 256 |
#define | VAR_BUF_SIZE 4096 |
#define | VAR_HARDTRAN 3 |
#define | VAR_NORMAL 1 |
#define | VAR_SOFTTRAN 2 |
#define | WAITEXTEN_MOH (1 << 0) |
Enumerations | |
enum | ext_match_t { E_MATCHMORE = 0x00, E_CANMATCH = 0x01, E_MATCH = 0x02, E_MATCH_MASK = 0x03, E_SPAWN = 0x12, E_FINDLABEL = 0x22 } |
Functions | |
static struct ast_context * | __ast_context_create (struct ast_context **extcontexts, const char *name, const char *registrar, int existsokay) |
void | __ast_context_destroy (struct ast_context *con, const char *registrar) |
static int | __ast_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority, int async) |
static int | __ast_pbx_run (struct ast_channel *c) |
static int | _extension_match_core (const char *pattern, const char *data, enum ext_match_t mode) |
static int | add_pri (struct ast_context *con, struct ast_exten *tmp, struct ast_exten *el, struct ast_exten *e, int replace) |
add the extension in the priority chain. returns 0 on success, -1 on failure | |
int | ast_active_calls (void) |
Retrieve the number of active calls. | |
int | ast_add_extension (const char *context, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar) |
Add and extension to an extension context. | |
int | ast_add_extension2 (struct ast_context *con, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar) |
Add an extension to an extension context, this time with an ast_context *. | |
static int | ast_add_hint (struct ast_exten *e) |
ast_add_hint: Add hint to hint list, check initial extension state | |
AST_APP_OPTIONS (resetcdr_opts,{AST_APP_OPTION('w', AST_CDR_FLAG_POSTED), AST_APP_OPTION('a', AST_CDR_FLAG_LOCKED), AST_APP_OPTION('v', AST_CDR_FLAG_KEEP_VARS),}) | |
AST_APP_OPTIONS (waitexten_opts,{AST_APP_OPTION_ARG('m', WAITEXTEN_MOH, 0),}) | |
AST_APP_OPTIONS (background_opts,{AST_APP_OPTION('s', BACKGROUND_SKIP), AST_APP_OPTION('n', BACKGROUND_NOANSWER), AST_APP_OPTION('m', BACKGROUND_MATCHEXTEN), AST_APP_OPTION('p', BACKGROUND_PLAYBACK),}) | |
int | ast_async_goto (struct ast_channel *chan, const char *context, const char *exten, int priority) |
int | ast_async_goto_by_name (const char *channame, const char *context, const char *exten, int priority) |
int | ast_async_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority) |
int | ast_build_timing (struct ast_timing *i, const char *info_in) |
int | ast_canmatch_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid) |
Looks for a valid matching extension. | |
static int | ast_change_hint (struct ast_exten *oe, struct ast_exten *ne) |
ast_change_hint: Change hint for an extension | |
int | ast_check_timing (const struct ast_timing *i) |
int | ast_context_add_ignorepat (const char *context, const char *value, const char *registrar) |
Add an ignorepat. | |
int | ast_context_add_ignorepat2 (struct ast_context *con, const char *value, const char *registrar) |
int | ast_context_add_include (const char *context, const char *include, const char *registrar) |
Add a context include. | |
int | ast_context_add_include2 (struct ast_context *con, const char *value, const char *registrar) |
Add a context include. | |
int | ast_context_add_switch (const char *context, const char *sw, const char *data, int eval, const char *registrar) |
Add a switch. | |
int | ast_context_add_switch2 (struct ast_context *con, const char *value, const char *data, int eval, const char *registrar) |
Adds a switch (first param is a ast_context). | |
ast_context * | ast_context_create (struct ast_context **extcontexts, const char *name, const char *registrar) |
Register a new context. | |
void | ast_context_destroy (struct ast_context *con, const char *registrar) |
Destroy a context (matches the specified context (or ANY context if NULL). | |
ast_context * | ast_context_find (const char *name) |
Find a context. | |
ast_context * | ast_context_find_or_create (struct ast_context **extcontexts, const char *name, const char *registrar) |
int | ast_context_lockmacro (const char *context) |
locks the macrolock in the given given context | |
int | ast_context_remove_extension (const char *context, const char *extension, int priority, const char *registrar) |
Simply remove extension from context. | |
int | ast_context_remove_extension2 (struct ast_context *con, const char *extension, int priority, const char *registrar) |
This functionc locks given context, search for the right extension and fires out all peer in this extensions with given priority. If priority is set to 0, all peers are removed. After that, unlock context and return. | |
int | ast_context_remove_extension_callerid (const char *context, const char *extension, int priority, const char *callerid, int matchcid, const char *registrar) |
int | ast_context_remove_extension_callerid2 (struct ast_context *con, const char *extension, int priority, const char *callerid, int matchcid, const char *registrar) |
int | ast_context_remove_ignorepat (const char *context, const char *ignorepat, const char *registrar) |
int | ast_context_remove_ignorepat2 (struct ast_context *con, const char *ignorepat, const char *registrar) |
int | ast_context_remove_include (const char *context, const char *include, const char *registrar) |
Remove a context include. | |
int | ast_context_remove_include2 (struct ast_context *con, const char *include, const char *registrar) |
Removes an include by an ast_context structure. | |
int | ast_context_remove_switch (const char *context, const char *sw, const char *data, const char *registrar) |
Remove a switch. | |
int | ast_context_remove_switch2 (struct ast_context *con, const char *sw, const char *data, const char *registrar) |
This function locks given context, removes switch, unlock context and return. | |
int | ast_context_unlockmacro (const char *context) |
Unlocks the macrolock in the given context. | |
int | ast_context_verify_includes (struct ast_context *con) |
Verifies includes in an ast_contect structure. | |
ast_custom_function * | ast_custom_function_find (const char *name) |
int | ast_custom_function_register (struct ast_custom_function *acf) |
Reigster a custom function. | |
int | ast_custom_function_unregister (struct ast_custom_function *acf) |
Unregister a custom function. | |
int | ast_exists_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid) |
Determine whether an extension exists. | |
int | ast_explicit_goto (struct ast_channel *chan, const char *context, const char *exten, int priority) |
int | ast_extension_close (const char *pattern, const char *data, int needmore) |
int | ast_extension_match (const char *pattern, const char *data) |
Determine if a given extension matches a given pattern (in NXX format). | |
int | ast_extension_state (struct ast_channel *c, const char *context, const char *exten) |
Uses hint and devicestate callback to get the state of an extension. | |
static int | ast_extension_state2 (struct ast_exten *e) |
ast_extensions_state2: Check state of extension by using hints | |
const char * | ast_extension_state2str (int extension_state) |
Return string representation of the state of an extension. | |
int | ast_extension_state_add (const char *context, const char *exten, ast_state_cb_type callback, void *data) |
Registers a state change callback. | |
int | ast_extension_state_del (int id, ast_state_cb_type callback) |
Deletes a registered state change callback by ID. | |
int | ast_findlabel_extension (struct ast_channel *c, const char *context, const char *exten, const char *label, const char *callerid) |
Find the priority of an extension that has the specified label. | |
int | ast_findlabel_extension2 (struct ast_channel *c, struct ast_context *con, const char *exten, const char *label, const char *callerid) |
Find the priority of an extension that has the specified label. | |
int | ast_func_read (struct ast_channel *chan, char *function, char *workspace, size_t len) |
executes a read operation on a function | |
int | ast_func_write (struct ast_channel *chan, char *function, const char *value) |
executes a write operation on a function | |
const char * | ast_get_context_name (struct ast_context *con) |
const char * | ast_get_context_registrar (struct ast_context *c) |
const char * | ast_get_extension_app (struct ast_exten *e) |
void * | ast_get_extension_app_data (struct ast_exten *e) |
const char * | ast_get_extension_cidmatch (struct ast_exten *e) |
ast_context * | ast_get_extension_context (struct ast_exten *exten) |
const char * | ast_get_extension_label (struct ast_exten *exten) |
int | ast_get_extension_matchcid (struct ast_exten *e) |
const char * | ast_get_extension_name (struct ast_exten *exten) |
int | ast_get_extension_priority (struct ast_exten *exten) |
const char * | ast_get_extension_registrar (struct ast_exten *e) |
int | ast_get_hint (char *hint, int hintsize, char *name, int namesize, struct ast_channel *c, const char *context, const char *exten) |
If an extension exists, return non-zero. | |
const char * | ast_get_ignorepat_name (struct ast_ignorepat *ip) |
const char * | ast_get_ignorepat_registrar (struct ast_ignorepat *ip) |
const char * | ast_get_include_name (struct ast_include *inc) |
const char * | ast_get_include_registrar (struct ast_include *i) |
const char * | ast_get_switch_data (struct ast_sw *sw) |
const char * | ast_get_switch_name (struct ast_sw *sw) |
const char * | ast_get_switch_registrar (struct ast_sw *sw) |
int | ast_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority) |
static struct ast_exten * | ast_hint_extension (struct ast_channel *c, const char *context, const char *exten) |
ast_hint_extension: Find hint for given extension in context | |
void | ast_hint_state_changed (const char *device) |
int | ast_ignore_pattern (const char *context, const char *pattern) |
Checks to see if a number should be ignored. | |
AST_LIST_HEAD (store_hints, store_hint) | |
static | AST_LIST_HEAD_STATIC (hints, ast_hint) |
static | AST_LIST_HEAD_STATIC (switches, ast_switch) |
static | AST_LIST_HEAD_STATIC (apps, ast_app) |
static | AST_LIST_HEAD_STATIC (acf_root, ast_custom_function) |
int | ast_lock_context (struct ast_context *con) |
Locks a given context. | |
int | ast_lock_contexts () |
Locks the context list. | |
int | ast_matchmore_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid) |
Looks to see if adding anything to this extension might match something. (exists ^ canmatch). | |
void | ast_merge_contexts_and_delete (struct ast_context **extcontexts, const char *registrar) |
Merge the temporary contexts into a global contexts list and delete from the global list the ones that are being added. | |
AST_MUTEX_DEFINE_STATIC (maxcalllock) | |
AST_MUTEX_DEFINE_STATIC (globalslock) | |
int | ast_parseable_goto (struct ast_channel *chan, const char *goto_string) |
int | ast_pbx_outgoing_app (const char *type, int format, void *data, int timeout, const char *app, const char *appdata, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel) |
static int | ast_pbx_outgoing_cdr_failed (void) |
int | ast_pbx_outgoing_exten (const char *type, int format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **channel) |
enum ast_pbx_result | ast_pbx_run (struct ast_channel *c) |
Execute the PBX in the current thread. | |
static void * | ast_pbx_run_app (void *data) |
run the application and free the descriptor once done | |
enum ast_pbx_result | ast_pbx_start (struct ast_channel *c) |
Create a new thread and start the PBX. | |
int | ast_rdlock_contexts (void) |
int | ast_register_application (const char *app, int(*execute)(struct ast_channel *, void *), const char *synopsis, const char *description) |
Register an application. | |
int | ast_register_switch (struct ast_switch *sw) |
Register an alternative dialplan switch. | |
static int | ast_remove_hint (struct ast_exten *e) |
ast_remove_hint: Remove hint from extension | |
AST_RWLOCK_DEFINE_STATIC (conlock) | |
int | ast_spawn_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid) |
Launch a new extension (i.e. new stack). | |
AST_THREADSTORAGE (switch_data, switch_data_init) | |
int | ast_unlock_context (struct ast_context *con) |
int | ast_unlock_contexts () |
Unlocks contexts. | |
int | ast_unregister_application (const char *app) |
Unregister an application. | |
void | ast_unregister_switch (struct ast_switch *sw) |
Unregister an alternative switch. | |
ast_exten * | ast_walk_context_extensions (struct ast_context *con, struct ast_exten *exten) |
ast_ignorepat * | ast_walk_context_ignorepats (struct ast_context *con, struct ast_ignorepat *ip) |
ast_include * | ast_walk_context_includes (struct ast_context *con, struct ast_include *inc) |
ast_sw * | ast_walk_context_switches (struct ast_context *con, struct ast_sw *sw) |
ast_context * | ast_walk_contexts (struct ast_context *con) |
ast_exten * | ast_walk_extension_priorities (struct ast_exten *exten, struct ast_exten *priority) |
int | ast_wrlock_contexts (void) |
static void * | async_wait (void *data) |
static int | collect_digits (struct ast_channel *c, int waittime, char *buf, int buflen, int pos) |
collect digits from the channel into the buffer, return -1 on error, 0 on timeout or done. | |
static char * | complete_show_application (const char *line, const char *word, int pos, int state) |
static char * | complete_show_applications (const char *line, const char *word, int pos, int state) |
static char * | complete_show_applications_deprecated (const char *line, const char *word, int pos, int state) |
static char * | complete_show_dialplan_context (const char *line, const char *word, int pos, int state) |
static char * | complete_show_function (const char *line, const char *word, int pos, int state) |
static void | decrease_call_count (void) |
static void | destroy_exten (struct ast_exten *e) |
static int | ext_cmp (const char *a, const char *b) |
the full routine to compare extensions in rules. | |
static int | ext_cmp1 (const char **p) |
helper functions to sort extensions and patterns in the desired way, so that more specific patterns appear first. | |
static int | ext_strncpy (char *dst, const char *src, int len) |
copy a string skipping whitespace | |
static int | extension_match_core (const char *pattern, const char *data, enum ext_match_t mode) |
static struct ast_context * | find_context_locked (const char *context) |
static char * | func_args (char *function) |
return a pointer to the arguments of the function, and terminates the function name with '\0' | |
static unsigned | get_range (char *src, int max, char *const names[], const char *msg) |
helper function to return a range up to max (7, 12, 31 respectively). names, if supplied, is an array of names that should be mapped to numbers. | |
static void | get_timerange (struct ast_timing *i, char *times) |
store a bitmask of valid times, one bit each 2 minute | |
static int | handle_set_global (int fd, int argc, char *argv[]) |
static int | handle_set_global_deprecated (int fd, int argc, char *argv[]) |
CLI support for setting global variables. | |
static int | handle_show_application (int fd, int argc, char *argv[]) |
static int | handle_show_application_deprecated (int fd, int argc, char *argv[]) |
static int | handle_show_applications (int fd, int argc, char *argv[]) |
static int | handle_show_applications_deprecated (int fd, int argc, char *argv[]) |
static int | handle_show_dialplan (int fd, int argc, char *argv[]) |
static int | handle_show_function (int fd, int argc, char *argv[]) |
static int | handle_show_function_deprecated (int fd, int argc, char *argv[]) |
static int | handle_show_functions (int fd, int argc, char *argv[]) |
static int | handle_show_functions_deprecated (int fd, int argc, char *argv[]) |
static int | handle_show_globals (int fd, int argc, char *argv[]) |
CLI support for listing global variables in a parseable way. | |
static int | handle_show_hints (int fd, int argc, char *argv[]) |
handle_show_hints: CLI support for listing registred dial plan hints | |
static int | handle_show_switches (int fd, int argc, char *argv[]) |
handle_show_switches: CLI support for listing registred dial plan switches | |
static int | include_valid (struct ast_include *i) |
static int | increase_call_count (const struct ast_channel *c) |
int | load_pbx (void) |
static int | lookup_name (const char *s, char *const names[], int max) |
Helper for get_range. return the index of the matching entry, starting from 1. If names is not supplied, try numeric values. | |
static int | matchcid (const char *cidpattern, const char *callerid) |
static int | parse_variable_name (char *var, int *offset, int *length, int *isfunc) |
extract offset:length from variable name. Returns 1 if there is a offset:length part, which is trimmed off (values go into variables) | |
static int | pbx_builtin_answer (struct ast_channel *, void *) |
static int | pbx_builtin_background (struct ast_channel *, void *) |
static int | pbx_builtin_busy (struct ast_channel *, void *) |
void | pbx_builtin_clear_globals (void) |
static int | pbx_builtin_congestion (struct ast_channel *, void *) |
static int | pbx_builtin_execiftime (struct ast_channel *, void *) |
const char * | pbx_builtin_getvar_helper (struct ast_channel *chan, const char *name) |
static int | pbx_builtin_goto (struct ast_channel *, void *) |
static int | pbx_builtin_gotoif (struct ast_channel *, void *) |
static int | pbx_builtin_gotoiftime (struct ast_channel *, void *) |
static int | pbx_builtin_hangup (struct ast_channel *, void *) |
static int | pbx_builtin_importvar (struct ast_channel *, void *) |
static int | pbx_builtin_noop (struct ast_channel *, void *) |
static int | pbx_builtin_progress (struct ast_channel *, void *) |
void | pbx_builtin_pushvar_helper (struct ast_channel *chan, const char *name, const char *value) |
static int | pbx_builtin_resetcdr (struct ast_channel *, void *) |
static int | pbx_builtin_ringing (struct ast_channel *, void *) |
static int | pbx_builtin_saycharacters (struct ast_channel *, void *) |
static int | pbx_builtin_saydate (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 *) |
static int | pbx_builtin_saytime (struct ast_channel *, void *) |
int | pbx_builtin_serialize_variables (struct ast_channel *chan, char *buf, size_t size) |
static int | pbx_builtin_setamaflags (struct ast_channel *, void *) |
static int | pbx_builtin_setglobalvar (struct ast_channel *, void *) |
int | pbx_builtin_setvar (struct ast_channel *, void *) |
void | pbx_builtin_setvar_helper (struct ast_channel *chan, const char *name, const char *value) |
static int | pbx_builtin_wait (struct ast_channel *, void *) |
static int | pbx_builtin_waitexten (struct ast_channel *, void *) |
int | pbx_checkcondition (const char *condition) |
Evaluate a condition. | |
static void | pbx_destroy (struct ast_pbx *p) |
int | pbx_exec (struct ast_channel *c, struct ast_app *app, void *data) |
Execute an application. | |
static int | pbx_extension_helper (struct ast_channel *c, struct ast_context *con, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action) |
The return value depends on the action:. | |
static struct ast_exten * | pbx_find_extension (struct ast_channel *chan, struct ast_context *bypass, struct pbx_find_info *q, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action) |
ast_app * | pbx_findapp (const char *app) |
Look up an application. | |
static struct ast_switch * | pbx_findswitch (const char *sw) |
void | pbx_retrieve_variable (struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp) |
pbx_retrieve_variable: Support for Asterisk built-in variables --- | |
int | pbx_set_autofallthrough (int newval) |
static void | pbx_substitute_variables (char *passdata, int datalen, struct ast_channel *c, struct ast_exten *e) |
void | pbx_substitute_variables_helper (struct ast_channel *c, const char *cp1, char *cp2, int count) |
static void | pbx_substitute_variables_helper_full (struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count) |
void | pbx_substitute_variables_varshead (struct varshead *headp, const char *cp1, char *cp2, int count) |
static void * | pbx_thread (void *data) |
static void | print_ext (struct ast_exten *e, char *buf, int buflen) |
helper function to print an extension | |
static void | set_ext_pri (struct ast_channel *c, const char *exten, int pri) |
static int | show_dialplan_helper (int fd, const char *context, const char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude, int includecount, const char *includes[]) |
static char * | substring (const char *value, int offset, int length, char *workspace, size_t workspace_len) |
takes a substring. It is ok to call with value == workspace. | |
static void | wait_for_hangup (struct ast_channel *chan, void *data) |
Variables | |
static int | autofallthrough = 1 |
static struct pbx_builtin | builtins [] |
Declaration of builtin applications. | |
static struct ast_cli_entry | cli_set_global_deprecated |
static struct ast_cli_entry | cli_show_application_deprecated |
static struct ast_cli_entry | cli_show_applications_deprecated |
static struct ast_cli_entry | cli_show_dialplan_deprecated |
static struct ast_cli_entry | cli_show_function_deprecated |
static struct ast_cli_entry | cli_show_functions_deprecated |
static struct ast_cli_entry | cli_show_globals_deprecated |
static struct ast_cli_entry | cli_show_hints_deprecated |
static struct ast_cli_entry | cli_show_switches_deprecated |
static struct ast_context * | contexts |
static int | countcalls |
static char * | days [] |
static struct cfextension_states | extension_states [] |
static struct varshead | globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE |
static char * | months [] |
static struct ast_cli_entry | pbx_cli [] |
static char | set_global_help [] |
static char | show_application_help [] |
static char | show_applications_help [] |
static char | show_dialplan_help [] |
static char | show_function_help [] |
static char | show_functions_help [] |
static char | show_globals_help [] |
static char | show_hints_help [] |
static char | show_switches_help [] |
ast_state_cb * | statecbs |
static int | stateid = 1 |
Definition in file pbx.c.
#define AST_PBX_MAX_STACK 128 |
Go no deeper than this through includes (not counting loops)
Definition at line 571 of file pbx.c.
Referenced by handle_show_dialplan(), pbx_find_extension(), and show_dialplan_helper().
#define BACKGROUND_MATCHEXTEN (1 << 2) |
#define BACKGROUND_NOANSWER (1 << 1) |
#define BACKGROUND_PLAYBACK (1 << 3) |
#define BACKGROUND_SKIP (1 << 0) |
#define EXT_DATA_SIZE 8192 |
Definition at line 78 of file pbx.c.
Referenced by pbx_extension_helper(), and realtime_exec().
#define STATUS_NO_CONTEXT 1 |
Definition at line 933 of file pbx.c.
Referenced by pbx_extension_helper(), and pbx_find_extension().
#define STATUS_NO_EXTENSION 2 |
Definition at line 934 of file pbx.c.
Referenced by pbx_extension_helper(), and pbx_find_extension().
#define STATUS_NO_LABEL 4 |
Definition at line 936 of file pbx.c.
Referenced by pbx_extension_helper(), and pbx_find_extension().
#define STATUS_NO_PRIORITY 3 |
Definition at line 935 of file pbx.c.
Referenced by pbx_extension_helper(), and pbx_find_extension().
#define STATUS_SUCCESS 5 |
#define VAR_BUF_SIZE 4096 |
Definition at line 83 of file pbx.c.
Referenced by ast_add_extension2(), pbx_builtin_importvar(), and pbx_substitute_variables_helper_full().
#define WAITEXTEN_MOH (1 << 0) |
enum ext_match_t |
When looking up extensions, we can have different requests identified by the 'action' argument, as follows. Note that the coding is such that the low 4 bits are the third argument to extension_match_core.
Definition at line 776 of file pbx.c.
00776 { 00777 E_MATCHMORE = 0x00, /* extension can match but only with more 'digits' */ 00778 E_CANMATCH = 0x01, /* extension can match with or without more 'digits' */ 00779 E_MATCH = 0x02, /* extension is an exact match */ 00780 E_MATCH_MASK = 0x03, /* mask for the argument to extension_match_core() */ 00781 E_SPAWN = 0x12, /* want to spawn an extension. Requires exact match */ 00782 E_FINDLABEL = 0x22 /* returns the priority for a given label. Requires exact match */ 00783 };
static struct ast_context* __ast_context_create | ( | struct ast_context ** | extcontexts, | |
const char * | name, | |||
const char * | registrar, | |||
int | existsokay | |||
) | [static] |
Definition at line 3883 of file pbx.c.
References ast_log(), ast_rdlock_contexts(), ast_unlock_contexts(), contexts, local_contexts, LOG_WARNING, name, and ast_context::next.
Referenced by ast_context_create(), and ast_context_find_or_create().
03884 { 03885 struct ast_context *tmp, **local_contexts; 03886 int length = sizeof(struct ast_context) + strlen(name) + 1; 03887 03888 if (!extcontexts) { 03889 ast_rdlock_contexts(); 03890 local_contexts = &contexts; 03891 } else 03892 local_contexts = extcontexts; 03893 03894 for (tmp = *local_contexts; tmp; tmp = tmp->next) { 03895 if (!strcasecmp(tmp->name, name)) { 03896 if (!existsokay) { 03897 ast_log(LOG_WARNING, "Tried to register context '%s', already in use\n", name); 03898 tmp = NULL; 03899 } 03900 if (!extcontexts) 03901 ast_unlock_contexts(); 03902 return tmp; 03903 } 03904 } 03905 03906 if (!extcontexts) 03907 ast_unlock_contexts(); 03908 03909 if ((tmp = ast_calloc(1, length))) { 03910 ast_mutex_init(&tmp->lock); 03911 ast_mutex_init(&tmp->macrolock); 03912 strcpy(tmp->name, name); 03913 tmp->registrar = registrar; 03914 if (!extcontexts) 03915 ast_wrlock_contexts(); 03916 tmp->next = *local_contexts; 03917 *local_contexts = tmp; 03918 if (!extcontexts) 03919 ast_unlock_contexts(); 03920 if (option_debug) 03921 ast_log(LOG_DEBUG, "Registered context '%s'\n", tmp->name); 03922 if (option_verbose > 2) 03923 ast_verbose( VERBOSE_PREFIX_3 "Registered extension context '%s'\n", tmp->name); 03924 } 03925 03926 return tmp; 03927 }
void __ast_context_destroy | ( | struct ast_context * | con, | |
const char * | registrar | |||
) |
Definition at line 5307 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().
05308 { 05309 struct ast_context *tmp, *tmpl=NULL; 05310 struct ast_include *tmpi; 05311 struct ast_sw *sw; 05312 struct ast_exten *e, *el, *en; 05313 struct ast_ignorepat *ipi; 05314 05315 for (tmp = contexts; tmp; ) { 05316 struct ast_context *next; /* next starting point */ 05317 for (; tmp; tmpl = tmp, tmp = tmp->next) { 05318 if (option_debug) 05319 ast_log(LOG_DEBUG, "check ctx %s %s\n", tmp->name, tmp->registrar); 05320 if ( (!registrar || !strcasecmp(registrar, tmp->registrar)) && 05321 (!con || !strcasecmp(tmp->name, con->name)) ) 05322 break; /* found it */ 05323 } 05324 if (!tmp) /* not found, we are done */ 05325 break; 05326 ast_mutex_lock(&tmp->lock); 05327 if (option_debug) 05328 ast_log(LOG_DEBUG, "delete ctx %s %s\n", tmp->name, tmp->registrar); 05329 next = tmp->next; 05330 if (tmpl) 05331 tmpl->next = next; 05332 else 05333 contexts = next; 05334 /* Okay, now we're safe to let it go -- in a sense, we were 05335 ready to let it go as soon as we locked it. */ 05336 ast_mutex_unlock(&tmp->lock); 05337 for (tmpi = tmp->includes; tmpi; ) { /* Free includes */ 05338 struct ast_include *tmpil = tmpi; 05339 tmpi = tmpi->next; 05340 free(tmpil); 05341 } 05342 for (ipi = tmp->ignorepats; ipi; ) { /* Free ignorepats */ 05343 struct ast_ignorepat *ipl = ipi; 05344 ipi = ipi->next; 05345 free(ipl); 05346 } 05347 while ((sw = AST_LIST_REMOVE_HEAD(&tmp->alts, list))) 05348 free(sw); 05349 for (e = tmp->root; e;) { 05350 for (en = e->peer; en;) { 05351 el = en; 05352 en = en->peer; 05353 destroy_exten(el); 05354 } 05355 el = e; 05356 e = e->next; 05357 destroy_exten(el); 05358 } 05359 ast_mutex_destroy(&tmp->lock); 05360 free(tmp); 05361 /* if we have a specific match, we are done, otherwise continue */ 05362 tmp = con ? NULL : next; 05363 } 05364 }
static int __ast_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority, | |||
int | async | |||
) | [static] |
Definition at line 6438 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().
06439 { 06440 int (*goto_func)(struct ast_channel *chan, const char *context, const char *exten, int priority); 06441 06442 if (!chan) 06443 return -2; 06444 06445 if (context == NULL) 06446 context = chan->context; 06447 if (exten == NULL) 06448 exten = chan->exten; 06449 06450 goto_func = (async) ? ast_async_goto : ast_explicit_goto; 06451 if (ast_exists_extension(chan, context, exten, priority, chan->cid.cid_num)) 06452 return goto_func(chan, context, exten, priority); 06453 else 06454 return -3; 06455 }
static int __ast_pbx_run | ( | struct ast_channel * | c | ) | [static] |
Definition at line 2384 of file pbx.c.
References ast_channel::_softhangup, ast_calloc, 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::cid, ast_callerid::cid_num, ast_channel::context, ast_pbx::dtimeout, ast_channel::exten, free, LOG_DEBUG, LOG_WARNING, option_debug, option_verbose, ast_channel::pbx, ast_channel::priority, ast_pbx::rtimeout, set_ext_pri(), and VERBOSE_PREFIX_2.
Referenced by ast_pbx_run(), and pbx_thread().
02385 { 02386 int found = 0; /* set if we find at least one match */ 02387 int res = 0; 02388 int autoloopflag; 02389 int error = 0; /* set an error conditions */ 02390 02391 /* A little initial setup here */ 02392 if (c->pbx) { 02393 ast_log(LOG_WARNING, "%s already has PBX structure??\n", c->name); 02394 /* XXX and now what ? */ 02395 free(c->pbx); 02396 } 02397 if (!(c->pbx = ast_calloc(1, sizeof(*c->pbx)))) 02398 return -1; 02399 /* Set reasonable defaults */ 02400 c->pbx->rtimeout = 10; 02401 c->pbx->dtimeout = 5; 02402 02403 autoloopflag = ast_test_flag(c, AST_FLAG_IN_AUTOLOOP); /* save value to restore at the end */ 02404 ast_set_flag(c, AST_FLAG_IN_AUTOLOOP); 02405 02406 /* Start by trying whatever the channel is set to */ 02407 if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) { 02408 /* If not successful fall back to 's' */ 02409 if (option_verbose > 1) 02410 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); 02411 /* XXX the original code used the existing priority in the call to 02412 * ast_exists_extension(), and reset it to 1 afterwards. 02413 * I believe the correct thing is to set it to 1 immediately. 02414 */ 02415 set_ext_pri(c, "s", 1); 02416 if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) { 02417 /* JK02: And finally back to default if everything else failed */ 02418 if (option_verbose > 1) 02419 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); 02420 ast_copy_string(c->context, "default", sizeof(c->context)); 02421 } 02422 } 02423 for (;;) { 02424 char dst_exten[256]; /* buffer to accumulate digits */ 02425 int pos = 0; /* XXX should check bounds */ 02426 int digit = 0; 02427 02428 /* loop on priorities in this context/exten */ 02429 while (ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) { 02430 found = 1; 02431 if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num))) { 02432 /* Something bad happened, or a hangup has been requested. */ 02433 if (strchr("0123456789ABCDEF*#", res)) { 02434 if (option_debug) 02435 ast_log(LOG_DEBUG, "Oooh, got something to jump out with ('%c')!\n", res); 02436 pos = 0; 02437 dst_exten[pos++] = digit = res; 02438 dst_exten[pos] = '\0'; 02439 break; 02440 } 02441 if (res == AST_PBX_KEEPALIVE) { 02442 if (option_debug) 02443 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name); 02444 if (option_verbose > 1) 02445 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name); 02446 error = 1; 02447 break; 02448 } 02449 if (option_debug) 02450 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 02451 if (option_verbose > 1) 02452 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 02453 if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) { 02454 c->_softhangup = 0; 02455 } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) { 02456 /* atimeout, nothing bad */ 02457 } else { 02458 if (c->cdr) 02459 ast_cdr_update(c); 02460 error = 1; 02461 break; 02462 } 02463 } 02464 if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) { 02465 c->_softhangup = 0; 02466 } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT && ast_exists_extension(c,c->context,"T",1,c->cid.cid_num)) { 02467 set_ext_pri(c, "T", 0); /* 0 will become 1 with the c->priority++; at the end */ 02468 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 02469 c->whentohangup = 0; 02470 c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT; 02471 } else if (c->_softhangup) { 02472 if (option_debug) 02473 ast_log(LOG_DEBUG, "Extension %s, priority %d returned normally even though call was hung up\n", 02474 c->exten, c->priority); 02475 error = 1; 02476 break; 02477 } 02478 c->priority++; 02479 } /* end while - from here on we can use 'break' to go out */ 02480 if (error) 02481 break; 02482 02483 /* XXX we get here on non-existing extension or a keypress or hangup ? */ 02484 02485 if (!ast_exists_extension(c, c->context, c->exten, 1, c->cid.cid_num)) { 02486 /* If there is no match at priority 1, it is not a valid extension anymore. 02487 * Try to continue at "i", 1 or exit if the latter does not exist. 02488 */ 02489 if (ast_exists_extension(c, c->context, "i", 1, c->cid.cid_num)) { 02490 if (option_verbose > 2) 02491 ast_verbose(VERBOSE_PREFIX_3 "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, c->name); 02492 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", c->exten); 02493 set_ext_pri(c, "i", 1); 02494 } else { 02495 ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n", 02496 c->name, c->exten, c->context); 02497 error = 1; /* we know what to do with it */ 02498 break; 02499 } 02500 } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) { 02501 /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */ 02502 c->_softhangup = 0; 02503 } else { /* keypress received, get more digits for a full extension */ 02504 int waittime = 0; 02505 if (digit) 02506 waittime = c->pbx->dtimeout; 02507 else if (!autofallthrough) 02508 waittime = c->pbx->rtimeout; 02509 if (!waittime) { 02510 const char *status = pbx_builtin_getvar_helper(c, "DIALSTATUS"); 02511 if (!status) 02512 status = "UNKNOWN"; 02513 if (option_verbose > 2) 02514 ast_verbose(VERBOSE_PREFIX_2 "Auto fallthrough, channel '%s' status is '%s'\n", c->name, status); 02515 if (!strcasecmp(status, "CONGESTION")) 02516 res = pbx_builtin_congestion(c, "10"); 02517 else if (!strcasecmp(status, "CHANUNAVAIL")) 02518 res = pbx_builtin_congestion(c, "10"); 02519 else if (!strcasecmp(status, "BUSY")) 02520 res = pbx_builtin_busy(c, "10"); 02521 error = 1; /* XXX disable message */ 02522 break; /* exit from the 'for' loop */ 02523 } 02524 02525 if (collect_digits(c, waittime, dst_exten, sizeof(dst_exten), pos)) 02526 break; 02527 if (ast_exists_extension(c, c->context, dst_exten, 1, c->cid.cid_num)) /* Prepare the next cycle */ 02528 set_ext_pri(c, dst_exten, 1); 02529 else { 02530 /* No such extension */ 02531 if (!ast_strlen_zero(dst_exten)) { 02532 /* An invalid extension */ 02533 if (ast_exists_extension(c, c->context, "i", 1, c->cid.cid_num)) { 02534 if (option_verbose > 2) 02535 ast_verbose( VERBOSE_PREFIX_3 "Invalid extension '%s' in context '%s' on %s\n", dst_exten, c->context, c->name); 02536 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", dst_exten); 02537 set_ext_pri(c, "i", 1); 02538 } else { 02539 ast_log(LOG_WARNING, "Invalid extension '%s', but no rule 'i' in context '%s'\n", dst_exten, c->context); 02540 found = 1; /* XXX disable message */ 02541 break; 02542 } 02543 } else { 02544 /* A simple timeout */ 02545 if (ast_exists_extension(c, c->context, "t", 1, c->cid.cid_num)) { 02546 if (option_verbose > 2) 02547 ast_verbose( VERBOSE_PREFIX_3 "Timeout on %s\n", c->name); 02548 set_ext_pri(c, "t", 1); 02549 } else { 02550 ast_log(LOG_WARNING, "Timeout, but no rule 't' in context '%s'\n", c->context); 02551 found = 1; /* XXX disable message */ 02552 break; 02553 } 02554 } 02555 } 02556 if (c->cdr) { 02557 if (option_verbose > 2) 02558 ast_verbose(VERBOSE_PREFIX_2 "CDR updated on %s\n",c->name); 02559 ast_cdr_update(c); 02560 } 02561 } 02562 } 02563 if (!found && !error) 02564 ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name); 02565 if (res != AST_PBX_KEEPALIVE) 02566 ast_softhangup(c, c->hangupcause ? c->hangupcause : AST_CAUSE_NORMAL_CLEARING); 02567 if ((res != AST_PBX_KEEPALIVE) && ast_exists_extension(c, c->context, "h", 1, c->cid.cid_num)) { 02568 set_ext_pri(c, "h", 1); 02569 while(ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) { 02570 if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num))) { 02571 /* Something bad happened, or a hangup has been requested. */ 02572 if (option_debug) 02573 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 02574 if (option_verbose > 1) 02575 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 02576 break; 02577 } 02578 c->priority++; 02579 } 02580 } 02581 ast_set2_flag(c, autoloopflag, AST_FLAG_IN_AUTOLOOP); 02582 02583 pbx_destroy(c->pbx); 02584 c->pbx = NULL; 02585 if (res != AST_PBX_KEEPALIVE) 02586 ast_hangup(c); 02587 return 0; 02588 }
static int _extension_match_core | ( | const char * | pattern, | |
const char * | data, | |||
enum ext_match_t | mode | |||
) | [static] |
Definition at line 794 of file pbx.c.
References ast_log(), E_MATCH, E_MATCH_MASK, E_MATCHMORE, and LOG_WARNING.
Referenced by extension_match_core().
00795 { 00796 mode &= E_MATCH_MASK; /* only consider the relevant bits */ 00797 00798 if ( (mode == E_MATCH) && (pattern[0] == '_') && (strcasecmp(pattern,data)==0) ) /* note: if this test is left out, then _x. will not match _x. !!! */ 00799 return 1; 00800 00801 if (pattern[0] != '_') { /* not a pattern, try exact or partial match */ 00802 int ld = strlen(data), lp = strlen(pattern); 00803 00804 if (lp < ld) /* pattern too short, cannot match */ 00805 return 0; 00806 /* depending on the mode, accept full or partial match or both */ 00807 if (mode == E_MATCH) 00808 return !strcmp(pattern, data); /* 1 on match, 0 on fail */ 00809 if (ld == 0 || !strncasecmp(pattern, data, ld)) /* partial or full match */ 00810 return (mode == E_MATCHMORE) ? lp > ld : 1; /* XXX should consider '!' and '/' ? */ 00811 else 00812 return 0; 00813 } 00814 pattern++; /* skip leading _ */ 00815 /* 00816 * XXX below we stop at '/' which is a separator for the CID info. However we should 00817 * not store '/' in the pattern at all. When we insure it, we can remove the checks. 00818 */ 00819 while (*data && *pattern && *pattern != '/') { 00820 const char *end; 00821 00822 if (*data == '-') { /* skip '-' in data (just a separator) */ 00823 data++; 00824 continue; 00825 } 00826 switch (toupper(*pattern)) { 00827 case '[': /* a range */ 00828 end = strchr(pattern+1, ']'); /* XXX should deal with escapes ? */ 00829 if (end == NULL) { 00830 ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n"); 00831 return 0; /* unconditional failure */ 00832 } 00833 for (pattern++; pattern != end; pattern++) { 00834 if (pattern+2 < end && pattern[1] == '-') { /* this is a range */ 00835 if (*data >= pattern[0] && *data <= pattern[2]) 00836 break; /* match found */ 00837 else { 00838 pattern += 2; /* skip a total of 3 chars */ 00839 continue; 00840 } 00841 } else if (*data == pattern[0]) 00842 break; /* match found */ 00843 } 00844 if (pattern == end) 00845 return 0; 00846 pattern = end; /* skip and continue */ 00847 break; 00848 case 'N': 00849 if (*data < '2' || *data > '9') 00850 return 0; 00851 break; 00852 case 'X': 00853 if (*data < '0' || *data > '9') 00854 return 0; 00855 break; 00856 case 'Z': 00857 if (*data < '1' || *data > '9') 00858 return 0; 00859 break; 00860 case '.': /* Must match, even with more digits */ 00861 return 1; 00862 case '!': /* Early match */ 00863 return 2; 00864 case ' ': 00865 case '-': /* Ignore these in patterns */ 00866 data--; /* compensate the final data++ */ 00867 break; 00868 default: 00869 if (*data != *pattern) 00870 return 0; 00871 } 00872 data++; 00873 pattern++; 00874 } 00875 if (*data) /* data longer than pattern, no match */ 00876 return 0; 00877 /* 00878 * match so far, but ran off the end of the data. 00879 * Depending on what is next, determine match or not. 00880 */ 00881 if (*pattern == '\0' || *pattern == '/') /* exact match */ 00882 return (mode == E_MATCHMORE) ? 0 : 1; /* this is a failure for E_MATCHMORE */ 00883 else if (*pattern == '!') /* early match */ 00884 return 2; 00885 else /* partial match */ 00886 return (mode == E_MATCH) ? 0 : 1; /* this is a failure for E_MATCH */ 00887 }
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 4701 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().
04703 { 04704 struct ast_exten *ep; 04705 04706 for (ep = NULL; e ; ep = e, e = e->peer) { 04707 if (e->priority >= tmp->priority) 04708 break; 04709 } 04710 if (!e) { /* go at the end, and ep is surely set because the list is not empty */ 04711 ep->peer = tmp; 04712 return 0; /* success */ 04713 } 04714 if (e->priority == tmp->priority) { 04715 /* Can't have something exactly the same. Is this a 04716 replacement? If so, replace, otherwise, bonk. */ 04717 if (!replace) { 04718 ast_log(LOG_WARNING, "Unable to register extension '%s', priority %d in '%s', already in use\n", tmp->exten, tmp->priority, con->name); 04719 if (tmp->datad) 04720 tmp->datad(tmp->data); 04721 free(tmp); 04722 return -1; 04723 } 04724 /* we are replacing e, so copy the link fields and then update 04725 * whoever pointed to e to point to us 04726 */ 04727 tmp->next = e->next; /* not meaningful if we are not first in the peer list */ 04728 tmp->peer = e->peer; /* always meaningful */ 04729 if (ep) /* We're in the peer list, just insert ourselves */ 04730 ep->peer = tmp; 04731 else if (el) /* We're the first extension. Take over e's functions */ 04732 el->next = tmp; 04733 else /* We're the very first extension. */ 04734 con->root = tmp; 04735 if (tmp->priority == PRIORITY_HINT) 04736 ast_change_hint(e,tmp); 04737 /* Destroy the old one */ 04738 if (e->datad) 04739 e->datad(e->data); 04740 free(e); 04741 } else { /* Slip ourselves in just before e */ 04742 tmp->peer = e; 04743 tmp->next = e->next; /* extension chain, or NULL if e is not the first extension */ 04744 if (ep) /* Easy enough, we're just in the peer list */ 04745 ep->peer = tmp; 04746 else { /* we are the first in some peer list, so link in the ext list */ 04747 if (el) 04748 el->next = tmp; /* in the middle... */ 04749 else 04750 con->root = tmp; /* ... or at the head */ 04751 e->next = NULL; /* e is no more at the head, so e->next must be reset */ 04752 } 04753 /* And immediately return success. */ 04754 if (tmp->priority == PRIORITY_HINT) 04755 ast_add_hint(tmp); 04756 } 04757 return 0; 04758 }
int ast_active_calls | ( | void | ) |
Retrieve the number of active calls.
Definition at line 2693 of file pbx.c.
References countcalls.
Referenced by handle_chanlist(), and handle_chanlist_deprecated().
02694 { 02695 return countcalls; 02696 }
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 4570 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().
04573 { 04574 int ret = -1; 04575 struct ast_context *c = find_context_locked(context); 04576 04577 if (c) { 04578 ret = ast_add_extension2(c, replace, extension, priority, label, callerid, 04579 application, data, datad, registrar); 04580 ast_unlock_contexts(); 04581 } 04582 return ret; 04583 }
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 4785 of file pbx.c.
References add_pri(), ast_exten::app, ast_add_hint(), ast_calloc, AST_LIST_FIRST, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), ast_exten::cidmatch, ast_exten::data, ast_exten::datad, el, errno, ext_cmp(), ext_strncpy(), ast_exten::exten, ast_exten::label, ast_context::lock, ast_exten::matchcid, ast_exten::next, option_verbose, ast_exten::parent, pbx_substitute_variables_varshead(), ast_exten::priority, PRIORITY_HINT, ast_exten::registrar, ast_context::root, ast_exten::stuff, VAR_BUF_SIZE, and VERBOSE_PREFIX_3.
Referenced by add_extensions(), ast_add_extension(), do_parking_thread(), park_call_full(), pbx_load_config(), and pbx_load_users().
04789 { 04790 /* 04791 * Sort extensions (or patterns) according to the rules indicated above. 04792 * These are implemented by the function ext_cmp()). 04793 * All priorities for the same ext/pattern/cid are kept in a list, 04794 * using the 'peer' field as a link field.. 04795 */ 04796 struct ast_exten *tmp, *e, *el = NULL; 04797 int res; 04798 int length; 04799 char *p; 04800 char expand_buf[VAR_BUF_SIZE] = { 0, }; 04801 04802 /* if we are adding a hint, and there are global variables, and the hint 04803 contains variable references, then expand them 04804 */ 04805 ast_mutex_lock(&globalslock); 04806 if (priority == PRIORITY_HINT && AST_LIST_FIRST(&globals) && strstr(application, "${")) { 04807 pbx_substitute_variables_varshead(&globals, application, expand_buf, sizeof(expand_buf)); 04808 application = expand_buf; 04809 } 04810 ast_mutex_unlock(&globalslock); 04811 04812 length = sizeof(struct ast_exten); 04813 length += strlen(extension) + 1; 04814 length += strlen(application) + 1; 04815 if (label) 04816 length += strlen(label) + 1; 04817 if (callerid) 04818 length += strlen(callerid) + 1; 04819 else 04820 length ++; /* just the '\0' */ 04821 04822 /* Be optimistic: Build the extension structure first */ 04823 if (!(tmp = ast_calloc(1, length))) 04824 return -1; 04825 04826 /* use p as dst in assignments, as the fields are const char * */ 04827 p = tmp->stuff; 04828 if (label) { 04829 tmp->label = p; 04830 strcpy(p, label); 04831 p += strlen(label) + 1; 04832 } 04833 tmp->exten = p; 04834 p += ext_strncpy(p, extension, strlen(extension) + 1) + 1; 04835 tmp->priority = priority; 04836 tmp->cidmatch = p; /* but use p for assignments below */ 04837 if (callerid) { 04838 p += ext_strncpy(p, callerid, strlen(callerid) + 1) + 1; 04839 tmp->matchcid = 1; 04840 } else { 04841 *p++ = '\0'; 04842 tmp->matchcid = 0; 04843 } 04844 tmp->app = p; 04845 strcpy(p, application); 04846 tmp->parent = con; 04847 tmp->data = data; 04848 tmp->datad = datad; 04849 tmp->registrar = registrar; 04850 04851 ast_mutex_lock(&con->lock); 04852 res = 0; /* some compilers will think it is uninitialized otherwise */ 04853 for (e = con->root; e; el = e, e = e->next) { /* scan the extension list */ 04854 res = ext_cmp(e->exten, extension); 04855 if (res == 0) { /* extension match, now look at cidmatch */ 04856 if (!e->matchcid && !tmp->matchcid) 04857 res = 0; 04858 else if (tmp->matchcid && !e->matchcid) 04859 res = 1; 04860 else if (e->matchcid && !tmp->matchcid) 04861 res = -1; 04862 else 04863 res = strcasecmp(e->cidmatch, tmp->cidmatch); 04864 } 04865 if (res >= 0) 04866 break; 04867 } 04868 if (e && res == 0) { /* exact match, insert in the pri chain */ 04869 res = add_pri(con, tmp, el, e, replace); 04870 ast_mutex_unlock(&con->lock); 04871 if (res < 0) { 04872 errno = EEXIST; /* XXX do we care ? */ 04873 return 0; /* XXX should we return -1 maybe ? */ 04874 } 04875 } else { 04876 /* 04877 * not an exact match, this is the first entry with this pattern, 04878 * so insert in the main list right before 'e' (if any) 04879 */ 04880 tmp->next = e; 04881 if (el) 04882 el->next = tmp; 04883 else 04884 con->root = tmp; 04885 ast_mutex_unlock(&con->lock); 04886 if (tmp->priority == PRIORITY_HINT) 04887 ast_add_hint(tmp); 04888 } 04889 if (option_debug) { 04890 if (tmp->matchcid) { 04891 if (option_debug) 04892 ast_log(LOG_DEBUG, "Added extension '%s' priority %d (CID match '%s') to %s\n", 04893 tmp->exten, tmp->priority, tmp->cidmatch, con->name); 04894 } else { 04895 if (option_debug) 04896 ast_log(LOG_DEBUG, "Added extension '%s' priority %d to %s\n", 04897 tmp->exten, tmp->priority, con->name); 04898 } 04899 } 04900 if (option_verbose > 2) { 04901 if (tmp->matchcid) { 04902 ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d (CID match '%s')to %s\n", 04903 tmp->exten, tmp->priority, tmp->cidmatch, con->name); 04904 } else { 04905 ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d to %s\n", 04906 tmp->exten, tmp->priority, con->name); 04907 } 04908 } 04909 return 0; 04910 }
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 2206 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().
02207 { 02208 struct ast_hint *hint; 02209 02210 if (!e) 02211 return -1; 02212 02213 AST_LIST_LOCK(&hints); 02214 02215 /* Search if hint exists, do nothing */ 02216 AST_LIST_TRAVERSE(&hints, hint, list) { 02217 if (hint->exten == e) { 02218 AST_LIST_UNLOCK(&hints); 02219 if (option_debug > 1) 02220 ast_log(LOG_DEBUG, "HINTS: Not re-adding existing hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e)); 02221 return -1; 02222 } 02223 } 02224 02225 if (option_debug > 1) 02226 ast_log(LOG_DEBUG, "HINTS: Adding hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e)); 02227 02228 if (!(hint = ast_calloc(1, sizeof(*hint)))) { 02229 AST_LIST_UNLOCK(&hints); 02230 return -1; 02231 } 02232 /* Initialize and insert new item at the top */ 02233 hint->exten = e; 02234 hint->laststate = ast_extension_state2(e); 02235 AST_LIST_INSERT_HEAD(&hints, hint, list); 02236 02237 AST_LIST_UNLOCK(&hints); 02238 return 0; 02239 }
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 4608 of file pbx.c.
References ast_channel::_state, ast_channel::amaflags, ast_cdr_discard(), ast_cdr_dup(), ast_channel_alloc(), ast_channel_lock, ast_channel_masquerade(), ast_channel_unlock, ast_do_masquerade(), ast_explicit_goto(), ast_hangup(), ast_log(), ast_pbx_start(), AST_SOFTHANGUP_ASYNCGOTO, ast_softhangup_nolock(), ast_channel::cdr, ast_channel::context, ast_channel::exten, LOG_WARNING, ast_channel::pbx, ast_channel::readformat, S_OR, and ast_channel::writeformat.
Referenced by __ast_goto_if_exists(), action_redirect(), ast_async_goto_by_name(), builtin_blindtransfer(), console_transfer(), console_transfer_deprecated(), dahdi_handle_dtmfup(), handle_request_bye(), handle_request_refer(), process_ast_dsp(), and socket_process().
04609 { 04610 int res = 0; 04611 04612 ast_channel_lock(chan); 04613 04614 if (chan->pbx) { /* This channel is currently in the PBX */ 04615 ast_explicit_goto(chan, context, exten, priority); 04616 ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO); 04617 } else { 04618 /* In order to do it when the channel doesn't really exist within 04619 the PBX, we have to make a new channel, masquerade, and start the PBX 04620 at the new location */ 04621 struct ast_channel *tmpchan = ast_channel_alloc(0, chan->_state, 0, 0, chan->accountcode, chan->exten, chan->context, chan->amaflags, "AsyncGoto/%s", chan->name); 04622 if (!tmpchan) { 04623 res = -1; 04624 } else { 04625 if (chan->cdr) { 04626 ast_cdr_discard(tmpchan->cdr); 04627 tmpchan->cdr = ast_cdr_dup(chan->cdr); /* share the love */ 04628 } 04629 /* Make formats okay */ 04630 tmpchan->readformat = chan->readformat; 04631 tmpchan->writeformat = chan->writeformat; 04632 /* Setup proper location */ 04633 ast_explicit_goto(tmpchan, 04634 S_OR(context, chan->context), S_OR(exten, chan->exten), priority); 04635 04636 /* Masquerade into temp channel */ 04637 if (ast_channel_masquerade(tmpchan, chan)) { 04638 /* Failed to set up the masquerade. It's probably chan_local 04639 * in the middle of optimizing itself out. Sad. :( */ 04640 ast_hangup(tmpchan); 04641 tmpchan = NULL; 04642 res = -1; 04643 } else { 04644 /* Grab the locks and get going */ 04645 ast_channel_lock(tmpchan); 04646 ast_do_masquerade(tmpchan); 04647 ast_channel_unlock(tmpchan); 04648 /* Start the PBX going on our stolen channel */ 04649 if (ast_pbx_start(tmpchan)) { 04650 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name); 04651 ast_hangup(tmpchan); 04652 res = -1; 04653 } 04654 } 04655 } 04656 } 04657 ast_channel_unlock(chan); 04658 return res; 04659 }
int ast_async_goto_by_name | ( | const char * | channame, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 4661 of file pbx.c.
References ast_async_goto(), ast_channel_unlock, and ast_get_channel_by_name_locked().
04662 { 04663 struct ast_channel *chan; 04664 int res = -1; 04665 04666 chan = ast_get_channel_by_name_locked(channame); 04667 if (chan) { 04668 res = ast_async_goto(chan, context, exten, priority); 04669 ast_channel_unlock(chan); 04670 } 04671 return res; 04672 }
int ast_async_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 6462 of file pbx.c.
References __ast_goto_if_exists().
Referenced by asyncgoto_exec().
06463 { 06464 return __ast_goto_if_exists(chan, context, exten, priority, 1); 06465 }
int ast_build_timing | ( | struct ast_timing * | i, | |
const char * | info_in | |||
) |
Definition at line 4253 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().
04254 { 04255 char info_save[256]; 04256 char *info; 04257 04258 /* Check for empty just in case */ 04259 if (ast_strlen_zero(info_in)) 04260 return 0; 04261 /* make a copy just in case we were passed a static string */ 04262 ast_copy_string(info_save, info_in, sizeof(info_save)); 04263 info = info_save; 04264 /* Assume everything except time */ 04265 i->monthmask = 0xfff; /* 12 bits */ 04266 i->daymask = 0x7fffffffU; /* 31 bits */ 04267 i->dowmask = 0x7f; /* 7 bits */ 04268 /* on each call, use strsep() to move info to the next argument */ 04269 get_timerange(i, strsep(&info, "|")); 04270 if (info) 04271 i->dowmask = get_range(strsep(&info, "|"), 7, days, "day of week"); 04272 if (info) 04273 i->daymask = get_range(strsep(&info, "|"), 31, NULL, "day"); 04274 if (info) 04275 i->monthmask = get_range(strsep(&info, "|"), 12, months, "month"); 04276 return 1; 04277 }
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 2330 of file pbx.c.
References E_CANMATCH, and pbx_extension_helper().
Referenced by background_detect_exec(), cb_events(), dp_lookup(), dundi_lookup_local(), get_also_info(), get_destination(), handle_link_data(), handle_link_phone_dtmf(), local_dtmf_helper(), loopback_canmatch(), mgcp_ss(), phone_check_exception(), skinny_ss(), ss_thread(), and valid_exit().
02331 { 02332 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH); 02333 }
ast_change_hint: Change hint for an extension
Definition at line 2242 of file pbx.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, and ast_hint::exten.
Referenced by add_pri().
02243 { 02244 struct ast_hint *hint; 02245 int res = -1; 02246 02247 AST_LIST_LOCK(&hints); 02248 AST_LIST_TRAVERSE(&hints, hint, list) { 02249 if (hint->exten == oe) { 02250 hint->exten = ne; 02251 res = 0; 02252 break; 02253 } 02254 } 02255 AST_LIST_UNLOCK(&hints); 02256 02257 return res; 02258 }
int ast_check_timing | ( | const struct ast_timing * | i | ) |
Definition at line 4279 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().
04280 { 04281 struct tm tm; 04282 time_t t = time(NULL); 04283 04284 ast_localtime(&t, &tm, NULL); 04285 04286 /* If it's not the right month, return */ 04287 if (!(i->monthmask & (1 << tm.tm_mon))) 04288 return 0; 04289 04290 /* If it's not that time of the month.... */ 04291 /* Warning, tm_mday has range 1..31! */ 04292 if (!(i->daymask & (1 << (tm.tm_mday-1)))) 04293 return 0; 04294 04295 /* If it's not the right day of the week */ 04296 if (!(i->dowmask & (1 << tm.tm_wday))) 04297 return 0; 04298 04299 /* Sanity check the hour just to be safe */ 04300 if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) { 04301 ast_log(LOG_WARNING, "Insane time...\n"); 04302 return 0; 04303 } 04304 04305 /* Now the tough part, we calculate if it fits 04306 in the right time based on min/hour */ 04307 if (!(i->minmask[tm.tm_hour] & (1 << (tm.tm_min / 2)))) 04308 return 0; 04309 04310 /* If we got this far, then we're good */ 04311 return 1; 04312 }
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 4506 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().
04507 { 04508 int ret = -1; 04509 struct ast_context *c = find_context_locked(context); 04510 04511 if (c) { 04512 ret = ast_context_add_ignorepat2(c, value, registrar); 04513 ast_unlock_contexts(); 04514 } 04515 return ret; 04516 }
int ast_context_add_ignorepat2 | ( | struct ast_context * | con, | |
const char * | value, | |||
const char * | registrar | |||
) |
Definition at line 4518 of file pbx.c.
References ast_calloc, ast_mutex_lock(), ast_mutex_unlock(), errno, ast_context::ignorepats, ast_context::lock, ast_ignorepat::next, ast_ignorepat::pattern, and ast_ignorepat::registrar.
Referenced by ast_context_add_ignorepat(), and pbx_load_config().
04519 { 04520 struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL; 04521 int length; 04522 length = sizeof(struct ast_ignorepat); 04523 length += strlen(value) + 1; 04524 if (!(ignorepat = ast_calloc(1, length))) 04525 return -1; 04526 /* The cast to char * is because we need to write the initial value. 04527 * The field is not supposed to be modified otherwise 04528 */ 04529 strcpy((char *)ignorepat->pattern, value); 04530 ignorepat->next = NULL; 04531 ignorepat->registrar = registrar; 04532 ast_mutex_lock(&con->lock); 04533 for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) { 04534 ignorepatl = ignorepatc; 04535 if (!strcasecmp(ignorepatc->pattern, value)) { 04536 /* Already there */ 04537 ast_mutex_unlock(&con->lock); 04538 errno = EEXIST; 04539 return -1; 04540 } 04541 } 04542 if (ignorepatl) 04543 ignorepatl->next = ignorepat; 04544 else 04545 con->ignorepats = ignorepat; 04546 ast_mutex_unlock(&con->lock); 04547 return 0; 04548 04549 }
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 4059 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().
04060 { 04061 int ret = -1; 04062 struct ast_context *c = find_context_locked(context); 04063 04064 if (c) { 04065 ret = ast_context_add_include2(c, include, registrar); 04066 ast_unlock_contexts(); 04067 } 04068 return ret; 04069 }
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 4321 of file pbx.c.
References ast_build_timing(), ast_calloc, ast_get_context_name(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), errno, free, ast_include::hastime, ast_context::includes, ast_context::lock, ast_include::name, ast_include::next, option_verbose, ast_include::registrar, ast_include::rname, ast_include::stuff, ast_include::timing, and VERBOSE_PREFIX_3.
Referenced by ast_context_add_include(), and pbx_load_config().
04323 { 04324 struct ast_include *new_include; 04325 char *c; 04326 struct ast_include *i, *il = NULL; /* include, include_last */ 04327 int length; 04328 char *p; 04329 04330 length = sizeof(struct ast_include); 04331 length += 2 * (strlen(value) + 1); 04332 04333 /* allocate new include structure ... */ 04334 if (!(new_include = ast_calloc(1, length))) 04335 return -1; 04336 /* Fill in this structure. Use 'p' for assignments, as the fields 04337 * in the structure are 'const char *' 04338 */ 04339 p = new_include->stuff; 04340 new_include->name = p; 04341 strcpy(p, value); 04342 p += strlen(value) + 1; 04343 new_include->rname = p; 04344 strcpy(p, value); 04345 /* Strip off timing info, and process if it is there */ 04346 if ( (c = strchr(p, '|')) ) { 04347 *c++ = '\0'; 04348 new_include->hastime = ast_build_timing(&(new_include->timing), c); 04349 } 04350 new_include->next = NULL; 04351 new_include->registrar = registrar; 04352 04353 ast_mutex_lock(&con->lock); 04354 04355 /* ... go to last include and check if context is already included too... */ 04356 for (i = con->includes; i; i = i->next) { 04357 if (!strcasecmp(i->name, new_include->name)) { 04358 free(new_include); 04359 ast_mutex_unlock(&con->lock); 04360 errno = EEXIST; 04361 return -1; 04362 } 04363 il = i; 04364 } 04365 04366 /* ... include new context into context list, unlock, return */ 04367 if (il) 04368 il->next = new_include; 04369 else 04370 con->includes = new_include; 04371 if (option_verbose > 2) 04372 ast_verbose(VERBOSE_PREFIX_3 "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con)); 04373 ast_mutex_unlock(&con->lock); 04374 04375 return 0; 04376 }
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 4383 of file pbx.c.
References ast_context_add_switch2(), ast_unlock_contexts(), and find_context_locked().
04384 { 04385 int ret = -1; 04386 struct ast_context *c = find_context_locked(context); 04387 04388 if (c) { /* found, add switch to this context */ 04389 ret = ast_context_add_switch2(c, sw, data, eval, registrar); 04390 ast_unlock_contexts(); 04391 } 04392 return ret; 04393 }
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 4402 of file pbx.c.
References ast_calloc, ast_get_context_name(), AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), ast_sw::data, errno, ast_sw::eval, free, ast_context::lock, ast_sw::name, option_verbose, ast_sw::registrar, and VERBOSE_PREFIX_3.
Referenced by ast_context_add_switch(), and pbx_load_config().
04404 { 04405 struct ast_sw *new_sw; 04406 struct ast_sw *i; 04407 int length; 04408 char *p; 04409 04410 length = sizeof(struct ast_sw); 04411 length += strlen(value) + 1; 04412 if (data) 04413 length += strlen(data); 04414 length++; 04415 04416 /* allocate new sw structure ... */ 04417 if (!(new_sw = ast_calloc(1, length))) 04418 return -1; 04419 /* ... fill in this structure ... */ 04420 p = new_sw->stuff; 04421 new_sw->name = p; 04422 strcpy(new_sw->name, value); 04423 p += strlen(value) + 1; 04424 new_sw->data = p; 04425 if (data) { 04426 strcpy(new_sw->data, data); 04427 p += strlen(data) + 1; 04428 } else { 04429 strcpy(new_sw->data, ""); 04430 p++; 04431 } 04432 new_sw->eval = eval; 04433 new_sw->registrar = registrar; 04434 04435 /* ... try to lock this context ... */ 04436 ast_mutex_lock(&con->lock); 04437 04438 /* ... go to last sw and check if context is already swd too... */ 04439 AST_LIST_TRAVERSE(&con->alts, i, list) { 04440 if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) { 04441 free(new_sw); 04442 ast_mutex_unlock(&con->lock); 04443 errno = EEXIST; 04444 return -1; 04445 } 04446 } 04447 04448 /* ... sw new context into context list, unlock, return */ 04449 AST_LIST_INSERT_TAIL(&con->alts, new_sw, list); 04450 04451 if (option_verbose > 2) 04452 ast_verbose(VERBOSE_PREFIX_3 "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con)); 04453 04454 ast_mutex_unlock(&con->lock); 04455 04456 return 0; 04457 }
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 3929 of file pbx.c.
References __ast_context_create().
Referenced by do_parking_thread(), park_call_full(), and set_config().
03930 { 03931 return __ast_context_create(extcontexts, name, registrar, 0); 03932 }
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 5366 of file pbx.c.
References __ast_context_destroy(), ast_unlock_contexts(), and ast_wrlock_contexts().
Referenced by cleanup_stale_contexts(), sla_destroy(), and unload_module().
05367 { 05368 ast_wrlock_contexts(); 05369 __ast_context_destroy(con,registrar); 05370 ast_unlock_contexts(); 05371 }
struct ast_context* ast_context_find | ( | const char * | name | ) |
Find a context.
name | name of the context to find |
Definition at line 917 of file pbx.c.
References ast_rdlock_contexts(), ast_unlock_contexts(), and ast_walk_contexts().
Referenced by _macro_exec(), ast_context_verify_includes(), ast_ignore_pattern(), cleanup_stale_contexts(), do_parking_thread(), park_call_full(), park_exec(), register_peer_exten(), and set_config().
00918 { 00919 struct ast_context *tmp = NULL; 00920 00921 ast_rdlock_contexts(); 00922 00923 while ( (tmp = ast_walk_contexts(tmp)) ) { 00924 if (!name || !strcasecmp(name, tmp->name)) 00925 break; 00926 } 00927 00928 ast_unlock_contexts(); 00929 00930 return tmp; 00931 }
struct ast_context* ast_context_find_or_create | ( | struct ast_context ** | extcontexts, | |
const char * | name, | |||
const char * | registrar | |||
) |
Definition at line 3934 of file pbx.c.
References __ast_context_create().
Referenced by pbx_load_config(), and pbx_load_users().
03935 { 03936 return __ast_context_create(extcontexts, name, registrar, 1); 03937 }
int ast_context_lockmacro | ( | const char * | context | ) |
locks the macrolock in the given given context
Definition at line 2930 of file pbx.c.
References ast_get_context_name(), ast_mutex_lock(), ast_rdlock_contexts(), ast_unlock_contexts(), and ast_walk_contexts().
Referenced by _macro_exec().
02931 { 02932 struct ast_context *c = NULL; 02933 int ret = -1; 02934 02935 ast_rdlock_contexts(); 02936 02937 while ((c = ast_walk_contexts(c))) { 02938 if (!strcmp(ast_get_context_name(c), context)) { 02939 ret = 0; 02940 break; 02941 } 02942 } 02943 02944 ast_unlock_contexts(); 02945 02946 /* if we found context, lock macrolock */ 02947 if (ret == 0) 02948 ret = ast_mutex_lock(&c->macrolock); 02949 02950 return ret; 02951 }
int ast_context_remove_extension | ( | const char * | context, | |
const char * | extension, | |||
int | priority, | |||
const char * | registrar | |||
) |
Simply remove extension from context.
context | context to remove extension from | |
extension | which extension to remove | |
priority | priority of extension to remove (0 to remove all) | |
callerid | NULL to remove all; non-NULL to match a single record per priority | |
matchcid | non-zero to match callerid element (if non-NULL); 0 to match default case | |
registrar | registrar of the extension |
0 | on success | |
-1 | on failure |
Definition at line 2831 of file pbx.c.
References ast_context_remove_extension_callerid().
Referenced by destroy_station(), destroy_trunk(), and register_peer_exten().
02832 { 02833 return ast_context_remove_extension_callerid(context, extension, priority, NULL, 0, registrar); 02834 }
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 2858 of file pbx.c.
References ast_context_remove_extension_callerid2().
Referenced by do_parking_thread(), and park_exec().
02859 { 02860 return ast_context_remove_extension_callerid2(con, extension, priority, NULL, 0, registrar); 02861 }
int ast_context_remove_extension_callerid | ( | const char * | context, | |
const char * | extension, | |||
int | priority, | |||
const char * | callerid, | |||
int | matchcid, | |||
const char * | registrar | |||
) |
Definition at line 2836 of file pbx.c.
References ast_context_remove_extension_callerid2(), ast_unlock_contexts(), and find_context_locked().
Referenced by ast_context_remove_extension(), handle_context_remove_extension(), and handle_context_remove_extension_deprecated().
02837 { 02838 int ret = -1; /* default error return */ 02839 struct ast_context *c = find_context_locked(context); 02840 02841 if (c) { /* ... remove extension ... */ 02842 ret = ast_context_remove_extension_callerid2(c, extension, priority, callerid, matchcid, registrar); 02843 ast_unlock_contexts(); 02844 } 02845 return ret; 02846 }
int ast_context_remove_extension_callerid2 | ( | struct ast_context * | con, | |
const char * | extension, | |||
int | priority, | |||
const char * | callerid, | |||
int | matchcid, | |||
const char * | registrar | |||
) |
Definition at line 2863 of file pbx.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_exten::cidmatch, destroy_exten(), exten, ast_exten::exten, ast_context::lock, ast_exten::next, ast_exten::peer, ast_exten::priority, ast_exten::registrar, and ast_context::root.
Referenced by ast_context_remove_extension2(), and ast_context_remove_extension_callerid().
02864 { 02865 struct ast_exten *exten, *prev_exten = NULL; 02866 struct ast_exten *peer; 02867 struct ast_exten *previous_peer = NULL; 02868 struct ast_exten *next_peer = NULL; 02869 int found = 0; 02870 02871 ast_mutex_lock(&con->lock); 02872 02873 /* scan the extension list to find first matching extension-registrar */ 02874 for (exten = con->root; exten; prev_exten = exten, exten = exten->next) { 02875 if (!strcmp(exten->exten, extension) && 02876 (!registrar || !strcmp(exten->registrar, registrar))) 02877 break; 02878 } 02879 if (!exten) { 02880 /* we can't find right extension */ 02881 ast_mutex_unlock(&con->lock); 02882 return -1; 02883 } 02884 02885 /* scan the priority list to remove extension with exten->priority == priority */ 02886 for (peer = exten, next_peer = exten->peer ? exten->peer : exten->next; 02887 peer && !strcmp(peer->exten, extension); 02888 peer = next_peer, next_peer = next_peer ? (next_peer->peer ? next_peer->peer : next_peer->next) : NULL) { 02889 if ((priority == 0 || peer->priority == priority) && 02890 (!callerid || !matchcid || (matchcid && !strcmp(peer->cidmatch, callerid))) && 02891 (!registrar || !strcmp(peer->registrar, registrar) )) { 02892 found = 1; 02893 02894 /* we are first priority extension? */ 02895 if (!previous_peer) { 02896 /* 02897 * We are first in the priority chain, so must update the extension chain. 02898 * The next node is either the next priority or the next extension 02899 */ 02900 struct ast_exten *next_node = peer->peer ? peer->peer : peer->next; 02901 02902 if (!prev_exten) { /* change the root... */ 02903 con->root = next_node; 02904 } else { 02905 prev_exten->next = next_node; /* unlink */ 02906 } 02907 if (peer->peer) { /* update the new head of the pri list */ 02908 peer->peer->next = peer->next; 02909 } 02910 } else { /* easy, we are not first priority in extension */ 02911 previous_peer->peer = peer->peer; 02912 } 02913 02914 /* now, free whole priority extension */ 02915 destroy_exten(peer); 02916 } else { 02917 previous_peer = peer; 02918 } 02919 } 02920 ast_mutex_unlock(&con->lock); 02921 return found ? 0 : -1; 02922 }
int ast_context_remove_ignorepat | ( | const char * | context, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 4463 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().
04464 { 04465 int ret = -1; 04466 struct ast_context *c = find_context_locked(context); 04467 04468 if (c) { 04469 ret = ast_context_remove_ignorepat2(c, ignorepat, registrar); 04470 ast_unlock_contexts(); 04471 } 04472 return ret; 04473 }
int ast_context_remove_ignorepat2 | ( | struct ast_context * | con, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 4475 of file pbx.c.
References ast_mutex_lock(), ast_mutex_unlock(), errno, free, ast_context::ignorepats, ast_context::lock, ast_ignorepat::next, ast_ignorepat::pattern, and ast_ignorepat::registrar.
Referenced by ast_context_remove_ignorepat().
04476 { 04477 struct ast_ignorepat *ip, *ipl = NULL; 04478 04479 ast_mutex_lock(&con->lock); 04480 04481 for (ip = con->ignorepats; ip; ip = ip->next) { 04482 if (!strcmp(ip->pattern, ignorepat) && 04483 (!registrar || (registrar == ip->registrar))) { 04484 if (ipl) { 04485 ipl->next = ip->next; 04486 free(ip); 04487 } else { 04488 con->ignorepats = ip->next; 04489 free(ip); 04490 } 04491 ast_mutex_unlock(&con->lock); 04492 return 0; 04493 } 04494 ipl = ip; 04495 } 04496 04497 ast_mutex_unlock(&con->lock); 04498 errno = EINVAL; 04499 return -1; 04500 }
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 2727 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().
02728 { 02729 int ret = -1; 02730 struct ast_context *c = find_context_locked(context); 02731 02732 if (c) { 02733 /* found, remove include from this context ... */ 02734 ret = ast_context_remove_include2(c, include, registrar); 02735 ast_unlock_contexts(); 02736 } 02737 return ret; 02738 }
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 2748 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().
02749 { 02750 struct ast_include *i, *pi = NULL; 02751 int ret = -1; 02752 02753 ast_mutex_lock(&con->lock); 02754 02755 /* find our include */ 02756 for (i = con->includes; i; pi = i, i = i->next) { 02757 if (!strcmp(i->name, include) && 02758 (!registrar || !strcmp(i->registrar, registrar))) { 02759 /* remove from list */ 02760 if (pi) 02761 pi->next = i->next; 02762 else 02763 con->includes = i->next; 02764 /* free include and return */ 02765 free(i); 02766 ret = 0; 02767 break; 02768 } 02769 } 02770 02771 ast_mutex_unlock(&con->lock); 02772 return ret; 02773 }
int ast_context_remove_switch | ( | const char * | context, | |
const char * | sw, | |||
const char * | data, | |||
const char * | registrar | |||
) |
Remove a switch.
Definition at line 2780 of file pbx.c.
References ast_context_remove_switch2(), ast_unlock_contexts(), and find_context_locked().
02781 { 02782 int ret = -1; /* default error return */ 02783 struct ast_context *c = find_context_locked(context); 02784 02785 if (c) { 02786 /* remove switch from this context ... */ 02787 ret = ast_context_remove_switch2(c, sw, data, registrar); 02788 ast_unlock_contexts(); 02789 } 02790 return ret; 02791 }
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 2801 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().
02802 { 02803 struct ast_sw *i; 02804 int ret = -1; 02805 02806 ast_mutex_lock(&con->lock); 02807 02808 /* walk switches */ 02809 AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) { 02810 if (!strcmp(i->name, sw) && !strcmp(i->data, data) && 02811 (!registrar || !strcmp(i->registrar, registrar))) { 02812 /* found, remove from list */ 02813 AST_LIST_REMOVE_CURRENT(&con->alts, list); 02814 free(i); /* free switch and return */ 02815 ret = 0; 02816 break; 02817 } 02818 } 02819 AST_LIST_TRAVERSE_SAFE_END 02820 02821 ast_mutex_unlock(&con->lock); 02822 02823 return ret; 02824 }
int ast_context_unlockmacro | ( | const char * | context | ) |
Unlocks the macrolock in the given context.
Definition at line 2958 of file pbx.c.
References ast_get_context_name(), ast_mutex_unlock(), ast_rdlock_contexts(), ast_unlock_contexts(), and ast_walk_contexts().
Referenced by _macro_exec().
02959 { 02960 struct ast_context *c = NULL; 02961 int ret = -1; 02962 02963 ast_rdlock_contexts(); 02964 02965 while ((c = ast_walk_contexts(c))) { 02966 if (!strcmp(ast_get_context_name(c), context)) { 02967 ret = 0; 02968 break; 02969 } 02970 } 02971 02972 ast_unlock_contexts(); 02973 02974 /* if we found context, unlock macrolock */ 02975 if (ret == 0) 02976 ret = ast_mutex_unlock(&c->macrolock); 02977 02978 return ret; 02979 }
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 6419 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().
06420 { 06421 struct ast_include *inc = NULL; 06422 int res = 0; 06423 06424 while ( (inc = ast_walk_context_includes(con, inc)) ) { 06425 if (ast_context_find(inc->rname)) 06426 continue; 06427 06428 res = -1; 06429 ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n", 06430 ast_get_context_name(con), inc->rname); 06431 break; 06432 } 06433 06434 return res; 06435 }
struct ast_custom_function* ast_custom_function_find | ( | const char * | name | ) |
Definition at line 1479 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().
01480 { 01481 struct ast_custom_function *acf = NULL; 01482 01483 AST_LIST_LOCK(&acf_root); 01484 AST_LIST_TRAVERSE(&acf_root, acf, acflist) { 01485 if (!strcmp(name, acf->name)) 01486 break; 01487 } 01488 AST_LIST_UNLOCK(&acf_root); 01489 01490 return acf; 01491 }
int ast_custom_function_register | ( | struct ast_custom_function * | acf | ) |
Reigster a custom function.
Definition at line 1515 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().
01516 { 01517 struct ast_custom_function *cur; 01518 01519 if (!acf) 01520 return -1; 01521 01522 AST_LIST_LOCK(&acf_root); 01523 01524 if (ast_custom_function_find(acf->name)) { 01525 ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name); 01526 AST_LIST_UNLOCK(&acf_root); 01527 return -1; 01528 } 01529 01530 /* Store in alphabetical order */ 01531 AST_LIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) { 01532 if (strcasecmp(acf->name, cur->name) < 0) { 01533 AST_LIST_INSERT_BEFORE_CURRENT(&acf_root, acf, acflist); 01534 break; 01535 } 01536 } 01537 AST_LIST_TRAVERSE_SAFE_END 01538 if (!cur) 01539 AST_LIST_INSERT_TAIL(&acf_root, acf, acflist); 01540 01541 AST_LIST_UNLOCK(&acf_root); 01542 01543 if (option_verbose > 1) 01544 ast_verbose(VERBOSE_PREFIX_2 "Registered custom function %s\n", acf->name); 01545 01546 return 0; 01547 }
int ast_custom_function_unregister | ( | struct ast_custom_function * | acf | ) |
Unregister a custom function.
Definition at line 1493 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().
01494 { 01495 struct ast_custom_function *cur; 01496 01497 if (!acf) 01498 return -1; 01499 01500 AST_LIST_LOCK(&acf_root); 01501 AST_LIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) { 01502 if (cur == acf) { 01503 AST_LIST_REMOVE_CURRENT(&acf_root, acflist); 01504 if (option_verbose > 1) 01505 ast_verbose(VERBOSE_PREFIX_2 "Unregistered custom function %s\n", acf->name); 01506 break; 01507 } 01508 } 01509 AST_LIST_TRAVERSE_SAFE_END 01510 AST_LIST_UNLOCK(&acf_root); 01511 01512 return acf ? 0 : -1; 01513 }
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 2315 of file pbx.c.
References E_MATCH, and pbx_extension_helper().
Referenced by __ast_goto_if_exists(), __ast_pbx_run(), __login_exec(), _macro_exec(), agentmonitoroutgoing_exec(), answer_call(), ast_app_dtget(), ast_pbx_outgoing_exten(), builtin_blindtransfer(), cb_events(), conf_run(), console_dial(), console_dial_deprecated(), console_transfer(), console_transfer_deprecated(), dahdi_handle_dtmfup(), disa_exec(), do_atxfer(), dp_lookup(), dundi_lookup_local(), get_also_info(), get_destination(), get_refer_info(), handle_link_data(), handle_link_phone_dtmf(), handle_stimulus_message(), leave_voicemail(), local_alloc(), local_devicestate(), local_dtmf_helper(), loopback_exists(), metermaidstate(), mgcp_ss(), misdn_overlap_dial_task(), park_call_full(), parkandannounce_exec(), pbx_builtin_waitexten(), phone_check_exception(), process_ast_dsp(), register_peer_exten(), skinny_ss(), socket_process(), ss_thread(), and waitstream_core().
02316 { 02317 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH); 02318 }
int ast_explicit_goto | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 4585 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, AST_FLAG_IN_AUTOLOOP, ast_strlen_zero(), ast_test_flag, ast_channel::context, ast_channel::exten, and ast_channel::priority.
Referenced by __ast_goto_if_exists(), ast_async_goto(), ast_parseable_goto(), disa_exec(), do_atxfer(), and handle_setpriority().
04586 { 04587 if (!chan) 04588 return -1; 04589 04590 ast_channel_lock(chan); 04591 04592 if (!ast_strlen_zero(context)) 04593 ast_copy_string(chan->context, context, sizeof(chan->context)); 04594 if (!ast_strlen_zero(exten)) 04595 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 04596 if (priority > -1) { 04597 chan->priority = priority; 04598 /* see flag description in channel.h for explanation */ 04599 if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP)) 04600 chan->priority--; 04601 } 04602 04603 ast_channel_unlock(chan); 04604 04605 return 0; 04606 }
int ast_extension_close | ( | const char * | pattern, | |
const char * | data, | |||
int | needmore | |||
) |
Definition at line 910 of file pbx.c.
References ast_log(), E_CANMATCH, E_MATCHMORE, extension_match_core(), and LOG_WARNING.
Referenced by realtime_switch_common().
00911 { 00912 if (needmore != E_MATCHMORE && needmore != E_CANMATCH) 00913 ast_log(LOG_WARNING, "invalid argument %d\n", needmore); 00914 return extension_match_core(pattern, data, needmore); 00915 }
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 905 of file pbx.c.
References E_MATCH, and extension_match_core().
Referenced by ast_ignore_pattern(), do_say(), find_matching_priority(), loopback_canmatch(), loopback_exists(), loopback_matchmore(), matchcid(), misdn_cfg_is_msn_valid(), realtime_switch_common(), and show_dialplan_helper().
00906 { 00907 return extension_match_core(pattern, data, E_MATCH); 00908 }
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 2039 of file pbx.c.
References ast_extension_state2(), and ast_hint_extension().
Referenced by action_extensionstate(), and handle_request_subscribe().
02040 { 02041 struct ast_exten *e; 02042 02043 e = ast_hint_extension(c, context, exten); /* Do we have a hint for this extension ? */ 02044 if (!e) 02045 return -1; /* No hint, return -1 */ 02046 02047 return ast_extension_state2(e); /* Check all devices in the hint */ 02048 }
static int ast_extension_state2 | ( | struct ast_exten * | e | ) | [static] |
ast_extensions_state2: Check state of extension by using hints
Definition at line 1942 of file pbx.c.
References AST_DEVICE_BUSY, AST_DEVICE_INUSE, AST_DEVICE_INVALID, AST_DEVICE_NOT_INUSE, AST_DEVICE_ONHOLD, AST_DEVICE_RINGING, AST_DEVICE_RINGINUSE, ast_device_state(), AST_DEVICE_UNAVAILABLE, AST_EXTENSION_BUSY, AST_EXTENSION_INUSE, AST_EXTENSION_NOT_INUSE, AST_EXTENSION_ONHOLD, AST_EXTENSION_RINGING, AST_EXTENSION_UNAVAILABLE, ast_get_extension_app(), AST_MAX_EXTENSION, busy, inuse, ring(), and strsep().
Referenced by ast_add_hint(), ast_extension_state(), and ast_hint_state_changed().
01943 { 01944 char hint[AST_MAX_EXTENSION]; 01945 char *cur, *rest; 01946 int allunavailable = 1, allbusy = 1, allfree = 1, allonhold = 1; 01947 int busy = 0, inuse = 0, ring = 0; 01948 01949 if (!e) 01950 return -1; 01951 01952 ast_copy_string(hint, ast_get_extension_app(e), sizeof(hint)); 01953 01954 rest = hint; /* One or more devices separated with a & character */ 01955 while ( (cur = strsep(&rest, "&")) ) { 01956 int res = ast_device_state(cur); 01957 switch (res) { 01958 case AST_DEVICE_NOT_INUSE: 01959 allunavailable = 0; 01960 allbusy = 0; 01961 allonhold = 0; 01962 break; 01963 case AST_DEVICE_INUSE: 01964 inuse = 1; 01965 allunavailable = 0; 01966 allfree = 0; 01967 allonhold = 0; 01968 break; 01969 case AST_DEVICE_RINGING: 01970 ring = 1; 01971 allunavailable = 0; 01972 allfree = 0; 01973 allonhold = 0; 01974 break; 01975 case AST_DEVICE_RINGINUSE: 01976 inuse = 1; 01977 ring = 1; 01978 allunavailable = 0; 01979 allfree = 0; 01980 allonhold = 0; 01981 break; 01982 case AST_DEVICE_ONHOLD: 01983 allunavailable = 0; 01984 allfree = 0; 01985 break; 01986 case AST_DEVICE_BUSY: 01987 allunavailable = 0; 01988 allfree = 0; 01989 allonhold = 0; 01990 busy = 1; 01991 break; 01992 case AST_DEVICE_UNAVAILABLE: 01993 case AST_DEVICE_INVALID: 01994 allbusy = 0; 01995 allfree = 0; 01996 allonhold = 0; 01997 break; 01998 default: 01999 allunavailable = 0; 02000 allbusy = 0; 02001 allfree = 0; 02002 allonhold = 0; 02003 } 02004 } 02005 02006 if (!inuse && ring) 02007 return AST_EXTENSION_RINGING; 02008 if (inuse && ring) 02009 return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING); 02010 if (inuse) 02011 return AST_EXTENSION_INUSE; 02012 if (allfree) 02013 return AST_EXTENSION_NOT_INUSE; 02014 if (allonhold) 02015 return AST_EXTENSION_ONHOLD; 02016 if (allbusy) 02017 return AST_EXTENSION_BUSY; 02018 if (allunavailable) 02019 return AST_EXTENSION_UNAVAILABLE; 02020 if (busy) 02021 return AST_EXTENSION_INUSE; 02022 02023 return AST_EXTENSION_NOT_INUSE; 02024 }
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 2027 of file pbx.c.
References extension_states.
Referenced by cb_extensionstate(), handle_request_subscribe(), and handle_show_hints().
02028 { 02029 int i; 02030 02031 for (i = 0; (i < (sizeof(extension_states) / sizeof(extension_states[0]))); i++) { 02032 if (extension_states[i].extension_state == extension_state) 02033 return extension_states[i].text; 02034 } 02035 return "Unknown"; 02036 }
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 2094 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().
02096 { 02097 struct ast_hint *hint; 02098 struct ast_state_cb *cblist; 02099 struct ast_exten *e; 02100 02101 /* If there's no context and extension: add callback to statecbs list */ 02102 if (!context && !exten) { 02103 AST_LIST_LOCK(&hints); 02104 02105 for (cblist = statecbs; cblist; cblist = cblist->next) { 02106 if (cblist->callback == callback) { 02107 cblist->data = data; 02108 AST_LIST_UNLOCK(&hints); 02109 return 0; 02110 } 02111 } 02112 02113 /* Now insert the callback */ 02114 if (!(cblist = ast_calloc(1, sizeof(*cblist)))) { 02115 AST_LIST_UNLOCK(&hints); 02116 return -1; 02117 } 02118 cblist->id = 0; 02119 cblist->callback = callback; 02120 cblist->data = data; 02121 02122 cblist->next = statecbs; 02123 statecbs = cblist; 02124 02125 AST_LIST_UNLOCK(&hints); 02126 return 0; 02127 } 02128 02129 if (!context || !exten) 02130 return -1; 02131 02132 /* This callback type is for only one hint, so get the hint */ 02133 e = ast_hint_extension(NULL, context, exten); 02134 if (!e) { 02135 return -1; 02136 } 02137 02138 /* Find the hint in the list of hints */ 02139 AST_LIST_LOCK(&hints); 02140 02141 AST_LIST_TRAVERSE(&hints, hint, list) { 02142 if (hint->exten == e) 02143 break; 02144 } 02145 02146 if (!hint) { 02147 /* We have no hint, sorry */ 02148 AST_LIST_UNLOCK(&hints); 02149 return -1; 02150 } 02151 02152 /* Now insert the callback in the callback list */ 02153 if (!(cblist = ast_calloc(1, sizeof(*cblist)))) { 02154 AST_LIST_UNLOCK(&hints); 02155 return -1; 02156 } 02157 cblist->id = stateid++; /* Unique ID for this callback */ 02158 cblist->callback = callback; /* Pointer to callback routine */ 02159 cblist->data = data; /* Data for the callback */ 02160 02161 cblist->next = hint->callbacks; 02162 hint->callbacks = cblist; 02163 02164 AST_LIST_UNLOCK(&hints); 02165 return cblist->id; 02166 }
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 2169 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().
02170 { 02171 struct ast_state_cb **p_cur = NULL; /* address of pointer to us */ 02172 int ret = -1; 02173 02174 if (!id && !callback) 02175 return -1; 02176 02177 AST_LIST_LOCK(&hints); 02178 02179 if (!id) { /* id == 0 is a callback without extension */ 02180 for (p_cur = &statecbs; *p_cur; p_cur = &(*p_cur)->next) { 02181 if ((*p_cur)->callback == callback) 02182 break; 02183 } 02184 } else { /* callback with extension, find the callback based on ID */ 02185 struct ast_hint *hint; 02186 AST_LIST_TRAVERSE(&hints, hint, list) { 02187 for (p_cur = &hint->callbacks; *p_cur; p_cur = &(*p_cur)->next) { 02188 if ((*p_cur)->id == id) 02189 break; 02190 } 02191 if (*p_cur) /* found in the inner loop */ 02192 break; 02193 } 02194 } 02195 if (p_cur && *p_cur) { 02196 struct ast_state_cb *cur = *p_cur; 02197 *p_cur = cur->next; 02198 free(cur); 02199 ret = 0; 02200 } 02201 AST_LIST_UNLOCK(&hints); 02202 return ret; 02203 }
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 2320 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().
02321 { 02322 return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL); 02323 }
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 2325 of file pbx.c.
References E_FINDLABEL, and pbx_extension_helper().
Referenced by pbx_load_config().
02326 { 02327 return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL); 02328 }
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 1569 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().
01570 { 01571 char *args = func_args(function); 01572 struct ast_custom_function *acfptr = ast_custom_function_find(function); 01573 01574 if (acfptr == NULL) 01575 ast_log(LOG_ERROR, "Function %s not registered\n", function); 01576 else if (!acfptr->read) 01577 ast_log(LOG_ERROR, "Function %s cannot be read\n", function); 01578 else 01579 return acfptr->read(chan, function, args, workspace, len); 01580 return -1; 01581 }
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 1583 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().
01584 { 01585 char *args = func_args(function); 01586 struct ast_custom_function *acfptr = ast_custom_function_find(function); 01587 01588 if (acfptr == NULL) 01589 ast_log(LOG_ERROR, "Function %s not registered\n", function); 01590 else if (!acfptr->write) 01591 ast_log(LOG_ERROR, "Function %s cannot be written to\n", function); 01592 else 01593 return acfptr->write(chan, function, args, value); 01594 01595 return -1; 01596 }
const char* ast_get_context_name | ( | struct ast_context * | con | ) |
Definition at line 6276 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 6314 of file pbx.c.
References ast_context::registrar.
Referenced by handle_save_dialplan(), and show_dialplan_helper().
06315 { 06316 return c ? c->registrar : NULL; 06317 }
const char* ast_get_extension_app | ( | struct ast_exten * | e | ) |
Definition at line 6344 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().
06345 { 06346 return e ? e->app : NULL; 06347 }
void* ast_get_extension_app_data | ( | struct ast_exten * | e | ) |
Definition at line 6349 of file pbx.c.
References ast_exten::data.
Referenced by _macro_exec(), ast_get_hint(), handle_save_dialplan(), and print_ext().
06350 { 06351 return e ? e->data : NULL; 06352 }
const char* ast_get_extension_cidmatch | ( | struct ast_exten * | e | ) |
Definition at line 6339 of file pbx.c.
References ast_exten::cidmatch.
Referenced by complete_context_remove_extension(), complete_context_remove_extension_deprecated(), find_matching_priority(), and handle_save_dialplan().
06340 { 06341 return e ? e->cidmatch : NULL; 06342 }
struct ast_context* ast_get_extension_context | ( | struct ast_exten * | exten | ) |
const char* ast_get_extension_label | ( | struct ast_exten * | exten | ) |
Definition at line 6291 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 6334 of file pbx.c.
References ast_exten::matchcid.
Referenced by complete_context_remove_extension(), complete_context_remove_extension_deprecated(), find_matching_priority(), and handle_save_dialplan().
06335 { 06336 return e ? e->matchcid : 0; 06337 }
const char* ast_get_extension_name | ( | struct ast_exten * | exten | ) |
Definition at line 6286 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 6306 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 6319 of file pbx.c.
References ast_exten::registrar.
Referenced by handle_save_dialplan(), and show_dialplan_helper().
06320 { 06321 return e ? e->registrar : NULL; 06322 }
int ast_get_hint | ( | char * | hint, | |
int | maxlen, | |||
char * | name, | |||
int | maxnamelen, | |||
struct ast_channel * | c, | |||
const char * | context, | |||
const char * | exten | |||
) |
If an extension exists, return non-zero.
hint | buffer for hint | |
maxlen | size of hint buffer | |
name | buffer for name portion of hint | |
maxnamelen | size of name buffer | |
c | this is not important | |
context | which context to look in | |
exten | which extension to search for |
Definition at line 2298 of file pbx.c.
References ast_get_extension_app(), ast_get_extension_app_data(), and ast_hint_extension().
Referenced by action_extensionstate(), get_cid_name(), get_destination(), pbx_retrieve_variable(), and transmit_state_notify().
02299 { 02300 struct ast_exten *e = ast_hint_extension(c, context, exten); 02301 02302 if (e) { 02303 if (hint) 02304 ast_copy_string(hint, ast_get_extension_app(e), hintsize); 02305 if (name) { 02306 const char *tmp = ast_get_extension_app_data(e); 02307 if (tmp) 02308 ast_copy_string(name, tmp, namesize); 02309 } 02310 return -1; 02311 } 02312 return 0; 02313 }
const char* ast_get_ignorepat_name | ( | struct ast_ignorepat * | ip | ) |
Definition at line 6301 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().
06302 { 06303 return ip ? ip->pattern : NULL; 06304 }
const char* ast_get_ignorepat_registrar | ( | struct ast_ignorepat * | ip | ) |
Definition at line 6329 of file pbx.c.
References ast_ignorepat::registrar.
Referenced by handle_save_dialplan(), and show_dialplan_helper().
06330 { 06331 return ip ? ip->registrar : NULL; 06332 }
const char* ast_get_include_name | ( | struct ast_include * | inc | ) |
Definition at line 6296 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().
06297 { 06298 return inc ? inc->name : NULL; 06299 }
const char* ast_get_include_registrar | ( | struct ast_include * | i | ) |
Definition at line 6324 of file pbx.c.
References ast_include::registrar.
Referenced by handle_save_dialplan(), and show_dialplan_helper().
06325 { 06326 return i ? i->registrar : NULL; 06327 }
const char* ast_get_switch_data | ( | struct ast_sw * | sw | ) |
Definition at line 6359 of file pbx.c.
References ast_sw::data.
Referenced by handle_save_dialplan(), and show_dialplan_helper().
06360 { 06361 return sw ? sw->data : NULL; 06362 }
const char* ast_get_switch_name | ( | struct ast_sw * | sw | ) |
Definition at line 6354 of file pbx.c.
References ast_sw::name.
Referenced by handle_save_dialplan(), and show_dialplan_helper().
06355 { 06356 return sw ? sw->name : NULL; 06357 }
const char* ast_get_switch_registrar | ( | struct ast_sw * | sw | ) |
Definition at line 6364 of file pbx.c.
References ast_sw::registrar.
Referenced by handle_save_dialplan(), and show_dialplan_helper().
06365 { 06366 return sw ? sw->registrar : NULL; 06367 }
int ast_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 6457 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().
06458 { 06459 return __ast_goto_if_exists(chan, context, exten, priority, 0); 06460 }
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 1929 of file pbx.c.
References ast_rdlock_contexts(), ast_unlock_contexts(), E_MATCH, pbx_find_extension(), PRIORITY_HINT, and pbx_find_info::stacklen.
Referenced by ast_extension_state(), and ast_get_hint().
01930 { 01931 struct ast_exten *e; 01932 struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */ 01933 01934 ast_rdlock_contexts(); 01935 e = pbx_find_extension(c, NULL, &q, context, exten, PRIORITY_HINT, NULL, "", E_MATCH); 01936 ast_unlock_contexts(); 01937 01938 return e; 01939 }
void ast_hint_state_changed | ( | const char * | device | ) |
Definition at line 2050 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().
02051 { 02052 struct ast_hint *hint; 02053 02054 AST_LIST_LOCK(&hints); 02055 02056 AST_LIST_TRAVERSE(&hints, hint, list) { 02057 struct ast_state_cb *cblist; 02058 char buf[AST_MAX_EXTENSION]; 02059 char *parse = buf; 02060 char *cur; 02061 int state; 02062 02063 ast_copy_string(buf, ast_get_extension_app(hint->exten), sizeof(buf)); 02064 while ( (cur = strsep(&parse, "&")) ) { 02065 if (!strcasecmp(cur, device)) 02066 break; 02067 } 02068 if (!cur) 02069 continue; 02070 02071 /* Get device state for this hint */ 02072 state = ast_extension_state2(hint->exten); 02073 02074 if ((state == -1) || (state == hint->laststate)) 02075 continue; 02076 02077 /* Device state changed since last check - notify the watchers */ 02078 02079 /* For general callbacks */ 02080 for (cblist = statecbs; cblist; cblist = cblist->next) 02081 cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data); 02082 02083 /* For extension callbacks */ 02084 for (cblist = hint->callbacks; cblist; cblist = cblist->next) 02085 cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data); 02086 02087 hint->laststate = state; /* record we saw the change */ 02088 } 02089 02090 AST_LIST_UNLOCK(&hints); 02091 }
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 4551 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().
04552 { 04553 struct ast_context *con = ast_context_find(context); 04554 if (con) { 04555 struct ast_ignorepat *pat; 04556 for (pat = con->ignorepats; pat; pat = pat->next) { 04557 if (ast_extension_match(pat->pattern, pattern)) 04558 return 1; 04559 } 04560 } 04561 04562 return 0; 04563 }
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 6263 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().
06264 { 06265 return ast_mutex_lock(&con->lock); 06266 }
int ast_lock_contexts | ( | void | ) |
Locks the context list.
0 | on success | |
-1 | on error |
Definition at line 6240 of file pbx.c.
References ast_rwlock_wrlock().
Referenced by find_matching_endwhile().
06241 { 06242 return ast_rwlock_wrlock(&conlock); 06243 }
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 2335 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().
02336 { 02337 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE); 02338 }
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 3952 of file pbx.c.
References __ast_context_destroy(), ast_calloc, AST_EXTENSION_REMOVED, AST_LIST_HEAD_INIT_VALUE, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_unlock_contexts(), ast_wrlock_contexts(), ast_state_cb::callback, ast_hint::callbacks, store_hint::callbacks, store_hint::context, contexts, ast_state_cb::data, E_MATCH, store_hint::exten, ast_hint::exten, ast_exten::exten, free, store_hint::laststate, ast_hint::laststate, LOG_WARNING, ast_context::next, ast_state_cb::next, ast_exten::parent, pbx_find_extension(), PRIORITY_HINT, ast_context::registrar, and pbx_find_info::stacklen.
Referenced by pbx_load_module().
03953 { 03954 struct ast_context *tmp, *lasttmp = NULL; 03955 struct store_hints store = AST_LIST_HEAD_INIT_VALUE; 03956 struct store_hint *this; 03957 struct ast_hint *hint; 03958 struct ast_exten *exten; 03959 int length; 03960 struct ast_state_cb *thiscb, *prevcb; 03961 03962 /* it is very important that this function hold the hint list lock _and_ the conlock 03963 during its operation; not only do we need to ensure that the list of contexts 03964 and extensions does not change, but also that no hint callbacks (watchers) are 03965 added or removed during the merge/delete process 03966 03967 in addition, the locks _must_ be taken in this order, because there are already 03968 other code paths that use this order 03969 */ 03970 ast_wrlock_contexts(); 03971 AST_LIST_LOCK(&hints); 03972 03973 /* preserve all watchers for hints associated with this registrar */ 03974 AST_LIST_TRAVERSE(&hints, hint, list) { 03975 if (hint->callbacks && !strcmp(registrar, hint->exten->parent->registrar)) { 03976 length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2 + sizeof(*this); 03977 if (!(this = ast_calloc(1, length))) 03978 continue; 03979 this->callbacks = hint->callbacks; 03980 hint->callbacks = NULL; 03981 this->laststate = hint->laststate; 03982 this->context = this->data; 03983 strcpy(this->data, hint->exten->parent->name); 03984 this->exten = this->data + strlen(this->context) + 1; 03985 strcpy(this->exten, hint->exten->exten); 03986 AST_LIST_INSERT_HEAD(&store, this, list); 03987 } 03988 } 03989 03990 tmp = *extcontexts; 03991 if (registrar) { 03992 /* XXX remove previous contexts from same registrar */ 03993 if (option_debug) 03994 ast_log(LOG_DEBUG, "must remove any reg %s\n", registrar); 03995 __ast_context_destroy(NULL,registrar); 03996 while (tmp) { 03997 lasttmp = tmp; 03998 tmp = tmp->next; 03999 } 04000 } else { 04001 /* XXX remove contexts with the same name */ 04002 while (tmp) { 04003 ast_log(LOG_WARNING, "must remove %s reg %s\n", tmp->name, tmp->registrar); 04004 __ast_context_destroy(tmp,tmp->registrar); 04005 lasttmp = tmp; 04006 tmp = tmp->next; 04007 } 04008 } 04009 if (lasttmp) { 04010 lasttmp->next = contexts; 04011 contexts = *extcontexts; 04012 *extcontexts = NULL; 04013 } else 04014 ast_log(LOG_WARNING, "Requested contexts didn't get merged\n"); 04015 04016 /* restore the watchers for hints that can be found; notify those that 04017 cannot be restored 04018 */ 04019 while ((this = AST_LIST_REMOVE_HEAD(&store, list))) { 04020 struct pbx_find_info q = { .stacklen = 0 }; 04021 exten = pbx_find_extension(NULL, NULL, &q, this->context, this->exten, PRIORITY_HINT, NULL, "", E_MATCH); 04022 /* Find the hint in the list of hints */ 04023 AST_LIST_TRAVERSE(&hints, hint, list) { 04024 if (hint->exten == exten) 04025 break; 04026 } 04027 if (!exten || !hint) { 04028 /* this hint has been removed, notify the watchers */ 04029 prevcb = NULL; 04030 thiscb = this->callbacks; 04031 while (thiscb) { 04032 prevcb = thiscb; 04033 thiscb = thiscb->next; 04034 prevcb->callback(this->context, this->exten, AST_EXTENSION_REMOVED, prevcb->data); 04035 free(prevcb); 04036 } 04037 } else { 04038 thiscb = this->callbacks; 04039 while (thiscb->next) 04040 thiscb = thiscb->next; 04041 thiscb->next = hint->callbacks; 04042 hint->callbacks = this->callbacks; 04043 hint->laststate = this->laststate; 04044 } 04045 free(this); 04046 } 04047 04048 AST_LIST_UNLOCK(&hints); 04049 ast_unlock_contexts(); 04050 04051 return; 04052 }
AST_MUTEX_DEFINE_STATIC | ( | maxcalllock | ) |
AST_MUTEX_DEFINE_STATIC | ( | globalslock | ) |
int ast_parseable_goto | ( | struct ast_channel * | chan, | |
const char * | goto_string | |||
) |
This function will handle locking the channel as needed.
Definition at line 6467 of file pbx.c.
References 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().
06468 { 06469 char *exten, *pri, *context; 06470 char *stringp; 06471 int ipri; 06472 int mode = 0; 06473 06474 if (ast_strlen_zero(goto_string)) { 06475 ast_log(LOG_WARNING, "Goto requires an argument (optional context|optional extension|priority)\n"); 06476 return -1; 06477 } 06478 stringp = ast_strdupa(goto_string); 06479 context = strsep(&stringp, "|"); /* guaranteed non-null */ 06480 exten = strsep(&stringp, "|"); 06481 pri = strsep(&stringp, "|"); 06482 if (!exten) { /* Only a priority in this one */ 06483 pri = context; 06484 exten = NULL; 06485 context = NULL; 06486 } else if (!pri) { /* Only an extension and priority in this one */ 06487 pri = exten; 06488 exten = context; 06489 context = NULL; 06490 } 06491 if (*pri == '+') { 06492 mode = 1; 06493 pri++; 06494 } else if (*pri == '-') { 06495 mode = -1; 06496 pri++; 06497 } 06498 if (sscanf(pri, "%d", &ipri) != 1) { 06499 if ((ipri = ast_findlabel_extension(chan, context ? context : chan->context, exten ? exten : chan->exten, 06500 pri, chan->cid.cid_num)) < 1) { 06501 ast_log(LOG_WARNING, "Priority '%s' must be a number > 0, or valid label\n", pri); 06502 return -1; 06503 } else 06504 mode = 0; 06505 } 06506 /* At this point we have a priority and maybe an extension and a context */ 06507 06508 if (mode) 06509 ipri = chan->priority + (ipri * mode); 06510 06511 ast_explicit_goto(chan, context, exten, ipri); 06512 return 0; 06513 06514 }
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 5178 of file pbx.c.
References __ast_request_and_dial(), ast_calloc, ast_cdr_disposition(), ast_cdr_failed(), ast_cdr_setaccount(), 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(), async_stat::chan, errno, free, LOG_WARNING, option_verbose, outgoing_helper::vars, and VERBOSE_PREFIX_4.
Referenced by action_originate(), attempt_thread(), fast_originate(), and orig_app().
05179 { 05180 struct ast_channel *chan; 05181 struct app_tmp *tmp; 05182 int res = -1, cdr_res = -1; 05183 struct outgoing_helper oh; 05184 pthread_attr_t attr; 05185 05186 memset(&oh, 0, sizeof(oh)); 05187 oh.vars = vars; 05188 oh.account = account; 05189 05190 if (locked_channel) 05191 *locked_channel = NULL; 05192 if (ast_strlen_zero(app)) { 05193 res = -1; 05194 goto outgoing_app_cleanup; 05195 } 05196 if (sync) { 05197 chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh); 05198 if (chan) { 05199 ast_set_variables(chan, vars); 05200 if (account) 05201 ast_cdr_setaccount(chan, account); 05202 if (chan->_state == AST_STATE_UP) { 05203 res = 0; 05204 if (option_verbose > 3) 05205 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", chan->name); 05206 tmp = ast_calloc(1, sizeof(*tmp)); 05207 if (!tmp) 05208 res = -1; 05209 else { 05210 ast_copy_string(tmp->app, app, sizeof(tmp->app)); 05211 if (appdata) 05212 ast_copy_string(tmp->data, appdata, sizeof(tmp->data)); 05213 tmp->chan = chan; 05214 if (sync > 1) { 05215 if (locked_channel) 05216 ast_channel_unlock(chan); 05217 ast_pbx_run_app(tmp); 05218 } else { 05219 pthread_attr_init(&attr); 05220 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 05221 if (locked_channel) 05222 ast_channel_lock(chan); 05223 if (ast_pthread_create(&tmp->t, &attr, ast_pbx_run_app, tmp)) { 05224 ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno)); 05225 free(tmp); 05226 if (locked_channel) 05227 ast_channel_unlock(chan); 05228 ast_hangup(chan); 05229 res = -1; 05230 } else { 05231 if (locked_channel) 05232 *locked_channel = chan; 05233 } 05234 pthread_attr_destroy(&attr); 05235 } 05236 } 05237 } else { 05238 if (option_verbose > 3) 05239 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", chan->name); 05240 if (chan->cdr) { /* update the cdr */ 05241 /* here we update the status of the call, which sould be busy. 05242 * if that fails then we set the status to failed */ 05243 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 05244 ast_cdr_failed(chan->cdr); 05245 } 05246 ast_hangup(chan); 05247 } 05248 } 05249 05250 if (res < 0) { /* the call failed for some reason */ 05251 if (*reason == 0) { /* if the call failed (not busy or no answer) 05252 * update the cdr with the failed message */ 05253 cdr_res = ast_pbx_outgoing_cdr_failed(); 05254 if (cdr_res != 0) { 05255 res = cdr_res; 05256 goto outgoing_app_cleanup; 05257 } 05258 } 05259 } 05260 05261 } else { 05262 struct async_stat *as; 05263 if (!(as = ast_calloc(1, sizeof(*as)))) { 05264 res = -1; 05265 goto outgoing_app_cleanup; 05266 } 05267 chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh); 05268 if (!chan) { 05269 free(as); 05270 res = -1; 05271 goto outgoing_app_cleanup; 05272 } 05273 as->chan = chan; 05274 ast_copy_string(as->app, app, sizeof(as->app)); 05275 if (appdata) 05276 ast_copy_string(as->appdata, appdata, sizeof(as->appdata)); 05277 as->timeout = timeout; 05278 ast_set_variables(chan, vars); 05279 if (account) 05280 ast_cdr_setaccount(chan, account); 05281 /* Start a new thread, and get something handling this channel. */ 05282 pthread_attr_init(&attr); 05283 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 05284 if (locked_channel) 05285 ast_channel_lock(chan); 05286 if (ast_pthread_create(&as->p, &attr, async_wait, as)) { 05287 ast_log(LOG_WARNING, "Failed to start async wait\n"); 05288 free(as); 05289 if (locked_channel) 05290 ast_channel_unlock(chan); 05291 ast_hangup(chan); 05292 res = -1; 05293 pthread_attr_destroy(&attr); 05294 goto outgoing_app_cleanup; 05295 } else { 05296 if (locked_channel) 05297 *locked_channel = chan; 05298 } 05299 pthread_attr_destroy(&attr); 05300 res = 0; 05301 } 05302 outgoing_app_cleanup: 05303 ast_variables_destroy(vars); 05304 return res; 05305 }
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 4986 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().
04987 { 04988 /* allocate a channel */ 04989 struct ast_channel *chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, 0); 04990 04991 if (!chan) 04992 return -1; /* failure */ 04993 04994 if (!chan->cdr) { 04995 /* allocation of the cdr failed */ 04996 ast_channel_free(chan); /* free the channel */ 04997 return -1; /* return failure */ 04998 } 04999 05000 /* allocation of the cdr was successful */ 05001 ast_cdr_init(chan->cdr, chan); /* initilize our channel's cdr */ 05002 ast_cdr_start(chan->cdr); /* record the start and stop time */ 05003 ast_cdr_end(chan->cdr); 05004 ast_cdr_failed(chan->cdr); /* set the status to failed */ 05005 ast_cdr_detach(chan->cdr); /* post and free the record */ 05006 chan->cdr = NULL; 05007 ast_channel_free(chan); /* free the channel */ 05008 05009 return 0; /* success */ 05010 }
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 5012 of file pbx.c.
References __ast_request_and_dial(), ast_channel::_state, ast_calloc, ast_cdr_disposition(), ast_cdr_failed(), ast_cdr_setaccount(), ast_channel_alloc(), ast_channel_lock, ast_channel_unlock, ast_exists_extension(), ast_hangup(), ast_log(), ast_pbx_outgoing_cdr_failed(), ast_pbx_run(), ast_pbx_start(), ast_pthread_create, ast_request_and_dial(), ast_set_variables(), AST_STATE_DOWN, AST_STATE_UP, ast_strlen_zero(), ast_variables_destroy(), ast_verbose(), async_wait(), ast_channel::cdr, ast_channel::context, free, ast_channel::hangupcause, LOAD_OH, LOG_ERROR, LOG_WARNING, option_verbose, pbx_builtin_setvar_helper(), set_ext_pri(), outgoing_helper::vars, and VERBOSE_PREFIX_4.
Referenced by action_originate(), attempt_thread(), fast_originate(), and orig_exten().
05013 { 05014 struct ast_channel *chan; 05015 struct async_stat *as; 05016 int res = -1, cdr_res = -1; 05017 struct outgoing_helper oh; 05018 pthread_attr_t attr; 05019 05020 if (sync) { 05021 LOAD_OH(oh); 05022 chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh); 05023 if (channel) { 05024 *channel = chan; 05025 if (chan) 05026 ast_channel_lock(chan); 05027 } 05028 if (chan) { 05029 if (chan->_state == AST_STATE_UP) { 05030 res = 0; 05031 if (option_verbose > 3) 05032 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", chan->name); 05033 05034 if (sync > 1) { 05035 if (channel) 05036 ast_channel_unlock(chan); 05037 if (ast_pbx_run(chan)) { 05038 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 05039 if (channel) 05040 *channel = NULL; 05041 ast_hangup(chan); 05042 chan = NULL; 05043 res = -1; 05044 } 05045 } else { 05046 if (ast_pbx_start(chan)) { 05047 ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name); 05048 if (channel) { 05049 *channel = NULL; 05050 ast_channel_unlock(chan); 05051 } 05052 ast_hangup(chan); 05053 res = -1; 05054 } 05055 chan = NULL; 05056 } 05057 } else { 05058 if (option_verbose > 3) 05059 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", chan->name); 05060 05061 if (chan->cdr) { /* update the cdr */ 05062 /* here we update the status of the call, which sould be busy. 05063 * if that fails then we set the status to failed */ 05064 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 05065 ast_cdr_failed(chan->cdr); 05066 } 05067 05068 if (channel) { 05069 *channel = NULL; 05070 ast_channel_unlock(chan); 05071 } 05072 ast_hangup(chan); 05073 chan = NULL; 05074 } 05075 } 05076 05077 if (res < 0) { /* the call failed for some reason */ 05078 if (*reason == 0) { /* if the call failed (not busy or no answer) 05079 * update the cdr with the failed message */ 05080 cdr_res = ast_pbx_outgoing_cdr_failed(); 05081 if (cdr_res != 0) { 05082 res = cdr_res; 05083 goto outgoing_exten_cleanup; 05084 } 05085 } 05086 05087 /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */ 05088 /* check if "failed" exists */ 05089 if (ast_exists_extension(chan, context, "failed", 1, NULL)) { 05090 chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "OutgoingSpoolFailed"); 05091 if (chan) { 05092 char failed_reason[4] = ""; 05093 if (!ast_strlen_zero(context)) 05094 ast_copy_string(chan->context, context, sizeof(chan->context)); 05095 set_ext_pri(chan, "failed", 1); 05096 ast_set_variables(chan, vars); 05097 snprintf(failed_reason, sizeof(failed_reason), "%d", *reason); 05098 pbx_builtin_setvar_helper(chan, "REASON", failed_reason); 05099 if (account) 05100 ast_cdr_setaccount(chan, account); 05101 if (ast_pbx_run(chan)) { 05102 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 05103 ast_hangup(chan); 05104 } 05105 chan = NULL; 05106 } 05107 } 05108 } 05109 } else { 05110 if (!(as = ast_calloc(1, sizeof(*as)))) { 05111 res = -1; 05112 goto outgoing_exten_cleanup; 05113 } 05114 chan = ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name); 05115 if (channel) { 05116 *channel = chan; 05117 if (chan) 05118 ast_channel_lock(chan); 05119 } 05120 if (!chan) { 05121 free(as); 05122 res = -1; 05123 goto outgoing_exten_cleanup; 05124 } 05125 as->chan = chan; 05126 ast_copy_string(as->context, context, sizeof(as->context)); 05127 set_ext_pri(as->chan, exten, priority); 05128 as->timeout = timeout; 05129 ast_set_variables(chan, vars); 05130 if (account) 05131 ast_cdr_setaccount(chan, account); 05132 pthread_attr_init(&attr); 05133 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 05134 if (ast_pthread_create(&as->p, &attr, async_wait, as)) { 05135 ast_log(LOG_WARNING, "Failed to start async wait\n"); 05136 free(as); 05137 if (channel) { 05138 *channel = NULL; 05139 ast_channel_unlock(chan); 05140 } 05141 ast_hangup(chan); 05142 res = -1; 05143 pthread_attr_destroy(&attr); 05144 goto outgoing_exten_cleanup; 05145 } 05146 pthread_attr_destroy(&attr); 05147 res = 0; 05148 } 05149 outgoing_exten_cleanup: 05150 ast_variables_destroy(vars); 05151 return res; 05152 }
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 2680 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().
02681 { 02682 enum ast_pbx_result res = AST_PBX_SUCCESS; 02683 02684 if (increase_call_count(c)) 02685 return AST_PBX_CALL_LIMIT; 02686 02687 res = __ast_pbx_run(c); 02688 decrease_call_count(); 02689 02690 return res; 02691 }
static void* ast_pbx_run_app | ( | void * | data | ) | [static] |
run the application and free the descriptor once done
Definition at line 5162 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().
05163 { 05164 struct app_tmp *tmp = data; 05165 struct ast_app *app; 05166 app = pbx_findapp(tmp->app); 05167 if (app) { 05168 if (option_verbose > 3) 05169 ast_verbose(VERBOSE_PREFIX_4 "Launching %s(%s) on %s\n", tmp->app, tmp->data, tmp->chan->name); 05170 pbx_exec(tmp->chan, app, tmp->data); 05171 } else 05172 ast_log(LOG_WARNING, "No such application '%s'\n", tmp->app); 05173 ast_hangup(tmp->chan); 05174 free(tmp); 05175 return NULL; 05176 }
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 2654 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(), dahdi_new(), 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(), and skinny_new().
02655 { 02656 pthread_t t; 02657 pthread_attr_t attr; 02658 02659 if (!c) { 02660 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n"); 02661 return AST_PBX_FAILED; 02662 } 02663 02664 if (increase_call_count(c)) 02665 return AST_PBX_CALL_LIMIT; 02666 02667 /* Start a new thread, and get something handling this channel. */ 02668 pthread_attr_init(&attr); 02669 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 02670 if (ast_pthread_create(&t, &attr, pbx_thread, c)) { 02671 ast_log(LOG_WARNING, "Failed to create new channel thread\n"); 02672 pthread_attr_destroy(&attr); 02673 return AST_PBX_FAILED; 02674 } 02675 pthread_attr_destroy(&attr); 02676 02677 return AST_PBX_SUCCESS; 02678 }
int ast_rdlock_contexts | ( | void | ) |
Definition at line 6245 of file pbx.c.
References ast_rwlock_rdlock().
Referenced by __ast_context_create(), _macro_exec(), ast_context_find(), ast_context_lockmacro(), ast_context_unlockmacro(), ast_hint_extension(), complete_context_add_extension(), complete_context_add_extension_deprecated(), complete_context_add_ignorepat(), complete_context_add_ignorepat_deprecated(), complete_context_add_include(), complete_context_add_include_deprecated(), complete_context_dont_include_deprecated(), complete_context_remove_extension(), complete_context_remove_extension_deprecated(), complete_context_remove_ignorepat(), complete_context_remove_ignorepat_deprecated(), complete_context_remove_include(), complete_show_dialplan_context(), dundi_precache_full(), find_context_locked(), handle_save_dialplan(), pbx_extension_helper(), and show_dialplan_helper().
06246 { 06247 return ast_rwlock_rdlock(&conlock); 06248 }
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 2982 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().
02983 { 02984 struct ast_app *tmp, *cur = NULL; 02985 char tmps[80]; 02986 int length; 02987 02988 AST_LIST_LOCK(&apps); 02989 AST_LIST_TRAVERSE(&apps, tmp, list) { 02990 if (!strcasecmp(app, tmp->name)) { 02991 ast_log(LOG_WARNING, "Already have an application '%s'\n", app); 02992 AST_LIST_UNLOCK(&apps); 02993 return -1; 02994 } 02995 } 02996 02997 length = sizeof(*tmp) + strlen(app) + 1; 02998 02999 if (!(tmp = ast_calloc(1, length))) { 03000 AST_LIST_UNLOCK(&apps); 03001 return -1; 03002 } 03003 03004 strcpy(tmp->name, app); 03005 tmp->execute = execute; 03006 tmp->synopsis = synopsis; 03007 tmp->description = description; 03008 03009 /* Store in alphabetical order */ 03010 AST_LIST_TRAVERSE_SAFE_BEGIN(&apps, cur, list) { 03011 if (strcasecmp(tmp->name, cur->name) < 0) { 03012 AST_LIST_INSERT_BEFORE_CURRENT(&apps, tmp, list); 03013 break; 03014 } 03015 } 03016 AST_LIST_TRAVERSE_SAFE_END 03017 if (!cur) 03018 AST_LIST_INSERT_TAIL(&apps, tmp, list); 03019 03020 if (option_verbose > 1) 03021 ast_verbose( VERBOSE_PREFIX_2 "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps))); 03022 03023 AST_LIST_UNLOCK(&apps); 03024 03025 return 0; 03026 }
int ast_register_switch | ( | struct ast_switch * | sw | ) |
Register an alternative dialplan switch.
sw | switch to register |
Definition at line 3032 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().
03033 { 03034 struct ast_switch *tmp; 03035 03036 AST_LIST_LOCK(&switches); 03037 AST_LIST_TRAVERSE(&switches, tmp, list) { 03038 if (!strcasecmp(tmp->name, sw->name)) { 03039 AST_LIST_UNLOCK(&switches); 03040 ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name); 03041 return -1; 03042 } 03043 } 03044 AST_LIST_INSERT_TAIL(&switches, sw, list); 03045 AST_LIST_UNLOCK(&switches); 03046 03047 return 0; 03048 }
static int ast_remove_hint | ( | struct ast_exten * | e | ) | [static] |
ast_remove_hint: Remove hint from extension
Definition at line 2261 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().
02262 { 02263 /* Cleanup the Notifys if hint is removed */ 02264 struct ast_hint *hint; 02265 struct ast_state_cb *cblist, *cbprev; 02266 int res = -1; 02267 02268 if (!e) 02269 return -1; 02270 02271 AST_LIST_LOCK(&hints); 02272 AST_LIST_TRAVERSE_SAFE_BEGIN(&hints, hint, list) { 02273 if (hint->exten == e) { 02274 cbprev = NULL; 02275 cblist = hint->callbacks; 02276 while (cblist) { 02277 /* Notify with -1 and remove all callbacks */ 02278 cbprev = cblist; 02279 cblist = cblist->next; 02280 cbprev->callback(hint->exten->parent->name, hint->exten->exten, AST_EXTENSION_DEACTIVATED, cbprev->data); 02281 free(cbprev); 02282 } 02283 hint->callbacks = NULL; 02284 AST_LIST_REMOVE_CURRENT(&hints, list); 02285 free(hint); 02286 res = 0; 02287 break; 02288 } 02289 } 02290 AST_LIST_TRAVERSE_SAFE_END 02291 AST_LIST_UNLOCK(&hints); 02292 02293 return res; 02294 }
AST_RWLOCK_DEFINE_STATIC | ( | conlock | ) |
Lock for the ast_context list
int ast_spawn_extension | ( | struct ast_channel * | c, | |
const char * | context, | |||
const char * | exten, | |||
int | priority, | |||
const char * | callerid | |||
) |
Launch a new extension (i.e. new stack).
c | not important | |
context | which context to generate the extension within | |
exten | new extension to add | |
priority | priority of new extension | |
callerid | callerid of extension |
0 | on success | |
-1 | on failure. |
Definition at line 2340 of file pbx.c.
References E_SPAWN, and pbx_extension_helper().
Referenced by __ast_pbx_run(), _macro_exec(), and loopback_exec().
02341 { 02342 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN); 02343 }
AST_THREADSTORAGE | ( | switch_data | , | |
switch_data_init | ||||
) |
int ast_unlock_context | ( | struct ast_context * | con | ) |
Unlocks | the given context |
con | context to unlock |
0 | on success | |
-1 | on failure |
Definition at line 6268 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().
06269 { 06270 return ast_mutex_unlock(&con->lock); 06271 }
int ast_unlock_contexts | ( | void | ) |
Unlocks contexts.
0 | on success | |
-1 | on failure |
Definition at line 6255 of file pbx.c.
References ast_rwlock_unlock().
Referenced by __ast_context_create(), _macro_exec(), ast_add_extension(), ast_context_add_ignorepat(), ast_context_add_include(), ast_context_add_switch(), ast_context_destroy(), ast_context_find(), ast_context_lockmacro(), ast_context_remove_extension_callerid(), ast_context_remove_ignorepat(), ast_context_remove_include(), ast_context_remove_switch(), ast_context_unlockmacro(), ast_hint_extension(), ast_merge_contexts_and_delete(), complete_context_add_extension(), complete_context_add_extension_deprecated(), complete_context_add_ignorepat(), complete_context_add_ignorepat_deprecated(), complete_context_add_include(), complete_context_add_include_deprecated(), complete_context_dont_include_deprecated(), complete_context_remove_extension(), complete_context_remove_extension_deprecated(), complete_context_remove_ignorepat(), complete_context_remove_ignorepat_deprecated(), complete_context_remove_include(), complete_show_dialplan_context(), dundi_precache_full(), find_context_locked(), find_matching_endwhile(), handle_save_dialplan(), pbx_extension_helper(), and show_dialplan_helper().
06256 { 06257 return ast_rwlock_unlock(&conlock); 06258 }
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 3863 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().
03864 { 03865 struct ast_app *tmp; 03866 03867 AST_LIST_LOCK(&apps); 03868 AST_LIST_TRAVERSE_SAFE_BEGIN(&apps, tmp, list) { 03869 if (!strcasecmp(app, tmp->name)) { 03870 AST_LIST_REMOVE_CURRENT(&apps, list); 03871 if (option_verbose > 1) 03872 ast_verbose( VERBOSE_PREFIX_2 "Unregistered application '%s'\n", tmp->name); 03873 free(tmp); 03874 break; 03875 } 03876 } 03877 AST_LIST_TRAVERSE_SAFE_END 03878 AST_LIST_UNLOCK(&apps); 03879 03880 return tmp ? 0 : -1; 03881 }
void ast_unregister_switch | ( | struct ast_switch * | sw | ) |
Unregister an alternative switch.
sw | switch to unregister |
Definition at line 3050 of file pbx.c.
References AST_LIST_LOCK, AST_LIST_REMOVE, and AST_LIST_UNLOCK.
Referenced by __unload_module(), and unload_module().
03051 { 03052 AST_LIST_LOCK(&switches); 03053 AST_LIST_REMOVE(&switches, sw, list); 03054 AST_LIST_UNLOCK(&switches); 03055 }
struct ast_exten* ast_walk_context_extensions | ( | struct ast_context * | con, | |
struct ast_exten * | exten | |||
) |
Definition at line 6377 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().
06379 { 06380 if (!exten) 06381 return con ? con->root : NULL; 06382 else 06383 return exten->next; 06384 }
struct ast_ignorepat* ast_walk_context_ignorepats | ( | struct ast_context * | con, | |
struct ast_ignorepat * | ip | |||
) |
Definition at line 6410 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().
06412 { 06413 if (!ip) 06414 return con ? con->ignorepats : NULL; 06415 else 06416 return ip->next; 06417 }
struct ast_include* ast_walk_context_includes | ( | struct ast_context * | con, | |
struct ast_include * | inc | |||
) |
Definition at line 6401 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().
06403 { 06404 if (!inc) 06405 return con ? con->includes : NULL; 06406 else 06407 return inc->next; 06408 }
struct ast_sw* ast_walk_context_switches | ( | struct ast_context * | con, | |
struct ast_sw * | sw | |||
) |
Definition at line 6386 of file pbx.c.
References AST_LIST_FIRST, and AST_LIST_NEXT.
Referenced by handle_save_dialplan(), and show_dialplan_helper().
06388 { 06389 if (!sw) 06390 return con ? AST_LIST_FIRST(&con->alts) : NULL; 06391 else 06392 return AST_LIST_NEXT(sw, list); 06393 }
struct ast_context* ast_walk_contexts | ( | struct ast_context * | con | ) |
Definition at line 6372 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 6395 of file pbx.c.
References exten, and ast_exten::priority.
Referenced by complete_context_remove_extension(), complete_context_remove_extension_deprecated(), find_matching_priority(), handle_save_dialplan(), pbx_find_extension(), and show_dialplan_helper().
int ast_wrlock_contexts | ( | void | ) |
Definition at line 6250 of file pbx.c.
References ast_rwlock_wrlock().
Referenced by ast_context_destroy(), ast_merge_contexts_and_delete(), and complete_context_dont_include_deprecated().
06251 { 06252 return ast_rwlock_wrlock(&conlock); 06253 }
static void* async_wait | ( | void * | data | ) | [static] |
Definition at line 4923 of file pbx.c.
References ast_channel::_state, app, async_stat::app, async_stat::appdata, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_FRAME_CONTROL, ast_frfree, ast_hangup(), ast_log(), ast_pbx_run(), ast_read(), AST_STATE_UP, ast_strlen_zero(), ast_verbose(), ast_waitfor(), async_stat::chan, ast_channel::context, async_stat::context, ast_channel::exten, async_stat::exten, f, free, LOG_ERROR, LOG_WARNING, option_verbose, pbx_exec(), pbx_findapp(), ast_channel::priority, async_stat::priority, async_stat::timeout, and VERBOSE_PREFIX_3.
Referenced by ast_pbx_outgoing_app(), and ast_pbx_outgoing_exten().
04924 { 04925 struct async_stat *as = data; 04926 struct ast_channel *chan = as->chan; 04927 int timeout = as->timeout; 04928 int res; 04929 struct ast_frame *f; 04930 struct ast_app *app; 04931 04932 while (timeout && (chan->_state != AST_STATE_UP)) { 04933 res = ast_waitfor(chan, timeout); 04934 if (res < 1) 04935 break; 04936 if (timeout > -1) 04937 timeout = res; 04938 f = ast_read(chan); 04939 if (!f) 04940 break; 04941 if (f->frametype == AST_FRAME_CONTROL) { 04942 if ((f->subclass == AST_CONTROL_BUSY) || 04943 (f->subclass == AST_CONTROL_CONGESTION) ) { 04944 ast_frfree(f); 04945 break; 04946 } 04947 } 04948 ast_frfree(f); 04949 } 04950 if (chan->_state == AST_STATE_UP) { 04951 if (!ast_strlen_zero(as->app)) { 04952 app = pbx_findapp(as->app); 04953 if (app) { 04954 if (option_verbose > 2) 04955 ast_verbose(VERBOSE_PREFIX_3 "Launching %s(%s) on %s\n", as->app, as->appdata, chan->name); 04956 pbx_exec(chan, app, as->appdata); 04957 } else 04958 ast_log(LOG_WARNING, "No such application '%s'\n", as->app); 04959 } else { 04960 if (!ast_strlen_zero(as->context)) 04961 ast_copy_string(chan->context, as->context, sizeof(chan->context)); 04962 if (!ast_strlen_zero(as->exten)) 04963 ast_copy_string(chan->exten, as->exten, sizeof(chan->exten)); 04964 if (as->priority > 0) 04965 chan->priority = as->priority; 04966 /* Run the PBX */ 04967 if (ast_pbx_run(chan)) { 04968 ast_log(LOG_ERROR, "Failed to start PBX on %s\n", chan->name); 04969 } else { 04970 /* PBX will have taken care of this */ 04971 chan = NULL; 04972 } 04973 } 04974 } 04975 free(as); 04976 if (chan) 04977 ast_hangup(chan); 04978 return NULL; 04979 }
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 2358 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.
02359 { 02360 int digit; 02361 02362 buf[pos] = '\0'; /* make sure it is properly terminated */ 02363 while (ast_matchmore_extension(c, c->context, buf, 1, c->cid.cid_num)) { 02364 /* As long as we're willing to wait, and as long as it's not defined, 02365 keep reading digits until we can't possibly get a right answer anymore. */ 02366 digit = ast_waitfordigit(c, waittime * 1000); 02367 if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) { 02368 c->_softhangup = 0; 02369 } else { 02370 if (!digit) /* No entry */ 02371 break; 02372 if (digit < 0) /* Error, maybe a hangup */ 02373 return -1; 02374 if (pos < buflen - 1) { /* XXX maybe error otherwise ? */ 02375 buf[pos++] = digit; 02376 buf[pos] = '\0'; 02377 } 02378 waittime = c->pbx->dtimeout; 02379 } 02380 } 02381 return 0; 02382 }
static char* complete_show_application | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 3108 of file pbx.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, and strdup.
03109 { 03110 struct ast_app *a; 03111 char *ret = NULL; 03112 int which = 0; 03113 int wordlen = strlen(word); 03114 03115 /* return the n-th [partial] matching entry */ 03116 AST_LIST_LOCK(&apps); 03117 AST_LIST_TRAVERSE(&apps, a, list) { 03118 if (!strncasecmp(word, a->name, wordlen) && ++which > state) { 03119 ret = strdup(a->name); 03120 break; 03121 } 03122 } 03123 AST_LIST_UNLOCK(&apps); 03124 03125 return ret; 03126 }
static char* complete_show_applications | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 3469 of file pbx.c.
References ast_cli_complete().
03470 { 03471 static char* choices[] = { "like", "describing", NULL }; 03472 03473 return (pos != 3) ? NULL : ast_cli_complete(word, choices, state); 03474 }
static char* complete_show_applications_deprecated | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 3462 of file pbx.c.
References ast_cli_complete().
03463 { 03464 static char* choices[] = { "like", "describing", NULL }; 03465 03466 return (pos != 2) ? NULL : ast_cli_complete(word, choices, state); 03467 }
static char* complete_show_dialplan_context | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 3479 of file pbx.c.
References ast_get_context_name(), ast_rdlock_contexts(), ast_strdup, ast_unlock_contexts(), and ast_walk_contexts().
03481 { 03482 struct ast_context *c = NULL; 03483 char *ret = NULL; 03484 int which = 0; 03485 int wordlen; 03486 03487 /* we are do completion of [exten@]context on second position only */ 03488 if (pos != 2) 03489 return NULL; 03490 03491 ast_rdlock_contexts(); 03492 03493 wordlen = strlen(word); 03494 03495 /* walk through all contexts and return the n-th match */ 03496 while ( (c = ast_walk_contexts(c)) ) { 03497 if (!strncasecmp(word, ast_get_context_name(c), wordlen) && ++which > state) { 03498 ret = ast_strdup(ast_get_context_name(c)); 03499 break; 03500 } 03501 } 03502 03503 ast_unlock_contexts(); 03504 03505 return ret; 03506 }
static char* complete_show_function | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 1459 of file pbx.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_custom_function::name, and strdup.
01460 { 01461 struct ast_custom_function *acf; 01462 char *ret = NULL; 01463 int which = 0; 01464 int wordlen = strlen(word); 01465 01466 /* case-insensitive for convenience in this 'complete' function */ 01467 AST_LIST_LOCK(&acf_root); 01468 AST_LIST_TRAVERSE(&acf_root, acf, acflist) { 01469 if (!strncasecmp(word, acf->name, wordlen) && ++which > state) { 01470 ret = strdup(acf->name); 01471 break; 01472 } 01473 } 01474 AST_LIST_UNLOCK(&acf_root); 01475 01476 return ret; 01477 }
static void decrease_call_count | ( | void | ) | [static] |
Definition at line 2616 of file pbx.c.
References ast_mutex_lock(), ast_mutex_unlock(), and countcalls.
Referenced by ast_pbx_run(), and pbx_thread().
02617 { 02618 ast_mutex_lock(&maxcalllock); 02619 if (countcalls > 0) 02620 countcalls--; 02621 ast_mutex_unlock(&maxcalllock); 02622 }
static void destroy_exten | ( | struct ast_exten * | e | ) | [static] |
Definition at line 2624 of file pbx.c.
References ast_remove_hint(), free, ast_exten::priority, and PRIORITY_HINT.
Referenced by __ast_context_destroy(), and ast_context_remove_extension_callerid2().
02625 { 02626 if (e->priority == PRIORITY_HINT) 02627 ast_remove_hint(e); 02628 02629 if (e->datad) 02630 e->datad(e->data); 02631 free(e); 02632 }
static int ext_cmp | ( | const char * | a, | |
const char * | b | |||
) | [static] |
the full routine to compare extensions in rules.
Definition at line 744 of file pbx.c.
References ext_cmp1().
Referenced by ast_add_extension2().
00745 { 00746 /* make sure non-patterns come first. 00747 * If a is not a pattern, it either comes first or 00748 * we use strcmp to compare the strings. 00749 */ 00750 int ret = 0; 00751 00752 if (a[0] != '_') 00753 return (b[0] == '_') ? -1 : strcmp(a, b); 00754 00755 /* Now we know a is a pattern; if b is not, a comes first */ 00756 if (b[0] != '_') 00757 return 1; 00758 #if 0 /* old mode for ext matching */ 00759 return strcmp(a, b); 00760 #endif 00761 /* ok we need full pattern sorting routine */ 00762 while (!ret && a && b) 00763 ret = ext_cmp1(&a) - ext_cmp1(&b); 00764 if (ret == 0) 00765 return 0; 00766 else 00767 return (ret > 0) ? 1 : -1; 00768 }
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 672 of file pbx.c.
References ast_log(), and LOG_WARNING.
Referenced by ext_cmp().
00673 { 00674 uint32_t chars[8]; 00675 int c, cmin = 0xff, count = 0; 00676 const char *end; 00677 00678 /* load, sign extend and advance pointer until we find 00679 * a valid character. 00680 */ 00681 while ( (c = *(*p)++) && (c == ' ' || c == '-') ) 00682 ; /* ignore some characters */ 00683 00684 /* always return unless we have a set of chars */ 00685 switch (c) { 00686 default: /* ordinary character */ 00687 return 0x0000 | (c & 0xff); 00688 00689 case 'N': /* 2..9 */ 00690 return 0x0700 | '2' ; 00691 00692 case 'X': /* 0..9 */ 00693 return 0x0900 | '0'; 00694 00695 case 'Z': /* 1..9 */ 00696 return 0x0800 | '1'; 00697 00698 case '.': /* wildcard */ 00699 return 0x10000; 00700 00701 case '!': /* earlymatch */ 00702 return 0x20000; /* less specific than NULL */ 00703 00704 case '\0': /* empty string */ 00705 *p = NULL; 00706 return 0x30000; 00707 00708 case '[': /* pattern */ 00709 break; 00710 } 00711 /* locate end of set */ 00712 end = strchr(*p, ']'); 00713 00714 if (end == NULL) { 00715 ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n"); 00716 return 0x40000; /* XXX make this entry go last... */ 00717 } 00718 00719 bzero(chars, sizeof(chars)); /* clear all chars in the set */ 00720 for (; *p < end ; (*p)++) { 00721 unsigned char c1, c2; /* first-last char in range */ 00722 c1 = (unsigned char)((*p)[0]); 00723 if (*p + 2 < end && (*p)[1] == '-') { /* this is a range */ 00724 c2 = (unsigned char)((*p)[2]); 00725 *p += 2; /* skip a total of 3 chars */ 00726 } else /* individual character */ 00727 c2 = c1; 00728 if (c1 < cmin) 00729 cmin = c1; 00730 for (; c1 <= c2; c1++) { 00731 uint32_t mask = 1 << (c1 % 32); 00732 if ( (chars[ c1 / 32 ] & mask) == 0) 00733 count += 0x100; 00734 chars[ c1 / 32 ] |= mask; 00735 } 00736 } 00737 (*p)++; 00738 return count == 0 ? 0x30000 : (count | cmin); 00739 }
static int ext_strncpy | ( | char * | dst, | |
const char * | src, | |||
int | len | |||
) | [static] |
copy a string skipping whitespace
Definition at line 4675 of file pbx.c.
Referenced by ast_add_extension2().
04676 { 04677 int count=0; 04678 04679 while (*src && (count < len - 1)) { 04680 switch(*src) { 04681 case ' ': 04682 /* otherwise exten => [a-b],1,... doesn't work */ 04683 /* case '-': */ 04684 /* Ignore */ 04685 break; 04686 default: 04687 *dst = *src; 04688 dst++; 04689 } 04690 src++; 04691 count++; 04692 } 04693 *dst = '\0'; 04694 04695 return count; 04696 }
static int extension_match_core | ( | const char * | pattern, | |
const char * | data, | |||
enum ext_match_t | mode | |||
) | [static] |
Definition at line 893 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().
00894 { 00895 int i; 00896 static int prof_id = -2; /* marker for 'unallocated' id */ 00897 if (prof_id == -2) 00898 prof_id = ast_add_profile("ext_match", 0); 00899 ast_mark(prof_id, 1); 00900 i = _extension_match_core(pattern, data, mode); 00901 ast_mark(prof_id, 0); 00902 return i; 00903 }
static struct ast_context* find_context_locked | ( | const char * | context | ) | [static] |
Definition at line 2708 of file pbx.c.
References ast_get_context_name(), ast_rdlock_contexts(), ast_unlock_contexts(), and ast_walk_contexts().
Referenced by ast_add_extension(), ast_context_add_ignorepat(), ast_context_add_include(), ast_context_add_switch(), ast_context_remove_extension_callerid(), ast_context_remove_ignorepat(), ast_context_remove_include(), and ast_context_remove_switch().
02709 { 02710 struct ast_context *c = NULL; 02711 02712 ast_rdlock_contexts(); 02713 while ( (c = ast_walk_contexts(c)) ) { 02714 if (!strcmp(ast_get_context_name(c), context)) 02715 return c; 02716 } 02717 ast_unlock_contexts(); 02718 02719 return NULL; 02720 }
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 1552 of file pbx.c.
References ast_log(), and LOG_WARNING.
Referenced by ast_func_read(), and ast_func_write().
01553 { 01554 char *args = strchr(function, '('); 01555 01556 if (!args) 01557 ast_log(LOG_WARNING, "Function doesn't contain parentheses. Assuming null argument.\n"); 01558 else { 01559 char *p; 01560 *args++ = '\0'; 01561 if ((p = strrchr(args, ')')) ) 01562 *p = '\0'; 01563 else 01564 ast_log(LOG_WARNING, "Can't find trailing parenthesis?\n"); 01565 } 01566 return args; 01567 }
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 4093 of file pbx.c.
References ast_log(), ast_strlen_zero(), LOG_WARNING, lookup_name(), and s.
Referenced by ast_build_timing().
04094 { 04095 int s, e; /* start and ending position */ 04096 unsigned int mask = 0; 04097 04098 /* Check for whole range */ 04099 if (ast_strlen_zero(src) || !strcmp(src, "*")) { 04100 s = 0; 04101 e = max - 1; 04102 } else { 04103 /* Get start and ending position */ 04104 char *c = strchr(src, '-'); 04105 if (c) 04106 *c++ = '\0'; 04107 /* Find the start */ 04108 s = lookup_name(src, names, max); 04109 if (!s) { 04110 ast_log(LOG_WARNING, "Invalid %s '%s', assuming none\n", msg, src); 04111 return 0; 04112 } 04113 s--; 04114 if (c) { /* find end of range */ 04115 e = lookup_name(c, names, max); 04116 if (!e) { 04117 ast_log(LOG_WARNING, "Invalid end %s '%s', assuming none\n", msg, c); 04118 return 0; 04119 } 04120 e--; 04121 } else 04122 e = s; 04123 } 04124 /* Fill the mask. Remember that ranges are cyclic */ 04125 mask = 1 << e; /* initialize with last element */ 04126 while (s != e) { 04127 if (s >= max) { 04128 s = 0; 04129 mask |= (1 << s); 04130 } else { 04131 mask |= (1 << s); 04132 s++; 04133 } 04134 } 04135 return mask; 04136 }
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 4139 of file pbx.c.
References ast_log(), ast_strlen_zero(), LOG_WARNING, and ast_timing::minmask.
Referenced by ast_build_timing().
04140 { 04141 char *e; 04142 int x; 04143 int s1, s2; 04144 int e1, e2; 04145 /* int cth, ctm; */ 04146 04147 /* start disabling all times, fill the fields with 0's, as they may contain garbage */ 04148 memset(i->minmask, 0, sizeof(i->minmask)); 04149 04150 /* 2-minutes per bit, since the mask has only 32 bits :( */ 04151 /* Star is all times */ 04152 if (ast_strlen_zero(times) || !strcmp(times, "*")) { 04153 for (x=0; x<24; x++) 04154 i->minmask[x] = 0x3fffffff; /* 30 bits */ 04155 return; 04156 } 04157 /* Otherwise expect a range */ 04158 e = strchr(times, '-'); 04159 if (!e) { 04160 ast_log(LOG_WARNING, "Time range is not valid. Assuming no restrictions based on time.\n"); 04161 return; 04162 } 04163 *e++ = '\0'; 04164 /* XXX why skip non digits ? */ 04165 while (*e && !isdigit(*e)) 04166 e++; 04167 if (!*e) { 04168 ast_log(LOG_WARNING, "Invalid time range. Assuming no restrictions based on time.\n"); 04169 return; 04170 } 04171 if (sscanf(times, "%d:%d", &s1, &s2) != 2) { 04172 ast_log(LOG_WARNING, "%s isn't a time. Assuming no restrictions based on time.\n", times); 04173 return; 04174 } 04175 if (sscanf(e, "%d:%d", &e1, &e2) != 2) { 04176 ast_log(LOG_WARNING, "%s isn't a time. Assuming no restrictions based on time.\n", e); 04177 return; 04178 } 04179 /* XXX this needs to be optimized */ 04180 #if 1 04181 s1 = s1 * 30 + s2/2; 04182 if ((s1 < 0) || (s1 >= 24*30)) { 04183 ast_log(LOG_WARNING, "%s isn't a valid start time. Assuming no time.\n", times); 04184 return; 04185 } 04186 e1 = e1 * 30 + e2/2; 04187 if ((e1 < 0) || (e1 >= 24*30)) { 04188 ast_log(LOG_WARNING, "%s isn't a valid end time. Assuming no time.\n", e); 04189 return; 04190 } 04191 /* Go through the time and enable each appropriate bit */ 04192 for (x=s1;x != e1;x = (x + 1) % (24 * 30)) { 04193 i->minmask[x/30] |= (1 << (x % 30)); 04194 } 04195 /* Do the last one */ 04196 i->minmask[x/30] |= (1 << (x % 30)); 04197 #else 04198 for (cth=0; cth<24; cth++) { 04199 /* Initialize masks to blank */ 04200 i->minmask[cth] = 0; 04201 for (ctm=0; ctm<30; ctm++) { 04202 if ( 04203 /* First hour with more than one hour */ 04204 (((cth == s1) && (ctm >= s2)) && 04205 ((cth < e1))) 04206 /* Only one hour */ 04207 || (((cth == s1) && (ctm >= s2)) && 04208 ((cth == e1) && (ctm <= e2))) 04209 /* In between first and last hours (more than 2 hours) */ 04210 || ((cth > s1) && 04211 (cth < e1)) 04212 /* Last hour with more than one hour */ 04213 || ((cth > s1) && 04214 ((cth == e1) && (ctm <= e2))) 04215 ) 04216 i->minmask[cth] |= (1 << (ctm / 2)); 04217 } 04218 } 04219 #endif 04220 /* All done */ 04221 return; 04222 }
static int handle_set_global | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3764 of file pbx.c.
References ast_cli(), pbx_builtin_setvar_helper(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03765 { 03766 if (argc != 5) 03767 return RESULT_SHOWUSAGE; 03768 03769 pbx_builtin_setvar_helper(NULL, argv[3], argv[4]); 03770 ast_cli(fd, "\n -- Global variable %s set to %s\n", argv[3], argv[4]); 03771 03772 return RESULT_SUCCESS; 03773 }
static int handle_set_global_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
CLI support for setting global variables.
Definition at line 3752 of file pbx.c.
References ast_cli(), pbx_builtin_setvar_helper(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03753 { 03754 if (argc != 4) 03755 return RESULT_SHOWUSAGE; 03756 03757 pbx_builtin_setvar_helper(NULL, argv[2], argv[3]); 03758 ast_cli(fd, "\n -- Global variable %s set to %s\n", argv[2], argv[3]); 03759 03760 return RESULT_SUCCESS; 03761 }
static int handle_show_application | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3198 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().
03199 { 03200 struct ast_app *a; 03201 int app, no_registered_app = 1; 03202 03203 if (argc < 4) 03204 return RESULT_SHOWUSAGE; 03205 03206 /* ... go through all applications ... */ 03207 AST_LIST_LOCK(&apps); 03208 AST_LIST_TRAVERSE(&apps, a, list) { 03209 /* ... compare this application name with all arguments given 03210 * to 'show application' command ... */ 03211 for (app = 3; app < argc; app++) { 03212 if (!strcasecmp(a->name, argv[app])) { 03213 /* Maximum number of characters added by terminal coloring is 22 */ 03214 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40]; 03215 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL; 03216 int synopsis_size, description_size; 03217 03218 no_registered_app = 0; 03219 03220 if (a->synopsis) 03221 synopsis_size = strlen(a->synopsis) + 23; 03222 else 03223 synopsis_size = strlen("Not available") + 23; 03224 synopsis = alloca(synopsis_size); 03225 03226 if (a->description) 03227 description_size = strlen(a->description) + 23; 03228 else 03229 description_size = strlen("Not available") + 23; 03230 description = alloca(description_size); 03231 03232 if (synopsis && description) { 03233 snprintf(info, 64 + AST_MAX_APP, "\n -= Info about application '%s' =- \n\n", a->name); 03234 term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22); 03235 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 03236 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40); 03237 term_color(synopsis, 03238 a->synopsis ? a->synopsis : "Not available", 03239 COLOR_CYAN, 0, synopsis_size); 03240 term_color(description, 03241 a->description ? a->description : "Not available", 03242 COLOR_CYAN, 0, description_size); 03243 03244 ast_cli(fd,"%s%s%s\n\n%s%s\n", infotitle, syntitle, synopsis, destitle, description); 03245 } else { 03246 /* ... one of our applications, show info ...*/ 03247 ast_cli(fd,"\n -= Info about application '%s' =- \n\n" 03248 "[Synopsis]\n %s\n\n" 03249 "[Description]\n%s\n", 03250 a->name, 03251 a->synopsis ? a->synopsis : "Not available", 03252 a->description ? a->description : "Not available"); 03253 } 03254 } 03255 } 03256 } 03257 AST_LIST_UNLOCK(&apps); 03258 03259 /* we found at least one app? no? */ 03260 if (no_registered_app) { 03261 ast_cli(fd, "Your application(s) is (are) not registered\n"); 03262 return RESULT_FAILURE; 03263 } 03264 03265 return RESULT_SUCCESS; 03266 }
static int handle_show_application_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3128 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().
03129 { 03130 struct ast_app *a; 03131 int app, no_registered_app = 1; 03132 03133 if (argc < 3) 03134 return RESULT_SHOWUSAGE; 03135 03136 /* ... go through all applications ... */ 03137 AST_LIST_LOCK(&apps); 03138 AST_LIST_TRAVERSE(&apps, a, list) { 03139 /* ... compare this application name with all arguments given 03140 * to 'show application' command ... */ 03141 for (app = 2; app < argc; app++) { 03142 if (!strcasecmp(a->name, argv[app])) { 03143 /* Maximum number of characters added by terminal coloring is 22 */ 03144 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40]; 03145 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL; 03146 int synopsis_size, description_size; 03147 03148 no_registered_app = 0; 03149 03150 if (a->synopsis) 03151 synopsis_size = strlen(a->synopsis) + 23; 03152 else 03153 synopsis_size = strlen("Not available") + 23; 03154 synopsis = alloca(synopsis_size); 03155 03156 if (a->description) 03157 description_size = strlen(a->description) + 23; 03158 else 03159 description_size = strlen("Not available") + 23; 03160 description = alloca(description_size); 03161 03162 if (synopsis && description) { 03163 snprintf(info, 64 + AST_MAX_APP, "\n -= Info about application '%s' =- \n\n", a->name); 03164 term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22); 03165 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 03166 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40); 03167 term_color(synopsis, 03168 a->synopsis ? a->synopsis : "Not available", 03169 COLOR_CYAN, 0, synopsis_size); 03170 term_color(description, 03171 a->description ? a->description : "Not available", 03172 COLOR_CYAN, 0, description_size); 03173 03174 ast_cli(fd,"%s%s%s\n\n%s%s\n", infotitle, syntitle, synopsis, destitle, description); 03175 } else { 03176 /* ... one of our applications, show info ...*/ 03177 ast_cli(fd,"\n -= Info about application '%s' =- \n\n" 03178 "[Synopsis]\n %s\n\n" 03179 "[Description]\n%s\n", 03180 a->name, 03181 a->synopsis ? a->synopsis : "Not available", 03182 a->description ? a->description : "Not available"); 03183 } 03184 } 03185 } 03186 } 03187 AST_LIST_UNLOCK(&apps); 03188 03189 /* we found at least one app? no? */ 03190 if (no_registered_app) { 03191 ast_cli(fd, "Your application(s) is (are) not registered\n"); 03192 return RESULT_FAILURE; 03193 } 03194 03195 return RESULT_SUCCESS; 03196 }
static int handle_show_applications | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3393 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.
03394 { 03395 struct ast_app *a; 03396 int like = 0, describing = 0; 03397 int total_match = 0; /* Number of matches in like clause */ 03398 int total_apps = 0; /* Number of apps registered */ 03399 03400 AST_LIST_LOCK(&apps); 03401 03402 if (AST_LIST_EMPTY(&apps)) { 03403 ast_cli(fd, "There are no registered applications\n"); 03404 AST_LIST_UNLOCK(&apps); 03405 return -1; 03406 } 03407 03408 /* core list applications like <keyword> */ 03409 if ((argc == 5) && (!strcmp(argv[3], "like"))) { 03410 like = 1; 03411 } else if ((argc > 4) && (!strcmp(argv[3], "describing"))) { 03412 describing = 1; 03413 } 03414 03415 /* core list applications describing <keyword1> [<keyword2>] [...] */ 03416 if ((!like) && (!describing)) { 03417 ast_cli(fd, " -= Registered Asterisk Applications =-\n"); 03418 } else { 03419 ast_cli(fd, " -= Matching Asterisk Applications =-\n"); 03420 } 03421 03422 AST_LIST_TRAVERSE(&apps, a, list) { 03423 int printapp = 0; 03424 total_apps++; 03425 if (like) { 03426 if (strcasestr(a->name, argv[4])) { 03427 printapp = 1; 03428 total_match++; 03429 } 03430 } else if (describing) { 03431 if (a->description) { 03432 /* Match all words on command line */ 03433 int i; 03434 printapp = 1; 03435 for (i = 4; i < argc; i++) { 03436 if (!strcasestr(a->description, argv[i])) { 03437 printapp = 0; 03438 } else { 03439 total_match++; 03440 } 03441 } 03442 } 03443 } else { 03444 printapp = 1; 03445 } 03446 03447 if (printapp) { 03448 ast_cli(fd," %20s: %s\n", a->name, a->synopsis ? a->synopsis : "<Synopsis not available>"); 03449 } 03450 } 03451 if ((!like) && (!describing)) { 03452 ast_cli(fd, " -= %d Applications Registered =-\n",total_apps); 03453 } else { 03454 ast_cli(fd, " -= %d Applications Matching =-\n",total_match); 03455 } 03456 03457 AST_LIST_UNLOCK(&apps); 03458 03459 return RESULT_SUCCESS; 03460 }
static int handle_show_applications_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3325 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.
03326 { 03327 struct ast_app *a; 03328 int like = 0, describing = 0; 03329 int total_match = 0; /* Number of matches in like clause */ 03330 int total_apps = 0; /* Number of apps registered */ 03331 03332 AST_LIST_LOCK(&apps); 03333 03334 if (AST_LIST_EMPTY(&apps)) { 03335 ast_cli(fd, "There are no registered applications\n"); 03336 AST_LIST_UNLOCK(&apps); 03337 return -1; 03338 } 03339 03340 /* show applications like <keyword> */ 03341 if ((argc == 4) && (!strcmp(argv[2], "like"))) { 03342 like = 1; 03343 } else if ((argc > 3) && (!strcmp(argv[2], "describing"))) { 03344 describing = 1; 03345 } 03346 03347 /* show applications describing <keyword1> [<keyword2>] [...] */ 03348 if ((!like) && (!describing)) { 03349 ast_cli(fd, " -= Registered Asterisk Applications =-\n"); 03350 } else { 03351 ast_cli(fd, " -= Matching Asterisk Applications =-\n"); 03352 } 03353 03354 AST_LIST_TRAVERSE(&apps, a, list) { 03355 int printapp = 0; 03356 total_apps++; 03357 if (like) { 03358 if (strcasestr(a->name, argv[3])) { 03359 printapp = 1; 03360 total_match++; 03361 } 03362 } else if (describing) { 03363 if (a->description) { 03364 /* Match all words on command line */ 03365 int i; 03366 printapp = 1; 03367 for (i = 3; i < argc; i++) { 03368 if (!strcasestr(a->description, argv[i])) { 03369 printapp = 0; 03370 } else { 03371 total_match++; 03372 } 03373 } 03374 } 03375 } else { 03376 printapp = 1; 03377 } 03378 03379 if (printapp) { 03380 ast_cli(fd," %20s: %s\n", a->name, a->synopsis ? a->synopsis : "<Synopsis not available>"); 03381 } 03382 } 03383 if ((!like) && (!describing)) { 03384 ast_cli(fd, " -= %d Applications Registered =-\n",total_apps); 03385 } else { 03386 ast_cli(fd, " -= %d Applications Matching =-\n",total_match); 03387 } 03388 03389 AST_LIST_UNLOCK(&apps); 03390 03391 return RESULT_SUCCESS; 03392 }
static int handle_show_dialplan | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3679 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().
03680 { 03681 char *exten = NULL, *context = NULL; 03682 /* Variables used for different counters */ 03683 struct dialplan_counters counters; 03684 03685 const char *incstack[AST_PBX_MAX_STACK]; 03686 memset(&counters, 0, sizeof(counters)); 03687 03688 if (argc != 2 && argc != 3) 03689 return RESULT_SHOWUSAGE; 03690 03691 /* we obtain [exten@]context? if yes, split them ... */ 03692 if (argc == 3) { 03693 if (strchr(argv[2], '@')) { /* split into exten & context */ 03694 context = ast_strdupa(argv[2]); 03695 exten = strsep(&context, "@"); 03696 /* change empty strings to NULL */ 03697 if (ast_strlen_zero(exten)) 03698 exten = NULL; 03699 } else { /* no '@' char, only context given */ 03700 context = argv[2]; 03701 } 03702 if (ast_strlen_zero(context)) 03703 context = NULL; 03704 } 03705 /* else Show complete dial plan, context and exten are NULL */ 03706 show_dialplan_helper(fd, context, exten, &counters, NULL, 0, incstack); 03707 03708 /* check for input failure and throw some error messages */ 03709 if (context && !counters.context_existence) { 03710 ast_cli(fd, "There is no existence of '%s' context\n", context); 03711 return RESULT_FAILURE; 03712 } 03713 03714 if (exten && !counters.extension_existence) { 03715 if (context) 03716 ast_cli(fd, "There is no existence of %s@%s extension\n", 03717 exten, context); 03718 else 03719 ast_cli(fd, 03720 "There is no existence of '%s' extension in all contexts\n", 03721 exten); 03722 return RESULT_FAILURE; 03723 } 03724 03725 ast_cli(fd,"-= %d %s (%d %s) in %d %s. =-\n", 03726 counters.total_exten, counters.total_exten == 1 ? "extension" : "extensions", 03727 counters.total_prio, counters.total_prio == 1 ? "priority" : "priorities", 03728 counters.total_context, counters.total_context == 1 ? "context" : "contexts"); 03729 03730 /* everything ok */ 03731 return RESULT_SUCCESS; 03732 }
static int handle_show_function | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1403 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().
01404 { 01405 struct ast_custom_function *acf; 01406 /* Maximum number of characters added by terminal coloring is 22 */ 01407 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40]; 01408 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL; 01409 char stxtitle[40], *syntax = NULL; 01410 int synopsis_size, description_size, syntax_size; 01411 01412 if (argc < 4) 01413 return RESULT_SHOWUSAGE; 01414 01415 if (!(acf = ast_custom_function_find(argv[3]))) { 01416 ast_cli(fd, "No function by that name registered.\n"); 01417 return RESULT_FAILURE; 01418 01419 } 01420 01421 if (acf->synopsis) 01422 synopsis_size = strlen(acf->synopsis) + 23; 01423 else 01424 synopsis_size = strlen("Not available") + 23; 01425 synopsis = alloca(synopsis_size); 01426 01427 if (acf->desc) 01428 description_size = strlen(acf->desc) + 23; 01429 else 01430 description_size = strlen("Not available") + 23; 01431 description = alloca(description_size); 01432 01433 if (acf->syntax) 01434 syntax_size = strlen(acf->syntax) + 23; 01435 else 01436 syntax_size = strlen("Not available") + 23; 01437 syntax = alloca(syntax_size); 01438 01439 snprintf(info, 64 + AST_MAX_APP, "\n -= Info about function '%s' =- \n\n", acf->name); 01440 term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22); 01441 term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40); 01442 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 01443 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40); 01444 term_color(syntax, 01445 acf->syntax ? acf->syntax : "Not available", 01446 COLOR_CYAN, 0, syntax_size); 01447 term_color(synopsis, 01448 acf->synopsis ? acf->synopsis : "Not available", 01449 COLOR_CYAN, 0, synopsis_size); 01450 term_color(description, 01451 acf->desc ? acf->desc : "Not available", 01452 COLOR_CYAN, 0, description_size); 01453 01454 ast_cli(fd,"%s%s%s\n\n%s%s\n\n%s%s\n", infotitle, stxtitle, syntax, syntitle, synopsis, destitle, description); 01455 01456 return RESULT_SUCCESS; 01457 }
static int handle_show_function_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1347 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().
01348 { 01349 struct ast_custom_function *acf; 01350 /* Maximum number of characters added by terminal coloring is 22 */ 01351 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40]; 01352 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL; 01353 char stxtitle[40], *syntax = NULL; 01354 int synopsis_size, description_size, syntax_size; 01355 01356 if (argc < 3) 01357 return RESULT_SHOWUSAGE; 01358 01359 if (!(acf = ast_custom_function_find(argv[2]))) { 01360 ast_cli(fd, "No function by that name registered.\n"); 01361 return RESULT_FAILURE; 01362 01363 } 01364 01365 if (acf->synopsis) 01366 synopsis_size = strlen(acf->synopsis) + 23; 01367 else 01368 synopsis_size = strlen("Not available") + 23; 01369 synopsis = alloca(synopsis_size); 01370 01371 if (acf->desc) 01372 description_size = strlen(acf->desc) + 23; 01373 else 01374 description_size = strlen("Not available") + 23; 01375 description = alloca(description_size); 01376 01377 if (acf->syntax) 01378 syntax_size = strlen(acf->syntax) + 23; 01379 else 01380 syntax_size = strlen("Not available") + 23; 01381 syntax = alloca(syntax_size); 01382 01383 snprintf(info, 64 + AST_MAX_APP, "\n -= Info about function '%s' =- \n\n", acf->name); 01384 term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22); 01385 term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40); 01386 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 01387 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40); 01388 term_color(syntax, 01389 acf->syntax ? acf->syntax : "Not available", 01390 COLOR_CYAN, 0, syntax_size); 01391 term_color(synopsis, 01392 acf->synopsis ? acf->synopsis : "Not available", 01393 COLOR_CYAN, 0, synopsis_size); 01394 term_color(description, 01395 acf->desc ? acf->desc : "Not available", 01396 COLOR_CYAN, 0, description_size); 01397 01398 ast_cli(fd,"%s%s%s\n\n%s%s\n\n%s%s\n", infotitle, stxtitle, syntax, syntitle, synopsis, destitle, description); 01399 01400 return RESULT_SUCCESS; 01401 }
static int handle_show_functions | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1319 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.
01320 { 01321 struct ast_custom_function *acf; 01322 int count_acf = 0; 01323 int like = 0; 01324 01325 if (argc == 5 && (!strcmp(argv[3], "like")) ) { 01326 like = 1; 01327 } else if (argc != 3) { 01328 return RESULT_SHOWUSAGE; 01329 } 01330 01331 ast_cli(fd, "%s Custom Functions:\n--------------------------------------------------------------------------------\n", like ? "Matching" : "Installed"); 01332 01333 AST_LIST_LOCK(&acf_root); 01334 AST_LIST_TRAVERSE(&acf_root, acf, acflist) { 01335 if (!like || strstr(acf->name, argv[4])) { 01336 count_acf++; 01337 ast_cli(fd, "%-20.20s %-35.35s %s\n", acf->name, acf->syntax, acf->synopsis); 01338 } 01339 } 01340 AST_LIST_UNLOCK(&acf_root); 01341 01342 ast_cli(fd, "%d %scustom functions installed.\n", count_acf, like ? "matching " : ""); 01343 01344 return RESULT_SUCCESS; 01345 }
static int handle_show_functions_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1292 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.
01293 { 01294 struct ast_custom_function *acf; 01295 int count_acf = 0; 01296 int like = 0; 01297 01298 if (argc == 4 && (!strcmp(argv[2], "like")) ) { 01299 like = 1; 01300 } else if (argc != 2) { 01301 return RESULT_SHOWUSAGE; 01302 } 01303 01304 ast_cli(fd, "%s Custom Functions:\n--------------------------------------------------------------------------------\n", like ? "Matching" : "Installed"); 01305 01306 AST_LIST_LOCK(&acf_root); 01307 AST_LIST_TRAVERSE(&acf_root, acf, acflist) { 01308 if (!like || strstr(acf->name, argv[3])) { 01309 count_acf++; 01310 ast_cli(fd, "%-20.20s %-35.35s %s\n", acf->name, acf->syntax, acf->synopsis); 01311 } 01312 } 01313 AST_LIST_UNLOCK(&acf_root); 01314 01315 ast_cli(fd, "%d %scustom functions installed.\n", count_acf, like ? "matching " : ""); 01316 01317 return RESULT_SUCCESS; 01318 }
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 3735 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.
03736 { 03737 int i = 0; 03738 struct ast_var_t *newvariable; 03739 03740 ast_mutex_lock(&globalslock); 03741 AST_LIST_TRAVERSE (&globals, newvariable, entries) { 03742 i++; 03743 ast_cli(fd, " %s=%s\n", ast_var_name(newvariable), ast_var_value(newvariable)); 03744 } 03745 ast_mutex_unlock(&globalslock); 03746 ast_cli(fd, "\n -- %d variables\n", i); 03747 03748 return RESULT_SUCCESS; 03749 }
static int handle_show_hints | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
handle_show_hints: CLI support for listing registred dial plan hints
Definition at line 3269 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.
03270 { 03271 struct ast_hint *hint; 03272 int num = 0; 03273 int watchers; 03274 struct ast_state_cb *watcher; 03275 03276 if (AST_LIST_EMPTY(&hints)) { 03277 ast_cli(fd, "There are no registered dialplan hints\n"); 03278 return RESULT_SUCCESS; 03279 } 03280 /* ... we have hints ... */ 03281 ast_cli(fd, "\n -= Registered Asterisk Dial Plan Hints =-\n"); 03282 AST_LIST_LOCK(&hints); 03283 AST_LIST_TRAVERSE(&hints, hint, list) { 03284 watchers = 0; 03285 for (watcher = hint->callbacks; watcher; watcher = watcher->next) 03286 watchers++; 03287 ast_cli(fd, " %20s@%-20.20s: %-20.20s State:%-15.15s Watchers %2d\n", 03288 ast_get_extension_name(hint->exten), 03289 ast_get_context_name(ast_get_extension_context(hint->exten)), 03290 ast_get_extension_app(hint->exten), 03291 ast_extension_state2str(hint->laststate), watchers); 03292 num++; 03293 } 03294 ast_cli(fd, "----------------\n"); 03295 ast_cli(fd, "- %d hints registered\n", num); 03296 AST_LIST_UNLOCK(&hints); 03297 return RESULT_SUCCESS; 03298 }
static int handle_show_switches | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
handle_show_switches: CLI support for listing registred dial plan switches
Definition at line 3301 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.
03302 { 03303 struct ast_switch *sw; 03304 03305 AST_LIST_LOCK(&switches); 03306 03307 if (AST_LIST_EMPTY(&switches)) { 03308 AST_LIST_UNLOCK(&switches); 03309 ast_cli(fd, "There are no registered alternative switches\n"); 03310 return RESULT_SUCCESS; 03311 } 03312 03313 ast_cli(fd, "\n -= Registered Asterisk Alternative Switches =-\n"); 03314 AST_LIST_TRAVERSE(&switches, sw, list) 03315 ast_cli(fd, "%s: %s\n", sw->name, sw->description); 03316 03317 AST_LIST_UNLOCK(&switches); 03318 03319 return RESULT_SUCCESS; 03320 }
static int include_valid | ( | struct ast_include * | i | ) | [inline, static] |
Definition at line 603 of file pbx.c.
References ast_check_timing(), ast_include::hastime, and ast_include::timing.
00604 { 00605 if (!i->hastime) 00606 return 1; 00607 00608 return ast_check_timing(&(i->timing)); 00609 }
static int increase_call_count | ( | const struct ast_channel * | c | ) | [static] |
Definition at line 2591 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().
02592 { 02593 int failed = 0; 02594 double curloadavg; 02595 ast_mutex_lock(&maxcalllock); 02596 if (option_maxcalls) { 02597 if (countcalls >= option_maxcalls) { 02598 ast_log(LOG_NOTICE, "Maximum call limit of %d calls exceeded by '%s'!\n", option_maxcalls, c->name); 02599 failed = -1; 02600 } 02601 } 02602 if (option_maxload) { 02603 getloadavg(&curloadavg, 1); 02604 if (curloadavg >= option_maxload) { 02605 ast_log(LOG_NOTICE, "Maximum loadavg limit of %f load exceeded by '%s' (currently %f)!\n", option_maxload, c->name, curloadavg); 02606 failed = -1; 02607 } 02608 } 02609 if (!failed) 02610 countcalls++; 02611 ast_mutex_unlock(&maxcalllock); 02612 02613 return failed; 02614 }
int load_pbx | ( | void | ) |
Provided by pbx.c
Definition at line 6214 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().
06215 { 06216 int x; 06217 06218 /* Initialize the PBX */ 06219 if (option_verbose) { 06220 ast_verbose( "Asterisk PBX Core Initializing\n"); 06221 ast_verbose( "Registering builtin applications:\n"); 06222 } 06223 ast_cli_register_multiple(pbx_cli, sizeof(pbx_cli) / sizeof(struct ast_cli_entry)); 06224 06225 /* Register builtin applications */ 06226 for (x=0; x<sizeof(builtins) / sizeof(struct pbx_builtin); x++) { 06227 if (option_verbose) 06228 ast_verbose( VERBOSE_PREFIX_1 "[%s]\n", builtins[x].name); 06229 if (ast_register_application(builtins[x].name, builtins[x].execute, builtins[x].synopsis, builtins[x].description)) { 06230 ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name); 06231 return -1; 06232 } 06233 } 06234 return 0; 06235 }
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 4075 of file pbx.c.
Referenced by get_range().
04076 { 04077 int i; 04078 04079 if (names) { 04080 for (i = 0; names[i]; i++) { 04081 if (!strcasecmp(s, names[i])) 04082 return i+1; 04083 } 04084 } else if (sscanf(s, "%d", &i) == 1 && i >= 1 && i <= max) { 04085 return i; 04086 } 04087 return 0; /* error return */ 04088 }
static int matchcid | ( | const char * | cidpattern, | |
const char * | callerid | |||
) | [static] |
Definition at line 939 of file pbx.c.
References ast_extension_match(), and ast_strlen_zero().
Referenced by pbx_find_extension().
00940 { 00941 /* If the Caller*ID pattern is empty, then we're matching NO Caller*ID, so 00942 failing to get a number should count as a match, otherwise not */ 00943 00944 if (ast_strlen_zero(callerid)) 00945 return ast_strlen_zero(cidpattern) ? 1 : 0; 00946 00947 return ast_extension_match(cidpattern, callerid); 00948 }
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 1105 of file pbx.c.
Referenced by pbx_retrieve_variable(), and pbx_substitute_variables_helper_full().
01106 { 01107 int parens=0; 01108 01109 *offset = 0; 01110 *length = INT_MAX; 01111 *isfunc = 0; 01112 for (; *var; var++) { 01113 if (*var == '(') { 01114 (*isfunc)++; 01115 parens++; 01116 } else if (*var == ')') { 01117 parens--; 01118 } else if (*var == ':' && parens == 0) { 01119 *var++ = '\0'; 01120 sscanf(var, "%d:%d", offset, length); 01121 return 1; /* offset:length valid */ 01122 } 01123 } 01124 return 0; 01125 }
void pbx_builtin_clear_globals | ( | void | ) |
Definition at line 6016 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().
06017 { 06018 struct ast_var_t *vardata; 06019 06020 ast_mutex_lock(&globalslock); 06021 while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries))) 06022 ast_var_delete(vardata); 06023 ast_mutex_unlock(&globalslock); 06024 }
const char* pbx_builtin_getvar_helper | ( | struct ast_channel * | chan, | |
const char * | name | |||
) |
Definition at line 5793 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, AST_LIST_TRAVERSE, ast_mutex_lock(), ast_mutex_unlock(), ast_var_name(), and ast_var_value().
Referenced by __login_exec(), _macro_exec(), _while_exec(), agent_hangup(), agent_read(), agentmonitoroutgoing_exec(), ast_bridge_call(), ast_channel_bridge(), ast_feature_interpret(), ast_monitor_stop(), builtin_automonitor(), check_goto_on_transfer(), common_exec(), conf_exec(), conf_run(), dahdi_call(), dahdi_hangup(), dundi_exec(), dundi_helper(), get_also_info(), get_index(), get_refer_info(), global_read(), iax2_exec(), import_ch(), leave_voicemail(), local_hangup(), misdn_answer(), misdn_hangup(), morsecode_exec(), notify_new_message(), oh323_call(), oh323_hangup(), park_call_full(), pickup_by_mark(), queue_exec(), real_ctx(), retrydial_exec(), return_exec(), ring_entry(), run_agi(), set_config_flags(), sip_addheader(), sla_trunk_exec(), speech_background(), try_calling(), try_suggested_sip_codec(), and wait_for_answer().
05794 { 05795 struct ast_var_t *variables; 05796 const char *ret = NULL; 05797 int i; 05798 struct varshead *places[2] = { NULL, &globals }; 05799 05800 if (!name) 05801 return NULL; 05802 05803 if (chan) { 05804 ast_channel_lock(chan); 05805 places[0] = &chan->varshead; 05806 } 05807 05808 for (i = 0; i < 2; i++) { 05809 if (!places[i]) 05810 continue; 05811 if (places[i] == &globals) 05812 ast_mutex_lock(&globalslock); 05813 AST_LIST_TRAVERSE(places[i], variables, entries) { 05814 if (!strcmp(name, ast_var_name(variables))) { 05815 ret = ast_var_value(variables); 05816 break; 05817 } 05818 } 05819 if (places[i] == &globals) 05820 ast_mutex_unlock(&globalslock); 05821 if (ret) 05822 break; 05823 } 05824 05825 if (chan) 05826 ast_channel_unlock(chan); 05827 05828 return ret; 05829 }
static int pbx_builtin_gotoif | ( | struct ast_channel * | , | |
void * | ||||
) | [static] |
Definition at line 6036 of file pbx.c.
References ast_log(), ast_strdupa, ast_strlen_zero(), LOG_WARNING, pbx_builtin_goto(), pbx_checkcondition(), and strsep().
06037 { 06038 char *condition, *branch1, *branch2, *branch; 06039 int rc; 06040 char *stringp; 06041 06042 if (ast_strlen_zero(data)) { 06043 ast_log(LOG_WARNING, "Ignoring, since there is no variable to check\n"); 06044 return 0; 06045 } 06046 06047 stringp = ast_strdupa(data); 06048 condition = strsep(&stringp,"?"); 06049 branch1 = strsep(&stringp,":"); 06050 branch2 = strsep(&stringp,""); 06051 branch = pbx_checkcondition(condition) ? branch1 : branch2; 06052 06053 if (ast_strlen_zero(branch)) { 06054 if (option_debug) 06055 ast_log(LOG_DEBUG, "Not taking any branch\n"); 06056 return 0; 06057 } 06058 06059 rc = pbx_builtin_goto(chan, branch); 06060 06061 return rc; 06062 }
int pbx_builtin_importvar | ( | struct ast_channel * | , | |
void * | ||||
) | [static] |
Definition at line 5955 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.
05956 { 05957 char *name; 05958 char *value; 05959 char *channel; 05960 char tmp[VAR_BUF_SIZE]=""; 05961 05962 if (ast_strlen_zero(data)) { 05963 ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n"); 05964 return 0; 05965 } 05966 05967 value = ast_strdupa(data); 05968 name = strsep(&value,"="); 05969 channel = strsep(&value,"|"); 05970 if (channel && value && name) { /*! \todo XXX should do !ast_strlen_zero(..) of the args ? */ 05971 struct ast_channel *chan2 = ast_get_channel_by_name_locked(channel); 05972 if (chan2) { 05973 char *s = alloca(strlen(value) + 4); 05974 if (s) { 05975 sprintf(s, "${%s}", value); 05976 pbx_substitute_variables_helper(chan2, s, tmp, sizeof(tmp) - 1); 05977 } 05978 ast_channel_unlock(chan2); 05979 } 05980 pbx_builtin_setvar_helper(chan, name, tmp); 05981 } 05982 05983 return(0); 05984 }
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 5831 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, ast_func_write(), AST_LIST_INSERT_HEAD, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_strdupa, ast_var_assign(), ast_verbose(), LOG_WARNING, option_verbose, and VERBOSE_PREFIX_2.
Referenced by acf_odbc_read(), acf_odbc_write(), and gosub_exec().
05832 { 05833 struct ast_var_t *newvariable; 05834 struct varshead *headp; 05835 05836 if (name[strlen(name)-1] == ')') { 05837 char *function = ast_strdupa(name); 05838 05839 ast_log(LOG_WARNING, "Cannot push a value onto a function\n"); 05840 ast_func_write(chan, function, value); 05841 return; 05842 } 05843 05844 if (chan) { 05845 ast_channel_lock(chan); 05846 headp = &chan->varshead; 05847 } else { 05848 ast_mutex_lock(&globalslock); 05849 headp = &globals; 05850 } 05851 05852 if (value) { 05853 if ((option_verbose > 1) && (headp == &globals)) 05854 ast_verbose(VERBOSE_PREFIX_2 "Setting global variable '%s' to '%s'\n", name, value); 05855 newvariable = ast_var_assign(name, value); 05856 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 05857 } 05858 05859 if (chan) 05860 ast_channel_unlock(chan); 05861 else 05862 ast_mutex_unlock(&globalslock); 05863 }
static int pbx_builtin_saycharacters | ( | struct ast_channel * | , | |
void * | ||||
) | [static] |
Definition at line 6101 of file pbx.c.
References ast_say_character_str().
06102 { 06103 int res = 0; 06104 06105 if (data) 06106 res = ast_say_character_str(chan, data, "", chan->language); 06107 return res; 06108 }
static int pbx_builtin_saydate | ( | struct ast_channel * | , | |
void * | ||||
) | [static] |
Definition at line 6119 of file pbx.c.
References AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), ast_say_date, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), LOG_WARNING, parse(), and pbx_builtin_setvar_helper().
06120 { 06121 int res = 0; 06122 char *parse; 06123 int unixdate = 0; 06124 char charascii[2]; 06125 06126 AST_DECLARE_APP_ARGS(args, 06127 AST_APP_ARG(datestr); 06128 AST_APP_ARG(digits); 06129 ); 06130 06131 06132 if (ast_strlen_zero(data)) { 06133 ast_log(LOG_WARNING, "SayDate requires an argument (date)\n"); 06134 return -1; 06135 } 06136 06137 if (!(parse = ast_strdupa(data))) { 06138 ast_log(LOG_WARNING, "Memory Error!\n"); 06139 return -1; 06140 } 06141 06142 AST_STANDARD_APP_ARGS(args, parse); 06143 06144 if (!ast_strlen_zero(args.digits) && (strspn(args.digits, "0123456789*#") != strlen(args.digits))) { 06145 ast_log(LOG_WARNING, "SayDate escape digits must be a subset from '0123456789*#'\n"); 06146 args.digits = ""; 06147 } 06148 06149 if (sscanf(args.datestr, "%d", &unixdate) != 1) { 06150 ast_log(LOG_WARNING, "Firt argument to SayDate must be numeric (date)\n"); 06151 return -1; 06152 } 06153 06154 res = ast_say_date(chan, (time_t)unixdate, args.digits, chan->language); 06155 if (res > 0) { 06156 if (isdigit(res) || (res == '*') || (res == '#')) { 06157 snprintf(charascii, 2, "%c", res); 06158 pbx_builtin_setvar_helper(chan, "USER_INPUT", charascii); 06159 res = 0; 06160 } else { 06161 ast_log(LOG_WARNING, "SayDate: invalid return value (%d) detected\n", res); 06162 } 06163 } 06164 return res; 06165 }
static int pbx_builtin_saydigits | ( | struct ast_channel * | , | |
void * | ||||
) | [static] |
Definition at line 6092 of file pbx.c.
References ast_say_digit_str().
06093 { 06094 int res = 0; 06095 06096 if (data) 06097 res = ast_say_digit_str(chan, data, "", chan->language); 06098 return res; 06099 }
static int pbx_builtin_saynumber | ( | struct ast_channel * | , | |
void * | ||||
) | [static] |
Definition at line 6064 of file pbx.c.
References ast_log(), ast_say_number(), ast_strlen_zero(), LOG_WARNING, and strsep().
06065 { 06066 char tmp[256]; 06067 char *number = tmp; 06068 char *options; 06069 06070 if (ast_strlen_zero(data)) { 06071 ast_log(LOG_WARNING, "SayNumber requires an argument (number)\n"); 06072 return -1; 06073 } 06074 ast_copy_string(tmp, data, sizeof(tmp)); 06075 strsep(&number, "|"); 06076 options = strsep(&number, "|"); 06077 if (options) { 06078 if ( strcasecmp(options, "f") && strcasecmp(options,"m") && 06079 strcasecmp(options, "c") && strcasecmp(options, "n") ) { 06080 ast_log(LOG_WARNING, "SayNumber gender option is either 'f', 'm', 'c' or 'n'\n"); 06081 return -1; 06082 } 06083 } 06084 06085 if (ast_say_number(chan, atoi(tmp), "", chan->language, options)) { 06086 ast_log(LOG_WARNING, "We were unable to say the number %s, is it too large?\n", tmp); 06087 } 06088 06089 return 0; 06090 }
static int pbx_builtin_sayphonetic | ( | struct ast_channel * | , | |
void * | ||||
) | [static] |
Definition at line 6110 of file pbx.c.
References ast_say_phonetic_str().
06111 { 06112 int res = 0; 06113 06114 if (data) 06115 res = ast_say_phonetic_str(chan, data, "", chan->language); 06116 return res; 06117 }
static int pbx_builtin_saytime | ( | struct ast_channel * | , | |
void * | ||||
) | [static] |
Definition at line 6167 of file pbx.c.
References AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), ast_say_time, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), LOG_WARNING, parse(), and pbx_builtin_setvar_helper().
06168 { 06169 int res = 0; 06170 char *parse; 06171 int secs = 0; 06172 char charascii[2]; 06173 06174 AST_DECLARE_APP_ARGS(args, 06175 AST_APP_ARG(timestr); 06176 AST_APP_ARG(digits); 06177 ); 06178 06179 if (ast_strlen_zero(data)) { 06180 ast_log(LOG_WARNING, "SayTime requires an argument (time in seconds)\n"); 06181 return -1; 06182 } 06183 06184 if (!(parse = ast_strdupa(data))) { 06185 ast_log(LOG_WARNING, "Memory Error!\n"); 06186 return -1; 06187 } 06188 06189 AST_STANDARD_APP_ARGS(args, parse); 06190 06191 if (!ast_strlen_zero(args.digits) && (strspn(args.digits, "0123456789*#") != strlen(args.digits))) { 06192 ast_log(LOG_WARNING, "SayTime escape digits must be a subset from '0123456789*#'\n"); 06193 args.digits = ""; 06194 } 06195 06196 if (sscanf(args.timestr, "%d", &secs) != 1) { 06197 ast_log(LOG_WARNING, "Firt argument to SayTime must be numeric (time in seconds)\n"); 06198 return -1; 06199 } 06200 06201 res = ast_say_time(chan, (time_t)secs, args.digits, chan->language); 06202 if (res > 0) { 06203 if (isdigit(res) || (res == '*') || (res == '#')) { 06204 snprintf(charascii, 2, "%c", res); 06205 pbx_builtin_setvar_helper(chan, "USER_INPUT", charascii); 06206 res = 0; 06207 } else { 06208 ast_log(LOG_WARNING, "SayTime: invalid return value (%d) detected\n", res); 06209 } 06210 } 06211 return res; 06212 }
int pbx_builtin_serialize_variables | ( | struct ast_channel * | chan, | |
char * | buf, | |||
size_t | size | |||
) |
Definition at line 5762 of file pbx.c.
References ast_build_string(), ast_channel_lock, ast_channel_unlock, AST_LIST_TRAVERSE, ast_log(), ast_var_name(), ast_var_value(), LOG_ERROR, total, var, and ast_channel::varshead.
Referenced by dumpchan_exec(), handle_showchan(), handle_showchan_deprecated(), and vars2manager().
05763 { 05764 struct ast_var_t *variables; 05765 const char *var, *val; 05766 int total = 0; 05767 05768 if (!chan) 05769 return 0; 05770 05771 memset(buf, 0, size); 05772 05773 ast_channel_lock(chan); 05774 05775 AST_LIST_TRAVERSE(&chan->varshead, variables, entries) { 05776 if ((var=ast_var_name(variables)) && (val=ast_var_value(variables)) 05777 /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */ 05778 ) { 05779 if (ast_build_string(&buf, &size, "%s=%s\n", var, val)) { 05780 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n"); 05781 break; 05782 } else 05783 total++; 05784 } else 05785 break; 05786 } 05787 05788 ast_channel_unlock(chan); 05789 05790 return total; 05791 }
static int pbx_builtin_setglobalvar | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 5987 of file pbx.c.
References ast_log(), ast_strlen_zero(), LOG_WARNING, pbx_builtin_setvar_helper(), and strsep().
05988 { 05989 char *name; 05990 char *stringp = data; 05991 static int dep_warning = 0; 05992 05993 if (ast_strlen_zero(data)) { 05994 ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n"); 05995 return 0; 05996 } 05997 05998 name = strsep(&stringp, "="); 05999 06000 if (!dep_warning) { 06001 dep_warning = 1; 06002 ast_log(LOG_WARNING, "SetGlobalVar is deprecated. Please use Set(GLOBAL(%s)=%s) instead.\n", name, stringp); 06003 } 06004 06005 /*! \todo XXX watch out, leading whitespace ? */ 06006 pbx_builtin_setvar_helper(NULL, name, stringp); 06007 06008 return(0); 06009 }
int pbx_builtin_setvar | ( | struct ast_channel * | , | |
void * | ||||
) |
Definition at line 5915 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().
05916 { 05917 char *name, *value, *mydata; 05918 int argc; 05919 char *argv[24]; /* this will only support a maximum of 24 variables being set in a single operation */ 05920 int global = 0; 05921 int x; 05922 05923 if (ast_strlen_zero(data)) { 05924 ast_log(LOG_WARNING, "Set requires at least one variable name/value pair.\n"); 05925 return 0; 05926 } 05927 05928 mydata = ast_strdupa(data); 05929 argc = ast_app_separate_args(mydata, '|', argv, sizeof(argv) / sizeof(argv[0])); 05930 05931 /* check for a trailing flags argument */ 05932 if ((argc > 1) && !strchr(argv[argc-1], '=')) { 05933 argc--; 05934 if (strchr(argv[argc], 'g')) { 05935 ast_log(LOG_WARNING, "The use of the 'g' flag is deprecated. Please use Set(GLOBAL(foo)=bar) instead\n"); 05936 global = 1; 05937 } 05938 } 05939 05940 if (argc > 1) 05941 ast_log(LOG_WARNING, "Setting multiple variables at once within Set is deprecated. Please separate each name/value pair into its own line.\n"); 05942 05943 for (x = 0; x < argc; x++) { 05944 name = argv[x]; 05945 if ((value = strchr(name, '='))) { 05946 *value++ = '\0'; 05947 pbx_builtin_setvar_helper((global) ? NULL : chan, name, value); 05948 } else 05949 ast_log(LOG_WARNING, "Ignoring entry '%s' with no = (and not last 'options' entry)\n", name); 05950 } 05951 05952 return(0); 05953 }
void pbx_builtin_setvar_helper | ( | struct ast_channel * | chan, | |
const char * | name, | |||
const char * | value | |||
) |
Definition at line 5865 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, ast_func_write(), AST_LIST_INSERT_HEAD, AST_LIST_REMOVE, AST_LIST_TRAVERSE, ast_mutex_lock(), ast_mutex_unlock(), ast_strdupa, ast_var_assign(), ast_var_delete(), ast_var_name(), ast_verbose(), option_verbose, and VERBOSE_PREFIX_2.
Referenced by __oh323_new(), _macro_exec(), _while_exec(), acf_odbc_read(), acf_odbc_write(), action_setvar(), agi_exec_full(), aji_status_exec(), app_exec(), aqm_exec(), array(), ast_bridge_call(), ast_channel_bridge(), ast_feature_request_and_dial(), ast_iax2_new(), ast_monitor_start(), ast_pbx_outgoing_exten(), ast_set_variables(), background_detect_exec(), builtin_automonitor(), builtin_blindtransfer(), cb_events(), chanavail_exec(), controlplayback_exec(), count_exec(), dahdi_handle_dtmfup(), dahdi_new(), disa_exec(), do_waiting(), export_aoc_vars(), export_ch(), function_db_delete(), function_db_exists(), function_db_read(), global_write(), handle_request_bye(), handle_request_refer(), handle_set_global(), handle_set_global_deprecated(), handle_setvariable(), hasvoicemail_exec(), isAnsweringMachine(), leave_voicemail(), local_hangup(), lookupblacklist_exec(), misdn_call(), mixmonitor_exec(), ospauth_exec(), ospfinished_exec(), osplookup_exec(), ospnext_exec(), park_exec(), parse_moved_contact(), pbx_builtin_importvar(), pbx_builtin_saydate(), pbx_builtin_saytime(), pbx_builtin_setglobalvar(), pbx_builtin_setvar(), pbx_load_config(), play_message_datetime(), playback_exec(), pop_exec(), pqm_exec(), prep_email_sub_vars(), privacy_exec(), process_ast_dsp(), read_exec(), readfile_exec(), realtime_exec(), realtime_update_exec(), record_exec(), return_exec(), rqm_exec(), sendimage_exec(), sendtext_exec(), sendurl_exec(), set(), set_agentbycallerid(), set_queue_result(), sip_addheader(), sip_hangup(), sip_new(), sla_calc_trunk_timeouts(), sla_station_exec(), sla_trunk_exec(), socket_process(), speech_create(), ss_thread(), start_monitor_exec(), system_exec_helper(), transfer_exec(), try_calling(), tryexec_exec(), upqm_exec(), vm_box_exists(), vm_exec(), and vmauthenticate().
05866 { 05867 struct ast_var_t *newvariable; 05868 struct varshead *headp; 05869 const char *nametail = name; 05870 05871 if (name[strlen(name)-1] == ')') { 05872 char *function = ast_strdupa(name); 05873 05874 ast_func_write(chan, function, value); 05875 return; 05876 } 05877 05878 if (chan) { 05879 ast_channel_lock(chan); 05880 headp = &chan->varshead; 05881 } else { 05882 ast_mutex_lock(&globalslock); 05883 headp = &globals; 05884 } 05885 05886 /* For comparison purposes, we have to strip leading underscores */ 05887 if (*nametail == '_') { 05888 nametail++; 05889 if (*nametail == '_') 05890 nametail++; 05891 } 05892 05893 AST_LIST_TRAVERSE (headp, newvariable, entries) { 05894 if (strcasecmp(ast_var_name(newvariable), nametail) == 0) { 05895 /* there is already such a variable, delete it */ 05896 AST_LIST_REMOVE(headp, newvariable, entries); 05897 ast_var_delete(newvariable); 05898 break; 05899 } 05900 } 05901 05902 if (value) { 05903 if ((option_verbose > 1) && (headp == &globals)) 05904 ast_verbose(VERBOSE_PREFIX_2 "Setting global variable '%s' to '%s'\n", name, value); 05905 newvariable = ast_var_assign(name, value); 05906 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 05907 } 05908 05909 if (chan) 05910 ast_channel_unlock(chan); 05911 else 05912 ast_mutex_unlock(&globalslock); 05913 }
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 6026 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().
06027 { 06028 if (ast_strlen_zero(condition)) /* NULL or empty strings are false */ 06029 return 0; 06030 else if (*condition >= '0' && *condition <= '9') /* Numbers are evaluated for truth */ 06031 return atoi(condition); 06032 else /* Strings are true */ 06033 return 1; 06034 }
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 537 of file pbx.c.
References app, ast_channel::appl, ast_cdr_setapp(), ast_check_hangup(), ast_channel::cdr, ast_channel::data, and S_OR.
Referenced by answer_exec_run(), ast_bridge_call(), ast_pbx_run_app(), async_wait(), builtin_automonitor(), conf_run(), dundi_exec(), exec_exec(), execif_exec(), feature_exec_app(), forward_message(), handle_exec(), iax2_exec(), milliwatt_exec(), page_exec(), pbx_builtin_execiftime(), pbx_extension_helper(), realtime_exec(), try_calling(), and tryexec_exec().
00540 { 00541 int res; 00542 00543 const char *saved_c_appl; 00544 const char *saved_c_data; 00545 00546 if (c->cdr && !ast_check_hangup(c)) 00547 ast_cdr_setapp(c->cdr, app->name, data); 00548 00549 /* save channel values */ 00550 saved_c_appl= c->appl; 00551 saved_c_data= c->data; 00552 00553 c->appl = app->name; 00554 c->data = data; 00555 /* XXX remember what to to when we have linked apps to modules */ 00556 if (app->module) { 00557 /* XXX LOCAL_USER_ADD(app->module) */ 00558 } 00559 res = app->execute(c, S_OR(data, "")); 00560 if (app->module) { 00561 /* XXX LOCAL_USER_REMOVE(app->module) */ 00562 } 00563 /* restore channel values */ 00564 c->appl = saved_c_appl; 00565 c->data = saved_c_data; 00566 return res; 00567 }
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 1831 of file pbx.c.
References ast_exten::app, app, ast_log(), ast_rdlock_contexts(), ast_unlock_contexts(), ast_verbose(), COLOR_BRCYAN, COLOR_BRMAGENTA, ast_channel::context, pbx_find_info::data, E_CANMATCH, E_FINDLABEL, E_MATCH, E_MATCHMORE, EVENT_FLAG_CALL, ast_switch::exec, EXT_DATA_SIZE, ast_channel::exten, pbx_find_info::foundcontext, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, manager_event(), ast_switch::name, option_debug, option_verbose, pbx_exec(), pbx_find_extension(), pbx_findapp(), pbx_substitute_variables(), ast_channel::priority, ast_exten::priority, pbx_find_info::stacklen, pbx_find_info::status, STATUS_NO_CONTEXT, STATUS_NO_EXTENSION, STATUS_NO_LABEL, STATUS_NO_PRIORITY, pbx_find_info::swo, term_color(), and VERBOSE_PREFIX_3.
Referenced by ast_canmatch_extension(), ast_exists_extension(), ast_findlabel_extension(), ast_findlabel_extension2(), ast_matchmore_extension(), and ast_spawn_extension().
01834 { 01835 struct ast_exten *e; 01836 struct ast_app *app; 01837 int res; 01838 struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */ 01839 char passdata[EXT_DATA_SIZE]; 01840 01841 int matching_action = (action == E_MATCH || action == E_CANMATCH || action == E_MATCHMORE); 01842 01843 ast_rdlock_contexts(); 01844 e = pbx_find_extension(c, con, &q, context, exten, priority, label, callerid, action); 01845 if (e) { 01846 if (matching_action) { 01847 ast_unlock_contexts(); 01848 return -1; /* success, we found it */ 01849 } else if (action == E_FINDLABEL) { /* map the label to a priority */ 01850 res = e->priority; 01851 ast_unlock_contexts(); 01852 return res; /* the priority we were looking for */ 01853 } else { /* spawn */ 01854 app = pbx_findapp(e->app); 01855 ast_unlock_contexts(); 01856 if (!app) { 01857 ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority); 01858 return -1; 01859 } 01860 if (c->context != context) 01861 ast_copy_string(c->context, context, sizeof(c->context)); 01862 if (c->exten != exten) 01863 ast_copy_string(c->exten, exten, sizeof(c->exten)); 01864 c->priority = priority; 01865 pbx_substitute_variables(passdata, sizeof(passdata), c, e); 01866 if (option_debug) { 01867 ast_log(LOG_DEBUG, "Launching '%s'\n", app->name); 01868 } 01869 if (option_verbose > 2) { 01870 char tmp[80], tmp2[80], tmp3[EXT_DATA_SIZE]; 01871 ast_verbose( VERBOSE_PREFIX_3 "Executing [%s@%s:%d] %s(\"%s\", \"%s\") %s\n", 01872 exten, context, priority, 01873 term_color(tmp, app->name, COLOR_BRCYAN, 0, sizeof(tmp)), 01874 term_color(tmp2, c->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)), 01875 term_color(tmp3, passdata, COLOR_BRMAGENTA, 0, sizeof(tmp3)), 01876 "in new stack"); 01877 } 01878 manager_event(EVENT_FLAG_CALL, "Newexten", 01879 "Channel: %s\r\n" 01880 "Context: %s\r\n" 01881 "Extension: %s\r\n" 01882 "Priority: %d\r\n" 01883 "Application: %s\r\n" 01884 "AppData: %s\r\n" 01885 "Uniqueid: %s\r\n", 01886 c->name, c->context, c->exten, c->priority, app->name, passdata, c->uniqueid); 01887 return pbx_exec(c, app, passdata); /* 0 on success, -1 on failure */ 01888 } 01889 } else if (q.swo) { /* not found here, but in another switch */ 01890 ast_unlock_contexts(); 01891 if (matching_action) { 01892 return -1; 01893 } else { 01894 if (!q.swo->exec) { 01895 ast_log(LOG_WARNING, "No execution engine for switch %s\n", q.swo->name); 01896 res = -1; 01897 } 01898 return q.swo->exec(c, q.foundcontext ? q.foundcontext : context, exten, priority, callerid, q.data); 01899 } 01900 } else { /* not found anywhere, see what happened */ 01901 ast_unlock_contexts(); 01902 switch (q.status) { 01903 case STATUS_NO_CONTEXT: 01904 if (!matching_action) 01905 ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", context); 01906 break; 01907 case STATUS_NO_EXTENSION: 01908 if (!matching_action) 01909 ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, context); 01910 break; 01911 case STATUS_NO_PRIORITY: 01912 if (!matching_action) 01913 ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, context); 01914 break; 01915 case STATUS_NO_LABEL: 01916 if (context) 01917 ast_log(LOG_NOTICE, "No such label '%s' in extension '%s' in context '%s'\n", label, exten, context); 01918 break; 01919 default: 01920 if (option_debug) 01921 ast_log(LOG_DEBUG, "Shouldn't happen!\n"); 01922 } 01923 01924 return (matching_action) ? 0 : -1; 01925 } 01926 }
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 966 of file pbx.c.
References ast_log(), AST_PBX_MAX_STACK, ast_walk_context_extensions(), ast_walk_contexts(), ast_walk_extension_priorities(), ast_exten::cidmatch, pbx_find_info::data, E_FINDLABEL, E_MATCHMORE, ast_exten::exten, extension_match_core(), pbx_find_info::foundcontext, pbx_find_info::incstack, ast_exten::label, LOG_WARNING, match(), matchcid(), ast_exten::matchcid, ast_exten::priority, pbx_find_info::stacklen, pbx_find_info::status, STATUS_NO_CONTEXT, STATUS_NO_EXTENSION, STATUS_NO_LABEL, STATUS_NO_PRIORITY, STATUS_SUCCESS, and pbx_find_info::swo.
Referenced by ast_hint_extension(), ast_merge_contexts_and_delete(), and pbx_extension_helper().
00970 { 00971 int x, res; 00972 struct ast_context *tmp; 00973 struct ast_exten *e, *eroot; 00974 struct ast_include *i; 00975 struct ast_sw *sw; 00976 char *tmpdata = NULL; 00977 00978 /* Initialize status if appropriate */ 00979 if (q->stacklen == 0) { 00980 q->status = STATUS_NO_CONTEXT; 00981 q->swo = NULL; 00982 q->data = NULL; 00983 q->foundcontext = NULL; 00984 } 00985 /* Check for stack overflow */ 00986 if (q->stacklen >= AST_PBX_MAX_STACK) { 00987 ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n"); 00988 return NULL; 00989 } 00990 /* Check first to see if we've already been checked */ 00991 for (x = 0; x < q->stacklen; x++) { 00992 if (!strcasecmp(q->incstack[x], context)) 00993 return NULL; 00994 } 00995 if (bypass) /* bypass means we only look there */ 00996 tmp = bypass; 00997 else { /* look in contexts */ 00998 tmp = NULL; 00999 while ((tmp = ast_walk_contexts(tmp)) ) { 01000 if (!strcmp(tmp->name, context)) 01001 break; 01002 } 01003 if (!tmp) 01004 return NULL; 01005 } 01006 if (q->status < STATUS_NO_EXTENSION) 01007 q->status = STATUS_NO_EXTENSION; 01008 01009 /* scan the list trying to match extension and CID */ 01010 eroot = NULL; 01011 while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) { 01012 int match = extension_match_core(eroot->exten, exten, action); 01013 /* 0 on fail, 1 on match, 2 on earlymatch */ 01014 01015 if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid))) 01016 continue; /* keep trying */ 01017 if (match == 2 && action == E_MATCHMORE) { 01018 /* We match an extension ending in '!'. 01019 * The decision in this case is final and is NULL (no match). 01020 */ 01021 return NULL; 01022 } 01023 /* found entry, now look for the right priority */ 01024 if (q->status < STATUS_NO_PRIORITY) 01025 q->status = STATUS_NO_PRIORITY; 01026 e = NULL; 01027 while ( (e = ast_walk_extension_priorities(eroot, e)) ) { 01028 /* Match label or priority */ 01029 if (action == E_FINDLABEL) { 01030 if (q->status < STATUS_NO_LABEL) 01031 q->status = STATUS_NO_LABEL; 01032 if (label && e->label && !strcmp(label, e->label)) 01033 break; /* found it */ 01034 } else if (e->priority == priority) { 01035 break; /* found it */ 01036 } /* else keep searching */ 01037 } 01038 if (e) { /* found a valid match */ 01039 q->status = STATUS_SUCCESS; 01040 q->foundcontext = context; 01041 return e; 01042 } 01043 } 01044 /* Check alternative switches */ 01045 AST_LIST_TRAVERSE(&tmp->alts, sw, list) { 01046 struct ast_switch *asw = pbx_findswitch(sw->name); 01047 ast_switch_f *aswf = NULL; 01048 char *datap; 01049 01050 if (!asw) { 01051 ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name); 01052 continue; 01053 } 01054 /* Substitute variables now */ 01055 if (sw->eval) { 01056 if (!(tmpdata = ast_threadstorage_get(&switch_data, 512))) { 01057 ast_log(LOG_WARNING, "Can't evaluate switch?!"); 01058 continue; 01059 } 01060 pbx_substitute_variables_helper(chan, sw->data, tmpdata, 512); 01061 } 01062 01063 /* equivalent of extension_match_core() at the switch level */ 01064 if (action == E_CANMATCH) 01065 aswf = asw->canmatch; 01066 else if (action == E_MATCHMORE) 01067 aswf = asw->matchmore; 01068 else /* action == E_MATCH */ 01069 aswf = asw->exists; 01070 datap = sw->eval ? tmpdata : sw->data; 01071 if (!aswf) 01072 res = 0; 01073 else { 01074 if (chan) 01075 ast_autoservice_start(chan); 01076 res = aswf(chan, context, exten, priority, callerid, datap); 01077 if (chan) 01078 ast_autoservice_stop(chan); 01079 } 01080 if (res) { /* Got a match */ 01081 q->swo = asw; 01082 q->data = datap; 01083 q->foundcontext = context; 01084 /* XXX keep status = STATUS_NO_CONTEXT ? */ 01085 return NULL; 01086 } 01087 } 01088 q->incstack[q->stacklen++] = tmp->name; /* Setup the stack */ 01089 /* Now try any includes we have in this context */ 01090 for (i = tmp->includes; i; i = i->next) { 01091 if (include_valid(i)) { 01092 if ((e = pbx_find_extension(chan, bypass, q, i->rname, exten, priority, label, callerid, action))) 01093 return e; 01094 if (q->swo) 01095 return NULL; 01096 } 01097 } 01098 return NULL; 01099 }
struct ast_app* pbx_findapp | ( | const char * | app | ) |
Look up an application.
app | name of the app |
Definition at line 575 of file pbx.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, and AST_LIST_UNLOCK.
Referenced by answer_exec_run(), ast_bridge_call(), ast_pbx_run_app(), async_wait(), builtin_automonitor(), conf_run(), dundi_exec(), exec_exec(), execif_exec(), feature_exec_app(), forward_message(), handle_exec(), iax2_exec(), milliwatt_exec(), page_exec(), pbx_builtin_execiftime(), pbx_extension_helper(), realtime_exec(), try_calling(), and tryexec_exec().
00576 { 00577 struct ast_app *tmp; 00578 00579 AST_LIST_LOCK(&apps); 00580 AST_LIST_TRAVERSE(&apps, tmp, list) { 00581 if (!strcasecmp(tmp->name, app)) 00582 break; 00583 } 00584 AST_LIST_UNLOCK(&apps); 00585 00586 return tmp; 00587 }
static struct ast_switch* pbx_findswitch | ( | const char * | sw | ) | [static] |
Definition at line 589 of file pbx.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, and ast_switch::name.
00590 { 00591 struct ast_switch *asw; 00592 00593 AST_LIST_LOCK(&switches); 00594 AST_LIST_TRAVERSE(&switches, asw, list) { 00595 if (!strcasecmp(asw->name, sw)) 00596 break; 00597 } 00598 AST_LIST_UNLOCK(&switches); 00599 00600 return asw; 00601 }
void pbx_retrieve_variable | ( | struct ast_channel * | c, | |
const char * | var, | |||
char ** | ret, | |||
char * | workspace, | |||
int | workspacelen, | |||
struct varshead * | headp | |||
) |
pbx_retrieve_variable: Support for Asterisk built-in variables ---
Definition at line 1173 of file pbx.c.
References ast_cause2str(), ast_channel_lock, ast_channel_unlock, ast_config_AST_SYSTEM_NAME, ast_get_hint(), AST_LIST_TRAVERSE, ast_mutex_lock(), ast_mutex_unlock(), ast_strdupa, ast_var_name(), ast_var_value(), ast_channel::cid, ast_callerid::cid_ani2, ast_callerid::cid_pres, ast_callerid::cid_tns, ast_callerid::cid_ton, ast_channel::context, ast_channel::exten, ast_channel::hangupcause, offset, parse_variable_name(), ast_channel::priority, s, and substring().
Referenced by action_getvar(), handle_getvariable(), and pbx_substitute_variables_helper_full().
01174 { 01175 const char not_found = '\0'; 01176 char *tmpvar; 01177 const char *s; /* the result */ 01178 int offset, length; 01179 int i, need_substring; 01180 struct varshead *places[2] = { headp, &globals }; /* list of places where we may look */ 01181 01182 if (c) { 01183 ast_channel_lock(c); 01184 places[0] = &c->varshead; 01185 } 01186 /* 01187 * Make a copy of var because parse_variable_name() modifies the string. 01188 * Then if called directly, we might need to run substring() on the result; 01189 * remember this for later in 'need_substring', 'offset' and 'length' 01190 */ 01191 tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */ 01192 need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */); 01193 01194 /* 01195 * Look first into predefined variables, then into variable lists. 01196 * Variable 's' points to the result, according to the following rules: 01197 * s == ¬_found (set at the beginning) means that we did not find a 01198 * matching variable and need to look into more places. 01199 * If s != ¬_found, s is a valid result string as follows: 01200 * s = NULL if the variable does not have a value; 01201 * you typically do this when looking for an unset predefined variable. 01202 * s = workspace if the result has been assembled there; 01203 * typically done when the result is built e.g. with an snprintf(), 01204 * so we don't need to do an additional copy. 01205 * s != workspace in case we have a string, that needs to be copied 01206 * (the ast_copy_string is done once for all at the end). 01207 * Typically done when the result is already available in some string. 01208 */ 01209 s = ¬_found; /* default value */ 01210 if (c) { /* This group requires a valid channel */ 01211 /* Names with common parts are looked up a piece at a time using strncmp. */ 01212 if (!strncmp(var, "CALL", 4)) { 01213 if (!strncmp(var + 4, "ING", 3)) { 01214 if (!strcmp(var + 7, "PRES")) { /* CALLINGPRES */ 01215 snprintf(workspace, workspacelen, "%d", c->cid.cid_pres); 01216 s = workspace; 01217 } else if (!strcmp(var + 7, "ANI2")) { /* CALLINGANI2 */ 01218 snprintf(workspace, workspacelen, "%d", c->cid.cid_ani2); 01219 s = workspace; 01220 } else if (!strcmp(var + 7, "TON")) { /* CALLINGTON */ 01221 snprintf(workspace, workspacelen, "%d", c->cid.cid_ton); 01222 s = workspace; 01223 } else if (!strcmp(var + 7, "TNS")) { /* CALLINGTNS */ 01224 snprintf(workspace, workspacelen, "%d", c->cid.cid_tns); 01225 s = workspace; 01226 } 01227 } 01228 } else if (!strcmp(var, "HINT")) { 01229 s = ast_get_hint(workspace, workspacelen, NULL, 0, c, c->context, c->exten) ? workspace : NULL; 01230 } else if (!strcmp(var, "HINTNAME")) { 01231 s = ast_get_hint(NULL, 0, workspace, workspacelen, c, c->context, c->exten) ? workspace : NULL; 01232 } else if (!strcmp(var, "EXTEN")) { 01233 s = c->exten; 01234 } else if (!strcmp(var, "CONTEXT")) { 01235 s = c->context; 01236 } else if (!strcmp(var, "PRIORITY")) { 01237 snprintf(workspace, workspacelen, "%d", c->priority); 01238 s = workspace; 01239 } else if (!strcmp(var, "CHANNEL")) { 01240 s = c->name; 01241 } else if (!strcmp(var, "UNIQUEID")) { 01242 s = c->uniqueid; 01243 } else if (!strcmp(var, "HANGUPCAUSE")) { 01244 snprintf(workspace, workspacelen, "%d", c->hangupcause); 01245 s = workspace; 01246 } else if (c && !strcmp(var, "HANGUPCAUSESTR")) { 01247 ast_copy_string(workspace, ast_cause2str(c->hangupcause), workspacelen); 01248 *ret = workspace; 01249 } 01250 } 01251 if (s == ¬_found) { /* look for more */ 01252 if (!strcmp(var, "EPOCH")) { 01253 snprintf(workspace, workspacelen, "%u",(int)time(NULL)); 01254 s = workspace; 01255 } else if (!strcmp(var, "SYSTEMNAME")) { 01256 s = ast_config_AST_SYSTEM_NAME; 01257 } 01258 } 01259 /* if not found, look into chanvars or global vars */ 01260 for (i = 0; s == ¬_found && i < (sizeof(places) / sizeof(places[0])); i++) { 01261 struct ast_var_t *variables; 01262 if (!places[i]) 01263 continue; 01264 if (places[i] == &globals) 01265 ast_mutex_lock(&globalslock); 01266 AST_LIST_TRAVERSE(places[i], variables, entries) { 01267 if (strcasecmp(ast_var_name(variables), var)==0) { 01268 s = ast_var_value(variables); 01269 break; 01270 } 01271 } 01272 if (places[i] == &globals) 01273 ast_mutex_unlock(&globalslock); 01274 } 01275 if (s == ¬_found || s == NULL) 01276 *ret = NULL; 01277 else { 01278 if (s != workspace) 01279 ast_copy_string(workspace, s, workspacelen); 01280 *ret = workspace; 01281 if (need_substring) 01282 *ret = substring(*ret, offset, length, workspace, workspacelen); 01283 } 01284 01285 if (c) 01286 ast_channel_unlock(c); 01287 }
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 2698 of file pbx.c.
References autofallthrough.
Referenced by pbx_load_module().
02699 { 02700 int oldval = autofallthrough; 02701 autofallthrough = newval; 02702 return oldval; 02703 }
static void pbx_substitute_variables | ( | char * | passdata, | |
int | datalen, | |||
struct ast_channel * | c, | |||
struct ast_exten * | e | |||
) | [static] |
Definition at line 1802 of file pbx.c.
References ast_exten::data, and pbx_substitute_variables_helper().
Referenced by pbx_extension_helper().
01803 { 01804 memset(passdata, 0, datalen); 01805 01806 /* No variables or expressions in e->data, so why scan it? */ 01807 if (e->data && !strchr(e->data, '$') && !strstr(e->data,"${") && !strstr(e->data,"$[") && !strstr(e->data,"$(")) { 01808 ast_copy_string(passdata, e->data, datalen); 01809 return; 01810 } 01811 01812 pbx_substitute_variables_helper(c, e->data, passdata, datalen - 1); 01813 }
void pbx_substitute_variables_helper | ( | struct ast_channel * | c, | |
const char * | cp1, | |||
char * | cp2, | |||
int | count | |||
) |
Definition at line 1792 of file pbx.c.
References pbx_substitute_variables_helper_full(), and ast_channel::varshead.
Referenced by _macro_exec(), acf_odbc_read(), acf_odbc_write(), add_extensions(), custom_log(), cut_internal(), exec_exec(), function_eval(), function_fieldqty(), handle_getvariablefull(), launch_monitor_thread(), make_email_file(), pbx_builtin_importvar(), pbx_load_config(), pbx_substitute_variables(), realtime_exec(), rpt_do_lstats(), sendpage(), try_calling(), and tryexec_exec().
01793 { 01794 pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count); 01795 }
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 1598 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().
01599 { 01600 /* Substitutes variables into cp2, based on string cp1, and assuming cp2 to be 01601 zero-filled */ 01602 char *cp4; 01603 const char *tmp, *whereweare; 01604 int length, offset, offset2, isfunction; 01605 char *workspace = NULL; 01606 char *ltmp = NULL, *var = NULL; 01607 char *nextvar, *nextexp, *nextthing; 01608 char *vars, *vare; 01609 int pos, brackets, needsub, len; 01610 01611 whereweare=tmp=cp1; 01612 while (!ast_strlen_zero(whereweare) && count) { 01613 /* Assume we're copying the whole remaining string */ 01614 pos = strlen(whereweare); 01615 nextvar = NULL; 01616 nextexp = NULL; 01617 nextthing = strchr(whereweare, '$'); 01618 if (nextthing) { 01619 switch(nextthing[1]) { 01620 case '{': 01621 nextvar = nextthing; 01622 pos = nextvar - whereweare; 01623 break; 01624 case '[': 01625 nextexp = nextthing; 01626 pos = nextexp - whereweare; 01627 break; 01628 default: 01629 pos = 1; 01630 } 01631 } 01632 01633 if (pos) { 01634 /* Can't copy more than 'count' bytes */ 01635 if (pos > count) 01636 pos = count; 01637 01638 /* Copy that many bytes */ 01639 memcpy(cp2, whereweare, pos); 01640 01641 count -= pos; 01642 cp2 += pos; 01643 whereweare += pos; 01644 } 01645 01646 if (nextvar) { 01647 /* We have a variable. Find the start and end, and determine 01648 if we are going to have to recursively call ourselves on the 01649 contents */ 01650 vars = vare = nextvar + 2; 01651 brackets = 1; 01652 needsub = 0; 01653 01654 /* Find the end of it */ 01655 while (brackets && *vare) { 01656 if ((vare[0] == '$') && (vare[1] == '{')) { 01657 needsub++; 01658 } else if (vare[0] == '{') { 01659 brackets++; 01660 } else if (vare[0] == '}') { 01661 brackets--; 01662 } else if ((vare[0] == '$') && (vare[1] == '[')) 01663 needsub++; 01664 vare++; 01665 } 01666 if (brackets) 01667 ast_log(LOG_NOTICE, "Error in extension logic (missing '}')\n"); 01668 len = vare - vars - 1; 01669 01670 /* Skip totally over variable string */ 01671 whereweare += (len + 3); 01672 01673 if (!var) 01674 var = alloca(VAR_BUF_SIZE); 01675 01676 /* Store variable name (and truncate) */ 01677 ast_copy_string(var, vars, len + 1); 01678 01679 /* Substitute if necessary */ 01680 if (needsub) { 01681 if (!ltmp) 01682 ltmp = alloca(VAR_BUF_SIZE); 01683 01684 memset(ltmp, 0, VAR_BUF_SIZE); 01685 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1); 01686 vars = ltmp; 01687 } else { 01688 vars = var; 01689 } 01690 01691 if (!workspace) 01692 workspace = alloca(VAR_BUF_SIZE); 01693 01694 workspace[0] = '\0'; 01695 01696 parse_variable_name(vars, &offset, &offset2, &isfunction); 01697 if (isfunction) { 01698 /* Evaluate function */ 01699 if (c || !headp) 01700 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 01701 else { 01702 struct varshead old; 01703 struct ast_channel *c = ast_channel_alloc(0, 0, "", "", "", "", "", 0, "Bogus/%p", vars); 01704 if (c) { 01705 memcpy(&old, &c->varshead, sizeof(old)); 01706 memcpy(&c->varshead, headp, sizeof(c->varshead)); 01707 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 01708 /* Don't deallocate the varshead that was passed in */ 01709 memcpy(&c->varshead, &old, sizeof(c->varshead)); 01710 ast_channel_free(c); 01711 } else 01712 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n"); 01713 } 01714 01715 if (option_debug) 01716 ast_log(LOG_DEBUG, "Function result is '%s'\n", cp4 ? cp4 : "(null)"); 01717 } else { 01718 /* Retrieve variable value */ 01719 pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp); 01720 } 01721 if (cp4) { 01722 cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE); 01723 01724 length = strlen(cp4); 01725 if (length > count) 01726 length = count; 01727 memcpy(cp2, cp4, length); 01728 count -= length; 01729 cp2 += length; 01730 } 01731 } else if (nextexp) { 01732 /* We have an expression. Find the start and end, and determine 01733 if we are going to have to recursively call ourselves on the 01734 contents */ 01735 vars = vare = nextexp + 2; 01736 brackets = 1; 01737 needsub = 0; 01738 01739 /* Find the end of it */ 01740 while(brackets && *vare) { 01741 if ((vare[0] == '$') && (vare[1] == '[')) { 01742 needsub++; 01743 brackets++; 01744 vare++; 01745 } else if (vare[0] == '[') { 01746 brackets++; 01747 } else if (vare[0] == ']') { 01748 brackets--; 01749 } else if ((vare[0] == '$') && (vare[1] == '{')) { 01750 needsub++; 01751 vare++; 01752 } 01753 vare++; 01754 } 01755 if (brackets) 01756 ast_log(LOG_NOTICE, "Error in extension logic (missing ']')\n"); 01757 len = vare - vars - 1; 01758 01759 /* Skip totally over expression */ 01760 whereweare += (len + 3); 01761 01762 if (!var) 01763 var = alloca(VAR_BUF_SIZE); 01764 01765 /* Store variable name (and truncate) */ 01766 ast_copy_string(var, vars, len + 1); 01767 01768 /* Substitute if necessary */ 01769 if (needsub) { 01770 if (!ltmp) 01771 ltmp = alloca(VAR_BUF_SIZE); 01772 01773 memset(ltmp, 0, VAR_BUF_SIZE); 01774 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1); 01775 vars = ltmp; 01776 } else { 01777 vars = var; 01778 } 01779 01780 length = ast_expr(vars, cp2, count); 01781 01782 if (length) { 01783 if (option_debug) 01784 ast_log(LOG_DEBUG, "Expression result is '%s'\n", cp2); 01785 count -= length; 01786 cp2 += length; 01787 } 01788 } 01789 } 01790 }
void pbx_substitute_variables_varshead | ( | struct varshead * | headp, | |
const char * | cp1, | |||
char * | cp2, | |||
int | count | |||
) |
Definition at line 1797 of file pbx.c.
References pbx_substitute_variables_helper_full().
Referenced by ast_add_extension2(), dundi_lookup_local(), and loopback_subst().
01798 { 01799 pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count); 01800 }
static void* pbx_thread | ( | void * | data | ) | [static] |
Definition at line 2634 of file pbx.c.
References __ast_pbx_run(), and decrease_call_count().
Referenced by ast_pbx_start().
02635 { 02636 /* Oh joyeous kernel, we're a new thread, with nothing to do but 02637 answer this channel and get it going. 02638 */ 02639 /* NOTE: 02640 The launcher of this function _MUST_ increment 'countcalls' 02641 before invoking the function; it will be decremented when the 02642 PBX has finished running on the channel 02643 */ 02644 struct ast_channel *c = data; 02645 02646 __ast_pbx_run(c); 02647 decrease_call_count(); 02648 02649 pthread_exit(NULL); 02650 02651 return NULL; 02652 }
static void print_ext | ( | struct ast_exten * | e, | |
char * | buf, | |||
int | buflen | |||
) | [static] |
helper function to print an extension
Definition at line 3517 of file pbx.c.
References ast_get_extension_app(), ast_get_extension_app_data(), ast_get_extension_priority(), ast_strlen_zero(), and PRIORITY_HINT.
Referenced by show_dialplan_helper().
03518 { 03519 int prio = ast_get_extension_priority(e); 03520 if (prio == PRIORITY_HINT) { 03521 snprintf(buf, buflen, "hint: %s", 03522 ast_get_extension_app(e)); 03523 } else { 03524 snprintf(buf, buflen, "%d. %s(%s)", 03525 prio, ast_get_extension_app(e), 03526 (!ast_strlen_zero(ast_get_extension_app_data(e)) ? (char *)ast_get_extension_app_data(e) : "")); 03527 } 03528 }
static void set_ext_pri | ( | struct ast_channel * | c, | |
const char * | exten, | |||
int | pri | |||
) | [static] |
Definition at line 2346 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, ast_channel::exten, and ast_channel::priority.
Referenced by __ast_pbx_run(), ast_pbx_outgoing_exten(), and pbx_builtin_waitexten().
02347 { 02348 ast_channel_lock(c); 02349 ast_copy_string(c->exten, exten, sizeof(c->exten)); 02350 c->priority = pri; 02351 ast_channel_unlock(c); 02352 }
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 3531 of file pbx.c.
References ast_cli(), ast_extension_match(), ast_get_context_name(), ast_get_context_registrar(), ast_get_extension_label(), ast_get_extension_name(), ast_get_extension_registrar(), ast_get_ignorepat_name(), ast_get_ignorepat_registrar(), ast_get_include_name(), ast_get_include_registrar(), ast_get_switch_data(), ast_get_switch_name(), ast_get_switch_registrar(), ast_lock_context(), ast_log(), AST_MAX_EXTENSION, AST_PBX_MAX_STACK, ast_rdlock_contexts(), ast_unlock_context(), ast_unlock_contexts(), ast_walk_context_extensions(), ast_walk_context_ignorepats(), ast_walk_context_includes(), ast_walk_context_switches(), ast_walk_contexts(), ast_walk_extension_priorities(), dialplan_counters::context_existence, el, dialplan_counters::extension_existence, LOG_NOTICE, LOG_WARNING, print_ext(), dialplan_counters::total_context, dialplan_counters::total_exten, and dialplan_counters::total_prio.
Referenced by handle_show_dialplan().
03532 { 03533 struct ast_context *c = NULL; 03534 int res = 0, old_total_exten = dpc->total_exten; 03535 03536 ast_rdlock_contexts(); 03537 03538 /* walk all contexts ... */ 03539 while ( (c = ast_walk_contexts(c)) ) { 03540 struct ast_exten *e; 03541 struct ast_include *i; 03542 struct ast_ignorepat *ip; 03543 char buf[256], buf2[256]; 03544 int context_info_printed = 0; 03545 03546 if (context && strcmp(ast_get_context_name(c), context)) 03547 continue; /* skip this one, name doesn't match */ 03548 03549 dpc->context_existence = 1; 03550 03551 ast_lock_context(c); 03552 03553 /* are we looking for exten too? if yes, we print context 03554 * only if we find our extension. 03555 * Otherwise print context even if empty ? 03556 * XXX i am not sure how the rinclude is handled. 03557 * I think it ought to go inside. 03558 */ 03559 if (!exten) { 03560 dpc->total_context++; 03561 ast_cli(fd, "[ Context '%s' created by '%s' ]\n", 03562 ast_get_context_name(c), ast_get_context_registrar(c)); 03563 context_info_printed = 1; 03564 } 03565 03566 /* walk extensions ... */ 03567 e = NULL; 03568 while ( (e = ast_walk_context_extensions(c, e)) ) { 03569 struct ast_exten *p; 03570 03571 if (exten && !ast_extension_match(ast_get_extension_name(e), exten)) 03572 continue; /* skip, extension match failed */ 03573 03574 dpc->extension_existence = 1; 03575 03576 /* may we print context info? */ 03577 if (!context_info_printed) { 03578 dpc->total_context++; 03579 if (rinclude) { /* TODO Print more info about rinclude */ 03580 ast_cli(fd, "[ Included context '%s' created by '%s' ]\n", 03581 ast_get_context_name(c), ast_get_context_registrar(c)); 03582 } else { 03583 ast_cli(fd, "[ Context '%s' created by '%s' ]\n", 03584 ast_get_context_name(c), ast_get_context_registrar(c)); 03585 } 03586 context_info_printed = 1; 03587 } 03588 dpc->total_prio++; 03589 03590 /* write extension name and first peer */ 03591 snprintf(buf, sizeof(buf), "'%s' =>", ast_get_extension_name(e)); 03592 03593 print_ext(e, buf2, sizeof(buf2)); 03594 03595 ast_cli(fd, " %-17s %-45s [%s]\n", buf, buf2, 03596 ast_get_extension_registrar(e)); 03597 03598 dpc->total_exten++; 03599 /* walk next extension peers */ 03600 p = e; /* skip the first one, we already got it */ 03601 while ( (p = ast_walk_extension_priorities(e, p)) ) { 03602 const char *el = ast_get_extension_label(p); 03603 dpc->total_prio++; 03604 if (el) 03605 snprintf(buf, sizeof(buf), " [%s]", el); 03606 else 03607 buf[0] = '\0'; 03608 print_ext(p, buf2, sizeof(buf2)); 03609 03610 ast_cli(fd," %-17s %-45s [%s]\n", buf, buf2, 03611 ast_get_extension_registrar(p)); 03612 } 03613 } 03614 03615 /* walk included and write info ... */ 03616 i = NULL; 03617 while ( (i = ast_walk_context_includes(c, i)) ) { 03618 snprintf(buf, sizeof(buf), "'%s'", ast_get_include_name(i)); 03619 if (exten) { 03620 /* Check all includes for the requested extension */ 03621 if (includecount >= AST_PBX_MAX_STACK) { 03622 ast_log(LOG_NOTICE, "Maximum include depth exceeded!\n"); 03623 } else { 03624 int dupe=0; 03625 int x; 03626 for (x=0;x<includecount;x++) { 03627 if (!strcasecmp(includes[x], ast_get_include_name(i))) { 03628 dupe++; 03629 break; 03630 } 03631 } 03632 if (!dupe) { 03633 includes[includecount] = ast_get_include_name(i); 03634 show_dialplan_helper(fd, ast_get_include_name(i), exten, dpc, i, includecount + 1, includes); 03635 } else { 03636 ast_log(LOG_WARNING, "Avoiding circular include of %s within %s\n", ast_get_include_name(i), context); 03637 } 03638 } 03639 } else { 03640 ast_cli(fd, " Include => %-45s [%s]\n", 03641 buf, ast_get_include_registrar(i)); 03642 } 03643 } 03644 03645 /* walk ignore patterns and write info ... */ 03646 ip = NULL; 03647 while ( (ip = ast_walk_context_ignorepats(c, ip)) ) { 03648 const char *ipname = ast_get_ignorepat_name(ip); 03649 char ignorepat[AST_MAX_EXTENSION]; 03650 snprintf(buf, sizeof(buf), "'%s'", ipname); 03651 snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname); 03652 if (!exten || ast_extension_match(ignorepat, exten)) { 03653 ast_cli(fd, " Ignore pattern => %-45s [%s]\n", 03654 buf, ast_get_ignorepat_registrar(ip)); 03655 } 03656 } 03657 if (!rinclude) { 03658 struct ast_sw *sw = NULL; 03659 while ( (sw = ast_walk_context_switches(c, sw)) ) { 03660 snprintf(buf, sizeof(buf), "'%s/%s'", 03661 ast_get_switch_name(sw), 03662 ast_get_switch_data(sw)); 03663 ast_cli(fd, " Alt. Switch => %-45s [%s]\n", 03664 buf, ast_get_switch_registrar(sw)); 03665 } 03666 } 03667 03668 ast_unlock_context(c); 03669 03670 /* if we print something in context, make an empty line */ 03671 if (context_info_printed) 03672 ast_cli(fd, "\r\n"); 03673 } 03674 ast_unlock_contexts(); 03675 03676 return (dpc->total_exten == old_total_exten) ? -1 : res; 03677 }
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 1135 of file pbx.c.
Referenced by pbx_retrieve_variable(), and pbx_substitute_variables_helper_full().
01136 { 01137 char *ret = workspace; 01138 int lr; /* length of the input string after the copy */ 01139 01140 ast_copy_string(workspace, value, workspace_len); /* always make a copy */ 01141 01142 lr = strlen(ret); /* compute length after copy, so we never go out of the workspace */ 01143 01144 /* Quick check if no need to do anything */ 01145 if (offset == 0 && length >= lr) /* take the whole string */ 01146 return ret; 01147 01148 if (offset < 0) { /* translate negative offset into positive ones */ 01149 offset = lr + offset; 01150 if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */ 01151 offset = 0; 01152 } 01153 01154 /* too large offset result in empty string so we know what to return */ 01155 if (offset >= lr) 01156 return ret + lr; /* the final '\0' */ 01157 01158 ret += offset; /* move to the start position */ 01159 if (length >= 0 && length < lr - offset) /* truncate if necessary */ 01160 ret[length] = '\0'; 01161 else if (length < 0) { 01162 if (lr > offset - length) /* After we remove from the front and from the rear, is there anything left? */ 01163 ret[lr + length - offset] = '\0'; 01164 else 01165 ret[0] = '\0'; 01166 } 01167 01168 return ret; 01169 }
static void wait_for_hangup | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 5373 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().
05374 { 05375 int res; 05376 struct ast_frame *f; 05377 int waittime; 05378 05379 if (ast_strlen_zero(data) || (sscanf(data, "%d", &waittime) != 1) || (waittime < 0)) 05380 waittime = -1; 05381 if (waittime > -1) { 05382 ast_safe_sleep(chan, waittime * 1000); 05383 } else do { 05384 res = ast_waitfor(chan, -1); 05385 if (res < 0) 05386 return; 05387 f = ast_read(chan); 05388 if (f) 05389 ast_frfree(f); 05390 } while(f); 05391 }
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 517 of file pbx.c.
Referenced by __ast_context_create(), __ast_context_destroy(), ast_merge_contexts_and_delete(), and ast_walk_contexts().
int countcalls [static] |
Definition at line 250 of file pbx.c.
Referenced by ast_active_calls(), decrease_call_count(), and increase_call_count().
char* days[] [static] |
struct cfextension_states extension_states[] [static] |
Referenced by ast_extension_state2str().
struct varshead globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE [static] |
char* months[] [static] |
struct ast_cli_entry pbx_cli[] [static] |
char set_global_help[] [static] |
char show_application_help[] [static] |
char show_applications_help[] [static] |
char show_dialplan_help[] [static] |
char show_function_help[] [static] |
char show_functions_help[] [static] |
char show_globals_help[] [static] |
char show_hints_help[] [static] |
char show_switches_help[] [static] |
struct ast_state_cb* statecbs |
Definition at line 532 of file pbx.c.
Referenced by ast_extension_state_add(), ast_extension_state_del(), and ast_hint_state_changed().