#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"
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) |
Main interface to add extensions to the list for out 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). | |
struct 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). | |
struct ast_context * | ast_context_find (const char *name) |
Find a context. | |
struct 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. | |
struct 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) |
ast_extension_state: Check extension state for an extension by using hint | |
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) |
ast_extension_state2str: Return extension_state as string | |
int | ast_extension_state_add (const char *context, const char *exten, ast_state_cb_type callback, void *data) |
ast_extension_state_add: Add watcher for extension states | |
int | ast_extension_state_del (int id, ast_state_cb_type callback) |
ast_extension_state_del: Remove a watcher from the callback list | |
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) |
struct 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) |
ast_get_hint: Get hint for channel | |
const char * | ast_get_ignorepat_name (struct ast_ignorepat *ip) |
const char * | ast_get_ignorepat_registrar (struct ast_ignorepat *ip) |
const char * | ast_get_include_name (struct ast_include *inc) |
const char * | ast_get_include_registrar (struct ast_include *i) |
const char * | ast_get_switch_data (struct ast_sw *sw) |
const char * | ast_get_switch_name (struct ast_sw *sw) |
const char * | ast_get_switch_registrar (struct ast_sw *sw) |
int | ast_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority) |
static struct ast_exten * | ast_hint_extension (struct ast_channel *c, const char *context, const char *exten) |
ast_hint_extension: Find hint for given extension in context | |
void | ast_hint_state_changed (const char *device) |
int | ast_ignore_pattern (const char *context, const char *pattern) |
Checks to see if a number should be ignored. | |
AST_LIST_HEAD (store_hints, store_hint) | |
static | AST_LIST_HEAD_STATIC (hints, ast_hint) |
static | AST_LIST_HEAD_STATIC (switches, ast_switch) |
static | AST_LIST_HEAD_STATIC (apps, ast_app) |
static | AST_LIST_HEAD_STATIC (acf_root, ast_custom_function) |
int | ast_lock_context (struct ast_context *con) |
Locks a given context. | |
int | ast_lock_contexts () |
Locks the context list. | |
int | ast_matchmore_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid) |
Looks to see if adding anything to this extension might match something. (exists ^ canmatch). | |
void | ast_merge_contexts_and_delete (struct ast_context **extcontexts, const char *registrar) |
Merge the temporary contexts into a global contexts list and delete from the global list the ones that are being added. | |
AST_MUTEX_DEFINE_STATIC (conlock) | |
AST_MUTEX_DEFINE_STATIC (maxcalllock) | |
AST_MUTEX_DEFINE_STATIC (globalslock) | |
int | ast_parseable_goto (struct ast_channel *chan, const char *goto_string) |
int | ast_pbx_outgoing_app (const char *type, int format, void *data, int timeout, const char *app, const char *appdata, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel) |
static int | ast_pbx_outgoing_cdr_failed (void) |
int | ast_pbx_outgoing_exten (const char *type, int format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **channel) |
enum ast_pbx_result | ast_pbx_run (struct ast_channel *c) |
Execute the PBX in the current thread. | |
static void * | ast_pbx_run_app (void *data) |
run the application and free the descriptor once done | |
enum ast_pbx_result | ast_pbx_start (struct ast_channel *c) |
Create a new thread and start the PBX. | |
int | ast_register_application (const char *app, int(*execute)(struct ast_channel *, void *), const char *synopsis, const char *description) |
Dynamically register a new dial plan application. | |
int | ast_register_switch (struct ast_switch *sw) |
Register an alternative dialplan switch. | |
static int | ast_remove_hint (struct ast_exten *e) |
ast_remove_hint: Remove hint from extension | |
int | ast_spawn_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid) |
Launch a new extension (i.e. new stack). | |
int | ast_unlock_context (struct ast_context *con) |
int | ast_unlock_contexts () |
Unlocks contexts. | |
int | ast_unregister_application (const char *app) |
Unregister an application. | |
void | ast_unregister_switch (struct ast_switch *sw) |
Unregister an alternative switch. | |
struct ast_exten * | ast_walk_context_extensions (struct ast_context *con, struct ast_exten *exten) |
struct ast_ignorepat * | ast_walk_context_ignorepats (struct ast_context *con, struct ast_ignorepat *ip) |
struct ast_include * | ast_walk_context_includes (struct ast_context *con, struct ast_include *inc) |
struct ast_sw * | ast_walk_context_switches (struct ast_context *con, struct ast_sw *sw) |
struct ast_context * | ast_walk_contexts (struct ast_context *con) |
struct ast_exten * | ast_walk_extension_priorities (struct ast_exten *exten, struct ast_exten *priority) |
static void * | async_wait (void *data) |
static int | collect_digits (struct ast_channel *c, int waittime, char *buf, int buflen, int pos) |
collect digits from the channel into the buffer, return -1 on error, 0 on timeout or done. | |
static char * | complete_show_application (const char *line, const char *word, int pos, int state) |
static char * | complete_show_applications (const char *line, const char *word, int pos, int state) |
static char * | complete_show_applications_deprecated (const char *line, const char *word, int pos, int state) |
static char * | complete_show_dialplan_context (const char *line, const char *word, int pos, int state) |
static char * | complete_show_function (const char *line, const char *word, int pos, int state) |
static void | decrease_call_count (void) |
static void | destroy_exten (struct ast_exten *e) |
static int | ext_cmp (const char *a, const char *b) |
the full routine to compare extensions in rules. | |
static int | ext_cmp1 (const char **p) |
helper functions to sort extensions and patterns in the desired way, so that more specific patterns appear first. | |
static int | ext_strncpy (char *dst, const char *src, int len) |
copy a string skipping whitespace | |
static int | extension_match_core (const char *pattern, const char *data, enum ext_match_t mode) |
static struct ast_context * | find_context_locked (const char *context) |
static char * | func_args (char *function) |
return a pointer to the arguments of the function, and terminates the function name with '\0' | |
static unsigned | get_range (char *src, int max, char *const names[], const char *msg) |
helper function to return a range up to max (7, 12, 31 respectively). names, if supplied, is an array of names that should be mapped to numbers. | |
static void | get_timerange (struct ast_timing *i, char *times) |
store a bitmask of valid times, one bit each 2 minute | |
static int | handle_set_global (int fd, int argc, char *argv[]) |
static int | handle_set_global_deprecated (int fd, int argc, char *argv[]) |
CLI support for setting global variables. | |
static int | handle_show_application (int fd, int argc, char *argv[]) |
static int | handle_show_application_deprecated (int fd, int argc, char *argv[]) |
static int | handle_show_applications (int fd, int argc, char *argv[]) |
static int | handle_show_applications_deprecated (int fd, int argc, char *argv[]) |
static int | handle_show_dialplan (int fd, int argc, char *argv[]) |
static int | handle_show_function (int fd, int argc, char *argv[]) |
static int | handle_show_function_deprecated (int fd, int argc, char *argv[]) |
static int | handle_show_functions (int fd, int argc, char *argv[]) |
static int | handle_show_functions_deprecated (int fd, int argc, char *argv[]) |
static int | handle_show_globals (int fd, int argc, char *argv[]) |
CLI support for listing global variables in a parseable way. | |
static int | handle_show_hints (int fd, int argc, char *argv[]) |
handle_show_hints: CLI support for listing 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_saydigits (struct ast_channel *, void *) |
static int | pbx_builtin_saynumber (struct ast_channel *, void *) |
static int | pbx_builtin_sayphonetic (struct ast_channel *, void *) |
int | pbx_builtin_serialize_variables (struct ast_channel *chan, char *buf, size_t size) |
static int | pbx_builtin_setamaflags (struct ast_channel *, void *) |
static int | pbx_builtin_setglobalvar (struct ast_channel *, void *) |
int | pbx_builtin_setvar (struct ast_channel *, void *) |
void | pbx_builtin_setvar_helper (struct ast_channel *chan, const char *name, const char *value) |
static int | pbx_builtin_wait (struct ast_channel *, void *) |
static int | pbx_builtin_waitexten (struct ast_channel *, void *) |
int | pbx_checkcondition (const char *condition) |
Evaluate a condition. | |
static void | pbx_destroy (struct ast_pbx *p) |
int | pbx_exec (struct ast_channel *c, struct ast_app *app, void *data) |
Execute an application. | |
static int | pbx_extension_helper (struct ast_channel *c, struct ast_context *con, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action) |
The return value depends on the action:. | |
static struct ast_exten * | pbx_find_extension (struct ast_channel *chan, struct ast_context *bypass, struct pbx_find_info *q, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action) |
struct ast_app * | pbx_findapp (const char *app) |
Find application handle in linked list. | |
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 [] |
struct 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 544 of file pbx.c.
Referenced by handle_show_dialplan(), pbx_find_extension(), and show_dialplan_helper().
#define BACKGROUND_MATCHEXTEN (1 << 2) |
#define BACKGROUND_NOANSWER (1 << 1) |
#define BACKGROUND_PLAYBACK (1 << 3) |
#define BACKGROUND_SKIP (1 << 0) |
#define EXT_DATA_SIZE 8192 |
Definition at line 77 of file pbx.c.
Referenced by pbx_extension_helper(), and realtime_exec().
#define STATUS_NO_CONTEXT 1 |
Definition at line 902 of file pbx.c.
Referenced by pbx_extension_helper(), and pbx_find_extension().
#define STATUS_NO_EXTENSION 2 |
Definition at line 903 of file pbx.c.
Referenced by pbx_extension_helper(), and pbx_find_extension().
#define STATUS_NO_LABEL 4 |
Definition at line 905 of file pbx.c.
Referenced by pbx_extension_helper(), and pbx_find_extension().
#define STATUS_NO_PRIORITY 3 |
Definition at line 904 of file pbx.c.
Referenced by pbx_extension_helper(), and pbx_find_extension().
#define STATUS_SUCCESS 5 |
#define SWITCH_DATA_LENGTH 256 |
Definition at line 80 of file pbx.c.
Referenced by ast_context_add_switch2(), and pbx_find_extension().
#define VAR_BUF_SIZE 4096 |
Definition at line 82 of file pbx.c.
Referenced by ast_add_extension2(), pbx_builtin_importvar(), and pbx_substitute_variables_helper_full().
#define WAITEXTEN_MOH (1 << 0) |
enum ext_match_t |
When looking up extensions, we can have different requests identified by the 'action' argument, as follows. Note that the coding is such that the low 4 bits are the third argument to extension_match_core.
Definition at line 749 of file pbx.c.
00749 { 00750 E_MATCHMORE = 0x00, /* extension can match but only with more 'digits' */ 00751 E_CANMATCH = 0x01, /* extension can match with or without more 'digits' */ 00752 E_MATCH = 0x02, /* extension is an exact match */ 00753 E_MATCH_MASK = 0x03, /* mask for the argument to extension_match_core() */ 00754 E_SPAWN = 0x12, /* want to spawn an extension. Requires exact match */ 00755 E_FINDLABEL = 0x22 /* returns the priority for a given label. Requires exact match */ 00756 };
static struct ast_context* __ast_context_create | ( | struct ast_context ** | extcontexts, | |
const char * | name, | |||
const char * | registrar, | |||
int | existsokay | |||
) | [static, read] |
Definition at line 3840 of file pbx.c.
References ast_calloc, ast_log(), ast_mutex_init(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), contexts, ast_context::ignorepats, ast_context::includes, local_contexts, ast_context::lock, LOG_DEBUG, LOG_WARNING, ast_context::next, option_debug, option_verbose, ast_context::registrar, ast_context::root, and VERBOSE_PREFIX_3.
Referenced by ast_context_create(), and ast_context_find_or_create().
03841 { 03842 struct ast_context *tmp, **local_contexts; 03843 int length = sizeof(struct ast_context) + strlen(name) + 1; 03844 03845 if (!extcontexts) { 03846 ast_mutex_lock(&conlock); 03847 local_contexts = &contexts; 03848 } else 03849 local_contexts = extcontexts; 03850 03851 for (tmp = *local_contexts; tmp; tmp = tmp->next) { 03852 if (!strcasecmp(tmp->name, name)) { 03853 if (!existsokay) { 03854 ast_log(LOG_WARNING, "Tried to register context '%s', already in use\n", name); 03855 tmp = NULL; 03856 } 03857 if (!extcontexts) 03858 ast_mutex_unlock(&conlock); 03859 return tmp; 03860 } 03861 } 03862 if ((tmp = ast_calloc(1, length))) { 03863 ast_mutex_init(&tmp->lock); 03864 ast_mutex_init(&tmp->macrolock); 03865 strcpy(tmp->name, name); 03866 tmp->root = NULL; 03867 tmp->registrar = registrar; 03868 tmp->next = *local_contexts; 03869 tmp->includes = NULL; 03870 tmp->ignorepats = NULL; 03871 *local_contexts = tmp; 03872 if (option_debug) 03873 ast_log(LOG_DEBUG, "Registered context '%s'\n", tmp->name); 03874 if (option_verbose > 2) 03875 ast_verbose( VERBOSE_PREFIX_3 "Registered extension context '%s'\n", tmp->name); 03876 } 03877 03878 if (!extcontexts) 03879 ast_mutex_unlock(&conlock); 03880 return tmp; 03881 }
void __ast_context_destroy | ( | struct ast_context * | con, | |
const char * | registrar | |||
) |
Definition at line 5259 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, LOG_DEBUG, ast_exten::next, ast_ignorepat::next, ast_include::next, ast_context::next, option_debug, and ast_exten::peer.
Referenced by ast_context_destroy(), and ast_merge_contexts_and_delete().
05260 { 05261 struct ast_context *tmp, *tmpl=NULL; 05262 struct ast_include *tmpi; 05263 struct ast_sw *sw; 05264 struct ast_exten *e, *el, *en; 05265 struct ast_ignorepat *ipi; 05266 05267 ast_mutex_lock(&conlock); 05268 for (tmp = contexts; tmp; ) { 05269 struct ast_context *next; /* next starting point */ 05270 for (; tmp; tmpl = tmp, tmp = tmp->next) { 05271 if (option_debug) 05272 ast_log(LOG_DEBUG, "check ctx %s %s\n", tmp->name, tmp->registrar); 05273 if ( (!registrar || !strcasecmp(registrar, tmp->registrar)) && 05274 (!con || !strcasecmp(tmp->name, con->name)) ) 05275 break; /* found it */ 05276 } 05277 if (!tmp) /* not found, we are done */ 05278 break; 05279 ast_mutex_lock(&tmp->lock); 05280 if (option_debug) 05281 ast_log(LOG_DEBUG, "delete ctx %s %s\n", tmp->name, tmp->registrar); 05282 next = tmp->next; 05283 if (tmpl) 05284 tmpl->next = next; 05285 else 05286 contexts = next; 05287 /* Okay, now we're safe to let it go -- in a sense, we were 05288 ready to let it go as soon as we locked it. */ 05289 ast_mutex_unlock(&tmp->lock); 05290 for (tmpi = tmp->includes; tmpi; ) { /* Free includes */ 05291 struct ast_include *tmpil = tmpi; 05292 tmpi = tmpi->next; 05293 free(tmpil); 05294 } 05295 for (ipi = tmp->ignorepats; ipi; ) { /* Free ignorepats */ 05296 struct ast_ignorepat *ipl = ipi; 05297 ipi = ipi->next; 05298 free(ipl); 05299 } 05300 while ((sw = AST_LIST_REMOVE_HEAD(&tmp->alts, list))) 05301 free(sw); 05302 for (e = tmp->root; e;) { 05303 for (en = e->peer; en;) { 05304 el = en; 05305 en = en->peer; 05306 destroy_exten(el); 05307 } 05308 el = e; 05309 e = e->next; 05310 destroy_exten(el); 05311 } 05312 ast_mutex_destroy(&tmp->lock); 05313 free(tmp); 05314 /* if we have a specific match, we are done, otherwise continue */ 05315 tmp = con ? NULL : next; 05316 } 05317 ast_mutex_unlock(&conlock); 05318 }
static int __ast_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority, | |||
int | async | |||
) | [static] |
Definition at line 6245 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().
06246 { 06247 int (*goto_func)(struct ast_channel *chan, const char *context, const char *exten, int priority); 06248 06249 if (!chan) 06250 return -2; 06251 06252 if (context == NULL) 06253 context = chan->context; 06254 if (exten == NULL) 06255 exten = chan->exten; 06256 06257 goto_func = (async) ? ast_async_goto : ast_explicit_goto; 06258 if (ast_exists_extension(chan, context, exten, priority, chan->cid.cid_num)) 06259 return goto_func(chan, context, exten, priority); 06260 else 06261 return -3; 06262 }
static int __ast_pbx_run | ( | struct ast_channel * | c | ) | [static] |
Definition at line 2328 of file pbx.c.
References ast_channel::_softhangup, ast_channel::amaflags, ast_calloc, AST_CAUSE_NORMAL_CLEARING, ast_cdr_alloc(), ast_cdr_end(), ast_cdr_init(), ast_cdr_start(), ast_cdr_update(), ast_exists_extension(), AST_FLAG_IN_AUTOLOOP, ast_hangup(), ast_log(), ast_opt_end_cdr_before_h_exten, AST_PBX_KEEPALIVE, ast_set2_flag, ast_set_flag, ast_softhangup(), AST_SOFTHANGUP_ASYNCGOTO, AST_SOFTHANGUP_TIMEOUT, ast_spawn_extension(), ast_strlen_zero(), ast_test_flag, ast_verbose(), autofallthrough, ast_channel::cdr, ast_channel::cid, ast_callerid::cid_num, collect_digits(), ast_channel::context, ast_pbx::dtimeout, error(), ast_channel::exten, free, ast_channel::hangupcause, LOG_DEBUG, LOG_WARNING, option_debug, option_verbose, ast_channel::pbx, pbx_builtin_busy(), pbx_builtin_congestion(), pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), pbx_destroy(), ast_channel::priority, ast_pbx::rtimeout, set_ext_pri(), ast_cdr::start, VERBOSE_PREFIX_2, VERBOSE_PREFIX_3, and ast_channel::whentohangup.
Referenced by ast_pbx_run(), and pbx_thread().
02329 { 02330 int found = 0; /* set if we find at least one match */ 02331 int res = 0; 02332 int autoloopflag; 02333 int error = 0; /* set an error conditions */ 02334 02335 /* A little initial setup here */ 02336 if (c->pbx) { 02337 ast_log(LOG_WARNING, "%s already has PBX structure??\n", c->name); 02338 /* XXX and now what ? */ 02339 free(c->pbx); 02340 } 02341 if (!(c->pbx = ast_calloc(1, sizeof(*c->pbx)))) 02342 return -1; 02343 if (c->amaflags) { 02344 if (!c->cdr) { 02345 c->cdr = ast_cdr_alloc(); 02346 if (!c->cdr) { 02347 ast_log(LOG_WARNING, "Unable to create Call Detail Record\n"); 02348 free(c->pbx); 02349 return -1; 02350 } 02351 ast_cdr_init(c->cdr, c); 02352 } 02353 } 02354 /* Set reasonable defaults */ 02355 c->pbx->rtimeout = 10; 02356 c->pbx->dtimeout = 5; 02357 02358 autoloopflag = ast_test_flag(c, AST_FLAG_IN_AUTOLOOP); /* save value to restore at the end */ 02359 ast_set_flag(c, AST_FLAG_IN_AUTOLOOP); 02360 02361 /* Start by trying whatever the channel is set to */ 02362 if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) { 02363 /* If not successful fall back to 's' */ 02364 if (option_verbose > 1) 02365 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); 02366 /* XXX the original code used the existing priority in the call to 02367 * ast_exists_extension(), and reset it to 1 afterwards. 02368 * I believe the correct thing is to set it to 1 immediately. 02369 */ 02370 set_ext_pri(c, "s", 1); 02371 if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) { 02372 /* JK02: And finally back to default if everything else failed */ 02373 if (option_verbose > 1) 02374 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); 02375 ast_copy_string(c->context, "default", sizeof(c->context)); 02376 } 02377 } 02378 if (c->cdr && ast_tvzero(c->cdr->start)) 02379 ast_cdr_start(c->cdr); 02380 for (;;) { 02381 char dst_exten[256]; /* buffer to accumulate digits */ 02382 int pos = 0; /* XXX should check bounds */ 02383 int digit = 0; 02384 02385 /* loop on priorities in this context/exten */ 02386 while (ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) { 02387 found = 1; 02388 if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num))) { 02389 /* Something bad happened, or a hangup has been requested. */ 02390 if (strchr("0123456789ABCDEF*#", res)) { 02391 if (option_debug) 02392 ast_log(LOG_DEBUG, "Oooh, got something to jump out with ('%c')!\n", res); 02393 pos = 0; 02394 dst_exten[pos++] = digit = res; 02395 dst_exten[pos] = '\0'; 02396 break; 02397 } 02398 if (res == AST_PBX_KEEPALIVE) { 02399 if (option_debug) 02400 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name); 02401 if (option_verbose > 1) 02402 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name); 02403 error = 1; 02404 break; 02405 } 02406 if (option_debug) 02407 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 02408 if (option_verbose > 1) 02409 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 02410 if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) { 02411 c->_softhangup =0; 02412 } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) { 02413 /* atimeout, nothing bad */ 02414 } else { 02415 if (c->cdr) 02416 ast_cdr_update(c); 02417 error = 1; 02418 break; 02419 } 02420 } 02421 if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT && ast_exists_extension(c,c->context,"T",1,c->cid.cid_num)) { 02422 set_ext_pri(c, "T", 0); /* 0 will become 1 with the c->priority++; at the end */ 02423 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 02424 c->whentohangup = 0; 02425 c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT; 02426 } else if (c->_softhangup) { 02427 if (option_debug) 02428 ast_log(LOG_DEBUG, "Extension %s, priority %d returned normally even though call was hung up\n", 02429 c->exten, c->priority); 02430 error = 1; 02431 break; 02432 } 02433 c->priority++; 02434 } /* end while - from here on we can use 'break' to go out */ 02435 if (error) 02436 break; 02437 02438 /* XXX we get here on non-existing extension or a keypress or hangup ? */ 02439 02440 if (!ast_exists_extension(c, c->context, c->exten, 1, c->cid.cid_num)) { 02441 /* If there is no match at priority 1, it is not a valid extension anymore. 02442 * Try to continue at "i", 1 or exit if the latter does not exist. 02443 */ 02444 if (ast_exists_extension(c, c->context, "i", 1, c->cid.cid_num)) { 02445 if (option_verbose > 2) 02446 ast_verbose(VERBOSE_PREFIX_3 "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, c->name); 02447 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", c->exten); 02448 set_ext_pri(c, "i", 1); 02449 } else { 02450 ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n", 02451 c->name, c->exten, c->context); 02452 error = 1; /* we know what to do with it */ 02453 break; 02454 } 02455 } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) { 02456 /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */ 02457 c->_softhangup = 0; 02458 } else { /* keypress received, get more digits for a full extension */ 02459 int waittime = 0; 02460 if (digit) 02461 waittime = c->pbx->dtimeout; 02462 else if (!autofallthrough) 02463 waittime = c->pbx->rtimeout; 02464 if (!waittime) { 02465 const char *status = pbx_builtin_getvar_helper(c, "DIALSTATUS"); 02466 if (!status) 02467 status = "UNKNOWN"; 02468 if (option_verbose > 2) 02469 ast_verbose(VERBOSE_PREFIX_2 "Auto fallthrough, channel '%s' status is '%s'\n", c->name, status); 02470 if (!strcasecmp(status, "CONGESTION")) 02471 res = pbx_builtin_congestion(c, "10"); 02472 else if (!strcasecmp(status, "CHANUNAVAIL")) 02473 res = pbx_builtin_congestion(c, "10"); 02474 else if (!strcasecmp(status, "BUSY")) 02475 res = pbx_builtin_busy(c, "10"); 02476 error = 1; /* XXX disable message */ 02477 break; /* exit from the 'for' loop */ 02478 } 02479 02480 if (collect_digits(c, waittime, dst_exten, sizeof(dst_exten), pos)) 02481 break; 02482 if (ast_exists_extension(c, c->context, dst_exten, 1, c->cid.cid_num)) /* Prepare the next cycle */ 02483 set_ext_pri(c, dst_exten, 1); 02484 else { 02485 /* No such extension */ 02486 if (!ast_strlen_zero(dst_exten)) { 02487 /* An invalid extension */ 02488 if (ast_exists_extension(c, c->context, "i", 1, c->cid.cid_num)) { 02489 if (option_verbose > 2) 02490 ast_verbose( VERBOSE_PREFIX_3 "Invalid extension '%s' in context '%s' on %s\n", dst_exten, c->context, c->name); 02491 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", dst_exten); 02492 set_ext_pri(c, "i", 1); 02493 } else { 02494 ast_log(LOG_WARNING, "Invalid extension '%s', but no rule 'i' in context '%s'\n", dst_exten, c->context); 02495 found = 1; /* XXX disable message */ 02496 break; 02497 } 02498 } else { 02499 /* A simple timeout */ 02500 if (ast_exists_extension(c, c->context, "t", 1, c->cid.cid_num)) { 02501 if (option_verbose > 2) 02502 ast_verbose( VERBOSE_PREFIX_3 "Timeout on %s\n", c->name); 02503 set_ext_pri(c, "t", 1); 02504 } else { 02505 ast_log(LOG_WARNING, "Timeout, but no rule 't' in context '%s'\n", c->context); 02506 found = 1; /* XXX disable message */ 02507 break; 02508 } 02509 } 02510 } 02511 if (c->cdr) { 02512 if (option_verbose > 2) 02513 ast_verbose(VERBOSE_PREFIX_2 "CDR updated on %s\n",c->name); 02514 ast_cdr_update(c); 02515 } 02516 } 02517 } 02518 if (!found && !error) 02519 ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name); 02520 if (res != AST_PBX_KEEPALIVE) 02521 ast_softhangup(c, c->hangupcause ? c->hangupcause : AST_CAUSE_NORMAL_CLEARING); 02522 if ((res != AST_PBX_KEEPALIVE) && ast_exists_extension(c, c->context, "h", 1, c->cid.cid_num)) { 02523 if (c->cdr && ast_opt_end_cdr_before_h_exten) 02524 ast_cdr_end(c->cdr); 02525 set_ext_pri(c, "h", 1); 02526 while(ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) { 02527 if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num))) { 02528 /* Something bad happened, or a hangup has been requested. */ 02529 if (option_debug) 02530 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 02531 if (option_verbose > 1) 02532 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 02533 break; 02534 } 02535 c->priority++; 02536 } 02537 } 02538 ast_set2_flag(c, autoloopflag, AST_FLAG_IN_AUTOLOOP); 02539 02540 pbx_destroy(c->pbx); 02541 c->pbx = NULL; 02542 if (res != AST_PBX_KEEPALIVE) 02543 ast_hangup(c); 02544 return 0; 02545 }
static int _extension_match_core | ( | const char * | pattern, | |
const char * | data, | |||
enum ext_match_t | mode | |||
) | [static] |
Definition at line 767 of file pbx.c.
References ast_log(), E_MATCH, E_MATCH_MASK, E_MATCHMORE, and LOG_WARNING.
Referenced by extension_match_core().
00768 { 00769 mode &= E_MATCH_MASK; /* only consider the relevant bits */ 00770 00771 if ( (mode == E_MATCH) && (pattern[0] == '_') && (strcasecmp(pattern,data)==0) ) /* note: if this test is left out, then _x. will not match _x. !!! */ 00772 return 1; 00773 00774 if (pattern[0] != '_') { /* not a pattern, try exact or partial match */ 00775 int ld = strlen(data), lp = strlen(pattern); 00776 00777 if (lp < ld) /* pattern too short, cannot match */ 00778 return 0; 00779 /* depending on the mode, accept full or partial match or both */ 00780 if (mode == E_MATCH) 00781 return !strcmp(pattern, data); /* 1 on match, 0 on fail */ 00782 if (ld == 0 || !strncasecmp(pattern, data, ld)) /* partial or full match */ 00783 return (mode == E_MATCHMORE) ? lp > ld : 1; /* XXX should consider '!' and '/' ? */ 00784 else 00785 return 0; 00786 } 00787 pattern++; /* skip leading _ */ 00788 /* 00789 * XXX below we stop at '/' which is a separator for the CID info. However we should 00790 * not store '/' in the pattern at all. When we insure it, we can remove the checks. 00791 */ 00792 while (*data && *pattern && *pattern != '/') { 00793 const char *end; 00794 00795 if (*data == '-') { /* skip '-' in data (just a separator) */ 00796 data++; 00797 continue; 00798 } 00799 switch (toupper(*pattern)) { 00800 case '[': /* a range */ 00801 end = strchr(pattern+1, ']'); /* XXX should deal with escapes ? */ 00802 if (end == NULL) { 00803 ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n"); 00804 return 0; /* unconditional failure */ 00805 } 00806 for (pattern++; pattern != end; pattern++) { 00807 if (pattern+2 < end && pattern[1] == '-') { /* this is a range */ 00808 if (*data >= pattern[0] && *data <= pattern[2]) 00809 break; /* match found */ 00810 else { 00811 pattern += 2; /* skip a total of 3 chars */ 00812 continue; 00813 } 00814 } else if (*data == pattern[0]) 00815 break; /* match found */ 00816 } 00817 if (pattern == end) 00818 return 0; 00819 pattern = end; /* skip and continue */ 00820 break; 00821 case 'N': 00822 if (*data < '2' || *data > '9') 00823 return 0; 00824 break; 00825 case 'X': 00826 if (*data < '0' || *data > '9') 00827 return 0; 00828 break; 00829 case 'Z': 00830 if (*data < '1' || *data > '9') 00831 return 0; 00832 break; 00833 case '.': /* Must match, even with more digits */ 00834 return 1; 00835 case '!': /* Early match */ 00836 return 2; 00837 case ' ': 00838 case '-': /* Ignore these in patterns */ 00839 data--; /* compensate the final data++ */ 00840 break; 00841 default: 00842 if (*data != *pattern) 00843 return 0; 00844 } 00845 data++; 00846 pattern++; 00847 } 00848 if (*data) /* data longer than pattern, no match */ 00849 return 0; 00850 /* 00851 * match so far, but ran off the end of the data. 00852 * Depending on what is next, determine match or not. 00853 */ 00854 if (*pattern == '\0' || *pattern == '/') /* exact match */ 00855 return (mode == E_MATCHMORE) ? 0 : 1; /* this is a failure for E_MATCHMORE */ 00856 else if (*pattern == '!') /* early match */ 00857 return 2; 00858 else /* partial match */ 00859 return (mode == E_MATCH) ? 0 : 1; /* this is a failure for E_MATCH */ 00860 }
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 4650 of file pbx.c.
References ast_add_hint(), ast_change_hint(), ast_log(), ast_exten::data, ast_exten::datad, 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().
04652 { 04653 struct ast_exten *ep; 04654 04655 for (ep = NULL; e ; ep = e, e = e->peer) { 04656 if (e->priority >= tmp->priority) 04657 break; 04658 } 04659 if (!e) { /* go at the end, and ep is surely set because the list is not empty */ 04660 ep->peer = tmp; 04661 return 0; /* success */ 04662 } 04663 if (e->priority == tmp->priority) { 04664 /* Can't have something exactly the same. Is this a 04665 replacement? If so, replace, otherwise, bonk. */ 04666 if (!replace) { 04667 ast_log(LOG_WARNING, "Unable to register extension '%s', priority %d in '%s', already in use\n", tmp->exten, tmp->priority, con->name); 04668 if (tmp->datad) 04669 tmp->datad(tmp->data); 04670 free(tmp); 04671 return -1; 04672 } 04673 /* we are replacing e, so copy the link fields and then update 04674 * whoever pointed to e to point to us 04675 */ 04676 tmp->next = e->next; /* not meaningful if we are not first in the peer list */ 04677 tmp->peer = e->peer; /* always meaningful */ 04678 if (ep) /* We're in the peer list, just insert ourselves */ 04679 ep->peer = tmp; 04680 else if (el) /* We're the first extension. Take over e's functions */ 04681 el->next = tmp; 04682 else /* We're the very first extension. */ 04683 con->root = tmp; 04684 if (tmp->priority == PRIORITY_HINT) 04685 ast_change_hint(e,tmp); 04686 /* Destroy the old one */ 04687 if (e->datad) 04688 e->datad(e->data); 04689 free(e); 04690 } else { /* Slip ourselves in just before e */ 04691 tmp->peer = e; 04692 tmp->next = e->next; /* extension chain, or NULL if e is not the first extension */ 04693 if (ep) /* Easy enough, we're just in the peer list */ 04694 ep->peer = tmp; 04695 else { /* we are the first in some peer list, so link in the ext list */ 04696 if (el) 04697 el->next = tmp; /* in the middle... */ 04698 else 04699 con->root = tmp; /* ... or at the head */ 04700 e->next = NULL; /* e is no more at the head, so e->next must be reset */ 04701 } 04702 /* And immediately return success. */ 04703 if (tmp->priority == PRIORITY_HINT) 04704 ast_add_hint(tmp); 04705 } 04706 return 0; 04707 }
int ast_active_calls | ( | void | ) |
Retrieve the number of active calls.
Definition at line 2650 of file pbx.c.
Referenced by handle_chanlist(), and handle_chanlist_deprecated().
02651 { 02652 return countcalls; 02653 }
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 4530 of file pbx.c.
Referenced by handle_context_add_extension(), handle_context_add_extension_deprecated(), park_add_hints(), and register_peer_exten().
04533 { 04534 int ret = -1; 04535 struct ast_context *c = find_context_locked(context); 04536 04537 if (c) { 04538 ret = ast_add_extension2(c, replace, extension, priority, label, callerid, 04539 application, data, datad, registrar); 04540 ast_unlock_contexts(); 04541 } 04542 return ret; 04543 }
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 | |||
) |
Main interface to add extensions to the list for out context.
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 4734 of file pbx.c.
Referenced by add_extensions(), ast_add_extension(), ast_park_call(), do_parking_thread(), load_config(), pbx_load_config(), pbx_load_users(), sla_build_station(), and sla_build_trunk().
04738 { 04739 /* 04740 * Sort extensions (or patterns) according to the rules indicated above. 04741 * These are implemented by the function ext_cmp()). 04742 * All priorities for the same ext/pattern/cid are kept in a list, 04743 * using the 'peer' field as a link field.. 04744 */ 04745 struct ast_exten *tmp, *e, *el = NULL; 04746 int res; 04747 int length; 04748 char *p; 04749 char expand_buf[VAR_BUF_SIZE] = { 0, }; 04750 04751 /* if we are adding a hint, and there are global variables, and the hint 04752 contains variable references, then expand them 04753 */ 04754 ast_mutex_lock(&globalslock); 04755 if (priority == PRIORITY_HINT && AST_LIST_FIRST(&globals) && strstr(application, "${")) { 04756 pbx_substitute_variables_varshead(&globals, application, expand_buf, sizeof(expand_buf)); 04757 application = expand_buf; 04758 } 04759 ast_mutex_unlock(&globalslock); 04760 04761 length = sizeof(struct ast_exten); 04762 length += strlen(extension) + 1; 04763 length += strlen(application) + 1; 04764 if (label) 04765 length += strlen(label) + 1; 04766 if (callerid) 04767 length += strlen(callerid) + 1; 04768 else 04769 length ++; /* just the '\0' */ 04770 04771 /* Be optimistic: Build the extension structure first */ 04772 if (!(tmp = ast_calloc(1, length))) 04773 return -1; 04774 04775 /* use p as dst in assignments, as the fields are const char * */ 04776 p = tmp->stuff; 04777 if (label) { 04778 tmp->label = p; 04779 strcpy(p, label); 04780 p += strlen(label) + 1; 04781 } 04782 tmp->exten = p; 04783 p += ext_strncpy(p, extension, strlen(extension) + 1) + 1; 04784 tmp->priority = priority; 04785 tmp->cidmatch = p; /* but use p for assignments below */ 04786 if (callerid) { 04787 p += ext_strncpy(p, callerid, strlen(callerid) + 1) + 1; 04788 tmp->matchcid = 1; 04789 } else { 04790 *p++ = '\0'; 04791 tmp->matchcid = 0; 04792 } 04793 tmp->app = p; 04794 strcpy(p, application); 04795 tmp->parent = con; 04796 tmp->data = data; 04797 tmp->datad = datad; 04798 tmp->registrar = registrar; 04799 04800 ast_mutex_lock(&con->lock); 04801 res = 0; /* some compilers will think it is uninitialized otherwise */ 04802 for (e = con->root; e; el = e, e = e->next) { /* scan the extension list */ 04803 res = ext_cmp(e->exten, extension); 04804 if (res == 0) { /* extension match, now look at cidmatch */ 04805 if (!e->matchcid && !tmp->matchcid) 04806 res = 0; 04807 else if (tmp->matchcid && !e->matchcid) 04808 res = 1; 04809 else if (e->matchcid && !tmp->matchcid) 04810 res = -1; 04811 else 04812 res = strcasecmp(e->cidmatch, tmp->cidmatch); 04813 } 04814 if (res >= 0) 04815 break; 04816 } 04817 if (e && res == 0) { /* exact match, insert in the pri chain */ 04818 res = add_pri(con, tmp, el, e, replace); 04819 ast_mutex_unlock(&con->lock); 04820 if (res < 0) { 04821 errno = EEXIST; /* XXX do we care ? */ 04822 return 0; /* XXX should we return -1 maybe ? */ 04823 } 04824 } else { 04825 /* 04826 * not an exact match, this is the first entry with this pattern, 04827 * so insert in the main list right before 'e' (if any) 04828 */ 04829 tmp->next = e; 04830 if (el) 04831 el->next = tmp; 04832 else 04833 con->root = tmp; 04834 ast_mutex_unlock(&con->lock); 04835 if (tmp->priority == PRIORITY_HINT) 04836 ast_add_hint(tmp); 04837 } 04838 if (option_debug) { 04839 if (tmp->matchcid) { 04840 if (option_debug) 04841 ast_log(LOG_DEBUG, "Added extension '%s' priority %d (CID match '%s') to %s\n", 04842 tmp->exten, tmp->priority, tmp->cidmatch, con->name); 04843 } else { 04844 if (option_debug) 04845 ast_log(LOG_DEBUG, "Added extension '%s' priority %d to %s\n", 04846 tmp->exten, tmp->priority, con->name); 04847 } 04848 } 04849 if (option_verbose > 2) { 04850 if (tmp->matchcid) { 04851 ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d (CID match '%s')to %s\n", 04852 tmp->exten, tmp->priority, tmp->cidmatch, con->name); 04853 } else { 04854 ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d to %s\n", 04855 tmp->exten, tmp->priority, con->name); 04856 } 04857 } 04858 return 0; 04859 }
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 2152 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, ast_hint::laststate, LOG_DEBUG, and option_debug.
Referenced by add_pri(), and ast_add_extension2().
02153 { 02154 struct ast_hint *hint; 02155 02156 if (!e) 02157 return -1; 02158 02159 AST_LIST_LOCK(&hints); 02160 02161 /* Search if hint exists, do nothing */ 02162 AST_LIST_TRAVERSE(&hints, hint, list) { 02163 if (hint->exten == e) { 02164 AST_LIST_UNLOCK(&hints); 02165 if (option_debug > 1) 02166 ast_log(LOG_DEBUG, "HINTS: Not re-adding existing hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e)); 02167 return -1; 02168 } 02169 } 02170 02171 if (option_debug > 1) 02172 ast_log(LOG_DEBUG, "HINTS: Adding hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e)); 02173 02174 if (!(hint = ast_calloc(1, sizeof(*hint)))) { 02175 AST_LIST_UNLOCK(&hints); 02176 return -1; 02177 } 02178 /* Initialize and insert new item at the top */ 02179 hint->exten = e; 02180 hint->laststate = ast_extension_state2(e); 02181 AST_LIST_INSERT_HEAD(&hints, hint, list); 02182 02183 AST_LIST_UNLOCK(&hints); 02184 return 0; 02185 }
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 4564 of file pbx.c.
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().
04565 { 04566 int res = 0; 04567 04568 ast_channel_lock(chan); 04569 04570 if (chan->pbx) { /* This channel is currently in the PBX */ 04571 ast_explicit_goto(chan, context, exten, priority); 04572 ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO); 04573 } else { 04574 /* In order to do it when the channel doesn't really exist within 04575 the PBX, we have to make a new channel, masquerade, and start the PBX 04576 at the new location */ 04577 struct ast_channel *tmpchan = ast_channel_alloc(0, chan->_state, 0, 0, chan->accountcode, chan->exten, chan->context, chan->amaflags, "AsyncGoto/%s", chan->name); 04578 if (chan->cdr) { 04579 tmpchan->cdr = ast_cdr_dup(chan->cdr); 04580 } 04581 if (!tmpchan) 04582 res = -1; 04583 else { 04584 /* Make formats okay */ 04585 tmpchan->readformat = chan->readformat; 04586 tmpchan->writeformat = chan->writeformat; 04587 /* Setup proper location */ 04588 ast_explicit_goto(tmpchan, 04589 S_OR(context, chan->context), S_OR(exten, chan->exten), priority); 04590 04591 /* Masquerade into temp channel */ 04592 ast_channel_masquerade(tmpchan, chan); 04593 04594 /* Grab the locks and get going */ 04595 ast_channel_lock(tmpchan); 04596 ast_do_masquerade(tmpchan); 04597 ast_channel_unlock(tmpchan); 04598 /* Start the PBX going on our stolen channel */ 04599 if (ast_pbx_start(tmpchan)) { 04600 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name); 04601 ast_hangup(tmpchan); 04602 res = -1; 04603 } 04604 } 04605 } 04606 ast_channel_unlock(chan); 04607 return res; 04608 }
int ast_async_goto_by_name | ( | const char * | channame, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 4610 of file pbx.c.
04611 { 04612 struct ast_channel *chan; 04613 int res = -1; 04614 04615 chan = ast_get_channel_by_name_locked(channame); 04616 if (chan) { 04617 res = ast_async_goto(chan, context, exten, priority); 04618 ast_channel_unlock(chan); 04619 } 04620 return res; 04621 }
int ast_async_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 6269 of file pbx.c.
Referenced by asyncgoto_exec().
06270 { 06271 return __ast_goto_if_exists(chan, context, exten, priority, 1); 06272 }
int ast_build_timing | ( | struct ast_timing * | i, | |
const char * | info_in | |||
) |
Definition at line 4206 of file pbx.c.
Referenced by ast_context_add_include2(), iftime(), pbx_builtin_execiftime(), and pbx_builtin_gotoiftime().
04207 { 04208 char info_save[256]; 04209 char *info; 04210 04211 /* Check for empty just in case */ 04212 if (ast_strlen_zero(info_in)) 04213 return 0; 04214 /* make a copy just in case we were passed a static string */ 04215 ast_copy_string(info_save, info_in, sizeof(info_save)); 04216 info = info_save; 04217 /* Assume everything except time */ 04218 i->monthmask = 0xfff; /* 12 bits */ 04219 i->daymask = 0x7fffffffU; /* 31 bits */ 04220 i->dowmask = 0x7f; /* 7 bits */ 04221 /* on each call, use strsep() to move info to the next argument */ 04222 get_timerange(i, strsep(&info, "|")); 04223 if (info) 04224 i->dowmask = get_range(strsep(&info, "|"), 7, days, "day of week"); 04225 if (info) 04226 i->daymask = get_range(strsep(&info, "|"), 31, NULL, "day"); 04227 if (info) 04228 i->monthmask = get_range(strsep(&info, "|"), 12, months, "month"); 04229 return 1; 04230 }
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 2276 of file pbx.c.
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().
02277 { 02278 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH); 02279 }
ast_change_hint: Change hint for an extension
Definition at line 2188 of file pbx.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, and ast_hint::exten.
Referenced by add_pri().
02189 { 02190 struct ast_hint *hint; 02191 int res = -1; 02192 02193 AST_LIST_LOCK(&hints); 02194 AST_LIST_TRAVERSE(&hints, hint, list) { 02195 if (hint->exten == oe) { 02196 hint->exten = ne; 02197 res = 0; 02198 break; 02199 } 02200 } 02201 AST_LIST_UNLOCK(&hints); 02202 02203 return res; 02204 }
int ast_check_timing | ( | const struct ast_timing * | i | ) |
Definition at line 4232 of file pbx.c.
Referenced by iftime(), include_valid(), pbx_builtin_execiftime(), and pbx_builtin_gotoiftime().
04233 { 04234 struct tm tm; 04235 time_t t = time(NULL); 04236 04237 ast_localtime(&t, &tm, NULL); 04238 04239 /* If it's not the right month, return */ 04240 if (!(i->monthmask & (1 << tm.tm_mon))) 04241 return 0; 04242 04243 /* If it's not that time of the month.... */ 04244 /* Warning, tm_mday has range 1..31! */ 04245 if (!(i->daymask & (1 << (tm.tm_mday-1)))) 04246 return 0; 04247 04248 /* If it's not the right day of the week */ 04249 if (!(i->dowmask & (1 << tm.tm_wday))) 04250 return 0; 04251 04252 /* Sanity check the hour just to be safe */ 04253 if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) { 04254 ast_log(LOG_WARNING, "Insane time...\n"); 04255 return 0; 04256 } 04257 04258 /* Now the tough part, we calculate if it fits 04259 in the right time based on min/hour */ 04260 if (!(i->minmask[tm.tm_hour] & (1 << (tm.tm_min / 2)))) 04261 return 0; 04262 04263 /* If we got this far, then we're good */ 04264 return 1; 04265 }
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 4466 of file pbx.c.
Referenced by handle_context_add_ignorepat(), and handle_context_add_ignorepat_deprecated().
04467 { 04468 int ret = -1; 04469 struct ast_context *c = find_context_locked(context); 04470 04471 if (c) { 04472 ret = ast_context_add_ignorepat2(c, value, registrar); 04473 ast_unlock_contexts(); 04474 } 04475 return ret; 04476 }
int ast_context_add_ignorepat2 | ( | struct ast_context * | con, | |
const char * | value, | |||
const char * | registrar | |||
) |
Definition at line 4478 of file pbx.c.
Referenced by ast_compile_ael2(), ast_context_add_ignorepat(), and pbx_load_config().
04479 { 04480 struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL; 04481 int length; 04482 length = sizeof(struct ast_ignorepat); 04483 length += strlen(value) + 1; 04484 if (!(ignorepat = ast_calloc(1, length))) 04485 return -1; 04486 /* The cast to char * is because we need to write the initial value. 04487 * The field is not supposed to be modified otherwise 04488 */ 04489 strcpy((char *)ignorepat->pattern, value); 04490 ignorepat->next = NULL; 04491 ignorepat->registrar = registrar; 04492 ast_mutex_lock(&con->lock); 04493 for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) { 04494 ignorepatl = ignorepatc; 04495 if (!strcasecmp(ignorepatc->pattern, value)) { 04496 /* Already there */ 04497 ast_mutex_unlock(&con->lock); 04498 errno = EEXIST; 04499 return -1; 04500 } 04501 } 04502 if (ignorepatl) 04503 ignorepatl->next = ignorepat; 04504 else 04505 con->ignorepats = ignorepat; 04506 ast_mutex_unlock(&con->lock); 04507 return 0; 04508 04509 }
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 4012 of file pbx.c.
Referenced by handle_context_add_include(), and handle_context_add_include_deprecated().
04013 { 04014 int ret = -1; 04015 struct ast_context *c = find_context_locked(context); 04016 04017 if (c) { 04018 ret = ast_context_add_include2(c, include, registrar); 04019 ast_unlock_contexts(); 04020 } 04021 return ret; 04022 }
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 4274 of file pbx.c.
Referenced by ast_compile_ael2(), ast_context_add_include(), and pbx_load_config().
04276 { 04277 struct ast_include *new_include; 04278 char *c; 04279 struct ast_include *i, *il = NULL; /* include, include_last */ 04280 int length; 04281 char *p; 04282 04283 length = sizeof(struct ast_include); 04284 length += 2 * (strlen(value) + 1); 04285 04286 /* allocate new include structure ... */ 04287 if (!(new_include = ast_calloc(1, length))) 04288 return -1; 04289 /* Fill in this structure. Use 'p' for assignments, as the fields 04290 * in the structure are 'const char *' 04291 */ 04292 p = new_include->stuff; 04293 new_include->name = p; 04294 strcpy(p, value); 04295 p += strlen(value) + 1; 04296 new_include->rname = p; 04297 strcpy(p, value); 04298 /* Strip off timing info, and process if it is there */ 04299 if ( (c = strchr(p, '|')) ) { 04300 *c++ = '\0'; 04301 new_include->hastime = ast_build_timing(&(new_include->timing), c); 04302 } 04303 new_include->next = NULL; 04304 new_include->registrar = registrar; 04305 04306 ast_mutex_lock(&con->lock); 04307 04308 /* ... go to last include and check if context is already included too... */ 04309 for (i = con->includes; i; i = i->next) { 04310 if (!strcasecmp(i->name, new_include->name)) { 04311 free(new_include); 04312 ast_mutex_unlock(&con->lock); 04313 errno = EEXIST; 04314 return -1; 04315 } 04316 il = i; 04317 } 04318 04319 /* ... include new context into context list, unlock, return */ 04320 if (il) 04321 il->next = new_include; 04322 else 04323 con->includes = new_include; 04324 if (option_verbose > 2) 04325 ast_verbose(VERBOSE_PREFIX_3 "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con)); 04326 ast_mutex_unlock(&con->lock); 04327 04328 return 0; 04329 }
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 4336 of file pbx.c.
04337 { 04338 int ret = -1; 04339 struct ast_context *c = find_context_locked(context); 04340 04341 if (c) { /* found, add switch to this context */ 04342 ret = ast_context_add_switch2(c, sw, data, eval, registrar); 04343 ast_unlock_contexts(); 04344 } 04345 return ret; 04346 }
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 4355 of file pbx.c.
Referenced by ast_compile_ael2(), ast_context_add_switch(), and pbx_load_config().
04357 { 04358 struct ast_sw *new_sw; 04359 struct ast_sw *i; 04360 int length; 04361 char *p; 04362 04363 length = sizeof(struct ast_sw); 04364 length += strlen(value) + 1; 04365 if (data) 04366 length += strlen(data); 04367 length++; 04368 if (eval) { 04369 /* Create buffer for evaluation of variables */ 04370 length += SWITCH_DATA_LENGTH; 04371 length++; 04372 } 04373 04374 /* allocate new sw structure ... */ 04375 if (!(new_sw = ast_calloc(1, length))) 04376 return -1; 04377 /* ... fill in this structure ... */ 04378 p = new_sw->stuff; 04379 new_sw->name = p; 04380 strcpy(new_sw->name, value); 04381 p += strlen(value) + 1; 04382 new_sw->data = p; 04383 if (data) { 04384 strcpy(new_sw->data, data); 04385 p += strlen(data) + 1; 04386 } else { 04387 strcpy(new_sw->data, ""); 04388 p++; 04389 } 04390 if (eval) 04391 new_sw->tmpdata = p; 04392 new_sw->eval = eval; 04393 new_sw->registrar = registrar; 04394 04395 /* ... try to lock this context ... */ 04396 ast_mutex_lock(&con->lock); 04397 04398 /* ... go to last sw and check if context is already swd too... */ 04399 AST_LIST_TRAVERSE(&con->alts, i, list) { 04400 if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) { 04401 free(new_sw); 04402 ast_mutex_unlock(&con->lock); 04403 errno = EEXIST; 04404 return -1; 04405 } 04406 } 04407 04408 /* ... sw new context into context list, unlock, return */ 04409 AST_LIST_INSERT_TAIL(&con->alts, new_sw, list); 04410 04411 if (option_verbose > 2) 04412 ast_verbose(VERBOSE_PREFIX_3 "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con)); 04413 04414 ast_mutex_unlock(&con->lock); 04415 04416 return 0; 04417 }
struct ast_context* ast_context_create | ( | struct ast_context ** | extcontexts, | |
const char * | name, | |||
const char * | registrar | |||
) | [read] |
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 3883 of file pbx.c.
Referenced by ast_compile_ael2(), ast_park_call(), do_parking_thread(), load_config(), reload_config(), and set_config().
03884 { 03885 return __ast_context_create(extcontexts, name, registrar, 0); 03886 }
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 5320 of file pbx.c.
Referenced by cleanup_stale_contexts(), and unload_module().
05321 { 05322 __ast_context_destroy(con,registrar); 05323 }
struct ast_context* ast_context_find | ( | const char * | name | ) | [read] |
Find a context.
name | name of the context to find |
Definition at line 890 of file pbx.c.
Referenced by _macro_exec(), ast_context_verify_includes(), ast_ignore_pattern(), ast_park_call(), cleanup_stale_contexts(), do_parking_thread(), load_config(), park_exec(), register_peer_exten(), reload_config(), and set_config().
00891 { 00892 struct ast_context *tmp = NULL; 00893 ast_mutex_lock(&conlock); 00894 while ( (tmp = ast_walk_contexts(tmp)) ) { 00895 if (!name || !strcasecmp(name, tmp->name)) 00896 break; 00897 } 00898 ast_mutex_unlock(&conlock); 00899 return tmp; 00900 }
struct ast_context* ast_context_find_or_create | ( | struct ast_context ** | extcontexts, | |
const char * | name, | |||
const char * | registrar | |||
) | [read] |
Definition at line 3888 of file pbx.c.
Referenced by pbx_load_config(), pbx_load_users(), sla_build_station(), and sla_build_trunk().
03889 { 03890 return __ast_context_create(extcontexts, name, registrar, 1); 03891 }
int ast_context_lockmacro | ( | const char * | context | ) |
locks the macrolock in the given given context
Definition at line 2887 of file pbx.c.
Referenced by _macro_exec().
02888 { 02889 struct ast_context *c = NULL; 02890 int ret = -1; 02891 02892 ast_lock_contexts(); 02893 02894 while ((c = ast_walk_contexts(c))) { 02895 if (!strcmp(ast_get_context_name(c), context)) { 02896 ret = 0; 02897 break; 02898 } 02899 } 02900 02901 ast_unlock_contexts(); 02902 02903 /* if we found context, lock macrolock */ 02904 if (ret == 0) 02905 ret = ast_mutex_lock(&c->macrolock); 02906 02907 return ret; 02908 }
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 2788 of file pbx.c.
Referenced by destroy_station(), destroy_trunk(), handle_context_remove_extension(), handle_context_remove_extension_deprecated(), and register_peer_exten().
02789 { 02790 int ret = -1; /* default error return */ 02791 struct ast_context *c = find_context_locked(context); 02792 02793 if (c) { /* ... remove extension ... */ 02794 ret = ast_context_remove_extension2(c, extension, priority, registrar); 02795 ast_unlock_contexts(); 02796 } 02797 return ret; 02798 }
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 2810 of file pbx.c.
Referenced by ast_context_remove_extension(), do_parking_thread(), load_config(), and park_exec().
02811 { 02812 struct ast_exten *exten, *prev_exten = NULL; 02813 struct ast_exten *peer; 02814 02815 ast_mutex_lock(&con->lock); 02816 02817 /* scan the extension list to find matching extension-registrar */ 02818 for (exten = con->root; exten; prev_exten = exten, exten = exten->next) { 02819 if (!strcmp(exten->exten, extension) && 02820 (!registrar || !strcmp(exten->registrar, registrar))) 02821 break; 02822 } 02823 if (!exten) { 02824 /* we can't find right extension */ 02825 ast_mutex_unlock(&con->lock); 02826 return -1; 02827 } 02828 02829 /* should we free all peers in this extension? (priority == 0)? */ 02830 if (priority == 0) { 02831 /* remove this extension from context list */ 02832 if (prev_exten) 02833 prev_exten->next = exten->next; 02834 else 02835 con->root = exten->next; 02836 02837 /* fire out all peers */ 02838 while ( (peer = exten) ) { 02839 exten = peer->peer; /* prepare for next entry */ 02840 destroy_exten(peer); 02841 } 02842 } else { 02843 /* scan the priority list to remove extension with exten->priority == priority */ 02844 struct ast_exten *previous_peer = NULL; 02845 02846 for (peer = exten; peer; previous_peer = peer, peer = peer->peer) { 02847 if (peer->priority == priority && 02848 (!registrar || !strcmp(peer->registrar, registrar) )) 02849 break; /* found our priority */ 02850 } 02851 if (!peer) { /* not found */ 02852 ast_mutex_unlock(&con->lock); 02853 return -1; 02854 } 02855 /* we are first priority extension? */ 02856 if (!previous_peer) { 02857 /* 02858 * We are first in the priority chain, so must update the extension chain. 02859 * The next node is either the next priority or the next extension 02860 */ 02861 struct ast_exten *next_node = peer->peer ? peer->peer : peer->next; 02862 02863 if (!prev_exten) /* change the root... */ 02864 con->root = next_node; 02865 else 02866 prev_exten->next = next_node; /* unlink */ 02867 if (peer->peer) /* XXX update the new head of the pri list */ 02868 peer->peer->next = peer->next; 02869 } else { /* easy, we are not first priority in extension */ 02870 previous_peer->peer = peer->peer; 02871 } 02872 02873 /* now, free whole priority extension */ 02874 destroy_exten(peer); 02875 /* XXX should we return -1 ? */ 02876 } 02877 ast_mutex_unlock(&con->lock); 02878 return 0; 02879 }
int ast_context_remove_ignorepat | ( | const char * | context, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 4423 of file pbx.c.
Referenced by handle_context_remove_ignorepat(), and handle_context_remove_ignorepat_deprecated().
04424 { 04425 int ret = -1; 04426 struct ast_context *c = find_context_locked(context); 04427 04428 if (c) { 04429 ret = ast_context_remove_ignorepat2(c, ignorepat, registrar); 04430 ast_unlock_contexts(); 04431 } 04432 return ret; 04433 }
int ast_context_remove_ignorepat2 | ( | struct ast_context * | con, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 4435 of file pbx.c.
Referenced by ast_context_remove_ignorepat().
04436 { 04437 struct ast_ignorepat *ip, *ipl = NULL; 04438 04439 ast_mutex_lock(&con->lock); 04440 04441 for (ip = con->ignorepats; ip; ip = ip->next) { 04442 if (!strcmp(ip->pattern, ignorepat) && 04443 (!registrar || (registrar == ip->registrar))) { 04444 if (ipl) { 04445 ipl->next = ip->next; 04446 free(ip); 04447 } else { 04448 con->ignorepats = ip->next; 04449 free(ip); 04450 } 04451 ast_mutex_unlock(&con->lock); 04452 return 0; 04453 } 04454 ipl = ip; 04455 } 04456 04457 ast_mutex_unlock(&con->lock); 04458 errno = EINVAL; 04459 return -1; 04460 }
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 2684 of file pbx.c.
Referenced by handle_context_dont_include_deprecated(), and handle_context_remove_include().
02685 { 02686 int ret = -1; 02687 struct ast_context *c = find_context_locked(context); 02688 02689 if (c) { 02690 /* found, remove include from this context ... */ 02691 ret = ast_context_remove_include2(c, include, registrar); 02692 ast_unlock_contexts(); 02693 } 02694 return ret; 02695 }
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 2705 of file pbx.c.
Referenced by ast_context_remove_include().
02706 { 02707 struct ast_include *i, *pi = NULL; 02708 int ret = -1; 02709 02710 ast_mutex_lock(&con->lock); 02711 02712 /* find our include */ 02713 for (i = con->includes; i; pi = i, i = i->next) { 02714 if (!strcmp(i->name, include) && 02715 (!registrar || !strcmp(i->registrar, registrar))) { 02716 /* remove from list */ 02717 if (pi) 02718 pi->next = i->next; 02719 else 02720 con->includes = i->next; 02721 /* free include and return */ 02722 free(i); 02723 ret = 0; 02724 break; 02725 } 02726 } 02727 02728 ast_mutex_unlock(&con->lock); 02729 return ret; 02730 }
int ast_context_remove_switch | ( | const char * | context, | |
const char * | sw, | |||
const char * | data, | |||
const char * | registrar | |||
) |
Remove a switch.
Definition at line 2737 of file pbx.c.
02738 { 02739 int ret = -1; /* default error return */ 02740 struct ast_context *c = find_context_locked(context); 02741 02742 if (c) { 02743 /* remove switch from this context ... */ 02744 ret = ast_context_remove_switch2(c, sw, data, registrar); 02745 ast_unlock_contexts(); 02746 } 02747 return ret; 02748 }
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 2758 of file pbx.c.
Referenced by ast_context_remove_switch().
02759 { 02760 struct ast_sw *i; 02761 int ret = -1; 02762 02763 ast_mutex_lock(&con->lock); 02764 02765 /* walk switches */ 02766 AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) { 02767 if (!strcmp(i->name, sw) && !strcmp(i->data, data) && 02768 (!registrar || !strcmp(i->registrar, registrar))) { 02769 /* found, remove from list */ 02770 AST_LIST_REMOVE_CURRENT(&con->alts, list); 02771 free(i); /* free switch and return */ 02772 ret = 0; 02773 break; 02774 } 02775 } 02776 AST_LIST_TRAVERSE_SAFE_END 02777 02778 ast_mutex_unlock(&con->lock); 02779 02780 return ret; 02781 }
int ast_context_unlockmacro | ( | const char * | context | ) |
Unlocks the macrolock in the given context.
Definition at line 2915 of file pbx.c.
Referenced by _macro_exec().
02916 { 02917 struct ast_context *c = NULL; 02918 int ret = -1; 02919 02920 ast_lock_contexts(); 02921 02922 while ((c = ast_walk_contexts(c))) { 02923 if (!strcmp(ast_get_context_name(c), context)) { 02924 ret = 0; 02925 break; 02926 } 02927 } 02928 02929 ast_unlock_contexts(); 02930 02931 /* if we found context, unlock macrolock */ 02932 if (ret == 0) 02933 ret = ast_mutex_unlock(&c->macrolock); 02934 02935 return ret; 02936 }
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 6230 of file pbx.c.
Referenced by pbx_load_module().
06231 { 06232 struct ast_include *inc = NULL; 06233 int res = 0; 06234 06235 while ( (inc = ast_walk_context_includes(con, inc)) ) 06236 if (!ast_context_find(inc->rname)) { 06237 res = -1; 06238 ast_log(LOG_WARNING, "Context '%s' tries includes nonexistent context '%s'\n", 06239 ast_get_context_name(con), inc->rname); 06240 } 06241 return res; 06242 }
struct ast_custom_function* ast_custom_function_find | ( | const char * | name | ) | [read] |
Definition at line 1427 of file pbx.c.
Referenced by ast_custom_function_register(), ast_func_read(), ast_func_write(), handle_show_function(), and handle_show_function_deprecated().
01428 { 01429 struct ast_custom_function *acf = NULL; 01430 01431 AST_LIST_LOCK(&acf_root); 01432 AST_LIST_TRAVERSE(&acf_root, acf, acflist) { 01433 if (!strcmp(name, acf->name)) 01434 break; 01435 } 01436 AST_LIST_UNLOCK(&acf_root); 01437 01438 return acf; 01439 }
int ast_custom_function_register | ( | struct ast_custom_function * | acf | ) |
Reigster a custom function.
Definition at line 1463 of file pbx.c.
Referenced by load_module(), odbc_load_module(), and reload().
01464 { 01465 struct ast_custom_function *cur; 01466 01467 if (!acf) 01468 return -1; 01469 01470 AST_LIST_LOCK(&acf_root); 01471 01472 if (ast_custom_function_find(acf->name)) { 01473 ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name); 01474 AST_LIST_UNLOCK(&acf_root); 01475 return -1; 01476 } 01477 01478 /* Store in alphabetical order */ 01479 AST_LIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) { 01480 if (strcasecmp(acf->name, cur->name) < 0) { 01481 AST_LIST_INSERT_BEFORE_CURRENT(&acf_root, acf, acflist); 01482 break; 01483 } 01484 } 01485 AST_LIST_TRAVERSE_SAFE_END 01486 if (!cur) 01487 AST_LIST_INSERT_TAIL(&acf_root, acf, acflist); 01488 01489 AST_LIST_UNLOCK(&acf_root); 01490 01491 if (option_verbose > 1) 01492 ast_verbose(VERBOSE_PREFIX_2 "Registered custom function %s\n", acf->name); 01493 01494 return 0; 01495 }
int ast_custom_function_unregister | ( | struct ast_custom_function * | acf | ) |
Unregister a custom function.
Definition at line 1441 of file pbx.c.
Referenced by odbc_unload_module(), reload(), and unload_module().
01442 { 01443 struct ast_custom_function *cur; 01444 01445 if (!acf) 01446 return -1; 01447 01448 AST_LIST_LOCK(&acf_root); 01449 AST_LIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) { 01450 if (cur == acf) { 01451 AST_LIST_REMOVE_CURRENT(&acf_root, acflist); 01452 if (option_verbose > 1) 01453 ast_verbose(VERBOSE_PREFIX_2 "Unregistered custom function %s\n", acf->name); 01454 break; 01455 } 01456 } 01457 AST_LIST_TRAVERSE_SAFE_END 01458 AST_LIST_UNLOCK(&acf_root); 01459 01460 return acf ? 0 : -1; 01461 }
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 2261 of file pbx.c.
Referenced by __ast_goto_if_exists(), __ast_pbx_run(), __login_exec(), _macro_exec(), agentmonitoroutgoing_exec(), answer_call(), ast_app_dtget(), ast_park_call(), ast_pbx_outgoing_exten(), builtin_atxfer(), builtin_blindtransfer(), cb_events(), console_dial(), console_dial_deprecated(), console_transfer(), console_transfer_deprecated(), disa_exec(), dp_lookup(), dundi_lookup_local(), get_also_info(), get_destination(), get_refer_info(), handle_link_data(), handle_link_phone_dtmf(), handle_stimulus_message(), leave_voicemail(), local_alloc(), local_devicestate(), local_dtmf_helper(), loopback_exists(), metermaidstate(), mgcp_ss(), misdn_overlap_dial_task(), parkandannounce_exec(), pbx_builtin_waitexten(), phone_check_exception(), process_ast_dsp(), register_peer_exten(), rpt_exec(), skinny_ss(), socket_process(), ss_thread(), waitstream_core(), and zt_handle_dtmfup().
02262 { 02263 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH); 02264 }
int ast_explicit_goto | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 4545 of file pbx.c.
Referenced by __ast_goto_if_exists(), ast_async_goto(), ast_parseable_goto(), builtin_atxfer(), disa_exec(), and handle_setpriority().
04546 { 04547 if (!chan) 04548 return -1; 04549 04550 if (!ast_strlen_zero(context)) 04551 ast_copy_string(chan->context, context, sizeof(chan->context)); 04552 if (!ast_strlen_zero(exten)) 04553 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 04554 if (priority > -1) { 04555 chan->priority = priority; 04556 /* see flag description in channel.h for explanation */ 04557 if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP)) 04558 chan->priority--; 04559 } 04560 04561 return 0; 04562 }
int ast_extension_close | ( | const char * | pattern, | |
const char * | data, | |||
int | needmore | |||
) |
Definition at line 883 of file pbx.c.
Referenced by realtime_switch_common().
00884 { 00885 if (needmore != E_MATCHMORE && needmore != E_CANMATCH) 00886 ast_log(LOG_WARNING, "invalid argument %d\n", needmore); 00887 return extension_match_core(pattern, data, needmore); 00888 }
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 878 of file pbx.c.
Referenced by ast_ignore_pattern(), do_say(), find_matching_priority(), loopback_canmatch(), loopback_exec(), loopback_exists(), loopback_matchmore(), matchcid(), misdn_cfg_is_msn_valid(), realtime_switch_common(), and show_dialplan_helper().
00879 { 00880 return extension_match_core(pattern, data, E_MATCH); 00881 }
int ast_extension_state | ( | struct ast_channel * | c, | |
const char * | context, | |||
const char * | exten | |||
) |
ast_extension_state: Check extension state for an extension by using hint
Uses hint and devicestate callback to get the state of an extension.
Definition at line 1985 of file pbx.c.
Referenced by action_extensionstate(), and handle_request_subscribe().
01986 { 01987 struct ast_exten *e; 01988 01989 e = ast_hint_extension(c, context, exten); /* Do we have a hint for this extension ? */ 01990 if (!e) 01991 return -1; /* No hint, return -1 */ 01992 01993 return ast_extension_state2(e); /* Check all devices in the hint */ 01994 }
static int ast_extension_state2 | ( | struct ast_exten * | e | ) | [static] |
ast_extensions_state2: Check state of extension by using hints
Definition at line 1888 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().
01889 { 01890 char hint[AST_MAX_EXTENSION]; 01891 char *cur, *rest; 01892 int allunavailable = 1, allbusy = 1, allfree = 1, allonhold = 1; 01893 int busy = 0, inuse = 0, ring = 0; 01894 01895 if (!e) 01896 return -1; 01897 01898 ast_copy_string(hint, ast_get_extension_app(e), sizeof(hint)); 01899 01900 rest = hint; /* One or more devices separated with a & character */ 01901 while ( (cur = strsep(&rest, "&")) ) { 01902 int res = ast_device_state(cur); 01903 switch (res) { 01904 case AST_DEVICE_NOT_INUSE: 01905 allunavailable = 0; 01906 allbusy = 0; 01907 allonhold = 0; 01908 break; 01909 case AST_DEVICE_INUSE: 01910 inuse = 1; 01911 allunavailable = 0; 01912 allfree = 0; 01913 allonhold = 0; 01914 break; 01915 case AST_DEVICE_RINGING: 01916 ring = 1; 01917 allunavailable = 0; 01918 allfree = 0; 01919 allonhold = 0; 01920 break; 01921 case AST_DEVICE_RINGINUSE: 01922 inuse = 1; 01923 ring = 1; 01924 allunavailable = 0; 01925 allfree = 0; 01926 allonhold = 0; 01927 break; 01928 case AST_DEVICE_ONHOLD: 01929 allunavailable = 0; 01930 allfree = 0; 01931 break; 01932 case AST_DEVICE_BUSY: 01933 allunavailable = 0; 01934 allfree = 0; 01935 allonhold = 0; 01936 busy = 1; 01937 break; 01938 case AST_DEVICE_UNAVAILABLE: 01939 case AST_DEVICE_INVALID: 01940 allbusy = 0; 01941 allfree = 0; 01942 allonhold = 0; 01943 break; 01944 default: 01945 allunavailable = 0; 01946 allbusy = 0; 01947 allfree = 0; 01948 allonhold = 0; 01949 } 01950 } 01951 01952 if (!inuse && ring) 01953 return AST_EXTENSION_RINGING; 01954 if (inuse && ring) 01955 return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING); 01956 if (inuse) 01957 return AST_EXTENSION_INUSE; 01958 if (allfree) 01959 return AST_EXTENSION_NOT_INUSE; 01960 if (allonhold) 01961 return AST_EXTENSION_ONHOLD; 01962 if (allbusy) 01963 return AST_EXTENSION_BUSY; 01964 if (allunavailable) 01965 return AST_EXTENSION_UNAVAILABLE; 01966 if (busy) 01967 return AST_EXTENSION_INUSE; 01968 01969 return AST_EXTENSION_NOT_INUSE; 01970 }
const char* ast_extension_state2str | ( | int | extension_state | ) |
ast_extension_state2str: Return extension_state as string
Return string representation of the state of an extension.
Definition at line 1973 of file pbx.c.
Referenced by __sip_show_channels(), cb_extensionstate(), handle_request_subscribe(), and handle_show_hints().
01974 { 01975 int i; 01976 01977 for (i = 0; (i < (sizeof(extension_states) / sizeof(extension_states[0]))); i++) { 01978 if (extension_states[i].extension_state == extension_state) 01979 return extension_states[i].text; 01980 } 01981 return "Unknown"; 01982 }
int ast_extension_state_add | ( | const char * | context, | |
const char * | exten, | |||
ast_state_cb_type | callback, | |||
void * | data | |||
) |
ast_extension_state_add: Add watcher for extension states
Registers a state change callback.
Definition at line 2040 of file pbx.c.
Referenced by handle_request_subscribe(), and init_manager().
02042 { 02043 struct ast_hint *hint; 02044 struct ast_state_cb *cblist; 02045 struct ast_exten *e; 02046 02047 /* If there's no context and extension: add callback to statecbs list */ 02048 if (!context && !exten) { 02049 AST_LIST_LOCK(&hints); 02050 02051 for (cblist = statecbs; cblist; cblist = cblist->next) { 02052 if (cblist->callback == callback) { 02053 cblist->data = data; 02054 AST_LIST_UNLOCK(&hints); 02055 return 0; 02056 } 02057 } 02058 02059 /* Now insert the callback */ 02060 if (!(cblist = ast_calloc(1, sizeof(*cblist)))) { 02061 AST_LIST_UNLOCK(&hints); 02062 return -1; 02063 } 02064 cblist->id = 0; 02065 cblist->callback = callback; 02066 cblist->data = data; 02067 02068 cblist->next = statecbs; 02069 statecbs = cblist; 02070 02071 AST_LIST_UNLOCK(&hints); 02072 return 0; 02073 } 02074 02075 if (!context || !exten) 02076 return -1; 02077 02078 /* This callback type is for only one hint, so get the hint */ 02079 e = ast_hint_extension(NULL, context, exten); 02080 if (!e) { 02081 return -1; 02082 } 02083 02084 /* Find the hint in the list of hints */ 02085 AST_LIST_LOCK(&hints); 02086 02087 AST_LIST_TRAVERSE(&hints, hint, list) { 02088 if (hint->exten == e) 02089 break; 02090 } 02091 02092 if (!hint) { 02093 /* We have no hint, sorry */ 02094 AST_LIST_UNLOCK(&hints); 02095 return -1; 02096 } 02097 02098 /* Now insert the callback in the callback list */ 02099 if (!(cblist = ast_calloc(1, sizeof(*cblist)))) { 02100 AST_LIST_UNLOCK(&hints); 02101 return -1; 02102 } 02103 cblist->id = stateid++; /* Unique ID for this callback */ 02104 cblist->callback = callback; /* Pointer to callback routine */ 02105 cblist->data = data; /* Data for the callback */ 02106 02107 cblist->next = hint->callbacks; 02108 hint->callbacks = cblist; 02109 02110 AST_LIST_UNLOCK(&hints); 02111 return cblist->id; 02112 }
int ast_extension_state_del | ( | int | id, | |
ast_state_cb_type | callback | |||
) |
ast_extension_state_del: Remove a watcher from the callback list
Deletes a registered state change callback by ID.
Definition at line 2115 of file pbx.c.
Referenced by __sip_destroy(), and handle_request_subscribe().
02116 { 02117 struct ast_state_cb **p_cur = NULL; /* address of pointer to us */ 02118 int ret = -1; 02119 02120 if (!id && !callback) 02121 return -1; 02122 02123 AST_LIST_LOCK(&hints); 02124 02125 if (!id) { /* id == 0 is a callback without extension */ 02126 for (p_cur = &statecbs; *p_cur; p_cur = &(*p_cur)->next) { 02127 if ((*p_cur)->callback == callback) 02128 break; 02129 } 02130 } else { /* callback with extension, find the callback based on ID */ 02131 struct ast_hint *hint; 02132 AST_LIST_TRAVERSE(&hints, hint, list) { 02133 for (p_cur = &hint->callbacks; *p_cur; p_cur = &(*p_cur)->next) { 02134 if ((*p_cur)->id == id) 02135 break; 02136 } 02137 if (*p_cur) /* found in the inner loop */ 02138 break; 02139 } 02140 } 02141 if (p_cur && *p_cur) { 02142 struct ast_state_cb *cur = *p_cur; 02143 *p_cur = cur->next; 02144 free(cur); 02145 ret = 0; 02146 } 02147 AST_LIST_UNLOCK(&hints); 02148 return ret; 02149 }
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 2266 of file pbx.c.
Referenced by action_originate(), action_redirect(), ast_parseable_goto(), asyncgoto_exec(), and handle_setpriority().
02267 { 02268 return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL); 02269 }
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 2271 of file pbx.c.
Referenced by pbx_load_config().
02272 { 02273 return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL); 02274 }
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 1517 of file pbx.c.
Referenced by action_getvar(), handle_getvariable(), and pbx_substitute_variables_helper_full().
01518 { 01519 char *args = func_args(function); 01520 struct ast_custom_function *acfptr = ast_custom_function_find(function); 01521 01522 if (acfptr == NULL) 01523 ast_log(LOG_ERROR, "Function %s not registered\n", function); 01524 else if (!acfptr->read) 01525 ast_log(LOG_ERROR, "Function %s cannot be read\n", function); 01526 else 01527 return acfptr->read(chan, function, args, workspace, len); 01528 return -1; 01529 }
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 1531 of file pbx.c.
Referenced by pbx_builtin_pushvar_helper(), and pbx_builtin_setvar_helper().
01532 { 01533 char *args = func_args(function); 01534 struct ast_custom_function *acfptr = ast_custom_function_find(function); 01535 01536 if (acfptr == NULL) 01537 ast_log(LOG_ERROR, "Function %s not registered\n", function); 01538 else if (!acfptr->write) 01539 ast_log(LOG_ERROR, "Function %s cannot be written to\n", function); 01540 else 01541 return acfptr->write(chan, function, args, value); 01542 01543 return -1; 01544 }
const char* ast_get_context_name | ( | struct ast_context * | con | ) |
Definition at line 6087 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 6125 of file pbx.c.
Referenced by handle_save_dialplan(), and show_dialplan_helper().
06126 { 06127 return c ? c->registrar : NULL; 06128 }
const char* ast_get_extension_app | ( | struct ast_exten * | e | ) |
Definition at line 6155 of file pbx.c.
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().
06156 { 06157 return e ? e->app : NULL; 06158 }
void* ast_get_extension_app_data | ( | struct ast_exten * | e | ) |
Definition at line 6160 of file pbx.c.
Referenced by _macro_exec(), ast_get_hint(), handle_save_dialplan(), and print_ext().
06161 { 06162 return e ? e->data : NULL; 06163 }
const char* ast_get_extension_cidmatch | ( | struct ast_exten * | e | ) |
Definition at line 6150 of file pbx.c.
Referenced by find_matching_priority(), and handle_save_dialplan().
06151 { 06152 return e ? e->cidmatch : NULL; 06153 }
struct ast_context* ast_get_extension_context | ( | struct ast_exten * | exten | ) | [read] |
Definition at line 6092 of file pbx.c.
Referenced by handle_show_hints().
06093 { 06094 return exten ? exten->parent : NULL; 06095 }
const char* ast_get_extension_label | ( | struct ast_exten * | exten | ) |
Definition at line 6102 of file pbx.c.
Referenced by handle_save_dialplan(), and show_dialplan_helper().
06103 { 06104 return exten ? exten->label : NULL; 06105 }
int ast_get_extension_matchcid | ( | struct ast_exten * | e | ) |
Definition at line 6145 of file pbx.c.
Referenced by find_matching_priority(), and handle_save_dialplan().
06146 { 06147 return e ? e->matchcid : 0; 06148 }
const char* ast_get_extension_name | ( | struct ast_exten * | exten | ) |
Definition at line 6097 of file pbx.c.
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().
06098 { 06099 return exten ? exten->exten : NULL; 06100 }
int ast_get_extension_priority | ( | struct ast_exten * | exten | ) |
Definition at line 6117 of file pbx.c.
Referenced by complete_context_remove_extension(), complete_context_remove_extension_deprecated(), find_matching_priority(), handle_save_dialplan(), and print_ext().
06118 { 06119 return exten ? exten->priority : -1; 06120 }
const char* ast_get_extension_registrar | ( | struct ast_exten * | e | ) |
Definition at line 6130 of file pbx.c.
Referenced by handle_save_dialplan(), and show_dialplan_helper().
06131 { 06132 return e ? e->registrar : NULL; 06133 }
int ast_get_hint | ( | char * | hint, | |
int | hintsize, | |||
char * | name, | |||
int | namesize, | |||
struct ast_channel * | c, | |||
const char * | context, | |||
const char * | exten | |||
) |
ast_get_hint: Get hint for channel
If an extension exists, return non-zero.
Definition at line 2244 of file pbx.c.
Referenced by action_extensionstate(), get_cid_name(), pbx_retrieve_variable(), and transmit_state_notify().
02245 { 02246 struct ast_exten *e = ast_hint_extension(c, context, exten); 02247 02248 if (e) { 02249 if (hint) 02250 ast_copy_string(hint, ast_get_extension_app(e), hintsize); 02251 if (name) { 02252 const char *tmp = ast_get_extension_app_data(e); 02253 if (tmp) 02254 ast_copy_string(name, tmp, namesize); 02255 } 02256 return -1; 02257 } 02258 return 0; 02259 }
const char* ast_get_ignorepat_name | ( | struct ast_ignorepat * | ip | ) |
Definition at line 6112 of file pbx.c.
Referenced by complete_context_remove_ignorepat(), complete_context_remove_ignorepat_deprecated(), handle_save_dialplan(), lookup_c_ip(), and show_dialplan_helper().
06113 { 06114 return ip ? ip->pattern : NULL; 06115 }
const char* ast_get_ignorepat_registrar | ( | struct ast_ignorepat * | ip | ) |
Definition at line 6140 of file pbx.c.
Referenced by handle_save_dialplan(), and show_dialplan_helper().
06141 { 06142 return ip ? ip->registrar : NULL; 06143 }
const char* ast_get_include_name | ( | struct ast_include * | inc | ) |
Definition at line 6107 of file pbx.c.
Referenced by complete_context_dont_include_deprecated(), complete_context_remove_include(), find_matching_priority(), handle_save_dialplan(), lookup_ci(), and show_dialplan_helper().
06108 { 06109 return inc ? inc->name : NULL; 06110 }
const char* ast_get_include_registrar | ( | struct ast_include * | i | ) |
Definition at line 6135 of file pbx.c.
Referenced by handle_save_dialplan(), and show_dialplan_helper().
06136 { 06137 return i ? i->registrar : NULL; 06138 }
const char* ast_get_switch_data | ( | struct ast_sw * | sw | ) |
Definition at line 6170 of file pbx.c.
Referenced by handle_save_dialplan(), and show_dialplan_helper().
06171 { 06172 return sw ? sw->data : NULL; 06173 }
const char* ast_get_switch_name | ( | struct ast_sw * | sw | ) |
Definition at line 6165 of file pbx.c.
Referenced by handle_save_dialplan(), and show_dialplan_helper().
06166 { 06167 return sw ? sw->name : NULL; 06168 }
const char* ast_get_switch_registrar | ( | struct ast_sw * | sw | ) |
Definition at line 6175 of file pbx.c.
Referenced by handle_save_dialplan(), and show_dialplan_helper().
06176 { 06177 return sw ? sw->registrar : NULL; 06178 }
int ast_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 6264 of file pbx.c.
Referenced by aqm_exec(), auth_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().
06265 { 06266 return __ast_goto_if_exists(chan, context, exten, priority, 0); 06267 }
static struct ast_exten* ast_hint_extension | ( | struct ast_channel * | c, | |
const char * | context, | |||
const char * | exten | |||
) | [static, read] |
ast_hint_extension: Find hint for given extension in context
Definition at line 1875 of file pbx.c.
References ast_mutex_lock(), ast_mutex_unlock(), E_MATCH, pbx_find_extension(), PRIORITY_HINT, and pbx_find_info::stacklen.
Referenced by ast_extension_state(), ast_extension_state_add(), ast_get_hint(), and ast_merge_contexts_and_delete().
01876 { 01877 struct ast_exten *e; 01878 struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */ 01879 01880 ast_mutex_lock(&conlock); 01881 e = pbx_find_extension(c, NULL, &q, context, exten, PRIORITY_HINT, NULL, "", E_MATCH); 01882 ast_mutex_unlock(&conlock); 01883 01884 return e; 01885 }
void ast_hint_state_changed | ( | const char * | device | ) |
Definition at line 1996 of file pbx.c.
Referenced by do_state_change().
01997 { 01998 struct ast_hint *hint; 01999 02000 AST_LIST_LOCK(&hints); 02001 02002 AST_LIST_TRAVERSE(&hints, hint, list) { 02003 struct ast_state_cb *cblist; 02004 char buf[AST_MAX_EXTENSION]; 02005 char *parse = buf; 02006 char *cur; 02007 int state; 02008 02009 ast_copy_string(buf, ast_get_extension_app(hint->exten), sizeof(buf)); 02010 while ( (cur = strsep(&parse, "&")) ) { 02011 if (!strcasecmp(cur, device)) 02012 break; 02013 } 02014 if (!cur) 02015 continue; 02016 02017 /* Get device state for this hint */ 02018 state = ast_extension_state2(hint->exten); 02019 02020 if ((state == -1) || (state == hint->laststate)) 02021 continue; 02022 02023 /* Device state changed since last check - notify the watchers */ 02024 02025 /* For general callbacks */ 02026 for (cblist = statecbs; cblist; cblist = cblist->next) 02027 cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data); 02028 02029 /* For extension callbacks */ 02030 for (cblist = hint->callbacks; cblist; cblist = cblist->next) 02031 cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data); 02032 02033 hint->laststate = state; /* record we saw the change */ 02034 } 02035 02036 AST_LIST_UNLOCK(&hints); 02037 }
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 4511 of file pbx.c.
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().
04512 { 04513 struct ast_context *con = ast_context_find(context); 04514 if (con) { 04515 struct ast_ignorepat *pat; 04516 for (pat = con->ignorepats; pat; pat = pat->next) { 04517 if (ast_extension_match(pat->pattern, pattern)) 04518 return 1; 04519 } 04520 } 04521 04522 return 0; 04523 }
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 6074 of file pbx.c.
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().
06075 { 06076 return ast_mutex_lock(&con->lock); 06077 }
int ast_lock_contexts | ( | void | ) |
Locks the context list.
0 | on success | |
-1 | on error |
Definition at line 6061 of file pbx.c.
Referenced by _macro_exec(), ast_context_lockmacro(), ast_context_unlockmacro(), complete_context_add_extension(), complete_context_add_extension_deprecated(), complete_context_add_ignorepat(), complete_context_add_ignorepat_deprecated(), complete_context_add_include(), complete_context_add_include_deprecated(), complete_context_dont_include_deprecated(), complete_context_remove_extension(), complete_context_remove_extension_deprecated(), complete_context_remove_ignorepat(), complete_context_remove_ignorepat_deprecated(), complete_context_remove_include(), complete_show_dialplan_context(), dundi_precache_full(), find_context_locked(), find_matching_endwhile(), handle_save_dialplan(), and show_dialplan_helper().
06062 { 06063 return ast_mutex_lock(&conlock); 06064 }
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 2281 of file pbx.c.
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().
02282 { 02283 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE); 02284 }
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 3906 of file pbx.c.
Referenced by pbx_load_module().
03907 { 03908 struct ast_context *tmp, *lasttmp = NULL; 03909 struct store_hints store = AST_LIST_HEAD_INIT_VALUE; 03910 struct store_hint *this; 03911 struct ast_hint *hint; 03912 struct ast_exten *exten; 03913 int length; 03914 struct ast_state_cb *thiscb, *prevcb; 03915 03916 /* it is very important that this function hold the hint list lock _and_ the conlock 03917 during its operation; not only do we need to ensure that the list of contexts 03918 and extensions does not change, but also that no hint callbacks (watchers) are 03919 added or removed during the merge/delete process 03920 03921 in addition, the locks _must_ be taken in this order, because there are already 03922 other code paths that use this order 03923 */ 03924 ast_mutex_lock(&conlock); 03925 AST_LIST_LOCK(&hints); 03926 03927 /* preserve all watchers for hints associated with this registrar */ 03928 AST_LIST_TRAVERSE(&hints, hint, list) { 03929 if (hint->callbacks && !strcmp(registrar, hint->exten->parent->registrar)) { 03930 length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2 + sizeof(*this); 03931 if (!(this = ast_calloc(1, length))) 03932 continue; 03933 this->callbacks = hint->callbacks; 03934 hint->callbacks = NULL; 03935 this->laststate = hint->laststate; 03936 this->context = this->data; 03937 strcpy(this->data, hint->exten->parent->name); 03938 this->exten = this->data + strlen(this->context) + 1; 03939 strcpy(this->exten, hint->exten->exten); 03940 AST_LIST_INSERT_HEAD(&store, this, list); 03941 } 03942 } 03943 03944 tmp = *extcontexts; 03945 if (registrar) { 03946 /* XXX remove previous contexts from same registrar */ 03947 if (option_debug) 03948 ast_log(LOG_DEBUG, "must remove any reg %s\n", registrar); 03949 __ast_context_destroy(NULL,registrar); 03950 while (tmp) { 03951 lasttmp = tmp; 03952 tmp = tmp->next; 03953 } 03954 } else { 03955 /* XXX remove contexts with the same name */ 03956 while (tmp) { 03957 ast_log(LOG_WARNING, "must remove %s reg %s\n", tmp->name, tmp->registrar); 03958 __ast_context_destroy(tmp,tmp->registrar); 03959 lasttmp = tmp; 03960 tmp = tmp->next; 03961 } 03962 } 03963 if (lasttmp) { 03964 lasttmp->next = contexts; 03965 contexts = *extcontexts; 03966 *extcontexts = NULL; 03967 } else 03968 ast_log(LOG_WARNING, "Requested contexts didn't get merged\n"); 03969 03970 /* restore the watchers for hints that can be found; notify those that 03971 cannot be restored 03972 */ 03973 while ((this = AST_LIST_REMOVE_HEAD(&store, list))) { 03974 exten = ast_hint_extension(NULL, this->context, this->exten); 03975 /* Find the hint in the list of hints */ 03976 AST_LIST_TRAVERSE(&hints, hint, list) { 03977 if (hint->exten == exten) 03978 break; 03979 } 03980 if (!exten || !hint) { 03981 /* this hint has been removed, notify the watchers */ 03982 prevcb = NULL; 03983 thiscb = this->callbacks; 03984 while (thiscb) { 03985 prevcb = thiscb; 03986 thiscb = thiscb->next; 03987 prevcb->callback(this->context, this->exten, AST_EXTENSION_REMOVED, prevcb->data); 03988 free(prevcb); 03989 } 03990 } else { 03991 thiscb = this->callbacks; 03992 while (thiscb->next) 03993 thiscb = thiscb->next; 03994 thiscb->next = hint->callbacks; 03995 hint->callbacks = this->callbacks; 03996 hint->laststate = this->laststate; 03997 } 03998 free(this); 03999 } 04000 04001 AST_LIST_UNLOCK(&hints); 04002 ast_mutex_unlock(&conlock); 04003 04004 return; 04005 }
AST_MUTEX_DEFINE_STATIC | ( | conlock | ) |
Lock for the ast_context list
AST_MUTEX_DEFINE_STATIC | ( | maxcalllock | ) |
AST_MUTEX_DEFINE_STATIC | ( | globalslock | ) |
int ast_parseable_goto | ( | struct ast_channel * | chan, | |
const char * | goto_string | |||
) |
Definition at line 6274 of file pbx.c.
Referenced by _while_exec(), check_goto_on_transfer(), gosub_exec(), ivr_dispatch(), pbx_builtin_goto(), random_exec(), return_exec(), and while_continue_exec().
06275 { 06276 char *exten, *pri, *context; 06277 char *stringp; 06278 int ipri; 06279 int mode = 0; 06280 06281 if (ast_strlen_zero(goto_string)) { 06282 ast_log(LOG_WARNING, "Goto requires an argument (optional context|optional extension|priority)\n"); 06283 return -1; 06284 } 06285 stringp = ast_strdupa(goto_string); 06286 context = strsep(&stringp, "|"); /* guaranteed non-null */ 06287 exten = strsep(&stringp, "|"); 06288 pri = strsep(&stringp, "|"); 06289 if (!exten) { /* Only a priority in this one */ 06290 pri = context; 06291 exten = NULL; 06292 context = NULL; 06293 } else if (!pri) { /* Only an extension and priority in this one */ 06294 pri = exten; 06295 exten = context; 06296 context = NULL; 06297 } 06298 if (*pri == '+') { 06299 mode = 1; 06300 pri++; 06301 } else if (*pri == '-') { 06302 mode = -1; 06303 pri++; 06304 } 06305 if (sscanf(pri, "%d", &ipri) != 1) { 06306 if ((ipri = ast_findlabel_extension(chan, context ? context : chan->context, exten ? exten : chan->exten, 06307 pri, chan->cid.cid_num)) < 1) { 06308 ast_log(LOG_WARNING, "Priority '%s' must be a number > 0, or valid label\n", pri); 06309 return -1; 06310 } else 06311 mode = 0; 06312 } 06313 /* At this point we have a priority and maybe an extension and a context */ 06314 06315 if (mode) 06316 ipri = chan->priority + (ipri * mode); 06317 06318 ast_explicit_goto(chan, context, exten, ipri); 06319 ast_cdr_update(chan); 06320 return 0; 06321 06322 }
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 5116 of file pbx.c.
Referenced by action_originate(), attempt_thread(), fast_originate(), and orig_app().
05117 { 05118 struct ast_channel *chan; 05119 struct app_tmp *tmp; 05120 int res = -1, cdr_res = -1; 05121 struct outgoing_helper oh; 05122 pthread_attr_t attr; 05123 05124 memset(&oh, 0, sizeof(oh)); 05125 oh.vars = vars; 05126 oh.account = account; 05127 05128 if (locked_channel) 05129 *locked_channel = NULL; 05130 if (ast_strlen_zero(app)) { 05131 res = -1; 05132 goto outgoing_app_cleanup; 05133 } 05134 if (sync) { 05135 chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh); 05136 if (chan) { 05137 if (chan->cdr) { /* check if the channel already has a cdr record, if not give it one */ 05138 ast_log(LOG_WARNING, "%s already has a call record??\n", chan->name); 05139 } else { 05140 chan->cdr = ast_cdr_alloc(); /* allocate a cdr for the channel */ 05141 if(!chan->cdr) { 05142 /* allocation of the cdr failed */ 05143 free(chan->pbx); 05144 res = -1; 05145 goto outgoing_app_cleanup; 05146 } 05147 /* allocation of the cdr was successful */ 05148 ast_cdr_init(chan->cdr, chan); /* initilize our channel's cdr */ 05149 ast_cdr_start(chan->cdr); 05150 } 05151 ast_set_variables(chan, vars); 05152 if (account) 05153 ast_cdr_setaccount(chan, account); 05154 if (chan->_state == AST_STATE_UP) { 05155 res = 0; 05156 if (option_verbose > 3) 05157 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", chan->name); 05158 tmp = ast_calloc(1, sizeof(*tmp)); 05159 if (!tmp) 05160 res = -1; 05161 else { 05162 ast_copy_string(tmp->app, app, sizeof(tmp->app)); 05163 if (appdata) 05164 ast_copy_string(tmp->data, appdata, sizeof(tmp->data)); 05165 tmp->chan = chan; 05166 if (sync > 1) { 05167 if (locked_channel) 05168 ast_channel_unlock(chan); 05169 ast_pbx_run_app(tmp); 05170 } else { 05171 pthread_attr_init(&attr); 05172 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 05173 if (locked_channel) 05174 ast_channel_lock(chan); 05175 if (ast_pthread_create(&tmp->t, &attr, ast_pbx_run_app, tmp)) { 05176 ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno)); 05177 free(tmp); 05178 if (locked_channel) 05179 ast_channel_unlock(chan); 05180 ast_hangup(chan); 05181 res = -1; 05182 } else { 05183 if (locked_channel) 05184 *locked_channel = chan; 05185 } 05186 pthread_attr_destroy(&attr); 05187 } 05188 } 05189 } else { 05190 if (option_verbose > 3) 05191 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", chan->name); 05192 if (chan->cdr) { /* update the cdr */ 05193 /* here we update the status of the call, which sould be busy. 05194 * if that fails then we set the status to failed */ 05195 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 05196 ast_cdr_failed(chan->cdr); 05197 } 05198 ast_hangup(chan); 05199 } 05200 } 05201 05202 if (res < 0) { /* the call failed for some reason */ 05203 if (*reason == 0) { /* if the call failed (not busy or no answer) 05204 * update the cdr with the failed message */ 05205 cdr_res = ast_pbx_outgoing_cdr_failed(); 05206 if (cdr_res != 0) { 05207 res = cdr_res; 05208 goto outgoing_app_cleanup; 05209 } 05210 } 05211 } 05212 05213 } else { 05214 struct async_stat *as; 05215 if (!(as = ast_calloc(1, sizeof(*as)))) { 05216 res = -1; 05217 goto outgoing_app_cleanup; 05218 } 05219 chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh); 05220 if (!chan) { 05221 free(as); 05222 res = -1; 05223 goto outgoing_app_cleanup; 05224 } 05225 as->chan = chan; 05226 ast_copy_string(as->app, app, sizeof(as->app)); 05227 if (appdata) 05228 ast_copy_string(as->appdata, appdata, sizeof(as->appdata)); 05229 as->timeout = timeout; 05230 ast_set_variables(chan, vars); 05231 if (account) 05232 ast_cdr_setaccount(chan, account); 05233 /* Start a new thread, and get something handling this channel. */ 05234 pthread_attr_init(&attr); 05235 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 05236 if (locked_channel) 05237 ast_channel_lock(chan); 05238 if (ast_pthread_create(&as->p, &attr, async_wait, as)) { 05239 ast_log(LOG_WARNING, "Failed to start async wait\n"); 05240 free(as); 05241 if (locked_channel) 05242 ast_channel_unlock(chan); 05243 ast_hangup(chan); 05244 res = -1; 05245 pthread_attr_destroy(&attr); 05246 goto outgoing_app_cleanup; 05247 } else { 05248 if (locked_channel) 05249 *locked_channel = chan; 05250 } 05251 pthread_attr_destroy(&attr); 05252 res = 0; 05253 } 05254 outgoing_app_cleanup: 05255 ast_variables_destroy(vars); 05256 return res; 05257 }
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 4935 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().
04936 { 04937 /* allocate a channel */ 04938 struct ast_channel *chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, 0); 04939 04940 if (!chan) 04941 return -1; /* failure */ 04942 04943 if (!chan->cdr) { 04944 /* allocation of the cdr failed */ 04945 ast_channel_free(chan); /* free the channel */ 04946 return -1; /* return failure */ 04947 } 04948 04949 /* allocation of the cdr was successful */ 04950 ast_cdr_init(chan->cdr, chan); /* initilize our channel's cdr */ 04951 ast_cdr_start(chan->cdr); /* record the start and stop time */ 04952 ast_cdr_end(chan->cdr); 04953 ast_cdr_failed(chan->cdr); /* set the status to failed */ 04954 ast_cdr_detach(chan->cdr); /* post and free the record */ 04955 ast_channel_free(chan); /* free the channel */ 04956 04957 return 0; /* success */ 04958 }
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 4960 of file pbx.c.
Referenced by action_originate(), attempt_thread(), fast_originate(), and orig_exten().
04961 { 04962 struct ast_channel *chan; 04963 struct async_stat *as; 04964 int res = -1, cdr_res = -1; 04965 struct outgoing_helper oh; 04966 pthread_attr_t attr; 04967 04968 if (sync) { 04969 LOAD_OH(oh); 04970 chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh); 04971 if (channel) { 04972 *channel = chan; 04973 if (chan) 04974 ast_channel_lock(chan); 04975 } 04976 if (chan) { 04977 if (chan->_state == AST_STATE_UP) { 04978 res = 0; 04979 if (option_verbose > 3) 04980 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", chan->name); 04981 04982 if (sync > 1) { 04983 if (channel) 04984 ast_channel_unlock(chan); 04985 if (ast_pbx_run(chan)) { 04986 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 04987 if (channel) 04988 *channel = NULL; 04989 ast_hangup(chan); 04990 res = -1; 04991 } 04992 } else { 04993 if (ast_pbx_start(chan)) { 04994 ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name); 04995 if (channel) { 04996 *channel = NULL; 04997 ast_channel_unlock(chan); 04998 } 04999 ast_hangup(chan); 05000 res = -1; 05001 } 05002 } 05003 } else { 05004 if (option_verbose > 3) 05005 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", chan->name); 05006 05007 if (chan->cdr) { /* update the cdr */ 05008 /* here we update the status of the call, which sould be busy. 05009 * if that fails then we set the status to failed */ 05010 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 05011 ast_cdr_failed(chan->cdr); 05012 } 05013 05014 if (channel) { 05015 *channel = NULL; 05016 ast_channel_unlock(chan); 05017 } 05018 ast_hangup(chan); 05019 } 05020 } 05021 05022 if (res < 0) { /* the call failed for some reason */ 05023 if (*reason == 0) { /* if the call failed (not busy or no answer) 05024 * update the cdr with the failed message */ 05025 cdr_res = ast_pbx_outgoing_cdr_failed(); 05026 if (cdr_res != 0) { 05027 res = cdr_res; 05028 goto outgoing_exten_cleanup; 05029 } 05030 } 05031 05032 /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */ 05033 /* check if "failed" exists */ 05034 if (ast_exists_extension(chan, context, "failed", 1, NULL)) { 05035 chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "OutgoingSpoolFailed"); 05036 if (chan) { 05037 if (!ast_strlen_zero(context)) 05038 ast_copy_string(chan->context, context, sizeof(chan->context)); 05039 set_ext_pri(chan, "failed", 1); 05040 ast_set_variables(chan, vars); 05041 if (account) 05042 ast_cdr_setaccount(chan, account); 05043 ast_pbx_run(chan); 05044 } 05045 } 05046 } 05047 } else { 05048 if (!(as = ast_calloc(1, sizeof(*as)))) { 05049 res = -1; 05050 goto outgoing_exten_cleanup; 05051 } 05052 chan = ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name); 05053 if (channel) { 05054 *channel = chan; 05055 if (chan) 05056 ast_channel_lock(chan); 05057 } 05058 if (!chan) { 05059 free(as); 05060 res = -1; 05061 goto outgoing_exten_cleanup; 05062 } 05063 as->chan = chan; 05064 ast_copy_string(as->context, context, sizeof(as->context)); 05065 set_ext_pri(as->chan, exten, priority); 05066 as->timeout = timeout; 05067 ast_set_variables(chan, vars); 05068 if (account) 05069 ast_cdr_setaccount(chan, account); 05070 pthread_attr_init(&attr); 05071 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 05072 if (ast_pthread_create(&as->p, &attr, async_wait, as)) { 05073 ast_log(LOG_WARNING, "Failed to start async wait\n"); 05074 free(as); 05075 if (channel) { 05076 *channel = NULL; 05077 ast_channel_unlock(chan); 05078 } 05079 ast_hangup(chan); 05080 res = -1; 05081 pthread_attr_destroy(&attr); 05082 goto outgoing_exten_cleanup; 05083 } 05084 pthread_attr_destroy(&attr); 05085 res = 0; 05086 } 05087 outgoing_exten_cleanup: 05088 ast_variables_destroy(vars); 05089 return res; 05090 }
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 2637 of file pbx.c.
Referenced by ast_pbx_outgoing_exten(), async_wait(), mgcp_ss(), skinny_newcall(), and ss_thread().
02638 { 02639 enum ast_pbx_result res = AST_PBX_SUCCESS; 02640 02641 if (increase_call_count(c)) 02642 return AST_PBX_CALL_LIMIT; 02643 02644 res = __ast_pbx_run(c); 02645 decrease_call_count(); 02646 02647 return res; 02648 }
static void* ast_pbx_run_app | ( | void * | data | ) | [static] |
run the application and free the descriptor once done
Definition at line 5100 of file pbx.c.
References app_tmp::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().
05101 { 05102 struct app_tmp *tmp = data; 05103 struct ast_app *app; 05104 app = pbx_findapp(tmp->app); 05105 if (app) { 05106 if (option_verbose > 3) 05107 ast_verbose(VERBOSE_PREFIX_4 "Launching %s(%s) on %s\n", tmp->app, tmp->data, tmp->chan->name); 05108 pbx_exec(tmp->chan, app, tmp->data); 05109 } else 05110 ast_log(LOG_WARNING, "No such application '%s'\n", tmp->app); 05111 ast_hangup(tmp->chan); 05112 free(tmp); 05113 return NULL; 05114 }
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 2611 of file pbx.c.
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().
02612 { 02613 pthread_t t; 02614 pthread_attr_t attr; 02615 02616 if (!c) { 02617 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n"); 02618 return AST_PBX_FAILED; 02619 } 02620 02621 if (increase_call_count(c)) 02622 return AST_PBX_CALL_LIMIT; 02623 02624 /* Start a new thread, and get something handling this channel. */ 02625 pthread_attr_init(&attr); 02626 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 02627 if (ast_pthread_create(&t, &attr, pbx_thread, c)) { 02628 ast_log(LOG_WARNING, "Failed to create new channel thread\n"); 02629 pthread_attr_destroy(&attr); 02630 return AST_PBX_FAILED; 02631 } 02632 pthread_attr_destroy(&attr); 02633 02634 return AST_PBX_SUCCESS; 02635 }
int ast_register_application | ( | const char * | app, | |
int(*)(struct ast_channel *, void *) | execute, | |||
const char * | synopsis, | |||
const char * | description | |||
) |
Dynamically register a new dial plan application.
Register an application.
Definition at line 2939 of file pbx.c.
Referenced by load_module(), and load_pbx().
02940 { 02941 struct ast_app *tmp, *cur = NULL; 02942 char tmps[80]; 02943 int length; 02944 02945 AST_LIST_LOCK(&apps); 02946 AST_LIST_TRAVERSE(&apps, tmp, list) { 02947 if (!strcasecmp(app, tmp->name)) { 02948 ast_log(LOG_WARNING, "Already have an application '%s'\n", app); 02949 AST_LIST_UNLOCK(&apps); 02950 return -1; 02951 } 02952 } 02953 02954 length = sizeof(*tmp) + strlen(app) + 1; 02955 02956 if (!(tmp = ast_calloc(1, length))) { 02957 AST_LIST_UNLOCK(&apps); 02958 return -1; 02959 } 02960 02961 strcpy(tmp->name, app); 02962 tmp->execute = execute; 02963 tmp->synopsis = synopsis; 02964 tmp->description = description; 02965 02966 /* Store in alphabetical order */ 02967 AST_LIST_TRAVERSE_SAFE_BEGIN(&apps, cur, list) { 02968 if (strcasecmp(tmp->name, cur->name) < 0) { 02969 AST_LIST_INSERT_BEFORE_CURRENT(&apps, tmp, list); 02970 break; 02971 } 02972 } 02973 AST_LIST_TRAVERSE_SAFE_END 02974 if (!cur) 02975 AST_LIST_INSERT_TAIL(&apps, tmp, list); 02976 02977 if (option_verbose > 1) 02978 ast_verbose( VERBOSE_PREFIX_2 "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps))); 02979 02980 AST_LIST_UNLOCK(&apps); 02981 02982 return 0; 02983 }
int ast_register_switch | ( | struct ast_switch * | sw | ) |
Register an alternative dialplan switch.
sw | switch to register |
Definition at line 2989 of file pbx.c.
Referenced by load_module().
02990 { 02991 struct ast_switch *tmp; 02992 02993 AST_LIST_LOCK(&switches); 02994 AST_LIST_TRAVERSE(&switches, tmp, list) { 02995 if (!strcasecmp(tmp->name, sw->name)) { 02996 AST_LIST_UNLOCK(&switches); 02997 ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name); 02998 return -1; 02999 } 03000 } 03001 AST_LIST_INSERT_TAIL(&switches, sw, list); 03002 AST_LIST_UNLOCK(&switches); 03003 03004 return 0; 03005 }
static int ast_remove_hint | ( | struct ast_exten * | e | ) | [static] |
ast_remove_hint: Remove hint from extension
Definition at line 2207 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().
02208 { 02209 /* Cleanup the Notifys if hint is removed */ 02210 struct ast_hint *hint; 02211 struct ast_state_cb *cblist, *cbprev; 02212 int res = -1; 02213 02214 if (!e) 02215 return -1; 02216 02217 AST_LIST_LOCK(&hints); 02218 AST_LIST_TRAVERSE_SAFE_BEGIN(&hints, hint, list) { 02219 if (hint->exten == e) { 02220 cbprev = NULL; 02221 cblist = hint->callbacks; 02222 while (cblist) { 02223 /* Notify with -1 and remove all callbacks */ 02224 cbprev = cblist; 02225 cblist = cblist->next; 02226 cbprev->callback(hint->exten->parent->name, hint->exten->exten, AST_EXTENSION_DEACTIVATED, cbprev->data); 02227 free(cbprev); 02228 } 02229 hint->callbacks = NULL; 02230 AST_LIST_REMOVE_CURRENT(&hints, list); 02231 free(hint); 02232 res = 0; 02233 break; 02234 } 02235 } 02236 AST_LIST_TRAVERSE_SAFE_END 02237 AST_LIST_UNLOCK(&hints); 02238 02239 return res; 02240 }
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 2286 of file pbx.c.
Referenced by __ast_pbx_run(), _macro_exec(), and loopback_exec().
02287 { 02288 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN); 02289 }
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 6079 of file pbx.c.
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().
06080 { 06081 return ast_mutex_unlock(&con->lock); 06082 }
int ast_unlock_contexts | ( | void | ) |
Unlocks contexts.
0 | on success | |
-1 | on failure |
Definition at line 6066 of file pbx.c.
Referenced by _macro_exec(), ast_add_extension(), ast_context_add_ignorepat(), ast_context_add_include(), ast_context_add_switch(), ast_context_lockmacro(), ast_context_remove_extension(), ast_context_remove_ignorepat(), ast_context_remove_include(), ast_context_remove_switch(), ast_context_unlockmacro(), complete_context_add_extension(), complete_context_add_extension_deprecated(), complete_context_add_ignorepat(), complete_context_add_ignorepat_deprecated(), complete_context_add_include(), complete_context_add_include_deprecated(), complete_context_dont_include_deprecated(), complete_context_remove_extension(), complete_context_remove_extension_deprecated(), complete_context_remove_ignorepat(), complete_context_remove_ignorepat_deprecated(), complete_context_remove_include(), complete_show_dialplan_context(), dundi_precache_full(), find_context_locked(), find_matching_endwhile(), handle_save_dialplan(), and show_dialplan_helper().
06067 { 06068 return ast_mutex_unlock(&conlock); 06069 }
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 3820 of file pbx.c.
Referenced by __unload_module(), and unload_module().
03821 { 03822 struct ast_app *tmp; 03823 03824 AST_LIST_LOCK(&apps); 03825 AST_LIST_TRAVERSE_SAFE_BEGIN(&apps, tmp, list) { 03826 if (!strcasecmp(app, tmp->name)) { 03827 AST_LIST_REMOVE_CURRENT(&apps, list); 03828 if (option_verbose > 1) 03829 ast_verbose( VERBOSE_PREFIX_2 "Unregistered application '%s'\n", tmp->name); 03830 free(tmp); 03831 break; 03832 } 03833 } 03834 AST_LIST_TRAVERSE_SAFE_END 03835 AST_LIST_UNLOCK(&apps); 03836 03837 return tmp ? 0 : -1; 03838 }
void ast_unregister_switch | ( | struct ast_switch * | sw | ) |
Unregister an alternative switch.
sw | switch to unregister |
Definition at line 3007 of file pbx.c.
Referenced by __unload_module(), and unload_module().
03008 { 03009 AST_LIST_LOCK(&switches); 03010 AST_LIST_REMOVE(&switches, sw, list); 03011 AST_LIST_UNLOCK(&switches); 03012 }
struct ast_exten* ast_walk_context_extensions | ( | struct ast_context * | con, | |
struct ast_exten * | exten | |||
) | [read] |
Definition at line 6188 of file pbx.c.
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().
06190 { 06191 if (!exten) 06192 return con ? con->root : NULL; 06193 else 06194 return exten->next; 06195 }
struct ast_ignorepat* ast_walk_context_ignorepats | ( | struct ast_context * | con, | |
struct ast_ignorepat * | ip | |||
) | [read] |
Definition at line 6221 of file pbx.c.
Referenced by complete_context_remove_ignorepat(), complete_context_remove_ignorepat_deprecated(), handle_save_dialplan(), lookup_c_ip(), and show_dialplan_helper().
06223 { 06224 if (!ip) 06225 return con ? con->ignorepats : NULL; 06226 else 06227 return ip->next; 06228 }
struct ast_include* ast_walk_context_includes | ( | struct ast_context * | con, | |
struct ast_include * | inc | |||
) | [read] |
Definition at line 6212 of file pbx.c.
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().
06214 { 06215 if (!inc) 06216 return con ? con->includes : NULL; 06217 else 06218 return inc->next; 06219 }
struct ast_sw* ast_walk_context_switches | ( | struct ast_context * | con, | |
struct ast_sw * | sw | |||
) | [read] |
Definition at line 6197 of file pbx.c.
Referenced by handle_save_dialplan(), and show_dialplan_helper().
06199 { 06200 if (!sw) 06201 return con ? AST_LIST_FIRST(&con->alts) : NULL; 06202 else 06203 return AST_LIST_NEXT(sw, list); 06204 }
struct ast_context* ast_walk_contexts | ( | struct ast_context * | con | ) | [read] |
Definition at line 6183 of file pbx.c.
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 | |||
) | [read] |
Definition at line 6206 of file pbx.c.
Referenced by complete_context_remove_extension(), complete_context_remove_extension_deprecated(), find_matching_priority(), handle_save_dialplan(), pbx_find_extension(), and show_dialplan_helper().
06208 { 06209 return priority ? priority->peer : exten; 06210 }
static void* async_wait | ( | void * | data | ) | [static] |
Definition at line 4872 of file pbx.c.
References ast_channel::_state, 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, ast_frame::frametype, free, LOG_ERROR, LOG_WARNING, option_verbose, pbx_exec(), pbx_findapp(), ast_channel::priority, async_stat::priority, ast_frame::subclass, async_stat::timeout, and VERBOSE_PREFIX_3.
Referenced by ast_pbx_outgoing_app(), and ast_pbx_outgoing_exten().
04873 { 04874 struct async_stat *as = data; 04875 struct ast_channel *chan = as->chan; 04876 int timeout = as->timeout; 04877 int res; 04878 struct ast_frame *f; 04879 struct ast_app *app; 04880 04881 while (timeout && (chan->_state != AST_STATE_UP)) { 04882 res = ast_waitfor(chan, timeout); 04883 if (res < 1) 04884 break; 04885 if (timeout > -1) 04886 timeout = res; 04887 f = ast_read(chan); 04888 if (!f) 04889 break; 04890 if (f->frametype == AST_FRAME_CONTROL) { 04891 if ((f->subclass == AST_CONTROL_BUSY) || 04892 (f->subclass == AST_CONTROL_CONGESTION) ) { 04893 ast_frfree(f); 04894 break; 04895 } 04896 } 04897 ast_frfree(f); 04898 } 04899 if (chan->_state == AST_STATE_UP) { 04900 if (!ast_strlen_zero(as->app)) { 04901 app = pbx_findapp(as->app); 04902 if (app) { 04903 if (option_verbose > 2) 04904 ast_verbose(VERBOSE_PREFIX_3 "Launching %s(%s) on %s\n", as->app, as->appdata, chan->name); 04905 pbx_exec(chan, app, as->appdata); 04906 } else 04907 ast_log(LOG_WARNING, "No such application '%s'\n", as->app); 04908 } else { 04909 if (!ast_strlen_zero(as->context)) 04910 ast_copy_string(chan->context, as->context, sizeof(chan->context)); 04911 if (!ast_strlen_zero(as->exten)) 04912 ast_copy_string(chan->exten, as->exten, sizeof(chan->exten)); 04913 if (as->priority > 0) 04914 chan->priority = as->priority; 04915 /* Run the PBX */ 04916 if (ast_pbx_run(chan)) { 04917 ast_log(LOG_ERROR, "Failed to start PBX on %s\n", chan->name); 04918 } else { 04919 /* PBX will have taken care of this */ 04920 chan = NULL; 04921 } 04922 } 04923 } 04924 free(as); 04925 if (chan) 04926 ast_hangup(chan); 04927 return NULL; 04928 }
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 2302 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.
Referenced by __ast_pbx_run().
02303 { 02304 int digit; 02305 02306 buf[pos] = '\0'; /* make sure it is properly terminated */ 02307 while (ast_matchmore_extension(c, c->context, buf, 1, c->cid.cid_num)) { 02308 /* As long as we're willing to wait, and as long as it's not defined, 02309 keep reading digits until we can't possibly get a right answer anymore. */ 02310 digit = ast_waitfordigit(c, waittime * 1000); 02311 if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) { 02312 c->_softhangup = 0; 02313 } else { 02314 if (!digit) /* No entry */ 02315 break; 02316 if (digit < 0) /* Error, maybe a hangup */ 02317 return -1; 02318 if (pos < buflen - 1) { /* XXX maybe error otherwise ? */ 02319 buf[pos++] = digit; 02320 buf[pos] = '\0'; 02321 } 02322 waittime = c->pbx->dtimeout; 02323 } 02324 } 02325 return 0; 02326 }
static char* complete_show_application | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 3065 of file pbx.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, and strdup.
03066 { 03067 struct ast_app *a; 03068 char *ret = NULL; 03069 int which = 0; 03070 int wordlen = strlen(word); 03071 03072 /* return the n-th [partial] matching entry */ 03073 AST_LIST_LOCK(&apps); 03074 AST_LIST_TRAVERSE(&apps, a, list) { 03075 if (!strncasecmp(word, a->name, wordlen) && ++which > state) { 03076 ret = strdup(a->name); 03077 break; 03078 } 03079 } 03080 AST_LIST_UNLOCK(&apps); 03081 03082 return ret; 03083 }
static char* complete_show_applications | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 3426 of file pbx.c.
References ast_cli_complete().
03427 { 03428 static char* choices[] = { "like", "describing", NULL }; 03429 03430 return (pos != 3) ? NULL : ast_cli_complete(word, choices, state); 03431 }
static char* complete_show_applications_deprecated | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 3419 of file pbx.c.
References ast_cli_complete().
03420 { 03421 static char* choices[] = { "like", "describing", NULL }; 03422 03423 return (pos != 2) ? NULL : ast_cli_complete(word, choices, state); 03424 }
static char* complete_show_dialplan_context | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 3436 of file pbx.c.
References ast_get_context_name(), ast_lock_contexts(), ast_strdup, ast_unlock_contexts(), and ast_walk_contexts().
03438 { 03439 struct ast_context *c = NULL; 03440 char *ret = NULL; 03441 int which = 0; 03442 int wordlen; 03443 03444 /* we are do completion of [exten@]context on second position only */ 03445 if (pos != 2) 03446 return NULL; 03447 03448 ast_lock_contexts(); 03449 03450 wordlen = strlen(word); 03451 03452 /* walk through all contexts and return the n-th match */ 03453 while ( (c = ast_walk_contexts(c)) ) { 03454 if (!strncasecmp(word, ast_get_context_name(c), wordlen) && ++which > state) { 03455 ret = ast_strdup(ast_get_context_name(c)); 03456 break; 03457 } 03458 } 03459 03460 ast_unlock_contexts(); 03461 03462 return ret; 03463 }
static char* complete_show_function | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 1407 of file pbx.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_custom_function::name, and strdup.
01408 { 01409 struct ast_custom_function *acf; 01410 char *ret = NULL; 01411 int which = 0; 01412 int wordlen = strlen(word); 01413 01414 /* case-insensitive for convenience in this 'complete' function */ 01415 AST_LIST_LOCK(&acf_root); 01416 AST_LIST_TRAVERSE(&acf_root, acf, acflist) { 01417 if (!strncasecmp(word, acf->name, wordlen) && ++which > state) { 01418 ret = strdup(acf->name); 01419 break; 01420 } 01421 } 01422 AST_LIST_UNLOCK(&acf_root); 01423 01424 return ret; 01425 }
static void decrease_call_count | ( | void | ) | [static] |
Definition at line 2573 of file pbx.c.
References ast_mutex_lock(), ast_mutex_unlock(), and countcalls.
Referenced by ast_pbx_run(), and pbx_thread().
02574 { 02575 ast_mutex_lock(&maxcalllock); 02576 if (countcalls > 0) 02577 countcalls--; 02578 ast_mutex_unlock(&maxcalllock); 02579 }
static void destroy_exten | ( | struct ast_exten * | e | ) | [static] |
Definition at line 2581 of file pbx.c.
References ast_remove_hint(), ast_exten::data, ast_exten::datad, free, ast_exten::priority, and PRIORITY_HINT.
Referenced by __ast_context_destroy(), and ast_context_remove_extension2().
02582 { 02583 if (e->priority == PRIORITY_HINT) 02584 ast_remove_hint(e); 02585 02586 if (e->datad) 02587 e->datad(e->data); 02588 free(e); 02589 }
static int ext_cmp | ( | const char * | a, | |
const char * | b | |||
) | [static] |
the full routine to compare extensions in rules.
Definition at line 717 of file pbx.c.
References ext_cmp1().
Referenced by ast_add_extension2().
00718 { 00719 /* make sure non-patterns come first. 00720 * If a is not a pattern, it either comes first or 00721 * we use strcmp to compare the strings. 00722 */ 00723 int ret = 0; 00724 00725 if (a[0] != '_') 00726 return (b[0] == '_') ? -1 : strcmp(a, b); 00727 00728 /* Now we know a is a pattern; if b is not, a comes first */ 00729 if (b[0] != '_') 00730 return 1; 00731 #if 0 /* old mode for ext matching */ 00732 return strcmp(a, b); 00733 #endif 00734 /* ok we need full pattern sorting routine */ 00735 while (!ret && a && b) 00736 ret = ext_cmp1(&a) - ext_cmp1(&b); 00737 if (ret == 0) 00738 return 0; 00739 else 00740 return (ret > 0) ? 1 : -1; 00741 }
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 645 of file pbx.c.
References ast_log(), and LOG_WARNING.
Referenced by ext_cmp().
00646 { 00647 uint32_t chars[8]; 00648 int c, cmin = 0xff, count = 0; 00649 const char *end; 00650 00651 /* load, sign extend and advance pointer until we find 00652 * a valid character. 00653 */ 00654 while ( (c = *(*p)++) && (c == ' ' || c == '-') ) 00655 ; /* ignore some characters */ 00656 00657 /* always return unless we have a set of chars */ 00658 switch (c) { 00659 default: /* ordinary character */ 00660 return 0x0000 | (c & 0xff); 00661 00662 case 'N': /* 2..9 */ 00663 return 0x0700 | '2' ; 00664 00665 case 'X': /* 0..9 */ 00666 return 0x0900 | '0'; 00667 00668 case 'Z': /* 1..9 */ 00669 return 0x0800 | '1'; 00670 00671 case '.': /* wildcard */ 00672 return 0x10000; 00673 00674 case '!': /* earlymatch */ 00675 return 0x20000; /* less specific than NULL */ 00676 00677 case '\0': /* empty string */ 00678 *p = NULL; 00679 return 0x30000; 00680 00681 case '[': /* pattern */ 00682 break; 00683 } 00684 /* locate end of set */ 00685 end = strchr(*p, ']'); 00686 00687 if (end == NULL) { 00688 ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n"); 00689 return 0x40000; /* XXX make this entry go last... */ 00690 } 00691 00692 bzero(chars, sizeof(chars)); /* clear all chars in the set */ 00693 for (; *p < end ; (*p)++) { 00694 unsigned char c1, c2; /* first-last char in range */ 00695 c1 = (unsigned char)((*p)[0]); 00696 if (*p + 2 < end && (*p)[1] == '-') { /* this is a range */ 00697 c2 = (unsigned char)((*p)[2]); 00698 *p += 2; /* skip a total of 3 chars */ 00699 } else /* individual character */ 00700 c2 = c1; 00701 if (c1 < cmin) 00702 cmin = c1; 00703 for (; c1 <= c2; c1++) { 00704 uint32_t mask = 1 << (c1 % 32); 00705 if ( (chars[ c1 / 32 ] & mask) == 0) 00706 count += 0x100; 00707 chars[ c1 / 32 ] |= mask; 00708 } 00709 } 00710 (*p)++; 00711 return count == 0 ? 0x30000 : (count | cmin); 00712 }
static int ext_strncpy | ( | char * | dst, | |
const char * | src, | |||
int | len | |||
) | [static] |
copy a string skipping whitespace
Definition at line 4624 of file pbx.c.
Referenced by ast_add_extension2().
04625 { 04626 int count=0; 04627 04628 while (*src && (count < len - 1)) { 04629 switch(*src) { 04630 case ' ': 04631 /* otherwise exten => [a-b],1,... doesn't work */ 04632 /* case '-': */ 04633 /* Ignore */ 04634 break; 04635 default: 04636 *dst = *src; 04637 dst++; 04638 } 04639 src++; 04640 count++; 04641 } 04642 *dst = '\0'; 04643 04644 return count; 04645 }
static int extension_match_core | ( | const char * | pattern, | |
const char * | data, | |||
enum ext_match_t | mode | |||
) | [static] |
Definition at line 866 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().
00867 { 00868 int i; 00869 static int prof_id = -2; /* marker for 'unallocated' id */ 00870 if (prof_id == -2) 00871 prof_id = ast_add_profile("ext_match", 0); 00872 ast_mark(prof_id, 1); 00873 i = _extension_match_core(pattern, data, mode); 00874 ast_mark(prof_id, 0); 00875 return i; 00876 }
static struct ast_context* find_context_locked | ( | const char * | context | ) | [static, read] |
Definition at line 2665 of file pbx.c.
References ast_get_context_name(), ast_lock_contexts(), ast_unlock_contexts(), and ast_walk_contexts().
Referenced by ast_add_extension(), ast_context_add_ignorepat(), ast_context_add_include(), ast_context_add_switch(), ast_context_remove_extension(), ast_context_remove_ignorepat(), ast_context_remove_include(), and ast_context_remove_switch().
02666 { 02667 struct ast_context *c = NULL; 02668 02669 ast_lock_contexts(); 02670 while ( (c = ast_walk_contexts(c)) ) { 02671 if (!strcmp(ast_get_context_name(c), context)) 02672 return c; 02673 } 02674 ast_unlock_contexts(); 02675 02676 return NULL; 02677 }
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 1500 of file pbx.c.
References ast_log(), and LOG_WARNING.
Referenced by ast_func_read(), and ast_func_write().
01501 { 01502 char *args = strchr(function, '('); 01503 01504 if (!args) 01505 ast_log(LOG_WARNING, "Function doesn't contain parentheses. Assuming null argument.\n"); 01506 else { 01507 char *p; 01508 *args++ = '\0'; 01509 if ((p = strrchr(args, ')')) ) 01510 *p = '\0'; 01511 else 01512 ast_log(LOG_WARNING, "Can't find trailing parenthesis?\n"); 01513 } 01514 return args; 01515 }
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 4046 of file pbx.c.
References ast_log(), ast_strlen_zero(), LOG_WARNING, lookup_name(), and s.
Referenced by ast_build_timing().
04047 { 04048 int s, e; /* start and ending position */ 04049 unsigned int mask = 0; 04050 04051 /* Check for whole range */ 04052 if (ast_strlen_zero(src) || !strcmp(src, "*")) { 04053 s = 0; 04054 e = max - 1; 04055 } else { 04056 /* Get start and ending position */ 04057 char *c = strchr(src, '-'); 04058 if (c) 04059 *c++ = '\0'; 04060 /* Find the start */ 04061 s = lookup_name(src, names, max); 04062 if (!s) { 04063 ast_log(LOG_WARNING, "Invalid %s '%s', assuming none\n", msg, src); 04064 return 0; 04065 } 04066 s--; 04067 if (c) { /* find end of range */ 04068 e = lookup_name(c, names, max); 04069 if (!e) { 04070 ast_log(LOG_WARNING, "Invalid end %s '%s', assuming none\n", msg, c); 04071 return 0; 04072 } 04073 e--; 04074 } else 04075 e = s; 04076 } 04077 /* Fill the mask. Remember that ranges are cyclic */ 04078 mask = 1 << e; /* initialize with last element */ 04079 while (s != e) { 04080 if (s >= max) { 04081 s = 0; 04082 mask |= (1 << s); 04083 } else { 04084 mask |= (1 << s); 04085 s++; 04086 } 04087 } 04088 return mask; 04089 }
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 4092 of file pbx.c.
References ast_log(), ast_strlen_zero(), LOG_WARNING, and ast_timing::minmask.
Referenced by ast_build_timing().
04093 { 04094 char *e; 04095 int x; 04096 int s1, s2; 04097 int e1, e2; 04098 /* int cth, ctm; */ 04099 04100 /* start disabling all times, fill the fields with 0's, as they may contain garbage */ 04101 memset(i->minmask, 0, sizeof(i->minmask)); 04102 04103 /* 2-minutes per bit, since the mask has only 32 bits :( */ 04104 /* Star is all times */ 04105 if (ast_strlen_zero(times) || !strcmp(times, "*")) { 04106 for (x=0; x<24; x++) 04107 i->minmask[x] = 0x3fffffff; /* 30 bits */ 04108 return; 04109 } 04110 /* Otherwise expect a range */ 04111 e = strchr(times, '-'); 04112 if (!e) { 04113 ast_log(LOG_WARNING, "Time range is not valid. Assuming no restrictions based on time.\n"); 04114 return; 04115 } 04116 *e++ = '\0'; 04117 /* XXX why skip non digits ? */ 04118 while (*e && !isdigit(*e)) 04119 e++; 04120 if (!*e) { 04121 ast_log(LOG_WARNING, "Invalid time range. Assuming no restrictions based on time.\n"); 04122 return; 04123 } 04124 if (sscanf(times, "%d:%d", &s1, &s2) != 2) { 04125 ast_log(LOG_WARNING, "%s isn't a time. Assuming no restrictions based on time.\n", times); 04126 return; 04127 } 04128 if (sscanf(e, "%d:%d", &e1, &e2) != 2) { 04129 ast_log(LOG_WARNING, "%s isn't a time. Assuming no restrictions based on time.\n", e); 04130 return; 04131 } 04132 /* XXX this needs to be optimized */ 04133 #if 1 04134 s1 = s1 * 30 + s2/2; 04135 if ((s1 < 0) || (s1 >= 24*30)) { 04136 ast_log(LOG_WARNING, "%s isn't a valid start time. Assuming no time.\n", times); 04137 return; 04138 } 04139 e1 = e1 * 30 + e2/2; 04140 if ((e1 < 0) || (e1 >= 24*30)) { 04141 ast_log(LOG_WARNING, "%s isn't a valid end time. Assuming no time.\n", e); 04142 return; 04143 } 04144 /* Go through the time and enable each appropriate bit */ 04145 for (x=s1;x != e1;x = (x + 1) % (24 * 30)) { 04146 i->minmask[x/30] |= (1 << (x % 30)); 04147 } 04148 /* Do the last one */ 04149 i->minmask[x/30] |= (1 << (x % 30)); 04150 #else 04151 for (cth=0; cth<24; cth++) { 04152 /* Initialize masks to blank */ 04153 i->minmask[cth] = 0; 04154 for (ctm=0; ctm<30; ctm++) { 04155 if ( 04156 /* First hour with more than one hour */ 04157 (((cth == s1) && (ctm >= s2)) && 04158 ((cth < e1))) 04159 /* Only one hour */ 04160 || (((cth == s1) && (ctm >= s2)) && 04161 ((cth == e1) && (ctm <= e2))) 04162 /* In between first and last hours (more than 2 hours) */ 04163 || ((cth > s1) && 04164 (cth < e1)) 04165 /* Last hour with more than one hour */ 04166 || ((cth > s1) && 04167 ((cth == e1) && (ctm <= e2))) 04168 ) 04169 i->minmask[cth] |= (1 << (ctm / 2)); 04170 } 04171 } 04172 #endif 04173 /* All done */ 04174 return; 04175 }
static int handle_set_global | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3721 of file pbx.c.
References ast_cli(), pbx_builtin_setvar_helper(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03722 { 03723 if (argc != 5) 03724 return RESULT_SHOWUSAGE; 03725 03726 pbx_builtin_setvar_helper(NULL, argv[3], argv[4]); 03727 ast_cli(fd, "\n -- Global variable %s set to %s\n", argv[3], argv[4]); 03728 03729 return RESULT_SUCCESS; 03730 }
static int handle_set_global_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
CLI support for setting global variables.
Definition at line 3709 of file pbx.c.
References ast_cli(), pbx_builtin_setvar_helper(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
03710 { 03711 if (argc != 4) 03712 return RESULT_SHOWUSAGE; 03713 03714 pbx_builtin_setvar_helper(NULL, argv[2], argv[3]); 03715 ast_cli(fd, "\n -- Global variable %s set to %s\n", argv[2], argv[3]); 03716 03717 return RESULT_SUCCESS; 03718 }
static int handle_show_application | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3155 of file pbx.c.
References ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, AST_MAX_APP, COLOR_CYAN, COLOR_MAGENTA, ast_app::description, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, ast_app::synopsis, and term_color().
03156 { 03157 struct ast_app *a; 03158 int app, no_registered_app = 1; 03159 03160 if (argc < 4) 03161 return RESULT_SHOWUSAGE; 03162 03163 /* ... go through all applications ... */ 03164 AST_LIST_LOCK(&apps); 03165 AST_LIST_TRAVERSE(&apps, a, list) { 03166 /* ... compare this application name with all arguments given 03167 * to 'show application' command ... */ 03168 for (app = 3; app < argc; app++) { 03169 if (!strcasecmp(a->name, argv[app])) { 03170 /* Maximum number of characters added by terminal coloring is 22 */ 03171 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40]; 03172 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL; 03173 int synopsis_size, description_size; 03174 03175 no_registered_app = 0; 03176 03177 if (a->synopsis) 03178 synopsis_size = strlen(a->synopsis) + 23; 03179 else 03180 synopsis_size = strlen("Not available") + 23; 03181 synopsis = alloca(synopsis_size); 03182 03183 if (a->description) 03184 description_size = strlen(a->description) + 23; 03185 else 03186 description_size = strlen("Not available") + 23; 03187 description = alloca(description_size); 03188 03189 if (synopsis && description) { 03190 snprintf(info, 64 + AST_MAX_APP, "\n -= Info about application '%s' =- \n\n", a->name); 03191 term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22); 03192 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 03193 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40); 03194 term_color(synopsis, 03195 a->synopsis ? a->synopsis : "Not available", 03196 COLOR_CYAN, 0, synopsis_size); 03197 term_color(description, 03198 a->description ? a->description : "Not available", 03199 COLOR_CYAN, 0, description_size); 03200 03201 ast_cli(fd,"%s%s%s\n\n%s%s\n", infotitle, syntitle, synopsis, destitle, description); 03202 } else { 03203 /* ... one of our applications, show info ...*/ 03204 ast_cli(fd,"\n -= Info about application '%s' =- \n\n" 03205 "[Synopsis]\n %s\n\n" 03206 "[Description]\n%s\n", 03207 a->name, 03208 a->synopsis ? a->synopsis : "Not available", 03209 a->description ? a->description : "Not available"); 03210 } 03211 } 03212 } 03213 } 03214 AST_LIST_UNLOCK(&apps); 03215 03216 /* we found at least one app? no? */ 03217 if (no_registered_app) { 03218 ast_cli(fd, "Your application(s) is (are) not registered\n"); 03219 return RESULT_FAILURE; 03220 } 03221 03222 return RESULT_SUCCESS; 03223 }
static int handle_show_application_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3085 of file pbx.c.
References ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, AST_MAX_APP, COLOR_CYAN, COLOR_MAGENTA, ast_app::description, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, ast_app::synopsis, and term_color().
03086 { 03087 struct ast_app *a; 03088 int app, no_registered_app = 1; 03089 03090 if (argc < 3) 03091 return RESULT_SHOWUSAGE; 03092 03093 /* ... go through all applications ... */ 03094 AST_LIST_LOCK(&apps); 03095 AST_LIST_TRAVERSE(&apps, a, list) { 03096 /* ... compare this application name with all arguments given 03097 * to 'show application' command ... */ 03098 for (app = 2; app < argc; app++) { 03099 if (!strcasecmp(a->name, argv[app])) { 03100 /* Maximum number of characters added by terminal coloring is 22 */ 03101 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40]; 03102 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL; 03103 int synopsis_size, description_size; 03104 03105 no_registered_app = 0; 03106 03107 if (a->synopsis) 03108 synopsis_size = strlen(a->synopsis) + 23; 03109 else 03110 synopsis_size = strlen("Not available") + 23; 03111 synopsis = alloca(synopsis_size); 03112 03113 if (a->description) 03114 description_size = strlen(a->description) + 23; 03115 else 03116 description_size = strlen("Not available") + 23; 03117 description = alloca(description_size); 03118 03119 if (synopsis && description) { 03120 snprintf(info, 64 + AST_MAX_APP, "\n -= Info about application '%s' =- \n\n", a->name); 03121 term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22); 03122 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 03123 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40); 03124 term_color(synopsis, 03125 a->synopsis ? a->synopsis : "Not available", 03126 COLOR_CYAN, 0, synopsis_size); 03127 term_color(description, 03128 a->description ? a->description : "Not available", 03129 COLOR_CYAN, 0, description_size); 03130 03131 ast_cli(fd,"%s%s%s\n\n%s%s\n", infotitle, syntitle, synopsis, destitle, description); 03132 } else { 03133 /* ... one of our applications, show info ...*/ 03134 ast_cli(fd,"\n -= Info about application '%s' =- \n\n" 03135 "[Synopsis]\n %s\n\n" 03136 "[Description]\n%s\n", 03137 a->name, 03138 a->synopsis ? a->synopsis : "Not available", 03139 a->description ? a->description : "Not available"); 03140 } 03141 } 03142 } 03143 } 03144 AST_LIST_UNLOCK(&apps); 03145 03146 /* we found at least one app? no? */ 03147 if (no_registered_app) { 03148 ast_cli(fd, "Your application(s) is (are) not registered\n"); 03149 return RESULT_FAILURE; 03150 } 03151 03152 return RESULT_SUCCESS; 03153 }
static int handle_show_applications | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3350 of file pbx.c.
References ast_cli(), AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_app::description, RESULT_SUCCESS, strcasestr(), and ast_app::synopsis.
03351 { 03352 struct ast_app *a; 03353 int like = 0, describing = 0; 03354 int total_match = 0; /* Number of matches in like clause */ 03355 int total_apps = 0; /* Number of apps registered */ 03356 03357 AST_LIST_LOCK(&apps); 03358 03359 if (AST_LIST_EMPTY(&apps)) { 03360 ast_cli(fd, "There are no registered applications\n"); 03361 AST_LIST_UNLOCK(&apps); 03362 return -1; 03363 } 03364 03365 /* core list applications like <keyword> */ 03366 if ((argc == 5) && (!strcmp(argv[3], "like"))) { 03367 like = 1; 03368 } else if ((argc > 4) && (!strcmp(argv[3], "describing"))) { 03369 describing = 1; 03370 } 03371 03372 /* core list applications describing <keyword1> [<keyword2>] [...] */ 03373 if ((!like) && (!describing)) { 03374 ast_cli(fd, " -= Registered Asterisk Applications =-\n"); 03375 } else { 03376 ast_cli(fd, " -= Matching Asterisk Applications =-\n"); 03377 } 03378 03379 AST_LIST_TRAVERSE(&apps, a, list) { 03380 int printapp = 0; 03381 total_apps++; 03382 if (like) { 03383 if (strcasestr(a->name, argv[4])) { 03384 printapp = 1; 03385 total_match++; 03386 } 03387 } else if (describing) { 03388 if (a->description) { 03389 /* Match all words on command line */ 03390 int i; 03391 printapp = 1; 03392 for (i = 4; i < argc; i++) { 03393 if (!strcasestr(a->description, argv[i])) { 03394 printapp = 0; 03395 } else { 03396 total_match++; 03397 } 03398 } 03399 } 03400 } else { 03401 printapp = 1; 03402 } 03403 03404 if (printapp) { 03405 ast_cli(fd," %20s: %s\n", a->name, a->synopsis ? a->synopsis : "<Synopsis not available>"); 03406 } 03407 } 03408 if ((!like) && (!describing)) { 03409 ast_cli(fd, " -= %d Applications Registered =-\n",total_apps); 03410 } else { 03411 ast_cli(fd, " -= %d Applications Matching =-\n",total_match); 03412 } 03413 03414 AST_LIST_UNLOCK(&apps); 03415 03416 return RESULT_SUCCESS; 03417 }
static int handle_show_applications_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3282 of file pbx.c.
References ast_cli(), AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_app::description, RESULT_SUCCESS, strcasestr(), and ast_app::synopsis.
03283 { 03284 struct ast_app *a; 03285 int like = 0, describing = 0; 03286 int total_match = 0; /* Number of matches in like clause */ 03287 int total_apps = 0; /* Number of apps registered */ 03288 03289 AST_LIST_LOCK(&apps); 03290 03291 if (AST_LIST_EMPTY(&apps)) { 03292 ast_cli(fd, "There are no registered applications\n"); 03293 AST_LIST_UNLOCK(&apps); 03294 return -1; 03295 } 03296 03297 /* show applications like <keyword> */ 03298 if ((argc == 4) && (!strcmp(argv[2], "like"))) { 03299 like = 1; 03300 } else if ((argc > 3) && (!strcmp(argv[2], "describing"))) { 03301 describing = 1; 03302 } 03303 03304 /* show applications describing <keyword1> [<keyword2>] [...] */ 03305 if ((!like) && (!describing)) { 03306 ast_cli(fd, " -= Registered Asterisk Applications =-\n"); 03307 } else { 03308 ast_cli(fd, " -= Matching Asterisk Applications =-\n"); 03309 } 03310 03311 AST_LIST_TRAVERSE(&apps, a, list) { 03312 int printapp = 0; 03313 total_apps++; 03314 if (like) { 03315 if (strcasestr(a->name, argv[3])) { 03316 printapp = 1; 03317 total_match++; 03318 } 03319 } else if (describing) { 03320 if (a->description) { 03321 /* Match all words on command line */ 03322 int i; 03323 printapp = 1; 03324 for (i = 3; i < argc; i++) { 03325 if (!strcasestr(a->description, argv[i])) { 03326 printapp = 0; 03327 } else { 03328 total_match++; 03329 } 03330 } 03331 } 03332 } else { 03333 printapp = 1; 03334 } 03335 03336 if (printapp) { 03337 ast_cli(fd," %20s: %s\n", a->name, a->synopsis ? a->synopsis : "<Synopsis not available>"); 03338 } 03339 } 03340 if ((!like) && (!describing)) { 03341 ast_cli(fd, " -= %d Applications Registered =-\n",total_apps); 03342 } else { 03343 ast_cli(fd, " -= %d Applications Matching =-\n",total_match); 03344 } 03345 03346 AST_LIST_UNLOCK(&apps); 03347 03348 return RESULT_SUCCESS; 03349 }
static int handle_show_dialplan | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 3636 of file pbx.c.
References ast_cli(), AST_PBX_MAX_STACK, ast_strdupa, ast_strlen_zero(), context, dialplan_counters::context_existence, exten, dialplan_counters::extension_existence, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, show_dialplan_helper(), strsep(), dialplan_counters::total_context, dialplan_counters::total_exten, and dialplan_counters::total_prio.
03637 { 03638 char *exten = NULL, *context = NULL; 03639 /* Variables used for different counters */ 03640 struct dialplan_counters counters; 03641 03642 const char *incstack[AST_PBX_MAX_STACK]; 03643 memset(&counters, 0, sizeof(counters)); 03644 03645 if (argc != 2 && argc != 3) 03646 return RESULT_SHOWUSAGE; 03647 03648 /* we obtain [exten@]context? if yes, split them ... */ 03649 if (argc == 3) { 03650 if (strchr(argv[2], '@')) { /* split into exten & context */ 03651 context = ast_strdupa(argv[2]); 03652 exten = strsep(&context, "@"); 03653 /* change empty strings to NULL */ 03654 if (ast_strlen_zero(exten)) 03655 exten = NULL; 03656 } else { /* no '@' char, only context given */ 03657 context = argv[2]; 03658 } 03659 if (ast_strlen_zero(context)) 03660 context = NULL; 03661 } 03662 /* else Show complete dial plan, context and exten are NULL */ 03663 show_dialplan_helper(fd, context, exten, &counters, NULL, 0, incstack); 03664 03665 /* check for input failure and throw some error messages */ 03666 if (context && !counters.context_existence) { 03667 ast_cli(fd, "There is no existence of '%s' context\n", context); 03668 return RESULT_FAILURE; 03669 } 03670 03671 if (exten && !counters.extension_existence) { 03672 if (context) 03673 ast_cli(fd, "There is no existence of %s@%s extension\n", 03674 exten, context); 03675 else 03676 ast_cli(fd, 03677 "There is no existence of '%s' extension in all contexts\n", 03678 exten); 03679 return RESULT_FAILURE; 03680 } 03681 03682 ast_cli(fd,"-= %d %s (%d %s) in %d %s. =-\n", 03683 counters.total_exten, counters.total_exten == 1 ? "extension" : "extensions", 03684 counters.total_prio, counters.total_prio == 1 ? "priority" : "priorities", 03685 counters.total_context, counters.total_context == 1 ? "context" : "contexts"); 03686 03687 /* everything ok */ 03688 return RESULT_SUCCESS; 03689 }
static int handle_show_function | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1351 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().
01352 { 01353 struct ast_custom_function *acf; 01354 /* Maximum number of characters added by terminal coloring is 22 */ 01355 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40]; 01356 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL; 01357 char stxtitle[40], *syntax = NULL; 01358 int synopsis_size, description_size, syntax_size; 01359 01360 if (argc < 4) 01361 return RESULT_SHOWUSAGE; 01362 01363 if (!(acf = ast_custom_function_find(argv[3]))) { 01364 ast_cli(fd, "No function by that name registered.\n"); 01365 return RESULT_FAILURE; 01366 01367 } 01368 01369 if (acf->synopsis) 01370 synopsis_size = strlen(acf->synopsis) + 23; 01371 else 01372 synopsis_size = strlen("Not available") + 23; 01373 synopsis = alloca(synopsis_size); 01374 01375 if (acf->desc) 01376 description_size = strlen(acf->desc) + 23; 01377 else 01378 description_size = strlen("Not available") + 23; 01379 description = alloca(description_size); 01380 01381 if (acf->syntax) 01382 syntax_size = strlen(acf->syntax) + 23; 01383 else 01384 syntax_size = strlen("Not available") + 23; 01385 syntax = alloca(syntax_size); 01386 01387 snprintf(info, 64 + AST_MAX_APP, "\n -= Info about function '%s' =- \n\n", acf->name); 01388 term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22); 01389 term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40); 01390 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 01391 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40); 01392 term_color(syntax, 01393 acf->syntax ? acf->syntax : "Not available", 01394 COLOR_CYAN, 0, syntax_size); 01395 term_color(synopsis, 01396 acf->synopsis ? acf->synopsis : "Not available", 01397 COLOR_CYAN, 0, synopsis_size); 01398 term_color(description, 01399 acf->desc ? acf->desc : "Not available", 01400 COLOR_CYAN, 0, description_size); 01401 01402 ast_cli(fd,"%s%s%s\n\n%s%s\n\n%s%s\n", infotitle, stxtitle, syntax, syntitle, synopsis, destitle, description); 01403 01404 return RESULT_SUCCESS; 01405 }
static int handle_show_function_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1295 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().
01296 { 01297 struct ast_custom_function *acf; 01298 /* Maximum number of characters added by terminal coloring is 22 */ 01299 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40]; 01300 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL; 01301 char stxtitle[40], *syntax = NULL; 01302 int synopsis_size, description_size, syntax_size; 01303 01304 if (argc < 3) 01305 return RESULT_SHOWUSAGE; 01306 01307 if (!(acf = ast_custom_function_find(argv[2]))) { 01308 ast_cli(fd, "No function by that name registered.\n"); 01309 return RESULT_FAILURE; 01310 01311 } 01312 01313 if (acf->synopsis) 01314 synopsis_size = strlen(acf->synopsis) + 23; 01315 else 01316 synopsis_size = strlen("Not available") + 23; 01317 synopsis = alloca(synopsis_size); 01318 01319 if (acf->desc) 01320 description_size = strlen(acf->desc) + 23; 01321 else 01322 description_size = strlen("Not available") + 23; 01323 description = alloca(description_size); 01324 01325 if (acf->syntax) 01326 syntax_size = strlen(acf->syntax) + 23; 01327 else 01328 syntax_size = strlen("Not available") + 23; 01329 syntax = alloca(syntax_size); 01330 01331 snprintf(info, 64 + AST_MAX_APP, "\n -= Info about function '%s' =- \n\n", acf->name); 01332 term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22); 01333 term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40); 01334 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 01335 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40); 01336 term_color(syntax, 01337 acf->syntax ? acf->syntax : "Not available", 01338 COLOR_CYAN, 0, syntax_size); 01339 term_color(synopsis, 01340 acf->synopsis ? acf->synopsis : "Not available", 01341 COLOR_CYAN, 0, synopsis_size); 01342 term_color(description, 01343 acf->desc ? acf->desc : "Not available", 01344 COLOR_CYAN, 0, description_size); 01345 01346 ast_cli(fd,"%s%s%s\n\n%s%s\n\n%s%s\n", infotitle, stxtitle, syntax, syntitle, synopsis, destitle, description); 01347 01348 return RESULT_SUCCESS; 01349 }
static int handle_show_functions | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1267 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.
01268 { 01269 struct ast_custom_function *acf; 01270 int count_acf = 0; 01271 int like = 0; 01272 01273 if (argc == 5 && (!strcmp(argv[3], "like")) ) { 01274 like = 1; 01275 } else if (argc != 3) { 01276 return RESULT_SHOWUSAGE; 01277 } 01278 01279 ast_cli(fd, "%s Custom Functions:\n--------------------------------------------------------------------------------\n", like ? "Matching" : "Installed"); 01280 01281 AST_LIST_LOCK(&acf_root); 01282 AST_LIST_TRAVERSE(&acf_root, acf, acflist) { 01283 if (!like || strstr(acf->name, argv[4])) { 01284 count_acf++; 01285 ast_cli(fd, "%-20.20s %-35.35s %s\n", acf->name, acf->syntax, acf->synopsis); 01286 } 01287 } 01288 AST_LIST_UNLOCK(&acf_root); 01289 01290 ast_cli(fd, "%d %scustom functions installed.\n", count_acf, like ? "matching " : ""); 01291 01292 return RESULT_SUCCESS; 01293 }
static int handle_show_functions_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1240 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.
01241 { 01242 struct ast_custom_function *acf; 01243 int count_acf = 0; 01244 int like = 0; 01245 01246 if (argc == 4 && (!strcmp(argv[2], "like")) ) { 01247 like = 1; 01248 } else if (argc != 2) { 01249 return RESULT_SHOWUSAGE; 01250 } 01251 01252 ast_cli(fd, "%s Custom Functions:\n--------------------------------------------------------------------------------\n", like ? "Matching" : "Installed"); 01253 01254 AST_LIST_LOCK(&acf_root); 01255 AST_LIST_TRAVERSE(&acf_root, acf, acflist) { 01256 if (!like || strstr(acf->name, argv[3])) { 01257 count_acf++; 01258 ast_cli(fd, "%-20.20s %-35.35s %s\n", acf->name, acf->syntax, acf->synopsis); 01259 } 01260 } 01261 AST_LIST_UNLOCK(&acf_root); 01262 01263 ast_cli(fd, "%d %scustom functions installed.\n", count_acf, like ? "matching " : ""); 01264 01265 return RESULT_SUCCESS; 01266 }
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 3692 of file pbx.c.
References ast_cli(), AST_LIST_TRAVERSE, ast_mutex_lock(), ast_mutex_unlock(), ast_var_name(), ast_var_value(), globals, and RESULT_SUCCESS.
03693 { 03694 int i = 0; 03695 struct ast_var_t *newvariable; 03696 03697 ast_mutex_lock(&globalslock); 03698 AST_LIST_TRAVERSE (&globals, newvariable, entries) { 03699 i++; 03700 ast_cli(fd, " %s=%s\n", ast_var_name(newvariable), ast_var_value(newvariable)); 03701 } 03702 ast_mutex_unlock(&globalslock); 03703 ast_cli(fd, "\n -- %d variables\n", i); 03704 03705 return RESULT_SUCCESS; 03706 }
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 3226 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.
03227 { 03228 struct ast_hint *hint; 03229 int num = 0; 03230 int watchers; 03231 struct ast_state_cb *watcher; 03232 03233 if (AST_LIST_EMPTY(&hints)) { 03234 ast_cli(fd, "There are no registered dialplan hints\n"); 03235 return RESULT_SUCCESS; 03236 } 03237 /* ... we have hints ... */ 03238 ast_cli(fd, "\n -= Registered Asterisk Dial Plan Hints =-\n"); 03239 AST_LIST_LOCK(&hints); 03240 AST_LIST_TRAVERSE(&hints, hint, list) { 03241 watchers = 0; 03242 for (watcher = hint->callbacks; watcher; watcher = watcher->next) 03243 watchers++; 03244 ast_cli(fd, " %20s@%-20.20s: %-20.20s State:%-15.15s Watchers %2d\n", 03245 ast_get_extension_name(hint->exten), 03246 ast_get_context_name(ast_get_extension_context(hint->exten)), 03247 ast_get_extension_app(hint->exten), 03248 ast_extension_state2str(hint->laststate), watchers); 03249 num++; 03250 } 03251 ast_cli(fd, "----------------\n"); 03252 ast_cli(fd, "- %d hints registered\n", num); 03253 AST_LIST_UNLOCK(&hints); 03254 return RESULT_SUCCESS; 03255 }
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 3258 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.
03259 { 03260 struct ast_switch *sw; 03261 03262 AST_LIST_LOCK(&switches); 03263 03264 if (AST_LIST_EMPTY(&switches)) { 03265 AST_LIST_UNLOCK(&switches); 03266 ast_cli(fd, "There are no registered alternative switches\n"); 03267 return RESULT_SUCCESS; 03268 } 03269 03270 ast_cli(fd, "\n -= Registered Asterisk Alternative Switches =-\n"); 03271 AST_LIST_TRAVERSE(&switches, sw, list) 03272 ast_cli(fd, "%s: %s\n", sw->name, sw->description); 03273 03274 AST_LIST_UNLOCK(&switches); 03275 03276 return RESULT_SUCCESS; 03277 }
static int include_valid | ( | struct ast_include * | i | ) | [inline, static] |
Definition at line 576 of file pbx.c.
References ast_check_timing(), ast_include::hastime, and ast_include::timing.
Referenced by pbx_find_extension().
00577 { 00578 if (!i->hastime) 00579 return 1; 00580 00581 return ast_check_timing(&(i->timing)); 00582 }
static int increase_call_count | ( | const struct ast_channel * | c | ) | [static] |
Definition at line 2548 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().
02549 { 02550 int failed = 0; 02551 double curloadavg; 02552 ast_mutex_lock(&maxcalllock); 02553 if (option_maxcalls) { 02554 if (countcalls >= option_maxcalls) { 02555 ast_log(LOG_NOTICE, "Maximum call limit of %d calls exceeded by '%s'!\n", option_maxcalls, c->name); 02556 failed = -1; 02557 } 02558 } 02559 if (option_maxload) { 02560 getloadavg(&curloadavg, 1); 02561 if (curloadavg >= option_maxload) { 02562 ast_log(LOG_NOTICE, "Maximum loadavg limit of %f load exceeded by '%s' (currently %f)!\n", option_maxload, c->name, curloadavg); 02563 failed = -1; 02564 } 02565 } 02566 if (!failed) 02567 countcalls++; 02568 ast_mutex_unlock(&maxcalllock); 02569 02570 return failed; 02571 }
int load_pbx | ( | void | ) |
Provided by pbx.c
Definition at line 6035 of file pbx.c.
Referenced by main().
06036 { 06037 int x; 06038 06039 /* Initialize the PBX */ 06040 if (option_verbose) { 06041 ast_verbose( "Asterisk PBX Core Initializing\n"); 06042 ast_verbose( "Registering builtin applications:\n"); 06043 } 06044 ast_cli_register_multiple(pbx_cli, sizeof(pbx_cli) / sizeof(struct ast_cli_entry)); 06045 06046 /* Register builtin applications */ 06047 for (x=0; x<sizeof(builtins) / sizeof(struct pbx_builtin); x++) { 06048 if (option_verbose) 06049 ast_verbose( VERBOSE_PREFIX_1 "[%s]\n", builtins[x].name); 06050 if (ast_register_application(builtins[x].name, builtins[x].execute, builtins[x].synopsis, builtins[x].description)) { 06051 ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name); 06052 return -1; 06053 } 06054 } 06055 return 0; 06056 }
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 4028 of file pbx.c.
Referenced by get_range().
04029 { 04030 int i; 04031 04032 if (names) { 04033 for (i = 0; names[i]; i++) { 04034 if (!strcasecmp(s, names[i])) 04035 return i+1; 04036 } 04037 } else if (sscanf(s, "%d", &i) == 1 && i >= 1 && i <= max) { 04038 return i; 04039 } 04040 return 0; /* error return */ 04041 }
static int matchcid | ( | const char * | cidpattern, | |
const char * | callerid | |||
) | [static] |
Definition at line 908 of file pbx.c.
References ast_extension_match(), and ast_strlen_zero().
Referenced by pbx_find_extension().
00909 { 00910 /* If the Caller*ID pattern is empty, then we're matching NO Caller*ID, so 00911 failing to get a number should count as a match, otherwise not */ 00912 00913 if (ast_strlen_zero(callerid)) 00914 return ast_strlen_zero(cidpattern) ? 1 : 0; 00915 00916 return ast_extension_match(cidpattern, callerid); 00917 }
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 1060 of file pbx.c.
Referenced by pbx_retrieve_variable(), and pbx_substitute_variables_helper_full().
01061 { 01062 int parens=0; 01063 01064 *offset = 0; 01065 *length = INT_MAX; 01066 *isfunc = 0; 01067 for (; *var; var++) { 01068 if (*var == '(') { 01069 (*isfunc)++; 01070 parens++; 01071 } else if (*var == ')') { 01072 parens--; 01073 } else if (*var == ':' && parens == 0) { 01074 *var++ = '\0'; 01075 sscanf(var, "%d:%d", offset, length); 01076 return 1; /* offset:length valid */ 01077 } 01078 } 01079 return 0; 01080 }
void pbx_builtin_clear_globals | ( | void | ) |
Definition at line 5937 of file pbx.c.
Referenced by handle_reload_extensions(), and reload().
05938 { 05939 struct ast_var_t *vardata; 05940 05941 ast_mutex_lock(&globalslock); 05942 while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries))) 05943 ast_var_delete(vardata); 05944 ast_mutex_unlock(&globalslock); 05945 }
const char* pbx_builtin_getvar_helper | ( | struct ast_channel * | chan, | |
const char * | name | |||
) |
Definition at line 5737 of file pbx.c.
Referenced by __ast_pbx_run(), __login_exec(), _macro_exec(), _while_exec(), agent_hangup(), agent_read(), agentmonitoroutgoing_exec(), ast_bridge_call(), ast_channel_bridge(), ast_feature_interpret(), ast_monitor_stop(), ast_park_call(), builtin_automonitor(), check_goto_on_transfer(), common_exec(), conf_exec(), conf_run(), dundi_exec(), dundi_helper(), get_also_info(), get_index(), get_refer_info(), global_read(), iax2_exec(), import_ch(), leave_voicemail(), local_hangup(), misdn_answer(), misdn_hangup(), morsecode_exec(), notify_new_message(), oh323_call(), oh323_hangup(), pickup_by_mark(), queue_exec(), real_ctx(), retrydial_exec(), return_exec(), 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().
05738 { 05739 struct ast_var_t *variables; 05740 const char *ret = NULL; 05741 int i; 05742 struct varshead *places[2] = { NULL, &globals }; 05743 05744 if (!name) 05745 return NULL; 05746 if (chan) 05747 places[0] = &chan->varshead; 05748 05749 for (i = 0; i < 2; i++) { 05750 if (!places[i]) 05751 continue; 05752 if (places[i] == &globals) 05753 ast_mutex_lock(&globalslock); 05754 AST_LIST_TRAVERSE(places[i], variables, entries) { 05755 if (!strcmp(name, ast_var_name(variables))) { 05756 ret = ast_var_value(variables); 05757 break; 05758 } 05759 } 05760 if (places[i] == &globals) 05761 ast_mutex_unlock(&globalslock); 05762 if (ret) 05763 break; 05764 } 05765 05766 return ret; 05767 }
static int pbx_builtin_gotoif | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 5957 of file pbx.c.
References ast_log(), ast_strdupa, ast_strlen_zero(), LOG_DEBUG, LOG_WARNING, option_debug, pbx_builtin_goto(), pbx_checkcondition(), and strsep().
05958 { 05959 char *condition, *branch1, *branch2, *branch; 05960 int rc; 05961 char *stringp; 05962 05963 if (ast_strlen_zero(data)) { 05964 ast_log(LOG_WARNING, "Ignoring, since there is no variable to check\n"); 05965 return 0; 05966 } 05967 05968 stringp = ast_strdupa(data); 05969 condition = strsep(&stringp,"?"); 05970 branch1 = strsep(&stringp,":"); 05971 branch2 = strsep(&stringp,""); 05972 branch = pbx_checkcondition(condition) ? branch1 : branch2; 05973 05974 if (ast_strlen_zero(branch)) { 05975 if (option_debug) 05976 ast_log(LOG_DEBUG, "Not taking any branch\n"); 05977 return 0; 05978 } 05979 05980 rc = pbx_builtin_goto(chan, branch); 05981 05982 return rc; 05983 }
int pbx_builtin_importvar | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 5876 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.
05877 { 05878 char *name; 05879 char *value; 05880 char *channel; 05881 char tmp[VAR_BUF_SIZE]=""; 05882 05883 if (ast_strlen_zero(data)) { 05884 ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n"); 05885 return 0; 05886 } 05887 05888 value = ast_strdupa(data); 05889 name = strsep(&value,"="); 05890 channel = strsep(&value,"|"); 05891 if (channel && value && name) { /*! \todo XXX should do !ast_strlen_zero(..) of the args ? */ 05892 struct ast_channel *chan2 = ast_get_channel_by_name_locked(channel); 05893 if (chan2) { 05894 char *s = alloca(strlen(value) + 4); 05895 if (s) { 05896 sprintf(s, "${%s}", value); 05897 pbx_substitute_variables_helper(chan2, s, tmp, sizeof(tmp) - 1); 05898 } 05899 ast_channel_unlock(chan2); 05900 } 05901 pbx_builtin_setvar_helper(chan, name, tmp); 05902 } 05903 05904 return(0); 05905 }
static int pbx_builtin_noop | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
void pbx_builtin_pushvar_helper | ( | struct ast_channel * | chan, | |
const char * | name, | |||
const char * | value | |||
) |
Definition at line 5769 of file pbx.c.
Referenced by acf_odbc_read(), acf_odbc_write(), and gosub_exec().
05770 { 05771 struct ast_var_t *newvariable; 05772 struct varshead *headp; 05773 05774 if (name[strlen(name)-1] == ')') { 05775 char *function = ast_strdupa(name); 05776 05777 ast_log(LOG_WARNING, "Cannot push a value onto a function\n"); 05778 ast_func_write(chan, function, value); 05779 return; 05780 } 05781 05782 headp = (chan) ? &chan->varshead : &globals; 05783 05784 if (value) { 05785 if ((option_verbose > 1) && (headp == &globals)) 05786 ast_verbose(VERBOSE_PREFIX_2 "Setting global variable '%s' to '%s'\n", name, value); 05787 newvariable = ast_var_assign(name, value); 05788 if (headp == &globals) 05789 ast_mutex_lock(&globalslock); 05790 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 05791 if (headp == &globals) 05792 ast_mutex_unlock(&globalslock); 05793 } 05794 }
static int pbx_builtin_saycharacters | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 6017 of file pbx.c.
References ast_say_character_str().
06018 { 06019 int res = 0; 06020 06021 if (data) 06022 res = ast_say_character_str(chan, data, "", chan->language); 06023 return res; 06024 }
static int pbx_builtin_saydigits | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 6008 of file pbx.c.
References ast_say_digit_str().
06009 { 06010 int res = 0; 06011 06012 if (data) 06013 res = ast_say_digit_str(chan, data, "", chan->language); 06014 return res; 06015 }
static int pbx_builtin_saynumber | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 5985 of file pbx.c.
References ast_log(), ast_say_number(), ast_strlen_zero(), LOG_WARNING, and strsep().
05986 { 05987 char tmp[256]; 05988 char *number = tmp; 05989 char *options; 05990 05991 if (ast_strlen_zero(data)) { 05992 ast_log(LOG_WARNING, "SayNumber requires an argument (number)\n"); 05993 return -1; 05994 } 05995 ast_copy_string(tmp, data, sizeof(tmp)); 05996 strsep(&number, "|"); 05997 options = strsep(&number, "|"); 05998 if (options) { 05999 if ( strcasecmp(options, "f") && strcasecmp(options,"m") && 06000 strcasecmp(options, "c") && strcasecmp(options, "n") ) { 06001 ast_log(LOG_WARNING, "SayNumber gender option is either 'f', 'm', 'c' or 'n'\n"); 06002 return -1; 06003 } 06004 } 06005 return ast_say_number(chan, atoi(tmp), "", chan->language, options); 06006 }
static int pbx_builtin_sayphonetic | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 6026 of file pbx.c.
References ast_say_phonetic_str().
06027 { 06028 int res = 0; 06029 06030 if (data) 06031 res = ast_say_phonetic_str(chan, data, "", chan->language); 06032 return res; 06033 }
int pbx_builtin_serialize_variables | ( | struct ast_channel * | chan, | |
char * | buf, | |||
size_t | size | |||
) |
Definition at line 5710 of file pbx.c.
Referenced by dumpchan_exec(), handle_showchan(), handle_showchan_deprecated(), and vars2manager().
05711 { 05712 struct ast_var_t *variables; 05713 const char *var, *val; 05714 int total = 0; 05715 05716 if (!chan) 05717 return 0; 05718 05719 memset(buf, 0, size); 05720 05721 AST_LIST_TRAVERSE(&chan->varshead, variables, entries) { 05722 if ((var=ast_var_name(variables)) && (val=ast_var_value(variables)) 05723 /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */ 05724 ) { 05725 if (ast_build_string(&buf, &size, "%s=%s\n", var, val)) { 05726 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n"); 05727 break; 05728 } else 05729 total++; 05730 } else 05731 break; 05732 } 05733 05734 return total; 05735 }
static int pbx_builtin_setglobalvar | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 5908 of file pbx.c.
References ast_log(), ast_strlen_zero(), LOG_WARNING, pbx_builtin_setvar_helper(), and strsep().
05909 { 05910 char *name; 05911 char *stringp = data; 05912 static int dep_warning = 0; 05913 05914 if (ast_strlen_zero(data)) { 05915 ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n"); 05916 return 0; 05917 } 05918 05919 name = strsep(&stringp, "="); 05920 05921 if (!dep_warning) { 05922 dep_warning = 1; 05923 ast_log(LOG_WARNING, "SetGlobalVar is deprecated. Please use Set(GLOBAL(%s)=%s) instead.\n", name, stringp); 05924 } 05925 05926 /*! \todo XXX watch out, leading whitespace ? */ 05927 pbx_builtin_setvar_helper(NULL, name, stringp); 05928 05929 return(0); 05930 }
int pbx_builtin_setvar | ( | struct ast_channel * | chan, | |
void * | data | |||
) |
Definition at line 5841 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().
05842 { 05843 char *name, *value, *mydata; 05844 int argc; 05845 char *argv[24]; /* this will only support a maximum of 24 variables being set in a single operation */ 05846 int global = 0; 05847 int x; 05848 05849 if (ast_strlen_zero(data)) { 05850 ast_log(LOG_WARNING, "Set requires at least one variable name/value pair.\n"); 05851 return 0; 05852 } 05853 05854 mydata = ast_strdupa(data); 05855 argc = ast_app_separate_args(mydata, '|', argv, sizeof(argv) / sizeof(argv[0])); 05856 05857 /* check for a trailing flags argument */ 05858 if ((argc > 1) && !strchr(argv[argc-1], '=')) { 05859 argc--; 05860 if (strchr(argv[argc], 'g')) 05861 global = 1; 05862 } 05863 05864 for (x = 0; x < argc; x++) { 05865 name = argv[x]; 05866 if ((value = strchr(name, '='))) { 05867 *value++ = '\0'; 05868 pbx_builtin_setvar_helper((global) ? NULL : chan, name, value); 05869 } else 05870 ast_log(LOG_WARNING, "Ignoring entry '%s' with no = (and not last 'options' entry)\n", name); 05871 } 05872 05873 return(0); 05874 }
void pbx_builtin_setvar_helper | ( | struct ast_channel * | chan, | |
const char * | name, | |||
const char * | value | |||
) |
Definition at line 5796 of file pbx.c.
Referenced by __ast_pbx_run(), __login_exec(), __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_set_variables(), background_detect_exec(), builtin_automonitor(), builtin_blindtransfer(), cb_events(), chanavail_exec(), conf_run(), 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_setglobalvar(), pbx_builtin_setvar(), pbx_extension_helper(), 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().
05797 { 05798 struct ast_var_t *newvariable; 05799 struct varshead *headp; 05800 const char *nametail = name; 05801 05802 /* XXX may need locking on the channel ? */ 05803 if (name[strlen(name)-1] == ')') { 05804 char *function = ast_strdupa(name); 05805 05806 ast_func_write(chan, function, value); 05807 return; 05808 } 05809 05810 headp = (chan) ? &chan->varshead : &globals; 05811 05812 /* For comparison purposes, we have to strip leading underscores */ 05813 if (*nametail == '_') { 05814 nametail++; 05815 if (*nametail == '_') 05816 nametail++; 05817 } 05818 05819 if (headp == &globals) 05820 ast_mutex_lock(&globalslock); 05821 AST_LIST_TRAVERSE (headp, newvariable, entries) { 05822 if (strcasecmp(ast_var_name(newvariable), nametail) == 0) { 05823 /* there is already such a variable, delete it */ 05824 AST_LIST_REMOVE(headp, newvariable, entries); 05825 ast_var_delete(newvariable); 05826 break; 05827 } 05828 } 05829 05830 if (value) { 05831 if ((option_verbose > 1) && (headp == &globals)) 05832 ast_verbose(VERBOSE_PREFIX_2 "Setting global variable '%s' to '%s'\n", name, value); 05833 newvariable = ast_var_assign(name, value); 05834 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 05835 } 05836 05837 if (headp == &globals) 05838 ast_mutex_unlock(&globalslock); 05839 }
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 5947 of file pbx.c.
Referenced by _macro_exec(), _while_exec(), acf_if(), execif_exec(), gosubif_exec(), macroif_exec(), and pbx_builtin_gotoif().
05948 { 05949 if (ast_strlen_zero(condition)) /* NULL or empty strings are false */ 05950 return 0; 05951 else if (*condition >= '0' && *condition <= '9') /* Numbers are evaluated for truth */ 05952 return atoi(condition); 05953 else /* Strings are true */ 05954 return 1; 05955 }
static void pbx_destroy | ( | struct ast_pbx * | p | ) | [static] |
Definition at line 584 of file pbx.c.
References free.
Referenced by __ast_pbx_run().
00585 { 00586 free(p); 00587 }
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 510 of file pbx.c.
Referenced by answer_exec_run(), ast_bridge_call(), ast_pbx_run_app(), async_wait(), builtin_automonitor(), conf_run(), dundi_exec(), exec_exec(), execif_exec(), feature_exec_app(), forward_message(), handle_exec(), iax2_exec(), page_exec(), pbx_builtin_execiftime(), pbx_extension_helper(), realtime_exec(), try_calling(), and tryexec_exec().
00513 { 00514 int res; 00515 00516 const char *saved_c_appl; 00517 const char *saved_c_data; 00518 00519 if (c->cdr && !ast_check_hangup(c)) 00520 ast_cdr_setapp(c->cdr, app->name, data); 00521 00522 /* save channel values */ 00523 saved_c_appl= c->appl; 00524 saved_c_data= c->data; 00525 00526 c->appl = app->name; 00527 c->data = data; 00528 /* XXX remember what to to when we have linked apps to modules */ 00529 if (app->module) { 00530 /* XXX LOCAL_USER_ADD(app->module) */ 00531 } 00532 res = app->execute(c, data); 00533 if (app->module) { 00534 /* XXX LOCAL_USER_REMOVE(app->module) */ 00535 } 00536 /* restore channel values */ 00537 c->appl = saved_c_appl; 00538 c->data = saved_c_data; 00539 return res; 00540 }
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 1771 of file pbx.c.
References ast_exten::app, app, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), COLOR_BRCYAN, COLOR_BRMAGENTA, ast_channel::context, pbx_find_info::data, E_CANMATCH, E_FINDLABEL, E_MATCH, E_MATCHMORE, EVENT_FLAG_CALL, ast_switch::exec, EXT_DATA_SIZE, ast_channel::exten, pbx_find_info::foundcontext, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, manager_event(), ast_switch::name, option_debug, option_verbose, pbx_builtin_setvar_helper(), pbx_exec(), pbx_find_extension(), pbx_findapp(), pbx_substitute_variables(), ast_channel::priority, ast_exten::priority, pbx_find_info::stacklen, pbx_find_info::status, STATUS_NO_CONTEXT, STATUS_NO_EXTENSION, STATUS_NO_LABEL, STATUS_NO_PRIORITY, pbx_find_info::swo, term_color(), and VERBOSE_PREFIX_3.
Referenced by ast_canmatch_extension(), ast_exists_extension(), ast_findlabel_extension(), ast_findlabel_extension2(), ast_matchmore_extension(), and ast_spawn_extension().
01774 { 01775 struct ast_exten *e; 01776 struct ast_app *app; 01777 int res; 01778 struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */ 01779 char passdata[EXT_DATA_SIZE]; 01780 01781 int matching_action = (action == E_MATCH || action == E_CANMATCH || action == E_MATCHMORE); 01782 01783 ast_mutex_lock(&conlock); 01784 e = pbx_find_extension(c, con, &q, context, exten, priority, label, callerid, action); 01785 if (e) { 01786 if (matching_action) { 01787 ast_mutex_unlock(&conlock); 01788 return -1; /* success, we found it */ 01789 } else if (action == E_FINDLABEL) { /* map the label to a priority */ 01790 res = e->priority; 01791 ast_mutex_unlock(&conlock); 01792 return res; /* the priority we were looking for */ 01793 } else { /* spawn */ 01794 app = pbx_findapp(e->app); 01795 ast_mutex_unlock(&conlock); 01796 if (!app) { 01797 ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority); 01798 return -1; 01799 } 01800 if (c->context != context) 01801 ast_copy_string(c->context, context, sizeof(c->context)); 01802 if (c->exten != exten) 01803 ast_copy_string(c->exten, exten, sizeof(c->exten)); 01804 c->priority = priority; 01805 pbx_substitute_variables(passdata, sizeof(passdata), c, e); 01806 if (option_debug) { 01807 char atmp[80]; 01808 char atmp2[EXT_DATA_SIZE+100]; 01809 ast_log(LOG_DEBUG, "Launching '%s'\n", app->name); 01810 snprintf(atmp, sizeof(atmp), "STACK-%s-%s-%d", context, exten, priority); 01811 snprintf(atmp2, sizeof(atmp2), "%s(\"%s\", \"%s\") %s", 01812 app->name, c->name, passdata, "in new stack"); 01813 pbx_builtin_setvar_helper(c, atmp, atmp2); 01814 } 01815 if (option_verbose > 2) { 01816 char tmp[80], tmp2[80], tmp3[EXT_DATA_SIZE]; 01817 ast_verbose( VERBOSE_PREFIX_3 "Executing [%s@%s:%d] %s(\"%s\", \"%s\") %s\n", 01818 exten, context, priority, 01819 term_color(tmp, app->name, COLOR_BRCYAN, 0, sizeof(tmp)), 01820 term_color(tmp2, c->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)), 01821 term_color(tmp3, passdata, COLOR_BRMAGENTA, 0, sizeof(tmp3)), 01822 "in new stack"); 01823 } 01824 manager_event(EVENT_FLAG_CALL, "Newexten", 01825 "Channel: %s\r\n" 01826 "Context: %s\r\n" 01827 "Extension: %s\r\n" 01828 "Priority: %d\r\n" 01829 "Application: %s\r\n" 01830 "AppData: %s\r\n" 01831 "Uniqueid: %s\r\n", 01832 c->name, c->context, c->exten, c->priority, app->name, passdata, c->uniqueid); 01833 return pbx_exec(c, app, passdata); /* 0 on success, -1 on failure */ 01834 } 01835 } else if (q.swo) { /* not found here, but in another switch */ 01836 ast_mutex_unlock(&conlock); 01837 if (matching_action) 01838 return -1; 01839 else { 01840 if (!q.swo->exec) { 01841 ast_log(LOG_WARNING, "No execution engine for switch %s\n", q.swo->name); 01842 res = -1; 01843 } 01844 return q.swo->exec(c, q.foundcontext ? q.foundcontext : context, exten, priority, callerid, q.data); 01845 } 01846 } else { /* not found anywhere, see what happened */ 01847 ast_mutex_unlock(&conlock); 01848 switch (q.status) { 01849 case STATUS_NO_CONTEXT: 01850 if (!matching_action) 01851 ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", context); 01852 break; 01853 case STATUS_NO_EXTENSION: 01854 if (!matching_action) 01855 ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, context); 01856 break; 01857 case STATUS_NO_PRIORITY: 01858 if (!matching_action) 01859 ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, context); 01860 break; 01861 case STATUS_NO_LABEL: 01862 if (context) 01863 ast_log(LOG_NOTICE, "No such label '%s' in extension '%s' in context '%s'\n", label, exten, context); 01864 break; 01865 default: 01866 if (option_debug) 01867 ast_log(LOG_DEBUG, "Shouldn't happen!\n"); 01868 } 01869 01870 return (matching_action) ? 0 : -1; 01871 } 01872 }
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, read] |
Definition at line 935 of file pbx.c.
References AST_LIST_TRAVERSE, ast_log(), AST_PBX_MAX_STACK, ast_walk_context_extensions(), ast_walk_contexts(), ast_walk_extension_priorities(), ast_switch::canmatch, ast_exten::cidmatch, ast_sw::data, pbx_find_info::data, E_CANMATCH, E_FINDLABEL, E_MATCHMORE, ast_sw::eval, ast_switch::exists, ast_exten::exten, extension_match_core(), pbx_find_info::foundcontext, include_valid(), ast_context::includes, pbx_find_info::incstack, ast_exten::label, LOG_WARNING, match(), matchcid(), ast_exten::matchcid, ast_switch::matchmore, ast_sw::name, ast_include::next, pbx_findswitch(), pbx_substitute_variables_helper(), ast_exten::priority, ast_include::rname, pbx_find_info::stacklen, pbx_find_info::status, STATUS_NO_CONTEXT, STATUS_NO_EXTENSION, STATUS_NO_LABEL, STATUS_NO_PRIORITY, STATUS_SUCCESS, SWITCH_DATA_LENGTH, and pbx_find_info::swo.
Referenced by ast_hint_extension(), and pbx_extension_helper().
00939 { 00940 int x, res; 00941 struct ast_context *tmp; 00942 struct ast_exten *e, *eroot; 00943 struct ast_include *i; 00944 struct ast_sw *sw; 00945 00946 /* Initialize status if appropriate */ 00947 if (q->stacklen == 0) { 00948 q->status = STATUS_NO_CONTEXT; 00949 q->swo = NULL; 00950 q->data = NULL; 00951 q->foundcontext = NULL; 00952 } 00953 /* Check for stack overflow */ 00954 if (q->stacklen >= AST_PBX_MAX_STACK) { 00955 ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n"); 00956 return NULL; 00957 } 00958 /* Check first to see if we've already been checked */ 00959 for (x = 0; x < q->stacklen; x++) { 00960 if (!strcasecmp(q->incstack[x], context)) 00961 return NULL; 00962 } 00963 if (bypass) /* bypass means we only look there */ 00964 tmp = bypass; 00965 else { /* look in contexts */ 00966 tmp = NULL; 00967 while ((tmp = ast_walk_contexts(tmp)) ) { 00968 if (!strcmp(tmp->name, context)) 00969 break; 00970 } 00971 if (!tmp) 00972 return NULL; 00973 } 00974 if (q->status < STATUS_NO_EXTENSION) 00975 q->status = STATUS_NO_EXTENSION; 00976 00977 /* scan the list trying to match extension and CID */ 00978 eroot = NULL; 00979 while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) { 00980 int match = extension_match_core(eroot->exten, exten, action); 00981 /* 0 on fail, 1 on match, 2 on earlymatch */ 00982 00983 if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid))) 00984 continue; /* keep trying */ 00985 if (match == 2 && action == E_MATCHMORE) { 00986 /* We match an extension ending in '!'. 00987 * The decision in this case is final and is NULL (no match). 00988 */ 00989 return NULL; 00990 } 00991 /* found entry, now look for the right priority */ 00992 if (q->status < STATUS_NO_PRIORITY) 00993 q->status = STATUS_NO_PRIORITY; 00994 e = NULL; 00995 while ( (e = ast_walk_extension_priorities(eroot, e)) ) { 00996 /* Match label or priority */ 00997 if (action == E_FINDLABEL) { 00998 if (q->status < STATUS_NO_LABEL) 00999 q->status = STATUS_NO_LABEL; 01000 if (label && e->label && !strcmp(label, e->label)) 01001 break; /* found it */ 01002 } else if (e->priority == priority) { 01003 break; /* found it */ 01004 } /* else keep searching */ 01005 } 01006 if (e) { /* found a valid match */ 01007 q->status = STATUS_SUCCESS; 01008 q->foundcontext = context; 01009 return e; 01010 } 01011 } 01012 /* Check alternative switches */ 01013 AST_LIST_TRAVERSE(&tmp->alts, sw, list) { 01014 struct ast_switch *asw = pbx_findswitch(sw->name); 01015 ast_switch_f *aswf = NULL; 01016 char *datap; 01017 01018 if (!asw) { 01019 ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name); 01020 continue; 01021 } 01022 /* Substitute variables now */ 01023 if (sw->eval) 01024 pbx_substitute_variables_helper(chan, sw->data, sw->tmpdata, SWITCH_DATA_LENGTH - 1); 01025 01026 /* equivalent of extension_match_core() at the switch level */ 01027 if (action == E_CANMATCH) 01028 aswf = asw->canmatch; 01029 else if (action == E_MATCHMORE) 01030 aswf = asw->matchmore; 01031 else /* action == E_MATCH */ 01032 aswf = asw->exists; 01033 datap = sw->eval ? sw->tmpdata : sw->data; 01034 res = !aswf ? 0 : aswf(chan, context, exten, priority, callerid, datap); 01035 if (res) { /* Got a match */ 01036 q->swo = asw; 01037 q->data = datap; 01038 q->foundcontext = context; 01039 /* XXX keep status = STATUS_NO_CONTEXT ? */ 01040 return NULL; 01041 } 01042 } 01043 q->incstack[q->stacklen++] = tmp->name; /* Setup the stack */ 01044 /* Now try any includes we have in this context */ 01045 for (i = tmp->includes; i; i = i->next) { 01046 if (include_valid(i)) { 01047 if ((e = pbx_find_extension(chan, bypass, q, i->rname, exten, priority, label, callerid, action))) 01048 return e; 01049 if (q->swo) 01050 return NULL; 01051 } 01052 } 01053 return NULL; 01054 }
struct ast_app* pbx_findapp | ( | const char * | app | ) | [read] |
Find application handle in linked list.
Look up an application.
Definition at line 548 of file pbx.c.
Referenced by answer_exec_run(), ast_bridge_call(), ast_pbx_run_app(), async_wait(), builtin_automonitor(), conf_run(), dundi_exec(), exec_exec(), execif_exec(), feature_exec_app(), forward_message(), handle_exec(), iax2_exec(), page_exec(), pbx_builtin_execiftime(), pbx_extension_helper(), realtime_exec(), try_calling(), and tryexec_exec().
00549 { 00550 struct ast_app *tmp; 00551 00552 AST_LIST_LOCK(&apps); 00553 AST_LIST_TRAVERSE(&apps, tmp, list) { 00554 if (!strcasecmp(tmp->name, app)) 00555 break; 00556 } 00557 AST_LIST_UNLOCK(&apps); 00558 00559 return tmp; 00560 }
static struct ast_switch* pbx_findswitch | ( | const char * | sw | ) | [static, read] |
Definition at line 562 of file pbx.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, and ast_switch::name.
Referenced by pbx_find_extension().
00563 { 00564 struct ast_switch *asw; 00565 00566 AST_LIST_LOCK(&switches); 00567 AST_LIST_TRAVERSE(&switches, asw, list) { 00568 if (!strcasecmp(asw->name, sw)) 00569 break; 00570 } 00571 AST_LIST_UNLOCK(&switches); 00572 00573 return asw; 00574 }
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 1128 of file pbx.c.
Referenced by action_getvar(), handle_getvariable(), and pbx_substitute_variables_helper_full().
01129 { 01130 const char not_found = '\0'; 01131 char *tmpvar; 01132 const char *s; /* the result */ 01133 int offset, length; 01134 int i, need_substring; 01135 struct varshead *places[2] = { headp, &globals }; /* list of places where we may look */ 01136 01137 if (c) { 01138 places[0] = &c->varshead; 01139 } 01140 /* 01141 * Make a copy of var because parse_variable_name() modifies the string. 01142 * Then if called directly, we might need to run substring() on the result; 01143 * remember this for later in 'need_substring', 'offset' and 'length' 01144 */ 01145 tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */ 01146 need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */); 01147 01148 /* 01149 * Look first into predefined variables, then into variable lists. 01150 * Variable 's' points to the result, according to the following rules: 01151 * s == ¬_found (set at the beginning) means that we did not find a 01152 * matching variable and need to look into more places. 01153 * If s != ¬_found, s is a valid result string as follows: 01154 * s = NULL if the variable does not have a value; 01155 * you typically do this when looking for an unset predefined variable. 01156 * s = workspace if the result has been assembled there; 01157 * typically done when the result is built e.g. with an snprintf(), 01158 * so we don't need to do an additional copy. 01159 * s != workspace in case we have a string, that needs to be copied 01160 * (the ast_copy_string is done once for all at the end). 01161 * Typically done when the result is already available in some string. 01162 */ 01163 s = ¬_found; /* default value */ 01164 if (c) { /* This group requires a valid channel */ 01165 /* Names with common parts are looked up a piece at a time using strncmp. */ 01166 if (!strncmp(var, "CALL", 4)) { 01167 if (!strncmp(var + 4, "ING", 3)) { 01168 if (!strcmp(var + 7, "PRES")) { /* CALLINGPRES */ 01169 snprintf(workspace, workspacelen, "%d", c->cid.cid_pres); 01170 s = workspace; 01171 } else if (!strcmp(var + 7, "ANI2")) { /* CALLINGANI2 */ 01172 snprintf(workspace, workspacelen, "%d", c->cid.cid_ani2); 01173 s = workspace; 01174 } else if (!strcmp(var + 7, "TON")) { /* CALLINGTON */ 01175 snprintf(workspace, workspacelen, "%d", c->cid.cid_ton); 01176 s = workspace; 01177 } else if (!strcmp(var + 7, "TNS")) { /* CALLINGTNS */ 01178 snprintf(workspace, workspacelen, "%d", c->cid.cid_tns); 01179 s = workspace; 01180 } 01181 } 01182 } else if (!strcmp(var, "HINT")) { 01183 s = ast_get_hint(workspace, workspacelen, NULL, 0, c, c->context, c->exten) ? workspace : NULL; 01184 } else if (!strcmp(var, "HINTNAME")) { 01185 s = ast_get_hint(NULL, 0, workspace, workspacelen, c, c->context, c->exten) ? workspace : NULL; 01186 } else if (!strcmp(var, "EXTEN")) { 01187 s = c->exten; 01188 } else if (!strcmp(var, "CONTEXT")) { 01189 s = c->context; 01190 } else if (!strcmp(var, "PRIORITY")) { 01191 snprintf(workspace, workspacelen, "%d", c->priority); 01192 s = workspace; 01193 } else if (!strcmp(var, "CHANNEL")) { 01194 s = c->name; 01195 } else if (!strcmp(var, "UNIQUEID")) { 01196 s = c->uniqueid; 01197 } else if (!strcmp(var, "HANGUPCAUSE")) { 01198 snprintf(workspace, workspacelen, "%d", c->hangupcause); 01199 s = workspace; 01200 } 01201 } 01202 if (s == ¬_found) { /* look for more */ 01203 if (!strcmp(var, "EPOCH")) { 01204 snprintf(workspace, workspacelen, "%u",(int)time(NULL)); 01205 s = workspace; 01206 } else if (!strcmp(var, "SYSTEMNAME")) { 01207 s = ast_config_AST_SYSTEM_NAME; 01208 } 01209 } 01210 /* if not found, look into chanvars or global vars */ 01211 for (i = 0; s == ¬_found && i < (sizeof(places) / sizeof(places[0])); i++) { 01212 struct ast_var_t *variables; 01213 if (!places[i]) 01214 continue; 01215 if (places[i] == &globals) 01216 ast_mutex_lock(&globalslock); 01217 AST_LIST_TRAVERSE(places[i], variables, entries) { 01218 if (strcasecmp(ast_var_name(variables), var)==0) { 01219 s = ast_var_value(variables); 01220 break; 01221 } 01222 } 01223 if (places[i] == &globals) 01224 ast_mutex_unlock(&globalslock); 01225 } 01226 if (s == ¬_found || s == NULL) 01227 *ret = NULL; 01228 else { 01229 if (s != workspace) 01230 ast_copy_string(workspace, s, workspacelen); 01231 *ret = workspace; 01232 if (need_substring) 01233 *ret = substring(*ret, offset, length, workspace, workspacelen); 01234 } 01235 }
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 2655 of file pbx.c.
Referenced by pbx_load_module().
02656 { 02657 int oldval = autofallthrough; 02658 autofallthrough = newval; 02659 return oldval; 02660 }
static void pbx_substitute_variables | ( | char * | passdata, | |
int | datalen, | |||
struct ast_channel * | c, | |||
struct ast_exten * | e | |||
) | [static] |
Definition at line 1749 of file pbx.c.
References ast_exten::data, and pbx_substitute_variables_helper().
Referenced by pbx_extension_helper().
01750 { 01751 memset(passdata, 0, datalen); 01752 01753 /* No variables or expressions in e->data, so why scan it? */ 01754 if (e->data && !strchr(e->data, '$') && !strstr(e->data,"${") && !strstr(e->data,"$[") && !strstr(e->data,"$(")) { 01755 ast_copy_string(passdata, e->data, datalen); 01756 return; 01757 } 01758 01759 pbx_substitute_variables_helper(c, e->data, passdata, datalen - 1); 01760 }
void pbx_substitute_variables_helper | ( | struct ast_channel * | c, | |
const char * | cp1, | |||
char * | cp2, | |||
int | count | |||
) |
Definition at line 1739 of file pbx.c.
Referenced by _macro_exec(), acf_odbc_read(), acf_odbc_write(), custom_log(), cut_internal(), exec_exec(), function_eval(), function_fieldqty(), handle_getvariablefull(), launch_monitor_thread(), make_email_file(), pbx_builtin_importvar(), pbx_find_extension(), pbx_load_config(), pbx_substitute_variables(), realtime_exec(), rpt_do_lstats(), rpt_exec(), sendpage(), try_calling(), and tryexec_exec().
01740 { 01741 pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count); 01742 }
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 1546 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().
01547 { 01548 /* Substitutes variables into cp2, based on string cp1, and assuming cp2 to be 01549 zero-filled */ 01550 char *cp4; 01551 const char *tmp, *whereweare; 01552 int length, offset, offset2, isfunction; 01553 char *workspace = NULL; 01554 char *ltmp = NULL, *var = NULL; 01555 char *nextvar, *nextexp, *nextthing; 01556 char *vars, *vare; 01557 int pos, brackets, needsub, len; 01558 01559 whereweare=tmp=cp1; 01560 while (!ast_strlen_zero(whereweare) && count) { 01561 /* Assume we're copying the whole remaining string */ 01562 pos = strlen(whereweare); 01563 nextvar = NULL; 01564 nextexp = NULL; 01565 nextthing = strchr(whereweare, '$'); 01566 if (nextthing) { 01567 switch(nextthing[1]) { 01568 case '{': 01569 nextvar = nextthing; 01570 pos = nextvar - whereweare; 01571 break; 01572 case '[': 01573 nextexp = nextthing; 01574 pos = nextexp - whereweare; 01575 break; 01576 } 01577 } 01578 01579 if (pos) { 01580 /* Can't copy more than 'count' bytes */ 01581 if (pos > count) 01582 pos = count; 01583 01584 /* Copy that many bytes */ 01585 memcpy(cp2, whereweare, pos); 01586 01587 count -= pos; 01588 cp2 += pos; 01589 whereweare += pos; 01590 } 01591 01592 if (nextvar) { 01593 /* We have a variable. Find the start and end, and determine 01594 if we are going to have to recursively call ourselves on the 01595 contents */ 01596 vars = vare = nextvar + 2; 01597 brackets = 1; 01598 needsub = 0; 01599 01600 /* Find the end of it */ 01601 while (brackets && *vare) { 01602 if ((vare[0] == '$') && (vare[1] == '{')) { 01603 needsub++; 01604 } else if (vare[0] == '{') { 01605 brackets++; 01606 } else if (vare[0] == '}') { 01607 brackets--; 01608 } else if ((vare[0] == '$') && (vare[1] == '[')) 01609 needsub++; 01610 vare++; 01611 } 01612 if (brackets) 01613 ast_log(LOG_NOTICE, "Error in extension logic (missing '}')\n"); 01614 len = vare - vars - 1; 01615 01616 /* Skip totally over variable string */ 01617 whereweare += (len + 3); 01618 01619 if (!var) 01620 var = alloca(VAR_BUF_SIZE); 01621 01622 /* Store variable name (and truncate) */ 01623 ast_copy_string(var, vars, len + 1); 01624 01625 /* Substitute if necessary */ 01626 if (needsub) { 01627 if (!ltmp) 01628 ltmp = alloca(VAR_BUF_SIZE); 01629 01630 memset(ltmp, 0, VAR_BUF_SIZE); 01631 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1); 01632 vars = ltmp; 01633 } else { 01634 vars = var; 01635 } 01636 01637 if (!workspace) 01638 workspace = alloca(VAR_BUF_SIZE); 01639 01640 workspace[0] = '\0'; 01641 01642 parse_variable_name(vars, &offset, &offset2, &isfunction); 01643 if (isfunction) { 01644 /* Evaluate function */ 01645 if (c || !headp) 01646 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 01647 else { 01648 struct varshead old; 01649 struct ast_channel *c = ast_channel_alloc(0, 0, "", "", "", "", "", 0, "Bogus/%p", vars); 01650 if (c) { 01651 memcpy(&old, &c->varshead, sizeof(old)); 01652 memcpy(&c->varshead, headp, sizeof(c->varshead)); 01653 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 01654 /* Don't deallocate the varshead that was passed in */ 01655 memcpy(&c->varshead, &old, sizeof(c->varshead)); 01656 ast_channel_free(c); 01657 } else 01658 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n"); 01659 } 01660 01661 if (option_debug) 01662 ast_log(LOG_DEBUG, "Function result is '%s'\n", cp4 ? cp4 : "(null)"); 01663 } else { 01664 /* Retrieve variable value */ 01665 pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp); 01666 } 01667 if (cp4) { 01668 cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE); 01669 01670 length = strlen(cp4); 01671 if (length > count) 01672 length = count; 01673 memcpy(cp2, cp4, length); 01674 count -= length; 01675 cp2 += length; 01676 } 01677 } else if (nextexp) { 01678 /* We have an expression. Find the start and end, and determine 01679 if we are going to have to recursively call ourselves on the 01680 contents */ 01681 vars = vare = nextexp + 2; 01682 brackets = 1; 01683 needsub = 0; 01684 01685 /* Find the end of it */ 01686 while(brackets && *vare) { 01687 if ((vare[0] == '$') && (vare[1] == '[')) { 01688 needsub++; 01689 brackets++; 01690 vare++; 01691 } else if (vare[0] == '[') { 01692 brackets++; 01693 } else if (vare[0] == ']') { 01694 brackets--; 01695 } else if ((vare[0] == '$') && (vare[1] == '{')) { 01696 needsub++; 01697 vare++; 01698 } 01699 vare++; 01700 } 01701 if (brackets) 01702 ast_log(LOG_NOTICE, "Error in extension logic (missing ']')\n"); 01703 len = vare - vars - 1; 01704 01705 /* Skip totally over expression */ 01706 whereweare += (len + 3); 01707 01708 if (!var) 01709 var = alloca(VAR_BUF_SIZE); 01710 01711 /* Store variable name (and truncate) */ 01712 ast_copy_string(var, vars, len + 1); 01713 01714 /* Substitute if necessary */ 01715 if (needsub) { 01716 if (!ltmp) 01717 ltmp = alloca(VAR_BUF_SIZE); 01718 01719 memset(ltmp, 0, VAR_BUF_SIZE); 01720 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1); 01721 vars = ltmp; 01722 } else { 01723 vars = var; 01724 } 01725 01726 length = ast_expr(vars, cp2, count); 01727 01728 if (length) { 01729 if (option_debug) 01730 ast_log(LOG_DEBUG, "Expression result is '%s'\n", cp2); 01731 count -= length; 01732 cp2 += length; 01733 } 01734 } else 01735 break; 01736 } 01737 }
void pbx_substitute_variables_varshead | ( | struct varshead * | headp, | |
const char * | cp1, | |||
char * | cp2, | |||
int | count | |||
) |
Definition at line 1744 of file pbx.c.
Referenced by ast_add_extension2(), do_say(), dundi_lookup_local(), and loopback_helper().
01745 { 01746 pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count); 01747 }
static void* pbx_thread | ( | void * | data | ) | [static] |
Definition at line 2591 of file pbx.c.
References __ast_pbx_run(), and decrease_call_count().
Referenced by ast_pbx_start().
02592 { 02593 /* Oh joyeous kernel, we're a new thread, with nothing to do but 02594 answer this channel and get it going. 02595 */ 02596 /* NOTE: 02597 The launcher of this function _MUST_ increment 'countcalls' 02598 before invoking the function; it will be decremented when the 02599 PBX has finished running on the channel 02600 */ 02601 struct ast_channel *c = data; 02602 02603 __ast_pbx_run(c); 02604 decrease_call_count(); 02605 02606 pthread_exit(NULL); 02607 02608 return NULL; 02609 }
static void print_ext | ( | struct ast_exten * | e, | |
char * | buf, | |||
int | buflen | |||
) | [static] |
helper function to print an extension
Definition at line 3474 of file pbx.c.
References ast_get_extension_app(), ast_get_extension_app_data(), ast_get_extension_priority(), and PRIORITY_HINT.
Referenced by show_dialplan_helper().
03475 { 03476 int prio = ast_get_extension_priority(e); 03477 if (prio == PRIORITY_HINT) { 03478 snprintf(buf, buflen, "hint: %s", 03479 ast_get_extension_app(e)); 03480 } else { 03481 snprintf(buf, buflen, "%d. %s(%s)", 03482 prio, ast_get_extension_app(e), 03483 (char *)ast_get_extension_app_data(e)); 03484 } 03485 }
static void set_ext_pri | ( | struct ast_channel * | c, | |
const char * | exten, | |||
int | pri | |||
) | [static] |
Definition at line 2292 of file pbx.c.
References ast_channel::exten, and ast_channel::priority.
Referenced by __ast_pbx_run(), ast_pbx_outgoing_exten(), and pbx_builtin_waitexten().
static int show_dialplan_helper | ( | int | fd, | |
const char * | context, | |||
const char * | exten, | |||
struct dialplan_counters * | dpc, | |||
struct ast_include * | rinclude, | |||
int | includecount, | |||
const char * | includes[] | |||
) | [static] |
Definition at line 3488 of file pbx.c.
References ast_cli(), ast_extension_match(), ast_get_context_name(), ast_get_context_registrar(), ast_get_extension_label(), ast_get_extension_name(), ast_get_extension_registrar(), ast_get_ignorepat_name(), ast_get_ignorepat_registrar(), ast_get_include_name(), ast_get_include_registrar(), ast_get_switch_data(), ast_get_switch_name(), ast_get_switch_registrar(), ast_lock_context(), ast_lock_contexts(), ast_log(), AST_MAX_EXTENSION, AST_PBX_MAX_STACK, ast_unlock_context(), ast_unlock_contexts(), ast_walk_context_extensions(), ast_walk_context_ignorepats(), ast_walk_context_includes(), ast_walk_context_switches(), ast_walk_contexts(), ast_walk_extension_priorities(), dialplan_counters::context_existence, el, dialplan_counters::extension_existence, LOG_NOTICE, LOG_WARNING, print_ext(), dialplan_counters::total_context, dialplan_counters::total_exten, and dialplan_counters::total_prio.
Referenced by handle_show_dialplan().
03489 { 03490 struct ast_context *c = NULL; 03491 int res = 0, old_total_exten = dpc->total_exten; 03492 03493 ast_lock_contexts(); 03494 03495 /* walk all contexts ... */ 03496 while ( (c = ast_walk_contexts(c)) ) { 03497 struct ast_exten *e; 03498 struct ast_include *i; 03499 struct ast_ignorepat *ip; 03500 char buf[256], buf2[256]; 03501 int context_info_printed = 0; 03502 03503 if (context && strcmp(ast_get_context_name(c), context)) 03504 continue; /* skip this one, name doesn't match */ 03505 03506 dpc->context_existence = 1; 03507 03508 ast_lock_context(c); 03509 03510 /* are we looking for exten too? if yes, we print context 03511 * only if we find our extension. 03512 * Otherwise print context even if empty ? 03513 * XXX i am not sure how the rinclude is handled. 03514 * I think it ought to go inside. 03515 */ 03516 if (!exten) { 03517 dpc->total_context++; 03518 ast_cli(fd, "[ Context '%s' created by '%s' ]\n", 03519 ast_get_context_name(c), ast_get_context_registrar(c)); 03520 context_info_printed = 1; 03521 } 03522 03523 /* walk extensions ... */ 03524 e = NULL; 03525 while ( (e = ast_walk_context_extensions(c, e)) ) { 03526 struct ast_exten *p; 03527 03528 if (exten && !ast_extension_match(ast_get_extension_name(e), exten)) 03529 continue; /* skip, extension match failed */ 03530 03531 dpc->extension_existence = 1; 03532 03533 /* may we print context info? */ 03534 if (!context_info_printed) { 03535 dpc->total_context++; 03536 if (rinclude) { /* TODO Print more info about rinclude */ 03537 ast_cli(fd, "[ Included context '%s' created by '%s' ]\n", 03538 ast_get_context_name(c), ast_get_context_registrar(c)); 03539 } else { 03540 ast_cli(fd, "[ Context '%s' created by '%s' ]\n", 03541 ast_get_context_name(c), ast_get_context_registrar(c)); 03542 } 03543 context_info_printed = 1; 03544 } 03545 dpc->total_prio++; 03546 03547 /* write extension name and first peer */ 03548 snprintf(buf, sizeof(buf), "'%s' =>", ast_get_extension_name(e)); 03549 03550 print_ext(e, buf2, sizeof(buf2)); 03551 03552 ast_cli(fd, " %-17s %-45s [%s]\n", buf, buf2, 03553 ast_get_extension_registrar(e)); 03554 03555 dpc->total_exten++; 03556 /* walk next extension peers */ 03557 p = e; /* skip the first one, we already got it */ 03558 while ( (p = ast_walk_extension_priorities(e, p)) ) { 03559 const char *el = ast_get_extension_label(p); 03560 dpc->total_prio++; 03561 if (el) 03562 snprintf(buf, sizeof(buf), " [%s]", el); 03563 else 03564 buf[0] = '\0'; 03565 print_ext(p, buf2, sizeof(buf2)); 03566 03567 ast_cli(fd," %-17s %-45s [%s]\n", buf, buf2, 03568 ast_get_extension_registrar(p)); 03569 } 03570 } 03571 03572 /* walk included and write info ... */ 03573 i = NULL; 03574 while ( (i = ast_walk_context_includes(c, i)) ) { 03575 snprintf(buf, sizeof(buf), "'%s'", ast_get_include_name(i)); 03576 if (exten) { 03577 /* Check all includes for the requested extension */ 03578 if (includecount >= AST_PBX_MAX_STACK) { 03579 ast_log(LOG_NOTICE, "Maximum include depth exceeded!\n"); 03580 } else { 03581 int dupe=0; 03582 int x; 03583 for (x=0;x<includecount;x++) { 03584 if (!strcasecmp(includes[x], ast_get_include_name(i))) { 03585 dupe++; 03586 break; 03587 } 03588 } 03589 if (!dupe) { 03590 includes[includecount] = ast_get_include_name(i); 03591 show_dialplan_helper(fd, ast_get_include_name(i), exten, dpc, i, includecount + 1, includes); 03592 } else { 03593 ast_log(LOG_WARNING, "Avoiding circular include of %s within %s\n", ast_get_include_name(i), context); 03594 } 03595 } 03596 } else { 03597 ast_cli(fd, " Include => %-45s [%s]\n", 03598 buf, ast_get_include_registrar(i)); 03599 } 03600 } 03601 03602 /* walk ignore patterns and write info ... */ 03603 ip = NULL; 03604 while ( (ip = ast_walk_context_ignorepats(c, ip)) ) { 03605 const char *ipname = ast_get_ignorepat_name(ip); 03606 char ignorepat[AST_MAX_EXTENSION]; 03607 snprintf(buf, sizeof(buf), "'%s'", ipname); 03608 snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname); 03609 if (!exten || ast_extension_match(ignorepat, exten)) { 03610 ast_cli(fd, " Ignore pattern => %-45s [%s]\n", 03611 buf, ast_get_ignorepat_registrar(ip)); 03612 } 03613 } 03614 if (!rinclude) { 03615 struct ast_sw *sw = NULL; 03616 while ( (sw = ast_walk_context_switches(c, sw)) ) { 03617 snprintf(buf, sizeof(buf), "'%s/%s'", 03618 ast_get_switch_name(sw), 03619 ast_get_switch_data(sw)); 03620 ast_cli(fd, " Alt. Switch => %-45s [%s]\n", 03621 buf, ast_get_switch_registrar(sw)); 03622 } 03623 } 03624 03625 ast_unlock_context(c); 03626 03627 /* if we print something in context, make an empty line */ 03628 if (context_info_printed) 03629 ast_cli(fd, "\r\n"); 03630 } 03631 ast_unlock_contexts(); 03632 03633 return (dpc->total_exten == old_total_exten) ? -1 : res; 03634 }
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 1090 of file pbx.c.
Referenced by pbx_retrieve_variable(), and pbx_substitute_variables_helper_full().
01091 { 01092 char *ret = workspace; 01093 int lr; /* length of the input string after the copy */ 01094 01095 ast_copy_string(workspace, value, workspace_len); /* always make a copy */ 01096 01097 lr = strlen(ret); /* compute length after copy, so we never go out of the workspace */ 01098 01099 /* Quick check if no need to do anything */ 01100 if (offset == 0 && length >= lr) /* take the whole string */ 01101 return ret; 01102 01103 if (offset < 0) { /* translate negative offset into positive ones */ 01104 offset = lr + offset; 01105 if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */ 01106 offset = 0; 01107 } 01108 01109 /* too large offset result in empty string so we know what to return */ 01110 if (offset >= lr) 01111 return ret + lr; /* the final '\0' */ 01112 01113 ret += offset; /* move to the start position */ 01114 if (length >= 0 && length < lr - offset) /* truncate if necessary */ 01115 ret[length] = '\0'; 01116 else if (length < 0) { 01117 if (lr > offset - length) /* After we remove from the front and from the rear, is there anything left? */ 01118 ret[lr + length - offset] = '\0'; 01119 else 01120 ret[0] = '\0'; 01121 } 01122 01123 return ret; 01124 }
static void wait_for_hangup | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 5325 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().
05326 { 05327 int res; 05328 struct ast_frame *f; 05329 int waittime; 05330 05331 if (ast_strlen_zero(data) || (sscanf(data, "%d", &waittime) != 1) || (waittime < 0)) 05332 waittime = -1; 05333 if (waittime > -1) { 05334 ast_safe_sleep(chan, waittime * 1000); 05335 } else do { 05336 res = ast_waitfor(chan, -1); 05337 if (res < 0) 05338 return; 05339 f = ast_read(chan); 05340 if (f) 05341 ast_frfree(f); 05342 } while(f); 05343 }
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 490 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 246 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] |
Definition at line 241 of file pbx.c.
Referenced by ast_add_extension2(), handle_show_globals(), pbx_builtin_clear_globals(), pbx_builtin_getvar_helper(), pbx_builtin_pushvar_helper(), pbx_builtin_setvar_helper(), and pbx_retrieve_variable().
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 505 of file pbx.c.
Referenced by ast_extension_state_add(), ast_extension_state_del(), and ast_hint_state_changed().
int stateid = 1 [static] |