Sun Dec 18 20:55:52 2011

Asterisk developer's documentation


pbx.c File Reference

Core PBX routines. More...

#include "asterisk.h"
#include <sys/types.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include <time.h>
#include <sys/time.h>
#include <limits.h>
#include "asterisk/lock.h"
#include "asterisk/cli.h"
#include "asterisk/pbx.h"
#include "asterisk/channel.h"
#include "asterisk/options.h"
#include "asterisk/logger.h"
#include "asterisk/file.h"
#include "asterisk/callerid.h"
#include "asterisk/cdr.h"
#include "asterisk/config.h"
#include "asterisk/term.h"
#include "asterisk/manager.h"
#include "asterisk/ast_expr.h"
#include "asterisk/linkedlists.h"
#include "asterisk/say.h"
#include "asterisk/utils.h"
#include "asterisk/causes.h"
#include "asterisk/musiconhold.h"
#include "asterisk/app.h"
#include "asterisk/devicestate.h"
#include "asterisk/stringfields.h"
#include "asterisk/threadstorage.h"

Include dependency graph for pbx.c:

Go to the source code of this file.

Data Structures

struct  app_tmp
struct  ast_app
 ast_app: A registered application More...
struct  ast_context
 ast_context: An extension context More...
struct  ast_exten
 ast_exten: An extension The dialplan is saved as a linked list with each context having it's own linked list of extensions - one item per priority. More...
struct  ast_hint
 Structure for dial plan hints. More...
struct  ast_ignorepat
 ast_ignorepat: Ignore patterns in dial plan More...
struct  ast_include
 ast_include: include= support in extensions.conf More...
struct  ast_state_cb
 ast_state_cb: An extension state notify register item More...
struct  ast_sw
 ast_sw: Switch statement in extensions.conf More...
struct  async_stat
struct  cfextension_states
struct  dialplan_counters
struct  pbx_builtin
 Declaration of builtin applications. More...
struct  pbx_find_info
struct  store_hint

Defines

#define AST_PBX_MAX_STACK   128
#define BACKGROUND_MATCHEXTEN   (1 << 2)
#define BACKGROUND_NOANSWER   (1 << 1)
#define BACKGROUND_PLAYBACK   (1 << 3)
#define BACKGROUND_SKIP   (1 << 0)
#define EXT_DATA_SIZE   8192
#define SAY_STUBS
#define STATUS_NO_CONTEXT   1
#define STATUS_NO_EXTENSION   2
#define STATUS_NO_LABEL   4
#define STATUS_NO_PRIORITY   3
#define STATUS_SUCCESS   5
#define SWITCH_DATA_LENGTH   256
#define VAR_BUF_SIZE   4096
#define VAR_HARDTRAN   3
#define VAR_NORMAL   1
#define VAR_SOFTTRAN   2
#define WAITEXTEN_MOH   (1 << 0)

Enumerations

enum  ext_match_t {
  E_MATCHMORE = 0x00, E_CANMATCH = 0x01, E_MATCH = 0x02, E_MATCH_MASK = 0x03,
  E_SPAWN = 0x12, E_FINDLABEL = 0x22
}

Functions

static struct ast_context__ast_context_create (struct ast_context **extcontexts, const char *name, const char *registrar, int existsokay)
void __ast_context_destroy (struct ast_context *con, const char *registrar)
static int __ast_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority, int async)
static int __ast_pbx_run (struct ast_channel *c)
static int _extension_match_core (const char *pattern, const char *data, enum ext_match_t mode)
static int add_pri (struct ast_context *con, struct ast_exten *tmp, struct ast_exten *el, struct ast_exten *e, int replace)
 add the extension in the priority chain. returns 0 on success, -1 on failure
int ast_active_calls (void)
 Retrieve the number of active calls.
int ast_add_extension (const char *context, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar)
 Add and extension to an extension context.
int ast_add_extension2 (struct ast_context *con, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar)
 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_contextast_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_contextast_context_find (const char *name)
 Find a context.
struct ast_contextast_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_functionast_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_contextast_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_extenast_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, char *cid_num, char *cid_name)
int ast_ignore_pattern (const char *context, const char *pattern)
 Checks to see if a number should be ignored.
 AST_LIST_HEAD (store_hints, store_hint)
static AST_LIST_HEAD_STATIC (hints, ast_hint)
static AST_LIST_HEAD_STATIC (switches, ast_switch)
static AST_LIST_HEAD_STATIC (apps, ast_app)
static AST_LIST_HEAD_STATIC (acf_root, ast_custom_function)
int ast_lock_context (struct ast_context *con)
 Locks a given context.
int ast_lock_contexts ()
 Locks the context list.
int ast_matchmore_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
 Looks to see if adding anything to this extension might match something. (exists ^ canmatch).
void ast_merge_contexts_and_delete (struct ast_context **extcontexts, const char *registrar)
 Merge the temporary contexts into a global contexts list and delete from the global list the ones that are being added.
 AST_MUTEX_DEFINE_STATIC (maxcalllock)
 AST_MUTEX_DEFINE_STATIC (globalslock)
int ast_parseable_goto (struct ast_channel *chan, const char *goto_string)
int ast_pbx_outgoing_app (const char *type, int format, void *data, int timeout, const char *app, const char *appdata, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel)
int ast_pbx_outgoing_app_uniqueid (const char *type, int format, void *data, int timeout, const char *app, const char *appdata, int *reason, int sync, int callingpres, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel, char *uniqueid)
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)
int ast_pbx_outgoing_exten_uniqueid (const char *type, int format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int sync, int callingpres, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **channel, char *uniqueid)
enum ast_pbx_result ast_pbx_run (struct ast_channel *c)
 Execute the PBX in the current thread.
static void * ast_pbx_run_app (void *data)
 run the application and free the descriptor once done
enum ast_pbx_result ast_pbx_start (struct ast_channel *c)
 Create a new thread and start the PBX.
int ast_rdlock_contexts (void)
int ast_register_application (const char *app, int(*execute)(struct ast_channel *, void *), const char *synopsis, const char *description)
 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
 AST_RWLOCK_DEFINE_STATIC (conlock)
int ast_spawn_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
 Launch a new extension (i.e. new stack).
 AST_THREADSTORAGE (switch_data, switch_data_init)
int ast_unlock_context (struct ast_context *con)
int ast_unlock_contexts ()
 Unlocks contexts.
int ast_unregister_application (const char *app)
 Unregister an application.
void ast_unregister_switch (struct ast_switch *sw)
 Unregister an alternative switch.
struct ast_extenast_walk_context_extensions (struct ast_context *con, struct ast_exten *exten)
struct ast_ignorepatast_walk_context_ignorepats (struct ast_context *con, struct ast_ignorepat *ip)
struct ast_includeast_walk_context_includes (struct ast_context *con, struct ast_include *inc)
struct ast_swast_walk_context_switches (struct ast_context *con, struct ast_sw *sw)
struct ast_contextast_walk_contexts (struct ast_context *con)
struct ast_extenast_walk_extension_priorities (struct ast_exten *exten, struct ast_exten *priority)
int ast_wrlock_contexts (void)
static void * async_wait (void *data)
static int collect_digits (struct ast_channel *c, int waittime, char *buf, int buflen, int pos)
 collect digits from the channel into the buffer, return -1 on error, 0 on timeout or done.
static char * complete_show_application (const char *line, const char *word, int pos, int state)
static char * complete_show_applications (const char *line, const char *word, int pos, int state)
static char * complete_show_applications_deprecated (const char *line, const char *word, int pos, int state)
static char * complete_show_dialplan_context (const char *line, const char *word, int pos, int state)
static char * complete_show_function (const char *line, const char *word, int pos, int state)
static void decrease_call_count (void)
static void destroy_exten (struct ast_exten *e)
static int ext_cmp (const char *a, const char *b)
 the full routine to compare extensions in rules.
static int ext_cmp1 (const char **p)
 helper functions to sort extensions and patterns in the desired way, so that more specific patterns appear first.
static int ext_strncpy (char *dst, const char *src, int len)
 copy a string skipping whitespace
static int extension_match_core (const char *pattern, const char *data, enum ext_match_t mode)
static struct ast_contextfind_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_extenpbx_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_apppbx_findapp (const char *app)
 Find application handle in linked list.
static struct ast_switchpbx_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_contextcontexts
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_cbstatecbs
static int stateid = 1


Detailed Description

Core PBX routines.

Author:
Mark Spencer <markster@digium.com>

Definition in file pbx.c.


Define Documentation

#define AST_PBX_MAX_STACK   128

Go no deeper than this through includes (not counting loops)

Definition at line 549 of file pbx.c.

Referenced by handle_show_dialplan(), pbx_find_extension(), and show_dialplan_helper().

#define BACKGROUND_MATCHEXTEN   (1 << 2)

Definition at line 91 of file pbx.c.

Referenced by pbx_builtin_background().

#define BACKGROUND_NOANSWER   (1 << 1)

Definition at line 90 of file pbx.c.

Referenced by pbx_builtin_background().

#define BACKGROUND_PLAYBACK   (1 << 3)

Definition at line 92 of file pbx.c.

Referenced by pbx_builtin_background().

#define BACKGROUND_SKIP   (1 << 0)

Definition at line 89 of file pbx.c.

Referenced by pbx_builtin_background().

#define EXT_DATA_SIZE   8192

Note:
I M P O R T A N T :
The speed of extension handling will likely be among the most important aspects of this PBX. The switching scheme as it exists right now isn't terribly bad (it's O(N+M), where N is the # of extensions and M is the avg # of priorities, but a constant search time here would be great ;-)

Definition at line 78 of file pbx.c.

Referenced by pbx_extension_helper(), and realtime_exec().

#define SAY_STUBS

Definition at line 55 of file pbx.c.

#define STATUS_NO_CONTEXT   1

Definition at line 911 of file pbx.c.

Referenced by pbx_extension_helper(), and pbx_find_extension().

#define STATUS_NO_EXTENSION   2

Definition at line 912 of file pbx.c.

Referenced by pbx_extension_helper(), and pbx_find_extension().

#define STATUS_NO_LABEL   4

Definition at line 914 of file pbx.c.

Referenced by pbx_extension_helper(), and pbx_find_extension().

#define STATUS_NO_PRIORITY   3

Definition at line 913 of file pbx.c.

Referenced by pbx_extension_helper(), and pbx_find_extension().

#define STATUS_SUCCESS   5

Definition at line 915 of file pbx.c.

Referenced by pbx_find_extension().

#define SWITCH_DATA_LENGTH   256

Definition at line 81 of file pbx.c.

#define VAR_BUF_SIZE   4096

#define VAR_HARDTRAN   3

Definition at line 87 of file pbx.c.

#define VAR_NORMAL   1

Definition at line 85 of file pbx.c.

#define VAR_SOFTTRAN   2

Definition at line 86 of file pbx.c.

#define WAITEXTEN_MOH   (1 << 0)

Definition at line 101 of file pbx.c.

Referenced by pbx_builtin_waitexten().


Enumeration Type Documentation

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.

Enumerator:
E_MATCHMORE 
E_CANMATCH 
E_MATCH 
E_MATCH_MASK 
E_SPAWN 
E_FINDLABEL 

Definition at line 754 of file pbx.c.

00754                  {
00755    E_MATCHMORE =  0x00, /* extension can match but only with more 'digits' */
00756    E_CANMATCH =   0x01, /* extension can match with or without more 'digits' */
00757    E_MATCH =   0x02, /* extension is an exact match */
00758    E_MATCH_MASK = 0x03, /* mask for the argument to extension_match_core() */
00759    E_SPAWN =   0x12, /* want to spawn an extension. Requires exact match */
00760    E_FINDLABEL =  0x22  /* returns the priority for a given label. Requires exact match */
00761 };


Function Documentation

static struct ast_context* __ast_context_create ( struct ast_context **  extcontexts,
const char *  name,
const char *  registrar,
int  existsokay 
) [static, read]

Definition at line 3873 of file pbx.c.

References ast_calloc, ast_log(), ast_mutex_init(), ast_rdlock_contexts(), ast_unlock_contexts(), ast_verbose(), ast_wrlock_contexts(), contexts, local_contexts, ast_context::lock, LOG_DEBUG, LOG_WARNING, ast_context::next, option_debug, option_verbose, ast_context::registrar, and VERBOSE_PREFIX_3.

Referenced by ast_context_create(), and ast_context_find_or_create().

03874 {
03875    struct ast_context *tmp, **local_contexts;
03876    int length = sizeof(struct ast_context) + strlen(name) + 1;
03877 
03878    if (!extcontexts) {
03879       ast_rdlock_contexts();
03880       local_contexts = &contexts;
03881    } else
03882       local_contexts = extcontexts;
03883 
03884    for (tmp = *local_contexts; tmp; tmp = tmp->next) {
03885       if (!strcasecmp(tmp->name, name)) {
03886          if (!existsokay) {
03887             ast_log(LOG_WARNING, "Tried to register context '%s', already in use\n", name);
03888             tmp = NULL;
03889          }
03890          if (!extcontexts)
03891             ast_unlock_contexts();
03892          return tmp;
03893       }
03894    }
03895    
03896    if (!extcontexts)
03897       ast_unlock_contexts();
03898 
03899    if ((tmp = ast_calloc(1, length))) {
03900       ast_mutex_init(&tmp->lock);
03901       ast_mutex_init(&tmp->macrolock);
03902       strcpy(tmp->name, name);
03903       tmp->registrar = registrar;
03904       if (!extcontexts)
03905          ast_wrlock_contexts();
03906       tmp->next = *local_contexts;
03907       *local_contexts = tmp;
03908       if (!extcontexts)
03909          ast_unlock_contexts();
03910       if (option_debug)
03911          ast_log(LOG_DEBUG, "Registered context '%s'\n", tmp->name);
03912       if (option_verbose > 2)
03913          ast_verbose( VERBOSE_PREFIX_3 "Registered extension context '%s'\n", tmp->name);
03914    }
03915 
03916    return tmp;
03917 }

void __ast_context_destroy ( struct ast_context con,
const char *  registrar 
)

Definition at line 5310 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().

05311 {
05312    struct ast_context *tmp, *tmpl=NULL;
05313    struct ast_include *tmpi;
05314    struct ast_sw *sw;
05315    struct ast_exten *e, *el, *en;
05316    struct ast_ignorepat *ipi;
05317 
05318    for (tmp = contexts; tmp; ) {
05319       struct ast_context *next;  /* next starting point */
05320       for (; tmp; tmpl = tmp, tmp = tmp->next) {
05321          if (option_debug)
05322             ast_log(LOG_DEBUG, "check ctx %s %s\n", tmp->name, tmp->registrar);
05323          if ( (!registrar || !strcasecmp(registrar, tmp->registrar)) &&
05324               (!con || !strcasecmp(tmp->name, con->name)) )
05325             break;   /* found it */
05326       }
05327       if (!tmp)   /* not found, we are done */
05328          break;
05329       ast_mutex_lock(&tmp->lock);
05330       if (option_debug)
05331          ast_log(LOG_DEBUG, "delete ctx %s %s\n", tmp->name, tmp->registrar);
05332       next = tmp->next;
05333       if (tmpl)
05334          tmpl->next = next;
05335       else
05336          contexts = next;
05337       /* Okay, now we're safe to let it go -- in a sense, we were
05338          ready to let it go as soon as we locked it. */
05339       ast_mutex_unlock(&tmp->lock);
05340       for (tmpi = tmp->includes; tmpi; ) { /* Free includes */
05341          struct ast_include *tmpil = tmpi;
05342          tmpi = tmpi->next;
05343          free(tmpil);
05344       }
05345       for (ipi = tmp->ignorepats; ipi; ) { /* Free ignorepats */
05346          struct ast_ignorepat *ipl = ipi;
05347          ipi = ipi->next;
05348          free(ipl);
05349       }
05350       while ((sw = AST_LIST_REMOVE_HEAD(&tmp->alts, list)))
05351          free(sw);
05352       for (e = tmp->root; e;) {
05353          for (en = e->peer; en;) {
05354             el = en;
05355             en = en->peer;
05356             destroy_exten(el);
05357          }
05358          el = e;
05359          e = e->next;
05360          destroy_exten(el);
05361       }
05362       ast_mutex_destroy(&tmp->lock);
05363       free(tmp);
05364       /* if we have a specific match, we are done, otherwise continue */
05365       tmp = con ? NULL : next;
05366    }
05367 }

static int __ast_goto_if_exists ( struct ast_channel chan,
const char *  context,
const char *  exten,
int  priority,
int  async 
) [static]

Definition at line 6361 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().

06362 {
06363    int (*goto_func)(struct ast_channel *chan, const char *context, const char *exten, int priority);
06364 
06365    if (!chan)
06366       return -2;
06367 
06368    if (context == NULL)
06369       context = chan->context;
06370    if (exten == NULL)
06371       exten = chan->exten;
06372 
06373    goto_func = (async) ? ast_async_goto : ast_explicit_goto;
06374    if (ast_exists_extension(chan, context, exten, priority, chan->cid.cid_num))
06375       return goto_func(chan, context, exten, priority);
06376    else
06377       return -3;
06378 }

static int __ast_pbx_run ( struct ast_channel c  )  [static]

Definition at line 2359 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().

02360 {
02361    int found = 0; /* set if we find at least one match */
02362    int res = 0;
02363    int autoloopflag;
02364    int error = 0;    /* set an error conditions */
02365 
02366    /* A little initial setup here */
02367    if (c->pbx) {
02368       ast_log(LOG_WARNING, "%s already has PBX structure??\n", c->name);
02369       /* XXX and now what ? */
02370       free(c->pbx);
02371    }
02372    if (!(c->pbx = ast_calloc(1, sizeof(*c->pbx))))
02373       return -1;
02374    if (c->amaflags) {
02375       if (!c->cdr) {
02376          c->cdr = ast_cdr_alloc();
02377          if (!c->cdr) {
02378             ast_log(LOG_WARNING, "Unable to create Call Detail Record\n");
02379             free(c->pbx);
02380             return -1;
02381          }
02382          ast_cdr_init(c->cdr, c);
02383       }
02384    }
02385    /* Set reasonable defaults */
02386    c->pbx->rtimeout = 10;
02387    c->pbx->dtimeout = 5;
02388 
02389    autoloopflag = ast_test_flag(c, AST_FLAG_IN_AUTOLOOP);   /* save value to restore at the end */
02390    ast_set_flag(c, AST_FLAG_IN_AUTOLOOP);
02391 
02392    /* Start by trying whatever the channel is set to */
02393    if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) {
02394       /* If not successful fall back to 's' */
02395       if (option_verbose > 1)
02396          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);
02397       /* XXX the original code used the existing priority in the call to
02398        * ast_exists_extension(), and reset it to 1 afterwards.
02399        * I believe the correct thing is to set it to 1 immediately.
02400        */
02401       set_ext_pri(c, "s", 1);
02402       if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) {
02403          /* JK02: And finally back to default if everything else failed */
02404          if (option_verbose > 1)
02405             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);
02406          ast_copy_string(c->context, "default", sizeof(c->context));
02407       }
02408    }
02409    if (c->cdr && ast_tvzero(c->cdr->start))
02410       ast_cdr_start(c->cdr);
02411    for (;;) {
02412       char dst_exten[256]; /* buffer to accumulate digits */
02413       int pos = 0;      /* XXX should check bounds */
02414       int digit = 0;
02415 
02416       /* loop on priorities in this context/exten */
02417       while (ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) {
02418          found = 1;
02419          if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num))) {
02420             /* Something bad happened, or a hangup has been requested. */
02421             if (strchr("0123456789ABCDEF*#", res)) {
02422                if (option_debug)
02423                   ast_log(LOG_DEBUG, "Oooh, got something to jump out with ('%c')!\n", res);
02424                pos = 0;
02425                dst_exten[pos++] = digit = res;
02426                dst_exten[pos] = '\0';
02427                break;
02428             }
02429             if (res == AST_PBX_KEEPALIVE) {
02430                if (option_debug)
02431                   ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
02432                if (option_verbose > 1)
02433                   ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
02434                error = 1;
02435                break;
02436             }
02437             if (option_debug)
02438                ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
02439             if (option_verbose > 1)
02440                ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
02441             if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
02442                c->_softhangup = 0;
02443             } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) {
02444                /* atimeout, nothing bad */
02445             } else {
02446                if (c->cdr)
02447                   ast_cdr_update(c);
02448                error = 1;
02449                break;
02450             }
02451          }
02452          if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
02453             c->_softhangup = 0;
02454          } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT && ast_exists_extension(c,c->context,"T",1,c->cid.cid_num)) {
02455             set_ext_pri(c, "T", 0); /* 0 will become 1 with the c->priority++; at the end */
02456             /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
02457             c->whentohangup = 0;
02458             c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT;
02459          } else if (c->_softhangup) {
02460             if (option_debug)
02461                ast_log(LOG_DEBUG, "Extension %s, priority %d returned normally even though call was hung up\n",
02462                   c->exten, c->priority);
02463             error = 1;
02464             break;
02465          }
02466          c->priority++;
02467       } /* end while  - from here on we can use 'break' to go out */
02468       if (error)
02469          break;
02470 
02471       /* XXX we get here on non-existing extension or a keypress or hangup ? */
02472 
02473       if (!ast_exists_extension(c, c->context, c->exten, 1, c->cid.cid_num)) {
02474          /* If there is no match at priority 1, it is not a valid extension anymore.
02475           * Try to continue at "i", 1 or exit if the latter does not exist.
02476           */
02477          if (ast_exists_extension(c, c->context, "i", 1, c->cid.cid_num)) {
02478             if (option_verbose > 2)
02479                ast_verbose(VERBOSE_PREFIX_3 "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, c->name);
02480             pbx_builtin_setvar_helper(c, "INVALID_EXTEN", c->exten);
02481             set_ext_pri(c, "i", 1);
02482          } else {
02483             ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n",
02484                c->name, c->exten, c->context);
02485             error = 1; /* we know what to do with it */
02486             break;
02487          }
02488       } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) {
02489          /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */
02490          c->_softhangup = 0;
02491       } else { /* keypress received, get more digits for a full extension */
02492          int waittime = 0;
02493          if (digit)
02494             waittime = c->pbx->dtimeout;
02495          else if (!autofallthrough)
02496             waittime = c->pbx->rtimeout;
02497          if (!waittime) {
02498             const char *status = pbx_builtin_getvar_helper(c, "DIALSTATUS");
02499             if (!status)
02500                status = "UNKNOWN";
02501             if (option_verbose > 2)
02502                ast_verbose(VERBOSE_PREFIX_2 "Auto fallthrough, channel '%s' status is '%s'\n", c->name, status);
02503             if (!strcasecmp(status, "CONGESTION"))
02504                res = pbx_builtin_congestion(c, "10");
02505             else if (!strcasecmp(status, "CHANUNAVAIL"))
02506                res = pbx_builtin_congestion(c, "10");
02507             else if (!strcasecmp(status, "BUSY"))
02508                res = pbx_builtin_busy(c, "10");
02509             error = 1; /* XXX disable message */
02510             break;   /* exit from the 'for' loop */
02511          }
02512 
02513          if (collect_digits(c, waittime, dst_exten, sizeof(dst_exten), pos))
02514             break;
02515          if (ast_exists_extension(c, c->context, dst_exten, 1, c->cid.cid_num)) /* Prepare the next cycle */
02516             set_ext_pri(c, dst_exten, 1);
02517          else {
02518             /* No such extension */
02519             if (!ast_strlen_zero(dst_exten)) {
02520                /* An invalid extension */
02521                if (ast_exists_extension(c, c->context, "i", 1, c->cid.cid_num)) {
02522                   if (option_verbose > 2)
02523                      ast_verbose( VERBOSE_PREFIX_3 "Invalid extension '%s' in context '%s' on %s\n", dst_exten, c->context, c->name);
02524                   pbx_builtin_setvar_helper(c, "INVALID_EXTEN", dst_exten);
02525                   set_ext_pri(c, "i", 1);
02526                } else {
02527                   ast_log(LOG_WARNING, "Invalid extension '%s', but no rule 'i' in context '%s'\n", dst_exten, c->context);
02528                   found = 1; /* XXX disable message */
02529                   break;
02530                }
02531             } else {
02532                /* A simple timeout */
02533                if (ast_exists_extension(c, c->context, "t", 1, c->cid.cid_num)) {
02534                   if (option_verbose > 2)
02535                      ast_verbose( VERBOSE_PREFIX_3 "Timeout on %s\n", c->name);
02536                   set_ext_pri(c, "t", 1);
02537                } else {
02538                   ast_log(LOG_WARNING, "Timeout, but no rule 't' in context '%s'\n", c->context);
02539                   found = 1; /* XXX disable message */
02540                   break;
02541                }
02542             }
02543          }
02544          if (c->cdr) {
02545             if (option_verbose > 2)
02546                ast_verbose(VERBOSE_PREFIX_2 "CDR updated on %s\n",c->name);
02547             ast_cdr_update(c);
02548          }
02549       }
02550    }
02551    if (!found && !error)
02552       ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name);
02553    if (res != AST_PBX_KEEPALIVE)
02554       ast_softhangup(c, c->hangupcause ? c->hangupcause : AST_CAUSE_NORMAL_CLEARING);
02555    if ((res != AST_PBX_KEEPALIVE) && ast_exists_extension(c, c->context, "h", 1, c->cid.cid_num)) {
02556       if (c->cdr && ast_opt_end_cdr_before_h_exten)
02557          ast_cdr_end(c->cdr);
02558       set_ext_pri(c, "h", 1);
02559       while(ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) {
02560          if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num))) {
02561             /* Something bad happened, or a hangup has been requested. */
02562             if (option_debug)
02563                ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
02564             if (option_verbose > 1)
02565                ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
02566             break;
02567          }
02568          c->priority++;
02569       }
02570    }
02571    ast_set2_flag(c, autoloopflag, AST_FLAG_IN_AUTOLOOP);
02572 
02573    pbx_destroy(c->pbx);
02574    c->pbx = NULL;
02575    if (res != AST_PBX_KEEPALIVE)
02576       ast_hangup(c);
02577    return 0;
02578 }

static int _extension_match_core ( const char *  pattern,
const char *  data,
enum ext_match_t  mode 
) [static]

Definition at line 772 of file pbx.c.

References ast_log(), E_MATCH, E_MATCH_MASK, E_MATCHMORE, and LOG_WARNING.

Referenced by extension_match_core().

00773 {
00774    mode &= E_MATCH_MASK;   /* only consider the relevant bits */
00775 
00776    if ( (mode == E_MATCH) && (pattern[0] == '_') && (strcasecmp(pattern,data)==0) ) /* note: if this test is left out, then _x. will not match _x. !!! */
00777       return 1;
00778 
00779    if (pattern[0] != '_') { /* not a pattern, try exact or partial match */
00780       int ld = strlen(data), lp = strlen(pattern);
00781 
00782       if (lp < ld)      /* pattern too short, cannot match */
00783          return 0;
00784       /* depending on the mode, accept full or partial match or both */
00785       if (mode == E_MATCH)
00786          return !strcmp(pattern, data); /* 1 on match, 0 on fail */
00787       if (ld == 0 || !strncasecmp(pattern, data, ld)) /* partial or full match */
00788          return (mode == E_MATCHMORE) ? lp > ld : 1; /* XXX should consider '!' and '/' ? */
00789       else
00790          return 0;
00791    }
00792    pattern++; /* skip leading _ */
00793    /*
00794     * XXX below we stop at '/' which is a separator for the CID info. However we should
00795     * not store '/' in the pattern at all. When we insure it, we can remove the checks.
00796     */
00797    while (*data && *pattern && *pattern != '/') {
00798       const char *end;
00799 
00800       if (*data == '-') { /* skip '-' in data (just a separator) */
00801          data++;
00802          continue;
00803       }
00804       switch (toupper(*pattern)) {
00805       case '[':   /* a range */
00806          end = strchr(pattern+1, ']'); /* XXX should deal with escapes ? */
00807          if (end == NULL) {
00808             ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n");
00809             return 0;   /* unconditional failure */
00810          }
00811          for (pattern++; pattern != end; pattern++) {
00812             if (pattern+2 < end && pattern[1] == '-') { /* this is a range */
00813                if (*data >= pattern[0] && *data <= pattern[2])
00814                   break;   /* match found */
00815                else {
00816                   pattern += 2; /* skip a total of 3 chars */
00817                   continue;
00818                }
00819             } else if (*data == pattern[0])
00820                break;   /* match found */
00821          }
00822          if (pattern == end)
00823             return 0;
00824          pattern = end; /* skip and continue */
00825          break;
00826       case 'N':
00827          if (*data < '2' || *data > '9')
00828             return 0;
00829          break;
00830       case 'X':
00831          if (*data < '0' || *data > '9')
00832             return 0;
00833          break;
00834       case 'Z':
00835          if (*data < '1' || *data > '9')
00836             return 0;
00837          break;
00838       case '.':   /* Must match, even with more digits */
00839          return 1;
00840       case '!':   /* Early match */
00841          return 2;
00842       case ' ':
00843       case '-':   /* Ignore these in patterns */
00844          data--; /* compensate the final data++ */
00845          break;
00846       default:
00847          if (*data != *pattern)
00848             return 0;
00849       }
00850       data++;
00851       pattern++;
00852    }
00853    if (*data)        /* data longer than pattern, no match */
00854       return 0;
00855    /*
00856     * match so far, but ran off the end of the data.
00857     * Depending on what is next, determine match or not.
00858     */
00859    if (*pattern == '\0' || *pattern == '/')  /* exact match */
00860       return (mode == E_MATCHMORE) ? 0 : 1;  /* this is a failure for E_MATCHMORE */
00861    else if (*pattern == '!')        /* early match */
00862       return 2;
00863    else                 /* partial match */
00864       return (mode == E_MATCH) ? 0 : 1;   /* this is a failure for E_MATCH */
00865 }

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 4685 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().

