#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_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 3898 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().
03899 { 03900 struct ast_context *tmp, **local_contexts; 03901 int length = sizeof(struct ast_context) + strlen(name) + 1; 03902 03903 if (!extcontexts) { 03904 ast_rdlock_contexts(); 03905 local_contexts = &contexts; 03906 } else 03907 local_contexts = extcontexts; 03908 03909 for (tmp = *local_contexts; tmp; tmp = tmp->next) { 03910 if (!strcasecmp(tmp->name, name)) { 03911 if (!existsokay) { 03912 ast_log(LOG_WARNING, "Tried to register context '%s', already in use\n", name); 03913 tmp = NULL; 03914 } 03915 if (!extcontexts) 03916 ast_unlock_contexts(); 03917 return tmp; 03918 } 03919 } 03920 03921 if (!extcontexts) 03922 ast_unlock_contexts(); 03923 03924 if ((tmp = ast_calloc(1, length))) { 03925 ast_mutex_init(&tmp->lock); 03926 ast_mutex_init(&tmp->macrolock); 03927 strcpy(tmp->name, name); 03928 tmp->registrar = registrar; 03929 if (!extcontexts) 03930 ast_wrlock_contexts(); 03931 tmp->next = *local_contexts; 03932 *local_contexts = tmp; 03933 if (!extcontexts) 03934 ast_unlock_contexts(); 03935 if (option_debug) 03936 ast_log(LOG_DEBUG, "Registered context '%s'\n", tmp->name); 03937 if (option_verbose > 2) 03938 ast_verbose( VERBOSE_PREFIX_3 "Registered extension context '%s'\n", tmp->name); 03939 } 03940 03941 return tmp; 03942 }
void __ast_context_destroy | ( | struct ast_context * | con, | |
const char * | registrar | |||
) |
Definition at line 5327 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().
05328 { 05329 struct ast_context *tmp, *tmpl=NULL; 05330 struct ast_include *tmpi; 05331 struct ast_sw *sw; 05332 struct ast_exten *e, *el, *en; 05333 struct ast_ignorepat *ipi; 05334 05335 for (tmp = contexts; tmp; ) { 05336 struct ast_context *next; /* next starting point */ 05337 for (; tmp; tmpl = tmp, tmp = tmp->next) { 05338 if (option_debug) 05339 ast_log(LOG_DEBUG, "check ctx %s %s\n", tmp->name, tmp->registrar); 05340 if ( (!registrar || !strcasecmp(registrar, tmp->registrar)) && 05341 (!con || !strcasecmp(tmp->name, con->name)) ) 05342 break; /* found it */ 05343 } 05344 if (!tmp) /* not found, we are done */ 05345 break; 05346 ast_mutex_lock(&tmp->lock); 05347 if (option_debug) 05348 ast_log(LOG_DEBUG, "delete ctx %s %s\n", tmp->name, tmp->registrar); 05349 next = tmp->next; 05350 if (tmpl) 05351 tmpl->next = next; 05352 else 05353 contexts = next; 05354 /* Okay, now we're safe to let it go -- in a sense, we were 05355 ready to let it go as soon as we locked it. */ 05356 ast_mutex_unlock(&tmp->lock); 05357 for (tmpi = tmp->includes; tmpi; ) { /* Free includes */ 05358 struct ast_include *tmpil = tmpi; 05359 tmpi = tmpi->next; 05360 free(tmpil); 05361 } 05362 for (ipi = tmp->ignorepats; ipi; ) { /* Free ignorepats */ 05363 struct ast_ignorepat *ipl = ipi; 05364 ipi = ipi->next; 05365 free(ipl); 05366 } 05367 while ((sw = AST_LIST_REMOVE_HEAD(&tmp->alts, list))) 05368 free(sw); 05369 for (e = tmp->root; e;) { 05370 for (en = e->peer; en;) { 05371 el = en; 05372 en = en->peer; 05373 destroy_exten(el); 05374 } 05375 el = e; 05376 e = e->next; 05377 destroy_exten(el); 05378 } 05379 ast_mutex_destroy(&tmp->lock); 05380 free(tmp); 05381 /* if we have a specific match, we are done, otherwise continue */ 05382 tmp = con ? NULL : next; 05383 } 05384 }
static int __ast_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority, | |||
int | async | |||
) | [static] |
Definition at line 6458 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().
06459 { 06460 int (*goto_func)(struct ast_channel *chan, const char *context, const char *exten, int priority); 06461 06462 if (!chan) 06463 return -2; 06464 06465 if (context == NULL) 06466 context = chan->context; 06467 if (exten == NULL) 06468 exten = chan->exten; 06469 06470 goto_func = (async) ? ast_async_goto : ast_explicit_goto; 06471 if (ast_exists_extension(chan, context, exten, priority, chan->cid.cid_num)) 06472 return goto_func(chan, context, exten, priority); 06473 else 06474 return -3; 06475 }
static int __ast_pbx_run | ( | struct ast_channel * | c | ) | [static] |
Definition at line 2384 of file pbx.c.
References ast_channel::_softhangup, ast_channel::amaflags, ast_calloc, ast_cdr_alloc(), ast_cdr_init(), ast_cdr_start(), ast_exists_extension(), AST_FLAG_IN_AUTOLOOP, ast_log(), AST_PBX_KEEPALIVE, ast_set_flag, AST_SOFTHANGUP_ASYNCGOTO, AST_SOFTHANGUP_TIMEOUT, ast_spawn_extension(), ast_test_flag, ast_verbose(), ast_channel::cdr, ast_channel::cid, ast_callerid::cid_num, ast_channel::context, ast_pbx::dtimeout, error(), ast_channel::exten, free, LOG_DEBUG, LOG_WARNING, option_debug, option_verbose, ast_channel::pbx, ast_channel::priority, ast_pbx::rtimeout, set_ext_pri(), ast_cdr::start, and VERBOSE_PREFIX_2.
Referenced by ast_pbx_run(), and pbx_thread().
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 if (c->amaflags) { 02400 if (!c->cdr) { 02401 c->cdr = ast_cdr_alloc(); 02402 if (!c->cdr) { 02403 ast_log(LOG_WARNING, "Unable to create Call Detail Record\n"); 02404 free(c->pbx); 02405 return -1; 02406 } 02407 ast_cdr_init(c->cdr, c); 02408 } 02409 } 02410 /* Set reasonable defaults */ 02411 c->pbx->rtimeout = 10; 02412 c->pbx->dtimeout = 5; 02413 02414 autoloopflag = ast_test_flag(c, AST_FLAG_IN_AUTOLOOP); /* save value to restore at the end */ 02415 ast_set_flag(c, AST_FLAG_IN_AUTOLOOP); 02416 02417 /* Start by trying whatever the channel is set to */ 02418 if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) { 02419 /* If not successful fall back to 's' */ 02420 if (option_verbose > 1) 02421 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); 02422 /* XXX the original code used the existing priority in the call to 02423 * ast_exists_extension(), and reset it to 1 afterwards. 02424 * I believe the correct thing is to set it to 1 immediately. 02425 */ 02426 set_ext_pri(c, "s", 1); 02427 if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) { 02428 /* JK02: And finally back to default if everything else failed */ 02429 if (option_verbose > 1) 02430 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); 02431 ast_copy_string(c->context, "default", sizeof(c->context)); 02432 } 02433 } 02434 if (c->cdr && ast_tvzero(c->cdr->start)) 02435 ast_cdr_start(c->cdr); 02436 for (;;) { 02437 char dst_exten[256]; /* buffer to accumulate digits */ 02438 int pos = 0; /* XXX should check bounds */ 02439 int digit = 0; 02440 02441 /* loop on priorities in this context/exten */ 02442 while (ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) { 02443 found = 1; 02444 if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num))) { 02445 /* Something bad happened, or a hangup has been requested. */ 02446 if (strchr("0123456789ABCDEF*#", res)) { 02447 if (option_debug) 02448 ast_log(LOG_DEBUG, "Oooh, got something to jump out with ('%c')!\n", res); 02449 pos = 0; 02450 dst_exten[pos++] = digit = res; 02451 dst_exten[pos] = '\0'; 02452 break; 02453 } 02454 if (res == AST_PBX_KEEPALIVE) { 02455 if (option_debug) 02456 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name); 02457 if (option_verbose > 1) 02458 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name); 02459 error = 1; 02460 break; 02461 } 02462 if (option_debug) 02463 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 02464 if (option_verbose > 1) 02465 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 02466 if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) { 02467 c->_softhangup = 0; 02468 } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) { 02469 /* atimeout, nothing bad */ 02470 } else { 02471 if (c->cdr) 02472 ast_cdr_update(c); 02473 error = 1; 02474 break; 02475 } 02476 } 02477 if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) { 02478 c->_softhangup = 0; 02479 } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT && ast_exists_extension(c,c->context,"T",1,c->cid.cid_num)) { 02480 set_ext_pri(c, "T", 0); /* 0 will become 1 with the c->priority++; at the end */ 02481 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 02482 c->whentohangup = 0; 02483 c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT; 02484 } else if (c->_softhangup) { 02485 if (option_debug) 02486 ast_log(LOG_DEBUG, "Extension %s, priority %d returned normally even though call was hung up\n", 02487 c->exten, c->priority); 02488 error = 1; 02489 break; 02490 } 02491 c->priority++; 02492 } /* end while - from here on we can use 'break' to go out */ 02493 if (error) 02494 break; 02495 02496 /* XXX we get here on non-existing extension or a keypress or hangup ? */ 02497 02498 if (!ast_exists_extension(c, c->context, c->exten, 1, c->cid.cid_num)) { 02499 /* If there is no match at priority 1, it is not a valid extension anymore. 02500 * Try to continue at "i", 1 or exit if the latter does not exist. 02501 */ 02502 if (ast_exists_extension(c, c->context, "i", 1, c->cid.cid_num)) { 02503 if (option_verbose > 2) 02504 ast_verbose(VERBOSE_PREFIX_3 "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, c->name); 02505 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", c->exten); 02506 set_ext_pri(c, "i", 1); 02507 } else { 02508 ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n", 02509 c->name, c->exten, c->context); 02510 error = 1; /* we know what to do with it */ 02511 break; 02512 } 02513 } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) { 02514 /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */ 02515 c->_softhangup = 0; 02516 } else { /* keypress received, get more digits for a full extension */ 02517 int waittime = 0; 02518 if (digit) 02519 waittime = c->pbx->dtimeout; 02520 else if (!autofallthrough) 02521 waittime = c->pbx->rtimeout; 02522 if (!waittime) { 02523 const char *status = pbx_builtin_getvar_helper(c, "DIALSTATUS"); 02524 if (!status) 02525 status = "UNKNOWN"; 02526 if (option_verbose > 2) 02527 ast_verbose(VERBOSE_PREFIX_2 "Auto fallthrough, channel '%s' status is '%s'\n", c->name, status); 02528 if (!strcasecmp(status, "CONGESTION")) 02529 res = pbx_builtin_congestion(c, "10"); 02530 else if (!strcasecmp(status, "CHANUNAVAIL")) 02531 res = pbx_builtin_congestion(c, "10"); 02532 else if (!strcasecmp(status, "BUSY")) 02533 res = pbx_builtin_busy(c, "10"); 02534 error = 1; /* XXX disable message */ 02535 break; /* exit from the 'for' loop */ 02536 } 02537 02538 if (collect_digits(c, waittime, dst_exten, sizeof(dst_exten), pos)) 02539 break; 02540 if (ast_exists_extension(c, c->context, dst_exten, 1, c->cid.cid_num)) /* Prepare the next cycle */ 02541 set_ext_pri(c, dst_exten, 1); 02542 else { 02543 /* No such extension */ 02544 if (!ast_strlen_zero(dst_exten)) { 02545 /* An invalid extension */ 02546 if (ast_exists_extension(c, c->context, "i", 1, c->cid.cid_num)) { 02547 if (option_verbose > 2) 02548 ast_verbose( VERBOSE_PREFIX_3 "Invalid extension '%s' in context '%s' on %s\n", dst_exten, c->context, c->name); 02549 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", dst_exten); 02550 set_ext_pri(c, "i", 1); 02551 } else { 02552 ast_log(LOG_WARNING, "Invalid extension '%s', but no rule 'i' in context '%s'\n", dst_exten, c->context); 02553 found = 1; /* XXX disable message */ 02554 break; 02555 } 02556 } else { 02557 /* A simple timeout */ 02558 if (ast_exists_extension(c, c->context, "t", 1, c->cid.cid_num)) { 02559 if (option_verbose > 2) 02560 ast_verbose( VERBOSE_PREFIX_3 "Timeout on %s\n", c->name); 02561 set_ext_pri(c, "t", 1); 02562 } else { 02563 ast_log(LOG_WARNING, "Timeout, but no rule 't' in context '%s'\n", c->context); 02564 found = 1; /* XXX disable message */ 02565 break; 02566 } 02567 } 02568 } 02569 if (c->cdr) { 02570 if (option_verbose > 2) 02571 ast_verbose(VERBOSE_PREFIX_2 "CDR updated on %s\n",c->name); 02572 ast_cdr_update(c); 02573 } 02574 } 02575 } 02576 if (!found && !error) 02577 ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name); 02578 if (res != AST_PBX_KEEPALIVE) 02579 ast_softhangup(c, c->hangupcause ? c->hangupcause : AST_CAUSE_NORMAL_CLEARING); 02580 if ((res != AST_PBX_KEEPALIVE) && ast_exists_extension(c, c->context, "h", 1, c->cid.cid_num)) { 02581 if (c->cdr && ast_opt_end_cdr_before_h_exten) 02582 ast_cdr_end(c->cdr); 02583 set_ext_pri(c, "h", 1); 02584 while(ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) { 02585 if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num))) { 02586 /* Something bad happened, or a hangup has been requested. */ 02587 if (option_debug) 02588 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 02589 if (option_verbose > 1) 02590 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 02591 break; 02592 } 02593 c->priority++; 02594 } 02595 } 02596 ast_set2_flag(c, autoloopflag, AST_FLAG_IN_AUTOLOOP); 02597 02598 pbx_destroy(c->pbx); 02599 c->pbx = NULL; 02600 if (res != AST_PBX_KEEPALIVE) 02601 ast_hangup(c); 02602 return 0; 02603 }
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 4710 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().
04712 { 04713 struct ast_exten *ep; 04714 04715 for (ep = NULL; e ; ep = e, e = e->peer) { 04716 if (e->priority >= tmp->priority) 04717 break; 04718 } 04719 if (!e) { /* go at the end, and ep is surely set because the list is not empty */ 04720 ep->peer = tmp; 04721 return 0; /* success */ 04722 } 04723 if (e->priority == tmp->priority) { 04724 /* Can't have something exactly the same. Is this a 04725 replacement? If so, replace, otherwise, bonk. */ 04726 if (!replace) { 04727 ast_log(LOG_WARNING, "Unable to register extension '%s', priority %d in '%s', already in use\n", tmp->exten, tmp->priority, con->name); 04728 if (tmp->datad) 04729 tmp->datad(tmp->data); 04730 free(tmp); 04731 return -1; 04732 } 04733 /* we are replacing e, so copy the link fields and then update 04734 * whoever pointed to e to point to us 04735 */ 04736 tmp->next = e->next; /* not meaningful if we are not first in the peer list */ 04737 tmp->peer = e->peer; /* always meaningful */ 04738 if (ep) /* We're in the peer list, just insert ourselves */ 04739 ep->peer = tmp; 04740 else if (el) /* We're the first extension. Take over e's functions */ 04741 el->next = tmp; 04742 else /* We're the very first extension. */ 04743 con->root = tmp; 04744 if (tmp->priority == PRIORITY_HINT) 04745 ast_change_hint(e,tmp); 04746 /* Destroy the old one */ 04747 if (e->datad) 04748 e->datad(e->data); 04749 free(e); 04750 } else { /* Slip ourselves in just before e */ 04751 tmp->peer = e; 04752 tmp->next = e->next; /* extension chain, or NULL if e is not the first extension */ 04753 if (ep) /* Easy enough, we're just in the peer list */ 04754 ep->peer = tmp; 04755 else { /* we are the first in some peer list, so link in the ext list */ 04756 if (el) 04757 el->next = tmp; /* in the middle... */ 04758 else 04759 con->root = tmp; /* ... or at the head */ 04760 e->next = NULL; /* e is no more at the head, so e->next must be reset */ 04761 } 04762 /* And immediately return success. */ 04763 if (tmp->priority == PRIORITY_HINT) 04764 ast_add_hint(tmp); 04765 } 04766 return 0; 04767 }
int ast_active_calls | ( | void | ) |
Retrieve the number of active calls.
Definition at line 2708 of file pbx.c.
References countcalls.
Referenced by handle_chanlist(), and handle_chanlist_deprecated().
02709 { 02710 return countcalls; 02711 }
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 4585 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().
04588 { 04589 int ret = -1; 04590 struct ast_context *c = find_context_locked(context); 04591 04592 if (c) { 04593 ret = ast_add_extension2(c, replace, extension, priority, label, callerid, 04594 application, data, datad, registrar); 04595 ast_unlock_contexts(); 04596 } 04597 return ret; 04598 }
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 4794 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().
04798 { 04799 /* 04800 * Sort extensions (or patterns) according to the rules indicated above. 04801 * These are implemented by the function ext_cmp()). 04802 * All priorities for the same ext/pattern/cid are kept in a list, 04803 * using the 'peer' field as a link field.. 04804 */ 04805 struct ast_exten *tmp, *e, *el = NULL; 04806 int res; 04807 int length; 04808 char *p; 04809 char expand_buf[VAR_BUF_SIZE] = { 0, }; 04810 04811 /* if we are adding a hint, and there are global variables, and the hint 04812 contains variable references, then expand them 04813 */ 04814 ast_mutex_lock(&globalslock); 04815 if (priority == PRIORITY_HINT && AST_LIST_FIRST(&globals) && strstr(application, "${")) { 04816 pbx_substitute_variables_varshead(&globals, application, expand_buf, sizeof(expand_buf)); 04817 application = expand_buf; 04818 } 04819 ast_mutex_unlock(&globalslock); 04820 04821 length = sizeof(struct ast_exten); 04822 length += strlen(extension) + 1; 04823 length += strlen(application) + 1; 04824 if (label) 04825 length += strlen(label) + 1; 04826 if (callerid) 04827 length += strlen(callerid) + 1; 04828 else 04829 length ++; /* just the '\0' */ 04830 04831 /* Be optimistic: Build the extension structure first */ 04832 if (!(tmp = ast_calloc(1, length))) 04833 return -1; 04834 04835 /* use p as dst in assignments, as the fields are const char * */ 04836 p = tmp->stuff; 04837 if (label) { 04838 tmp->label = p; 04839 strcpy(p, label); 04840 p += strlen(label) + 1; 04841 } 04842 tmp->exten = p; 04843 p += ext_strncpy(p, extension, strlen(extension) + 1) + 1; 04844 tmp->priority = priority; 04845 tmp->cidmatch = p; /* but use p for assignments below */ 04846 if (callerid) { 04847 p += ext_strncpy(p, callerid, strlen(callerid) + 1) + 1; 04848 tmp->matchcid = 1; 04849 } else { 04850 *p++ = '\0'; 04851 tmp->matchcid = 0; 04852 } 04853 tmp->app = p; 04854 strcpy(p, application); 04855 tmp->parent = con; 04856 tmp->data = data; 04857 tmp->datad = datad; 04858 tmp->registrar = registrar; 04859 04860 ast_mutex_lock(&con->lock); 04861 res = 0; /* some compilers will think it is uninitialized otherwise */ 04862 for (e = con->root; e; el = e, e = e->next) { /* scan the extension list */ 04863 res = ext_cmp(e->exten, extension); 04864 if (res == 0) { /* extension match, now look at cidmatch */ 04865 if (!e->matchcid && !tmp->matchcid) 04866 res = 0; 04867 else if (tmp->matchcid && !e->matchcid) 04868 res = 1; 04869 else if (e->matchcid && !tmp->matchcid) 04870 res = -1; 04871 else 04872 res = strcasecmp(e->cidmatch, tmp->cidmatch); 04873 } 04874 if (res >= 0) 04875 break; 04876 } 04877 if (e && res == 0) { /* exact match, insert in the pri chain */ 04878 res = add_pri(con, tmp, el, e, replace); 04879 ast_mutex_unlock(&con->lock); 04880 if (res < 0) { 04881 errno = EEXIST; /* XXX do we care ? */ 04882 return 0; /* XXX should we return -1 maybe ? */ 04883 } 04884 } else { 04885 /* 04886 * not an exact match, this is the first entry with this pattern, 04887 * so insert in the main list right before 'e' (if any) 04888 */ 04889 tmp->next = e; 04890 if (el) 04891 el->next = tmp; 04892 else 04893 con->root = tmp; 04894 ast_mutex_unlock(&con->lock); 04895 if (tmp->priority == PRIORITY_HINT) 04896 ast_add_hint(tmp); 04897 } 04898 if (option_debug) { 04899 if (tmp->matchcid) { 04900 if (option_debug) 04901 ast_log(LOG_DEBUG, "Added extension '%s' priority %d (CID match '%s') to %s\n", 04902 tmp->exten, tmp->priority, tmp->cidmatch, con->name); 04903 } else { 04904 if (option_debug) 04905 ast_log(LOG_DEBUG, "Added extension '%s' priority %d to %s\n", 04906 tmp->exten, tmp->priority, con->name); 04907 } 04908 } 04909 if (option_verbose > 2) { 04910 if (tmp->matchcid) { 04911 ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d (CID match '%s')to %s\n", 04912 tmp->exten, tmp->priority, tmp->cidmatch, con->name); 04913 } else { 04914 ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d to %s\n", 04915 tmp->exten, tmp->priority, con->name); 04916 } 04917 } 04918 return 0; 04919 }
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 4623 of file pbx.c.
References ast_channel::_state, ast_channel::amaflags, ast_cdr_discard(), ast_cdr_dup(), ast_channel_alloc(), ast_channel_lock, ast_channel_masquerade(), ast_channel_unlock, ast_do_masquerade(), ast_explicit_goto(), ast_hangup(), ast_log(), ast_pbx_start(), AST_SOFTHANGUP_ASYNCGOTO, ast_softhangup_nolock(), ast_channel::cdr, ast_channel::context, ast_channel::exten, LOG_WARNING, ast_channel::pbx, ast_channel::readformat, S_OR, and ast_channel::writeformat.
Referenced by __ast_goto_if_exists(), action_redirect(), ast_async_goto_by_name(), builtin_blindtransfer(), console_transfer(), console_transfer_deprecated(), handle_request_bye(), handle_request_refer(), process_ast_dsp(), socket_process(), and zt_handle_dtmfup().
04624 { 04625 int res = 0; 04626 04627 ast_channel_lock(chan); 04628 04629 if (chan->pbx) { /* This channel is currently in the PBX */ 04630 ast_explicit_goto(chan, context, exten, priority); 04631 ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO); 04632 } else { 04633 /* In order to do it when the channel doesn't really exist within 04634 the PBX, we have to make a new channel, masquerade, and start the PBX 04635 at the new location */ 04636 struct ast_channel *tmpchan = ast_channel_alloc(0, chan->_state, 0, 0, chan->accountcode, chan->exten, chan->context, chan->amaflags, "AsyncGoto/%s", chan->name); 04637 if (!tmpchan) { 04638 res = -1; 04639 } else { 04640 if (chan->cdr) { 04641 ast_cdr_discard(tmpchan->cdr); 04642 tmpchan->cdr = ast_cdr_dup(chan->cdr); /* share the love */ 04643 } 04644 /* Make formats okay */ 04645 tmpchan->readformat = chan->readformat; 04646 tmpchan->writeformat = chan->writeformat; 04647 /* Setup proper location */ 04648 ast_explicit_goto(tmpchan, 04649 S_OR(context, chan->context), S_OR(exten, chan->exten), priority); 04650 04651 /* Masquerade into temp channel */ 04652 ast_channel_masquerade(tmpchan, chan); 04653 04654 /* Grab the locks and get going */ 04655 ast_channel_lock(tmpchan); 04656 ast_do_masquerade(tmpchan); 04657 ast_channel_unlock(tmpchan); 04658 /* Start the PBX going on our stolen channel */ 04659 if (ast_pbx_start(tmpchan)) { 04660 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name); 04661 ast_hangup(tmpchan); 04662 res = -1; 04663 } 04664 } 04665 } 04666 ast_channel_unlock(chan); 04667 return res; 04668 }
int ast_async_goto_by_name | ( | const char * | channame, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 4670 of file pbx.c.
References ast_async_goto(), ast_channel_unlock, and ast_get_channel_by_name_locked().
04671 { 04672 struct ast_channel *chan; 04673 int res = -1; 04674 04675 chan = ast_get_channel_by_name_locked(channame); 04676 if (chan) { 04677 res = ast_async_goto(chan, context, exten, priority); 04678 ast_channel_unlock(chan); 04679 } 04680 return res; 04681 }
int ast_async_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 6482 of file pbx.c.
References __ast_goto_if_exists().
Referenced by asyncgoto_exec().
06483 { 06484 return __ast_goto_if_exists(chan, context, exten, priority, 1); 06485 }
int ast_build_timing | ( | struct ast_timing * | i, | |
const char * | info_in | |||
) |
Definition at line 4268 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().
04269 { 04270 char info_save[256]; 04271 char *info; 04272 04273 /* Check for empty just in case */ 04274 if (ast_strlen_zero(info_in)) 04275 return 0; 04276 /* make a copy just in case we were passed a static string */ 04277 ast_copy_string(info_save, info_in, sizeof(info_save)); 04278 info = info_save; 04279 /* Assume everything except time */ 04280 i->monthmask = 0xfff; /* 12 bits */ 04281 i->daymask = 0x7fffffffU; /* 31 bits */ 04282 i->dowmask = 0x7f; /* 7 bits */ 04283 /* on each call, use strsep() to move info to the next argument */ 04284 get_timerange(i, strsep(&info, "|")); 04285 if (info) 04286 i->dowmask = get_range(strsep(&info, "|"), 7, days, "day of week"); 04287 if (info) 04288 i->daymask = get_range(strsep(&info, "|"), 31, NULL, "day"); 04289 if (info) 04290 i->monthmask = get_range(strsep(&info, "|"), 12, months, "month"); 04291 return 1; 04292 }
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 4294 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().
04295 { 04296 struct tm tm; 04297 time_t t = time(NULL); 04298 04299 ast_localtime(&t, &tm, NULL); 04300 04301 /* If it's not the right month, return */ 04302 if (!(i->monthmask & (1 << tm.tm_mon))) 04303 return 0; 04304 04305 /* If it's not that time of the month.... */ 04306 /* Warning, tm_mday has range 1..31! */ 04307 if (!(i->daymask & (1 << (tm.tm_mday-1)))) 04308 return 0; 04309 04310 /* If it's not the right day of the week */ 04311 if (!(i->dowmask & (1 << tm.tm_wday))) 04312 return 0; 04313 04314 /* Sanity check the hour just to be safe */ 04315 if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) { 04316 ast_log(LOG_WARNING, "Insane time...\n"); 04317 return 0; 04318 } 04319 04320 /* Now the tough part, we calculate if it fits 04321 in the right time based on min/hour */ 04322 if (!(i->minmask[tm.tm_hour] & (1 << (tm.tm_min / 2)))) 04323 return 0; 04324 04325 /* If we got this far, then we're good */ 04326 return 1; 04327 }
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 4521 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().
04522 { 04523 int ret = -1; 04524 struct ast_context *c = find_context_locked(context); 04525 04526 if (c) { 04527 ret = ast_context_add_ignorepat2(c, value, registrar); 04528 ast_unlock_contexts(); 04529 } 04530 return ret; 04531 }
int ast_context_add_ignorepat2 | ( | struct ast_context * | con, | |
const char * | value, | |||
const char * | registrar | |||
) |
Definition at line 4533 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().
04534 { 04535 struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL; 04536 int length; 04537 length = sizeof(struct ast_ignorepat); 04538 length += strlen(value) + 1; 04539 if (!(ignorepat = ast_calloc(1, length))) 04540 return -1; 04541 /* The cast to char * is because we need to write the initial value. 04542 * The field is not supposed to be modified otherwise 04543 */ 04544 strcpy((char *)ignorepat->pattern, value); 04545 ignorepat->next = NULL; 04546 ignorepat->registrar = registrar; 04547 ast_mutex_lock(&con->lock); 04548 for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) { 04549 ignorepatl = ignorepatc; 04550 if (!strcasecmp(ignorepatc->pattern, value)) { 04551 /* Already there */ 04552 ast_mutex_unlock(&con->lock); 04553 errno = EEXIST; 04554 return -1; 04555 } 04556 } 04557 if (ignorepatl) 04558 ignorepatl->next = ignorepat; 04559 else 04560 con->ignorepats = ignorepat; 04561 ast_mutex_unlock(&con->lock); 04562 return 0; 04563 04564 }
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 4074 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().
04075 { 04076 int ret = -1; 04077 struct ast_context *c = find_context_locked(context); 04078 04079 if (c) { 04080 ret = ast_context_add_include2(c, include, registrar); 04081 ast_unlock_contexts(); 04082 } 04083 return ret; 04084 }
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 4336 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().
04338 { 04339 struct ast_include *new_include; 04340 char *c; 04341 struct ast_include *i, *il = NULL; /* include, include_last */ 04342 int length; 04343 char *p; 04344 04345 length = sizeof(struct ast_include); 04346 length += 2 * (strlen(value) + 1); 04347 04348 /* allocate new include structure ... */ 04349 if (!(new_include = ast_calloc(1, length))) 04350 return -1; 04351 /* Fill in this structure. Use 'p' for assignments, as the fields 04352 * in the structure are 'const char *' 04353 */ 04354 p = new_include->stuff; 04355 new_include->name = p; 04356 strcpy(p, value); 04357 p += strlen(value) + 1; 04358 new_include->rname = p; 04359 strcpy(p, value); 04360 /* Strip off timing info, and process if it is there */ 04361 if ( (c = strchr(p, '|')) ) { 04362 *c++ = '\0'; 04363 new_include->hastime = ast_build_timing(&(new_include->timing), c); 04364 } 04365 new_include->next = NULL; 04366 new_include->registrar = registrar; 04367 04368 ast_mutex_lock(&con->lock); 04369 04370 /* ... go to last include and check if context is already included too... */ 04371 for (i = con->includes; i; i = i->next) { 04372 if (!strcasecmp(i->name, new_include->name)) { 04373 free(new_include); 04374 ast_mutex_unlock(&con->lock); 04375 errno = EEXIST; 04376 return -1; 04377 } 04378 il = i; 04379 } 04380 04381 /* ... include new context into context list, unlock, return */ 04382 if (il) 04383 il->next = new_include; 04384 else 04385 con->includes = new_include; 04386 if (option_verbose > 2) 04387 ast_verbose(VERBOSE_PREFIX_3 "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con)); 04388 ast_mutex_unlock(&con->lock); 04389 04390 return 0; 04391 }
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 4398 of file pbx.c.
References ast_context_add_switch2(), ast_unlock_contexts(), and find_context_locked().
04399 { 04400 int ret = -1; 04401 struct ast_context *c = find_context_locked(context); 04402 04403 if (c) { /* found, add switch to this context */ 04404 ret = ast_context_add_switch2(c, sw, data, eval, registrar); 04405 ast_unlock_contexts(); 04406 } 04407 return ret; 04408 }
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 4417 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().
04419 { 04420 struct ast_sw *new_sw; 04421 struct ast_sw *i; 04422 int length; 04423 char *p; 04424 04425 length = sizeof(struct ast_sw); 04426 length += strlen(value) + 1; 04427 if (data) 04428 length += strlen(data); 04429 length++; 04430 04431 /* allocate new sw structure ... */ 04432 if (!(new_sw = ast_calloc(1, length))) 04433 return -1; 04434 /* ... fill in this structure ... */ 04435 p = new_sw->stuff; 04436 new_sw->name = p; 04437 strcpy(new_sw->name, value); 04438 p += strlen(value) + 1; 04439 new_sw->data = p; 04440 if (data) { 04441 strcpy(new_sw->data, data); 04442 p += strlen(data) + 1; 04443 } else { 04444 strcpy(new_sw->data, ""); 04445 p++; 04446 } 04447 new_sw->eval = eval; 04448 new_sw->registrar = registrar; 04449 04450 /* ... try to lock this context ... */ 04451 ast_mutex_lock(&con->lock); 04452 04453 /* ... go to last sw and check if context is already swd too... */ 04454 AST_LIST_TRAVERSE(&con->alts, i, list) { 04455 if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) { 04456 free(new_sw); 04457 ast_mutex_unlock(&con->lock); 04458 errno = EEXIST; 04459 return -1; 04460 } 04461 } 04462 04463 /* ... sw new context into context list, unlock, return */ 04464 AST_LIST_INSERT_TAIL(&con->alts, new_sw, list); 04465 04466 if (option_verbose > 2) 04467 ast_verbose(VERBOSE_PREFIX_3 "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con)); 04468 04469 ast_mutex_unlock(&con->lock); 04470 04471 return 0; 04472 }
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 3944 of file pbx.c.
References __ast_context_create().
Referenced by do_parking_thread(), park_call_full(), and set_config().
03945 { 03946 return __ast_context_create(extcontexts, name, registrar, 0); 03947 }
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 5386 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().
05387 { 05388 ast_wrlock_contexts(); 05389 __ast_context_destroy(con,registrar); 05390 ast_unlock_contexts(); 05391 }
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 3949 of file pbx.c.
References __ast_context_create().
Referenced by pbx_load_config(), and pbx_load_users().
03950 { 03951 return __ast_context_create(extcontexts, name, registrar, 1); 03952 }
int ast_context_lockmacro | ( | const char * | context | ) |
locks the macrolock in the given given context
Definition at line 2945 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().
02946 { 02947 struct ast_context *c = NULL; 02948 int ret = -1; 02949 02950 ast_rdlock_contexts(); 02951 02952 while ((c = ast_walk_contexts(c))) { 02953 if (!strcmp(ast_get_context_name(c), context)) { 02954 ret = 0; 02955 break; 02956 } 02957 } 02958 02959 ast_unlock_contexts(); 02960 02961 /* if we found context, lock macrolock */ 02962 if (ret == 0) 02963 ret = ast_mutex_lock(&c->macrolock); 02964 02965 return ret; 02966 }
int ast_context_remove_extension | ( | const char * | context, | |
const char * | extension, | |||
int | priority, | |||
const char * | registrar | |||
) |
Simply remove extension from context.
context | context to remove extension from | |
extension | which extension to remove | |
priority | priority of extension to remove | |
registrar | registrar of the extension |
0 | on success | |
-1 | on failure |
Definition at line 2846 of file pbx.c.
References ast_context_remove_extension2(), ast_unlock_contexts(), and find_context_locked().
Referenced by destroy_station(), destroy_trunk(), handle_context_remove_extension(), handle_context_remove_extension_deprecated(), and register_peer_exten().
02847 { 02848 int ret = -1; /* default error return */ 02849 struct ast_context *c = find_context_locked(context); 02850 02851 if (c) { /* ... remove extension ... */ 02852 ret = ast_context_remove_extension2(c, extension, priority, registrar); 02853 ast_unlock_contexts(); 02854 } 02855 return ret; 02856 }
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 2868 of file pbx.c.
References ast_mutex_lock(), ast_mutex_unlock(), destroy_exten(), exten, ast_context::lock, ast_exten::next, ast_exten::peer, and ast_context::root.
Referenced by ast_context_remove_extension(), do_parking_thread(), and park_exec().
02869 { 02870 struct ast_exten *exten, *prev_exten = NULL; 02871 struct ast_exten *peer; 02872 02873 ast_mutex_lock(&con->lock); 02874 02875 /* scan the extension list to find matching extension-registrar */ 02876 for (exten = con->root; exten; prev_exten = exten, exten = exten->next) { 02877 if (!strcmp(exten->exten, extension) && 02878 (!registrar || !strcmp(exten->registrar, registrar))) 02879 break; 02880 } 02881 if (!exten) { 02882 /* we can't find right extension */ 02883 ast_mutex_unlock(&con->lock); 02884 return -1; 02885 } 02886 02887 /* should we free all peers in this extension? (priority == 0)? */ 02888 if (priority == 0) { 02889 /* remove this extension from context list */ 02890 if (prev_exten) 02891 prev_exten->next = exten->next; 02892 else 02893 con->root = exten->next; 02894 02895 /* fire out all peers */ 02896 while ( (peer = exten) ) { 02897 exten = peer->peer; /* prepare for next entry */ 02898 destroy_exten(peer); 02899 } 02900 } else { 02901 /* scan the priority list to remove extension with exten->priority == priority */ 02902 struct ast_exten *previous_peer = NULL; 02903 02904 for (peer = exten; peer; previous_peer = peer, peer = peer->peer) { 02905 if (peer->priority == priority && 02906 (!registrar || !strcmp(peer->registrar, registrar) )) 02907 break; /* found our priority */ 02908 } 02909 if (!peer) { /* not found */ 02910 ast_mutex_unlock(&con->lock); 02911 return -1; 02912 } 02913 /* we are first priority extension? */ 02914 if (!previous_peer) { 02915 /* 02916 * We are first in the priority chain, so must update the extension chain. 02917 * The next node is either the next priority or the next extension 02918 */ 02919 struct ast_exten *next_node = peer->peer ? peer->peer : peer->next; 02920 02921 if (!prev_exten) /* change the root... */ 02922 con->root = next_node; 02923 else 02924 prev_exten->next = next_node; /* unlink */ 02925 if (peer->peer) /* XXX update the new head of the pri list */ 02926 peer->peer->next = peer->next; 02927 } else { /* easy, we are not first priority in extension */ 02928 previous_peer->peer = peer->peer; 02929 } 02930 02931 /* now, free whole priority extension */ 02932 destroy_exten(peer); 02933 /* XXX should we return -1 ? */ 02934 } 02935 ast_mutex_unlock(&con->lock); 02936 return 0; 02937 }
int ast_context_remove_ignorepat | ( | const char * | context, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 4478 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().
04479 { 04480 int ret = -1; 04481 struct ast_context *c = find_context_locked(context); 04482 04483 if (c) { 04484 ret = ast_context_remove_ignorepat2(c, ignorepat, registrar); 04485 ast_unlock_contexts(); 04486 } 04487 return ret; 04488 }
int ast_context_remove_ignorepat2 | ( | struct ast_context * | con, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 4490 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().
04491 { 04492 struct ast_ignorepat *ip, *ipl = NULL; 04493 04494 ast_mutex_lock(&con->lock); 04495 04496 for (ip = con->ignorepats; ip; ip = ip->next) { 04497 if (!strcmp(ip->pattern, ignorepat) && 04498 (!registrar || (registrar == ip->registrar))) { 04499 if (ipl) { 04500 ipl->next = ip->next; 04501 free(ip); 04502 } else { 04503 con->ignorepats = ip->next; 04504 free(ip); 04505 } 04506 ast_mutex_unlock(&con->lock); 04507 return 0; 04508 } 04509 ipl = ip; 04510 } 04511 04512 ast_mutex_unlock(&con->lock); 04513 errno = EINVAL; 04514 return -1; 04515 }
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 2742 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().
02743 { 02744 int ret = -1; 02745 struct ast_context *c = find_context_locked(context); 02746 02747 if (c) { 02748 /* found, remove include from this context ... */ 02749 ret = ast_context_remove_include2(c, include, registrar); 02750 ast_unlock_contexts(); 02751 } 02752 return ret; 02753 }
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 2763 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().
02764 { 02765 struct ast_include *i, *pi = NULL; 02766 int ret = -1; 02767 02768 ast_mutex_lock(&con->lock); 02769 02770 /* find our include */ 02771 for (i = con->includes; i; pi = i, i = i->next) { 02772 if (!strcmp(i->name, include) && 02773 (!registrar || !strcmp(i->registrar, registrar))) { 02774 /* remove from list */ 02775 if (pi) 02776 pi->next = i->next; 02777 else 02778 con->includes = i->next; 02779 /* free include and return */ 02780 free(i); 02781 ret = 0; 02782 break; 02783 } 02784 } 02785 02786 ast_mutex_unlock(&con->lock); 02787 return ret; 02788 }
int ast_context_remove_switch | ( | const char * | context, | |
const char * | sw, | |||
const char * | data, | |||
const char * | registrar | |||
) |
Remove a switch.
Definition at line 2795 of file pbx.c.
References ast_context_remove_switch2(), ast_unlock_contexts(), and find_context_locked().
02796 { 02797 int ret = -1; /* default error return */ 02798 struct ast_context *c = find_context_locked(context); 02799 02800 if (c) { 02801 /* remove switch from this context ... */ 02802 ret = ast_context_remove_switch2(c, sw, data, registrar); 02803 ast_unlock_contexts(); 02804 } 02805 return ret; 02806 }
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 2816 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().
02817 { 02818 struct ast_sw *i; 02819 int ret = -1; 02820 02821 ast_mutex_lock(&con->lock); 02822 02823 /* walk switches */ 02824 AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) { 02825 if (!strcmp(i->name, sw) && !strcmp(i->data, data) && 02826 (!registrar || !strcmp(i->registrar, registrar))) { 02827 /* found, remove from list */ 02828 AST_LIST_REMOVE_CURRENT(&con->alts, list); 02829 free(i); /* free switch and return */ 02830 ret = 0; 02831 break; 02832 } 02833 } 02834 AST_LIST_TRAVERSE_SAFE_END 02835 02836 ast_mutex_unlock(&con->lock); 02837 02838 return ret; 02839 }
int ast_context_unlockmacro | ( | const char * | context | ) |
Unlocks the macrolock in the given context.
Definition at line 2973 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().
02974 { 02975 struct ast_context *c = NULL; 02976 int ret = -1; 02977 02978 ast_rdlock_contexts(); 02979 02980 while ((c = ast_walk_contexts(c))) { 02981 if (!strcmp(ast_get_context_name(c), context)) { 02982 ret = 0; 02983 break; 02984 } 02985 } 02986 02987 ast_unlock_contexts(); 02988 02989 /* if we found context, unlock macrolock */ 02990 if (ret == 0) 02991 ret = ast_mutex_unlock(&c->macrolock); 02992 02993 return ret; 02994 }
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 6439 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().
06440 { 06441 struct ast_include *inc = NULL; 06442 int res = 0; 06443 06444 while ( (inc = ast_walk_context_includes(con, inc)) ) { 06445 if (ast_context_find(inc->rname)) 06446 continue; 06447 06448 res = -1; 06449 ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n", 06450 ast_get_context_name(con), inc->rname); 06451 break; 06452 } 06453 06454 return res; 06455 }
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(), console_dial(), console_dial_deprecated(), console_transfer(), console_transfer_deprecated(), 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(), waitstream_core(), and zt_handle_dtmfup().
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 4600 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().
04601 { 04602 if (!chan) 04603 return -1; 04604 04605 ast_channel_lock(chan); 04606 04607 if (!ast_strlen_zero(context)) 04608 ast_copy_string(chan->context, context, sizeof(chan->context)); 04609 if (!ast_strlen_zero(exten)) 04610 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 04611 if (priority > -1) { 04612 chan->priority = priority; 04613 /* see flag description in channel.h for explanation */ 04614 if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP)) 04615 chan->priority--; 04616 } 04617 04618 ast_channel_unlock(chan); 04619 04620 return 0; 04621 }
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 6296 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 6334 of file pbx.c.
References ast_context::registrar.
Referenced by handle_save_dialplan(), and show_dialplan_helper().
06335 { 06336 return c ? c->registrar : NULL; 06337 }
const char* ast_get_extension_app | ( | struct ast_exten * | e | ) |
Definition at line 6364 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().
06365 { 06366 return e ? e->app : NULL; 06367 }
void* ast_get_extension_app_data | ( | struct ast_exten * | e | ) |
Definition at line 6369 of file pbx.c.
References ast_exten::data.
Referenced by _macro_exec(), ast_get_hint(), handle_save_dialplan(), and print_ext().
06370 { 06371 return e ? e->data : NULL; 06372 }
const char* ast_get_extension_cidmatch | ( | struct ast_exten * | e | ) |
Definition at line 6359 of file pbx.c.
References ast_exten::cidmatch.
Referenced by find_matching_priority(), and handle_save_dialplan().
06360 { 06361 return e ? e->cidmatch : NULL; 06362 }
struct ast_context* ast_get_extension_context | ( | struct ast_exten * | exten | ) |
const char* ast_get_extension_label | ( | struct ast_exten * | exten | ) |
Definition at line 6311 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 6354 of file pbx.c.
References ast_exten::matchcid.
Referenced by find_matching_priority(), and handle_save_dialplan().
06355 { 06356 return e ? e->matchcid : 0; 06357 }
const char* ast_get_extension_name | ( | struct ast_exten * | exten | ) |
Definition at line 6306 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 6326 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 6339 of file pbx.c.
References ast_exten::registrar.
Referenced by handle_save_dialplan(), and show_dialplan_helper().
06340 { 06341 return e ? e->registrar : NULL; 06342 }
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 6321 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().
06322 { 06323 return ip ? ip->pattern : NULL; 06324 }
const char* ast_get_ignorepat_registrar | ( | struct ast_ignorepat * | ip | ) |
Definition at line 6349 of file pbx.c.
References ast_ignorepat::registrar.
Referenced by handle_save_dialplan(), and show_dialplan_helper().
06350 { 06351 return ip ? ip->registrar : NULL; 06352 }
const char* ast_get_include_name | ( | struct ast_include * | inc | ) |
Definition at line 6316 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().
06317 { 06318 return inc ? inc->name : NULL; 06319 }
const char* ast_get_include_registrar | ( | struct ast_include * | i | ) |
Definition at line 6344 of file pbx.c.
References ast_include::registrar.
Referenced by handle_save_dialplan(), and show_dialplan_helper().
06345 { 06346 return i ? i->registrar : NULL; 06347 }
const char* ast_get_switch_data | ( | struct ast_sw * | sw | ) |
Definition at line 6379 of file pbx.c.
References ast_sw::data.
Referenced by handle_save_dialplan(), and show_dialplan_helper().
06380 { 06381 return sw ? sw->data : NULL; 06382 }
const char* ast_get_switch_name | ( | struct ast_sw * | sw | ) |
Definition at line 6374 of file pbx.c.
References ast_sw::name.
Referenced by handle_save_dialplan(), and show_dialplan_helper().
06375 { 06376 return sw ? sw->name : NULL; 06377 }
const char* ast_get_switch_registrar | ( | struct ast_sw * | sw | ) |
Definition at line 6384 of file pbx.c.
References ast_sw::registrar.
Referenced by handle_save_dialplan(), and show_dialplan_helper().
06385 { 06386 return sw ? sw->registrar : NULL; 06387 }
int ast_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 6477 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().
06478 { 06479 return __ast_goto_if_exists(chan, context, exten, priority, 0); 06480 }
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 4566 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().
04567 { 04568 struct ast_context *con = ast_context_find(context); 04569 if (con) { 04570 struct ast_ignorepat *pat; 04571 for (pat = con->ignorepats; pat; pat = pat->next) { 04572 if (ast_extension_match(pat->pattern, pattern)) 04573 return 1; 04574 } 04575 } 04576 04577 return 0; 04578 }
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 6283 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().
06284 { 06285 return ast_mutex_lock(&con->lock); 06286 }
int ast_lock_contexts | ( | void | ) |
Locks the context list.
0 | on success | |
-1 | on error |
Definition at line 6260 of file pbx.c.
References ast_rwlock_wrlock().
Referenced by find_matching_endwhile().
06261 { 06262 return ast_rwlock_wrlock(&conlock); 06263 }
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 3967 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().
03968 { 03969 struct ast_context *tmp, *lasttmp = NULL; 03970 struct store_hints store = AST_LIST_HEAD_INIT_VALUE; 03971 struct store_hint *this; 03972 struct ast_hint *hint; 03973 struct ast_exten *exten; 03974 int length; 03975 struct ast_state_cb *thiscb, *prevcb; 03976 03977 /* it is very important that this function hold the hint list lock _and_ the conlock 03978 during its operation; not only do we need to ensure that the list of contexts 03979 and extensions does not change, but also that no hint callbacks (watchers) are 03980 added or removed during the merge/delete process 03981 03982 in addition, the locks _must_ be taken in this order, because there are already 03983 other code paths that use this order 03984 */ 03985 ast_wrlock_contexts(); 03986 AST_LIST_LOCK(&hints); 03987 03988 /* preserve all watchers for hints associated with this registrar */ 03989 AST_LIST_TRAVERSE(&hints, hint, list) { 03990 if (hint->callbacks && !strcmp(registrar, hint->exten->parent->registrar)) { 03991 length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2 + sizeof(*this); 03992 if (!(this = ast_calloc(1, length))) 03993 continue; 03994 this->callbacks = hint->callbacks; 03995 hint->callbacks = NULL; 03996 this->laststate = hint->laststate; 03997 this->context = this->data; 03998 strcpy(this->data, hint->exten->parent->name); 03999 this->exten = this->data + strlen(this->context) + 1; 04000 strcpy(this->exten, hint->exten->exten); 04001 AST_LIST_INSERT_HEAD(&store, this, list); 04002 } 04003 } 04004 04005 tmp = *extcontexts; 04006 if (registrar) { 04007 /* XXX remove previous contexts from same registrar */ 04008 if (option_debug) 04009 ast_log(LOG_DEBUG, "must remove any reg %s\n", registrar); 04010 __ast_context_destroy(NULL,registrar); 04011 while (tmp) { 04012 lasttmp = tmp; 04013 tmp = tmp->next; 04014 } 04015 } else { 04016 /* XXX remove contexts with the same name */ 04017 while (tmp) { 04018 ast_log(LOG_WARNING, "must remove %s reg %s\n", tmp->name, tmp->registrar); 04019 __ast_context_destroy(tmp,tmp->registrar); 04020 lasttmp = tmp; 04021 tmp = tmp->next; 04022 } 04023 } 04024 if (lasttmp) { 04025 lasttmp->next = contexts; 04026 contexts = *extcontexts; 04027 *extcontexts = NULL; 04028 } else 04029 ast_log(LOG_WARNING, "Requested contexts didn't get merged\n"); 04030 04031 /* restore the watchers for hints that can be found; notify those that 04032 cannot be restored 04033 */ 04034 while ((this = AST_LIST_REMOVE_HEAD(&store, list))) { 04035 struct pbx_find_info q = { .stacklen = 0 }; 04036 exten = pbx_find_extension(NULL, NULL, &q, this->context, this->exten, PRIORITY_HINT, NULL, "", E_MATCH); 04037 /* Find the hint in the list of hints */ 04038 AST_LIST_TRAVERSE(&hints, hint, list) { 04039 if (hint->exten == exten) 04040 break; 04041 } 04042 if (!exten || !hint) { 04043 /* this hint has been removed, notify the watchers */ 04044 prevcb = NULL; 04045 thiscb = this->callbacks; 04046 while (thiscb) { 04047 prevcb = thiscb; 04048 thiscb = thiscb->next; 04049 prevcb->callback(this->context, this->exten, AST_EXTENSION_REMOVED, prevcb->data); 04050 free(prevcb); 04051 } 04052 } else { 04053 thiscb = this->callbacks; 04054 while (thiscb->next) 04055 thiscb = thiscb->next; 04056 thiscb->next = hint->callbacks; 04057 hint->callbacks = this->callbacks; 04058 hint->laststate = this->laststate; 04059 } 04060 free(this); 04061 } 04062 04063 AST_LIST_UNLOCK(&hints); 04064 ast_unlock_contexts(); 04065 04066 return; 04067 }
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 6487 of file pbx.c.
References ast_cdr_update(), ast_explicit_goto(), ast_findlabel_extension(), ast_log(), ast_strdupa, ast_strlen_zero(), ast_channel::cid, ast_callerid::cid_num, ast_channel::context, exten, ast_channel::exten, LOG_WARNING, ast_channel::priority, and strsep().
Referenced by _while_exec(), check_goto_on_transfer(), gosub_exec(), ivr_dispatch(), pbx_builtin_goto(), random_exec(), return_exec(), and while_continue_exec().
06488 { 06489 char *exten, *pri, *context; 06490 char *stringp; 06491 int ipri; 06492 int mode = 0; 06493 06494 if (ast_strlen_zero(goto_string)) { 06495 ast_log(LOG_WARNING, "Goto requires an argument (optional context|optional extension|priority)\n"); 06496 return -1; 06497 } 06498 stringp = ast_strdupa(goto_string); 06499 context = strsep(&stringp, "|"); /* guaranteed non-null */ 06500 exten = strsep(&stringp, "|"); 06501 pri = strsep(&stringp, "|"); 06502 if (!exten) { /* Only a priority in this one */ 06503 pri = context; 06504 exten = NULL; 06505 context = NULL; 06506 } else if (!pri) { /* Only an extension and priority in this one */ 06507 pri = exten; 06508 exten = context; 06509 context = NULL; 06510 } 06511 if (*pri == '+') { 06512 mode = 1; 06513 pri++; 06514 } else if (*pri == '-') { 06515 mode = -1; 06516 pri++; 06517 } 06518 if (sscanf(pri, "%d", &ipri) != 1) { 06519 if ((ipri = ast_findlabel_extension(chan, context ? context : chan->context, exten ? exten : chan->exten, 06520 pri, chan->cid.cid_num)) < 1) { 06521 ast_log(LOG_WARNING, "Priority '%s' must be a number > 0, or valid label\n", pri); 06522 return -1; 06523 } else 06524 mode = 0; 06525 } 06526 /* At this point we have a priority and maybe an extension and a context */ 06527 06528 if (mode) 06529 ipri = chan->priority + (ipri * mode); 06530 06531 ast_explicit_goto(chan, context, exten, ipri); 06532 ast_cdr_update(chan); 06533 return 0; 06534 06535 }
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 5186 of file pbx.c.
References __ast_request_and_dial(), ast_calloc, ast_cdr_alloc(), ast_cdr_disposition(), ast_cdr_failed(), ast_cdr_init(), ast_cdr_setaccount(), ast_cdr_start(), ast_channel_lock, ast_channel_unlock, ast_hangup(), ast_log(), ast_pbx_outgoing_cdr_failed(), ast_pbx_run_app(), ast_pthread_create, ast_set_variables(), AST_STATE_UP, ast_strlen_zero(), ast_variables_destroy(), ast_verbose(), async_wait(), ast_channel::cdr, async_stat::chan, errno, free, LOG_WARNING, option_verbose, ast_channel::pbx, outgoing_helper::vars, and VERBOSE_PREFIX_4.
Referenced by action_originate(), attempt_thread(), fast_originate(), and orig_app().
05187 { 05188 struct ast_channel *chan; 05189 struct app_tmp *tmp; 05190 int res = -1, cdr_res = -1; 05191 struct outgoing_helper oh; 05192 pthread_attr_t attr; 05193 05194 memset(&oh, 0, sizeof(oh)); 05195 oh.vars = vars; 05196 oh.account = account; 05197 05198 if (locked_channel) 05199 *locked_channel = NULL; 05200 if (ast_strlen_zero(app)) { 05201 res = -1; 05202 goto outgoing_app_cleanup; 05203 } 05204 if (sync) { 05205 chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh); 05206 if (chan) { 05207 if (!chan->cdr) { /* check if the channel already has a cdr record, if not give it one */ 05208 chan->cdr = ast_cdr_alloc(); /* allocate a cdr for the channel */ 05209 if(!chan->cdr) { 05210 /* allocation of the cdr failed */ 05211 free(chan->pbx); 05212 res = -1; 05213 goto outgoing_app_cleanup; 05214 } 05215 /* allocation of the cdr was successful */ 05216 ast_cdr_init(chan->cdr, chan); /* initilize our channel's cdr */ 05217 ast_cdr_start(chan->cdr); 05218 } 05219 ast_set_variables(chan, vars); 05220 if (account) 05221 ast_cdr_setaccount(chan, account); 05222 if (chan->_state == AST_STATE_UP) { 05223 res = 0; 05224 if (option_verbose > 3) 05225 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", chan->name); 05226 tmp = ast_calloc(1, sizeof(*tmp)); 05227 if (!tmp) 05228 res = -1; 05229 else { 05230 ast_copy_string(tmp->app, app, sizeof(tmp->app)); 05231 if (appdata) 05232 ast_copy_string(tmp->data, appdata, sizeof(tmp->data)); 05233 tmp->chan = chan; 05234 if (sync > 1) { 05235 if (locked_channel) 05236 ast_channel_unlock(chan); 05237 ast_pbx_run_app(tmp); 05238 } else { 05239 pthread_attr_init(&attr); 05240 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 05241 if (locked_channel) 05242 ast_channel_lock(chan); 05243 if (ast_pthread_create(&tmp->t, &attr, ast_pbx_run_app, tmp)) { 05244 ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno)); 05245 free(tmp); 05246 if (locked_channel) 05247 ast_channel_unlock(chan); 05248 ast_hangup(chan); 05249 res = -1; 05250 } else { 05251 if (locked_channel) 05252 *locked_channel = chan; 05253 } 05254 pthread_attr_destroy(&attr); 05255 } 05256 } 05257 } else { 05258 if (option_verbose > 3) 05259 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", chan->name); 05260 if (chan->cdr) { /* update the cdr */ 05261 /* here we update the status of the call, which sould be busy. 05262 * if that fails then we set the status to failed */ 05263 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 05264 ast_cdr_failed(chan->cdr); 05265 } 05266 ast_hangup(chan); 05267 } 05268 } 05269 05270 if (res < 0) { /* the call failed for some reason */ 05271 if (*reason == 0) { /* if the call failed (not busy or no answer) 05272 * update the cdr with the failed message */ 05273 cdr_res = ast_pbx_outgoing_cdr_failed(); 05274 if (cdr_res != 0) { 05275 res = cdr_res; 05276 goto outgoing_app_cleanup; 05277 } 05278 } 05279 } 05280 05281 } else { 05282 struct async_stat *as; 05283 if (!(as = ast_calloc(1, sizeof(*as)))) { 05284 res = -1; 05285 goto outgoing_app_cleanup; 05286 } 05287 chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh); 05288 if (!chan) { 05289 free(as); 05290 res = -1; 05291 goto outgoing_app_cleanup; 05292 } 05293 as->chan = chan; 05294 ast_copy_string(as->app, app, sizeof(as->app)); 05295 if (appdata) 05296 ast_copy_string(as->appdata, appdata, sizeof(as->appdata)); 05297 as->timeout = timeout; 05298 ast_set_variables(chan, vars); 05299 if (account) 05300 ast_cdr_setaccount(chan, account); 05301 /* Start a new thread, and get something handling this channel. */ 05302 pthread_attr_init(&attr); 05303 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 05304 if (locked_channel) 05305 ast_channel_lock(chan); 05306 if (ast_pthread_create(&as->p, &attr, async_wait, as)) { 05307 ast_log(LOG_WARNING, "Failed to start async wait\n"); 05308 free(as); 05309 if (locked_channel) 05310 ast_channel_unlock(chan); 05311 ast_hangup(chan); 05312 res = -1; 05313 pthread_attr_destroy(&attr); 05314 goto outgoing_app_cleanup; 05315 } else { 05316 if (locked_channel) 05317 *locked_channel = chan; 05318 } 05319 pthread_attr_destroy(&attr); 05320 res = 0; 05321 } 05322 outgoing_app_cleanup: 05323 ast_variables_destroy(vars); 05324 return res; 05325 }
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 4995 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().
04996 { 04997 /* allocate a channel */ 04998 struct ast_channel *chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, 0); 04999 05000 if (!chan) 05001 return -1; /* failure */ 05002 05003 if (!chan->cdr) { 05004 /* allocation of the cdr failed */ 05005 ast_channel_free(chan); /* free the channel */ 05006 return -1; /* return failure */ 05007 } 05008 05009 /* allocation of the cdr was successful */ 05010 ast_cdr_init(chan->cdr, chan); /* initilize our channel's cdr */ 05011 ast_cdr_start(chan->cdr); /* record the start and stop time */ 05012 ast_cdr_end(chan->cdr); 05013 ast_cdr_failed(chan->cdr); /* set the status to failed */ 05014 ast_cdr_detach(chan->cdr); /* post and free the record */ 05015 ast_channel_free(chan); /* free the channel */ 05016 05017 return 0; /* success */ 05018 }
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 5020 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().
05021 { 05022 struct ast_channel *chan; 05023 struct async_stat *as; 05024 int res = -1, cdr_res = -1; 05025 struct outgoing_helper oh; 05026 pthread_attr_t attr; 05027 05028 if (sync) { 05029 LOAD_OH(oh); 05030 chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh); 05031 if (channel) { 05032 *channel = chan; 05033 if (chan) 05034 ast_channel_lock(chan); 05035 } 05036 if (chan) { 05037 if (chan->_state == AST_STATE_UP) { 05038 res = 0; 05039 if (option_verbose > 3) 05040 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", chan->name); 05041 05042 if (sync > 1) { 05043 if (channel) 05044 ast_channel_unlock(chan); 05045 if (ast_pbx_run(chan)) { 05046 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 05047 if (channel) 05048 *channel = NULL; 05049 ast_hangup(chan); 05050 chan = NULL; 05051 res = -1; 05052 } 05053 } else { 05054 if (ast_pbx_start(chan)) { 05055 ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name); 05056 if (channel) { 05057 *channel = NULL; 05058 ast_channel_unlock(chan); 05059 } 05060 ast_hangup(chan); 05061 res = -1; 05062 } 05063 chan = NULL; 05064 } 05065 } else { 05066 if (option_verbose > 3) 05067 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", chan->name); 05068 05069 if (chan->cdr) { /* update the cdr */ 05070 /* here we update the status of the call, which sould be busy. 05071 * if that fails then we set the status to failed */ 05072 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 05073 ast_cdr_failed(chan->cdr); 05074 } 05075 05076 if (channel) { 05077 *channel = NULL; 05078 ast_channel_unlock(chan); 05079 } 05080 ast_hangup(chan); 05081 chan = NULL; 05082 } 05083 } 05084 05085 if (res < 0) { /* the call failed for some reason */ 05086 if (*reason == 0) { /* if the call failed (not busy or no answer) 05087 * update the cdr with the failed message */ 05088 cdr_res = ast_pbx_outgoing_cdr_failed(); 05089 if (cdr_res != 0) { 05090 res = cdr_res; 05091 goto outgoing_exten_cleanup; 05092 } 05093 } 05094 05095 /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */ 05096 /* check if "failed" exists */ 05097 if (ast_exists_extension(chan, context, "failed", 1, NULL)) { 05098 chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "OutgoingSpoolFailed"); 05099 if (chan) { 05100 char failed_reason[4] = ""; 05101 if (!ast_strlen_zero(context)) 05102 ast_copy_string(chan->context, context, sizeof(chan->context)); 05103 set_ext_pri(chan, "failed", 1); 05104 ast_set_variables(chan, vars); 05105 snprintf(failed_reason, sizeof(failed_reason), "%d", *reason); 05106 pbx_builtin_setvar_helper(chan, "REASON", failed_reason); 05107 if (account) 05108 ast_cdr_setaccount(chan, account); 05109 if (ast_pbx_run(chan)) { 05110 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 05111 ast_hangup(chan); 05112 } 05113 chan = NULL; 05114 } 05115 } 05116 } 05117 } else { 05118 if (!(as = ast_calloc(1, sizeof(*as)))) { 05119 res = -1; 05120 goto outgoing_exten_cleanup; 05121 } 05122 chan = ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name); 05123 if (channel) { 05124 *channel = chan; 05125 if (chan) 05126 ast_channel_lock(chan); 05127 } 05128 if (!chan) { 05129 free(as); 05130 res = -1; 05131 goto outgoing_exten_cleanup; 05132 } 05133 as->chan = chan; 05134 ast_copy_string(as->context, context, sizeof(as->context)); 05135 set_ext_pri(as->chan, exten, priority); 05136 as->timeout = timeout; 05137 ast_set_variables(chan, vars); 05138 if (account) 05139 ast_cdr_setaccount(chan, account); 05140 pthread_attr_init(&attr); 05141 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 05142 if (ast_pthread_create(&as->p, &attr, async_wait, as)) { 05143 ast_log(LOG_WARNING, "Failed to start async wait\n"); 05144 free(as); 05145 if (channel) { 05146 *channel = NULL; 05147 ast_channel_unlock(chan); 05148 } 05149 ast_hangup(chan); 05150 res = -1; 05151 pthread_attr_destroy(&attr); 05152 goto outgoing_exten_cleanup; 05153 } 05154 pthread_attr_destroy(&attr); 05155 res = 0; 05156 } 05157 outgoing_exten_cleanup: 05158 ast_variables_destroy(vars); 05159 return res; 05160 }
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 2695 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().
02696 { 02697 enum ast_pbx_result res = AST_PBX_SUCCESS; 02698 02699 if (increase_call_count(c)) 02700 return AST_PBX_CALL_LIMIT; 02701 02702 res = __ast_pbx_run(c); 02703 decrease_call_count(); 02704 02705 return res; 02706 }
static void* ast_pbx_run_app | ( | void * | data | ) | [static] |
run the application and free the descriptor once done
Definition at line 5170 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().
05171 { 05172 struct app_tmp *tmp = data; 05173 struct ast_app *app; 05174 app = pbx_findapp(tmp->app); 05175 if (app) { 05176 if (option_verbose > 3) 05177 ast_verbose(VERBOSE_PREFIX_4 "Launching %s(%s) on %s\n", tmp->app, tmp->data, tmp->chan->name); 05178 pbx_exec(tmp->chan, app, tmp->data); 05179 } else 05180 ast_log(LOG_WARNING, "No such application '%s'\n", tmp->app); 05181 ast_hangup(tmp->chan); 05182 free(tmp); 05183 return NULL; 05184 }
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 2669 of file pbx.c.
References ast_log(), AST_PBX_CALL_LIMIT, AST_PBX_FAILED, AST_PBX_SUCCESS, ast_pthread_create, increase_call_count(), LOG_WARNING, pbx_thread(), and t.
Referenced by __oh323_new(), alsa_new(), ast_async_goto(), ast_iax2_new(), ast_pbx_outgoing_exten(), check_goto_on_transfer(), do_parking_thread(), gtalk_new(), gtalk_newcall(), handle_request_invite(), local_call(), mgcp_new(), nbs_new(), oss_new(), pbx_start_chan(), phone_new(), rpt_call(), sip_new(), skinny_new(), and zt_new().
02670 { 02671 pthread_t t; 02672 pthread_attr_t attr; 02673 02674 if (!c) { 02675 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n"); 02676 return AST_PBX_FAILED; 02677 } 02678 02679 if (increase_call_count(c)) 02680 return AST_PBX_CALL_LIMIT; 02681 02682 /* Start a new thread, and get something handling this channel. */ 02683 pthread_attr_init(&attr); 02684 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 02685 if (ast_pthread_create(&t, &attr, pbx_thread, c)) { 02686 ast_log(LOG_WARNING, "Failed to create new channel thread\n"); 02687 pthread_attr_destroy(&attr); 02688 return AST_PBX_FAILED; 02689 } 02690 pthread_attr_destroy(&attr); 02691 02692 return AST_PBX_SUCCESS; 02693 }
int ast_rdlock_contexts | ( | void | ) |
Definition at line 6265 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().
06266 { 06267 return ast_rwlock_rdlock(&conlock); 06268 }
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 2997 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().
02998 { 02999 struct ast_app *tmp, *cur = NULL; 03000 char tmps[80]; 03001 int length; 03002 03003 AST_LIST_LOCK(&apps); 03004 AST_LIST_TRAVERSE(&apps, tmp, list) { 03005 if (!strcasecmp(app, tmp->name)) { 03006 ast_log(LOG_WARNING, "Already have an application '%s'\n", app); 03007 AST_LIST_UNLOCK(&apps); 03008 return -1; 03009 } 03010 } 03011 03012 length = sizeof(*tmp) + strlen(app) + 1; 03013 03014 if (!(tmp = ast_calloc(1, length))) { 03015 AST_LIST_UNLOCK(&apps); 03016 return -1; 03017 } 03018 03019 strcpy(tmp->name, app); 03020 tmp->execute = execute; 03021 tmp->synopsis = synopsis; 03022 tmp->description = description; 03023 03024 /* Store in alphabetical order */ 03025 AST_LIST_TRAVERSE_SAFE_BEGIN(&apps, cur, list) { 03026 if (strcasecmp(tmp->name, cur->name) < 0) { 03027 AST_LIST_INSERT_BEFORE_CURRENT(&apps, tmp, list); 03028 break; 03029 } 03030 } 03031 AST_LIST_TRAVERSE_SAFE_END 03032 if (!cur) 03033 AST_LIST_INSERT_TAIL(&apps, tmp, list); 03034 03035 if (option_verbose > 1) 03036 ast_verbose( VERBOSE_PREFIX_2 "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps))); 03037 03038 AST_LIST_UNLOCK(&apps); 03039 03040 return 0; 03041 }
int ast_register_switch | ( | struct ast_switch * | sw | ) |
Register an alternative dialplan switch.
sw | switch to register |
Definition at line 3047 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().
03048 { 03049 struct ast_switch *tmp; 03050 03051 AST_LIST_LOCK(&switches); 03052 AST_LIST_TRAVERSE(&switches, tmp, list) { 03053 if (!strcasecmp(tmp->name, sw->name)) { 03054 AST_LIST_UNLOCK(&switches); 03055 ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name); 03056 return -1; 03057 } 03058 } 03059 AST_LIST_INSERT_TAIL(&switches, sw, list); 03060 AST_LIST_UNLOCK(&switches); 03061 03062 return 0; 03063 }
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 6288 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().
06289 { 06290 return ast_mutex_unlock(&con->lock); 06291 }
int ast_unlock_contexts | ( | void | ) |
Unlocks contexts.
0 | on success | |
-1 | on failure |
Definition at line 6275 of file pbx.c.
References ast_rwlock_unlock().
Referenced by __ast_context_create(), _macro_exec(), ast_add_extension(), ast_context_add_ignorepat(), ast_context_add_include(), ast_context_add_switch(), ast_context_destroy(), ast_context_find(), ast_context_lockmacro(), ast_context_remove_extension(), ast_context_remove_ignorepat(), ast_context_remove_include(), ast_context_remove_switch(), ast_context_unlockmacro(), ast_hint_extension(), ast_merge_contexts_and_delete(), complete_context_add_extension(), complete_context_add_extension_deprecated(), complete_context_add_ignorepat(), complete_context_add_ignorepat_deprecated(), complete_context_add_include(), complete_context_add_include_deprecated(), complete_context_dont_include_deprecated(), complete_context_remove_extension(), complete_context_remove_extension_deprecated(), complete_context_remove_ignorepat(), complete_context_remove_ignorepat_deprecated(), complete_context_remove_include(), complete_show_dialplan_context(), dundi_precache_full(), find_context_locked(), find_matching_endwhile(), handle_save_dialplan(), pbx_extension_helper(), and show_dialplan_helper().
06276 { 06277 return ast_rwlock_unlock(&conlock); 06278 }
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 3878 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().
03879 { 03880 struct ast_app *tmp; 03881 03882 AST_LIST_LOCK(&apps); 03883 AST_LIST_TRAVERSE_SAFE_BEGIN(&apps, tmp, list) { 03884 if (!strcasecmp(app, tmp->name)) { 03885 AST_LIST_REMOVE_CURRENT(&apps, list); 03886 if (option_verbose > 1) 03887 ast_verbose( VERBOSE_PREFIX_2 "Unregistered application '%s'\n", tmp->name); 03888 free(tmp); 03889 break; 03890 } 03891 } 03892 AST_LIST_TRAVERSE_SAFE_END 03893 AST_LIST_UNLOCK(&apps); 03894 03895 return tmp ? 0 : -1; 03896 }
void ast_unregister_switch | ( | struct ast_switch * | sw | ) |
Unregister an alternative switch.
sw | switch to unregister |
Definition at line 3065 of file pbx.c.
References AST_LIST_LOCK, AST_LIST_REMOVE, and AST_LIST_UNLOCK.
Referenced by __unload_module(), and unload_module().
03066 { 03067 AST_LIST_LOCK(&switches); 03068 AST_LIST_REMOVE(&switches, sw, list); 03069 AST_LIST_UNLOCK(&switches); 03070 }
struct ast_exten* ast_walk_context_extensions | ( | struct ast_context * | con, | |
struct ast_exten * | exten | |||
) |
Definition at line 6397 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().
06399 { 06400 if (!exten) 06401 return con ? con->root : NULL; 06402 else 06403 return exten->next; 06404 }
struct ast_ignorepat* ast_walk_context_ignorepats | ( | struct ast_context * | con, | |
struct ast_ignorepat * | ip | |||
) |
Definition at line 6430 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().
06432 { 06433 if (!ip) 06434 return con ? con->ignorepats : NULL; 06435 else 06436 return ip->next; 06437 }
struct ast_include* ast_walk_context_includes | ( | struct ast_context * | con, | |
struct ast_include * | inc | |||
) |
Definition at line 6421 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().
06423 { 06424 if (!inc) 06425 return con ? con->includes : NULL; 06426 else 06427 return inc->next; 06428 }
struct ast_sw* ast_walk_context_switches | ( | struct ast_context * | con, | |
struct ast_sw * | sw | |||
) |
Definition at line 6406 of file pbx.c.
References AST_LIST_FIRST, and AST_LIST_NEXT.
Referenced by handle_save_dialplan(), and show_dialplan_helper().
06408 { 06409 if (!sw) 06410 return con ? AST_LIST_FIRST(&con->alts) : NULL; 06411 else 06412 return AST_LIST_NEXT(sw, list); 06413 }
struct ast_context* ast_walk_contexts | ( | struct ast_context * | con | ) |
Definition at line 6392 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 6415 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 6270 of file pbx.c.
References ast_rwlock_wrlock().
Referenced by ast_context_destroy(), ast_merge_contexts_and_delete(), and complete_context_dont_include_deprecated().
06271 { 06272 return ast_rwlock_wrlock(&conlock); 06273 }
static void* async_wait | ( | void * | data | ) | [static] |
Definition at line 4932 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().
04933 { 04934 struct async_stat *as = data; 04935 struct ast_channel *chan = as->chan; 04936 int timeout = as->timeout; 04937 int res; 04938 struct ast_frame *f; 04939 struct ast_app *app; 04940 04941 while (timeout && (chan->_state != AST_STATE_UP)) { 04942 res = ast_waitfor(chan, timeout); 04943 if (res < 1) 04944 break; 04945 if (timeout > -1) 04946 timeout = res; 04947 f = ast_read(chan); 04948 if (!f) 04949 break; 04950 if (f->frametype == AST_FRAME_CONTROL) { 04951 if ((f->subclass == AST_CONTROL_BUSY) || 04952 (f->subclass == AST_CONTROL_CONGESTION) ) { 04953 ast_frfree(f); 04954 break; 04955 } 04956 } 04957 ast_frfree(f); 04958 } 04959 if (chan->_state == AST_STATE_UP) { 04960 if (!ast_strlen_zero(as->app)) { 04961 app = pbx_findapp(as->app); 04962 if (app) { 04963 if (option_verbose > 2) 04964 ast_verbose(VERBOSE_PREFIX_3 "Launching %s(%s) on %s\n", as->app, as->appdata, chan->name); 04965 pbx_exec(chan, app, as->appdata); 04966 } else 04967 ast_log(LOG_WARNING, "No such application '%s'\n", as->app); 04968 } else { 04969 if (!ast_strlen_zero(as->context)) 04970 ast_copy_string(chan->context, as->context, sizeof(chan->context)); 04971 if (!ast_strlen_zero(as->exten)) 04972 ast_copy_string(chan->exten, as->exten, sizeof(chan->exten)); 04973 if (as->priority > 0) 04974 chan->priority = as->priority; 04975 /* Run the PBX */ 04976 if (ast_pbx_run(chan)) { 04977 ast_log(LOG_ERROR, "Failed to start PBX on %s\n", chan->name); 04978 } else { 04979 /* PBX will have taken care of this */ 04980 chan = NULL; 04981 } 04982 } 04983 } 04984 free(as); 04985 if (chan) 04986 ast_hangup(chan); 04987 return NULL; 04988 }
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 3123 of file pbx.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, and strdup.
03124 { 03125 struct ast_app *a; 03126 char *ret = NULL; 03127 int which = 0; 03128 int wordlen = strlen(word); 03129 03130 /* return the n-th [partial] matching entry */ 03131 AST_LIST_LOCK(&apps); 03132 AST_LIST_TRAVERSE(&apps, a, list) { 03133 if (!strncasecmp(word, a->name, wordlen) && ++which > state) { 03134 ret = strdup(a->name); 03135 break; 03136 } 03137 } 03138 AST_LIST_UNLOCK(&apps); 03139 03140 return ret; 03141 }
static char* complete_show_applications | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 3484 of file pbx.c.
References ast_cli_complete().
03485 { 03486 static char* choices[] = { "like", "describing", NULL }; 03487 03488 return (pos != 3) ? NULL : ast_cli_complete(word, choices, state); 03489 }
static char* complete_show_applications_deprecated | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 3477 of file pbx.c.
References ast_cli_complete().
03478 { 03479 static char* choices[] = { "like", "describing", NULL }; 03480 03481 return (pos != 2) ? NULL : ast_cli_complete(word, choices, state); 03482 }
static char* complete_show_dialplan_context | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 3494 of file pbx.c.
References ast_get_context_name(), ast_rdlock_contexts(), ast_strdup, ast_unlock_contexts(), and ast_walk_contexts().
03496 { 03497 struct ast_context *c = NULL; 03498 char *ret = NULL; 03499 int which = 0; 03500 int wordlen; 03501 03502 /* we are do completion of [exten@]context on second position only */ 03503 if (pos != 2) 03504 return NULL; 03505 03506 ast_rdlock_contexts(); 03507 03508 wordlen = strlen(word); 03509 03510 /* walk through all contexts and return the n-th match */ 03511 while ( (c = ast_walk_contexts(c)) ) { 03512 if (!strncasecmp(word, ast_get_context_name(c), wordlen) && ++which > state) { 03513 ret = ast_strdup(ast_get_context_name(c)); 03514 break; 03515 } 03516 } 03517 03518 ast_unlock_contexts(); 03519 03520 return ret; 03521 }
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 2631 of file pbx.c.
References ast_mutex_lock(), ast_mutex_unlock(), and countcalls.
Referenced by ast_pbx_run(), and pbx_thread().
02632 { 02633 ast_mutex_lock(&maxcalllock); 02634 if (countcalls > 0) 02635 countcalls--; 02636 ast_mutex_unlock(&maxcalllock); 02637 }
static void destroy_exten | ( | struct ast_exten * | e | ) | [static] |
Definition at line 2639 of file pbx.c.
References ast_remove_hint(), free, ast_exten::priority, and PRIORITY_HINT.
Referenced by __ast_context_destroy(), and ast_context_remove_extension2().
02640 { 02641 if (e->priority == PRIORITY_HINT) 02642 ast_remove_hint(e); 02643 02644 if (e->datad) 02645 e->datad(e->data); 02646 free(e); 02647 }
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 4684 of file pbx.c.
Referenced by ast_add_extension2().
04685 { 04686 int count=0; 04687 04688 while (*src && (count < len - 1)) { 04689 switch(*src) { 04690 case ' ': 04691 /* otherwise exten => [a-b],1,... doesn't work */ 04692 /* case '-': */ 04693 /* Ignore */ 04694 break; 04695 default: 04696 *dst = *src; 04697 dst++; 04698 } 04699 src++; 04700 count++; 04701 } 04702 *dst = '\0'; 04703 04704 return count; 04705 }
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 2723 of file pbx.c.
References ast_get_context_name(), ast_rdlock_contexts(), ast_unlock_contexts(), and ast_walk_contexts().
Referenced by ast_add_extension(), ast_context_add_ignorepat(), ast_context_add_include(), ast_context_add_switch(), ast_context_remove_extension(), ast_context_remove_ignorepat(), ast_context_remove_include(), and ast_context_remove_switch().
02724 { 02725 struct ast_context *c = NULL; 02726 02727 ast_rdlock_contexts(); 02728 while ( (c = ast_walk_contexts(c)) ) { 02729 if (!strcmp(ast_get_context_name(c), context)) 02730 return c; 02731 } 02732 ast_unlock_contexts(); 02733 02734 return NULL; 02735 }
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 4108 of file pbx.c.
References ast_log(), ast_strlen_zero(), LOG_WARNING, lookup_name(), and s.
Referenced by ast_build_timing().
04109 { 04110 int s, e; /* start and ending position */ 04111 unsigned int mask = 0; 04112 04113 /* Check for whole range */ 04114 if (ast_strlen_zero(src) || !strcmp(src, "*")) { 04115 s = 0; 04116 e = max - 1; 04117 } else { 04118 /* Get start and ending position */ 04119 char *c = strchr(src, '-'); 04120 if (c) 04121 *c++ = '\0'; 04122 /* Find the start */ 04123 s = lookup_name(src, names, max); 04124 if (!s) { 04125 ast_log(LOG_WARNING, "Invalid %s '%s', assuming none\n", msg, src); 04126 return 0; 04127 } 04128 s--; 04129 if (c) { /* find end of range */ 04130 e = lookup_name(c, names, max); 04131 if (!e) { 04132 ast_log(LOG_WARNING, "Invalid end %s '%s', assuming none\n", msg, c); 04133 return 0; 04134 } 04135 e--; 04136 } else 04137 e = s; 04138 } 04139 /* Fill the mask. Remember that ranges are cyclic */ 04140 mask = 1 << e; /* initialize with last element */ 04141 while (s != e) { 04142 if (s >= max) { 04143 s = 0; 04144 mask |= (1 << s); 04145 } else { 04146 mask |= (1 << s); 04147 s++; 04148 } 04149 } 04150 return mask; 04151 }
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 4154 of file pbx.c.
References ast_log(), ast_strlen_zero(), LOG_WARNING, and ast_timing::minmask.
Referenced by ast_build_timing().
04155 { 04156 char *e; 04157 int x; 04158 int s1, s2; 04159 int e1, e2; 04160 /* int cth, ctm; */ 04161 04162 /* start disabling all times, fill the fields with 0's, as they may contain garbage */ 04163 memset(i->minmask, 0, sizeof(i->minmask)); 04164 04165 /* 2-minutes per bit, since the mask has only 32 bits :( */ 04166 /* Star is all times */ 04167 if (ast_strlen_zero(times) || !strcmp(times, "*")) { 04168 for (x=0; x<24; x++) 04169 i->minmask[x] = 0x3fffffff; /* 30 bits */ 04170 return; 04171 } 04172 /* Otherwise expect a range */ 04173 e = strchr(times, '-'); 04174 if (!e) { 04175 ast_log(LOG_WARNING, "Time range is not valid. Assuming no restrictions based on time.\n"); 04176 return; 04177 } 04178 *e++ = '\0'; 04179 /* XXX why skip non digits ? */ 04180 while (*e && !isdigit(*e)) 04181 e++; 04182 if (!*e) { 04183 ast_log(LOG_WARNING, "Invalid time range. Assuming no restrictions based on time.\n"); 04184 return; 04185 } 04186 if (sscanf(times, "%d:%d", &s1, &s2) != 2) { 04187 ast_log(LOG_WARNING, "%s isn't a time. Assuming no restrictions based on time.\n", times); 04188 return; 04189 } 04190 if (sscanf(e, "%d:%d", &e1, &e2) != 2) { 04191 ast_log(LOG_WARNING, "%s isn't a time. Assuming no restrictions based on time.\n", e); 04192 return; 04193 } 04194 /* XXX this needs to be optimized */ 04195 #if 1 04196 s1 = s1 * 30 + s2/2; 04197 if ((s1 < 0) || (s1 >= 24*30)) { 04198 ast_log(LOG_WARNING, "%s isn't a valid start time. Assuming no time.\n", times); 04199 return; 04200 } 04201 e1 = e1 * 30 + e2/2; 04202 if ((e1 < 0) || (e1 >= 24*30)) { 04203 ast_log(LOG_WARNING, "%s isn't a valid end time. Assuming no time.\n", e); 04204 return; 04205 } 04206 /* Go through the time and enable each appropriate bit */ 04207 for (x=s1;x != e1;x = (x + 1) % (24 * 30)) { 04208 i->minmask[x/30] |= (1 << (x % 30)); 04209 } 04210 /* Do the last one */ 04211 i->minmask[x/30] |= (1 << (x % 30)); 04212 #else 04213 for (cth=0; cth<24; cth++) { 04214 /* Initialize masks to blank */ 04215 i->minmask[cth] = 0; 04216 for (ctm=0; ctm<30; ctm++) { 04217 if ( 04218 /* First hour with more than one hour */ 04219 (((cth == s1) && (ctm >= s2)) && 04220 ((cth < e1))) 04221 /* Only one hour */ 04222 || (((cth == s1) && (ctm >= s2)) && 04223 ((cth == e1) && (ctm <= e2))) 04224 /* In between first and last hours (more than 2 hours) */ 04225 || ((cth > s1) && 04226 (cth < e1)) 04227 /* Last hour with more than one hour */ 04228 || ((cth > s1) && 04229 ((cth == e1) && (ctm <= e2))) 04230 ) 04231 i->minmask[cth] |= (1 << (ctm / 2)); 04232 } 04233 } 04234 #endif 04235 /* All done */ 04236 return; 04237 }
static int handle_set_global | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3779 of file pbx.c.
References ast_cli(), pbx_builtin_setvar_helper(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03780 { 03781 if (argc != 5) 03782 return RESULT_SHOWUSAGE; 03783 03784 pbx_builtin_setvar_helper(NULL, argv[3], argv[4]); 03785 ast_cli(fd, "\n -- Global variable %s set to %s\n", argv[3], argv[4]); 03786 03787 return RESULT_SUCCESS; 03788 }
static int handle_set_global_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
CLI support for setting global variables.
Definition at line 3767 of file pbx.c.
References ast_cli(), pbx_builtin_setvar_helper(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03768 { 03769 if (argc != 4) 03770 return RESULT_SHOWUSAGE; 03771 03772 pbx_builtin_setvar_helper(NULL, argv[2], argv[3]); 03773 ast_cli(fd, "\n -- Global variable %s set to %s\n", argv[2], argv[3]); 03774 03775 return RESULT_SUCCESS; 03776 }
static int handle_show_application | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3213 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().
03214 { 03215 struct ast_app *a; 03216 int app, no_registered_app = 1; 03217 03218 if (argc < 4) 03219 return RESULT_SHOWUSAGE; 03220 03221 /* ... go through all applications ... */ 03222 AST_LIST_LOCK(&apps); 03223 AST_LIST_TRAVERSE(&apps, a, list) { 03224 /* ... compare this application name with all arguments given 03225 * to 'show application' command ... */ 03226 for (app = 3; app < argc; app++) { 03227 if (!strcasecmp(a->name, argv[app])) { 03228 /* Maximum number of characters added by terminal coloring is 22 */ 03229 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40]; 03230 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL; 03231 int synopsis_size, description_size; 03232 03233 no_registered_app = 0; 03234 03235 if (a->synopsis) 03236 synopsis_size = strlen(a->synopsis) + 23; 03237 else 03238 synopsis_size = strlen("Not available") + 23; 03239 synopsis = alloca(synopsis_size); 03240 03241 if (a->description) 03242 description_size = strlen(a->description) + 23; 03243 else 03244 description_size = strlen("Not available") + 23; 03245 description = alloca(description_size); 03246 03247 if (synopsis && description) { 03248 snprintf(info, 64 + AST_MAX_APP, "\n -= Info about application '%s' =- \n\n", a->name); 03249 term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22); 03250 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 03251 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40); 03252 term_color(synopsis, 03253 a->synopsis ? a->synopsis : "Not available", 03254 COLOR_CYAN, 0, synopsis_size); 03255 term_color(description, 03256 a->description ? a->description : "Not available", 03257 COLOR_CYAN, 0, description_size); 03258 03259 ast_cli(fd,"%s%s%s\n\n%s%s\n", infotitle, syntitle, synopsis, destitle, description); 03260 } else { 03261 /* ... one of our applications, show info ...*/ 03262 ast_cli(fd,"\n -= Info about application '%s' =- \n\n" 03263 "[Synopsis]\n %s\n\n" 03264 "[Description]\n%s\n", 03265 a->name, 03266 a->synopsis ? a->synopsis : "Not available", 03267 a->description ? a->description : "Not available"); 03268 } 03269 } 03270 } 03271 } 03272 AST_LIST_UNLOCK(&apps); 03273 03274 /* we found at least one app? no? */ 03275 if (no_registered_app) { 03276 ast_cli(fd, "Your application(s) is (are) not registered\n"); 03277 return RESULT_FAILURE; 03278 } 03279 03280 return RESULT_SUCCESS; 03281 }
static int handle_show_application_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3143 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().
03144 { 03145 struct ast_app *a; 03146 int app, no_registered_app = 1; 03147 03148 if (argc < 3) 03149 return RESULT_SHOWUSAGE; 03150 03151 /* ... go through all applications ... */ 03152 AST_LIST_LOCK(&apps); 03153 AST_LIST_TRAVERSE(&apps, a, list) { 03154 /* ... compare this application name with all arguments given 03155 * to 'show application' command ... */ 03156 for (app = 2; app < argc; app++) { 03157 if (!strcasecmp(a->name, argv[app])) { 03158 /* Maximum number of characters added by terminal coloring is 22 */ 03159 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40]; 03160 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL; 03161 int synopsis_size, description_size; 03162 03163 no_registered_app = 0; 03164 03165 if (a->synopsis) 03166 synopsis_size = strlen(a->synopsis) + 23; 03167 else 03168 synopsis_size = strlen("Not available") + 23; 03169 synopsis = alloca(synopsis_size); 03170 03171 if (a->description) 03172 description_size = strlen(a->description) + 23; 03173 else 03174 description_size = strlen("Not available") + 23; 03175 description = alloca(description_size); 03176 03177 if (synopsis && description) { 03178 snprintf(info, 64 + AST_MAX_APP, "\n -= Info about application '%s' =- \n\n", a->name); 03179 term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22); 03180 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 03181 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40); 03182 term_color(synopsis, 03183 a->synopsis ? a->synopsis : "Not available", 03184 COLOR_CYAN, 0, synopsis_size); 03185 term_color(description, 03186 a->description ? a->description : "Not available", 03187 COLOR_CYAN, 0, description_size); 03188 03189 ast_cli(fd,"%s%s%s\n\n%s%s\n", infotitle, syntitle, synopsis, destitle, description); 03190 } else { 03191 /* ... one of our applications, show info ...*/ 03192 ast_cli(fd,"\n -= Info about application '%s' =- \n\n" 03193 "[Synopsis]\n %s\n\n" 03194 "[Description]\n%s\n", 03195 a->name, 03196 a->synopsis ? a->synopsis : "Not available", 03197 a->description ? a->description : "Not available"); 03198 } 03199 } 03200 } 03201 } 03202 AST_LIST_UNLOCK(&apps); 03203 03204 /* we found at least one app? no? */ 03205 if (no_registered_app) { 03206 ast_cli(fd, "Your application(s) is (are) not registered\n"); 03207 return RESULT_FAILURE; 03208 } 03209 03210 return RESULT_SUCCESS; 03211 }
static int handle_show_applications | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3408 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.
03409 { 03410 struct ast_app *a; 03411 int like = 0, describing = 0; 03412 int total_match = 0; /* Number of matches in like clause */ 03413 int total_apps = 0; /* Number of apps registered */ 03414 03415 AST_LIST_LOCK(&apps); 03416 03417 if (AST_LIST_EMPTY(&apps)) { 03418 ast_cli(fd, "There are no registered applications\n"); 03419 AST_LIST_UNLOCK(&apps); 03420 return -1; 03421 } 03422 03423 /* core list applications like <keyword> */ 03424 if ((argc == 5) && (!strcmp(argv[3], "like"))) { 03425 like = 1; 03426 } else if ((argc > 4) && (!strcmp(argv[3], "describing"))) { 03427 describing = 1; 03428 } 03429 03430 /* core list applications describing <keyword1> [<keyword2>] [...] */ 03431 if ((!like) && (!describing)) { 03432 ast_cli(fd, " -= Registered Asterisk Applications =-\n"); 03433 } else { 03434 ast_cli(fd, " -= Matching Asterisk Applications =-\n"); 03435 } 03436 03437 AST_LIST_TRAVERSE(&apps, a, list) { 03438 int printapp = 0; 03439 total_apps++; 03440 if (like) { 03441 if (strcasestr(a->name, argv[4])) { 03442 printapp = 1; 03443 total_match++; 03444 } 03445 } else if (describing) { 03446 if (a->description) { 03447 /* Match all words on command line */ 03448 int i; 03449 printapp = 1; 03450 for (i = 4; i < argc; i++) { 03451 if (!strcasestr(a->description, argv[i])) { 03452 printapp = 0; 03453 } else { 03454 total_match++; 03455 } 03456 } 03457 } 03458 } else { 03459 printapp = 1; 03460 } 03461 03462 if (printapp) { 03463 ast_cli(fd," %20s: %s\n", a->name, a->synopsis ? a->synopsis : "<Synopsis not available>"); 03464 } 03465 } 03466 if ((!like) && (!describing)) { 03467 ast_cli(fd, " -= %d Applications Registered =-\n",total_apps); 03468 } else { 03469 ast_cli(fd, " -= %d Applications Matching =-\n",total_match); 03470 } 03471 03472 AST_LIST_UNLOCK(&apps); 03473 03474 return RESULT_SUCCESS; 03475 }
static int handle_show_applications_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3340 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.
03341 { 03342 struct ast_app *a; 03343 int like = 0, describing = 0; 03344 int total_match = 0; /* Number of matches in like clause */ 03345 int total_apps = 0; /* Number of apps registered */ 03346 03347 AST_LIST_LOCK(&apps); 03348 03349 if (AST_LIST_EMPTY(&apps)) { 03350 ast_cli(fd, "There are no registered applications\n"); 03351 AST_LIST_UNLOCK(&apps); 03352 return -1; 03353 } 03354 03355 /* show applications like <keyword> */ 03356 if ((argc == 4) && (!strcmp(argv[2], "like"))) { 03357 like = 1; 03358 } else if ((argc > 3) && (!strcmp(argv[2], "describing"))) { 03359 describing = 1; 03360 } 03361 03362 /* show applications describing <keyword1> [<keyword2>] [...] */ 03363 if ((!like) && (!describing)) { 03364 ast_cli(fd, " -= Registered Asterisk Applications =-\n"); 03365 } else { 03366 ast_cli(fd, " -= Matching Asterisk Applications =-\n"); 03367 } 03368 03369 AST_LIST_TRAVERSE(&apps, a, list) { 03370 int printapp = 0; 03371 total_apps++; 03372 if (like) { 03373 if (strcasestr(a->name, argv[3])) { 03374 printapp = 1; 03375 total_match++; 03376 } 03377 } else if (describing) { 03378 if (a->description) { 03379 /* Match all words on command line */ 03380 int i; 03381 printapp = 1; 03382 for (i = 3; i < argc; i++) { 03383 if (!strcasestr(a->description, argv[i])) { 03384 printapp = 0; 03385 } else { 03386 total_match++; 03387 } 03388 } 03389 } 03390 } else { 03391 printapp = 1; 03392 } 03393 03394 if (printapp) { 03395 ast_cli(fd," %20s: %s\n", a->name, a->synopsis ? a->synopsis : "<Synopsis not available>"); 03396 } 03397 } 03398 if ((!like) && (!describing)) { 03399 ast_cli(fd, " -= %d Applications Registered =-\n",total_apps); 03400 } else { 03401 ast_cli(fd, " -= %d Applications Matching =-\n",total_match); 03402 } 03403 03404 AST_LIST_UNLOCK(&apps); 03405 03406 return RESULT_SUCCESS; 03407 }
static int handle_show_dialplan | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3694 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().
03695 { 03696 char *exten = NULL, *context = NULL; 03697 /* Variables used for different counters */ 03698 struct dialplan_counters counters; 03699 03700 const char *incstack[AST_PBX_MAX_STACK]; 03701 memset(&counters, 0, sizeof(counters)); 03702 03703 if (argc != 2 && argc != 3) 03704 return RESULT_SHOWUSAGE; 03705 03706 /* we obtain [exten@]context? if yes, split them ... */ 03707 if (argc == 3) { 03708 if (strchr(argv[2], '@')) { /* split into exten & context */ 03709 context = ast_strdupa(argv[2]); 03710 exten = strsep(&context, "@"); 03711 /* change empty strings to NULL */ 03712 if (ast_strlen_zero(exten)) 03713 exten = NULL; 03714 } else { /* no '@' char, only context given */ 03715 context = argv[2]; 03716 } 03717 if (ast_strlen_zero(context)) 03718 context = NULL; 03719 } 03720 /* else Show complete dial plan, context and exten are NULL */ 03721 show_dialplan_helper(fd, context, exten, &counters, NULL, 0, incstack); 03722 03723 /* check for input failure and throw some error messages */ 03724 if (context && !counters.context_existence) { 03725 ast_cli(fd, "There is no existence of '%s' context\n", context); 03726 return RESULT_FAILURE; 03727 } 03728 03729 if (exten && !counters.extension_existence) { 03730 if (context) 03731 ast_cli(fd, "There is no existence of %s@%s extension\n", 03732 exten, context); 03733 else 03734 ast_cli(fd, 03735 "There is no existence of '%s' extension in all contexts\n", 03736 exten); 03737 return RESULT_FAILURE; 03738 } 03739 03740 ast_cli(fd,"-= %d %s (%d %s) in %d %s. =-\n", 03741 counters.total_exten, counters.total_exten == 1 ? "extension" : "extensions", 03742 counters.total_prio, counters.total_prio == 1 ? "priority" : "priorities", 03743 counters.total_context, counters.total_context == 1 ? "context" : "contexts"); 03744 03745 /* everything ok */ 03746 return RESULT_SUCCESS; 03747 }
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 3750 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.
03751 { 03752 int i = 0; 03753 struct ast_var_t *newvariable; 03754 03755 ast_mutex_lock(&globalslock); 03756 AST_LIST_TRAVERSE (&globals, newvariable, entries) { 03757 i++; 03758 ast_cli(fd, " %s=%s\n", ast_var_name(newvariable), ast_var_value(newvariable)); 03759 } 03760 ast_mutex_unlock(&globalslock); 03761 ast_cli(fd, "\n -- %d variables\n", i); 03762 03763 return RESULT_SUCCESS; 03764 }
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 3284 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.
03285 { 03286 struct ast_hint *hint; 03287 int num = 0; 03288 int watchers; 03289 struct ast_state_cb *watcher; 03290 03291 if (AST_LIST_EMPTY(&hints)) { 03292 ast_cli(fd, "There are no registered dialplan hints\n"); 03293 return RESULT_SUCCESS; 03294 } 03295 /* ... we have hints ... */ 03296 ast_cli(fd, "\n -= Registered Asterisk Dial Plan Hints =-\n"); 03297 AST_LIST_LOCK(&hints); 03298 AST_LIST_TRAVERSE(&hints, hint, list) { 03299 watchers = 0; 03300 for (watcher = hint->callbacks; watcher; watcher = watcher->next) 03301 watchers++; 03302 ast_cli(fd, " %20s@%-20.20s: %-20.20s State:%-15.15s Watchers %2d\n", 03303 ast_get_extension_name(hint->exten), 03304 ast_get_context_name(ast_get_extension_context(hint->exten)), 03305 ast_get_extension_app(hint->exten), 03306 ast_extension_state2str(hint->laststate), watchers); 03307 num++; 03308 } 03309 ast_cli(fd, "----------------\n"); 03310 ast_cli(fd, "- %d hints registered\n", num); 03311 AST_LIST_UNLOCK(&hints); 03312 return RESULT_SUCCESS; 03313 }
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 3316 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.
03317 { 03318 struct ast_switch *sw; 03319 03320 AST_LIST_LOCK(&switches); 03321 03322 if (AST_LIST_EMPTY(&switches)) { 03323 AST_LIST_UNLOCK(&switches); 03324 ast_cli(fd, "There are no registered alternative switches\n"); 03325 return RESULT_SUCCESS; 03326 } 03327 03328 ast_cli(fd, "\n -= Registered Asterisk Alternative Switches =-\n"); 03329 AST_LIST_TRAVERSE(&switches, sw, list) 03330 ast_cli(fd, "%s: %s\n", sw->name, sw->description); 03331 03332 AST_LIST_UNLOCK(&switches); 03333 03334 return RESULT_SUCCESS; 03335 }
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 2606 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().
02607 { 02608 int failed = 0; 02609 double curloadavg; 02610 ast_mutex_lock(&maxcalllock); 02611 if (option_maxcalls) { 02612 if (countcalls >= option_maxcalls) { 02613 ast_log(LOG_NOTICE, "Maximum call limit of %d calls exceeded by '%s'!\n", option_maxcalls, c->name); 02614 failed = -1; 02615 } 02616 } 02617 if (option_maxload) { 02618 getloadavg(&curloadavg, 1); 02619 if (curloadavg >= option_maxload) { 02620 ast_log(LOG_NOTICE, "Maximum loadavg limit of %f load exceeded by '%s' (currently %f)!\n", option_maxload, c->name, curloadavg); 02621 failed = -1; 02622 } 02623 } 02624 if (!failed) 02625 countcalls++; 02626 ast_mutex_unlock(&maxcalllock); 02627 02628 return failed; 02629 }
int load_pbx | ( | void | ) |
Provided by pbx.c
Definition at line 6234 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().
06235 { 06236 int x; 06237 06238 /* Initialize the PBX */ 06239 if (option_verbose) { 06240 ast_verbose( "Asterisk PBX Core Initializing\n"); 06241 ast_verbose( "Registering builtin applications:\n"); 06242 } 06243 ast_cli_register_multiple(pbx_cli, sizeof(pbx_cli) / sizeof(struct ast_cli_entry)); 06244 06245 /* Register builtin applications */ 06246 for (x=0; x<sizeof(builtins) / sizeof(struct pbx_builtin); x++) { 06247 if (option_verbose) 06248 ast_verbose( VERBOSE_PREFIX_1 "[%s]\n", builtins[x].name); 06249 if (ast_register_application(builtins[x].name, builtins[x].execute, builtins[x].synopsis, builtins[x].description)) { 06250 ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name); 06251 return -1; 06252 } 06253 } 06254 return 0; 06255 }
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 4090 of file pbx.c.
Referenced by get_range().
04091 { 04092 int i; 04093 04094 if (names) { 04095 for (i = 0; names[i]; i++) { 04096 if (!strcasecmp(s, names[i])) 04097 return i+1; 04098 } 04099 } else if (sscanf(s, "%d", &i) == 1 && i >= 1 && i <= max) { 04100 return i; 04101 } 04102 return 0; /* error return */ 04103 }
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 6036 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().
06037 { 06038 struct ast_var_t *vardata; 06039 06040 ast_mutex_lock(&globalslock); 06041 while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries))) 06042 ast_var_delete(vardata); 06043 ast_mutex_unlock(&globalslock); 06044 }
const char* pbx_builtin_getvar_helper | ( | struct ast_channel * | chan, | |
const char * | name | |||
) |
Definition at line 5813 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, AST_LIST_TRAVERSE, ast_mutex_lock(), ast_mutex_unlock(), ast_var_name(), and ast_var_value().
Referenced by __login_exec(), _macro_exec(), _while_exec(), agent_hangup(), agent_read(), agentmonitoroutgoing_exec(), ast_bridge_call(), ast_channel_bridge(), ast_feature_interpret(), ast_monitor_stop(), builtin_automonitor(), check_goto_on_transfer(), common_exec(), conf_exec(), conf_run(), dundi_exec(), dundi_helper(), get_also_info(), get_index(), get_refer_info(), global_read(), iax2_exec(), import_ch(), leave_voicemail(), local_hangup(), misdn_answer(), misdn_hangup(), morsecode_exec(), notify_new_message(), oh323_call(), oh323_hangup(), park_call_full(), pickup_by_mark(), queue_exec(), real_ctx(), retrydial_exec(), return_exec(), ring_entry(), run_agi(), set_config_flags(), sip_addheader(), sla_trunk_exec(), speech_background(), try_calling(), try_suggested_sip_codec(), wait_for_answer(), zt_call(), and zt_hangup().
05814 { 05815 struct ast_var_t *variables; 05816 const char *ret = NULL; 05817 int i; 05818 struct varshead *places[2] = { NULL, &globals }; 05819 05820 if (!name) 05821 return NULL; 05822 05823 if (chan) { 05824 ast_channel_lock(chan); 05825 places[0] = &chan->varshead; 05826 } 05827 05828 for (i = 0; i < 2; i++) { 05829 if (!places[i]) 05830 continue; 05831 if (places[i] == &globals) 05832 ast_mutex_lock(&globalslock); 05833 AST_LIST_TRAVERSE(places[i], variables, entries) { 05834 if (!strcmp(name, ast_var_name(variables))) { 05835 ret = ast_var_value(variables); 05836 break; 05837 } 05838 } 05839 if (places[i] == &globals) 05840 ast_mutex_unlock(&globalslock); 05841 if (ret) 05842 break; 05843 } 05844 05845 if (chan) 05846 ast_channel_unlock(chan); 05847 05848 return ret; 05849 }
static int pbx_builtin_gotoif | ( | struct ast_channel * | , | |
void * | ||||
) | [static] |
Definition at line 6056 of file pbx.c.
References ast_log(), ast_strdupa, ast_strlen_zero(), LOG_WARNING, pbx_builtin_goto(), pbx_checkcondition(), and strsep().
06057 { 06058 char *condition, *branch1, *branch2, *branch; 06059 int rc; 06060 char *stringp; 06061 06062 if (ast_strlen_zero(data)) { 06063 ast_log(LOG_WARNING, "Ignoring, since there is no variable to check\n"); 06064 return 0; 06065 } 06066 06067 stringp = ast_strdupa(data); 06068 condition = strsep(&stringp,"?"); 06069 branch1 = strsep(&stringp,":"); 06070 branch2 = strsep(&stringp,""); 06071 branch = pbx_checkcondition(condition) ? branch1 : branch2; 06072 06073 if (ast_strlen_zero(branch)) { 06074 if (option_debug) 06075 ast_log(LOG_DEBUG, "Not taking any branch\n"); 06076 return 0; 06077 } 06078 06079 rc = pbx_builtin_goto(chan, branch); 06080 06081 return rc; 06082 }
int pbx_builtin_importvar | ( | struct ast_channel * | , | |
void * | ||||
) | [static] |
Definition at line 5975 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.
05976 { 05977 char *name; 05978 char *value; 05979 char *channel; 05980 char tmp[VAR_BUF_SIZE]=""; 05981 05982 if (ast_strlen_zero(data)) { 05983 ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n"); 05984 return 0; 05985 } 05986 05987 value = ast_strdupa(data); 05988 name = strsep(&value,"="); 05989 channel = strsep(&value,"|"); 05990 if (channel && value && name) { /*! \todo XXX should do !ast_strlen_zero(..) of the args ? */ 05991 struct ast_channel *chan2 = ast_get_channel_by_name_locked(channel); 05992 if (chan2) { 05993 char *s = alloca(strlen(value) + 4); 05994 if (s) { 05995 sprintf(s, "${%s}", value); 05996 pbx_substitute_variables_helper(chan2, s, tmp, sizeof(tmp) - 1); 05997 } 05998 ast_channel_unlock(chan2); 05999 } 06000 pbx_builtin_setvar_helper(chan, name, tmp); 06001 } 06002 06003 return(0); 06004 }
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 5851 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().
05852 { 05853 struct ast_var_t *newvariable; 05854 struct varshead *headp; 05855 05856 if (name[strlen(name)-1] == ')') { 05857 char *function = ast_strdupa(name); 05858 05859 ast_log(LOG_WARNING, "Cannot push a value onto a function\n"); 05860 ast_func_write(chan, function, value); 05861 return; 05862 } 05863 05864 if (chan) { 05865 ast_channel_lock(chan); 05866 headp = &chan->varshead; 05867 } else { 05868 ast_mutex_lock(&globalslock); 05869 headp = &globals; 05870 } 05871 05872 if (value) { 05873 if ((option_verbose > 1) && (headp == &globals)) 05874 ast_verbose(VERBOSE_PREFIX_2 "Setting global variable '%s' to '%s'\n", name, value); 05875 newvariable = ast_var_assign(name, value); 05876 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 05877 } 05878 05879 if (chan) 05880 ast_channel_unlock(chan); 05881 else 05882 ast_mutex_unlock(&globalslock); 05883 }
static int pbx_builtin_saycharacters | ( | struct ast_channel * | , | |
void * | ||||
) | [static] |
Definition at line 6121 of file pbx.c.
References ast_say_character_str().
06122 { 06123 int res = 0; 06124 06125 if (data) 06126 res = ast_say_character_str(chan, data, "", chan->language); 06127 return res; 06128 }
static int pbx_builtin_saydate | ( | struct ast_channel * | , | |
void * | ||||
) | [static] |
Definition at line 6139 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().
06140 { 06141 int res = 0; 06142 char *parse; 06143 int unixdate = 0; 06144 char charascii[2]; 06145 06146 AST_DECLARE_APP_ARGS(args, 06147 AST_APP_ARG(datestr); 06148 AST_APP_ARG(digits); 06149 ); 06150 06151 06152 if (ast_strlen_zero(data)) { 06153 ast_log(LOG_WARNING, "SayDate requires an argument (date)\n"); 06154 return -1; 06155 } 06156 06157 if (!(parse = ast_strdupa(data))) { 06158 ast_log(LOG_WARNING, "Memory Error!\n"); 06159 return -1; 06160 } 06161 06162 AST_STANDARD_APP_ARGS(args, parse); 06163 06164 if (!ast_strlen_zero(args.digits) && (strspn(args.digits, "0123456789*#") != strlen(args.digits))) { 06165 ast_log(LOG_WARNING, "SayDate escape digits must be a subset from '0123456789*#'\n"); 06166 args.digits = ""; 06167 } 06168 06169 if (sscanf(args.datestr, "%d", &unixdate) != 1) { 06170 ast_log(LOG_WARNING, "Firt argument to SayDate must be numeric (date)\n"); 06171 return -1; 06172 } 06173 06174 res = ast_say_date(chan, (time_t)unixdate, args.digits, chan->language); 06175 if (res > 0) { 06176 if (isdigit(res) || (res == '*') || (res == '#')) { 06177 snprintf(charascii, 2, "%c", res); 06178 pbx_builtin_setvar_helper(chan, "USER_INPUT", charascii); 06179 res = 0; 06180 } else { 06181 ast_log(LOG_WARNING, "SayDate: invalid return value (%d) detected\n", res); 06182 } 06183 } 06184 return res; 06185 }
static int pbx_builtin_saydigits | ( | struct ast_channel * | , | |
void * | ||||
) | [static] |
Definition at line 6112 of file pbx.c.
References ast_say_digit_str().
06113 { 06114 int res = 0; 06115 06116 if (data) 06117 res = ast_say_digit_str(chan, data, "", chan->language); 06118 return res; 06119 }
static int pbx_builtin_saynumber | ( | struct ast_channel * | , | |
void * | ||||
) | [static] |
Definition at line 6084 of file pbx.c.
References ast_log(), ast_say_number(), ast_strlen_zero(), LOG_WARNING, and strsep().
06085 { 06086 char tmp[256]; 06087 char *number = tmp; 06088 char *options; 06089 06090 if (ast_strlen_zero(data)) { 06091 ast_log(LOG_WARNING, "SayNumber requires an argument (number)\n"); 06092 return -1; 06093 } 06094 ast_copy_string(tmp, data, sizeof(tmp)); 06095 strsep(&number, "|"); 06096 options = strsep(&number, "|"); 06097 if (options) { 06098 if ( strcasecmp(options, "f") && strcasecmp(options,"m") && 06099 strcasecmp(options, "c") && strcasecmp(options, "n") ) { 06100 ast_log(LOG_WARNING, "SayNumber gender option is either 'f', 'm', 'c' or 'n'\n"); 06101 return -1; 06102 } 06103 } 06104 06105 if (ast_say_number(chan, atoi(tmp), "", chan->language, options)) { 06106 ast_log(LOG_WARNING, "We were unable to say the number %s, is it too large?\n", tmp); 06107 } 06108 06109 return 0; 06110 }
static int pbx_builtin_sayphonetic | ( | struct ast_channel * | , | |
void * | ||||
) | [static] |
Definition at line 6130 of file pbx.c.
References ast_say_phonetic_str().
06131 { 06132 int res = 0; 06133 06134 if (data) 06135 res = ast_say_phonetic_str(chan, data, "", chan->language); 06136 return res; 06137 }
static int pbx_builtin_saytime | ( | struct ast_channel * | , | |
void * | ||||
) | [static] |
Definition at line 6187 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().
06188 { 06189 int res = 0; 06190 char *parse; 06191 int secs = 0; 06192 char charascii[2]; 06193 06194 AST_DECLARE_APP_ARGS(args, 06195 AST_APP_ARG(timestr); 06196 AST_APP_ARG(digits); 06197 ); 06198 06199 if (ast_strlen_zero(data)) { 06200 ast_log(LOG_WARNING, "SayTime requires an argument (time in seconds)\n"); 06201 return -1; 06202 } 06203 06204 if (!(parse = ast_strdupa(data))) { 06205 ast_log(LOG_WARNING, "Memory Error!\n"); 06206 return -1; 06207 } 06208 06209 AST_STANDARD_APP_ARGS(args, parse); 06210 06211 if (!ast_strlen_zero(args.digits) && (strspn(args.digits, "0123456789*#") != strlen(args.digits))) { 06212 ast_log(LOG_WARNING, "SayTime escape digits must be a subset from '0123456789*#'\n"); 06213 args.digits = ""; 06214 } 06215 06216 if (sscanf(args.timestr, "%d", &secs) != 1) { 06217 ast_log(LOG_WARNING, "Firt argument to SayTime must be numeric (time in seconds)\n"); 06218 return -1; 06219 } 06220 06221 res = ast_say_time(chan, (time_t)secs, args.digits, chan->language); 06222 if (res > 0) { 06223 if (isdigit(res) || (res == '*') || (res == '#')) { 06224 snprintf(charascii, 2, "%c", res); 06225 pbx_builtin_setvar_helper(chan, "USER_INPUT", charascii); 06226 res = 0; 06227 } else { 06228 ast_log(LOG_WARNING, "SayTime: invalid return value (%d) detected\n", res); 06229 } 06230 } 06231 return res; 06232 }
int pbx_builtin_serialize_variables | ( | struct ast_channel * | chan, | |
char * | buf, | |||
size_t | size | |||
) |
Definition at line 5782 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().
05783 { 05784 struct ast_var_t *variables; 05785 const char *var, *val; 05786 int total = 0; 05787 05788 if (!chan) 05789 return 0; 05790 05791 memset(buf, 0, size); 05792 05793 ast_channel_lock(chan); 05794 05795 AST_LIST_TRAVERSE(&chan->varshead, variables, entries) { 05796 if ((var=ast_var_name(variables)) && (val=ast_var_value(variables)) 05797 /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */ 05798 ) { 05799 if (ast_build_string(&buf, &size, "%s=%s\n", var, val)) { 05800 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n"); 05801 break; 05802 } else 05803 total++; 05804 } else 05805 break; 05806 } 05807 05808 ast_channel_unlock(chan); 05809 05810 return total; 05811 }
static int pbx_builtin_setglobalvar | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 6007 of file pbx.c.
References ast_log(), ast_strlen_zero(), LOG_WARNING, pbx_builtin_setvar_helper(), and strsep().
06008 { 06009 char *name; 06010 char *stringp = data; 06011 static int dep_warning = 0; 06012 06013 if (ast_strlen_zero(data)) { 06014 ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n"); 06015 return 0; 06016 } 06017 06018 name = strsep(&stringp, "="); 06019 06020 if (!dep_warning) { 06021 dep_warning = 1; 06022 ast_log(LOG_WARNING, "SetGlobalVar is deprecated. Please use Set(GLOBAL(%s)=%s) instead.\n", name, stringp); 06023 } 06024 06025 /*! \todo XXX watch out, leading whitespace ? */ 06026 pbx_builtin_setvar_helper(NULL, name, stringp); 06027 06028 return(0); 06029 }
int pbx_builtin_setvar | ( | struct ast_channel * | , | |
void * | ||||
) |
Definition at line 5935 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().
05936 { 05937 char *name, *value, *mydata; 05938 int argc; 05939 char *argv[24]; /* this will only support a maximum of 24 variables being set in a single operation */ 05940 int global = 0; 05941 int x; 05942 05943 if (ast_strlen_zero(data)) { 05944 ast_log(LOG_WARNING, "Set requires at least one variable name/value pair.\n"); 05945 return 0; 05946 } 05947 05948 mydata = ast_strdupa(data); 05949 argc = ast_app_separate_args(mydata, '|', argv, sizeof(argv) / sizeof(argv[0])); 05950 05951 /* check for a trailing flags argument */ 05952 if ((argc > 1) && !strchr(argv[argc-1], '=')) { 05953 argc--; 05954 if (strchr(argv[argc], 'g')) { 05955 ast_log(LOG_WARNING, "The use of the 'g' flag is deprecated. Please use Set(GLOBAL(foo)=bar) instead\n"); 05956 global = 1; 05957 } 05958 } 05959 05960 if (argc > 1) 05961 ast_log(LOG_WARNING, "Setting multiple variables at once within Set is deprecated. Please separate each name/value pair into its own line.\n"); 05962 05963 for (x = 0; x < argc; x++) { 05964 name = argv[x]; 05965 if ((value = strchr(name, '='))) { 05966 *value++ = '\0'; 05967 pbx_builtin_setvar_helper((global) ? NULL : chan, name, value); 05968 } else 05969 ast_log(LOG_WARNING, "Ignoring entry '%s' with no = (and not last 'options' entry)\n", name); 05970 } 05971 05972 return(0); 05973 }
void pbx_builtin_setvar_helper | ( | struct ast_channel * | chan, | |
const char * | name, | |||
const char * | value | |||
) |
Definition at line 5885 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(), 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(), vmauthenticate(), zt_handle_dtmfup(), and zt_new().
05886 { 05887 struct ast_var_t *newvariable; 05888 struct varshead *headp; 05889 const char *nametail = name; 05890 05891 if (name[strlen(name)-1] == ')') { 05892 char *function = ast_strdupa(name); 05893 05894 ast_func_write(chan, function, value); 05895 return; 05896 } 05897 05898 if (chan) { 05899 ast_channel_lock(chan); 05900 headp = &chan->varshead; 05901 } else { 05902 ast_mutex_lock(&globalslock); 05903 headp = &globals; 05904 } 05905 05906 /* For comparison purposes, we have to strip leading underscores */ 05907 if (*nametail == '_') { 05908 nametail++; 05909 if (*nametail == '_') 05910 nametail++; 05911 } 05912 05913 AST_LIST_TRAVERSE (headp, newvariable, entries) { 05914 if (strcasecmp(ast_var_name(newvariable), nametail) == 0) { 05915 /* there is already such a variable, delete it */ 05916 AST_LIST_REMOVE(headp, newvariable, entries); 05917 ast_var_delete(newvariable); 05918 break; 05919 } 05920 } 05921 05922 if (value) { 05923 if ((option_verbose > 1) && (headp == &globals)) 05924 ast_verbose(VERBOSE_PREFIX_2 "Setting global variable '%s' to '%s'\n", name, value); 05925 newvariable = ast_var_assign(name, value); 05926 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 05927 } 05928 05929 if (chan) 05930 ast_channel_unlock(chan); 05931 else 05932 ast_mutex_unlock(&globalslock); 05933 }
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 6046 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().
06047 { 06048 if (ast_strlen_zero(condition)) /* NULL or empty strings are false */ 06049 return 0; 06050 else if (*condition >= '0' && *condition <= '9') /* Numbers are evaluated for truth */ 06051 return atoi(condition); 06052 else /* Strings are true */ 06053 return 1; 06054 }
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 2713 of file pbx.c.
References autofallthrough.
Referenced by pbx_load_module().
02714 { 02715 int oldval = autofallthrough; 02716 autofallthrough = newval; 02717 return oldval; 02718 }
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 2649 of file pbx.c.
References __ast_pbx_run(), and decrease_call_count().
Referenced by ast_pbx_start().
02650 { 02651 /* Oh joyeous kernel, we're a new thread, with nothing to do but 02652 answer this channel and get it going. 02653 */ 02654 /* NOTE: 02655 The launcher of this function _MUST_ increment 'countcalls' 02656 before invoking the function; it will be decremented when the 02657 PBX has finished running on the channel 02658 */ 02659 struct ast_channel *c = data; 02660 02661 __ast_pbx_run(c); 02662 decrease_call_count(); 02663 02664 pthread_exit(NULL); 02665 02666 return NULL; 02667 }
static void print_ext | ( | struct ast_exten * | e, | |
char * | buf, | |||
int | buflen | |||
) | [static] |
helper function to print an extension
Definition at line 3532 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().
03533 { 03534 int prio = ast_get_extension_priority(e); 03535 if (prio == PRIORITY_HINT) { 03536 snprintf(buf, buflen, "hint: %s", 03537 ast_get_extension_app(e)); 03538 } else { 03539 snprintf(buf, buflen, "%d. %s(%s)", 03540 prio, ast_get_extension_app(e), 03541 (!ast_strlen_zero(ast_get_extension_app_data(e)) ? (char *)ast_get_extension_app_data(e) : "")); 03542 } 03543 }
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 3546 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().
03547 { 03548 struct ast_context *c = NULL; 03549 int res = 0, old_total_exten = dpc->total_exten; 03550 03551 ast_rdlock_contexts(); 03552 03553 /* walk all contexts ... */ 03554 while ( (c = ast_walk_contexts(c)) ) { 03555 struct ast_exten *e; 03556 struct ast_include *i; 03557 struct ast_ignorepat *ip; 03558 char buf[256], buf2[256]; 03559 int context_info_printed = 0; 03560 03561 if (context && strcmp(ast_get_context_name(c), context)) 03562 continue; /* skip this one, name doesn't match */ 03563 03564 dpc->context_existence = 1; 03565 03566 ast_lock_context(c); 03567 03568 /* are we looking for exten too? if yes, we print context 03569 * only if we find our extension. 03570 * Otherwise print context even if empty ? 03571 * XXX i am not sure how the rinclude is handled. 03572 * I think it ought to go inside. 03573 */ 03574 if (!exten) { 03575 dpc->total_context++; 03576 ast_cli(fd, "[ Context '%s' created by '%s' ]\n", 03577 ast_get_context_name(c), ast_get_context_registrar(c)); 03578 context_info_printed = 1; 03579 } 03580 03581 /* walk extensions ... */ 03582 e = NULL; 03583 while ( (e = ast_walk_context_extensions(c, e)) ) { 03584 struct ast_exten *p; 03585 03586 if (exten && !ast_extension_match(ast_get_extension_name(e), exten)) 03587 continue; /* skip, extension match failed */ 03588 03589 dpc->extension_existence = 1; 03590 03591 /* may we print context info? */ 03592 if (!context_info_printed) { 03593 dpc->total_context++; 03594 if (rinclude) { /* TODO Print more info about rinclude */ 03595 ast_cli(fd, "[ Included context '%s' created by '%s' ]\n", 03596 ast_get_context_name(c), ast_get_context_registrar(c)); 03597 } else { 03598 ast_cli(fd, "[ Context '%s' created by '%s' ]\n", 03599 ast_get_context_name(c), ast_get_context_registrar(c)); 03600 } 03601 context_info_printed = 1; 03602 } 03603 dpc->total_prio++; 03604 03605 /* write extension name and first peer */ 03606 snprintf(buf, sizeof(buf), "'%s' =>", ast_get_extension_name(e)); 03607 03608 print_ext(e, buf2, sizeof(buf2)); 03609 03610 ast_cli(fd, " %-17s %-45s [%s]\n", buf, buf2, 03611 ast_get_extension_registrar(e)); 03612 03613 dpc->total_exten++; 03614 /* walk next extension peers */ 03615 p = e; /* skip the first one, we already got it */ 03616 while ( (p = ast_walk_extension_priorities(e, p)) ) { 03617 const char *el = ast_get_extension_label(p); 03618 dpc->total_prio++; 03619 if (el) 03620 snprintf(buf, sizeof(buf), " [%s]", el); 03621 else 03622 buf[0] = '\0'; 03623 print_ext(p, buf2, sizeof(buf2)); 03624 03625 ast_cli(fd," %-17s %-45s [%s]\n", buf, buf2, 03626 ast_get_extension_registrar(p)); 03627 } 03628 } 03629 03630 /* walk included and write info ... */ 03631 i = NULL; 03632 while ( (i = ast_walk_context_includes(c, i)) ) { 03633 snprintf(buf, sizeof(buf), "'%s'", ast_get_include_name(i)); 03634 if (exten) { 03635 /* Check all includes for the requested extension */ 03636 if (includecount >= AST_PBX_MAX_STACK) { 03637 ast_log(LOG_NOTICE, "Maximum include depth exceeded!\n"); 03638 } else { 03639 int dupe=0; 03640 int x; 03641 for (x=0;x<includecount;x++) { 03642 if (!strcasecmp(includes[x], ast_get_include_name(i))) { 03643 dupe++; 03644 break; 03645 } 03646 } 03647 if (!dupe) { 03648 includes[includecount] = ast_get_include_name(i); 03649 show_dialplan_helper(fd, ast_get_include_name(i), exten, dpc, i, includecount + 1, includes); 03650 } else { 03651 ast_log(LOG_WARNING, "Avoiding circular include of %s within %s\n", ast_get_include_name(i), context); 03652 } 03653 } 03654 } else { 03655 ast_cli(fd, " Include => %-45s [%s]\n", 03656 buf, ast_get_include_registrar(i)); 03657 } 03658 } 03659 03660 /* walk ignore patterns and write info ... */ 03661 ip = NULL; 03662 while ( (ip = ast_walk_context_ignorepats(c, ip)) ) { 03663 const char *ipname = ast_get_ignorepat_name(ip); 03664 char ignorepat[AST_MAX_EXTENSION]; 03665 snprintf(buf, sizeof(buf), "'%s'", ipname); 03666 snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname); 03667 if (!exten || ast_extension_match(ignorepat, exten)) { 03668 ast_cli(fd, " Ignore pattern => %-45s [%s]\n", 03669 buf, ast_get_ignorepat_registrar(ip)); 03670 } 03671 } 03672 if (!rinclude) { 03673 struct ast_sw *sw = NULL; 03674 while ( (sw = ast_walk_context_switches(c, sw)) ) { 03675 snprintf(buf, sizeof(buf), "'%s/%s'", 03676 ast_get_switch_name(sw), 03677 ast_get_switch_data(sw)); 03678 ast_cli(fd, " Alt. Switch => %-45s [%s]\n", 03679 buf, ast_get_switch_registrar(sw)); 03680 } 03681 } 03682 03683 ast_unlock_context(c); 03684 03685 /* if we print something in context, make an empty line */ 03686 if (context_info_printed) 03687 ast_cli(fd, "\r\n"); 03688 } 03689 ast_unlock_contexts(); 03690 03691 return (dpc->total_exten == old_total_exten) ? -1 : res; 03692 }
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 5393 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().
05394 { 05395 int res; 05396 struct ast_frame *f; 05397 int waittime; 05398 05399 if (ast_strlen_zero(data) || (sscanf(data, "%d", &waittime) != 1) || (waittime < 0)) 05400 waittime = -1; 05401 if (waittime > -1) { 05402 ast_safe_sleep(chan, waittime * 1000); 05403 } else do { 05404 res = ast_waitfor(chan, -1); 05405 if (res < 0) 05406 return; 05407 f = ast_read(chan); 05408 if (f) 05409 ast_frfree(f); 05410 } while(f); 05411 }
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().