04687 {
04688    struct ast_exten *ep;
04689 
04690    for (ep = NULL; e ; ep = e, e = e->peer) {
04691       if (e->priority >= tmp->priority)
04692          break;
04693    }
04694    if (!e) {   /* go at the end, and ep is surely set because the list is not empty */
04695       ep->peer = tmp;
04696       return 0;   /* success */
04697    }
04698    if (e->priority == tmp->priority) {
04699       /* Can't have something exactly the same.  Is this a
04700          replacement?  If so, replace, otherwise, bonk. */
04701       if (!replace) {
04702          ast_log(LOG_WARNING, "Unable to register extension '%s', priority %d in '%s', already in use\n", tmp->exten, tmp->priority, con->name);
04703          if (tmp->datad)
04704             tmp->datad(tmp->data);
04705          free(tmp);
04706          return -1;
04707       }
04708       /* we are replacing e, so copy the link fields and then update
04709        * whoever pointed to e to point to us
04710        */
04711       tmp->next = e->next; /* not meaningful if we are not first in the peer list */
04712       tmp->peer = e->peer; /* always meaningful */
04713       if (ep)        /* We're in the peer list, just insert ourselves */
04714          ep->peer = tmp;
04715       else if (el)      /* We're the first extension. Take over e's functions */
04716          el->next = tmp;
04717       else        /* We're the very first extension.  */
04718          con->root = tmp;
04719       if (tmp->priority == PRIORITY_HINT)
04720          ast_change_hint(e,tmp);
04721       /* Destroy the old one */
04722       if (e->datad)
04723          e->datad(e->data);
04724       free(e);
04725    } else { /* Slip ourselves in just before e */
04726       tmp->peer = e;
04727       tmp->next = e->next; /* extension chain, or NULL if e is not the first extension */
04728       if (ep)        /* Easy enough, we're just in the peer list */
04729          ep->peer = tmp;
04730       else {         /* we are the first in some peer list, so link in the ext list */
04731          if (el)
04732             el->next = tmp;   /* in the middle... */
04733          else
04734             con->root = tmp; /* ... or at the head */
04735          e->next = NULL;   /* e is no more at the head, so e->next must be reset */
04736       }
04737       /* And immediately return success. */
04738       if (tmp->priority == PRIORITY_HINT)
04739           ast_add_hint(tmp);
04740    }
04741    return 0;
04742 }

int ast_active_calls ( void   ) 

Retrieve the number of active calls.

Definition at line 2683 of file pbx.c.

References countcalls.

Referenced by handle_chanlist(), and handle_chanlist_deprecated().

02684 {
02685    return countcalls;
02686 }

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.

Parameters:
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
Return values:
0 success
-1 failure

Definition at line 4560 of file pbx.c.

References ast_add_extension2(), ast_unlock_contexts(), and find_context_locked().

Referenced by handle_context_add_extension(), handle_context_add_extension_deprecated(), park_add_hints(), and register_peer_exten().

04563 {
04564    int ret = -1;
04565    struct ast_context *c = find_context_locked(context);
04566 
04567    if (c) {
04568       ret = ast_add_extension2(c, replace, extension, priority, label, callerid,
04569          application, data, datad, registrar);
04570       ast_unlock_contexts();
04571    }
04572    return ret;
04573 }

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 4769 of file pbx.c.

References add_pri(), ast_exten::app, ast_add_hint(), ast_calloc, AST_LIST_FIRST, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), ast_exten::cidmatch, ast_exten::data, ast_exten::datad, el, errno, ext_cmp(), ext_strncpy(), ast_exten::exten, globals, ast_exten::label, ast_context::lock, LOG_DEBUG, ast_exten::matchcid, ast_exten::next, option_debug, option_verbose, ast_exten::parent, pbx_substitute_variables_varshead(), ast_exten::priority, PRIORITY_HINT, ast_exten::registrar, ast_context::root, ast_exten::stuff, VAR_BUF_SIZE, and VERBOSE_PREFIX_3.

Referenced by add_extensions(), ast_add_extension(), ast_autoanswer_login(), autoanswer_reregister_extensions(), do_parking_thread(), load_config(), park_call_full(), pbx_load_config(), pbx_load_users(), sla_build_station(), and sla_build_trunk().

04773 {
04774    /*
04775     * Sort extensions (or patterns) according to the rules indicated above.
04776     * These are implemented by the function ext_cmp()).
04777     * All priorities for the same ext/pattern/cid are kept in a list,
04778     * using the 'peer' field  as a link field..
04779     */
04780    struct ast_exten *tmp, *e, *el = NULL;
04781    int res;
04782    int length;
04783    char *p;
04784    char expand_buf[VAR_BUF_SIZE] = { 0, };
04785 
04786    /* if we are adding a hint, and there are global variables, and the hint
04787       contains variable references, then expand them
04788    */
04789    ast_mutex_lock(&globalslock);
04790    if (priority == PRIORITY_HINT && AST_LIST_FIRST(&globals) && strstr(application, "${")) {
04791       pbx_substitute_variables_varshead(&globals, application, expand_buf, sizeof(expand_buf));
04792       application = expand_buf;
04793    }
04794    ast_mutex_unlock(&globalslock);
04795 
04796    length = sizeof(struct ast_exten);
04797    length += strlen(extension) + 1;
04798    length += strlen(application) + 1;
04799    if (label)
04800       length += strlen(label) + 1;
04801    if (callerid)
04802       length += strlen(callerid) + 1;
04803    else
04804       length ++;  /* just the '\0' */
04805 
04806    /* Be optimistic:  Build the extension structure first */
04807    if (!(tmp = ast_calloc(1, length)))
04808       return -1;
04809 
04810    /* use p as dst in assignments, as the fields are const char * */
04811    p = tmp->stuff;
04812    if (label) {
04813       tmp->label = p;
04814       strcpy(p, label);
04815       p += strlen(label) + 1;
04816    }
04817    tmp->exten = p;
04818    p += ext_strncpy(p, extension, strlen(extension) + 1) + 1;
04819    tmp->priority = priority;
04820    tmp->cidmatch = p;   /* but use p for assignments below */
04821    if (callerid) {
04822       p += ext_strncpy(p, callerid, strlen(callerid) + 1) + 1;
04823       tmp->matchcid = 1;
04824    } else {
04825       *p++ = '\0';
04826       tmp->matchcid = 0;
04827    }
04828    tmp->app = p;
04829    strcpy(p, application);
04830    tmp->parent = con;
04831    tmp->data = data;
04832    tmp->datad = datad;
04833    tmp->registrar = registrar;
04834 
04835    ast_mutex_lock(&con->lock);
04836    res = 0; /* some compilers will think it is uninitialized otherwise */
04837    for (e = con->root; e; el = e, e = e->next) {   /* scan the extension list */
04838       res = ext_cmp(e->exten, extension);
04839       if (res == 0) { /* extension match, now look at cidmatch */
04840          if (!e->matchcid && !tmp->matchcid)
04841             res = 0;
04842          else if (tmp->matchcid && !e->matchcid)
04843             res = 1;
04844          else if (e->matchcid && !tmp->matchcid)
04845             res = -1;
04846          else
04847             res = strcasecmp(e->cidmatch, tmp->cidmatch);
04848       }
04849       if (res >= 0)
04850          break;
04851    }
04852    if (e && res == 0) { /* exact match, insert in the pri chain */
04853       res = add_pri(con, tmp, el, e, replace);
04854       ast_mutex_unlock(&con->lock);
04855       if (res < 0) {
04856          errno = EEXIST;   /* XXX do we care ? */
04857          return 0; /* XXX should we return -1 maybe ? */
04858       }
04859    } else {
04860       /*
04861        * not an exact match, this is the first entry with this pattern,
04862        * so insert in the main list right before 'e' (if any)
04863        */
04864       tmp->next = e;
04865       if (el)
04866          el->next = tmp;
04867       else
04868          con->root = tmp;
04869       ast_mutex_unlock(&con->lock);
04870       if (tmp->priority == PRIORITY_HINT)
04871          ast_add_hint(tmp);
04872    }
04873    if (option_debug) {
04874       if (tmp->matchcid) {
04875          if (option_debug)
04876             ast_log(LOG_DEBUG, "Added extension '%s' priority %d (CID match '%s') to %s\n",
04877                tmp->exten, tmp->priority, tmp->cidmatch, con->name);
04878       } else {
04879          if (option_debug)
04880             ast_log(LOG_DEBUG, "Added extension '%s' priority %d to %s\n",
04881                tmp->exten, tmp->priority, con->name);
04882       }
04883    }
04884    if (option_verbose > 2) {
04885       if (tmp->matchcid) {
04886          ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d (CID match '%s')to %s\n",
04887             tmp->exten, tmp->priority, tmp->cidmatch, con->name);
04888       } else {
04889          ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d to %s\n",
04890             tmp->exten, tmp->priority, con->name);
04891       }
04892    }
04893    return 0;
04894 }

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 2181 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().

02182 {
02183    struct ast_hint *hint;
02184 
02185    if (!e)
02186       return -1;
02187 
02188    AST_LIST_LOCK(&hints);
02189 
02190    /* Search if hint exists, do nothing */
02191    AST_LIST_TRAVERSE(&hints, hint, list) {
02192       if (hint->exten == e) {
02193          AST_LIST_UNLOCK(&hints);
02194          if (option_debug > 1)
02195             ast_log(LOG_DEBUG, "HINTS: Not re-adding existing hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e));
02196          return -1;
02197       }
02198    }
02199 
02200    if (option_debug > 1)
02201       ast_log(LOG_DEBUG, "HINTS: Adding hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e));
02202 
02203    if (!(hint = ast_calloc(1, sizeof(*hint)))) {
02204       AST_LIST_UNLOCK(&hints);
02205       return -1;
02206    }
02207    /* Initialize and insert new item at the top */
02208    hint->exten = e;
02209    hint->laststate = ast_extension_state2(e);
02210    AST_LIST_INSERT_HEAD(&hints, hint, list);
02211 
02212    AST_LIST_UNLOCK(&hints);
02213    return 0;
02214 }

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 4598 of file pbx.c.

References ast_channel::_state, ast_channel::amaflags, ast_cdr_discard(), ast_cdr_dup(), ast_channel_alloc(), ast_channel_lock, ast_channel_masquerade(), ast_channel_unlock, ast_do_masquerade(), ast_explicit_goto(), ast_hangup(), ast_log(), ast_pbx_start(), AST_SOFTHANGUP_ASYNCGOTO, ast_softhangup_nolock(), ast_channel::cdr, ast_channel::context, ast_channel::exten, LOG_WARNING, ast_channel::pbx, ast_channel::readformat, S_OR, and ast_channel::writeformat.

Referenced by __ast_goto_if_exists(), action_redirect(), ast_async_goto_by_name(), builtin_blindtransfer(), console_transfer(), console_transfer_deprecated(), handle_request_bye(), handle_request_refer(), process_ast_dsp(), socket_process(), and zt_handle_dtmfup().

04599 {
04600    int res = 0;
04601 
04602    ast_channel_lock(chan);
04603 
04604    if (chan->pbx) { /* This channel is currently in the PBX */
04605       ast_explicit_goto(chan, context, exten, priority);
04606       ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO);
04607    } else {
04608       /* In order to do it when the channel doesn't really exist within
04609          the PBX, we have to make a new channel, masquerade, and start the PBX
04610          at the new location */
04611       struct ast_channel *tmpchan = ast_channel_alloc(0, chan->_state, 0, 0, chan->accountcode, chan->exten, chan->context, chan->amaflags, "AsyncGoto/%s", chan->name);
04612       if (!tmpchan) {
04613          res = -1;
04614       } else {
04615          if (chan->cdr) {
04616             ast_cdr_discard(tmpchan->cdr);
04617             tmpchan->cdr = ast_cdr_dup(chan->cdr);  /* share the love */
04618          }
04619          /* Make formats okay */
04620          tmpchan->readformat = chan->readformat;
04621          tmpchan->writeformat = chan->writeformat;
04622          /* Setup proper location */
04623          ast_explicit_goto(tmpchan,
04624             S_OR(context, chan->context), S_OR(exten, chan->exten), priority);
04625 
04626          /* Masquerade into temp channel */
04627          ast_channel_masquerade(tmpchan, chan);
04628 
04629          /* Grab the locks and get going */
04630          ast_channel_lock(tmpchan);
04631          ast_do_masquerade(tmpchan);
04632          ast_channel_unlock(tmpchan);
04633          /* Start the PBX going on our stolen channel */
04634          if (ast_pbx_start(tmpchan)) {
04635             ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name);
04636             ast_hangup(tmpchan);
04637             res = -1;
04638          }
04639       }
04640    }
04641    ast_channel_unlock(chan);
04642    return res;
04643 }

int ast_async_goto_by_name ( const char *  channame,
const char *  context,
const char *  exten,
int  priority 
)

Definition at line 4645 of file pbx.c.

References ast_async_goto(), ast_channel_unlock, and ast_get_channel_by_name_locked().

04646 {
04647    struct ast_channel *chan;
04648    int res = -1;
04649 
04650    chan = ast_get_channel_by_name_locked(channame);
04651    if (chan) {
04652       res = ast_async_goto(chan, context, exten, priority);
04653       ast_channel_unlock(chan);
04654    }
04655    return res;
04656 }

int ast_async_goto_if_exists ( struct ast_channel chan,
const char *  context,
const char *  exten,
int  priority 
)

Note:
This function will handle locking the channel as needed.

Definition at line 6385 of file pbx.c.

References __ast_goto_if_exists().

Referenced by asyncgoto_exec().

06386 {
06387    return __ast_goto_if_exists(chan, context, exten, priority, 1);
06388 }

int ast_build_timing ( struct ast_timing i,
const char *  info_in 
)

Definition at line 4243 of file pbx.c.

References ast_strlen_zero(), ast_timing::daymask, days, ast_timing::dowmask, get_range(), get_timerange(), ast_timing::monthmask, months, and strsep().

Referenced by ast_context_add_include2(), iftime(), pbx_builtin_execiftime(), and pbx_builtin_gotoiftime().

04244 {
04245    char info_save[256];
04246    char *info;
04247 
04248    /* Check for empty just in case */
04249    if (ast_strlen_zero(info_in))
04250       return 0;
04251    /* make a copy just in case we were passed a static string */
04252    ast_copy_string(info_save, info_in, sizeof(info_save));
04253    info = info_save;
04254    /* Assume everything except time */
04255    i->monthmask = 0xfff;   /* 12 bits */
04256    i->daymask = 0x7fffffffU; /* 31 bits */
04257    i->dowmask = 0x7f; /* 7 bits */
04258    /* on each call, use strsep() to move info to the next argument */
04259    get_timerange(i, strsep(&info, "|"));
04260    if (info)
04261       i->dowmask = get_range(strsep(&info, "|"), 7, days, "day of week");
04262    if (info)
04263       i->daymask = get_range(strsep(&info, "|"), 31, NULL, "day");
04264    if (info)
04265       i->monthmask = get_range(strsep(&info, "|"), 12, months, "month");
04266    return 1;
04267 }

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.

Parameters:
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
Returns:
If "exten" *could be* a valid extension in this context with or without some more digits, return non-zero. Basically, when this returns 0, no matter what you add to exten, it's not going to be a valid extension anymore

Definition at line 2305 of file pbx.c.

References E_CANMATCH, and pbx_extension_helper().

Referenced by background_detect_exec(), cb_events(), dp_lookup(), dundi_lookup_local(), get_also_info(), get_destination(), handle_link_data(), handle_link_phone_dtmf(), local_dtmf_helper(), loopback_canmatch(), mgcp_ss(), phone_check_exception(), skinny_ss(), ss_thread(), and valid_exit().

02306 {
02307    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH);
02308 }

static int ast_change_hint ( struct ast_exten oe,
struct ast_exten ne 
) [static]

ast_change_hint: Change hint for an extension

Definition at line 2217 of file pbx.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, and ast_hint::exten.

Referenced by add_pri().

02218 {
02219    struct ast_hint *hint;
02220    int res = -1;
02221 
02222    AST_LIST_LOCK(&hints);
02223    AST_LIST_TRAVERSE(&hints, hint, list) {
02224       if (hint->exten == oe) {
02225             hint->exten = ne;
02226          res = 0;
02227          break;
02228       }
02229    }
02230    AST_LIST_UNLOCK(&hints);
02231 
02232    return res;
02233 }

int ast_check_timing ( const struct ast_timing i  ) 

Definition at line 4269 of file pbx.c.

References ast_localtime(), ast_log(), ast_timing::daymask, ast_timing::dowmask, LOG_WARNING, ast_timing::minmask, ast_timing::monthmask, and t.

Referenced by iftime(), include_valid(), pbx_builtin_execiftime(), and pbx_builtin_gotoiftime().

04270 {
04271    struct tm tm;
04272    time_t t = time(NULL);
04273 
04274    ast_localtime(&t, &tm, NULL);
04275 
04276    /* If it's not the right month, return */
04277    if (!(i->monthmask & (1 << tm.tm_mon)))
04278       return 0;
04279 
04280    /* If it's not that time of the month.... */
04281    /* Warning, tm_mday has range 1..31! */
04282    if (!(i->daymask & (1 << (tm.tm_mday-1))))
04283       return 0;
04284 
04285    /* If it's not the right day of the week */
04286    if (!(i->dowmask & (1 << tm.tm_wday)))
04287       return 0;
04288 
04289    /* Sanity check the hour just to be safe */
04290    if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) {
04291       ast_log(LOG_WARNING, "Insane time...\n");
04292       return 0;
04293    }
04294 
04295    /* Now the tough part, we calculate if it fits
04296       in the right time based on min/hour */
04297    if (!(i->minmask[tm.tm_hour] & (1 << (tm.tm_min / 2))))
04298       return 0;
04299 
04300    /* If we got this far, then we're good */
04301    return 1;
04302 }

int ast_context_add_ignorepat ( const char *  context,
const char *  ignorepat,
const char *  registrar 
)

Add an ignorepat.

Parameters:
context which context to add the ignorpattern to
ignorepat ignorepattern to set up for the extension
registrar registrar of the ignore pattern
Adds an ignore pattern to a particular context.

Return values:
0 on success
-1 on failure

Definition at line 4496 of file pbx.c.

References ast_context_add_ignorepat2(), ast_unlock_contexts(), and find_context_locked().

Referenced by handle_context_add_ignorepat(), and handle_context_add_ignorepat_deprecated().

04497 {
04498    int ret = -1;
04499    struct ast_context *c = find_context_locked(context);
04500 
04501    if (c) {
04502       ret = ast_context_add_ignorepat2(c, value, registrar);
04503       ast_unlock_contexts();
04504    }
04505    return ret;
04506 }

int ast_context_add_ignorepat2 ( struct ast_context con,
const char *  value,
const char *  registrar 
)

Definition at line 4508 of file pbx.c.

References ast_calloc, ast_mutex_lock(), ast_mutex_unlock(), errno, ast_context::ignorepats, ast_context::lock, ast_ignorepat::next, ast_ignorepat::pattern, and ast_ignorepat::registrar.

Referenced by ast_compile_ael2(), ast_context_add_ignorepat(), and pbx_load_config().

04509 {
04510    struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL;
04511    int length;
04512    length = sizeof(struct ast_ignorepat);
04513    length += strlen(value) + 1;
04514    if (!(ignorepat = ast_calloc(1, length)))
04515       return -1;
04516    /* The cast to char * is because we need to write the initial value.
04517     * The field is not supposed to be modified otherwise
04518     */
04519    strcpy((char *)ignorepat->pattern, value);
04520    ignorepat->next = NULL;
04521    ignorepat->registrar = registrar;
04522    ast_mutex_lock(&con->lock);
04523    for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) {
04524       ignorepatl = ignorepatc;
04525       if (!strcasecmp(ignorepatc->pattern, value)) {
04526          /* Already there */
04527          ast_mutex_unlock(&con->lock);
04528          errno = EEXIST;
04529          return -1;
04530       }
04531    }
04532    if (ignorepatl)
04533       ignorepatl->next = ignorepat;
04534    else
04535       con->ignorepats = ignorepat;
04536    ast_mutex_unlock(&con->lock);
04537    return 0;
04538 
04539 }

int ast_context_add_include ( const char *  context,
const char *  include,
const char *  registrar 
)

Add a context include.

Parameters:
context context to add include to
include new include to add
registrar who's registering it
Adds an include taking a char * string as the context parameter

Return values:
0 on success
-1 on error

Definition at line 4049 of file pbx.c.

References ast_context_add_include2(), ast_unlock_contexts(), and find_context_locked().

Referenced by handle_context_add_include(), and handle_context_add_include_deprecated().

04050 {
04051    int ret = -1;
04052    struct ast_context *c = find_context_locked(context);
04053 
04054    if (c) {
04055       ret = ast_context_add_include2(c, include, registrar);
04056       ast_unlock_contexts();
04057    }
04058    return ret;
04059 }

int ast_context_add_include2 ( struct ast_context con,
const char *  include,
const char *  registrar 
)

Add a context include.

Parameters:
con context to add the include to
include include to add
registrar who registered the context
Adds an include taking a struct ast_context as the first parameter

Return values:
0 on success
-1 on failure

Definition at line 4311 of file pbx.c.

References ast_build_timing(), ast_calloc, ast_get_context_name(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), errno, free, ast_include::hastime, ast_context::includes, ast_context::lock, ast_include::name, ast_include::next, option_verbose, ast_include::registrar, ast_include::rname, ast_include::stuff, ast_include::timing, and VERBOSE_PREFIX_3.

Referenced by ast_compile_ael2(), ast_context_add_include(), and pbx_load_config().

04313 {
04314    struct ast_include *new_include;
04315    char *c;
04316    struct ast_include *i, *il = NULL; /* include, include_last */
04317    int length;
04318    char *p;
04319 
04320    length = sizeof(struct ast_include);
04321    length += 2 * (strlen(value) + 1);
04322 
04323    /* allocate new include structure ... */
04324    if (!(new_include = ast_calloc(1, length)))
04325       return -1;
04326    /* Fill in this structure. Use 'p' for assignments, as the fields
04327     * in the structure are 'const char *'
04328     */
04329    p = new_include->stuff;
04330    new_include->name = p;
04331    strcpy(p, value);
04332    p += strlen(value) + 1;
04333    new_include->rname = p;
04334    strcpy(p, value);
04335    /* Strip off timing info, and process if it is there */
04336    if ( (c = strchr(p, '|')) ) {
04337       *c++ = '\0';
04338            new_include->hastime = ast_build_timing(&(new_include->timing), c);
04339    }
04340    new_include->next      = NULL;
04341    new_include->registrar = registrar;
04342 
04343    ast_mutex_lock(&con->lock);
04344 
04345    /* ... go to last include and check if context is already included too... */
04346    for (i = con->includes; i; i = i->next) {
04347       if (!strcasecmp(i->name, new_include->name)) {
04348          free(new_include);
04349          ast_mutex_unlock(&con->lock);
04350          errno = EEXIST;
04351          return -1;
04352       }
04353       il = i;
04354    }
04355 
04356    /* ... include new context into context list, unlock, return */
04357    if (il)
04358       il->next = new_include;
04359    else
04360       con->includes = new_include;
04361    if (option_verbose > 2)
04362       ast_verbose(VERBOSE_PREFIX_3 "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con));
04363    ast_mutex_unlock(&con->lock);
04364 
04365    return 0;
04366 }

int ast_context_add_switch ( const char *  context,
const char *  sw,
const char *  data,
int  eval,
const char *  registrar 
)

Add a switch.

Parameters:
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
This function registers a switch with the asterisk switch architecture

Return values:
0 on success
-1 on failure

Definition at line 4373 of file pbx.c.

References ast_context_add_switch2(), ast_unlock_contexts(), and find_context_locked().

04374 {
04375    int ret = -1;
04376    struct ast_context *c = find_context_locked(context);
04377 
04378    if (c) { /* found, add switch to this context */
04379       ret = ast_context_add_switch2(c, sw, data, eval, registrar);
04380       ast_unlock_contexts();
04381    }
04382    return ret;
04383 }

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).

Note:
See ast_context_add_switch() for argument information, with the exception of the first argument. In this case, it's a pointer to an ast_context structure as opposed to the name.

Definition at line 4392 of file pbx.c.

References ast_calloc, ast_get_context_name(), AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), ast_sw::data, errno, ast_sw::eval, free, ast_context::lock, ast_sw::name, option_verbose, ast_sw::registrar, and VERBOSE_PREFIX_3.

Referenced by ast_compile_ael2(), ast_context_add_switch(), and pbx_load_config().

04394 {
04395    struct ast_sw *new_sw;
04396    struct ast_sw *i;
04397    int length;
04398    char *p;
04399 
04400    length = sizeof(struct ast_sw);
04401    length += strlen(value) + 1;
04402    if (data)
04403       length += strlen(data);
04404    length++;
04405 
04406    /* allocate new sw structure ... */
04407    if (!(new_sw = ast_calloc(1, length)))
04408       return -1;
04409    /* ... fill in this structure ... */
04410    p = new_sw->stuff;
04411    new_sw->name = p;
04412    strcpy(new_sw->name, value);
04413    p += strlen(value) + 1;
04414    new_sw->data = p;
04415    if (data) {
04416       strcpy(new_sw->data, data);
04417       p += strlen(data) + 1;
04418    } else {
04419       strcpy(new_sw->data, "");
04420       p++;
04421    }
04422    new_sw->eval     = eval;
04423    new_sw->registrar = registrar;
04424 
04425    /* ... try to lock this context ... */
04426    ast_mutex_lock(&con->lock);
04427 
04428    /* ... go to last sw and check if context is already swd too... */
04429    AST_LIST_TRAVERSE(&con->alts, i, list) {
04430       if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) {
04431          free(new_sw);
04432          ast_mutex_unlock(&con->lock);
04433          errno = EEXIST;
04434          return -1;
04435       }
04436    }
04437 
04438    /* ... sw new context into context list, unlock, return */
04439    AST_LIST_INSERT_TAIL(&con->alts, new_sw, list);
04440 
04441    if (option_verbose > 2)
04442       ast_verbose(VERBOSE_PREFIX_3 "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con));
04443 
04444    ast_mutex_unlock(&con->lock);
04445 
04446    return 0;
04447 }

struct ast_context* ast_context_create ( struct ast_context **  extcontexts,
const char *  name,
const char *  registrar 
) [read]

Register a new context.

Parameters:
extcontexts pointer to the ast_context structure pointer
name name of the new context
registrar registrar of the context
This will first search for a context with your name. If it exists already, it will not create a new one. If it does not exist, it will create a new one with the given name and registrar.

Returns:
NULL on failure, and an ast_context structure on success

Definition at line 3919 of file pbx.c.

References __ast_context_create().

Referenced by ast_autoanswer_login(), ast_compile_ael2(), autoanswer_reregister_extensions(), do_parking_thread(), load_config(), park_call_full(), reload_config(), and set_config().

03920 {
03921    return __ast_context_create(extcontexts, name, registrar, 0);
03922 }

void ast_context_destroy ( struct ast_context con,
const char *  registrar 
)

Destroy a context (matches the specified context (or ANY context if NULL).

Parameters:
con context to destroy
registrar who registered it
You can optionally leave out either parameter. It will find it based on either the ast_context or the registrar name.

Returns:
nothing

Definition at line 5369 of file pbx.c.

References __ast_context_destroy(), ast_unlock_contexts(), and ast_wrlock_contexts().

Referenced by cleanup_stale_contexts(), sla_destroy(), and unload_module().

05370 {
05371    ast_wrlock_contexts();
05372    __ast_context_destroy(con,registrar);
05373    ast_unlock_contexts();
05374 }

struct ast_context* ast_context_find ( const char *  name  )  [read]

Find a context.

Parameters:
name name of the context to find
Will search for the context with the given name.

Returns:
the ast_context on success, NULL on failure.

Definition at line 895 of file pbx.c.

References ast_rdlock_contexts(), ast_unlock_contexts(), and ast_walk_contexts().

Referenced by _macro_exec(), ast_autoanswer_login(), ast_context_verify_includes(), ast_ignore_pattern(), autoanswer_reregister_extensions(), cleanup_stale_contexts(), do_autoanswer_thread(), do_parking_thread(), load_config(), park_call_full(), park_exec(), register_peer_exten(), reload_config(), and set_config().

00896 {
00897    struct ast_context *tmp = NULL;
00898 
00899    ast_rdlock_contexts();
00900 
00901    while ( (tmp = ast_walk_contexts(tmp)) ) {
00902       if (!name || !strcasecmp(name, tmp->name))
00903          break;
00904    }
00905 
00906    ast_unlock_contexts();
00907 
00908    return tmp;
00909 }

struct ast_context* ast_context_find_or_create ( struct ast_context **  extcontexts,
const char *  name,
const char *  registrar 
) [read]

Definition at line 3924 of file pbx.c.

References __ast_context_create().

Referenced by ast_compile_ael2(), pbx_load_config(), pbx_load_users(), sla_build_station(), and sla_build_trunk().

03925 {
03926    return __ast_context_create(extcontexts, name, registrar, 1);
03927 }

int ast_context_lockmacro ( const char *  context  ) 

locks the macrolock in the given given context

Note:
This function locks contexts list by &conlist, searches for the right context structure, and locks the macrolock mutex in that context. macrolock is used to limit a macro to be executed by one call at a time.

Definition at line 2920 of file pbx.c.

References ast_get_context_name(), ast_mutex_lock(), ast_rdlock_contexts(), ast_unlock_contexts(), and ast_walk_contexts().

Referenced by _macro_exec().

02921 {
02922    struct ast_context *c = NULL;
02923    int ret = -1;
02924 
02925    ast_rdlock_contexts();
02926 
02927    while ((c = ast_walk_contexts(c))) {
02928       if (!strcmp(ast_get_context_name(c), context)) {
02929          ret = 0;
02930          break;
02931       }
02932    }
02933 
02934    ast_unlock_contexts();
02935 
02936    /* if we found context, lock macrolock */
02937    if (ret == 0) 
02938       ret = ast_mutex_lock(&c->macrolock);
02939 
02940    return ret;
02941 }

int ast_context_remove_extension ( const char *  context,
const char *  extension,
int  priority,
const char *  registrar 
)

Simply remove extension from context.

Parameters:
context context to remove extension from
extension which extension to remove
priority priority of extension to remove
registrar registrar of the extension
This function removes an extension from a given context.

Return values:
0 on success
-1 on failure

Definition at line 2821 of file pbx.c.

References ast_context_remove_extension2(), ast_unlock_contexts(), and find_context_locked().

Referenced by destroy_station(), destroy_trunk(), handle_context_remove_extension(), handle_context_remove_extension_deprecated(), and register_peer_exten().

02822 {
02823    int ret = -1; /* default error return */
02824    struct ast_context *c = find_context_locked(context);
02825 
02826    if (c) { /* ... remove extension ... */
02827       ret = ast_context_remove_extension2(c, extension, priority, registrar);
02828       ast_unlock_contexts();
02829    }
02830    return ret;
02831 }

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.

Note:
When do you want to call this function, make sure that &conlock is locked, because some process can handle with your *con context before you lock it.

Definition at line 2843 of file pbx.c.

References ast_mutex_lock(), ast_mutex_unlock(), destroy_exten(), ast_exten::exten, exten, ast_context::lock, ast_exten::next, ast_exten::peer, ast_exten::registrar, and ast_context::root.

Referenced by ast_context_remove_extension(), do_autoanswer_thread(), do_parking_thread(), load_config(), and park_exec().

02844 {
02845    struct ast_exten *exten, *prev_exten = NULL;
02846    struct ast_exten *peer;
02847 
02848    ast_mutex_lock(&con->lock);
02849 
02850    /* scan the extension list to find matching extension-registrar */
02851    for (exten = con->root; exten; prev_exten = exten, exten = exten->next) {
02852       if (!strcmp(exten->exten, extension) &&
02853          (!registrar || !strcmp(exten->registrar, registrar)))
02854          break;
02855    }
02856    if (!exten) {
02857       /* we can't find right extension */
02858       ast_mutex_unlock(&con->lock);
02859       return -1;
02860    }
02861 
02862    /* should we free all peers in this extension? (priority == 0)? */
02863    if (priority == 0) {
02864       /* remove this extension from context list */
02865       if (prev_exten)
02866          prev_exten->next = exten->next;
02867       else
02868          con->root = exten->next;
02869 
02870       /* fire out all peers */
02871       while ( (peer = exten) ) {
02872          exten = peer->peer; /* prepare for next entry */
02873          destroy_exten(peer);
02874       }
02875    } else {
02876       /* scan the priority list to remove extension with exten->priority == priority */
02877       struct ast_exten *previous_peer = NULL;
02878 
02879       for (peer = exten; peer; previous_peer = peer, peer = peer->peer) {
02880          if (peer->priority == priority &&
02881                (!registrar || !strcmp(peer->registrar, registrar) ))
02882             break; /* found our priority */
02883       }
02884       if (!peer) { /* not found */
02885          ast_mutex_unlock(&con->lock);
02886          return -1;
02887       }
02888       /* we are first priority extension? */
02889       if (!previous_peer) {
02890          /*
02891           * We are first in the priority chain, so must update the extension chain.
02892           * The next node is either the next priority or the next extension
02893           */
02894          struct ast_exten *next_node = peer->peer ? peer->peer : peer->next;
02895 
02896          if (!prev_exten)  /* change the root... */
02897             con->root = next_node;
02898          else
02899             prev_exten->next = next_node; /* unlink */
02900          if (peer->peer)   /* XXX update the new head of the pri list */
02901             peer->peer->next = peer->next;
02902       } else { /* easy, we are not first priority in extension */
02903          previous_peer->peer = peer->peer;
02904       }
02905 
02906       /* now, free whole priority extension */
02907       destroy_exten(peer);
02908       /* XXX should we return -1 ? */
02909    }
02910    ast_mutex_unlock(&con->lock);
02911    return 0;
02912 }

int ast_context_remove_ignorepat ( const char *  context,
const char *  ignorepat,
const char *  registrar 
)

Definition at line 4453 of file pbx.c.

References ast_context_remove_ignorepat2(), ast_unlock_contexts(), and find_context_locked().

Referenced by handle_context_remove_ignorepat(), and handle_context_remove_ignorepat_deprecated().

04454 {
04455    int ret = -1;
04456    struct ast_context *c = find_context_locked(context);
04457 
04458    if (c) {
04459       ret = ast_context_remove_ignorepat2(c, ignorepat, registrar);
04460       ast_unlock_contexts();
04461    }
04462    return ret;
04463 }

int ast_context_remove_ignorepat2 ( struct ast_context con,
const char *  ignorepat,
const char *  registrar 
)

Definition at line 4465 of file pbx.c.

References ast_mutex_lock(), ast_mutex_unlock(), errno, free, ast_context::ignorepats, ast_context::lock, ast_ignorepat::next, ast_ignorepat::pattern, and ast_ignorepat::registrar.

Referenced by ast_context_remove_ignorepat().

04466 {
04467    struct ast_ignorepat *ip, *ipl = NULL;
04468 
04469    ast_mutex_lock(&con->lock);
04470 
04471    for (ip = con->ignorepats; ip; ip = ip->next) {
04472       if (!strcmp(ip->pattern, ignorepat) &&
04473          (!registrar || (registrar == ip->registrar))) {
04474          if (ipl) {
04475             ipl->next = ip->next;
04476             free(ip);
04477          } else {
04478             con->ignorepats = ip->next;
04479             free(ip);
04480          }
04481          ast_mutex_unlock(&con->lock);
04482          return 0;
04483       }
04484       ipl = ip;
04485    }
04486 
04487    ast_mutex_unlock(&con->lock);
04488    errno = EINVAL;
04489    return -1;
04490 }

int ast_context_remove_include ( const char *  context,
const char *  include,
const char *  registrar 
)

Remove a context include.

Note:
See ast_context_add_include for information on arguments
Return values:
0 on success
-1 on failure

Definition at line 2717 of file pbx.c.

References ast_context_remove_include2(), ast_unlock_contexts(), and find_context_locked().

Referenced by handle_context_dont_include_deprecated(), and handle_context_remove_include().

02718 {
02719    int ret = -1;
02720    struct ast_context *c = find_context_locked(context);
02721 
02722    if (c) {
02723       /* found, remove include from this context ... */
02724       ret = ast_context_remove_include2(c, include, registrar);
02725       ast_unlock_contexts();
02726    }
02727    return ret;
02728 }

int ast_context_remove_include2 ( struct ast_context con,
const char *  include,
const char *  registrar 
)

Removes an include by an ast_context structure.

Note:
See ast_context_add_include2 for information on arguments
Return values:
0 on success
-1 on success

Definition at line 2738 of file pbx.c.

References ast_mutex_lock(), ast_mutex_unlock(), free, ast_context::includes, ast_context::lock, ast_include::name, ast_include::next, and ast_include::registrar.

Referenced by ast_context_remove_include().

02739 {
02740    struct ast_include *i, *pi = NULL;
02741    int ret = -1;
02742 
02743    ast_mutex_lock(&con->lock);
02744 
02745    /* find our include */
02746    for (i = con->includes; i; pi = i, i = i->next) {
02747       if (!strcmp(i->name, include) &&
02748             (!registrar || !strcmp(i->registrar, registrar))) {
02749          /* remove from list */
02750          if (pi)
02751             pi->next = i->next;
02752          else
02753             con->includes = i->next;
02754          /* free include and return */
02755          free(i);
02756          ret = 0;
02757          break;
02758       }
02759    }
02760 
02761    ast_mutex_unlock(&con->lock);
02762    return ret;
02763 }

int ast_context_remove_switch ( const char *  context,
const char *  sw,
const char *  data,
const char *  registrar 
)

Remove a switch.

Note:
This function locks contexts list by &conlist, search for the rigt context structure, leave context list locked and call ast_context_remove_switch2 which removes switch, unlock contexts list and return ...

Definition at line 2770 of file pbx.c.

References ast_context_remove_switch2(), ast_unlock_contexts(), and find_context_locked().

02771 {
02772    int ret = -1; /* default error return */
02773    struct ast_context *c = find_context_locked(context);
02774 
02775    if (c) {
02776       /* remove switch from this context ... */
02777       ret = ast_context_remove_switch2(c, sw, data, registrar);
02778       ast_unlock_contexts();
02779    }
02780    return ret;
02781 }

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.

Note:
When we call this function, &conlock lock must be locked, because when we giving *con argument, some process can remove/change this context and after that there can be segfault.

Definition at line 2791 of file pbx.c.

References AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_mutex_lock(), ast_mutex_unlock(), ast_sw::data, free, ast_context::lock, ast_sw::name, and ast_sw::registrar.

Referenced by ast_context_remove_switch().

02792 {
02793    struct ast_sw *i;
02794    int ret = -1;
02795 
02796    ast_mutex_lock(&con->lock);
02797 
02798    /* walk switches */
02799    AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) {
02800       if (!strcmp(i->name, sw) && !strcmp(i->data, data) &&
02801          (!registrar || !strcmp(i->registrar, registrar))) {
02802          /* found, remove from list */
02803          AST_LIST_REMOVE_CURRENT(&con->alts, list);
02804          free(i); /* free switch and return */
02805          ret = 0;
02806          break;
02807       }
02808    }
02809    AST_LIST_TRAVERSE_SAFE_END
02810 
02811    ast_mutex_unlock(&con->lock);
02812 
02813    return ret;
02814 }

int ast_context_unlockmacro ( const char *  context  ) 

Unlocks the macrolock in the given context.

Note:
This function locks contexts list by &conlist, searches for the right context structure, and unlocks the macrolock mutex in that context. macrolock is used to limit a macro to be executed by one call at a time.

Definition at line 2948 of file pbx.c.

References ast_get_context_name(), ast_mutex_unlock(), ast_rdlock_contexts(), ast_unlock_contexts(), and ast_walk_contexts().

Referenced by _macro_exec().

02949 {
02950    struct ast_context *c = NULL;
02951    int ret = -1;
02952 
02953    ast_rdlock_contexts();
02954 
02955    while ((c = ast_walk_contexts(c))) {
02956       if (!strcmp(ast_get_context_name(c), context)) {
02957          ret = 0;
02958          break;
02959       }
02960    }
02961 
02962    ast_unlock_contexts();
02963 
02964    /* if we found context, unlock macrolock */
02965    if (ret == 0) 
02966       ret = ast_mutex_unlock(&c->macrolock);
02967 
02968    return ret;
02969 }

int ast_context_verify_includes ( struct ast_context con  ) 

Verifies includes in an ast_contect structure.

Parameters:
con context in which to verify the includes
Return values:
0 if no problems found
-1 if there were any missing context

Definition at line 6342 of file pbx.c.

References ast_context_find(), ast_get_context_name(), ast_log(), ast_walk_context_includes(), LOG_WARNING, and ast_include::rname.

Referenced by pbx_load_module().

06343 {
06344    struct ast_include *inc = NULL;
06345    int res = 0;
06346 
06347    while ( (inc = ast_walk_context_includes(con, inc)) ) {
06348       if (ast_context_find(inc->rname))
06349          continue;
06350 
06351       res = -1;
06352       ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n",
06353          ast_get_context_name(con), inc->rname);
06354       break;
06355    }
06356 
06357    return res;
06358 }

struct ast_custom_function* ast_custom_function_find ( const char *  name  )  [read]

Definition at line 1454 of file pbx.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, and ast_custom_function::name.

Referenced by ast_custom_function_register(), ast_func_read(), ast_func_write(), handle_show_function(), and handle_show_function_deprecated().

01455 {
01456    struct ast_custom_function *acf = NULL;
01457 
01458    AST_LIST_LOCK(&acf_root);
01459    AST_LIST_TRAVERSE(&acf_root, acf, acflist) {
01460       if (!strcmp(name, acf->name))
01461          break;
01462    }
01463    AST_LIST_UNLOCK(&acf_root);
01464 
01465    return acf;
01466 }

int ast_custom_function_register ( struct ast_custom_function acf  ) 

Reigster a custom function.

Definition at line 1490 of file pbx.c.

References ast_custom_function_find(), AST_LIST_INSERT_BEFORE_CURRENT, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), ast_verbose(), LOG_ERROR, ast_custom_function::name, option_verbose, and VERBOSE_PREFIX_2.

Referenced by load_module(), odbc_load_module(), and reload().

01491 {
01492    struct ast_custom_function *cur;
01493 
01494    if (!acf)
01495       return -1;
01496 
01497    AST_LIST_LOCK(&acf_root);
01498 
01499    if (ast_custom_function_find(acf->name)) {
01500       ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name);
01501       AST_LIST_UNLOCK(&acf_root);
01502       return -1;
01503    }
01504 
01505    /* Store in alphabetical order */
01506    AST_LIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) {
01507       if (strcasecmp(acf->name, cur->name) < 0) {
01508          AST_LIST_INSERT_BEFORE_CURRENT(&acf_root, acf, acflist);
01509          break;
01510       }
01511    }
01512    AST_LIST_TRAVERSE_SAFE_END
01513    if (!cur)
01514       AST_LIST_INSERT_TAIL(&acf_root, acf, acflist);
01515 
01516    AST_LIST_UNLOCK(&acf_root);
01517 
01518    if (option_verbose > 1)
01519       ast_verbose(VERBOSE_PREFIX_2 "Registered custom function %s\n", acf->name);
01520 
01521    return 0;
01522 }

int ast_custom_function_unregister ( struct ast_custom_function acf  ) 

Unregister a custom function.

Definition at line 1468 of file pbx.c.

References AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_verbose(), ast_custom_function::name, option_verbose, and VERBOSE_PREFIX_2.

Referenced by odbc_unload_module(), reload(), and unload_module().

01469 {
01470    struct ast_custom_function *cur;
01471 
01472    if (!acf)
01473       return -1;
01474 
01475    AST_LIST_LOCK(&acf_root);
01476    AST_LIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) {
01477       if (cur == acf) {
01478          AST_LIST_REMOVE_CURRENT(&acf_root, acflist);
01479          if (option_verbose > 1)
01480             ast_verbose(VERBOSE_PREFIX_2 "Unregistered custom function %s\n", acf->name);
01481          break;
01482       }
01483    }
01484    AST_LIST_TRAVERSE_SAFE_END
01485    AST_LIST_UNLOCK(&acf_root);
01486 
01487    return acf ? 0 : -1;
01488 }

int ast_exists_extension ( struct ast_channel c,
const char *  context,
const char *  exten,
int  priority,
const char *  callerid 
)

Determine whether an extension exists.

Parameters:
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
Returns:
If an extension within the given context(or callerid) with the given priority is found a non zero value will be returned. Otherwise, 0 is returned.

Definition at line 2290 of file pbx.c.

References E_MATCH, and pbx_extension_helper().

Referenced by __ast_goto_if_exists(), __ast_pbx_run(), __login_exec(), _macro_exec(), agentmonitoroutgoing_exec(), answer_call(), ast_app_dtget(), ast_pbx_outgoing_exten_uniqueid(), 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(), park_call_full(), 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().

02291 {
02292    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH);
02293 }

int ast_explicit_goto ( struct ast_channel chan,
const char *  context,
const char *  exten,
int  priority 
)

Note:
This function will handle locking the channel as needed.

Definition at line 4575 of file pbx.c.

References ast_channel_lock, ast_channel_unlock, AST_FLAG_IN_AUTOLOOP, ast_strlen_zero(), ast_test_flag, ast_channel::context, ast_channel::exten, and ast_channel::priority.

Referenced by __ast_goto_if_exists(), ast_async_goto(), ast_parseable_goto(), builtin_atxfer(), disa_exec(), do_bridge_masquerade(), and handle_setpriority().

04576 {
04577    if (!chan)
04578       return -1;
04579 
04580    ast_channel_lock(chan);
04581 
04582    if (!ast_strlen_zero(context))
04583       ast_copy_string(chan->context, context, sizeof(chan->context));
04584    if (!ast_strlen_zero(exten))
04585       ast_copy_string(chan->exten, exten, sizeof(chan->exten));
04586    if (priority > -1) {
04587       chan->priority = priority;
04588       /* see flag description in channel.h for explanation */
04589       if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP))
04590          chan->priority--;
04591    }
04592 
04593    ast_channel_unlock(chan);
04594 
04595    return 0;
04596 }

int ast_extension_close ( const char *  pattern,
const char *  data,
int  needmore 
)

Definition at line 888 of file pbx.c.

References ast_log(), E_CANMATCH, E_MATCHMORE, extension_match_core(), and LOG_WARNING.

Referenced by realtime_switch_common().

00889 {
00890    if (needmore != E_MATCHMORE && needmore != E_CANMATCH)
00891       ast_log(LOG_WARNING, "invalid argument %d\n", needmore);
00892    return extension_match_core(pattern, data, needmore);
00893 }

int ast_extension_match ( const char *  pattern,
const char *  extension 
)

Determine if a given extension matches a given pattern (in NXX format).

Parameters:
pattern pattern to match
extension extension to check against the pattern.
Checks whether or not the given extension matches the given pattern.

Return values:
1 on match
0 on failure

Definition at line 883 of file pbx.c.

References E_MATCH, and extension_match_core().

Referenced by ast_ignore_pattern(), do_say(), find_matching_priority(), loopback_canmatch(), loopback_exists(), loopback_matchmore(), matchcid(), misdn_cfg_is_msn_valid(), realtime_switch_common(), and show_dialplan_helper().

00884 {
00885    return extension_match_core(pattern, data, E_MATCH);
00886 }

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 2014 of file pbx.c.

References ast_extension_state2(), and ast_hint_extension().

Referenced by action_extensionstate(), and handle_request_subscribe().

02015 {
02016    struct ast_exten *e;
02017 
02018    e = ast_hint_extension(c, context, exten);   /* Do we have a hint for this extension ? */
02019    if (!e)
02020       return -1;           /* No hint, return -1 */
02021 
02022    return ast_extension_state2(e);        /* Check all devices in the hint */
02023 }

static int ast_extension_state2 ( struct ast_exten e  )  [static]

ast_extensions_state2: Check state of extension by using hints

Definition at line 1917 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().

01918 {
01919    char hint[AST_MAX_EXTENSION];
01920    char *cur, *rest;
01921    int allunavailable = 1, allbusy = 1, allfree = 1, allonhold = 1;
01922    int busy = 0, inuse = 0, ring = 0;
01923 
01924    if (!e)
01925       return -1;
01926 
01927    ast_copy_string(hint, ast_get_extension_app(e), sizeof(hint));
01928 
01929    rest = hint;   /* One or more devices separated with a & character */
01930    while ( (cur = strsep(&rest, "&")) ) {
01931       int res = ast_device_state(cur);
01932       switch (res) {
01933       case AST_DEVICE_NOT_INUSE:
01934          allunavailable = 0;
01935          allbusy = 0;
01936          allonhold = 0;
01937          break;
01938       case AST_DEVICE_INUSE:
01939          inuse = 1;
01940          allunavailable = 0;
01941          allfree = 0;
01942          allonhold = 0;
01943          break;
01944       case AST_DEVICE_RINGING:
01945          ring = 1;
01946          allunavailable = 0;
01947          allfree = 0;
01948          allonhold = 0;
01949          break;
01950       case AST_DEVICE_RINGINUSE:
01951          inuse = 1;
01952          ring = 1;
01953          allunavailable = 0;
01954          allfree = 0;
01955          allonhold = 0;
01956          break;
01957       case AST_DEVICE_ONHOLD:
01958          allunavailable = 0;
01959          allfree = 0;
01960          break;
01961       case AST_DEVICE_BUSY:
01962          allunavailable = 0;
01963          allfree = 0;
01964          allonhold = 0;
01965          busy = 1;
01966          break;
01967       case AST_DEVICE_UNAVAILABLE:
01968       case AST_DEVICE_INVALID:
01969          allbusy = 0;
01970          allfree = 0;
01971          allonhold = 0;
01972          break;
01973       default:
01974          allunavailable = 0;
01975          allbusy = 0;
01976          allfree = 0;
01977          allonhold = 0;
01978       }
01979    }
01980 
01981    if (!inuse && ring)
01982       return AST_EXTENSION_RINGING;
01983    if (inuse && ring)
01984       return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING);
01985    if (inuse)
01986       return AST_EXTENSION_INUSE;
01987    if (allfree)
01988       return AST_EXTENSION_NOT_INUSE;
01989    if (allonhold)
01990       return AST_EXTENSION_ONHOLD;
01991    if (allbusy)
01992       return AST_EXTENSION_BUSY;
01993    if (allunavailable)
01994       return AST_EXTENSION_UNAVAILABLE;
01995    if (busy)
01996       return AST_EXTENSION_INUSE;
01997 
01998    return AST_EXTENSION_NOT_INUSE;
01999 }

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 2002 of file pbx.c.

References extension_states, and cfextension_states::text.

Referenced by __sip_show_channels(), cb_extensionstate(), handle_request_subscribe(), and handle_show_hints().

02003 {
02004    int i;
02005 
02006    for (i = 0; (i < (sizeof(extension_states) / sizeof(extension_states[0]))); i++) {
02007       if (extension_states[i].extension_state == extension_state)
02008          return extension_states[i].text;
02009    }
02010    return "Unknown";
02011 }

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 2069 of file pbx.c.

References ast_calloc, ast_hint_extension(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_state_cb::callback, ast_hint::callbacks, ast_state_cb::data, ast_hint::exten, ast_state_cb::id, ast_state_cb::next, statecbs, and stateid.

Referenced by handle_request_subscribe(), init_manager(), and load_module().

02071 {
02072    struct ast_hint *hint;
02073    struct ast_state_cb *cblist;
02074    struct ast_exten *e;
02075 
02076    /* If there's no context and extension:  add callback to statecbs list */
02077    if (!context && !exten) {
02078       AST_LIST_LOCK(&hints);
02079 
02080       for (cblist = statecbs; cblist; cblist = cblist->next) {
02081          if (cblist->callback == callback) {
02082             cblist->data = data;
02083             AST_LIST_UNLOCK(&hints);
02084             return 0;
02085          }
02086       }
02087 
02088       /* Now insert the callback */
02089       if (!(cblist = ast_calloc(1, sizeof(*cblist)))) {
02090          AST_LIST_UNLOCK(&hints);
02091          return -1;
02092       }
02093       cblist->id = 0;
02094       cblist->callback = callback;
02095       cblist->data = data;
02096 
02097       cblist->next = statecbs;
02098       statecbs = cblist;
02099 
02100       AST_LIST_UNLOCK(&hints);
02101       return 0;
02102    }
02103 
02104    if (!context || !exten)
02105       return -1;
02106 
02107    /* This callback type is for only one hint, so get the hint */
02108    e = ast_hint_extension(NULL, context, exten);
02109    if (!e) {
02110       return -1;
02111    }
02112 
02113    /* Find the hint in the list of hints */
02114    AST_LIST_LOCK(&hints);
02115 
02116    AST_LIST_TRAVERSE(&hints, hint, list) {
02117       if (hint->exten == e)
02118          break;
02119    }
02120 
02121    if (!hint) {
02122       /* We have no hint, sorry */
02123       AST_LIST_UNLOCK(&hints);
02124       return -1;
02125    }
02126 
02127    /* Now insert the callback in the callback list  */
02128    if (!(cblist = ast_calloc(1, sizeof(*cblist)))) {
02129       AST_LIST_UNLOCK(&hints);
02130       return -1;
02131    }
02132    cblist->id = stateid++;    /* Unique ID for this callback */
02133    cblist->callback = callback;  /* Pointer to callback routine */
02134    cblist->data = data;    /* Data for the callback */
02135 
02136    cblist->next = hint->callbacks;
02137    hint->callbacks = cblist;
02138 
02139    AST_LIST_UNLOCK(&hints);
02140    return cblist->id;
02141 }

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 2144 of file pbx.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_hint::callbacks, free, ast_state_cb::next, and statecbs.

Referenced by __sip_destroy(), and handle_request_subscribe().

02145 {
02146    struct ast_state_cb **p_cur = NULL; /* address of pointer to us */
02147    int ret = -1;
02148 
02149    if (!id && !callback)
02150       return -1;
02151 
02152    AST_LIST_LOCK(&hints);
02153 
02154    if (!id) {  /* id == 0 is a callback without extension */
02155       for (p_cur = &statecbs; *p_cur; p_cur = &(*p_cur)->next) {
02156          if ((*p_cur)->callback == callback)
02157             break;
02158       }
02159    } else { /* callback with extension, find the callback based on ID */
02160       struct ast_hint *hint;
02161       AST_LIST_TRAVERSE(&hints, hint, list) {
02162          for (p_cur = &hint->callbacks; *p_cur; p_cur = &(*p_cur)->next) {
02163             if ((*p_cur)->id == id)
02164                break;
02165          }
02166          if (*p_cur) /* found in the inner loop */
02167             break;
02168       }
02169    }
02170    if (p_cur && *p_cur) {
02171       struct ast_state_cb *cur = *p_cur;
02172       *p_cur = cur->next;
02173       free(cur);
02174       ret = 0;
02175    }
02176    AST_LIST_UNLOCK(&hints);
02177    return ret;
02178 }

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.

Parameters:
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
Returns:
the priority which matches the given label in the extension or -1 if not found.

Definition at line 2295 of file pbx.c.

References E_FINDLABEL, and pbx_extension_helper().

Referenced by action_originate(), action_redirect(), ast_parseable_goto(), asyncgoto_exec(), and handle_setpriority().

02296 {
02297    return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL);
02298 }

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.

Note:
This function is the same as ast_findlabel_extension, except that it accepts a pointer to an ast_context structure to specify the context instead of the name of the context. Otherwise, the functions behave the same.

Definition at line 2300 of file pbx.c.

References E_FINDLABEL, and pbx_extension_helper().

Referenced by pbx_load_config().

02301 {
02302    return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL);
02303 }

int ast_func_read ( struct ast_channel chan,
char *  function,
char *  workspace,
size_t  len 
)

executes a read operation on a function

Parameters:
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
This application executes a function in read mode on a given channel.

Returns:
zero on success, non-zero on failure

Definition at line 1544 of file pbx.c.

References ast_custom_function_find(), ast_log(), func_args(), LOG_ERROR, and ast_custom_function::read.

Referenced by action_getvar(), handle_getvariable(), and pbx_substitute_variables_helper_full().

01545 {
01546    char *args = func_args(function);
01547    struct ast_custom_function *acfptr = ast_custom_function_find(function);
01548 
01549    if (acfptr == NULL)
01550       ast_log(LOG_ERROR, "Function %s not registered\n", function);
01551    else if (!acfptr->read)
01552       ast_log(LOG_ERROR, "Function %s cannot be read\n", function);
01553    else
01554       return acfptr->read(chan, function, args, workspace, len);
01555    return -1;
01556 }

int ast_func_write ( struct ast_channel chan,
char *  function,
const char *  value 
)

executes a write operation on a function

Parameters:
chan Channel to execute on
function Data containing the function call string (will be modified)
value A value parameter to pass for writing
This application executes a function in write mode on a given channel.

Returns:
zero on success, non-zero on failure

Definition at line 1558 of file pbx.c.

References ast_custom_function_find(), ast_log(), func_args(), LOG_ERROR, and ast_custom_function::write.

Referenced by pbx_builtin_pushvar_helper(), and pbx_builtin_setvar_helper().

01559 {
01560    char *args = func_args(function);
01561    struct ast_custom_function *acfptr = ast_custom_function_find(function);
01562 
01563    if (acfptr == NULL)
01564       ast_log(LOG_ERROR, "Function %s not registered\n", function);
01565    else if (!acfptr->write)
01566       ast_log(LOG_ERROR, "Function %s cannot be written to\n", function);
01567    else
01568       return acfptr->write(chan, function, args, value);
01569 
01570    return -1;
01571 }

const char* ast_get_context_name ( struct ast_context con  ) 

const char* ast_get_context_registrar ( struct ast_context c  ) 

Definition at line 6237 of file pbx.c.

References ast_context::registrar.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06238 {
06239    return c ? c->registrar : NULL;
06240 }

const char* ast_get_extension_app ( struct ast_exten e  ) 

void* ast_get_extension_app_data ( struct ast_exten e  ) 

Definition at line 6272 of file pbx.c.

References ast_exten::data.

Referenced by _macro_exec(), ast_get_hint(), handle_save_dialplan(), and print_ext().

06273 {
06274    return e ? e->data : NULL;
06275 }

const char* ast_get_extension_cidmatch ( struct ast_exten e  ) 

Definition at line 6262 of file pbx.c.

References ast_exten::cidmatch.

Referenced by find_matching_priority(), and handle_save_dialplan().

06263 {
06264    return e ? e->cidmatch : NULL;
06265 }

struct ast_context* ast_get_extension_context ( struct ast_exten exten  )  [read]

Definition at line 6204 of file pbx.c.

References ast_exten::parent.

Referenced by handle_show_hints().

06205 {
06206    return exten ? exten->parent : NULL;
06207 }

const char* ast_get_extension_label ( struct ast_exten exten  ) 

Definition at line 6214 of file pbx.c.

References ast_exten::label.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06215 {
06216    return exten ? exten->label : NULL;
06217 }

int ast_get_extension_matchcid ( struct ast_exten e  ) 

Definition at line 6257 of file pbx.c.

References ast_exten::matchcid.

Referenced by find_matching_priority(), and handle_save_dialplan().

06258 {
06259    return e ? e->matchcid : 0;
06260 }

const char* ast_get_extension_name ( struct ast_exten exten  ) 

int ast_get_extension_priority ( struct ast_exten exten  ) 

Definition at line 6229 of file pbx.c.

References ast_exten::priority.

Referenced by complete_context_remove_extension(), complete_context_remove_extension_deprecated(), find_matching_priority(), handle_save_dialplan(), and print_ext().

06230 {
06231    return exten ? exten->priority : -1;
06232 }

const char* ast_get_extension_registrar ( struct ast_exten e  ) 

Definition at line 6242 of file pbx.c.

References ast_exten::registrar.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06243 {
06244    return e ? e->registrar : NULL;
06245 }

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 2273 of file pbx.c.

References ast_get_extension_app(), ast_get_extension_app_data(), and ast_hint_extension().

Referenced by action_extensionstate(), get_cid_name(), get_destination(), manager_state_cb(), pbx_retrieve_variable(), and transmit_state_notify().

02274 {
02275    struct ast_exten *e = ast_hint_extension(c, context, exten);
02276 
02277    if (e) {
02278       if (hint)
02279          ast_copy_string(hint, ast_get_extension_app(e), hintsize);
02280       if (name) {
02281          const char *tmp = ast_get_extension_app_data(e);
02282          if (tmp)
02283             ast_copy_string(name, tmp, namesize);
02284       }
02285       return -1;
02286    }
02287    return 0;
02288 }

const char* ast_get_ignorepat_name ( struct ast_ignorepat ip  ) 

Definition at line 6224 of file pbx.c.

References ast_ignorepat::pattern.

Referenced by complete_context_remove_ignorepat(), complete_context_remove_ignorepat_deprecated(), handle_save_dialplan(), lookup_c_ip(), and show_dialplan_helper().

06225 {
06226    return ip ? ip->pattern : NULL;
06227 }

const char* ast_get_ignorepat_registrar ( struct ast_ignorepat ip  ) 

Definition at line 6252 of file pbx.c.

References ast_ignorepat::registrar.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06253 {
06254    return ip ? ip->registrar : NULL;
06255 }

const char* ast_get_include_name ( struct ast_include inc  ) 

Definition at line 6219 of file pbx.c.

References ast_include::name.

Referenced by complete_context_dont_include_deprecated(), complete_context_remove_include(), find_matching_priority(), handle_save_dialplan(), lookup_ci(), and show_dialplan_helper().

06220 {
06221    return inc ? inc->name : NULL;
06222 }

const char* ast_get_include_registrar ( struct ast_include i  ) 

Definition at line 6247 of file pbx.c.

References ast_include::registrar.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06248 {
06249    return i ? i->registrar : NULL;
06250 }

const char* ast_get_switch_data ( struct ast_sw sw  ) 

Definition at line 6282 of file pbx.c.

References ast_sw::data.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06283 {
06284    return sw ? sw->data : NULL;
06285 }

const char* ast_get_switch_name ( struct ast_sw sw  ) 

Definition at line 6277 of file pbx.c.

References ast_sw::name.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06278 {
06279    return sw ? sw->name : NULL;
06280 }

const char* ast_get_switch_registrar ( struct ast_sw sw  ) 

Definition at line 6287 of file pbx.c.

References ast_sw::registrar.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06288 {
06289    return sw ? sw->registrar : NULL;
06290 }

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 
) [static, read]

ast_hint_extension: Find hint for given extension in context

Definition at line 1904 of file pbx.c.

References ast_rdlock_contexts(), ast_unlock_contexts(), E_MATCH, pbx_find_extension(), PRIORITY_HINT, and pbx_find_info::stacklen.

Referenced by ast_extension_state(), ast_extension_state_add(), and ast_get_hint().

01905 {
01906    struct ast_exten *e;
01907    struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */
01908 
01909    ast_rdlock_contexts();
01910    e = pbx_find_extension(c, NULL, &q, context, exten, PRIORITY_HINT, NULL, "", E_MATCH);
01911    ast_unlock_contexts();
01912 
01913    return e;
01914 }

void ast_hint_state_changed ( const char *  device,
char *  cid_num,
char *  cid_name 
)

Definition at line 2025 of file pbx.c.

References ast_extension_state2(), ast_get_extension_app(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, AST_MAX_EXTENSION, ast_state_cb::callback, ast_hint::callbacks, ast_state_cb::data, ast_exten::exten, ast_hint::exten, ast_hint::laststate, ast_state_cb::next, ast_exten::parent, parse(), statecbs, and strsep().

Referenced by do_state_change().

02026 {
02027    struct ast_hint *hint;
02028 
02029    AST_LIST_LOCK(&hints);
02030 
02031    AST_LIST_TRAVERSE(&hints, hint, list) {
02032       struct ast_state_cb *cblist;
02033       char buf[AST_MAX_EXTENSION];
02034       char *parse = buf;
02035       char *cur;
02036       int state;
02037 
02038       ast_copy_string(buf, ast_get_extension_app(hint->exten), sizeof(buf));
02039       while ( (cur = strsep(&parse, "&")) ) {
02040          if (!strcasecmp(cur, device))
02041             break;
02042       }
02043       if (!cur)
02044          continue;
02045 
02046       /* Get device state for this hint */
02047       state = ast_extension_state2(hint->exten);
02048 
02049       if ((state == -1) || (state == hint->laststate))
02050          continue;
02051 
02052       /* Device state changed since last check - notify the watchers */
02053 
02054       /* For general callbacks */
02055       for (cblist = statecbs; cblist; cblist = cblist->next)
02056          cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data, cid_num, cid_name);
02057 
02058       /* For extension callbacks */
02059       for (cblist = hint->callbacks; cblist; cblist = cblist->next)
02060          cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data, cid_num, cid_name);
02061 
02062       hint->laststate = state;   /* record we saw the change */
02063    }
02064 
02065    AST_LIST_UNLOCK(&hints);
02066 }

int ast_ignore_pattern ( const char *  context,
const char *  pattern 
)

Checks to see if a number should be ignored.

Parameters:
context context to search within
pattern to check whether it should be ignored or not
Check if a number should be ignored with respect to dialtone cancellation.

Return values:
0 if the pattern should not be ignored
non-zero if the pattern should be ignored

Definition at line 4541 of file pbx.c.

References ast_context_find(), ast_extension_match(), ast_context::ignorepats, ast_ignorepat::next, and ast_ignorepat::pattern.

Referenced by ast_app_dtget(), disa_exec(), dp_lookup(), dundi_lookup_local(), handle_enbloc_call_message(), handle_soft_key_event_message(), handle_stimulus_message(), mgcp_ss(), skinny_ss(), and ss_thread().

04542 {
04543    struct ast_context *con = ast_context_find(context);
04544    if (con) {
04545       struct ast_ignorepat *pat;
04546       for (pat = con->ignorepats; pat; pat = pat->next) {
04547          if (ast_extension_match(pat->pattern, pattern))
04548             return 1;
04549       }
04550    }
04551 
04552    return 0;
04553 }

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.

Parameters:
con context to lock
Return values:
0 on success
-1 on failure

Definition at line 6186 of file pbx.c.

References ast_mutex_lock(), and ast_context::lock.

Referenced by _macro_exec(), complete_context_dont_include_deprecated(), complete_context_remove_ignorepat(), complete_context_remove_ignorepat_deprecated(), complete_context_remove_include(), dundi_precache_full(), find_matching_endwhile(), handle_save_dialplan(), lookup_c_ip(), lookup_ci(), and show_dialplan_helper().

06187 {
06188    return ast_mutex_lock(&con->lock);
06189 }

int ast_lock_contexts ( void   ) 

Locks the context list.

Return values:
0 on success
-1 on error

Definition at line 6163 of file pbx.c.

References ast_rwlock_wrlock().

Referenced by find_matching_endwhile().

06164 {
06165    return ast_rwlock_wrlock(&conlock);
06166 }

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).

Parameters:
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
Returns:
If "exten" *could match* a valid extension in this context with some more digits, return non-zero. Does NOT return non-zero if this is an exact-match only. Basically, when this returns 0, no matter what you add to exten, it's not going to be a valid extension anymore

Definition at line 2310 of file pbx.c.

References E_MATCHMORE, and pbx_extension_helper().

Referenced by ast_app_dtget(), collect_digits(), disa_exec(), dp_lookup(), dundi_lookup_local(), handle_stimulus_message(), loopback_matchmore(), mgcp_ss(), skinny_ss(), and ss_thread().

02311 {
02312    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE);
02313 }

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.

Parameters:
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 3942 of file pbx.c.

References __ast_context_destroy(), ast_calloc, AST_EXTENSION_REMOVED, AST_LIST_HEAD_INIT_VALUE, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_unlock_contexts(), ast_wrlock_contexts(), ast_state_cb::callback, ast_hint::callbacks, context, contexts, ast_state_cb::data, E_MATCH, ast_exten::exten, ast_hint::exten, exten, free, ast_hint::laststate, LOG_DEBUG, LOG_WARNING, ast_state_cb::next, ast_context::next, option_debug, ast_exten::parent, pbx_find_extension(), PRIORITY_HINT, ast_context::registrar, and pbx_find_info::stacklen.

Referenced by pbx_load_module().

03943 {
03944    struct ast_context *tmp, *lasttmp = NULL;
03945    struct store_hints store = AST_LIST_HEAD_INIT_VALUE;
03946    struct store_hint *this;
03947    struct ast_hint *hint;
03948    struct ast_exten *exten;
03949    int length;
03950    struct ast_state_cb *thiscb, *prevcb;
03951 
03952    /* it is very important that this function hold the hint list lock _and_ the conlock
03953       during its operation; not only do we need to ensure that the list of contexts
03954       and extensions does not change, but also that no hint callbacks (watchers) are
03955       added or removed during the merge/delete process
03956 
03957       in addition, the locks _must_ be taken in this order, because there are already
03958       other code paths that use this order
03959    */
03960    ast_wrlock_contexts();
03961    AST_LIST_LOCK(&hints);
03962 
03963    /* preserve all watchers for hints associated with this registrar */
03964    AST_LIST_TRAVERSE(&hints, hint, list) {
03965       if (hint->callbacks && !strcmp(registrar, hint->exten->parent->registrar)) {
03966          length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2 + sizeof(*this);
03967          if (!(this = ast_calloc(1, length)))
03968             continue;
03969          this->callbacks = hint->callbacks;
03970          hint->callbacks = NULL;
03971          this->laststate = hint->laststate;
03972          this->context = this->data;
03973          strcpy(this->data, hint->exten->parent->name);
03974          this->exten = this->data + strlen(this->context) + 1;
03975          strcpy(this->exten, hint->exten->exten);
03976          AST_LIST_INSERT_HEAD(&store, this, list);
03977       }
03978    }
03979 
03980    tmp = *extcontexts;
03981    if (registrar) {
03982       /* XXX remove previous contexts from same registrar */
03983       if (option_debug)
03984          ast_log(LOG_DEBUG, "must remove any reg %s\n", registrar);
03985       __ast_context_destroy(NULL,registrar);
03986       while (tmp) {
03987          lasttmp = tmp;
03988          tmp = tmp->next;
03989       }
03990    } else {
03991       /* XXX remove contexts with the same name */
03992       while (tmp) {
03993          ast_log(LOG_WARNING, "must remove %s  reg %s\n", tmp->name, tmp->registrar);
03994          __ast_context_destroy(tmp,tmp->registrar);
03995          lasttmp = tmp;
03996          tmp = tmp->next;
03997       }
03998    }
03999    if (lasttmp) {
04000       lasttmp->next = contexts;
04001       contexts = *extcontexts;
04002       *extcontexts = NULL;
04003    } else
04004       ast_log(LOG_WARNING, "Requested contexts didn't get merged\n");
04005 
04006    /* restore the watchers for hints that can be found; notify those that
04007       cannot be restored
04008    */
04009    while ((this = AST_LIST_REMOVE_HEAD(&store, list))) {
04010       struct pbx_find_info q = { .stacklen = 0 };
04011       exten = pbx_find_extension(NULL, NULL, &q, this->context, this->exten, PRIORITY_HINT, NULL, "", E_MATCH);
04012       /* Find the hint in the list of hints */
04013       AST_LIST_TRAVERSE(&hints, hint, list) {
04014          if (hint->exten == exten)
04015             break;
04016       }
04017       if (!exten || !hint) {
04018          /* this hint has been removed, notify the watchers */
04019          prevcb = NULL;
04020          thiscb = this->callbacks;
04021          while (thiscb) {
04022             prevcb = thiscb;
04023             thiscb = thiscb->next;
04024             prevcb->callback(this->context, this->exten, AST_EXTENSION_REMOVED, prevcb->data, NULL, NULL);
04025             free(prevcb);
04026             }
04027       } else {
04028          thiscb = this->callbacks;
04029          while (thiscb->next)
04030             thiscb = thiscb->next;
04031          thiscb->next = hint->callbacks;
04032          hint->callbacks = this->callbacks;
04033          hint->laststate = this->laststate;
04034       }
04035       free(this);
04036    }
04037 
04038    AST_LIST_UNLOCK(&hints);
04039    ast_unlock_contexts();
04040 
04041    return;
04042 }

AST_MUTEX_DEFINE_STATIC ( maxcalllock   ) 

AST_MUTEX_DEFINE_STATIC ( globalslock   ) 

int ast_parseable_goto ( struct ast_channel chan,
const char *  goto_string 
)

Note:
I can find neither parsable nor parseable at dictionary.com, but google gives me 169000 hits for parseable and only 49,800 for parsable

This function will handle locking the channel as needed.

Definition at line 6390 of file pbx.c.

References ast_cdr_update(), ast_explicit_goto(), ast_findlabel_extension(), ast_log(), ast_strdupa, ast_strlen_zero(), ast_channel::cid, ast_callerid::cid_num, ast_channel::context, ast_channel::exten, exten, LOG_WARNING, ast_channel::priority, and strsep().

Referenced by _while_exec(), check_goto_on_transfer(), gosub_exec(), ivr_dispatch(), pbx_builtin_goto(), random_exec(), return_exec(), and while_continue_exec().

06391 {
06392    char *exten, *pri, *context;
06393    char *stringp;
06394    int ipri;
06395    int mode = 0;
06396 
06397    if (ast_strlen_zero(goto_string)) {
06398       ast_log(LOG_WARNING, "Goto requires an argument (optional context|optional extension|priority)\n");
06399       return -1;
06400    }
06401    stringp = ast_strdupa(goto_string);
06402    context = strsep(&stringp, "|"); /* guaranteed non-null */
06403    exten = strsep(&stringp, "|");
06404    pri = strsep(&stringp, "|");
06405    if (!exten) {  /* Only a priority in this one */
06406       pri = context;
06407       exten = NULL;
06408       context = NULL;
06409    } else if (!pri) {   /* Only an extension and priority in this one */
06410       pri = exten;
06411       exten = context;
06412       context = NULL;
06413    }
06414    if (*pri == '+') {
06415       mode = 1;
06416       pri++;
06417    } else if (*pri == '-') {
06418       mode = -1;
06419       pri++;
06420    }
06421    if (sscanf(pri, "%d", &ipri) != 1) {
06422       if ((ipri = ast_findlabel_extension(chan, context ? context : chan->context, exten ? exten : chan->exten,
06423          pri, chan->cid.cid_num)) < 1) {
06424          ast_log(LOG_WARNING, "Priority '%s' must be a number > 0, or valid label\n", pri);
06425          return -1;
06426       } else
06427          mode = 0;
06428    }
06429    /* At this point we have a priority and maybe an extension and a context */
06430 
06431    if (mode)
06432       ipri = chan->priority + (ipri * mode);
06433 
06434    ast_explicit_goto(chan, context, exten, ipri);
06435    ast_cdr_update(chan);
06436    return 0;
06437 
06438 }

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 5306 of file pbx.c.

References ast_pbx_outgoing_app_uniqueid().

Referenced by attempt_thread(), and orig_app().

05307 {
05308     return ast_pbx_outgoing_app_uniqueid(type, format, data, timeout, app, appdata, reason, sync, 0, cid_num, cid_name, vars, account, locked_channel, NULL);
05309 }

int ast_pbx_outgoing_app_uniqueid ( const char *  type,
int  format,
void *  data,
int  timeout,
const char *  app,
const char *  appdata,
int *  reason,
int  sync,
int  callingpres,
const char *  cid_num,
const char *  cid_name,
struct ast_variable vars,
const char *  account,
struct ast_channel **  locked_channel,
char *  uniqueid 
)

Synchronously or asynchronously make an outbound call and send it to a particular application with given extension (extended version with callinpres and uniqueid)

Definition at line 5165 of file pbx.c.

References __ast_request_and_dial_uniqueid(), ast_channel::_state, outgoing_helper::account, async_stat::app, app_tmp::app, async_stat::appdata, ast_calloc, ast_cdr_alloc(), ast_cdr_disposition(), ast_cdr_failed(), ast_cdr_init(), ast_cdr_setaccount(), ast_cdr_start(), ast_channel_lock, ast_channel_unlock, ast_hangup(), ast_log(), ast_pbx_outgoing_cdr_failed(), ast_pbx_run_app(), ast_pthread_create, ast_set_variables(), AST_STATE_UP, ast_strlen_zero(), ast_variables_destroy(), ast_verbose(), async_wait(), ast_channel::cdr, async_stat::chan, app_tmp::chan, app_tmp::data, errno, free, ast_channel::hangupcause, LOG_WARNING, option_verbose, async_stat::p, ast_channel::pbx, app_tmp::t, async_stat::timeout, outgoing_helper::vars, and VERBOSE_PREFIX_4.

Referenced by action_originate(), ast_pbx_outgoing_app(), and fast_originate().

05166 {
05167    struct ast_channel *chan;
05168    struct app_tmp *tmp;
05169    int res = -1, cdr_res = -1;
05170    struct outgoing_helper oh;
05171    pthread_attr_t attr;
05172 
05173    memset(&oh, 0, sizeof(oh));
05174    oh.vars = vars;
05175    oh.account = account;
05176 
05177    if (locked_channel)
05178       *locked_channel = NULL;
05179    if (ast_strlen_zero(app)) {
05180       res = -1;
05181       goto outgoing_app_cleanup;
05182    }
05183    if (sync) {
05184       chan = __ast_request_and_dial_uniqueid(type, format, data, timeout, reason, callingpres, cid_num, cid_name, &oh, uniqueid);
05185       if (chan) {
05186          if (!chan->cdr) { /* check if the channel already has a cdr record, if not give it one */
05187             chan->cdr = ast_cdr_alloc();   /* allocate a cdr for the channel */
05188             if(!chan->cdr) {
05189                /* allocation of the cdr failed */
05190                free(chan->pbx);
05191                res = -1;
05192                goto outgoing_app_cleanup;
05193             }
05194             /* allocation of the cdr was successful */
05195             ast_cdr_init(chan->cdr, chan);  /* initilize our channel's cdr */
05196             ast_cdr_start(chan->cdr);
05197          }
05198          ast_set_variables(chan, vars);
05199          if (account)
05200             ast_cdr_setaccount(chan, account);
05201          if (chan->_state == AST_STATE_UP) {
05202             res = 0;
05203             if (option_verbose > 3)
05204                ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", chan->name);
05205             tmp = ast_calloc(1, sizeof(*tmp));
05206             if (!tmp)
05207                res = -1;
05208             else {
05209                ast_copy_string(tmp->app, app, sizeof(tmp->app));
05210                if (appdata)
05211                   ast_copy_string(tmp->data, appdata, sizeof(tmp->data));
05212                tmp->chan = chan;
05213                if (sync > 1) {
05214                   if (locked_channel)
05215                      ast_channel_unlock(chan);
05216                   ast_pbx_run_app(tmp);
05217                } else {
05218                   pthread_attr_init(&attr);
05219                   pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
05220                   if (locked_channel)
05221                      ast_channel_lock(chan);
05222                   if (ast_pthread_create(&tmp->t, &attr, ast_pbx_run_app, tmp)) {
05223                      ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno));
05224                      free(tmp);
05225                      if (locked_channel)
05226                         ast_channel_unlock(chan);
05227                      ast_hangup(chan);
05228                      res = -1;
05229                   } else {
05230                      if (locked_channel)
05231                         *locked_channel = chan;
05232                   }
05233                   pthread_attr_destroy(&attr);
05234                }
05235             }
05236          } else {
05237             if (option_verbose > 3)
05238                ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", chan->name);
05239             if (chan->cdr) { /* update the cdr */
05240                /* here we update the status of the call, which sould be busy.
05241                 * if that fails then we set the status to failed */
05242                if (ast_cdr_disposition(chan->cdr, chan->hangupcause))
05243                   ast_cdr_failed(chan->cdr);
05244             }
05245             ast_hangup(chan);
05246          }
05247       }
05248 
05249       if (res < 0) { /* the call failed for some reason */
05250          if (*reason == 0) { /* if the call failed (not busy or no answer)
05251                         * update the cdr with the failed message */
05252             cdr_res = ast_pbx_outgoing_cdr_failed();
05253             if (cdr_res != 0) {
05254                res = cdr_res;
05255                goto outgoing_app_cleanup;
05256             }
05257          }
05258       }
05259 
05260    } else {
05261       struct async_stat *as;
05262       if (!(as = ast_calloc(1, sizeof(*as)))) {
05263          res = -1;
05264          goto outgoing_app_cleanup;
05265       }
05266       chan = __ast_request_and_dial_uniqueid(type, format, data, timeout, reason, callingpres, cid_num, cid_name, &oh, uniqueid);
05267       if (!chan) {
05268          free(as);
05269          res = -1;
05270          goto outgoing_app_cleanup;
05271       }
05272       as->chan = chan;
05273       ast_copy_string(as->app, app, sizeof(as->app));
05274       if (appdata)
05275          ast_copy_string(as->appdata,  appdata, sizeof(as->appdata));
05276       as->timeout = timeout;
05277       ast_set_variables(chan, vars);
05278       if (account)
05279          ast_cdr_setaccount(chan, account);
05280       /* Start a new thread, and get something handling this channel. */
05281       pthread_attr_init(&attr);
05282       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
05283       if (locked_channel)
05284          ast_channel_lock(chan);
05285       if (ast_pthread_create(&as->p, &attr, async_wait, as)) {
05286          ast_log(LOG_WARNING, "Failed to start async wait\n");
05287          free(as);
05288          if (locked_channel)
05289             ast_channel_unlock(chan);
05290          ast_hangup(chan);
05291          res = -1;
05292          pthread_attr_destroy(&attr);
05293          goto outgoing_app_cleanup;
05294       } else {
05295          if (locked_channel)
05296             *locked_channel = chan;
05297       }
05298       pthread_attr_destroy(&attr);
05299       res = 0;
05300    }
05301 outgoing_app_cleanup:
05302    ast_variables_destroy(vars);
05303    return res;
05304 }

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 4970 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_uniqueid(), and ast_pbx_outgoing_exten_uniqueid().

04971 {
04972    /* allocate a channel */
04973    struct ast_channel *chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, 0);
04974 
04975    if (!chan)
04976       return -1;  /* failure */
04977 
04978    if (!chan->cdr) {
04979       /* allocation of the cdr failed */
04980       ast_channel_free(chan);   /* free the channel */
04981       return -1;                /* return failure */
04982    }
04983 
04984    /* allocation of the cdr was successful */
04985    ast_cdr_init(chan->cdr, chan);  /* initilize our channel's cdr */
04986    ast_cdr_start(chan->cdr);       /* record the start and stop time */
04987    ast_cdr_end(chan->cdr);
04988    ast_cdr_failed(chan->cdr);      /* set the status to failed */
04989    ast_cdr_detach(chan->cdr);      /* post and free the record */
04990    ast_channel_free(chan);         /* free the channel */
04991 
04992    return 0;  /* success */
04993 }

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 5137 of file pbx.c.

References ast_pbx_outgoing_exten_uniqueid().

Referenced by attempt_thread(), and orig_exten().

05138 {
05139     return ast_pbx_outgoing_exten_uniqueid(type, format, data, timeout, context, exten, priority, reason, sync, 0, cid_num, cid_name, vars, account, channel, NULL);
05140 }

int ast_pbx_outgoing_exten_uniqueid ( const char *  type,
int  format,
void *  data,
int  timeout,
const char *  context,
const char *  exten,
int  priority,
int *  reason,
int  sync,
int  callingpres,
const char *  cid_num,
const char *  cid_name,
struct ast_variable vars,
const char *  account,
struct ast_channel **  locked_channel,
char *  uniqueid 
)

Synchronously or asynchronously make an outbound call and send it to a particular extension (extended version with callinpres and uniqueid)

Definition at line 4995 of file pbx.c.

References __ast_request_and_dial_uniqueid(), ast_channel::_state, ast_calloc, ast_cdr_disposition(), ast_cdr_failed(), ast_cdr_setaccount(), ast_channel_alloc(), ast_channel_lock, ast_channel_unlock, ast_exists_extension(), ast_hangup(), ast_log(), ast_pbx_outgoing_cdr_failed(), ast_pbx_run(), ast_pbx_start(), ast_pthread_create, ast_request_and_dial_uniqueid(), ast_set_variables(), AST_STATE_DOWN, AST_STATE_UP, ast_strlen_zero(), ast_variables_destroy(), ast_verbose(), async_wait(), ast_channel::cdr, async_stat::chan, async_stat::context, ast_channel::context, free, ast_channel::hangupcause, LOAD_OH, LOG_ERROR, LOG_WARNING, option_verbose, async_stat::p, pbx_builtin_setvar_helper(), set_ext_pri(), async_stat::timeout, and VERBOSE_PREFIX_4.

Referenced by action_originate(), ast_pbx_outgoing_exten(), and fast_originate().

04996 {
04997    struct ast_channel *chan;
04998    struct async_stat *as;
04999    int res = -1, cdr_res = -1;
05000    struct outgoing_helper oh;
05001    pthread_attr_t attr;
05002 
05003    if (sync) {
05004       LOAD_OH(oh);
05005       chan = __ast_request_and_dial_uniqueid(type, format, data, timeout, reason, callingpres, cid_num, cid_name, &oh, uniqueid);
05006       if (channel) {
05007          *channel = chan;
05008          if (chan)
05009             ast_channel_lock(chan);
05010       }
05011       if (chan) {
05012          if (chan->_state == AST_STATE_UP) {
05013                res = 0;
05014             if (option_verbose > 3)
05015                ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", chan->name);
05016 
05017             if (sync > 1) {
05018                if (channel)
05019                   ast_channel_unlock(chan);
05020                if (ast_pbx_run(chan)) {
05021                   ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name);
05022                   if (channel)
05023                      *channel = NULL;
05024                   ast_hangup(chan);
05025                   chan = NULL;
05026                   res = -1;
05027                }
05028             } else {
05029                if (ast_pbx_start(chan)) {
05030                   ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name);
05031                   if (channel) {
05032                      *channel = NULL;
05033                      ast_channel_unlock(chan);
05034                   }
05035                   ast_hangup(chan);
05036                   res = -1;
05037                }
05038                chan = NULL;
05039             }
05040          } else {
05041             if (option_verbose > 3)
05042                ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", chan->name);
05043 
05044             if (chan->cdr) { /* update the cdr */
05045                /* here we update the status of the call, which sould be busy.
05046                 * if that fails then we set the status to failed */
05047                if (ast_cdr_disposition(chan->cdr, chan->hangupcause))
05048                   ast_cdr_failed(chan->cdr);
05049             }
05050 
05051             if (channel) {
05052                *channel = NULL;
05053                ast_channel_unlock(chan);
05054             }
05055             ast_hangup(chan);
05056             chan = NULL;
05057          }
05058       }
05059 
05060       if (res < 0) { /* the call failed for some reason */
05061          if (*reason == 0) { /* if the call failed (not busy or no answer)
05062                         * update the cdr with the failed message */
05063             cdr_res = ast_pbx_outgoing_cdr_failed();
05064             if (cdr_res != 0) {
05065                res = cdr_res;
05066                goto outgoing_exten_cleanup;
05067             }
05068          }
05069 
05070          /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */
05071          /* check if "failed" exists */
05072          if (ast_exists_extension(chan, context, "failed", 1, NULL)) {
05073             chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "OutgoingSpoolFailed");
05074             if (chan) {
05075                char failed_reason[4] = "";
05076                if (!ast_strlen_zero(context))
05077                   ast_copy_string(chan->context, context, sizeof(chan->context));
05078                set_ext_pri(chan, "failed", 1);
05079                ast_set_variables(chan, vars);
05080                snprintf(failed_reason, sizeof(failed_reason), "%d", *reason);
05081                pbx_builtin_setvar_helper(chan, "REASON", failed_reason);
05082                if (account)
05083                   ast_cdr_setaccount(chan, account);
05084                if (ast_pbx_run(chan)) {
05085                   ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name);
05086                   ast_hangup(chan);
05087                }
05088                chan = NULL;
05089             }
05090          }
05091       }
05092    } else {
05093       if (!(as = ast_calloc(1, sizeof(*as)))) {
05094          res = -1;
05095          goto outgoing_exten_cleanup;
05096       }
05097       chan = ast_request_and_dial_uniqueid(type, format, data, timeout, reason, callingpres, cid_num, cid_name, uniqueid);
05098       if (channel) {
05099          *channel = chan;
05100          if (chan)
05101             ast_channel_lock(chan);
05102       }
05103       if (!chan) {
05104          free(as);
05105          res = -1;
05106          goto outgoing_exten_cleanup;
05107       }
05108       as->chan = chan;
05109       ast_copy_string(as->context, context, sizeof(as->context));
05110       set_ext_pri(as->chan,  exten, priority);
05111       as->timeout = timeout;
05112       ast_set_variables(chan, vars);
05113       if (account)
05114          ast_cdr_setaccount(chan, account);
05115       pthread_attr_init(&attr);
05116       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
05117       if (ast_pthread_create(&as->p, &attr, async_wait, as)) {
05118          ast_log(LOG_WARNING, "Failed to start async wait\n");
05119          free(as);
05120          if (channel) {
05121             *channel = NULL;
05122             ast_channel_unlock(chan);
05123          }
05124          ast_hangup(chan);
05125          res = -1;
05126          pthread_attr_destroy(&attr);
05127          goto outgoing_exten_cleanup;
05128       }
05129       pthread_attr_destroy(&attr);
05130       res = 0;
05131    }
05132 outgoing_exten_cleanup:
05133    ast_variables_destroy(vars);
05134    return res;
05135 }

enum ast_pbx_result ast_pbx_run ( struct ast_channel c  ) 

Execute the PBX in the current thread.

Parameters:
c channel to run the pbx on
This executes the PBX on a given channel. It allocates a new PBX structure for the channel, and provides all PBX functionality. See ast_pbx_start for an asynchronous function to run the PBX in a new thread as opposed to the current one.

Returns:
Zero on success, non-zero on failure

Definition at line 2670 of file pbx.c.

References __ast_pbx_run(), AST_PBX_CALL_LIMIT, AST_PBX_SUCCESS, decrease_call_count(), and increase_call_count().

Referenced by ast_pbx_outgoing_exten_uniqueid(), async_wait(), mgcp_ss(), skinny_newcall(), and ss_thread().

02671 {
02672    enum ast_pbx_result res = AST_PBX_SUCCESS;
02673 
02674    if (increase_call_count(c))
02675       return AST_PBX_CALL_LIMIT;
02676 
02677    res = __ast_pbx_run(c);
02678    decrease_call_count();
02679 
02680    return res;
02681 }

static void* ast_pbx_run_app ( void *  data  )  [static]

run the application and free the descriptor once done

Definition at line 5149 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_uniqueid().

05150 {
05151    struct app_tmp *tmp = data;
05152    struct ast_app *app;
05153    app = pbx_findapp(tmp->app);
05154    if (app) {
05155       if (option_verbose > 3)
05156          ast_verbose(VERBOSE_PREFIX_4 "Launching %s(%s) on %s\n", tmp->app, tmp->data, tmp->chan->name);
05157       pbx_exec(tmp->chan, app, tmp->data);
05158    } else
05159       ast_log(LOG_WARNING, "No such application '%s'\n", tmp->app);
05160    ast_hangup(tmp->chan);
05161    free(tmp);
05162    return NULL;
05163 }

enum ast_pbx_result ast_pbx_start ( struct ast_channel c  ) 

Create a new thread and start the PBX.

Parameters:
c channel to start the pbx on
See ast_pbx_run for a synchronous function to run the PBX in the current thread, as opposed to starting a new one.

Returns:
Zero on success, non-zero on failure

Definition at line 2644 of file pbx.c.

References ast_log(), AST_PBX_CALL_LIMIT, AST_PBX_FAILED, AST_PBX_SUCCESS, ast_pthread_create, increase_call_count(), LOG_WARNING, pbx_thread(), and t.

Referenced by __oh323_new(), alsa_new(), ast_async_goto(), ast_bridge_call_thread(), ast_iax2_new(), ast_pbx_outgoing_exten_uniqueid(), bridge_exec(), 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().

02645 {
02646    pthread_t t;
02647    pthread_attr_t attr;
02648 
02649    if (!c) {
02650       ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
02651       return AST_PBX_FAILED;
02652    }
02653 
02654    if (increase_call_count(c))
02655       return AST_PBX_CALL_LIMIT;
02656 
02657    /* Start a new thread, and get something handling this channel. */
02658    pthread_attr_init(&attr);
02659    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
02660    if (ast_pthread_create(&t, &attr, pbx_thread, c)) {
02661       ast_log(LOG_WARNING, "Failed to create new channel thread\n");
02662       pthread_attr_destroy(&attr);
02663       return AST_PBX_FAILED;
02664    }
02665    pthread_attr_destroy(&attr);
02666 
02667    return AST_PBX_SUCCESS;
02668 }

int ast_rdlock_contexts ( void   ) 

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 2972 of file pbx.c.

References ast_calloc, AST_LIST_INSERT_BEFORE_CURRENT, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), ast_verbose(), COLOR_BRCYAN, ast_app::description, ast_app::execute, LOG_WARNING, option_verbose, ast_app::synopsis, term_color(), and VERBOSE_PREFIX_2.

Referenced by load_module(), and load_pbx().

02973 {
02974    struct ast_app *tmp, *cur = NULL;
02975    char tmps[80];
02976    int length;
02977 
02978    AST_LIST_LOCK(&apps);
02979    AST_LIST_TRAVERSE(&apps, tmp, list) {
02980       if (!strcasecmp(app, tmp->name)) {
02981          ast_log(LOG_WARNING, "Already have an application '%s'\n", app);
02982          AST_LIST_UNLOCK(&apps);
02983          return -1;
02984       }
02985    }
02986 
02987    length = sizeof(*tmp) + strlen(app) + 1;
02988 
02989    if (!(tmp = ast_calloc(1, length))) {
02990       AST_LIST_UNLOCK(&apps);
02991       return -1;
02992    }
02993 
02994    strcpy(tmp->name, app);
02995    tmp->execute = execute;
02996    tmp->synopsis = synopsis;
02997    tmp->description = description;
02998 
02999    /* Store in alphabetical order */
03000    AST_LIST_TRAVERSE_SAFE_BEGIN(&apps, cur, list) {
03001       if (strcasecmp(tmp->name, cur->name) < 0) {
03002          AST_LIST_INSERT_BEFORE_CURRENT(&apps, tmp, list);
03003          break;
03004       }
03005    }
03006    AST_LIST_TRAVERSE_SAFE_END
03007    if (!cur)
03008       AST_LIST_INSERT_TAIL(&apps, tmp, list);
03009 
03010    if (option_verbose > 1)
03011       ast_verbose( VERBOSE_PREFIX_2 "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps)));
03012 
03013    AST_LIST_UNLOCK(&apps);
03014 
03015    return 0;
03016 }

int ast_register_switch ( struct ast_switch sw  ) 

Register an alternative dialplan switch.

Parameters:
sw switch to register
This function registers a populated ast_switch structure with the asterisk switching architecture.

Returns:
0 on success, and other than 0 on failure

Definition at line 3022 of file pbx.c.

References AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), LOG_WARNING, and ast_switch::name.

Referenced by load_module().

03023 {
03024    struct ast_switch *tmp;
03025 
03026    AST_LIST_LOCK(&switches);
03027    AST_LIST_TRAVERSE(&switches, tmp, list) {
03028       if (!strcasecmp(tmp->name, sw->name)) {
03029          AST_LIST_UNLOCK(&switches);
03030          ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name);
03031          return -1;
03032       }
03033    }
03034    AST_LIST_INSERT_TAIL(&switches, sw, list);
03035    AST_LIST_UNLOCK(&switches);
03036 
03037    return 0;
03038 }

static int ast_remove_hint ( struct ast_exten e  )  [static]

ast_remove_hint: Remove hint from extension

Definition at line 2236 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().

02237 {
02238    /* Cleanup the Notifys if hint is removed */
02239    struct ast_hint *hint;
02240    struct ast_state_cb *cblist, *cbprev;
02241    int res = -1;
02242 
02243    if (!e)
02244       return -1;
02245 
02246    AST_LIST_LOCK(&hints);
02247    AST_LIST_TRAVERSE_SAFE_BEGIN(&hints, hint, list) {
02248       if (hint->exten == e) {
02249          cbprev = NULL;
02250          cblist = hint->callbacks;
02251          while (cblist) {
02252             /* Notify with -1 and remove all callbacks */
02253             cbprev = cblist;
02254             cblist = cblist->next;
02255             cbprev->callback(hint->exten->parent->name, hint->exten->exten, AST_EXTENSION_DEACTIVATED, cbprev->data, NULL, NULL);
02256             free(cbprev);
02257             }
02258             hint->callbacks = NULL;
02259          AST_LIST_REMOVE_CURRENT(&hints, list);
02260             free(hint);
02261             res = 0;
02262          break;
02263       }
02264    }
02265    AST_LIST_TRAVERSE_SAFE_END
02266    AST_LIST_UNLOCK(&hints);
02267 
02268    return res;
02269 }

AST_RWLOCK_DEFINE_STATIC ( conlock   ) 

Lock for the ast_context list

int ast_spawn_extension ( struct ast_channel c,
const char *  context,
const char *  exten,
int  priority,
const char *  callerid 
)

Launch a new extension (i.e. new stack).

Parameters:
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
This adds a new extension to the asterisk extension list.

Return values:
0 on success
-1 on failure.

Definition at line 2315 of file pbx.c.

References E_SPAWN, and pbx_extension_helper().

Referenced by __ast_pbx_run(), _macro_exec(), and loopback_exec().

02316 {
02317    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN);
02318 }

AST_THREADSTORAGE ( switch_data  ,
switch_data_init   
)

int ast_unlock_context ( struct ast_context con  ) 

Return values:
Unlocks the given context
Parameters:
con context to unlock
Return values:
0 on success
-1 on failure

Definition at line 6191 of file pbx.c.

References ast_mutex_unlock(), and ast_context::lock.

Referenced by _macro_exec(), complete_context_dont_include_deprecated(), complete_context_remove_ignorepat(), complete_context_remove_ignorepat_deprecated(), complete_context_remove_include(), dundi_precache_full(), find_matching_endwhile(), handle_save_dialplan(), lookup_c_ip(), lookup_ci(), and show_dialplan_helper().

06192 {
06193    return ast_mutex_unlock(&con->lock);
06194 }

int ast_unlock_contexts ( void   ) 

int ast_unregister_application ( const char *  app  ) 

Unregister an application.

Parameters:
app name of the application (does not have to be the same string as the one that was registered)
This unregisters an application from Asterisk's internal application list.

Return values:
0 success
-1 failure

Definition at line 3853 of file pbx.c.

References AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_verbose(), free, option_verbose, and VERBOSE_PREFIX_2.

Referenced by __unload_module(), and unload_module().

03854 {
03855    struct ast_app *tmp;
03856 
03857    AST_LIST_LOCK(&apps);
03858    AST_LIST_TRAVERSE_SAFE_BEGIN(&apps, tmp, list) {
03859       if (!strcasecmp(app, tmp->name)) {
03860          AST_LIST_REMOVE_CURRENT(&apps, list);
03861          if (option_verbose > 1)
03862             ast_verbose( VERBOSE_PREFIX_2 "Unregistered application '%s'\n", tmp->name);
03863          free(tmp);
03864          break;
03865       }
03866    }
03867    AST_LIST_TRAVERSE_SAFE_END
03868    AST_LIST_UNLOCK(&apps);
03869 
03870    return tmp ? 0 : -1;
03871 }

void ast_unregister_switch ( struct ast_switch sw  ) 

Unregister an alternative switch.

Parameters:
sw switch to unregister
Unregisters a switch from asterisk.

Returns:
nothing

Definition at line 3040 of file pbx.c.

References AST_LIST_LOCK, AST_LIST_REMOVE, and AST_LIST_UNLOCK.

Referenced by __unload_module(), and unload_module().

03041 {
03042    AST_LIST_LOCK(&switches);
03043    AST_LIST_REMOVE(&switches, sw, list);
03044    AST_LIST_UNLOCK(&switches);
03045 }

struct ast_exten* ast_walk_context_extensions ( struct ast_context con,
struct ast_exten exten 
) [read]

Definition at line 6300 of file pbx.c.

References ast_exten::next, and ast_context::root.

Referenced by complete_context_remove_extension(), complete_context_remove_extension_deprecated(), dundi_precache_full(), find_matching_priority(), handle_save_dialplan(), pbx_find_extension(), and show_dialplan_helper().

06302 {
06303    if (!exten)
06304       return con ? con->root : NULL;
06305    else
06306       return exten->next;
06307 }

struct ast_ignorepat* ast_walk_context_ignorepats ( struct ast_context con,
struct ast_ignorepat ip 
) [read]

Definition at line 6333 of file pbx.c.

References ast_context::ignorepats, and ast_ignorepat::next.

Referenced by complete_context_remove_ignorepat(), complete_context_remove_ignorepat_deprecated(), handle_save_dialplan(), lookup_c_ip(), and show_dialplan_helper().

06335 {
06336    if (!ip)
06337       return con ? con->ignorepats : NULL;
06338    else
06339       return ip->next;
06340 }

struct ast_include* ast_walk_context_includes ( struct ast_context con,
struct ast_include inc 
) [read]

Definition at line 6324 of file pbx.c.

References ast_context::includes, and ast_include::next.

Referenced by ast_context_verify_includes(), complete_context_dont_include_deprecated(), complete_context_remove_include(), find_matching_priority(), handle_save_dialplan(), lookup_ci(), and show_dialplan_helper().

06326 {
06327    if (!inc)
06328       return con ? con->includes : NULL;
06329    else
06330       return inc->next;
06331 }

struct ast_sw* ast_walk_context_switches ( struct ast_context con,
struct ast_sw sw 
) [read]

Definition at line 6309 of file pbx.c.

References AST_LIST_FIRST, and AST_LIST_NEXT.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06311 {
06312    if (!sw)
06313       return con ? AST_LIST_FIRST(&con->alts) : NULL;
06314    else
06315       return AST_LIST_NEXT(sw, list);
06316 }

struct ast_context* ast_walk_contexts ( struct ast_context con  )  [read]

struct ast_exten* ast_walk_extension_priorities ( struct ast_exten exten,
struct ast_exten priority 
) [read]

Definition at line 6318 of file pbx.c.

References ast_exten::peer.

Referenced by complete_context_remove_extension(), complete_context_remove_extension_deprecated(), find_matching_priority(), handle_save_dialplan(), pbx_find_extension(), and show_dialplan_helper().

06320 {
06321    return priority ? priority->peer : exten;
06322 }

int ast_wrlock_contexts ( void   ) 

Definition at line 6173 of file pbx.c.

References ast_rwlock_wrlock().

Referenced by __ast_context_create(), ast_context_destroy(), ast_merge_contexts_and_delete(), and complete_context_dont_include_deprecated().

06174 {
06175    return ast_rwlock_wrlock(&conlock);
06176 }

static void* async_wait ( void *  data  )  [static]

Definition at line 4907 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_uniqueid(), and ast_pbx_outgoing_exten_uniqueid().

04908 {
04909    struct async_stat *as = data;
04910    struct ast_channel *chan = as->chan;
04911    int timeout = as->timeout;
04912    int res;
04913    struct ast_frame *f;
04914    struct ast_app *app;
04915 
04916    while (timeout && (chan->_state != AST_STATE_UP)) {
04917       res = ast_waitfor(chan, timeout);
04918       if (res < 1)
04919          break;
04920       if (timeout > -1)
04921          timeout = res;
04922       f = ast_read(chan);
04923       if (!f)
04924          break;
04925       if (f->frametype == AST_FRAME_CONTROL) {
04926          if ((f->subclass == AST_CONTROL_BUSY)  ||
04927              (f->subclass == AST_CONTROL_CONGESTION) ) {
04928             ast_frfree(f);
04929             break;
04930          }
04931       }
04932       ast_frfree(f);
04933    }
04934    if (chan->_state == AST_STATE_UP) {
04935       if (!ast_strlen_zero(as->app)) {
04936          app = pbx_findapp(as->app);
04937          if (app) {
04938             if (option_verbose > 2)
04939                ast_verbose(VERBOSE_PREFIX_3 "Launching %s(%s) on %s\n", as->app, as->appdata, chan->name);
04940             pbx_exec(chan, app, as->appdata);
04941          } else
04942             ast_log(LOG_WARNING, "No such application '%s'\n", as->app);
04943       } else {
04944          if (!ast_strlen_zero(as->context))
04945             ast_copy_string(chan->context, as->context, sizeof(chan->context));
04946          if (!ast_strlen_zero(as->exten))
04947             ast_copy_string(chan->exten, as->exten, sizeof(chan->exten));
04948          if (as->priority > 0)
04949             chan->priority = as->priority;
04950          /* Run the PBX */
04951          if (ast_pbx_run(chan)) {
04952             ast_log(LOG_ERROR, "Failed to start PBX on %s\n", chan->name);
04953          } else {
04954             /* PBX will have taken care of this */
04955             chan = NULL;
04956          }
04957       }
04958    }
04959    free(as);
04960    if (chan)
04961       ast_hangup(chan);
04962    return NULL;
04963 }

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 2333 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().

02334 {
02335    int digit;
02336 
02337    buf[pos] = '\0';  /* make sure it is properly terminated */
02338    while (ast_matchmore_extension(c, c->context, buf, 1, c->cid.cid_num)) {
02339       /* As long as we're willing to wait, and as long as it's not defined,
02340          keep reading digits until we can't possibly get a right answer anymore.  */
02341       digit = ast_waitfordigit(c, waittime * 1000);
02342       if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
02343          c->_softhangup = 0;
02344       } else {
02345          if (!digit) /* No entry */
02346             break;
02347          if (digit < 0) /* Error, maybe a  hangup */
02348             return -1;
02349          if (pos < buflen - 1) { /* XXX maybe error otherwise ? */
02350             buf[pos++] = digit;
02351             buf[pos] = '\0';
02352          }
02353          waittime = c->pbx->dtimeout;
02354       }
02355    }
02356    return 0;
02357 }

static char* complete_show_application ( const char *  line,
const char *  word,
int  pos,
int  state 
) [static]

Definition at line 3098 of file pbx.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, and strdup.

03099 {
03100    struct ast_app *a;
03101    char *ret = NULL;
03102    int which = 0;
03103    int wordlen = strlen(word);
03104 
03105    /* return the n-th [partial] matching entry */
03106    AST_LIST_LOCK(&apps);
03107    AST_LIST_TRAVERSE(&apps, a, list) {
03108       if (!strncasecmp(word, a->name, wordlen) && ++which > state) {
03109          ret = strdup(a->name);
03110          break;
03111       }
03112    }
03113    AST_LIST_UNLOCK(&apps);
03114 
03115    return ret;
03116 }

static char* complete_show_applications ( const char *  line,
const char *  word,
int  pos,
int  state 
) [static]

Definition at line 3459 of file pbx.c.

References ast_cli_complete().

03460 {
03461    static char* choices[] = { "like", "describing", NULL };
03462 
03463    return (pos != 3) ? NULL : ast_cli_complete(word, choices, state);
03464 }

static char* complete_show_applications_deprecated ( const char *  line,
const char *  word,
int  pos,
int  state 
) [static]

Definition at line 3452 of file pbx.c.

References ast_cli_complete().

03453 {
03454    static char* choices[] = { "like", "describing", NULL };
03455 
03456    return (pos != 2) ? NULL : ast_cli_complete(word, choices, state);
03457 }

static char* complete_show_dialplan_context ( const char *  line,
const char *  word,
int  pos,
int  state 
) [static]

Definition at line 3469 of file pbx.c.

References ast_get_context_name(), ast_rdlock_contexts(), ast_strdup, ast_unlock_contexts(), and ast_walk_contexts().

03471 {
03472    struct ast_context *c = NULL;
03473    char *ret = NULL;
03474    int which = 0;
03475    int wordlen;
03476 
03477    /* we are do completion of [exten@]context on second position only */
03478    if (pos != 2)
03479       return NULL;
03480 
03481    ast_rdlock_contexts();
03482 
03483    wordlen = strlen(word);
03484 
03485    /* walk through all contexts and return the n-th match */
03486    while ( (c = ast_walk_contexts(c)) ) {
03487       if (!strncasecmp(word, ast_get_context_name(c), wordlen) && ++which > state) {
03488          ret = ast_strdup(ast_get_context_name(c));
03489          break;
03490       }
03491    }
03492 
03493    ast_unlock_contexts();
03494 
03495    return ret;
03496 }

static char* complete_show_function ( const char *  line,
const char *  word,
int  pos,
int  state 
) [static]

Definition at line 1434 of file pbx.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_custom_function::name, and strdup.

01435 {
01436    struct ast_custom_function *acf;
01437    char *ret = NULL;
01438    int which = 0;
01439    int wordlen = strlen(word);
01440 
01441    /* case-insensitive for convenience in this 'complete' function */
01442    AST_LIST_LOCK(&acf_root);
01443    AST_LIST_TRAVERSE(&acf_root, acf, acflist) {
01444       if (!strncasecmp(word, acf->name, wordlen) && ++which > state) {
01445          ret = strdup(acf->name);
01446          break;
01447       }
01448    }
01449    AST_LIST_UNLOCK(&acf_root);
01450 
01451    return ret;
01452 }

static void decrease_call_count ( void   )  [static]

Definition at line 2606 of file pbx.c.

References ast_mutex_lock(), ast_mutex_unlock(), and countcalls.

Referenced by ast_pbx_run(), and pbx_thread().

02607 {
02608    ast_mutex_lock(&maxcalllock);
02609    if (countcalls > 0)
02610       countcalls--;
02611    ast_mutex_unlock(&maxcalllock);
02612 }

static void destroy_exten ( struct ast_exten e  )  [static]

Definition at line 2614 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().

02615 {
02616    if (e->priority == PRIORITY_HINT)
02617       ast_remove_hint(e);
02618 
02619    if (e->datad)
02620       e->datad(e->data);
02621    free(e);
02622 }

static int ext_cmp ( const char *  a,
const char *  b 
) [static]

the full routine to compare extensions in rules.

Definition at line 722 of file pbx.c.

References ext_cmp1().

Referenced by ast_add_extension2().

00723 {
00724    /* make sure non-patterns come first.
00725     * If a is not a pattern, it either comes first or
00726     * we use strcmp to compare the strings.
00727     */
00728    int ret = 0;
00729 
00730    if (a[0] != '_')
00731       return (b[0] == '_') ? -1 : strcmp(a, b);
00732 
00733    /* Now we know a is a pattern; if b is not, a comes first */
00734    if (b[0] != '_')
00735       return 1;
00736 #if 0 /* old mode for ext matching */
00737    return strcmp(a, b);
00738 #endif
00739    /* ok we need full pattern sorting routine */
00740    while (!ret && a && b)
00741       ret = ext_cmp1(&a) - ext_cmp1(&b);
00742    if (ret == 0)
00743       return 0;
00744    else
00745       return (ret > 0) ? 1 : -1;
00746 }

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 650 of file pbx.c.

References ast_log(), and LOG_WARNING.

Referenced by ext_cmp().

00651 {
00652    uint32_t chars[8];
00653    int c, cmin = 0xff, count = 0;
00654    const char *end;
00655 
00656    /* load, sign extend and advance pointer until we find
00657     * a valid character.
00658     */
00659    while ( (c = *(*p)++) && (c == ' ' || c == '-') )
00660       ;  /* ignore some characters */
00661 
00662    /* always return unless we have a set of chars */
00663    switch (c) {
00664    default: /* ordinary character */
00665       return 0x0000 | (c & 0xff);
00666 
00667    case 'N':   /* 2..9 */
00668       return 0x0700 | '2' ;
00669 
00670    case 'X':   /* 0..9 */
00671       return 0x0900 | '0';
00672 
00673    case 'Z':   /* 1..9 */
00674       return 0x0800 | '1';
00675 
00676    case '.':   /* wildcard */
00677       return 0x10000;
00678 
00679    case '!':   /* earlymatch */
00680       return 0x20000;   /* less specific than NULL */
00681 
00682    case '\0':  /* empty string */
00683       *p = NULL;
00684       return 0x30000;
00685 
00686    case '[':   /* pattern */
00687       break;
00688    }
00689    /* locate end of set */
00690    end = strchr(*p, ']');  
00691 
00692    if (end == NULL) {
00693       ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n");
00694       return 0x40000;   /* XXX make this entry go last... */
00695    }
00696 
00697    bzero(chars, sizeof(chars));  /* clear all chars in the set */
00698    for (; *p < end  ; (*p)++) {
00699       unsigned char c1, c2;   /* first-last char in range */
00700       c1 = (unsigned char)((*p)[0]);
00701       if (*p + 2 < end && (*p)[1] == '-') { /* this is a range */
00702          c2 = (unsigned char)((*p)[2]);
00703          *p += 2; /* skip a total of 3 chars */
00704       } else         /* individual character */
00705          c2 = c1;
00706       if (c1 < cmin)
00707          cmin = c1;
00708       for (; c1 <= c2; c1++) {
00709          uint32_t mask = 1 << (c1 % 32);
00710          if ( (chars[ c1 / 32 ] & mask) == 0)
00711             count += 0x100;
00712          chars[ c1 / 32 ] |= mask;
00713       }
00714    }
00715    (*p)++;
00716    return count == 0 ? 0x30000 : (count | cmin);
00717 }

static int ext_strncpy ( char *  dst,
const char *  src,
int  len 
) [static]

copy a string skipping whitespace

Definition at line 4659 of file pbx.c.

Referenced by ast_add_extension2().

04660 {
04661    int count=0;
04662 
04663    while (*src && (count < len - 1)) {
04664       switch(*src) {
04665       case ' ':
04666          /* otherwise exten => [a-b],1,... doesn't work */
04667          /*    case '-': */
04668          /* Ignore */
04669          break;
04670       default:
04671          *dst = *src;
04672          dst++;
04673       }
04674       src++;
04675       count++;
04676    }
04677    *dst = '\0';
04678 
04679    return count;
04680 }

static int extension_match_core ( const char *  pattern,
const char *  data,
enum ext_match_t  mode 
) [static]

Definition at line 871 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().

00872 {
00873    int i;
00874    static int prof_id = -2;   /* marker for 'unallocated' id */
00875    if (prof_id == -2)
00876       prof_id = ast_add_profile("ext_match", 0);
00877    ast_mark(prof_id, 1);
00878    i = _extension_match_core(pattern, data, mode);
00879    ast_mark(prof_id, 0);
00880    return i;
00881 }

static struct ast_context* find_context_locked ( const char *  context  )  [static, read]

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 1527 of file pbx.c.

References ast_log(), and LOG_WARNING.

Referenced by ast_func_read(), and ast_func_write().

01528 {
01529    char *args = strchr(function, '(');
01530 
01531    if (!args)
01532       ast_log(LOG_WARNING, "Function doesn't contain parentheses.  Assuming null argument.\n");
01533    else {
01534       char *p;
01535       *args++ = '\0';
01536       if ((p = strrchr(args, ')')) )
01537          *p = '\0';
01538       else
01539          ast_log(LOG_WARNING, "Can't find trailing parenthesis?\n");
01540    }
01541    return args;
01542 }

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 4083 of file pbx.c.

References ast_log(), ast_strlen_zero(), LOG_WARNING, lookup_name(), and s.

Referenced by ast_build_timing().

04084 {
04085    int s, e; /* start and ending position */
04086    unsigned int mask = 0;
04087 
04088    /* Check for whole range */
04089    if (ast_strlen_zero(src) || !strcmp(src, "*")) {
04090       s = 0;
04091       e = max - 1;
04092    } else {
04093       /* Get start and ending position */
04094       char *c = strchr(src, '-');
04095       if (c)
04096          *c++ = '\0';
04097       /* Find the start */
04098       s = lookup_name(src, names, max);
04099       if (!s) {
04100          ast_log(LOG_WARNING, "Invalid %s '%s', assuming none\n", msg, src);
04101          return 0;
04102       }
04103       s--;
04104       if (c) { /* find end of range */
04105          e = lookup_name(c, names, max);
04106          if (!e) {
04107             ast_log(LOG_WARNING, "Invalid end %s '%s', assuming none\n", msg, c);
04108             return 0;
04109          }
04110          e--;
04111       } else
04112          e = s;
04113    }
04114    /* Fill the mask. Remember that ranges are cyclic */
04115    mask = 1 << e; /* initialize with last element */
04116    while (s != e) {
04117       if (s >= max) {
04118          s = 0;
04119          mask |= (1 << s);
04120       } else {
04121          mask |= (1 << s);
04122          s++;
04123       }
04124    }
04125    return mask;
04126 }

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 4129 of file pbx.c.

References ast_log(), ast_strlen_zero(), LOG_WARNING, and ast_timing::minmask.

Referenced by ast_build_timing().

04130 {
04131    char *e;
04132    int x;
04133    int s1, s2;
04134    int e1, e2;
04135    /* int cth, ctm; */
04136 
04137    /* start disabling all times, fill the fields with 0's, as they may contain garbage */
04138    memset(i->minmask, 0, sizeof(i->minmask));
04139 
04140    /* 2-minutes per bit, since the mask has only 32 bits :( */
04141    /* Star is all times */
04142    if (ast_strlen_zero(times) || !strcmp(times, "*")) {
04143       for (x=0; x<24; x++)
04144          i->minmask[x] = 0x3fffffff; /* 30 bits */
04145       return;
04146    }
04147    /* Otherwise expect a range */
04148    e = strchr(times, '-');
04149    if (!e) {
04150       ast_log(LOG_WARNING, "Time range is not valid. Assuming no restrictions based on time.\n");
04151       return;
04152    }
04153    *e++ = '\0';
04154    /* XXX why skip non digits ? */
04155    while (*e && !isdigit(*e))
04156       e++;
04157    if (!*e) {
04158       ast_log(LOG_WARNING, "Invalid time range.  Assuming no restrictions based on time.\n");
04159       return;
04160    }
04161    if (sscanf(times, "%d:%d", &s1, &s2) != 2) {
04162       ast_log(LOG_WARNING, "%s isn't a time.  Assuming no restrictions based on time.\n", times);
04163       return;
04164    }
04165    if (sscanf(e, "%d:%d", &e1, &e2) != 2) {
04166       ast_log(LOG_WARNING, "%s isn't a time.  Assuming no restrictions based on time.\n", e);
04167       return;
04168    }
04169    /* XXX this needs to be optimized */
04170 #if 1
04171    s1 = s1 * 30 + s2/2;
04172    if ((s1 < 0) || (s1 >= 24*30)) {
04173       ast_log(LOG_WARNING, "%s isn't a valid start time. Assuming no time.\n", times);
04174       return;
04175    }
04176    e1 = e1 * 30 + e2/2;
04177    if ((e1 < 0) || (e1 >= 24*30)) {
04178       ast_log(LOG_WARNING, "%s isn't a valid end time. Assuming no time.\n", e);
04179       return;
04180    }
04181    /* Go through the time and enable each appropriate bit */
04182    for (x=s1;x != e1;x = (x + 1) % (24 * 30)) {
04183       i->minmask[x/30] |= (1 << (x % 30));
04184    }
04185    /* Do the last one */
04186    i->minmask[x/30] |= (1 << (x % 30));
04187 #else
04188    for (cth=0; cth<24; cth++) {
04189       /* Initialize masks to blank */
04190       i->minmask[cth] = 0;
04191       for (ctm=0; ctm<30; ctm++) {
04192          if (
04193          /* First hour with more than one hour */
04194                (((cth == s1) && (ctm >= s2)) &&
04195                 ((cth < e1)))
04196          /* Only one hour */
04197          ||    (((cth == s1) && (ctm >= s2)) &&
04198                 ((cth == e1) && (ctm <= e2)))
04199          /* In between first and last hours (more than 2 hours) */
04200          ||    ((cth > s1) &&
04201                 (cth < e1))
04202          /* Last hour with more than one hour */
04203          ||    ((cth > s1) &&
04204                 ((cth == e1) && (ctm <= e2)))
04205          )
04206             i->minmask[cth] |= (1 << (ctm / 2));
04207       }
04208    }
04209 #endif
04210    /* All done */
04211    return;
04212 }

static int handle_set_global ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 3754 of file pbx.c.

References ast_cli(), pbx_builtin_setvar_helper(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03755 {
03756    if (argc != 5)
03757       return RESULT_SHOWUSAGE;
03758 
03759    pbx_builtin_setvar_helper(NULL, argv[3], argv[4]);
03760    ast_cli(fd, "\n    -- Global variable %s set to %s\n", argv[3], argv[4]);
03761 
03762    return RESULT_SUCCESS;
03763 }

static int handle_set_global_deprecated ( int  fd,
int  argc,
char *  argv[] 
) [static]

CLI support for setting global variables.

Definition at line 3742 of file pbx.c.

References ast_cli(), pbx_builtin_setvar_helper(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03743 {
03744    if (argc != 4)
03745       return RESULT_SHOWUSAGE;
03746 
03747    pbx_builtin_setvar_helper(NULL, argv[2], argv[3]);
03748    ast_cli(fd, "\n    -- Global variable %s set to %s\n", argv[2], argv[3]);
03749 
03750    return RESULT_SUCCESS;
03751 }

static int handle_show_application ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 3188 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().

03189 {
03190    struct ast_app *a;
03191    int app, no_registered_app = 1;
03192 
03193    if (argc < 4)
03194       return RESULT_SHOWUSAGE;
03195 
03196    /* ... go through all applications ... */
03197    AST_LIST_LOCK(&apps);
03198    AST_LIST_TRAVERSE(&apps, a, list) {
03199       /* ... compare this application name with all arguments given
03200        * to 'show application' command ... */
03201       for (app = 3; app < argc; app++) {
03202          if (!strcasecmp(a->name, argv[app])) {
03203             /* Maximum number of characters added by terminal coloring is 22 */
03204             char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40];
03205             char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL;
03206             int synopsis_size, description_size;
03207 
03208             no_registered_app = 0;
03209 
03210             if (a->synopsis)
03211                synopsis_size = strlen(a->synopsis) + 23;
03212             else
03213                synopsis_size = strlen("Not available") + 23;
03214             synopsis = alloca(synopsis_size);
03215 
03216             if (a->description)
03217                description_size = strlen(a->description) + 23;
03218             else
03219                description_size = strlen("Not available") + 23;
03220             description = alloca(description_size);
03221 
03222             if (synopsis && description) {
03223                snprintf(info, 64 + AST_MAX_APP, "\n  -= Info about application '%s' =- \n\n", a->name);
03224                term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22);
03225                term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
03226                term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
03227                term_color(synopsis,
03228                            a->synopsis ? a->synopsis : "Not available",
03229                            COLOR_CYAN, 0, synopsis_size);
03230                term_color(description,
03231                            a->description ? a->description : "Not available",
03232                            COLOR_CYAN, 0, description_size);
03233 
03234                ast_cli(fd,"%s%s%s\n\n%s%s\n", infotitle, syntitle, synopsis, destitle, description);
03235             } else {
03236                /* ... one of our applications, show info ...*/
03237                ast_cli(fd,"\n  -= Info about application '%s' =- \n\n"
03238                   "[Synopsis]\n  %s\n\n"
03239                   "[Description]\n%s\n",
03240                   a->name,
03241                   a->synopsis ? a->synopsis : "Not available",
03242                   a->description ? a->description : "Not available");
03243             }
03244          }
03245       }
03246    }
03247    AST_LIST_UNLOCK(&apps);
03248 
03249    /* we found at least one app? no? */
03250    if (no_registered_app) {
03251       ast_cli(fd, "Your application(s) is (are) not registered\n");
03252       return RESULT_FAILURE;
03253    }
03254 
03255    return RESULT_SUCCESS;
03256 }

static int handle_show_application_deprecated ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 3118 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().

03119 {
03120    struct ast_app *a;
03121    int app, no_registered_app = 1;
03122 
03123    if (argc < 3)
03124       return RESULT_SHOWUSAGE;
03125 
03126    /* ... go through all applications ... */
03127    AST_LIST_LOCK(&apps);
03128    AST_LIST_TRAVERSE(&apps, a, list) {
03129       /* ... compare this application name with all arguments given
03130        * to 'show application' command ... */
03131       for (app = 2; app < argc; app++) {
03132          if (!strcasecmp(a->name, argv[app])) {
03133             /* Maximum number of characters added by terminal coloring is 22 */
03134             char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40];
03135             char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL;
03136             int synopsis_size, description_size;
03137 
03138             no_registered_app = 0;
03139 
03140             if (a->synopsis)
03141                synopsis_size = strlen(a->synopsis) + 23;
03142             else
03143                synopsis_size = strlen("Not available") + 23;
03144             synopsis = alloca(synopsis_size);
03145 
03146             if (a->description)
03147                description_size = strlen(a->description) + 23;
03148             else
03149                description_size = strlen("Not available") + 23;
03150             description = alloca(description_size);
03151 
03152             if (synopsis && description) {
03153                snprintf(info, 64 + AST_MAX_APP, "\n  -= Info about application '%s' =- \n\n", a->name);
03154                term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22);
03155                term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
03156                term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
03157                term_color(synopsis,
03158                            a->synopsis ? a->synopsis : "Not available",
03159                            COLOR_CYAN, 0, synopsis_size);
03160                term_color(description,
03161                            a->description ? a->description : "Not available",
03162                            COLOR_CYAN, 0, description_size);
03163 
03164                ast_cli(fd,"%s%s%s\n\n%s%s\n", infotitle, syntitle, synopsis, destitle, description);
03165             } else {
03166                /* ... one of our applications, show info ...*/
03167                ast_cli(fd,"\n  -= Info about application '%s' =- \n\n"
03168                   "[Synopsis]\n  %s\n\n"
03169                   "[Description]\n%s\n",
03170                   a->name,
03171                   a->synopsis ? a->synopsis : "Not available",
03172                   a->description ? a->description : "Not available");
03173             }
03174          }
03175       }
03176    }
03177    AST_LIST_UNLOCK(&apps);
03178 
03179    /* we found at least one app? no? */
03180    if (no_registered_app) {
03181       ast_cli(fd, "Your application(s) is (are) not registered\n");
03182       return RESULT_FAILURE;
03183    }
03184 
03185    return RESULT_SUCCESS;
03186 }

static int handle_show_applications ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 3383 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.

03384 {
03385    struct ast_app *a;
03386    int like = 0, describing = 0;
03387    int total_match = 0;    /* Number of matches in like clause */
03388    int total_apps = 0;  /* Number of apps registered */
03389 
03390    AST_LIST_LOCK(&apps);
03391 
03392    if (AST_LIST_EMPTY(&apps)) {
03393       ast_cli(fd, "There are no registered applications\n");
03394       AST_LIST_UNLOCK(&apps);
03395       return -1;
03396    }
03397 
03398    /* core list applications like <keyword> */
03399    if ((argc == 5) && (!strcmp(argv[3], "like"))) {
03400       like = 1;
03401    } else if ((argc > 4) && (!strcmp(argv[3], "describing"))) {
03402       describing = 1;
03403    }
03404 
03405    /* core list applications describing <keyword1> [<keyword2>] [...] */
03406    if ((!like) && (!describing)) {
03407       ast_cli(fd, "    -= Registered Asterisk Applications =-\n");
03408    } else {
03409       ast_cli(fd, "    -= Matching Asterisk Applications =-\n");
03410    }
03411 
03412    AST_LIST_TRAVERSE(&apps, a, list) {
03413       int printapp = 0;
03414       total_apps++;
03415       if (like) {
03416          if (strcasestr(a->name, argv[4])) {
03417             printapp = 1;
03418             total_match++;
03419          }
03420       } else if (describing) {
03421          if (a->description) {
03422             /* Match all words on command line */
03423             int i;
03424             printapp = 1;
03425             for (i = 4; i < argc; i++) {
03426                if (!strcasestr(a->description, argv[i])) {
03427                   printapp = 0;
03428                } else {
03429                   total_match++;
03430                }
03431             }
03432          }
03433       } else {
03434          printapp = 1;
03435       }
03436 
03437       if (printapp) {
03438          ast_cli(fd,"  %20s: %s\n", a->name, a->synopsis ? a->synopsis : "<Synopsis not available>");
03439       }
03440    }
03441    if ((!like) && (!describing)) {
03442       ast_cli(fd, "    -= %d Applications Registered =-\n",total_apps);
03443    } else {
03444       ast_cli(fd, "    -= %d Applications Matching =-\n",total_match);
03445    }
03446 
03447    AST_LIST_UNLOCK(&apps);
03448 
03449    return RESULT_SUCCESS;
03450 }

static int handle_show_applications_deprecated ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 3315 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.

03316 {
03317    struct ast_app *a;
03318    int like = 0, describing = 0;
03319    int total_match = 0;    /* Number of matches in like clause */
03320    int total_apps = 0;  /* Number of apps registered */
03321 
03322    AST_LIST_LOCK(&apps);
03323 
03324    if (AST_LIST_EMPTY(&apps)) {
03325       ast_cli(fd, "There are no registered applications\n");
03326       AST_LIST_UNLOCK(&apps);
03327       return -1;
03328    }
03329 
03330    /* show applications like <keyword> */
03331    if ((argc == 4) && (!strcmp(argv[2], "like"))) {
03332       like = 1;
03333    } else if ((argc > 3) && (!strcmp(argv[2], "describing"))) {
03334       describing = 1;
03335    }
03336 
03337    /* show applications describing <keyword1> [<keyword2>] [...] */
03338    if ((!like) && (!describing)) {
03339       ast_cli(fd, "    -= Registered Asterisk Applications =-\n");
03340    } else {
03341       ast_cli(fd, "    -= Matching Asterisk Applications =-\n");
03342    }
03343 
03344    AST_LIST_TRAVERSE(&apps, a, list) {
03345       int printapp = 0;
03346       total_apps++;
03347       if (like) {
03348          if (strcasestr(a->name, argv[3])) {
03349             printapp = 1;
03350             total_match++;
03351          }
03352       } else if (describing) {
03353          if (a->description) {
03354             /* Match all words on command line */
03355             int i;
03356             printapp = 1;
03357             for (i = 3; i < argc; i++) {
03358                if (!strcasestr(a->description, argv[i])) {
03359                   printapp = 0;
03360                } else {
03361                   total_match++;
03362                }
03363             }
03364          }
03365       } else {
03366          printapp = 1;
03367       }
03368 
03369       if (printapp) {
03370          ast_cli(fd,"  %20s: %s\n", a->name, a->synopsis ? a->synopsis : "<Synopsis not available>");
03371       }
03372    }
03373    if ((!like) && (!describing)) {
03374       ast_cli(fd, "    -= %d Applications Registered =-\n",total_apps);
03375    } else {
03376       ast_cli(fd, "    -= %d Applications Matching =-\n",total_match);
03377    }
03378 
03379    AST_LIST_UNLOCK(&apps);
03380 
03381    return RESULT_SUCCESS;
03382 }

static int handle_show_dialplan ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 3669 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.

03670 {
03671    char *exten = NULL, *context = NULL;
03672    /* Variables used for different counters */
03673    struct dialplan_counters counters;
03674 
03675    const char *incstack[AST_PBX_MAX_STACK];
03676    memset(&counters, 0, sizeof(counters));
03677 
03678    if (argc != 2 && argc != 3)
03679       return RESULT_SHOWUSAGE;
03680 
03681    /* we obtain [exten@]context? if yes, split them ... */
03682    if (argc == 3) {
03683       if (strchr(argv[2], '@')) {   /* split into exten & context */
03684          context = ast_strdupa(argv[2]);
03685          exten = strsep(&context, "@");
03686          /* change empty strings to NULL */
03687          if (ast_strlen_zero(exten))
03688             exten = NULL;
03689       } else { /* no '@' char, only context given */
03690          context = argv[2];
03691       }
03692       if (ast_strlen_zero(context))
03693          context = NULL;
03694    }
03695    /* else Show complete dial plan, context and exten are NULL */
03696    show_dialplan_helper(fd, context, exten, &counters, NULL, 0, incstack);
03697 
03698    /* check for input failure and throw some error messages */
03699    if (context && !counters.context_existence) {
03700       ast_cli(fd, "There is no existence of '%s' context\n", context);
03701       return RESULT_FAILURE;
03702    }
03703 
03704    if (exten && !counters.extension_existence) {
03705       if (context)
03706          ast_cli(fd, "There is no existence of %s@%s extension\n",
03707             exten, context);
03708       else
03709          ast_cli(fd,
03710             "There is no existence of '%s' extension in all contexts\n",
03711             exten);
03712       return RESULT_FAILURE;
03713    }
03714 
03715    ast_cli(fd,"-= %d %s (%d %s) in %d %s. =-\n",
03716             counters.total_exten, counters.total_exten == 1 ? "extension" : "extensions",
03717             counters.total_prio, counters.total_prio == 1 ? "priority" : "priorities",
03718             counters.total_context, counters.total_context == 1 ? "context" : "contexts");
03719 
03720    /* everything ok */
03721    return RESULT_SUCCESS;
03722 }

static int handle_show_function ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 1378 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().

01379 {
01380    struct ast_custom_function *acf;
01381    /* Maximum number of characters added by terminal coloring is 22 */
01382    char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40];
01383    char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL;
01384    char stxtitle[40], *syntax = NULL;
01385    int synopsis_size, description_size, syntax_size;
01386 
01387    if (argc < 4)
01388       return RESULT_SHOWUSAGE;
01389 
01390    if (!(acf = ast_custom_function_find(argv[3]))) {
01391       ast_cli(fd, "No function by that name registered.\n");
01392       return RESULT_FAILURE;
01393 
01394    }
01395 
01396    if (acf->synopsis)
01397       synopsis_size = strlen(acf->synopsis) + 23;
01398    else
01399       synopsis_size = strlen("Not available") + 23;
01400    synopsis = alloca(synopsis_size);
01401 
01402    if (acf->desc)
01403       description_size = strlen(acf->desc) + 23;
01404    else
01405       description_size = strlen("Not available") + 23;
01406    description = alloca(description_size);
01407 
01408    if (acf->syntax)
01409       syntax_size = strlen(acf->syntax) + 23;
01410    else
01411       syntax_size = strlen("Not available") + 23;
01412    syntax = alloca(syntax_size);
01413 
01414    snprintf(info, 64 + AST_MAX_APP, "\n  -= Info about function '%s' =- \n\n", acf->name);
01415    term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22);
01416    term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40);
01417    term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
01418    term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
01419    term_color(syntax,
01420          acf->syntax ? acf->syntax : "Not available",
01421          COLOR_CYAN, 0, syntax_size);
01422    term_color(synopsis,
01423          acf->synopsis ? acf->synopsis : "Not available",
01424          COLOR_CYAN, 0, synopsis_size);
01425    term_color(description,
01426          acf->desc ? acf->desc : "Not available",
01427          COLOR_CYAN, 0, description_size);
01428 
01429    ast_cli(fd,"%s%s%s\n\n%s%s\n\n%s%s\n", infotitle, stxtitle, syntax, syntitle, synopsis, destitle, description);
01430 
01431    return RESULT_SUCCESS;
01432 }

static int handle_show_function_deprecated ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 1322 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().

01323 {
01324    struct ast_custom_function *acf;
01325    /* Maximum number of characters added by terminal coloring is 22 */
01326    char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40];
01327    char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL;
01328    char stxtitle[40], *syntax = NULL;
01329    int synopsis_size, description_size, syntax_size;
01330 
01331    if (argc < 3)
01332       return RESULT_SHOWUSAGE;
01333 
01334    if (!(acf = ast_custom_function_find(argv[2]))) {
01335       ast_cli(fd, "No function by that name registered.\n");
01336       return RESULT_FAILURE;
01337 
01338    }
01339 
01340    if (acf->synopsis)
01341       synopsis_size = strlen(acf->synopsis) + 23;
01342    else
01343       synopsis_size = strlen("Not available") + 23;
01344    synopsis = alloca(synopsis_size);
01345 
01346    if (acf->desc)
01347       description_size = strlen(acf->desc) + 23;
01348    else
01349       description_size = strlen("Not available") + 23;
01350    description = alloca(description_size);
01351 
01352    if (acf->syntax)
01353       syntax_size = strlen(acf->syntax) + 23;
01354    else
01355       syntax_size = strlen("Not available") + 23;
01356    syntax = alloca(syntax_size);
01357 
01358    snprintf(info, 64 + AST_MAX_APP, "\n  -= Info about function '%s' =- \n\n", acf->name);
01359    term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22);
01360    term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40);
01361    term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
01362    term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
01363    term_color(syntax,
01364          acf->syntax ? acf->syntax : "Not available",
01365          COLOR_CYAN, 0, syntax_size);
01366    term_color(synopsis,
01367          acf->synopsis ? acf->synopsis : "Not available",
01368          COLOR_CYAN, 0, synopsis_size);
01369    term_color(description,
01370          acf->desc ? acf->desc : "Not available",
01371          COLOR_CYAN, 0, description_size);
01372 
01373    ast_cli(fd,"%s%s%s\n\n%s%s\n\n%s%s\n", infotitle, stxtitle, syntax, syntitle, synopsis, destitle, description);
01374 
01375    return RESULT_SUCCESS;
01376 }

static int handle_show_functions ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 1294 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.

01295 {
01296    struct ast_custom_function *acf;
01297    int count_acf = 0;
01298    int like = 0;
01299 
01300    if (argc == 5 && (!strcmp(argv[3], "like")) ) {
01301       like = 1;
01302    } else if (argc != 3) {
01303       return RESULT_SHOWUSAGE;
01304    }
01305 
01306    ast_cli(fd, "%s Custom Functions:\n--------------------------------------------------------------------------------\n", like ? "Matching" : "Installed");
01307 
01308    AST_LIST_LOCK(&acf_root);
01309    AST_LIST_TRAVERSE(&acf_root, acf, acflist) {
01310       if (!like || strstr(acf->name, argv[4])) {
01311          count_acf++;
01312          ast_cli(fd, "%-20.20s  %-35.35s  %s\n", acf->name, acf->syntax, acf->synopsis);
01313       }
01314    }
01315    AST_LIST_UNLOCK(&acf_root);
01316 
01317    ast_cli(fd, "%d %scustom functions installed.\n", count_acf, like ? "matching " : "");
01318 
01319    return RESULT_SUCCESS;
01320 }

static int handle_show_functions_deprecated ( 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 == 4 && (!strcmp(argv[2], "like")) ) {
01274       like = 1;
01275    } else if (argc != 2) {
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[3])) {
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_globals ( int  fd,
int  argc,
char *  argv[] 
) [static]

CLI support for listing global variables in a parseable way.

Definition at line 3725 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.

03726 {
03727    int i = 0;
03728    struct ast_var_t *newvariable;
03729 
03730    ast_mutex_lock(&globalslock);
03731    AST_LIST_TRAVERSE (&globals, newvariable, entries) {
03732       i++;
03733       ast_cli(fd, "   %s=%s\n", ast_var_name(newvariable), ast_var_value(newvariable));
03734    }
03735    ast_mutex_unlock(&globalslock);
03736    ast_cli(fd, "\n    -- %d variables\n", i);
03737 
03738    return RESULT_SUCCESS;
03739 }

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 3259 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.

03260 {
03261    struct ast_hint *hint;
03262    int num = 0;
03263    int watchers;
03264    struct ast_state_cb *watcher;
03265 
03266    if (AST_LIST_EMPTY(&hints)) {
03267       ast_cli(fd, "There are no registered dialplan hints\n");
03268       return RESULT_SUCCESS;
03269    }
03270    /* ... we have hints ... */
03271    ast_cli(fd, "\n    -= Registered Asterisk Dial Plan Hints =-\n");
03272    AST_LIST_LOCK(&hints);
03273    AST_LIST_TRAVERSE(&hints, hint, list) {
03274       watchers = 0;
03275       for (watcher = hint->callbacks; watcher; watcher = watcher->next)
03276          watchers++;
03277       ast_cli(fd, "   %20s@%-20.20s: %-20.20s  State:%-15.15s Watchers %2d\n",
03278          ast_get_extension_name(hint->exten),
03279          ast_get_context_name(ast_get_extension_context(hint->exten)),
03280          ast_get_extension_app(hint->exten),
03281          ast_extension_state2str(hint->laststate), watchers);
03282       num++;
03283    }
03284    ast_cli(fd, "----------------\n");
03285    ast_cli(fd, "- %d hints registered\n", num);
03286    AST_LIST_UNLOCK(&hints);
03287    return RESULT_SUCCESS;
03288 }

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 3291 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.

03292 {
03293    struct ast_switch *sw;
03294 
03295    AST_LIST_LOCK(&switches);
03296 
03297    if (AST_LIST_EMPTY(&switches)) {
03298       AST_LIST_UNLOCK(&switches);
03299       ast_cli(fd, "There are no registered alternative switches\n");
03300       return RESULT_SUCCESS;
03301    }
03302 
03303    ast_cli(fd, "\n    -= Registered Asterisk Alternative Switches =-\n");
03304    AST_LIST_TRAVERSE(&switches, sw, list)
03305       ast_cli(fd, "%s: %s\n", sw->name, sw->description);
03306 
03307    AST_LIST_UNLOCK(&switches);
03308 
03309    return RESULT_SUCCESS;
03310 }

static int include_valid ( struct ast_include i  )  [inline, static]

Definition at line 581 of file pbx.c.

References ast_check_timing(), ast_include::hastime, and ast_include::timing.

Referenced by pbx_find_extension().

00582 {
00583    if (!i->hastime)
00584       return 1;
00585 
00586    return ast_check_timing(&(i->timing));
00587 }

static int increase_call_count ( const struct ast_channel c  )  [static]

Definition at line 2581 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().

02582 {
02583    int failed = 0;
02584    double curloadavg;
02585    ast_mutex_lock(&maxcalllock);
02586    if (option_maxcalls) {
02587       if (countcalls >= option_maxcalls) {
02588          ast_log(LOG_NOTICE, "Maximum call limit of %d calls exceeded by '%s'!\n", option_maxcalls, c->name);
02589          failed = -1;
02590       }
02591    }
02592    if (option_maxload) {
02593       getloadavg(&curloadavg, 1);
02594       if (curloadavg >= option_maxload) {
02595          ast_log(LOG_NOTICE, "Maximum loadavg limit of %f load exceeded by '%s' (currently %f)!\n", option_maxload, c->name, curloadavg);
02596          failed = -1;
02597       }
02598    }
02599    if (!failed)
02600       countcalls++;
02601    ast_mutex_unlock(&maxcalllock);
02602 
02603    return failed;
02604 }

int load_pbx ( void   ) 

Provided by pbx.c

Definition at line 6137 of file pbx.c.

References ast_cli_register_multiple(), ast_log(), ast_register_application(), ast_verbose(), builtins, LOG_ERROR, option_verbose, pbx_cli, and VERBOSE_PREFIX_1.

Referenced by main().

06138 {
06139    int x;
06140 
06141    /* Initialize the PBX */
06142    if (option_verbose) {
06143       ast_verbose( "Asterisk PBX Core Initializing\n");
06144       ast_verbose( "Registering builtin applications:\n");
06145    }
06146    ast_cli_register_multiple(pbx_cli, sizeof(pbx_cli) / sizeof(struct ast_cli_entry));
06147 
06148    /* Register builtin applications */
06149    for (x=0; x<sizeof(builtins) / sizeof(struct pbx_builtin); x++) {
06150       if (option_verbose)
06151          ast_verbose( VERBOSE_PREFIX_1 "[%s]\n", builtins[x].name);
06152       if (ast_register_application(builtins[x].name, builtins[x].execute, builtins[x].synopsis, builtins[x].description)) {
06153          ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name);
06154          return -1;
06155       }
06156    }
06157    return 0;
06158 }

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 4065 of file pbx.c.

Referenced by get_range().

04066 {
04067    int i;
04068 
04069    if (names) {
04070       for (i = 0; names[i]; i++) {
04071          if (!strcasecmp(s, names[i]))
04072             return i+1;
04073       }
04074    } else if (sscanf(s, "%d", &i) == 1 && i >= 1 && i <= max) {
04075       return i;
04076    }
04077    return 0; /* error return */
04078 }

static int matchcid ( const char *  cidpattern,
const char *  callerid 
) [static]

Definition at line 917 of file pbx.c.

References ast_extension_match(), and ast_strlen_zero().

Referenced by pbx_find_extension().

00918 {
00919    /* If the Caller*ID pattern is empty, then we're matching NO Caller*ID, so
00920       failing to get a number should count as a match, otherwise not */
00921 
00922    if (ast_strlen_zero(callerid))
00923       return ast_strlen_zero(cidpattern) ? 1 : 0;
00924 
00925    return ast_extension_match(cidpattern, callerid);
00926 }

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 1083 of file pbx.c.

Referenced by pbx_retrieve_variable(), and pbx_substitute_variables_helper_full().

01084 {
01085    int parens=0;
01086 
01087    *offset = 0;
01088    *length = INT_MAX;
01089    *isfunc = 0;
01090    for (; *var; var++) {
01091       if (*var == '(') {
01092          (*isfunc)++;
01093          parens++;
01094       } else if (*var == ')') {
01095          parens--;
01096       } else if (*var == ':' && parens == 0) {
01097          *var++ = '\0';
01098          sscanf(var, "%d:%d", offset, length);
01099          return 1; /* offset:length valid */
01100       }
01101    }
01102    return 0;
01103 }

void pbx_builtin_clear_globals ( void   ) 

Definition at line 6019 of file pbx.c.

References AST_LIST_REMOVE_HEAD, ast_mutex_lock(), ast_mutex_unlock(), ast_var_delete(), and globals.

Referenced by handle_reload_extensions(), and reload().

06020 {
06021    struct ast_var_t *vardata;
06022 
06023    ast_mutex_lock(&globalslock);
06024    while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries)))
06025       ast_var_delete(vardata);
06026    ast_mutex_unlock(&globalslock);
06027 }

const char* pbx_builtin_getvar_helper ( struct ast_channel chan,
const char *  name 
)

Note:
Will lock the channel.

Definition at line 5796 of file pbx.c.

References ast_channel_lock, ast_channel_unlock, AST_LIST_TRAVERSE, ast_mutex_lock(), ast_mutex_unlock(), ast_var_name(), ast_var_value(), globals, and ast_channel::varshead.

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(), builtin_automonitor(), check_goto_on_transfer(), common_exec(), conf_exec(), conf_run(), dundi_exec(), dundi_helper(), get_also_info(), get_index(), get_refer_info(), global_read(), iax2_exec(), import_ch(), leave_voicemail(), local_hangup(), misdn_answer(), misdn_hangup(), morsecode_exec(), notify_new_message(), oh323_call(), oh323_hangup(), park_call_full(), pickup_by_mark(), queue_exec(), real_ctx(), retrydial_exec(), return_exec(), ring_entry(), run_agi(), set_config_flags(), sip_addheader(), sla_trunk_exec(), speech_background(), try_calling(), try_suggested_sip_codec(), wait_for_answer(), zt_call(), and zt_hangup().

05797 {
05798    struct ast_var_t *variables;
05799    const char *ret = NULL;
05800    int i;
05801    struct varshead *places[2] = { NULL, &globals };
05802 
05803    if (!name)
05804       return NULL;
05805 
05806    if (chan) {
05807       ast_channel_lock(chan);
05808       places[0] = &chan->varshead;
05809    }
05810 
05811    for (i = 0; i < 2; i++) {
05812       if (!places[i])
05813          continue;
05814       if (places[i] == &globals)
05815          ast_mutex_lock(&globalslock);
05816       AST_LIST_TRAVERSE(places[i], variables, entries) {
05817          if (!strcmp(name, ast_var_name(variables))) {
05818             ret = ast_var_value(variables);
05819             break;
05820          }
05821       }
05822       if (places[i] == &globals)
05823          ast_mutex_unlock(&globalslock);
05824       if (ret)
05825          break;
05826    }
05827 
05828    if (chan)
05829       ast_channel_unlock(chan);
05830 
05831    return ret;
05832 }

static int pbx_builtin_gotoif ( struct ast_channel chan,
void *  data 
) [static]

Definition at line 6039 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().

06040 {
06041    char *condition, *branch1, *branch2, *branch;
06042    int rc;
06043    char *stringp;
06044 
06045    if (ast_strlen_zero(data)) {
06046       ast_log(LOG_WARNING, "Ignoring, since there is no variable to check\n");
06047       return 0;
06048    }
06049 
06050    stringp = ast_strdupa(data);
06051    condition = strsep(&stringp,"?");
06052    branch1 = strsep(&stringp,":");
06053    branch2 = strsep(&stringp,"");
06054    branch = pbx_checkcondition(condition) ? branch1 : branch2;
06055 
06056    if (ast_strlen_zero(branch)) {
06057       if (option_debug)
06058          ast_log(LOG_DEBUG, "Not taking any branch\n");
06059       return 0;
06060    }
06061 
06062    rc = pbx_builtin_goto(chan, branch);
06063 
06064    return rc;
06065 }

int pbx_builtin_importvar ( struct ast_channel chan,
void *  data 
) [static]

Todo:
XXX should do !ast_strlen_zero(..) of the args ?

Definition at line 5958 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.

05959 {
05960    char *name;
05961    char *value;
05962    char *channel;
05963    char tmp[VAR_BUF_SIZE]="";
05964 
05965    if (ast_strlen_zero(data)) {
05966       ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n");
05967       return 0;
05968    }
05969 
05970    value = ast_strdupa(data);
05971    name = strsep(&value,"=");
05972    channel = strsep(&value,"|");
05973    if (channel && value && name) { /*! \todo XXX should do !ast_strlen_zero(..) of the args ? */
05974       struct ast_channel *chan2 = ast_get_channel_by_name_locked(channel);
05975       if (chan2) {
05976          char *s = alloca(strlen(value) + 4);
05977          if (s) {
05978             sprintf(s, "${%s}", value);
05979             pbx_substitute_variables_helper(chan2, s, tmp, sizeof(tmp) - 1);
05980          }
05981          ast_channel_unlock(chan2);
05982       }
05983       pbx_builtin_setvar_helper(chan, name, tmp);
05984    }
05985 
05986    return(0);
05987 }

static int pbx_builtin_noop ( struct ast_channel chan,
void *  data 
) [static]

Definition at line 6014 of file pbx.c.

06015 {
06016    return 0;
06017 }

void pbx_builtin_pushvar_helper ( struct ast_channel chan,
const char *  name,
const char *  value 
)

Note:
Will lock the channel.

Definition at line 5834 of file pbx.c.

References ast_channel_lock, ast_channel_unlock, ast_func_write(), AST_LIST_INSERT_HEAD, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_strdupa, ast_var_assign(), ast_verbose(), globals, LOG_WARNING, option_verbose, ast_channel::varshead, and VERBOSE_PREFIX_2.

Referenced by acf_odbc_read(), acf_odbc_write(), and gosub_exec().

05835 {
05836    struct ast_var_t *newvariable;
05837    struct varshead *headp;
05838 
05839    if (name[strlen(name)-1] == ')') {
05840       char *function = ast_strdupa(name);
05841 
05842       ast_log(LOG_WARNING, "Cannot push a value onto a function\n");
05843       ast_func_write(chan, function, value);
05844       return;
05845    }
05846 
05847    if (chan) {
05848       ast_channel_lock(chan);
05849       headp = &chan->varshead;
05850    } else {
05851       ast_mutex_lock(&globalslock);
05852       headp = &globals;
05853    }
05854 
05855    if (value) {
05856       if ((option_verbose > 1) && (headp == &globals))
05857          ast_verbose(VERBOSE_PREFIX_2 "Setting global variable '%s' to '%s'\n", name, value);
05858       newvariable = ast_var_assign(name, value);
05859       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
05860    }
05861 
05862    if (chan)
05863       ast_channel_unlock(chan);
05864    else
05865       ast_mutex_unlock(&globalslock);
05866 }

static int pbx_builtin_saycharacters ( struct ast_channel chan,
void *  data 
) [static]

Definition at line 6111 of file pbx.c.

References ast_channel::_state, ast_answer(), ast_say_character_str(), and AST_STATE_UP.

06112 {
06113    int res = 0;
06114 
06115    if (data) {
06116       if (chan->_state != AST_STATE_UP) {
06117           ast_answer(chan);
06118       }
06119       res = ast_say_character_str(chan, data, "", chan->language);
06120    }
06121    return res;
06122 }

static int pbx_builtin_saydigits ( struct ast_channel chan,
void *  data 
) [static]

Definition at line 6098 of file pbx.c.

References ast_channel::_state, ast_answer(), ast_say_digit_str(), and AST_STATE_UP.

06099 {
06100    int res = 0;
06101 
06102    if (data) {
06103       if (chan->_state != AST_STATE_UP) {
06104           ast_answer(chan);
06105       }
06106       res = ast_say_digit_str(chan, data, "", chan->language);
06107    }
06108    return res;
06109 }

static int pbx_builtin_saynumber ( struct ast_channel chan,
void *  data 
) [static]

Definition at line 6067 of file pbx.c.

References ast_channel::_state, ast_answer(), ast_log(), ast_say_number(), AST_STATE_UP, ast_strlen_zero(), LOG_WARNING, and strsep().

06068 {
06069    char tmp[256];
06070    char *number = tmp;
06071    char *options;
06072 
06073    if (ast_strlen_zero(data)) {
06074       ast_log(LOG_WARNING, "SayNumber requires an argument (number)\n");
06075       return -1;
06076    }
06077    ast_copy_string(tmp, data, sizeof(tmp));
06078    strsep(&number, "|");
06079    options = strsep(&number, "|");
06080    if (options) {
06081       if ( strcasecmp(options, "f") && strcasecmp(options,"m") &&
06082          strcasecmp(options, "c") && strcasecmp(options, "n") ) {
06083          ast_log(LOG_WARNING, "SayNumber gender option is either 'f', 'm', 'c' or 'n'\n");
06084          return -1;
06085       }
06086    }
06087    if (chan->_state != AST_STATE_UP) {
06088        ast_answer(chan);
06089    }
06090 
06091    if (ast_say_number(chan, atoi(tmp), "", chan->language, options)) {
06092       ast_log(LOG_WARNING, "We were unable to say the number %s, is it too large?\n", tmp);
06093    }
06094 
06095    return 0;
06096 }

static int pbx_builtin_sayphonetic ( struct ast_channel chan,
void *  data 
) [static]

Definition at line 6124 of file pbx.c.

References ast_channel::_state, ast_answer(), ast_say_phonetic_str(), and AST_STATE_UP.

06125 {
06126    int res = 0;
06127 
06128    if (data) {
06129       if (chan->_state != AST_STATE_UP) {
06130           ast_answer(chan);
06131       }
06132       res = ast_say_phonetic_str(chan, data, "", chan->language);
06133    }
06134    return res;
06135 }

int pbx_builtin_serialize_variables ( struct ast_channel chan,
char *  buf,
size_t  size 
)

Note:
Will lock the channel.

Definition at line 5765 of file pbx.c.

References ast_build_string(), ast_channel_lock, ast_channel_unlock, AST_LIST_TRAVERSE, ast_log(), ast_var_name(), ast_var_value(), LOG_ERROR, total, var, and ast_channel::varshead.

Referenced by dumpchan_exec(), handle_showchan(), handle_showchan_deprecated(), and vars2manager().

05766 {
05767    struct ast_var_t *variables;
05768    const char *var, *val;
05769    int total = 0;
05770 
05771    if (!chan)
05772       return 0;
05773 
05774    memset(buf, 0, size);
05775 
05776    ast_channel_lock(chan);
05777 
05778    AST_LIST_TRAVERSE(&chan->varshead, variables, entries) {
05779       if ((var=ast_var_name(variables)) && (val=ast_var_value(variables))
05780          /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */
05781          ) {
05782          if (ast_build_string(&buf, &size, "%s=%s\n", var, val)) {
05783             ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
05784             break;
05785          } else
05786             total++;
05787       } else
05788          break;
05789    }
05790 
05791    ast_channel_unlock(chan);
05792 
05793    return total;
05794 }

static int pbx_builtin_setglobalvar ( struct ast_channel chan,
void *  data 
) [static]

Todo:
XXX overwrites data ?

Todo:
XXX watch out, leading whitespace ?

Definition at line 5990 of file pbx.c.

References ast_log(), ast_strlen_zero(), LOG_WARNING, pbx_builtin_setvar_helper(), and strsep().

05991 {
05992    char *name;
05993    char *stringp = data;
05994    static int dep_warning = 0;
05995 
05996    if (ast_strlen_zero(data)) {
05997       ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n");
05998       return 0;
05999    }
06000 
06001    name = strsep(&stringp, "=");
06002 
06003    if (!dep_warning) {
06004       dep_warning = 1;
06005       ast_log(LOG_WARNING, "SetGlobalVar is deprecated.  Please use Set(GLOBAL(%s)=%s) instead.\n", name, stringp);
06006    }
06007 
06008    /*! \todo XXX watch out, leading whitespace ? */
06009    pbx_builtin_setvar_helper(NULL, name, stringp);
06010 
06011    return(0);
06012 }

int pbx_builtin_setvar ( struct ast_channel chan,
void *  data 
)

Definition at line 5918 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().

05919 {
05920    char *name, *value, *mydata;
05921    int argc;
05922    char *argv[24];      /* this will only support a maximum of 24 variables being set in a single operation */
05923    int global = 0;
05924    int x;
05925 
05926    if (ast_strlen_zero(data)) {
05927       ast_log(LOG_WARNING, "Set requires at least one variable name/value pair.\n");
05928       return 0;
05929    }
05930 
05931    mydata = ast_strdupa(data);
05932    argc = ast_app_separate_args(mydata, '|', argv, sizeof(argv) / sizeof(argv[0]));
05933 
05934    /* check for a trailing flags argument */
05935    if ((argc > 1) && !strchr(argv[argc-1], '=')) {
05936       argc--;
05937       if (strchr(argv[argc], 'g')) {
05938          ast_log(LOG_WARNING, "The use of the 'g' flag is deprecated.  Please use Set(GLOBAL(foo)=bar) instead\n");
05939          global = 1;
05940       }
05941    }
05942 
05943    if (argc > 1)
05944       ast_log(LOG_WARNING, "Setting multiple variables at once within Set is deprecated.  Please separate each name/value pair into its own line.\n");
05945 
05946    for (x = 0; x < argc; x++) {
05947       name = argv[x];
05948       if ((value = strchr(name, '='))) {
05949          *value++ = '\0';
05950          pbx_builtin_setvar_helper((global) ? NULL : chan, name, value);
05951       } else
05952          ast_log(LOG_WARNING, "Ignoring entry '%s' with no = (and not last 'options' entry)\n", name);
05953    }
05954 
05955    return(0);
05956 }

void pbx_builtin_setvar_helper ( struct ast_channel chan,
const char *  name,
const char *  value 
)

Note:
Will lock the channel.

Definition at line 5868 of file pbx.c.

References ast_channel_lock, ast_channel_unlock, ast_func_write(), AST_LIST_INSERT_HEAD, AST_LIST_REMOVE, AST_LIST_TRAVERSE, ast_mutex_lock(), ast_mutex_unlock(), ast_strdupa, ast_var_assign(), ast_var_delete(), ast_var_name(), ast_verbose(), globals, option_verbose, ast_channel::varshead, and VERBOSE_PREFIX_2.

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_pbx_outgoing_exten_uniqueid(), ast_set_variables(), background_detect_exec(), bridge_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_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().

05869 {
05870    struct ast_var_t *newvariable;
05871    struct varshead *headp;
05872    const char *nametail = name;
05873 
05874    if (name[strlen(name)-1] == ')') {
05875       char *function = ast_strdupa(name);
05876 
05877       ast_func_write(chan, function, value);
05878       return;
05879    }
05880 
05881    if (chan) {
05882       ast_channel_lock(chan);
05883       headp = &chan->varshead;
05884    } else {
05885       ast_mutex_lock(&globalslock);
05886       headp = &globals;
05887    }
05888 
05889    /* For comparison purposes, we have to strip leading underscores */
05890    if (*nametail == '_') {
05891       nametail++;
05892       if (*nametail == '_')
05893          nametail++;
05894    }
05895 
05896    AST_LIST_TRAVERSE (headp, newvariable, entries) {
05897       if (strcasecmp(ast_var_name(newvariable), nametail) == 0) {
05898          /* there is already such a variable, delete it */
05899          AST_LIST_REMOVE(headp, newvariable, entries);
05900          ast_var_delete(newvariable);
05901          break;
05902       }
05903    }
05904 
05905    if (value) {
05906       if ((option_verbose > 1) && (headp == &globals))
05907          ast_verbose(VERBOSE_PREFIX_2 "Setting global variable '%s' to '%s'\n", name, value);
05908       newvariable = ast_var_assign(name, value);
05909       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
05910    }
05911 
05912    if (chan)
05913       ast_channel_unlock(chan);
05914    else
05915       ast_mutex_unlock(&globalslock);
05916 }

int pbx_checkcondition ( const char *  condition  ) 

Evaluate a condition.

Return values:
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 6029 of file pbx.c.

References ast_strlen_zero().

Referenced by _macro_exec(), _while_exec(), acf_if(), execif_exec(), gosubif_exec(), macroif_exec(), and pbx_builtin_gotoif().

06030 {
06031    if (ast_strlen_zero(condition))  /* NULL or empty strings are false */
06032       return 0;
06033    else if (*condition >= '0' && *condition <= '9')   /* Numbers are evaluated for truth */
06034       return atoi(condition);
06035    else  /* Strings are true */
06036       return 1;
06037 }

static void pbx_destroy ( struct ast_pbx p  )  [static]

Definition at line 589 of file pbx.c.

References free.

Referenced by __ast_pbx_run().

00590 {
00591    free(p);
00592 }

int pbx_exec ( struct ast_channel c,
struct ast_app app,
void *  data 
)

Execute an application.

Parameters:
c channel to execute on
app which app to execute
data the data passed into the app
This application executes an application on a given channel. It saves the stack and executes the given appliation passing in the given data.

Returns:
0 on success, and -1 on failure
Parameters:
c  Channel
app  Application
data  Data for execution

Definition at line 515 of file pbx.c.

References ast_channel::appl, ast_cdr_setapp(), ast_check_hangup(), ast_channel::cdr, ast_channel::data, ast_app::execute, and S_OR.

Referenced by answer_exec_run(), ast_bridge_call(), ast_pbx_run_app(), async_wait(), builtin_automonitor(), conf_run(), dundi_exec(), exec_exec(), execif_exec(), feature_exec_app(), forward_message(), handle_exec(), iax2_exec(), milliwatt_exec(), page_exec(), pbx_builtin_execiftime(), pbx_extension_helper(), realtime_exec(), try_calling(), and tryexec_exec().

00518 {
00519    int res;
00520 
00521    const char *saved_c_appl;
00522    const char *saved_c_data;
00523 
00524    if (c->cdr && !ast_check_hangup(c))
00525       ast_cdr_setapp(c->cdr, app->name, data);
00526 
00527    /* save channel values */
00528    saved_c_appl= c->appl;
00529    saved_c_data= c->data;
00530 
00531    c->appl = app->name;
00532    c->data = data;
00533    /* XXX remember what to to when we have linked apps to modules */
00534    if (app->module) {
00535       /* XXX LOCAL_USER_ADD(app->module) */
00536    }
00537    res = app->execute(c, S_OR(data, ""));
00538    if (app->module) {
00539       /* XXX LOCAL_USER_REMOVE(app->module) */
00540    }
00541    /* restore channel values */
00542    c->appl = saved_c_appl;
00543    c->data = saved_c_data;
00544    return res;
00545 }

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.

Note:
The channel is auto-serviced in this function, because doing an extension match may block for a long time. For example, if the lookup has to use a network dialplan switch, such as DUNDi or IAX2, it may take a while. However, the channel auto-service code will queue up any important signalling frames to be processed after this is done.

Definition at line 1806 of file pbx.c.

References ast_exten::app, app, ast_log(), ast_rdlock_contexts(), ast_unlock_contexts(), ast_verbose(), COLOR_BRCYAN, COLOR_BRMAGENTA, ast_channel::context, pbx_find_info::data, E_CANMATCH, E_FINDLABEL, E_MATCH, E_MATCHMORE, EVENT_FLAG_CALL, ast_switch::exec, EXT_DATA_SIZE, ast_channel::exten, pbx_find_info::foundcontext, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, manager_event(), ast_switch::name, option_debug, option_verbose, pbx_exec(), pbx_find_extension(), pbx_findapp(), pbx_substitute_variables(), ast_channel::priority, ast_exten::priority, pbx_find_info::stacklen, pbx_find_info::status, STATUS_NO_CONTEXT, STATUS_NO_EXTENSION, STATUS_NO_LABEL, STATUS_NO_PRIORITY, pbx_find_info::swo, term_color(), and VERBOSE_PREFIX_3.

Referenced by ast_canmatch_extension(), ast_exists_extension(), ast_findlabel_extension(), ast_findlabel_extension2(), ast_matchmore_extension(), and ast_spawn_extension().

01809 {
01810    struct ast_exten *e;
01811    struct ast_app *app;
01812    int res;
01813    struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */
01814    char passdata[EXT_DATA_SIZE];
01815 
01816    int matching_action = (action == E_MATCH || action == E_CANMATCH || action == E_MATCHMORE);
01817 
01818    ast_rdlock_contexts();
01819    e = pbx_find_extension(c, con, &q, context, exten, priority, label, callerid, action);
01820    if (e) {
01821       if (matching_action) {
01822          ast_unlock_contexts();
01823          return -1;  /* success, we found it */
01824       } else if (action == E_FINDLABEL) { /* map the label to a priority */
01825          res = e->priority;
01826          ast_unlock_contexts();
01827          return res; /* the priority we were looking for */
01828       } else { /* spawn */
01829          app = pbx_findapp(e->app);
01830          ast_unlock_contexts();
01831          if (!app) {
01832             ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority);
01833             return -1;
01834          }
01835          if (c->context != context)
01836             ast_copy_string(c->context, context, sizeof(c->context));
01837          if (c->exten != exten)
01838             ast_copy_string(c->exten, exten, sizeof(c->exten));
01839          c->priority = priority;
01840          pbx_substitute_variables(passdata, sizeof(passdata), c, e);
01841          if (option_debug) {
01842             ast_log(LOG_DEBUG, "Launching '%s'\n", app->name);
01843          }
01844          if (option_verbose > 2) {
01845             char tmp[80], tmp2[80], tmp3[EXT_DATA_SIZE];
01846             ast_verbose( VERBOSE_PREFIX_3 "Executing [%s@%s:%d] %s(\"%s\", \"%s\") %s\n",
01847                exten, context, priority,
01848                term_color(tmp, app->name, COLOR_BRCYAN, 0, sizeof(tmp)),
01849                term_color(tmp2, c->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)),
01850                term_color(tmp3, passdata, COLOR_BRMAGENTA, 0, sizeof(tmp3)),
01851                "in new stack");
01852          }
01853          manager_event(EVENT_FLAG_CALL, "Newexten",
01854                "Channel: %s\r\n"
01855                "Context: %s\r\n"
01856                "Extension: %s\r\n"
01857                "Priority: %d\r\n"
01858                "Application: %s\r\n"
01859                "AppData: %s\r\n"
01860                "Uniqueid: %s\r\n",
01861                c->name, c->context, c->exten, c->priority, app->name, passdata, c->uniqueid);
01862          return pbx_exec(c, app, passdata);  /* 0 on success, -1 on failure */
01863       }
01864    } else if (q.swo) {  /* not found here, but in another switch */
01865       ast_unlock_contexts();
01866       if (matching_action) {
01867          return -1;
01868       } else {
01869          if (!q.swo->exec) {
01870             ast_log(LOG_WARNING, "No execution engine for switch %s\n", q.swo->name);
01871             res = -1;
01872          }
01873          return q.swo->exec(c, q.foundcontext ? q.foundcontext : context, exten, priority, callerid, q.data);
01874       }
01875    } else { /* not found anywhere, see what happened */
01876       ast_unlock_contexts();
01877       switch (q.status) {
01878       case STATUS_NO_CONTEXT:
01879          if (!matching_action)
01880             ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", context);
01881          break;
01882       case STATUS_NO_EXTENSION:
01883          if (!matching_action)
01884             ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, context);
01885          break;
01886       case STATUS_NO_PRIORITY:
01887          if (!matching_action)
01888             ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, context);
01889          break;
01890       case STATUS_NO_LABEL:
01891          if (context)
01892             ast_log(LOG_NOTICE, "No such label '%s' in extension '%s' in context '%s'\n", label, exten, context);
01893          break;
01894       default:
01895          if (option_debug)
01896             ast_log(LOG_DEBUG, "Shouldn't happen!\n");
01897       }
01898 
01899       return (matching_action) ? 0 : -1;
01900    }
01901 }

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 944 of file pbx.c.

References ast_autoservice_start(), ast_autoservice_stop(), 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, and pbx_find_info::swo.

Referenced by ast_hint_extension(), ast_merge_contexts_and_delete(), and pbx_extension_helper().

00948 {
00949    int x, res;
00950    struct ast_context *tmp;
00951    struct ast_exten *e, *eroot;
00952    struct ast_include *i;
00953    struct ast_sw *sw;
00954    char *tmpdata = NULL;
00955 
00956    /* Initialize status if appropriate */
00957    if (q->stacklen == 0) {
00958       q->status = STATUS_NO_CONTEXT;
00959       q->swo = NULL;
00960       q->data = NULL;
00961       q->foundcontext = NULL;
00962    }
00963    /* Check for stack overflow */
00964    if (q->stacklen >= AST_PBX_MAX_STACK) {
00965       ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n");
00966       return NULL;
00967    }
00968    /* Check first to see if we've already been checked */
00969    for (x = 0; x < q->stacklen; x++) {
00970       if (!strcasecmp(q->incstack[x], context))
00971          return NULL;
00972    }
00973    if (bypass) /* bypass means we only look there */
00974       tmp = bypass;
00975    else {   /* look in contexts */
00976       tmp = NULL;
00977       while ((tmp = ast_walk_contexts(tmp)) ) {
00978          if (!strcmp(tmp->name, context))
00979             break;
00980       }
00981       if (!tmp)
00982          return NULL;
00983    }
00984    if (q->status < STATUS_NO_EXTENSION)
00985       q->status = STATUS_NO_EXTENSION;
00986 
00987    /* scan the list trying to match extension and CID */
00988    eroot = NULL;
00989    while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) {
00990       int match = extension_match_core(eroot->exten, exten, action);
00991       /* 0 on fail, 1 on match, 2 on earlymatch */
00992 
00993       if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid)))
00994          continue;   /* keep trying */
00995       if (match == 2 && action == E_MATCHMORE) {
00996          /* We match an extension ending in '!'.
00997           * The decision in this case is final and is NULL (no match).
00998           */
00999          return NULL;
01000       }
01001       /* found entry, now look for the right priority */
01002       if (q->status < STATUS_NO_PRIORITY)
01003          q->status = STATUS_NO_PRIORITY;
01004       e = NULL;
01005       while ( (e = ast_walk_extension_priorities(eroot, e)) ) {
01006          /* Match label or priority */
01007          if (action == E_FINDLABEL) {
01008             if (q->status < STATUS_NO_LABEL)
01009                q->status = STATUS_NO_LABEL;
01010             if (label && e->label && !strcmp(label, e->label))
01011                break;   /* found it */
01012          } else if (e->priority == priority) {
01013             break;   /* found it */
01014          } /* else keep searching */
01015       }
01016       if (e) { /* found a valid match */
01017          q->status = STATUS_SUCCESS;
01018          q->foundcontext = context;
01019          return e;
01020       }
01021    }
01022    /* Check alternative switches */
01023    AST_LIST_TRAVERSE(&tmp->alts, sw, list) {
01024       struct ast_switch *asw = pbx_findswitch(sw->name);
01025       ast_switch_f *aswf = NULL;
01026       char *datap;
01027 
01028       if (!asw) {
01029          ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name);
01030          continue;
01031       }
01032       /* Substitute variables now */
01033       if (sw->eval) {
01034          if (!(tmpdata = ast_threadstorage_get(&switch_data, 512))) {
01035             ast_log(LOG_WARNING, "Can't evaluate switch?!");
01036             continue;
01037          }
01038          pbx_substitute_variables_helper(chan, sw->data, tmpdata, 512);
01039       }
01040 
01041       /* equivalent of extension_match_core() at the switch level */
01042       if (action == E_CANMATCH)
01043          aswf = asw->canmatch;
01044       else if (action == E_MATCHMORE)
01045          aswf = asw->matchmore;
01046       else /* action == E_MATCH */
01047          aswf = asw->exists;
01048       datap = sw->eval ? tmpdata : sw->data;
01049       if (!aswf)
01050          res = 0;
01051       else {
01052          if (chan)
01053             ast_autoservice_start(chan);
01054          res = aswf(chan, context, exten, priority, callerid, datap);
01055          if (chan)
01056             ast_autoservice_stop(chan);
01057       }
01058       if (res) {  /* Got a match */
01059          q->swo = asw;
01060          q->data = datap;
01061          q->foundcontext = context;
01062          /* XXX keep status = STATUS_NO_CONTEXT ? */
01063          return NULL;
01064       }
01065    }
01066    q->incstack[q->stacklen++] = tmp->name;   /* Setup the stack */
01067    /* Now try any includes we have in this context */
01068    for (i = tmp->includes; i; i = i->next) {
01069       if (include_valid(i)) {
01070          if ((e = pbx_find_extension(chan, bypass, q, i->rname, exten, priority, label, callerid, action)))
01071             return e;
01072          if (q->swo)
01073             return NULL;
01074       }
01075    }
01076    return NULL;
01077 }

struct ast_app* pbx_findapp ( const char *  app  )  [read]

Find application handle in linked list.

Look up an application.

Definition at line 553 of file pbx.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, and AST_LIST_UNLOCK.

Referenced by answer_exec_run(), ast_bridge_call(), ast_pbx_run_app(), async_wait(), builtin_automonitor(), conf_run(), dundi_exec(), exec_exec(), execif_exec(), feature_exec_app(), forward_message(), handle_exec(), iax2_exec(), milliwatt_exec(), page_exec(), pbx_builtin_execiftime(), pbx_extension_helper(), realtime_exec(), try_calling(), and tryexec_exec().

00554 {
00555    struct ast_app *tmp;
00556 
00557    AST_LIST_LOCK(&apps);
00558    AST_LIST_TRAVERSE(&apps, tmp, list) {
00559       if (!strcasecmp(tmp->name, app))
00560          break;
00561    }
00562    AST_LIST_UNLOCK(&apps);
00563 
00564    return tmp;
00565 }

static struct ast_switch* pbx_findswitch ( const char *  sw  )  [static, read]

Definition at line 567 of file pbx.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, and ast_switch::name.

Referenced by pbx_find_extension().

00568 {
00569    struct ast_switch *asw;
00570 
00571    AST_LIST_LOCK(&switches);
00572    AST_LIST_TRAVERSE(&switches, asw, list) {
00573       if (!strcasecmp(asw->name, sw))
00574          break;
00575    }
00576    AST_LIST_UNLOCK(&switches);
00577 
00578    return asw;
00579 }

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 ---

Note:
Will lock the channel.

Definition at line 1151 of file pbx.c.

References ast_channel_lock, ast_channel_unlock, ast_config_AST_SYSTEM_NAME, ast_get_hint(), AST_LIST_TRAVERSE, ast_mutex_lock(), ast_mutex_unlock(), ast_strdupa, ast_var_name(), ast_var_value(), ast_channel::cid, ast_callerid::cid_ani2, ast_callerid::cid_pres, ast_callerid::cid_tns, ast_callerid::cid_ton, ast_channel::context, ast_channel::exten, globals, ast_channel::hangupcause, offset, parse_variable_name(), ast_channel::priority, s, substring(), and ast_channel::varshead.

Referenced by action_getvar(), handle_getvariable(), and pbx_substitute_variables_helper_full().

01152 {
01153    const char not_found = '\0';
01154    char *tmpvar;
01155    const char *s; /* the result */
01156    int offset, length;
01157    int i, need_substring;
01158    struct varshead *places[2] = { headp, &globals };  /* list of places where we may look */
01159 
01160    if (c) {
01161       ast_channel_lock(c);
01162       places[0] = &c->varshead;
01163    }
01164    /*
01165     * Make a copy of var because parse_variable_name() modifies the string.
01166     * Then if called directly, we might need to run substring() on the result;
01167     * remember this for later in 'need_substring', 'offset' and 'length'
01168     */
01169    tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */
01170    need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */);
01171 
01172    /*
01173     * Look first into predefined variables, then into variable lists.
01174     * Variable 's' points to the result, according to the following rules:
01175     * s == &not_found (set at the beginning) means that we did not find a
01176     * matching variable and need to look into more places.
01177     * If s != &not_found, s is a valid result string as follows:
01178     * s = NULL if the variable does not have a value;
01179     * you typically do this when looking for an unset predefined variable.
01180     * s = workspace if the result has been assembled there;
01181     * typically done when the result is built e.g. with an snprintf(),
01182     * so we don't need to do an additional copy.
01183     * s != workspace in case we have a string, that needs to be copied
01184     * (the ast_copy_string is done once for all at the end).
01185     * Typically done when the result is already available in some string.
01186     */
01187    s = &not_found;   /* default value */
01188    if (c) { /* This group requires a valid channel */
01189       /* Names with common parts are looked up a piece at a time using strncmp. */
01190       if (!strncmp(var, "CALL", 4)) {
01191          if (!strncmp(var + 4, "ING", 3)) {
01192             if (!strcmp(var + 7, "PRES")) {        /* CALLINGPRES */
01193                snprintf(workspace, workspacelen, "%d", c->cid.cid_pres);
01194                s = workspace;
01195             } else if (!strcmp(var + 7, "ANI2")) {    /* CALLINGANI2 */
01196                snprintf(workspace, workspacelen, "%d", c->cid.cid_ani2);
01197                s = workspace;
01198             } else if (!strcmp(var + 7, "TON")) {     /* CALLINGTON */
01199                snprintf(workspace, workspacelen, "%d", c->cid.cid_ton);
01200                s = workspace;
01201             } else if (!strcmp(var + 7, "TNS")) {     /* CALLINGTNS */
01202                snprintf(workspace, workspacelen, "%d", c->cid.cid_tns);
01203                s = workspace;
01204             }
01205          }
01206       } else if (!strcmp(var, "HINT")) {
01207          s = ast_get_hint(workspace, workspacelen, NULL, 0, c, c->context, c->exten) ? workspace : NULL;
01208       } else if (!strcmp(var, "HINTNAME")) {
01209          s = ast_get_hint(NULL, 0, workspace, workspacelen, c, c->context, c->exten) ? workspace : NULL;
01210       } else if (!strcmp(var, "EXTEN")) {
01211          s = c->exten;
01212       } else if (!strcmp(var, "CONTEXT")) {
01213          s = c->context;
01214       } else if (!strcmp(var, "PRIORITY")) {
01215          snprintf(workspace, workspacelen, "%d", c->priority);
01216          s = workspace;
01217       } else if (!strcmp(var, "CHANNEL")) {
01218          s = c->name;
01219       } else if (!strcmp(var, "UNIQUEID")) {
01220          s = c->uniqueid;
01221       } else if (!strcmp(var, "HANGUPCAUSE")) {
01222          snprintf(workspace, workspacelen, "%d", c->hangupcause);
01223          s = workspace;
01224       }
01225    }
01226    if (s == &not_found) { /* look for more */
01227       if (!strcmp(var, "EPOCH")) {
01228          snprintf(workspace, workspacelen, "%u",(int)time(NULL));
01229          s = workspace;
01230       } else if (!strcmp(var, "SYSTEMNAME")) {
01231          s = ast_config_AST_SYSTEM_NAME;
01232       }
01233    }
01234    /* if not found, look into chanvars or global vars */
01235    for (i = 0; s == &not_found && i < (sizeof(places) / sizeof(places[0])); i++) {
01236       struct ast_var_t *variables;
01237       if (!places[i])
01238          continue;
01239       if (places[i] == &globals)
01240          ast_mutex_lock(&globalslock);
01241       AST_LIST_TRAVERSE(places[i], variables, entries) {
01242          if (strcasecmp(ast_var_name(variables), var)==0) {
01243             s = ast_var_value(variables);
01244             break;
01245          }
01246       }
01247       if (places[i] == &globals)
01248          ast_mutex_unlock(&globalslock);
01249    }
01250    if (s == &not_found || s == NULL)
01251       *ret = NULL;
01252    else {
01253       if (s != workspace)
01254          ast_copy_string(workspace, s, workspacelen);
01255       *ret = workspace;
01256       if (need_substring)
01257          *ret = substring(*ret, offset, length, workspace, workspacelen);
01258    }
01259 
01260    if (c)
01261       ast_channel_unlock(c);
01262 }

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 2688 of file pbx.c.

References autofallthrough.

Referenced by pbx_load_module().

02689 {
02690    int oldval = autofallthrough;
02691    autofallthrough = newval;
02692    return oldval;
02693 }

static void pbx_substitute_variables ( char *  passdata,
int  datalen,
struct ast_channel c,
struct ast_exten e 
) [static]

Definition at line 1777 of file pbx.c.

References ast_exten::data, and pbx_substitute_variables_helper().

Referenced by pbx_extension_helper().

01778 {
01779    memset(passdata, 0, datalen);
01780 
01781    /* No variables or expressions in e->data, so why scan it? */
01782    if (e->data && !strchr(e->data, '$') && !strstr(e->data,"${") && !strstr(e->data,"$[") && !strstr(e->data,"$(")) {
01783       ast_copy_string(passdata, e->data, datalen);
01784       return;
01785    }
01786 
01787    pbx_substitute_variables_helper(c, e->data, passdata, datalen - 1);
01788 }

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 
) [static]

Definition at line 1573 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().

01574 {
01575    /* Substitutes variables into cp2, based on string cp1, and assuming cp2 to be
01576       zero-filled */
01577    char *cp4;
01578    const char *tmp, *whereweare;
01579    int length, offset, offset2, isfunction;
01580    char *workspace = NULL;
01581    char *ltmp = NULL, *var = NULL;
01582    char *nextvar, *nextexp, *nextthing;
01583    char *vars, *vare;
01584    int pos, brackets, needsub, len;
01585 
01586    whereweare=tmp=cp1;
01587    while (!ast_strlen_zero(whereweare) && count) {
01588       /* Assume we're copying the whole remaining string */
01589       pos = strlen(whereweare);
01590       nextvar = NULL;
01591       nextexp = NULL;
01592       nextthing = strchr(whereweare, '$');
01593       if (nextthing) {
01594          switch(nextthing[1]) {
01595          case '{':
01596             nextvar = nextthing;
01597             pos = nextvar - whereweare;
01598             break;
01599          case '[':
01600             nextexp = nextthing;
01601             pos = nextexp - whereweare;
01602             break;
01603          default:
01604             pos = 1;
01605          }
01606       }
01607 
01608       if (pos) {
01609          /* Can't copy more than 'count' bytes */
01610          if (pos > count)
01611             pos = count;
01612 
01613          /* Copy that many bytes */
01614          memcpy(cp2, whereweare, pos);
01615 
01616          count -= pos;
01617          cp2 += pos;
01618          whereweare += pos;
01619       }
01620 
01621       if (nextvar) {
01622          /* We have a variable.  Find the start and end, and determine
01623             if we are going to have to recursively call ourselves on the
01624             contents */
01625          vars = vare = nextvar + 2;
01626          brackets = 1;
01627          needsub = 0;
01628 
01629          /* Find the end of it */
01630          while (brackets && *vare) {
01631             if ((vare[0] == '$') && (vare[1] == '{')) {
01632                needsub++;
01633             } else if (vare[0] == '{') {
01634                brackets++;
01635             } else if (vare[0] == '}') {
01636                brackets--;
01637             } else if ((vare[0] == '$') && (vare[1] == '['))
01638                needsub++;
01639             vare++;
01640          }
01641          if (brackets)
01642             ast_log(LOG_NOTICE, "Error in extension logic (missing '}')\n");
01643          len = vare - vars - 1;
01644 
01645          /* Skip totally over variable string */
01646          whereweare += (len + 3);
01647 
01648          if (!var)
01649             var = alloca(VAR_BUF_SIZE);
01650 
01651          /* Store variable name (and truncate) */
01652          ast_copy_string(var, vars, len + 1);
01653 
01654          /* Substitute if necessary */
01655          if (needsub) {
01656             if (!ltmp)
01657                ltmp = alloca(VAR_BUF_SIZE);
01658 
01659             memset(ltmp, 0, VAR_BUF_SIZE);
01660             pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1);
01661             vars = ltmp;
01662          } else {
01663             vars = var;
01664          }
01665 
01666          if (!workspace)
01667             workspace = alloca(VAR_BUF_SIZE);
01668 
01669          workspace[0] = '\0';
01670 
01671          parse_variable_name(vars, &offset, &offset2, &isfunction);
01672          if (isfunction) {
01673             /* Evaluate function */
01674             if (c || !headp)
01675                cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
01676             else {
01677                struct varshead old;
01678                struct ast_channel *c = ast_channel_alloc(0, 0, "", "", "", "", "", 0, "Bogus/%p", vars);
01679                if (c) {
01680                   memcpy(&old, &c->varshead, sizeof(old));
01681                   memcpy(&c->varshead, headp, sizeof(c->varshead));
01682                   cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
01683                   /* Don't deallocate the varshead that was passed in */
01684                   memcpy(&c->varshead, &old, sizeof(c->varshead));
01685                   ast_channel_free(c);
01686                } else
01687                   ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution.  Function results may be blank.\n");
01688             }
01689 
01690             if (option_debug)
01691                ast_log(LOG_DEBUG, "Function result is '%s'\n", cp4 ? cp4 : "(null)");
01692          } else {
01693             /* Retrieve variable value */
01694             pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp);
01695          }
01696          if (cp4) {
01697             cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE);
01698 
01699             length = strlen(cp4);
01700             if (length > count)
01701                length = count;
01702             memcpy(cp2, cp4, length);
01703             count -= length;
01704             cp2 += length;
01705          }
01706       } else if (nextexp) {
01707          /* We have an expression.  Find the start and end, and determine
01708             if we are going to have to recursively call ourselves on the
01709             contents */
01710          vars = vare = nextexp + 2;
01711          brackets = 1;
01712          needsub = 0;
01713 
01714          /* Find the end of it */
01715          while(brackets && *vare) {
01716             if ((vare[0] == '$') && (vare[1] == '[')) {
01717                needsub++;
01718                brackets++;
01719                vare++;
01720             } else if (vare[0] == '[') {
01721                brackets++;
01722             } else if (vare[0] == ']') {
01723                brackets--;
01724             } else if ((vare[0] == '$') && (vare[1] == '{')) {
01725                needsub++;
01726                vare++;
01727             }
01728             vare++;
01729          }
01730          if (brackets)
01731             ast_log(LOG_NOTICE, "Error in extension logic (missing ']')\n");
01732          len = vare - vars - 1;
01733 
01734          /* Skip totally over expression */
01735          whereweare += (len + 3);
01736 
01737          if (!var)
01738             var = alloca(VAR_BUF_SIZE);
01739 
01740          /* Store variable name (and truncate) */
01741          ast_copy_string(var, vars, len + 1);
01742 
01743          /* Substitute if necessary */
01744          if (needsub) {
01745             if (!ltmp)
01746                ltmp = alloca(VAR_BUF_SIZE);
01747 
01748             memset(ltmp, 0, VAR_BUF_SIZE);
01749             pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1);
01750             vars = ltmp;
01751          } else {
01752             vars = var;
01753          }
01754 
01755          length = ast_expr(vars, cp2, count);
01756 
01757          if (length) {
01758             if (option_debug)
01759                ast_log(LOG_DEBUG, "Expression result is '%s'\n", cp2);
01760             count -= length;
01761             cp2 += length;
01762          }
01763       }
01764    }
01765 }

void pbx_substitute_variables_varshead ( struct varshead *  headp,
const char *  cp1,
char *  cp2,
int  count 
)

Definition at line 1772 of file pbx.c.

References pbx_substitute_variables_helper_full().

Referenced by ast_add_extension2(), do_say(), dundi_lookup_local(), and loopback_subst().

01773 {
01774    pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count);
01775 }

static void* pbx_thread ( void *  data  )  [static]

Definition at line 2624 of file pbx.c.

References __ast_pbx_run(), and decrease_call_count().

Referenced by ast_pbx_start().

02625 {
02626    /* Oh joyeous kernel, we're a new thread, with nothing to do but
02627       answer this channel and get it going.
02628    */
02629    /* NOTE:
02630       The launcher of this function _MUST_ increment 'countcalls'
02631       before invoking the function; it will be decremented when the
02632       PBX has finished running on the channel
02633     */
02634    struct ast_channel *c = data;
02635 
02636    __ast_pbx_run(c);
02637    decrease_call_count();
02638 
02639    pthread_exit(NULL);
02640 
02641    return NULL;
02642 }

static void print_ext ( struct ast_exten e,
char *  buf,
int  buflen 
) [static]

helper function to print an extension

Definition at line 3507 of file pbx.c.

References ast_get_extension_app(), ast_get_extension_app_data(), ast_get_extension_priority(), ast_strlen_zero(), and PRIORITY_HINT.

Referenced by show_dialplan_helper().

03508 {
03509    int prio = ast_get_extension_priority(e);
03510    if (prio == PRIORITY_HINT) {
03511       snprintf(buf, buflen, "hint: %s",
03512          ast_get_extension_app(e));
03513    } else {
03514       snprintf(buf, buflen, "%d. %s(%s)",
03515          prio, ast_get_extension_app(e),
03516          (!ast_strlen_zero(ast_get_extension_app_data(e)) ? (char *)ast_get_extension_app_data(e) : ""));
03517    }
03518 }

static void set_ext_pri ( struct ast_channel c,
const char *  exten,
int  pri 
) [static]

Definition at line 2321 of file pbx.c.

References ast_channel_lock, ast_channel_unlock, ast_channel::exten, and ast_channel::priority.

Referenced by __ast_pbx_run(), ast_pbx_outgoing_exten_uniqueid(), and pbx_builtin_waitexten().

02322 {
02323    ast_channel_lock(c);
02324    ast_copy_string(c->exten, exten, sizeof(c->exten));
02325    c->priority = pri;
02326    ast_channel_unlock(c);
02327 }

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 3521 of file pbx.c.

References ast_cli(), ast_extension_match(), ast_get_context_name(), ast_get_context_registrar(), ast_get_extension_label(), ast_get_extension_name(), ast_get_extension_registrar(), ast_get_ignorepat_name(), ast_get_ignorepat_registrar(), ast_get_include_name(), ast_get_include_registrar(), ast_get_switch_data(), ast_get_switch_name(), ast_get_switch_registrar(), ast_lock_context(), ast_log(), AST_MAX_EXTENSION, AST_PBX_MAX_STACK, ast_rdlock_contexts(), ast_unlock_context(), ast_unlock_contexts(), ast_walk_context_extensions(), ast_walk_context_ignorepats(), ast_walk_context_includes(), ast_walk_context_switches(), ast_walk_contexts(), ast_walk_extension_priorities(), dialplan_counters::context_existence, el, dialplan_counters::extension_existence, LOG_NOTICE, LOG_WARNING, print_ext(), dialplan_counters::total_context, dialplan_counters::total_exten, and dialplan_counters::total_prio.

Referenced by handle_show_dialplan().

03522 {
03523    struct ast_context *c = NULL;
03524    int res = 0, old_total_exten = dpc->total_exten;
03525 
03526    ast_rdlock_contexts();
03527 
03528    /* walk all contexts ... */
03529    while ( (c = ast_walk_contexts(c)) ) {
03530       struct ast_exten *e;
03531       struct ast_include *i;
03532       struct ast_ignorepat *ip;
03533       char buf[256], buf2[256];
03534       int context_info_printed = 0;
03535 
03536       if (context && strcmp(ast_get_context_name(c), context))
03537          continue;   /* skip this one, name doesn't match */
03538 
03539       dpc->context_existence = 1;
03540 
03541       ast_lock_context(c);
03542 
03543       /* are we looking for exten too? if yes, we print context
03544        * only if we find our extension.
03545        * Otherwise print context even if empty ?
03546        * XXX i am not sure how the rinclude is handled.
03547        * I think it ought to go inside.
03548        */
03549       if (!exten) {
03550          dpc->total_context++;
03551          ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
03552             ast_get_context_name(c), ast_get_context_registrar(c));
03553          context_info_printed = 1;
03554       }
03555 
03556       /* walk extensions ... */
03557       e = NULL;
03558       while ( (e = ast_walk_context_extensions(c, e)) ) {
03559          struct ast_exten *p;
03560 
03561          if (exten && !ast_extension_match(ast_get_extension_name(e), exten))
03562             continue;   /* skip, extension match failed */
03563 
03564          dpc->extension_existence = 1;
03565 
03566          /* may we print context info? */
03567          if (!context_info_printed) {
03568             dpc->total_context++;
03569             if (rinclude) { /* TODO Print more info about rinclude */
03570                ast_cli(fd, "[ Included context '%s' created by '%s' ]\n",
03571                   ast_get_context_name(c), ast_get_context_registrar(c));
03572             } else {
03573                ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
03574                   ast_get_context_name(c), ast_get_context_registrar(c));
03575             }
03576             context_info_printed = 1;
03577          }
03578          dpc->total_prio++;
03579 
03580          /* write extension name and first peer */
03581          snprintf(buf, sizeof(buf), "'%s' =>", ast_get_extension_name(e));
03582 
03583          print_ext(e, buf2, sizeof(buf2));
03584 
03585          ast_cli(fd, "  %-17s %-45s [%s]\n", buf, buf2,
03586             ast_get_extension_registrar(e));
03587 
03588          dpc->total_exten++;
03589          /* walk next extension peers */
03590          p = e;   /* skip the first one, we already got it */
03591          while ( (p = ast_walk_extension_priorities(e, p)) ) {
03592             const char *el = ast_get_extension_label(p);
03593             dpc->total_prio++;
03594             if (el)
03595                snprintf(buf, sizeof(buf), "   [%s]", el);
03596             else
03597                buf[0] = '\0';
03598             print_ext(p, buf2, sizeof(buf2));
03599 
03600             ast_cli(fd,"  %-17s %-45s [%s]\n", buf, buf2,
03601                ast_get_extension_registrar(p));
03602          }
03603       }
03604 
03605       /* walk included and write info ... */
03606       i = NULL;
03607       while ( (i = ast_walk_context_includes(c, i)) ) {
03608          snprintf(buf, sizeof(buf), "'%s'", ast_get_include_name(i));
03609          if (exten) {
03610             /* Check all includes for the requested extension */
03611             if (includecount >= AST_PBX_MAX_STACK) {
03612                ast_log(LOG_NOTICE, "Maximum include depth exceeded!\n");
03613             } else {
03614                int dupe=0;
03615                int x;
03616                for (x=0;x<includecount;x++) {
03617                   if (!strcasecmp(includes[x], ast_get_include_name(i))) {
03618                      dupe++;
03619                      break;
03620                   }
03621                }
03622                if (!dupe) {
03623                   includes[includecount] = ast_get_include_name(i);
03624                   show_dialplan_helper(fd, ast_get_include_name(i), exten, dpc, i, includecount + 1, includes);
03625                } else {
03626                   ast_log(LOG_WARNING, "Avoiding circular include of %s within %s\n", ast_get_include_name(i), context);
03627                }
03628             }
03629          } else {
03630             ast_cli(fd, "  Include =>        %-45s [%s]\n",
03631                buf, ast_get_include_registrar(i));
03632          }
03633       }
03634 
03635       /* walk ignore patterns and write info ... */
03636       ip = NULL;
03637       while ( (ip = ast_walk_context_ignorepats(c, ip)) ) {
03638          const char *ipname = ast_get_ignorepat_name(ip);
03639          char ignorepat[AST_MAX_EXTENSION];
03640          snprintf(buf, sizeof(buf), "'%s'", ipname);
03641          snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname);
03642          if (!exten || ast_extension_match(ignorepat, exten)) {
03643             ast_cli(fd, "  Ignore pattern => %-45s [%s]\n",
03644                buf, ast_get_ignorepat_registrar(ip));
03645          }
03646       }
03647       if (!rinclude) {
03648          struct ast_sw *sw = NULL;
03649          while ( (sw = ast_walk_context_switches(c, sw)) ) {
03650             snprintf(buf, sizeof(buf), "'%s/%s'",
03651                ast_get_switch_name(sw),
03652                ast_get_switch_data(sw));
03653             ast_cli(fd, "  Alt. Switch =>    %-45s [%s]\n",
03654                buf, ast_get_switch_registrar(sw));
03655          }
03656       }
03657 
03658       ast_unlock_context(c);
03659 
03660       /* if we print something in context, make an empty line */
03661       if (context_info_printed)
03662          ast_cli(fd, "\r\n");
03663    }
03664    ast_unlock_contexts();
03665 
03666    return (dpc->total_exten == old_total_exten) ? -1 : res;
03667 }

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 1113 of file pbx.c.

Referenced by pbx_retrieve_variable(), and pbx_substitute_variables_helper_full().

01114 {
01115    char *ret = workspace;
01116    int lr;  /* length of the input string after the copy */
01117 
01118    ast_copy_string(workspace, value, workspace_len); /* always make a copy */
01119 
01120    lr = strlen(ret); /* compute length after copy, so we never go out of the workspace */
01121 
01122    /* Quick check if no need to do anything */
01123    if (offset == 0 && length >= lr) /* take the whole string */
01124       return ret;
01125 
01126    if (offset < 0)   {  /* translate negative offset into positive ones */
01127       offset = lr + offset;
01128       if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */
01129          offset = 0;
01130    }
01131 
01132    /* too large offset result in empty string so we know what to return */
01133    if (offset >= lr)
01134       return ret + lr;  /* the final '\0' */
01135 
01136    ret += offset;    /* move to the start position */
01137    if (length >= 0 && length < lr - offset)  /* truncate if necessary */
01138       ret[length] = '\0';
01139    else if (length < 0) {
01140       if (lr > offset - length) /* After we remove from the front and from the rear, is there anything left? */
01141          ret[lr + length - offset] = '\0';
01142       else
01143          ret[0] = '\0';
01144    }
01145 
01146    return ret;
01147 }

static void wait_for_hangup ( struct ast_channel chan,
void *  data 
) [static]

Definition at line 5376 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().

05377 {
05378    int res;
05379    struct ast_frame *f;
05380    int waittime;
05381 
05382    if (ast_strlen_zero(data) || (sscanf(data, "%d", &waittime) != 1) || (waittime < 0))
05383       waittime = -1;
05384    if (waittime > -1) {
05385       ast_safe_sleep(chan, waittime * 1000);
05386    } else do {
05387       res = ast_waitfor(chan, -1);
05388       if (res < 0)
05389          return;
05390       f = ast_read(chan);
05391       if (f)
05392          ast_frfree(f);
05393    } while(f);
05394 }


Variable Documentation

int autofallthrough = 1 [static]

Definition at line 245 of file pbx.c.

Referenced by __ast_pbx_run(), and pbx_set_autofallthrough().

struct pbx_builtin builtins[] [static]

Declaration of builtin applications.

Initial value:

 {
   { "set", "global", NULL },
   handle_set_global_deprecated, NULL,
        NULL }

Definition at line 3810 of file pbx.c.

Initial value:

 {
   { "show", "application", NULL },
   handle_show_application_deprecated, NULL,
        NULL, complete_show_application }

Definition at line 3800 of file pbx.c.

Initial value:

 {
   { "show", "applications", NULL },
   handle_show_applications_deprecated, NULL,
   NULL, complete_show_applications_deprecated }

Definition at line 3770 of file pbx.c.

Initial value:

 {
   { "show", "dialplan", NULL },
   handle_show_dialplan, NULL,
        NULL, complete_show_dialplan_context }

Definition at line 3805 of file pbx.c.

Initial value:

 {
   { "show" , "function", NULL },
   handle_show_function_deprecated, NULL,
        NULL, complete_show_function }

Definition at line 3795 of file pbx.c.

Initial value:

 {
   { "show", "functions", NULL },
   handle_show_functions_deprecated, NULL,
        NULL }

Definition at line 3775 of file pbx.c.

Initial value:

 {
   { "show", "globals", NULL },
   handle_show_globals, NULL,
        NULL }

Definition at line 3790 of file pbx.c.

Initial value:

 {
   { "show", "hints", NULL },
   handle_show_hints, NULL,
        NULL }

Definition at line 3785 of file pbx.c.

Initial value:

 {
   { "show", "switches", NULL },
   handle_show_switches, NULL,
        NULL }

Definition at line 3780 of file pbx.c.

struct ast_context* contexts [static]

int countcalls [static]

Definition at line 248 of file pbx.c.

Referenced by ast_active_calls(), decrease_call_count(), and increase_call_count().

char* days[] [static]

Definition at line 4214 of file pbx.c.

Referenced by ast_build_timing().

Referenced by ast_extension_state2str().

struct varshead globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE [static]

char* months[] [static]

Definition at line 4226 of file pbx.c.

Referenced by ast_build_timing().

struct ast_cli_entry pbx_cli[] [static]

Definition at line 3815 of file pbx.c.

Referenced by load_pbx().

char set_global_help[] [static]

Initial value:

"Usage: core set global <name> <value>\n"
"       Set global dialplan variable <name> to <value>\n"

Definition at line 3084 of file pbx.c.

char show_application_help[] [static]

Initial value:

"Usage: core show application <application> [<application> [<application> [...]]]\n"
"       Describes a particular application.\n"

Definition at line 3072 of file pbx.c.

char show_applications_help[] [static]

Initial value:

"Usage: core show applications [{like|describing} <text>]\n"
"       List applications which are currently available.\n"
"       If 'like', <text> will be a substring of the app name\n"
"       If 'describing', <text> will be a substring of the description\n"

Definition at line 3050 of file pbx.c.

char show_dialplan_help[] [static]

Initial value:

"Usage: dialplan show [exten@][context]\n"
"       Show dialplan\n"

Definition at line 3080 of file pbx.c.

char show_function_help[] [static]

Initial value:

"Usage: core show function <function>\n"
"       Describe a particular dialplan function.\n"

Definition at line 3076 of file pbx.c.

char show_functions_help[] [static]

Initial value:

"Usage: core show functions [like <text>]\n"
"       List builtin functions, optionally only those matching a given string\n"

Definition at line 3056 of file pbx.c.

char show_globals_help[] [static]

Initial value:

"Usage: core show globals\n"
"       List current global dialplan variables and their values\n"

Definition at line 3068 of file pbx.c.

char show_hints_help[] [static]

Initial value:

"Usage: core show hints\n"
"       List registered hints\n"

Definition at line 3064 of file pbx.c.

char show_switches_help[] [static]

Initial value:

"Usage: core show switches\n"
"       List registered switches\n"

Definition at line 3060 of file pbx.c.

Definition at line 510 of file pbx.c.

Referenced by ast_extension_state_add(), ast_extension_state_del(), and ast_hint_state_changed().

int stateid = 1 [static]

Definition at line 502 of file pbx.c.

Referenced by ast_extension_state_add().


Generated on Sun Dec 18 20:55:52 2011 for Asterisk - the Open Source PBX by  doxygen 1.5.6