Fri Aug 24 02:27:05 2007

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 dependency graph for pbx.c:

Go to the source code of this file.

Data Structures

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

Defines

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

Enumerations

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

Functions

static struct ast_context__ast_context_create (struct ast_context **extcontexts, const char *name, const char *registrar, int existsokay)
void __ast_context_destroy (struct ast_context *con, const char *registrar)
static int __ast_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority, int async)
static int __ast_pbx_run (struct ast_channel *c)
static int _extension_match_core (const char *pattern, const char *data, enum ext_match_t mode)
static int add_pri (struct ast_context *con, struct ast_exten *tmp, struct ast_exten *el, struct ast_exten *e, int replace)
 add the extension in the priority chain. returns 0 on success, -1 on failure
int ast_active_calls (void)
 Retrieve the number of active calls.
int ast_add_extension (const char *context, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar)
 Add and extension to an extension context.
int ast_add_extension2 (struct ast_context *con, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar)
 Add an extension to an extension context, this time with an ast_context *.
static int ast_add_hint (struct ast_exten *e)
 ast_add_hint: Add hint to hint list, check initial extension state
 AST_APP_OPTIONS (resetcdr_opts,{AST_APP_OPTION('w', AST_CDR_FLAG_POSTED), AST_APP_OPTION('a', AST_CDR_FLAG_LOCKED), AST_APP_OPTION('v', AST_CDR_FLAG_KEEP_VARS),})
 AST_APP_OPTIONS (waitexten_opts,{AST_APP_OPTION_ARG('m', WAITEXTEN_MOH, 0),})
 AST_APP_OPTIONS (background_opts,{AST_APP_OPTION('s', BACKGROUND_SKIP), AST_APP_OPTION('n', BACKGROUND_NOANSWER), AST_APP_OPTION('m', BACKGROUND_MATCHEXTEN), AST_APP_OPTION('p', BACKGROUND_PLAYBACK),})
int ast_async_goto (struct ast_channel *chan, const char *context, const char *exten, int priority)
int ast_async_goto_by_name (const char *channame, const char *context, const char *exten, int priority)
int ast_async_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority)
int ast_build_timing (struct ast_timing *i, const char *info_in)
int ast_canmatch_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
 Looks for a valid matching extension.
static int ast_change_hint (struct ast_exten *oe, struct ast_exten *ne)
 ast_change_hint: Change hint for an extension
int ast_check_timing (const struct ast_timing *i)
int ast_context_add_ignorepat (const char *context, const char *value, const char *registrar)
 Add an ignorepat.
int ast_context_add_ignorepat2 (struct ast_context *con, const char *value, const char *registrar)
int ast_context_add_include (const char *context, const char *include, const char *registrar)
 Add a context include.
int ast_context_add_include2 (struct ast_context *con, const char *value, const char *registrar)
 Add a context include.
int ast_context_add_switch (const char *context, const char *sw, const char *data, int eval, const char *registrar)
 Add a switch.
int ast_context_add_switch2 (struct ast_context *con, const char *value, const char *data, int eval, const char *registrar)
 Adds a switch (first param is a ast_context).
ast_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).
ast_contextast_context_find (const char *name)
 Find a context.
ast_contextast_context_find_or_create (struct ast_context **extcontexts, const char *name, const char *registrar)
 Register a new context or find an existing one.
int ast_context_lockmacro (const char *context)
 locks the macrolock in the given given context
int ast_context_remove_extension (const char *context, const char *extension, int priority, const char *registrar)
 Simply remove extension from context.
int ast_context_remove_extension2 (struct ast_context *con, const char *extension, int priority, const char *registrar)
 This functionc locks given context, search for the right extension and fires out all peer in this extensions with given priority. If priority is set to 0, all peers are removed. After that, unlock context and return.
int ast_context_remove_ignorepat (const char *context, const char *ignorepat, const char *registrar)
int ast_context_remove_ignorepat2 (struct ast_context *con, const char *ignorepat, const char *registrar)
int ast_context_remove_include (const char *context, const char *include, const char *registrar)
 Remove a context include.
int ast_context_remove_include2 (struct ast_context *con, const char *include, const char *registrar)
 Removes an include by an ast_context structure.
int ast_context_remove_switch (const char *context, const char *sw, const char *data, const char *registrar)
 Remove a switch.
int ast_context_remove_switch2 (struct ast_context *con, const char *sw, const char *data, const char *registrar)
 This function locks given context, removes switch, unlock context and return.
int ast_context_unlockmacro (const char *context)
 Unlocks the macrolock in the given context.
int ast_context_verify_includes (struct ast_context *con)
 Verifies includes in an ast_contect structure.
ast_custom_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)
 Uses hint and devicestate callback to get the state of an extension.
static int ast_extension_state2 (struct ast_exten *e)
 ast_extensions_state2: Check state of extension by using hints
const char * ast_extension_state2str (int extension_state)
 Return string representation of the state of an extension.
int ast_extension_state_add (const char *context, const char *exten, ast_state_cb_type callback, void *data)
 Registers a state change callback.
int ast_extension_state_del (int id, ast_state_cb_type callback)
 Deletes a registered state change callback by ID.
int ast_findlabel_extension (struct ast_channel *c, const char *context, const char *exten, const char *label, const char *callerid)
 Find the priority of an extension that has the specified label.
int ast_findlabel_extension2 (struct ast_channel *c, struct ast_context *con, const char *exten, const char *label, const char *callerid)
 Find the priority of an extension that has the specified label.
int ast_func_read (struct ast_channel *chan, char *function, char *workspace, size_t len)
 executes a read operation on a function
int ast_func_write (struct ast_channel *chan, char *function, const char *value)
 executes a write operation on a function
const char * ast_get_context_name (struct ast_context *con)
const char * ast_get_context_registrar (struct ast_context *c)
const char * ast_get_extension_app (struct ast_exten *e)
void * ast_get_extension_app_data (struct ast_exten *e)
const char * ast_get_extension_cidmatch (struct ast_exten *e)
ast_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)
 If an extension hint exists, return non-zero.
const char * ast_get_ignorepat_name (struct ast_ignorepat *ip)
const char * ast_get_ignorepat_registrar (struct ast_ignorepat *ip)
const char * ast_get_include_name (struct ast_include *inc)
const char * ast_get_include_registrar (struct ast_include *i)
const char * ast_get_switch_data (struct ast_sw *sw)
const char * ast_get_switch_name (struct ast_sw *sw)
const char * ast_get_switch_registrar (struct ast_sw *sw)
int ast_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority)
static struct ast_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)
int ast_ignore_pattern (const char *context, const char *pattern)
 Checks to see if a number should be ignored.
 AST_LIST_HEAD (store_hints, store_hint)
static AST_LIST_HEAD_STATIC (hints, ast_hint)
static AST_LIST_HEAD_STATIC (switches, ast_switch)
static AST_LIST_HEAD_STATIC (apps, ast_app)
static AST_LIST_HEAD_STATIC (acf_root, ast_custom_function)
int ast_lock_context (struct ast_context *con)
 Locks a given context.
int ast_lock_contexts ()
 Locks the context list.
int ast_matchmore_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
 Looks to see if adding anything to this extension might match something. (exists ^ canmatch).
void ast_merge_contexts_and_delete (struct ast_context **extcontexts, const char *registrar)
 Merge the temporary contexts into a global contexts list and delete from the global list the ones that are being added.
 AST_MUTEX_DEFINE_STATIC (conlock)
 AST_MUTEX_DEFINE_STATIC (maxcalllock)
 AST_MUTEX_DEFINE_STATIC (globalslock)
int ast_parseable_goto (struct ast_channel *chan, const char *goto_string)
int ast_pbx_outgoing_app (const char *type, int format, void *data, int timeout, const char *app, const char *appdata, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel)
static int ast_pbx_outgoing_cdr_failed (void)
int ast_pbx_outgoing_exten (const char *type, int format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **channel)
enum ast_pbx_result ast_pbx_run (struct ast_channel *c)
 Execute the PBX in the current thread.
static void * ast_pbx_run_app (void *data)
 run the application and free the descriptor once done
enum ast_pbx_result ast_pbx_start (struct ast_channel *c)
 Create a new thread and start the PBX.
int ast_register_application (const char *app, int(*execute)(struct ast_channel *, void *), const char *synopsis, const char *description)
 Register an application.
int ast_register_switch (struct ast_switch *sw)
 Register an alternative dialplan switch.
static int ast_remove_hint (struct ast_exten *e)
 ast_remove_hint: Remove hint from extension
int ast_spawn_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
 Launch a new extension (i.e. new stack).
int ast_unlock_context (struct ast_context *con)
int ast_unlock_contexts ()
 Unlocks contexts.
int ast_unregister_application (const char *app)
 Unregister an application.
void ast_unregister_switch (struct ast_switch *sw)
 Unregister an alternative switch.
ast_extenast_walk_context_extensions (struct ast_context *con, struct ast_exten *exten)
ast_ignorepatast_walk_context_ignorepats (struct ast_context *con, struct ast_ignorepat *ip)
ast_includeast_walk_context_includes (struct ast_context *con, struct ast_include *inc)
ast_swast_walk_context_switches (struct ast_context *con, struct ast_sw *sw)
ast_contextast_walk_contexts (struct ast_context *con)
ast_extenast_walk_extension_priorities (struct ast_exten *exten, struct ast_exten *priority)
static void * async_wait (void *data)
static int collect_digits (struct ast_channel *c, int waittime, char *buf, int buflen, int pos)
 collect digits from the channel into the buffer, return -1 on error, 0 on timeout or done.
static char * complete_show_application (const char *line, const char *word, int pos, int state)
static char * complete_show_applications (const char *line, const char *word, int pos, int state)
static char * complete_show_applications_deprecated (const char *line, const char *word, int pos, int state)
static char * complete_show_dialplan_context (const char *line, const char *word, int pos, int state)
static char * complete_show_function (const char *line, const char *word, int pos, int state)
static void decrease_call_count (void)
static void destroy_exten (struct ast_exten *e)
static int ext_cmp (const char *a, const char *b)
 the full routine to compare extensions in rules.
static int ext_cmp1 (const char **p)
 helper functions to sort extensions and patterns in the desired way, so that more specific patterns appear first.
static int ext_strncpy (char *dst, const char *src, int len)
 copy a string skipping whitespace
static int extension_match_core (const char *pattern, const char *data, enum ext_match_t mode)
static struct ast_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 registered dial plan hints
static int handle_show_switches (int fd, int argc, char *argv[])
 handle_show_switches: CLI support for listing registered dial plan switches
static int include_valid (struct ast_include *i)
static int increase_call_count (const struct ast_channel *c)
int load_pbx (void)
static int lookup_name (const char *s, char *const names[], int max)
 Helper for get_range. return the index of the matching entry, starting from 1. If names is not supplied, try numeric values.
static int matchcid (const char *cidpattern, const char *callerid)
static int parse_variable_name (char *var, int *offset, int *length, int *isfunc)
 extract offset:length from variable name. Returns 1 if there is a offset:length part, which is trimmed off (values go into variables)
static int pbx_builtin_answer (struct ast_channel *, void *)
static int pbx_builtin_background (struct ast_channel *, void *)
static int pbx_builtin_busy (struct ast_channel *, void *)
void pbx_builtin_clear_globals (void)
static int pbx_builtin_congestion (struct ast_channel *, void *)
static int pbx_builtin_execiftime (struct ast_channel *, void *)
const char * pbx_builtin_getvar_helper (struct ast_channel *chan, const char *name)
static int pbx_builtin_goto (struct ast_channel *, void *)
static int pbx_builtin_gotoif (struct ast_channel *, void *)
static int pbx_builtin_gotoiftime (struct ast_channel *, void *)
static int pbx_builtin_hangup (struct ast_channel *, void *)
static int pbx_builtin_importvar (struct ast_channel *, void *)
static int pbx_builtin_noop (struct ast_channel *, void *)
static int pbx_builtin_progress (struct ast_channel *, void *)
void pbx_builtin_pushvar_helper (struct ast_channel *chan, const char *name, const char *value)
static int pbx_builtin_resetcdr (struct ast_channel *, void *)
static int pbx_builtin_ringing (struct ast_channel *, void *)
static int pbx_builtin_saycharacters (struct ast_channel *, void *)
static int pbx_builtin_saydigits (struct ast_channel *, void *)
static int pbx_builtin_saynumber (struct ast_channel *, void *)
static int pbx_builtin_sayphonetic (struct ast_channel *, void *)
int pbx_builtin_serialize_variables (struct ast_channel *chan, char *buf, size_t size)
static int pbx_builtin_setamaflags (struct ast_channel *, void *)
static int pbx_builtin_setglobalvar (struct ast_channel *, void *)
int pbx_builtin_setvar (struct ast_channel *, void *)
void pbx_builtin_setvar_helper (struct ast_channel *chan, const char *name, const char *value)
static int pbx_builtin_wait (struct ast_channel *, void *)
static int pbx_builtin_waitexten (struct ast_channel *, void *)
int pbx_checkcondition (const char *condition)
 Evaluate a condition.
static void pbx_destroy (struct ast_pbx *p)
int pbx_exec (struct ast_channel *c, struct ast_app *app, void *data)
 Execute an application.
static int pbx_extension_helper (struct ast_channel *c, struct ast_context *con, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action)
 The return value depends on the action:.
static struct ast_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)
ast_apppbx_findapp (const char *app)
 Look up an application.
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)
 Support for Asterisk built-in variables and functions in the dialplan.
int pbx_set_autofallthrough (int newval)
static void pbx_substitute_variables (char *passdata, int datalen, struct ast_channel *c, struct ast_exten *e)
void pbx_substitute_variables_helper (struct ast_channel *c, const char *cp1, char *cp2, int count)
static void pbx_substitute_variables_helper_full (struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count)
void pbx_substitute_variables_varshead (struct varshead *headp, const char *cp1, char *cp2, int count)
static void * pbx_thread (void *data)
static void print_ext (struct ast_exten *e, char *buf, int buflen)
 helper function to print an extension
static void set_ext_pri (struct ast_channel *c, const char *exten, int pri)
static int show_dialplan_helper (int fd, const char *context, const char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude, int includecount, const char *includes[])
static char * substring (const char *value, int offset, int length, char *workspace, size_t workspace_len)
 takes a substring. It is ok to call with value == workspace.
static void wait_for_hangup (struct ast_channel *chan, void *data)

Variables

static int autofallthrough = 1
static struct pbx_builtin builtins []
 Declaration of builtin applications.
static struct ast_cli_entry cli_set_global_deprecated
static struct ast_cli_entry cli_show_application_deprecated
static struct ast_cli_entry cli_show_applications_deprecated
static struct ast_cli_entry cli_show_dialplan_deprecated
static struct ast_cli_entry cli_show_function_deprecated
static struct ast_cli_entry cli_show_functions_deprecated
static struct ast_cli_entry cli_show_globals_deprecated
static struct ast_cli_entry cli_show_hints_deprecated
static struct ast_cli_entry cli_show_switches_deprecated
static struct ast_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 []
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 546 of file pbx.c.

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

#define BACKGROUND_MATCHEXTEN   (1 << 2)

Definition at line 90 of file pbx.c.

Referenced by pbx_builtin_background().

#define BACKGROUND_NOANSWER   (1 << 1)

Definition at line 89 of file pbx.c.

Referenced by pbx_builtin_background().

#define BACKGROUND_PLAYBACK   (1 << 3)

Definition at line 91 of file pbx.c.

Referenced by pbx_builtin_background().

#define BACKGROUND_SKIP   (1 << 0)

Definition at line 88 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 77 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 904 of file pbx.c.

Referenced by pbx_extension_helper(), and pbx_find_extension().

#define STATUS_NO_EXTENSION   2

Definition at line 905 of file pbx.c.

Referenced by pbx_extension_helper(), and pbx_find_extension().

#define STATUS_NO_LABEL   4

Definition at line 907 of file pbx.c.

Referenced by pbx_extension_helper(), and pbx_find_extension().

#define STATUS_NO_PRIORITY   3

Definition at line 906 of file pbx.c.

Referenced by pbx_extension_helper(), and pbx_find_extension().

#define STATUS_SUCCESS   5

Definition at line 908 of file pbx.c.

Referenced by pbx_find_extension().

#define SWITCH_DATA_LENGTH   256

Definition at line 80 of file pbx.c.

Referenced by ast_context_add_switch2().

#define VAR_BUF_SIZE   4096

Definition at line 82 of file pbx.c.

Referenced by ast_add_extension2(), pbx_builtin_importvar(), and pbx_substitute_variables_helper_full().

#define VAR_HARDTRAN   3

Definition at line 86 of file pbx.c.

#define VAR_NORMAL   1

Definition at line 84 of file pbx.c.

#define VAR_SOFTTRAN   2

Definition at line 85 of file pbx.c.

#define WAITEXTEN_MOH   (1 << 0)

Definition at line 100 of file pbx.c.

Referenced by pbx_builtin_waitexten().


Enumeration Type Documentation

enum ext_match_t

When looking up extensions, we can have different requests identified by the 'action' argument, as follows. Note that the coding is such that the low 4 bits are the third argument to extension_match_core.

Enumerator:
E_MATCHMORE 
E_CANMATCH 
E_MATCH 
E_MATCH_MASK 
E_SPAWN 
E_FINDLABEL 

Definition at line 751 of file pbx.c.

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


Function Documentation

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

Definition at line 3846 of file pbx.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), contexts, local_contexts, LOG_WARNING, name, and ast_context::next.

Referenced by ast_context_create(), and ast_context_find_or_create().

03847 {
03848    struct ast_context *tmp, **local_contexts;
03849    int length = sizeof(struct ast_context) + strlen(name) + 1;
03850 
03851    if (!extcontexts) {
03852       ast_mutex_lock(&conlock);
03853       local_contexts = &contexts;
03854    } else
03855       local_contexts = extcontexts;
03856 
03857    for (tmp = *local_contexts; tmp; tmp = tmp->next) {
03858       if (!strcasecmp(tmp->name, name)) {
03859          if (!existsokay) {
03860             ast_log(LOG_WARNING, "Tried to register context '%s', already in use\n", name);
03861             tmp = NULL;
03862          }
03863          if (!extcontexts)
03864             ast_mutex_unlock(&conlock);
03865          return tmp;
03866       }
03867    }
03868    if ((tmp = ast_calloc(1, length))) {
03869       ast_mutex_init(&tmp->lock);
03870       ast_mutex_init(&tmp->macrolock);
03871       strcpy(tmp->name, name);
03872       tmp->root = NULL;
03873       tmp->registrar = registrar;
03874       tmp->next = *local_contexts;
03875       tmp->includes = NULL;
03876       tmp->ignorepats = NULL;
03877       *local_contexts = tmp;
03878       if (option_debug)
03879          ast_log(LOG_DEBUG, "Registered context '%s'\n", tmp->name);
03880       if (option_verbose > 2)
03881          ast_verbose( VERBOSE_PREFIX_3 "Registered extension context '%s'\n", tmp->name);
03882    }
03883 
03884    if (!extcontexts)
03885       ast_mutex_unlock(&conlock);
03886    return tmp;
03887 }

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

Definition at line 5265 of file pbx.c.

References AST_LIST_REMOVE_HEAD, ast_log(), ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), contexts, destroy_exten(), el, free, ast_exten::next, ast_include::next, ast_context::next, ast_ignorepat::next, and ast_exten::peer.

Referenced by ast_context_destroy(), and ast_merge_contexts_and_delete().

05266 {
05267    struct ast_context *tmp, *tmpl=NULL;
05268    struct ast_include *tmpi;
05269    struct ast_sw *sw;
05270    struct ast_exten *e, *el, *en;
05271    struct ast_ignorepat *ipi;
05272 
05273    ast_mutex_lock(&conlock);
05274    for (tmp = contexts; tmp; ) {
05275       struct ast_context *next;  /* next starting point */
05276       for (; tmp; tmpl = tmp, tmp = tmp->next) {
05277          if (option_debug)
05278             ast_log(LOG_DEBUG, "check ctx %s %s\n", tmp->name, tmp->registrar);
05279          if ( (!registrar || !strcasecmp(registrar, tmp->registrar)) &&
05280               (!con || !strcasecmp(tmp->name, con->name)) )
05281             break;   /* found it */
05282       }
05283       if (!tmp)   /* not found, we are done */
05284          break;
05285       ast_mutex_lock(&tmp->lock);
05286       if (option_debug)
05287          ast_log(LOG_DEBUG, "delete ctx %s %s\n", tmp->name, tmp->registrar);
05288       next = tmp->next;
05289       if (tmpl)
05290          tmpl->next = next;
05291       else
05292          contexts = next;
05293       /* Okay, now we're safe to let it go -- in a sense, we were
05294          ready to let it go as soon as we locked it. */
05295       ast_mutex_unlock(&tmp->lock);
05296       for (tmpi = tmp->includes; tmpi; ) { /* Free includes */
05297          struct ast_include *tmpil = tmpi;
05298          tmpi = tmpi->next;
05299          free(tmpil);
05300       }
05301       for (ipi = tmp->ignorepats; ipi; ) { /* Free ignorepats */
05302          struct ast_ignorepat *ipl = ipi;
05303          ipi = ipi->next;
05304          free(ipl);
05305       }
05306       while ((sw = AST_LIST_REMOVE_HEAD(&tmp->alts, list)))
05307          free(sw);
05308       for (e = tmp->root; e;) {
05309          for (en = e->peer; en;) {
05310             el = en;
05311             en = en->peer;
05312             destroy_exten(el);
05313          }
05314          el = e;
05315          e = e->next;
05316          destroy_exten(el);
05317       }
05318       ast_mutex_destroy(&tmp->lock);
05319       free(tmp);
05320       /* if we have a specific match, we are done, otherwise continue */
05321       tmp = con ? NULL : next;
05322    }
05323    ast_mutex_unlock(&conlock);
05324 }

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

Definition at line 6257 of file pbx.c.

References ast_async_goto(), ast_exists_extension(), ast_explicit_goto(), ast_channel::cid, ast_callerid::cid_num, ast_channel::context, and ast_channel::exten.

Referenced by ast_async_goto_if_exists(), and ast_goto_if_exists().

06258 {
06259    int (*goto_func)(struct ast_channel *chan, const char *context, const char *exten, int priority);
06260 
06261    if (!chan)
06262       return -2;
06263 
06264    if (context == NULL)
06265       context = chan->context;
06266    if (exten == NULL)
06267       exten = chan->exten;
06268 
06269    goto_func = (async) ? ast_async_goto : ast_explicit_goto;
06270    if (ast_exists_extension(chan, context, exten, priority, chan->cid.cid_num))
06271       return goto_func(chan, context, exten, priority);
06272    else
06273       return -3;
06274 }

static int __ast_pbx_run ( struct ast_channel c  )  [static]

Definition at line 2334 of file pbx.c.

References ast_channel::_softhangup, ast_channel::amaflags, ast_calloc, ast_cdr_alloc(), ast_cdr_init(), ast_cdr_start(), ast_exists_extension(), AST_FLAG_IN_AUTOLOOP, ast_log(), AST_PBX_KEEPALIVE, ast_set_flag, AST_SOFTHANGUP_ASYNCGOTO, AST_SOFTHANGUP_TIMEOUT, ast_spawn_extension(), ast_test_flag, ast_verbose(), ast_channel::cdr, ast_channel::cid, ast_callerid::cid_num, ast_channel::context, ast_pbx::dtimeout, error(), ast_channel::exten, free, LOG_DEBUG, LOG_WARNING, option_debug, option_verbose, ast_channel::pbx, ast_channel::priority, ast_pbx::rtimeout, set_ext_pri(), ast_cdr::start, and VERBOSE_PREFIX_2.

Referenced by ast_pbx_run(), and pbx_thread().

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

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

Definition at line 769 of file pbx.c.

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

Referenced by extension_match_core().

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

static int add_pri ( struct ast_context con,
struct ast_exten tmp,
struct ast_exten el,
struct ast_exten e,
int  replace 
) [static]

add the extension in the priority chain. returns 0 on success, -1 on failure

Definition at line 4656 of file pbx.c.

References ast_change_hint(), ast_log(), ast_exten::data, ast_exten::datad, el, ast_exten::exten, free, LOG_WARNING, ast_exten::next, ast_exten::peer, ast_exten::priority, PRIORITY_HINT, and ast_context::root.

Referenced by ast_add_extension2().

04658 {
04659    struct ast_exten *ep;
04660 
04661    for (ep = NULL; e ; ep = e, e = e->peer) {
04662       if (e->priority >= tmp->priority)
04663          break;
04664    }
04665    if (!e) {   /* go at the end, and ep is surely set because the list is not empty */
04666       ep->peer = tmp;
04667       return 0;   /* success */
04668    }
04669    if (e->priority == tmp->priority) {
04670       /* Can't have something exactly the same.  Is this a
04671          replacement?  If so, replace, otherwise, bonk. */
04672       if (!replace) {
04673          ast_log(LOG_WARNING, "Unable to register extension '%s', priority %d in '%s', already in use\n", tmp->exten, tmp->priority, con->name);
04674          if (tmp->datad)
04675             tmp->datad(tmp->data);
04676          free(tmp);
04677          return -1;
04678       }
04679       /* we are replacing e, so copy the link fields and then update
04680        * whoever pointed to e to point to us
04681        */
04682       tmp->next = e->next; /* not meaningful if we are not first in the peer list */
04683       tmp->peer = e->peer; /* always meaningful */
04684       if (ep)        /* We're in the peer list, just insert ourselves */
04685          ep->peer = tmp;
04686       else if (el)      /* We're the first extension. Take over e's functions */
04687          el->next = tmp;
04688       else        /* We're the very first extension.  */
04689          con->root = tmp;
04690       if (tmp->priority == PRIORITY_HINT)
04691          ast_change_hint(e,tmp);
04692       /* Destroy the old one */
04693       if (e->datad)
04694          e->datad(e->data);
04695       free(e);
04696    } else { /* Slip ourselves in just before e */
04697       tmp->peer = e;
04698       tmp->next = e->next; /* extension chain, or NULL if e is not the first extension */
04699       if (ep)        /* Easy enough, we're just in the peer list */
04700          ep->peer = tmp;
04701       else {         /* we are the first in some peer list, so link in the ext list */
04702          if (el)
04703             el->next = tmp;   /* in the middle... */
04704          else
04705             con->root = tmp; /* ... or at the head */
04706          e->next = NULL;   /* e is no more at the head, so e->next must be reset */
04707       }
04708       /* And immediately return success. */
04709       if (tmp->priority == PRIORITY_HINT)
04710           ast_add_hint(tmp);
04711    }
04712    return 0;
04713 }

int ast_active_calls ( void   ) 

Retrieve the number of active calls.

Definition at line 2656 of file pbx.c.

References countcalls.

Referenced by handle_chanlist(), and handle_chanlist_deprecated().

02657 {
02658    return countcalls;
02659 }

int ast_add_extension ( const char *  context,
int  replace,
const char *  extension,
int  priority,
const char *  label,
const char *  callerid,
const char *  application,
void *  data,
void(*)(void *)  datad,
const char *  registrar 
)

Add and extension to an extension context.

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

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

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

04539 {
04540    int ret = -1;
04541    struct ast_context *c = find_context_locked(context);
04542 
04543    if (c) {
04544       ret = ast_add_extension2(c, replace, extension, priority, label, callerid,
04545          application, data, datad, registrar);
04546       ast_unlock_contexts();
04547    }
04548    return ret;
04549 }

int ast_add_extension2 ( struct ast_context con,
int  replace,
const char *  extension,
int  priority,
const char *  label,
const char *  callerid,
const char *  application,
void *  data,
void(*)(void *)  datad,
const char *  registrar 
)

Add an extension to an extension context, this time with an ast_context *.

We sort extensions in order of matching preference, so that we can stop the search as soon as we find a suitable match. This ordering also takes care of wildcards such as '.' (meaning "one or more of any character") and '!' (which is 'earlymatch', meaning "zero or more of any character" but also impacts the return value from CANMATCH and EARLYMATCH.

The extension match rules defined in the devmeeting 2006.05.05 are quite simple: WE SELECT THE LONGEST MATCH. In detail, "longest" means the number of matched characters in the extension. In case of ties (e.g. _XXX and 333) in the length of a pattern, we give priority to entries with the smallest cardinality (e.g, [5-9] comes before [2-8] before the former has only 5 elements, while the latter has 7, etc. In case of same cardinality, the first element in the range counts. If we still have a tie, any final '!' will make this as a possibly less specific pattern.

EBUSY - can't lock EEXIST - extension with the same priority exist and no replace is set

Definition at line 4740 of file pbx.c.

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

Referenced by add_extensions(), ast_add_extension(), ast_park_call(), do_parking_thread(), pbx_load_config(), and pbx_load_users().

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

static int ast_add_hint ( struct ast_exten e  )  [static]

ast_add_hint: Add hint to hint list, check initial extension state

Definition at line 2158 of file pbx.c.

References ast_calloc, ast_extension_state2(), ast_get_extension_app(), ast_get_extension_name(), AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_hint::exten, LOG_DEBUG, and option_debug.

Referenced by ast_add_extension2().

02159 {
02160    struct ast_hint *hint;
02161 
02162    if (!e)
02163       return -1;
02164 
02165    AST_LIST_LOCK(&hints);
02166 
02167    /* Search if hint exists, do nothing */
02168    AST_LIST_TRAVERSE(&hints, hint, list) {
02169       if (hint->exten == e) {
02170          AST_LIST_UNLOCK(&hints);
02171          if (option_debug > 1)
02172             ast_log(LOG_DEBUG, "HINTS: Not re-adding existing hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e));
02173          return -1;
02174       }
02175    }
02176 
02177    if (option_debug > 1)
02178       ast_log(LOG_DEBUG, "HINTS: Adding hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e));
02179 
02180    if (!(hint = ast_calloc(1, sizeof(*hint)))) {
02181       AST_LIST_UNLOCK(&hints);
02182       return -1;
02183    }
02184    /* Initialize and insert new item at the top */
02185    hint->exten = e;
02186    hint->laststate = ast_extension_state2(e);
02187    AST_LIST_INSERT_HEAD(&hints, hint, list);
02188 
02189    AST_LIST_UNLOCK(&hints);
02190    return 0;
02191 }

AST_APP_OPTIONS ( resetcdr_opts   ) 

AST_APP_OPTIONS ( waitexten_opts   ) 

AST_APP_OPTIONS ( background_opts   ) 

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

Definition at line 4570 of file pbx.c.

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

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

04571 {
04572    int res = 0;
04573 
04574    ast_channel_lock(chan);
04575 
04576    if (chan->pbx) { /* This channel is currently in the PBX */
04577       ast_explicit_goto(chan, context, exten, priority);
04578       ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO);
04579    } else {
04580       /* In order to do it when the channel doesn't really exist within
04581          the PBX, we have to make a new channel, masquerade, and start the PBX
04582          at the new location */
04583       struct ast_channel *tmpchan = ast_channel_alloc(0, chan->_state, 0, 0, chan->accountcode, chan->exten, chan->context, chan->amaflags, "AsyncGoto/%s", chan->name);
04584       if (chan->cdr) {
04585          tmpchan->cdr = ast_cdr_dup(chan->cdr);
04586       }
04587       if (!tmpchan)
04588          res = -1;
04589       else {
04590          /* Make formats okay */
04591          tmpchan->readformat = chan->readformat;
04592          tmpchan->writeformat = chan->writeformat;
04593          /* Setup proper location */
04594          ast_explicit_goto(tmpchan,
04595             S_OR(context, chan->context), S_OR(exten, chan->exten), priority);
04596 
04597          /* Masquerade into temp channel */
04598          ast_channel_masquerade(tmpchan, chan);
04599 
04600          /* Grab the locks and get going */
04601          ast_channel_lock(tmpchan);
04602          ast_do_masquerade(tmpchan);
04603          ast_channel_unlock(tmpchan);
04604          /* Start the PBX going on our stolen channel */
04605          if (ast_pbx_start(tmpchan)) {
04606             ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name);
04607             ast_hangup(tmpchan);
04608             res = -1;
04609          }
04610       }
04611    }
04612    ast_channel_unlock(chan);
04613    return res;
04614 }

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

Definition at line 4616 of file pbx.c.

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

04617 {
04618    struct ast_channel *chan;
04619    int res = -1;
04620 
04621    chan = ast_get_channel_by_name_locked(channame);
04622    if (chan) {
04623       res = ast_async_goto(chan, context, exten, priority);
04624       ast_channel_unlock(chan);
04625    }
04626    return res;
04627 }

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

Definition at line 6281 of file pbx.c.

References __ast_goto_if_exists().

Referenced by asyncgoto_exec().

06282 {
06283    return __ast_goto_if_exists(chan, context, exten, priority, 1);
06284 }

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

Definition at line 4212 of file pbx.c.

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

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

04213 {
04214    char info_save[256];
04215    char *info;
04216 
04217    /* Check for empty just in case */
04218    if (ast_strlen_zero(info_in))
04219       return 0;
04220    /* make a copy just in case we were passed a static string */
04221    ast_copy_string(info_save, info_in, sizeof(info_save));
04222    info = info_save;
04223    /* Assume everything except time */
04224    i->monthmask = 0xfff;   /* 12 bits */
04225    i->daymask = 0x7fffffffU; /* 31 bits */
04226    i->dowmask = 0x7f; /* 7 bits */
04227    /* on each call, use strsep() to move info to the next argument */
04228    get_timerange(i, strsep(&info, "|"));
04229    if (info)
04230       i->dowmask = get_range(strsep(&info, "|"), 7, days, "day of week");
04231    if (info)
04232       i->daymask = get_range(strsep(&info, "|"), 31, NULL, "day");
04233    if (info)
04234       i->monthmask = get_range(strsep(&info, "|"), 12, months, "month");
04235    return 1;
04236 }

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

Looks for a valid matching extension.

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

References E_CANMATCH, and pbx_extension_helper().

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

02283 {
02284    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH);
02285 }

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

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

Referenced by add_pri().

02195 {
02196    struct ast_hint *hint;
02197    int res = -1;
02198 
02199    AST_LIST_LOCK(&hints);
02200    AST_LIST_TRAVERSE(&hints, hint, list) {
02201       if (hint->exten == oe) {
02202             hint->exten = ne;
02203          res = 0;
02204          break;
02205       }
02206    }
02207    AST_LIST_UNLOCK(&hints);
02208 
02209    return res;
02210 }

int ast_check_timing ( const struct ast_timing i  ) 

Definition at line 4238 of file pbx.c.

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

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

04239 {
04240    struct tm tm;
04241    time_t t = time(NULL);
04242 
04243    ast_localtime(&t, &tm, NULL);
04244 
04245    /* If it's not the right month, return */
04246    if (!(i->monthmask & (1 << tm.tm_mon)))
04247       return 0;
04248 
04249    /* If it's not that time of the month.... */
04250    /* Warning, tm_mday has range 1..31! */
04251    if (!(i->daymask & (1 << (tm.tm_mday-1))))
04252       return 0;
04253 
04254    /* If it's not the right day of the week */
04255    if (!(i->dowmask & (1 << tm.tm_wday)))
04256       return 0;
04257 
04258    /* Sanity check the hour just to be safe */
04259    if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) {
04260       ast_log(LOG_WARNING, "Insane time...\n");
04261       return 0;
04262    }
04263 
04264    /* Now the tough part, we calculate if it fits
04265       in the right time based on min/hour */
04266    if (!(i->minmask[tm.tm_hour] & (1 << (tm.tm_min / 2))))
04267       return 0;
04268 
04269    /* If we got this far, then we're good */
04270    return 1;
04271 }

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

Add an ignorepat.

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

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

Referenced by handle_context_add_ignorepat(), and handle_context_add_ignorepat_deprecated().

04473 {
04474    int ret = -1;
04475    struct ast_context *c = find_context_locked(context);
04476 
04477    if (c) {
04478       ret = ast_context_add_ignorepat2(c, value, registrar);
04479       ast_unlock_contexts();
04480    }
04481    return ret;
04482 }

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

Definition at line 4484 of file pbx.c.

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

Referenced by ast_context_add_ignorepat(), and pbx_load_config().

04485 {
04486    struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL;
04487    int length;
04488    length = sizeof(struct ast_ignorepat);
04489    length += strlen(value) + 1;
04490    if (!(ignorepat = ast_calloc(1, length)))
04491       return -1;
04492    /* The cast to char * is because we need to write the initial value.
04493     * The field is not supposed to be modified otherwise
04494     */
04495    strcpy((char *)ignorepat->pattern, value);
04496    ignorepat->next = NULL;
04497    ignorepat->registrar = registrar;
04498    ast_mutex_lock(&con->lock);
04499    for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) {
04500       ignorepatl = ignorepatc;
04501       if (!strcasecmp(ignorepatc->pattern, value)) {
04502          /* Already there */
04503          ast_mutex_unlock(&con->lock);
04504          errno = EEXIST;
04505          return -1;
04506       }
04507    }
04508    if (ignorepatl)
04509       ignorepatl->next = ignorepat;
04510    else
04511       con->ignorepats = ignorepat;
04512    ast_mutex_unlock(&con->lock);
04513    return 0;
04514 
04515 }

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

Add a context include.

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

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

Referenced by handle_context_add_include(), and handle_context_add_include_deprecated().

04019 {
04020    int ret = -1;
04021    struct ast_context *c = find_context_locked(context);
04022 
04023    if (c) {
04024       ret = ast_context_add_include2(c, include, registrar);
04025       ast_unlock_contexts();
04026    }
04027    return ret;
04028 }

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

Add a context include.

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

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

Referenced by ast_context_add_include(), and pbx_load_config().

04282 {
04283    struct ast_include *new_include;
04284    char *c;
04285    struct ast_include *i, *il = NULL; /* include, include_last */
04286    int length;
04287    char *p;
04288 
04289    length = sizeof(struct ast_include);
04290    length += 2 * (strlen(value) + 1);
04291 
04292    /* allocate new include structure ... */
04293    if (!(new_include = ast_calloc(1, length)))
04294       return -1;
04295    /* Fill in this structure. Use 'p' for assignments, as the fields
04296     * in the structure are 'const char *'
04297     */
04298    p = new_include->stuff;
04299    new_include->name = p;
04300    strcpy(p, value);
04301    p += strlen(value) + 1;
04302    new_include->rname = p;
04303    strcpy(p, value);
04304    /* Strip off timing info, and process if it is there */
04305    if ( (c = strchr(p, '|')) ) {
04306       *c++ = '\0';
04307            new_include->hastime = ast_build_timing(&(new_include->timing), c);
04308    }
04309    new_include->next      = NULL;
04310    new_include->registrar = registrar;
04311 
04312    ast_mutex_lock(&con->lock);
04313 
04314    /* ... go to last include and check if context is already included too... */
04315    for (i = con->includes; i; i = i->next) {
04316       if (!strcasecmp(i->name, new_include->name)) {
04317          free(new_include);
04318          ast_mutex_unlock(&con->lock);
04319          errno = EEXIST;
04320          return -1;
04321       }
04322       il = i;
04323    }
04324 
04325    /* ... include new context into context list, unlock, return */
04326    if (il)
04327       il->next = new_include;
04328    else
04329       con->includes = new_include;
04330    if (option_verbose > 2)
04331       ast_verbose(VERBOSE_PREFIX_3 "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con));
04332    ast_mutex_unlock(&con->lock);
04333 
04334    return 0;
04335 }

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

Add a switch.

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

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

04343 {
04344    int ret = -1;
04345    struct ast_context *c = find_context_locked(context);
04346 
04347    if (c) { /* found, add switch to this context */
04348       ret = ast_context_add_switch2(c, sw, data, eval, registrar);
04349       ast_unlock_contexts();
04350    }
04351    return ret;
04352 }

int ast_context_add_switch2 ( struct ast_context con,
const char *  sw,
const char *  data,
int  eval,
const char *  registrar 
)

Adds a switch (first param is a ast_context).

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

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

Referenced by ast_context_add_switch(), and pbx_load_config().

04363 {
04364    struct ast_sw *new_sw;
04365    struct ast_sw *i;
04366    int length;
04367    char *p;
04368 
04369    length = sizeof(struct ast_sw);
04370    length += strlen(value) + 1;
04371    if (data)
04372       length += strlen(data);
04373    length++;
04374    if (eval) {
04375       /* Create buffer for evaluation of variables */
04376       length += SWITCH_DATA_LENGTH;
04377       length++;
04378    }
04379 
04380    /* allocate new sw structure ... */
04381    if (!(new_sw = ast_calloc(1, length)))
04382       return -1;
04383    /* ... fill in this structure ... */
04384    p = new_sw->stuff;
04385    new_sw->name = p;
04386    strcpy(new_sw->name, value);
04387    p += strlen(value) + 1;
04388    new_sw->data = p;
04389    if (data) {
04390       strcpy(new_sw->data, data);
04391       p += strlen(data) + 1;
04392    } else {
04393       strcpy(new_sw->data, "");
04394       p++;
04395    }
04396    if (eval)
04397       new_sw->tmpdata = p;
04398    new_sw->eval     = eval;
04399    new_sw->registrar = registrar;
04400 
04401    /* ... try to lock this context ... */
04402    ast_mutex_lock(&con->lock);
04403 
04404    /* ... go to last sw and check if context is already swd too... */
04405    AST_LIST_TRAVERSE(&con->alts, i, list) {
04406       if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) {
04407          free(new_sw);
04408          ast_mutex_unlock(&con->lock);
04409          errno = EEXIST;
04410          return -1;
04411       }
04412    }
04413 
04414    /* ... sw new context into context list, unlock, return */
04415    AST_LIST_INSERT_TAIL(&con->alts, new_sw, list);
04416 
04417    if (option_verbose > 2)
04418       ast_verbose(VERBOSE_PREFIX_3 "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con));
04419 
04420    ast_mutex_unlock(&con->lock);
04421 
04422    return 0;
04423 }

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

Register a new context.

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

References __ast_context_create().

Referenced by ast_park_call(), do_parking_thread(), and set_config().

03890 {
03891    return __ast_context_create(extcontexts, name, registrar, 0);
03892 }

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

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

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

References __ast_context_destroy().

Referenced by cleanup_stale_contexts(), and unload_module().

05327 {
05328    __ast_context_destroy(con,registrar);
05329 }

struct ast_context* ast_context_find ( const char *  name  ) 

Find a context.

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

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

Referenced by _macro_exec(), ast_context_verify_includes(), ast_ignore_pattern(), ast_park_call(), cleanup_stale_contexts(), do_parking_thread(), park_exec(), register_peer_exten(), and set_config().

00893 {
00894    struct ast_context *tmp = NULL;
00895    ast_mutex_lock(&conlock);
00896    while ( (tmp = ast_walk_contexts(tmp)) ) {
00897       if (!name || !strcasecmp(name, tmp->name))
00898          break;
00899    }
00900    ast_mutex_unlock(&conlock);
00901    return tmp;
00902 }

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

Register a new context or find an existing one.

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

References __ast_context_create().

Referenced by pbx_load_config(), and pbx_load_users().

03895 {
03896    return __ast_context_create(extcontexts, name, registrar, 1);
03897 }

int ast_context_lockmacro ( const char *  context  ) 

locks the macrolock in the given given context

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

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

Referenced by _macro_exec().

02894 {
02895    struct ast_context *c = NULL;
02896    int ret = -1;
02897 
02898    ast_lock_contexts();
02899 
02900    while ((c = ast_walk_contexts(c))) {
02901       if (!strcmp(ast_get_context_name(c), context)) {
02902          ret = 0;
02903          break;
02904       }
02905    }
02906 
02907    ast_unlock_contexts();
02908 
02909    /* if we found context, lock macrolock */
02910    if (ret == 0) 
02911       ret = ast_mutex_lock(&c->macrolock);
02912 
02913    return ret;
02914 }

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

Simply remove extension from context.

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

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

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

02795 {
02796    int ret = -1; /* default error return */
02797    struct ast_context *c = find_context_locked(context);
02798 
02799    if (c) { /* ... remove extension ... */
02800       ret = ast_context_remove_extension2(c, extension, priority, registrar);
02801       ast_unlock_contexts();
02802    }
02803    return ret;
02804 }

int ast_context_remove_extension2 ( struct ast_context con,
const char *  extension,
int  priority,
const char *  registrar 
)

This functionc locks given context, search for the right extension and fires out all peer in this extensions with given priority. If priority is set to 0, all peers are removed. After that, unlock context and return.

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

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

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

02817 {
02818    struct ast_exten *exten, *prev_exten = NULL;
02819    struct ast_exten *peer;
02820 
02821    ast_mutex_lock(&con->lock);
02822 
02823    /* scan the extension list to find matching extension-registrar */
02824    for (exten = con->root; exten; prev_exten = exten, exten = exten->next) {
02825       if (!strcmp(exten->exten, extension) &&
02826          (!registrar || !strcmp(exten->registrar, registrar)))
02827          break;
02828    }
02829    if (!exten) {
02830       /* we can't find right extension */
02831       ast_mutex_unlock(&con->lock);
02832       return -1;
02833    }
02834 
02835    /* should we free all peers in this extension? (priority == 0)? */
02836    if (priority == 0) {
02837       /* remove this extension from context list */
02838       if (prev_exten)
02839          prev_exten->next = exten->next;
02840       else
02841          con->root = exten->next;
02842 
02843       /* fire out all peers */
02844       while ( (peer = exten) ) {
02845          exten = peer->peer; /* prepare for next entry */
02846          destroy_exten(peer);
02847       }
02848    } else {
02849       /* scan the priority list to remove extension with exten->priority == priority */
02850       struct ast_exten *previous_peer = NULL;
02851 
02852       for (peer = exten; peer; previous_peer = peer, peer = peer->peer) {
02853          if (peer->priority == priority &&
02854                (!registrar || !strcmp(peer->registrar, registrar) ))
02855             break; /* found our priority */
02856       }
02857       if (!peer) { /* not found */
02858          ast_mutex_unlock(&con->lock);
02859          return -1;
02860       }
02861       /* we are first priority extension? */
02862       if (!previous_peer) {
02863          /*
02864           * We are first in the priority chain, so must update the extension chain.
02865           * The next node is either the next priority or the next extension
02866           */
02867          struct ast_exten *next_node = peer->peer ? peer->peer : peer->next;
02868 
02869          if (!prev_exten)  /* change the root... */
02870             con->root = next_node;
02871          else
02872             prev_exten->next = next_node; /* unlink */
02873          if (peer->peer)   /* XXX update the new head of the pri list */
02874             peer->peer->next = peer->next;
02875       } else { /* easy, we are not first priority in extension */
02876          previous_peer->peer = peer->peer;
02877       }
02878 
02879       /* now, free whole priority extension */
02880       destroy_exten(peer);
02881       /* XXX should we return -1 ? */
02882    }
02883    ast_mutex_unlock(&con->lock);
02884    return 0;
02885 }

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

Definition at line 4429 of file pbx.c.

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

Referenced by handle_context_remove_ignorepat(), and handle_context_remove_ignorepat_deprecated().

04430 {
04431    int ret = -1;
04432    struct ast_context *c = find_context_locked(context);
04433 
04434    if (c) {
04435       ret = ast_context_remove_ignorepat2(c, ignorepat, registrar);
04436       ast_unlock_contexts();
04437    }
04438    return ret;
04439 }

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

Definition at line 4441 of file pbx.c.

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

Referenced by ast_context_remove_ignorepat().

04442 {
04443    struct ast_ignorepat *ip, *ipl = NULL;
04444 
04445    ast_mutex_lock(&con->lock);
04446 
04447    for (ip = con->ignorepats; ip; ip = ip->next) {
04448       if (!strcmp(ip->pattern, ignorepat) &&
04449          (!registrar || (registrar == ip->registrar))) {
04450          if (ipl) {
04451             ipl->next = ip->next;
04452             free(ip);
04453          } else {
04454             con->ignorepats = ip->next;
04455             free(ip);
04456          }
04457          ast_mutex_unlock(&con->lock);
04458          return 0;
04459       }
04460       ipl = ip;
04461    }
04462 
04463    ast_mutex_unlock(&con->lock);
04464    errno = EINVAL;
04465    return -1;
04466 }

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

Remove a context include.

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

Definition at line 2690 of file pbx.c.

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

Referenced by handle_context_dont_include_deprecated(), and handle_context_remove_include().

02691 {
02692    int ret = -1;
02693    struct ast_context *c = find_context_locked(context);
02694 
02695    if (c) {
02696       /* found, remove include from this context ... */
02697       ret = ast_context_remove_include2(c, include, registrar);
02698       ast_unlock_contexts();
02699    }
02700    return ret;
02701 }

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

Removes an include by an ast_context structure.

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

Definition at line 2711 of file pbx.c.

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

Referenced by ast_context_remove_include().

02712 {
02713    struct ast_include *i, *pi = NULL;
02714    int ret = -1;
02715 
02716    ast_mutex_lock(&con->lock);
02717 
02718    /* find our include */
02719    for (i = con->includes; i; pi = i, i = i->next) {
02720       if (!strcmp(i->name, include) &&
02721             (!registrar || !strcmp(i->registrar, registrar))) {
02722          /* remove from list */
02723          if (pi)
02724             pi->next = i->next;
02725          else
02726             con->includes = i->next;
02727          /* free include and return */
02728          free(i);
02729          ret = 0;
02730          break;
02731       }
02732    }
02733 
02734    ast_mutex_unlock(&con->lock);
02735    return ret;
02736 }

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

Remove a switch.

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

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

02744 {
02745    int ret = -1; /* default error return */
02746    struct ast_context *c = find_context_locked(context);
02747 
02748    if (c) {
02749       /* remove switch from this context ... */
02750       ret = ast_context_remove_switch2(c, sw, data, registrar);
02751       ast_unlock_contexts();
02752    }
02753    return ret;
02754 }

int ast_context_remove_switch2 ( struct ast_context con,
const char *  sw,
const char *  data,
const char *  registrar 
)

This function locks given context, removes switch, unlock context and return.

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

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

Referenced by ast_context_remove_switch().

02765 {
02766    struct ast_sw *i;
02767    int ret = -1;
02768 
02769    ast_mutex_lock(&con->lock);
02770 
02771    /* walk switches */
02772    AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) {
02773       if (!strcmp(i->name, sw) && !strcmp(i->data, data) &&
02774          (!registrar || !strcmp(i->registrar, registrar))) {
02775          /* found, remove from list */
02776          AST_LIST_REMOVE_CURRENT(&con->alts, list);
02777          free(i); /* free switch and return */
02778          ret = 0;
02779          break;
02780       }
02781    }
02782    AST_LIST_TRAVERSE_SAFE_END
02783 
02784    ast_mutex_unlock(&con->lock);
02785 
02786    return ret;
02787 }

int ast_context_unlockmacro ( const char *  context  ) 

Unlocks the macrolock in the given context.

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

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

Referenced by _macro_exec().

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

int ast_context_verify_includes ( struct ast_context con  ) 

Verifies includes in an ast_contect structure.

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

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

Referenced by pbx_load_module().

06243 {
06244    struct ast_include *inc = NULL;
06245    int res = 0;
06246 
06247    while ( (inc = ast_walk_context_includes(con, inc)) )
06248       if (!ast_context_find(inc->rname)) {
06249          res = -1;
06250          ast_log(LOG_WARNING, "Context '%s' tries includes nonexistent context '%s'\n",
06251                ast_get_context_name(con), inc->rname);
06252       }
06253    return res;
06254 }

struct ast_custom_function* ast_custom_function_find ( const char *  name  ) 

Definition at line 1433 of file pbx.c.

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

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

01434 {
01435    struct ast_custom_function *acf = NULL;
01436 
01437    AST_LIST_LOCK(&acf_root);
01438    AST_LIST_TRAVERSE(&acf_root, acf, acflist) {
01439       if (!strcmp(name, acf->name))
01440          break;
01441    }
01442    AST_LIST_UNLOCK(&acf_root);
01443 
01444    return acf;
01445 }

int ast_custom_function_register ( struct ast_custom_function acf  ) 

Reigster a custom function.

Definition at line 1469 of file pbx.c.

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

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

01470 {
01471    struct ast_custom_function *cur;
01472 
01473    if (!acf)
01474       return -1;
01475 
01476    AST_LIST_LOCK(&acf_root);
01477 
01478    if (ast_custom_function_find(acf->name)) {
01479       ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name);
01480       AST_LIST_UNLOCK(&acf_root);
01481       return -1;
01482    }
01483 
01484    /* Store in alphabetical order */
01485    AST_LIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) {
01486       if (strcasecmp(acf->name, cur->name) < 0) {
01487          AST_LIST_INSERT_BEFORE_CURRENT(&acf_root, acf, acflist);
01488          break;
01489       }
01490    }
01491    AST_LIST_TRAVERSE_SAFE_END
01492    if (!cur)
01493       AST_LIST_INSERT_TAIL(&acf_root, acf, acflist);
01494 
01495    AST_LIST_UNLOCK(&acf_root);
01496 
01497    if (option_verbose > 1)
01498       ast_verbose(VERBOSE_PREFIX_2 "Registered custom function %s\n", acf->name);
01499 
01500    return 0;
01501 }

int ast_custom_function_unregister ( struct ast_custom_function acf  ) 

Unregister a custom function.

Definition at line 1447 of file pbx.c.

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

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

01448 {
01449    struct ast_custom_function *cur;
01450 
01451    if (!acf)
01452       return -1;
01453 
01454    AST_LIST_LOCK(&acf_root);
01455    AST_LIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) {
01456       if (cur == acf) {
01457          AST_LIST_REMOVE_CURRENT(&acf_root, acflist);
01458          if (option_verbose > 1)
01459             ast_verbose(VERBOSE_PREFIX_2 "Unregistered custom function %s\n", acf->name);
01460          break;
01461       }
01462    }
01463    AST_LIST_TRAVERSE_SAFE_END
01464    AST_LIST_UNLOCK(&acf_root);
01465 
01466    return acf ? 0 : -1;
01467 }

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

Determine whether an extension exists.

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

References E_MATCH, and pbx_extension_helper().

Referenced by __ast_goto_if_exists(), __ast_pbx_run(), __login_exec(), _macro_exec(), agentmonitoroutgoing_exec(), answer_call(), ast_app_dtget(), ast_park_call(), ast_pbx_outgoing_exten(), builtin_atxfer(), builtin_blindtransfer(), cb_events(), console_dial(), console_dial_deprecated(), console_transfer(), console_transfer_deprecated(), disa_exec(), dp_lookup(), dundi_lookup_local(), get_also_info(), get_destination(), get_refer_info(), handle_link_data(), handle_link_phone_dtmf(), handle_stimulus_message(), leave_voicemail(), local_alloc(), local_devicestate(), local_dtmf_helper(), loopback_exists(), metermaidstate(), mgcp_ss(), misdn_overlap_dial_task(), nv_background_detect_exec(), nv_detectfax_exec(), parkandannounce_exec(), pbx_builtin_waitexten(), phone_check_exception(), process_ast_dsp(), register_peer_exten(), skinny_ss(), socket_process(), ss_thread(), waitstream_core(), and zt_handle_dtmfup().

02268 {
02269    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH);
02270 }

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

Definition at line 4551 of file pbx.c.

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

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

04552 {
04553    if (!chan)
04554       return -1;
04555 
04556    if (!ast_strlen_zero(context))
04557       ast_copy_string(chan->context, context, sizeof(chan->context));
04558    if (!ast_strlen_zero(exten))
04559       ast_copy_string(chan->exten, exten, sizeof(chan->exten));
04560    if (priority > -1) {
04561       chan->priority = priority;
04562       /* see flag description in channel.h for explanation */
04563       if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP))
04564          chan->priority--;
04565    }
04566 
04567    return 0;
04568 }

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

Definition at line 885 of file pbx.c.

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

Referenced by realtime_switch_common().

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

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

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

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

References E_MATCH, and extension_match_core().

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

00881 {
00882    return extension_match_core(pattern, data, E_MATCH);
00883 }

int ast_extension_state ( struct ast_channel c,
const char *  context,
const char *  exten 
)

Uses hint and devicestate callback to get the state of an extension.

Parameters:
c this is not important
context which context to look in
exten which extension to get state
Returns:
extension state as defined in the ast_extension_states enum

Definition at line 1991 of file pbx.c.

References ast_extension_state2(), and ast_hint_extension().

Referenced by action_extensionstate(), and handle_request_subscribe().

01992 {
01993    struct ast_exten *e;
01994 
01995    e = ast_hint_extension(c, context, exten);   /* Do we have a hint for this extension ? */
01996    if (!e)
01997       return -1;           /* No hint, return -1 */
01998 
01999    return ast_extension_state2(e);        /* Check all devices in the hint */
02000 }

static int ast_extension_state2 ( struct ast_exten e  )  [static]

ast_extensions_state2: Check state of extension by using hints

Definition at line 1894 of file pbx.c.

References AST_DEVICE_BUSY, AST_DEVICE_INUSE, AST_DEVICE_INVALID, AST_DEVICE_NOT_INUSE, AST_DEVICE_ONHOLD, AST_DEVICE_RINGING, AST_DEVICE_RINGINUSE, ast_device_state(), AST_DEVICE_UNAVAILABLE, AST_EXTENSION_BUSY, AST_EXTENSION_INUSE, AST_EXTENSION_NOT_INUSE, AST_EXTENSION_ONHOLD, AST_EXTENSION_RINGING, AST_EXTENSION_UNAVAILABLE, ast_get_extension_app(), AST_MAX_EXTENSION, inuse, ring(), and strsep().

Referenced by ast_add_hint(), ast_extension_state(), and ast_hint_state_changed().

01895 {
01896    char hint[AST_MAX_EXTENSION];
01897    char *cur, *rest;
01898    int allunavailable = 1, allbusy = 1, allfree = 1, allonhold = 1;
01899    int busy = 0, inuse = 0, ring = 0;
01900 
01901    if (!e)
01902       return -1;
01903 
01904    ast_copy_string(hint, ast_get_extension_app(e), sizeof(hint));
01905 
01906    rest = hint;   /* One or more devices separated with a & character */
01907    while ( (cur = strsep(&rest, "&")) ) {
01908       int res = ast_device_state(cur);
01909       switch (res) {
01910       case AST_DEVICE_NOT_INUSE:
01911          allunavailable = 0;
01912          allbusy = 0;
01913          allonhold = 0;
01914          break;
01915       case AST_DEVICE_INUSE:
01916          inuse = 1;
01917          allunavailable = 0;
01918          allfree = 0;
01919          allonhold = 0;
01920          break;
01921       case AST_DEVICE_RINGING:
01922          ring = 1;
01923          allunavailable = 0;
01924          allfree = 0;
01925          allonhold = 0;
01926          break;
01927       case AST_DEVICE_RINGINUSE:
01928          inuse = 1;
01929          ring = 1;
01930          allunavailable = 0;
01931          allfree = 0;
01932          allonhold = 0;
01933          break;
01934       case AST_DEVICE_ONHOLD:
01935          allunavailable = 0;
01936          allfree = 0;
01937          break;
01938       case AST_DEVICE_BUSY:
01939          allunavailable = 0;
01940          allfree = 0;
01941          allonhold = 0;
01942          busy = 1;
01943          break;
01944       case AST_DEVICE_UNAVAILABLE:
01945       case AST_DEVICE_INVALID:
01946          allbusy = 0;
01947          allfree = 0;
01948          allonhold = 0;
01949          break;
01950       default:
01951          allunavailable = 0;
01952          allbusy = 0;
01953          allfree = 0;
01954          allonhold = 0;
01955       }
01956    }
01957 
01958    if (!inuse && ring)
01959       return AST_EXTENSION_RINGING;
01960    if (inuse && ring)
01961       return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING);
01962    if (inuse)
01963       return AST_EXTENSION_INUSE;
01964    if (allfree)
01965       return AST_EXTENSION_NOT_INUSE;
01966    if (allonhold)
01967       return AST_EXTENSION_ONHOLD;
01968    if (allbusy)
01969       return AST_EXTENSION_BUSY;
01970    if (allunavailable)
01971       return AST_EXTENSION_UNAVAILABLE;
01972    if (busy)
01973       return AST_EXTENSION_INUSE;
01974 
01975    return AST_EXTENSION_NOT_INUSE;
01976 }

const char* ast_extension_state2str ( int  extension_state  ) 

Return string representation of the state of an extension.

Parameters:
extension_state is the numerical state delivered by ast_extension_state
Returns:
the state of an extension as string

Definition at line 1979 of file pbx.c.

References extension_states.

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

01980 {
01981    int i;
01982 
01983    for (i = 0; (i < (sizeof(extension_states) / sizeof(extension_states[0]))); i++) {
01984       if (extension_states[i].extension_state == extension_state)
01985          return extension_states[i].text;
01986    }
01987    return "Unknown";
01988 }

int ast_extension_state_add ( const char *  context,
const char *  exten,
ast_state_cb_type  callback,
void *  data 
)

Registers a state change callback.

Parameters:
context which context to look in
exten which extension to get state
callback callback to call if state changed
data to pass to callback
The callback is called if the state of an extension is changed.

Return values:
-1 on failure
ID on success

Definition at line 2046 of file pbx.c.

References ast_calloc, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_state_cb::callback, ast_state_cb::data, ast_state_cb::next, and statecbs.

Referenced by handle_request_subscribe(), and init_manager().

02048 {
02049    struct ast_hint *hint;
02050    struct ast_state_cb *cblist;
02051    struct ast_exten *e;
02052 
02053    /* If there's no context and extension:  add callback to statecbs list */
02054    if (!context && !exten) {
02055       AST_LIST_LOCK(&hints);
02056 
02057       for (cblist = statecbs; cblist; cblist = cblist->next) {
02058          if (cblist->callback == callback) {
02059             cblist->data = data;
02060             AST_LIST_UNLOCK(&hints);
02061             return 0;
02062          }
02063       }
02064 
02065       /* Now insert the callback */
02066       if (!(cblist = ast_calloc(1, sizeof(*cblist)))) {
02067          AST_LIST_UNLOCK(&hints);
02068          return -1;
02069       }
02070       cblist->id = 0;
02071       cblist->callback = callback;
02072       cblist->data = data;
02073 
02074       cblist->next = statecbs;
02075       statecbs = cblist;
02076 
02077       AST_LIST_UNLOCK(&hints);
02078       return 0;
02079    }
02080 
02081    if (!context || !exten)
02082       return -1;
02083 
02084    /* This callback type is for only one hint, so get the hint */
02085    e = ast_hint_extension(NULL, context, exten);
02086    if (!e) {
02087       return -1;
02088    }
02089 
02090    /* Find the hint in the list of hints */
02091    AST_LIST_LOCK(&hints);
02092 
02093    AST_LIST_TRAVERSE(&hints, hint, list) {
02094       if (hint->exten == e)
02095          break;
02096    }
02097 
02098    if (!hint) {
02099       /* We have no hint, sorry */
02100       AST_LIST_UNLOCK(&hints);
02101       return -1;
02102    }
02103 
02104    /* Now insert the callback in the callback list  */
02105    if (!(cblist = ast_calloc(1, sizeof(*cblist)))) {
02106       AST_LIST_UNLOCK(&hints);
02107       return -1;
02108    }
02109    cblist->id = stateid++;    /* Unique ID for this callback */
02110    cblist->callback = callback;  /* Pointer to callback routine */
02111    cblist->data = data;    /* Data for the callback */
02112 
02113    cblist->next = hint->callbacks;
02114    hint->callbacks = cblist;
02115 
02116    AST_LIST_UNLOCK(&hints);
02117    return cblist->id;
02118 }

int ast_extension_state_del ( int  id,
ast_state_cb_type  callback 
)

Deletes a registered state change callback by ID.

Parameters:
id of the callback to delete
callback callback
Removes the callback from list of callbacks

Return values:
0 success
-1 failure

Definition at line 2121 of file pbx.c.

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

Referenced by __sip_destroy(), and handle_request_subscribe().

02122 {
02123    struct ast_state_cb **p_cur = NULL; /* address of pointer to us */
02124    int ret = -1;
02125 
02126    if (!id && !callback)
02127       return -1;
02128 
02129    AST_LIST_LOCK(&hints);
02130 
02131    if (!id) {  /* id == 0 is a callback without extension */
02132       for (p_cur = &statecbs; *p_cur; p_cur = &(*p_cur)->next) {
02133          if ((*p_cur)->callback == callback)
02134             break;
02135       }
02136    } else { /* callback with extension, find the callback based on ID */
02137       struct ast_hint *hint;
02138       AST_LIST_TRAVERSE(&hints, hint, list) {
02139          for (p_cur = &hint->callbacks; *p_cur; p_cur = &(*p_cur)->next) {
02140             if ((*p_cur)->id == id)
02141                break;
02142          }
02143          if (*p_cur) /* found in the inner loop */
02144             break;
02145       }
02146    }
02147    if (p_cur && *p_cur) {
02148       struct ast_state_cb *cur = *p_cur;
02149       *p_cur = cur->next;
02150       free(cur);
02151       ret = 0;
02152    }
02153    AST_LIST_UNLOCK(&hints);
02154    return ret;
02155 }

int ast_findlabel_extension ( struct ast_channel c,
const char *  context,
const char *  exten,
const char *  label,
const char *  callerid 
)

Find the priority of an extension that has the specified label.

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

References E_FINDLABEL, and pbx_extension_helper().

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

02273 {
02274    return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL);
02275 }

int ast_findlabel_extension2 ( struct ast_channel c,
struct ast_context con,
const char *  exten,
const char *  label,
const char *  callerid 
)

Find the priority of an extension that has the specified label.

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

References E_FINDLABEL, and pbx_extension_helper().

Referenced by pbx_load_config().

02278 {
02279    return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL);
02280 }

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

executes a read operation on a function

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

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

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

01524 {
01525    char *args = func_args(function);
01526    struct ast_custom_function *acfptr = ast_custom_function_find(function);
01527 
01528    if (acfptr == NULL)
01529       ast_log(LOG_ERROR, "Function %s not registered\n", function);
01530    else if (!acfptr->read)
01531       ast_log(LOG_ERROR, "Function %s cannot be read\n", function);
01532    else
01533       return acfptr->read(chan, function, args, workspace, len);
01534    return -1;
01535 }

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

executes a write operation on a function

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

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

Referenced by pbx_builtin_pushvar_helper(), and pbx_builtin_setvar_helper().

01538 {
01539    char *args = func_args(function);
01540    struct ast_custom_function *acfptr = ast_custom_function_find(function);
01541 
01542    if (acfptr == NULL)
01543       ast_log(LOG_ERROR, "Function %s not registered\n", function);
01544    else if (!acfptr->write)
01545       ast_log(LOG_ERROR, "Function %s cannot be written to\n", function);
01546    else
01547       return acfptr->write(chan, function, args, value);
01548 
01549    return -1;
01550 }

const char* ast_get_context_name ( struct ast_context con  ) 

Definition at line 6099 of file pbx.c.

Referenced by _macro_exec(), ast_context_add_include2(), ast_context_add_switch2(), ast_context_lockmacro(), ast_context_unlockmacro(), ast_context_verify_includes(), complete_context_add_extension(), complete_context_add_extension_deprecated(), complete_context_add_ignorepat(), complete_context_add_ignorepat_deprecated(), complete_context_add_include(), complete_context_add_include_deprecated(), complete_context_dont_include_deprecated(), complete_context_remove_extension(), complete_context_remove_extension_deprecated(), complete_context_remove_ignorepat(), complete_context_remove_ignorepat_deprecated(), complete_context_remove_include(), complete_show_dialplan_context(), dundi_precache_full(), find_context_locked(), find_matching_endwhile(), find_matching_priority(), handle_save_dialplan(), handle_show_hints(), and show_dialplan_helper().

06100 {
06101    return con ? con->name : NULL;
06102 }

const char* ast_get_context_registrar ( struct ast_context c  ) 

Definition at line 6137 of file pbx.c.

References ast_context::registrar.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06138 {
06139    return c ? c->registrar : NULL;
06140 }

const char* ast_get_extension_app ( struct ast_exten e  ) 

Definition at line 6167 of file pbx.c.

References ast_exten::app.

Referenced by _macro_exec(), ast_add_hint(), ast_extension_state2(), ast_get_hint(), ast_hint_state_changed(), find_matching_endwhile(), handle_save_dialplan(), handle_show_hints(), and print_ext().

06168 {
06169    return e ? e->app : NULL;
06170 }

void* ast_get_extension_app_data ( struct ast_exten e  ) 

Definition at line 6172 of file pbx.c.

References ast_exten::data.

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

06173 {
06174    return e ? e->data : NULL;
06175 }

const char* ast_get_extension_cidmatch ( struct ast_exten e  ) 

Definition at line 6162 of file pbx.c.

References ast_exten::cidmatch.

Referenced by find_matching_priority(), and handle_save_dialplan().

06163 {
06164    return e ? e->cidmatch : NULL;
06165 }

struct ast_context* ast_get_extension_context ( struct ast_exten exten  ) 

Definition at line 6104 of file pbx.c.

References exten.

Referenced by handle_show_hints().

06105 {
06106    return exten ? exten->parent : NULL;
06107 }

const char* ast_get_extension_label ( struct ast_exten exten  ) 

Definition at line 6114 of file pbx.c.

References exten.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06115 {
06116    return exten ? exten->label : NULL;
06117 }

int ast_get_extension_matchcid ( struct ast_exten e  ) 

Definition at line 6157 of file pbx.c.

References ast_exten::matchcid.

Referenced by find_matching_priority(), and handle_save_dialplan().

06158 {
06159    return e ? e->matchcid : 0;
06160 }

const char* ast_get_extension_name ( struct ast_exten exten  ) 

Definition at line 6109 of file pbx.c.

References exten.

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

06110 {
06111    return exten ? exten->exten : NULL;
06112 }

int ast_get_extension_priority ( struct ast_exten exten  ) 

Definition at line 6129 of file pbx.c.

References exten.

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

06130 {
06131    return exten ? exten->priority : -1;
06132 }

const char* ast_get_extension_registrar ( struct ast_exten e  ) 

Definition at line 6142 of file pbx.c.

References ast_exten::registrar.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06143 {
06144    return e ? e->registrar : NULL;
06145 }

int ast_get_hint ( char *  hint,
int  maxlen,
char *  name,
int  maxnamelen,
struct ast_channel c,
const char *  context,
const char *  exten 
)

If an extension hint exists, return non-zero.

Parameters:
hint buffer for hint
maxlen size of hint buffer
name buffer for name portion of hint
maxnamelen size of name buffer
c this is not important
context which context to look in
exten which extension to search for
Returns:
If an extension within the given context with the priority PRIORITY_HINT is found a non zero value will be returned. Otherwise, 0 is returned.

Definition at line 2250 of file pbx.c.

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

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

02251 {
02252    struct ast_exten *e = ast_hint_extension(c, context, exten);
02253 
02254    if (e) {
02255       if (hint)
02256          ast_copy_string(hint, ast_get_extension_app(e), hintsize);
02257       if (name) {
02258          const char *tmp = ast_get_extension_app_data(e);
02259          if (tmp)
02260             ast_copy_string(name, tmp, namesize);
02261       }
02262       return -1;
02263    }
02264    return 0;
02265 }

const char* ast_get_ignorepat_name ( struct ast_ignorepat ip  ) 

Definition at line 6124 of file pbx.c.

References ast_ignorepat::pattern.

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

06125 {
06126    return ip ? ip->pattern : NULL;
06127 }

const char* ast_get_ignorepat_registrar ( struct ast_ignorepat ip  ) 

Definition at line 6152 of file pbx.c.

References ast_ignorepat::registrar.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06153 {
06154    return ip ? ip->registrar : NULL;
06155 }

const char* ast_get_include_name ( struct ast_include inc  ) 

Definition at line 6119 of file pbx.c.

References ast_include::name.

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

06120 {
06121    return inc ? inc->name : NULL;
06122 }

const char* ast_get_include_registrar ( struct ast_include i  ) 

Definition at line 6147 of file pbx.c.

References ast_include::registrar.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06148 {
06149    return i ? i->registrar : NULL;
06150 }

const char* ast_get_switch_data ( struct ast_sw sw  ) 

Definition at line 6182 of file pbx.c.

References ast_sw::data.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06183 {
06184    return sw ? sw->data : NULL;
06185 }

const char* ast_get_switch_name ( struct ast_sw sw  ) 

Definition at line 6177 of file pbx.c.

References ast_sw::name.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06178 {
06179    return sw ? sw->name : NULL;
06180 }

const char* ast_get_switch_registrar ( struct ast_sw sw  ) 

Definition at line 6187 of file pbx.c.

References ast_sw::registrar.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06188 {
06189    return sw ? sw->registrar : NULL;
06190 }

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

Definition at line 6276 of file pbx.c.

References __ast_goto_if_exists().

Referenced by aqm_exec(), background_detect_exec(), chanavail_exec(), conf_run(), controlplayback_exec(), do_directory(), hasvoicemail_exec(), leave_voicemail(), lookupblacklist_exec(), onedigit_goto(), ospauth_exec(), ospfinished_exec(), osplookup_exec(), ospnext_exec(), play_mailbox_owner(), playback_exec(), pqm_exec(), privacy_exec(), rqm_exec(), sendimage_exec(), sendtext_exec(), sendurl_exec(), system_exec_helper(), transfer_exec(), upqm_exec(), valid_exit(), vm_box_exists(), vm_exec(), and wait_for_answer().

06277 {
06278    return __ast_goto_if_exists(chan, context, exten, priority, 0);
06279 }

static struct ast_exten* ast_hint_extension ( struct ast_channel c,
const char *  context,
const char *  exten 
) [static]

ast_hint_extension: Find hint for given extension in context

Definition at line 1881 of file pbx.c.

References ast_mutex_lock(), ast_mutex_unlock(), E_MATCH, pbx_find_extension(), PRIORITY_HINT, and pbx_find_info::stacklen.

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

01882 {
01883    struct ast_exten *e;
01884    struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */
01885 
01886    ast_mutex_lock(&conlock);
01887    e = pbx_find_extension(c, NULL, &q, context, exten, PRIORITY_HINT, NULL, "", E_MATCH);
01888    ast_mutex_unlock(&conlock);
01889 
01890    return e;
01891 }

void ast_hint_state_changed ( const char *  device  ) 

Definition at line 2002 of file pbx.c.

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

Referenced by do_state_change().

02003 {
02004    struct ast_hint *hint;
02005 
02006    AST_LIST_LOCK(&hints);
02007 
02008    AST_LIST_TRAVERSE(&hints, hint, list) {
02009       struct ast_state_cb *cblist;
02010       char buf[AST_MAX_EXTENSION];
02011       char *parse = buf;
02012       char *cur;
02013       int state;
02014 
02015       ast_copy_string(buf, ast_get_extension_app(hint->exten), sizeof(buf));
02016       while ( (cur = strsep(&parse, "&")) ) {
02017          if (!strcasecmp(cur, device))
02018             break;
02019       }
02020       if (!cur)
02021          continue;
02022 
02023       /* Get device state for this hint */
02024       state = ast_extension_state2(hint->exten);
02025 
02026       if ((state == -1) || (state == hint->laststate))
02027          continue;
02028 
02029       /* Device state changed since last check - notify the watchers */
02030 
02031       /* For general callbacks */
02032       for (cblist = statecbs; cblist; cblist = cblist->next)
02033          cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data);
02034 
02035       /* For extension callbacks */
02036       for (cblist = hint->callbacks; cblist; cblist = cblist->next)
02037          cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data);
02038 
02039       hint->laststate = state;   /* record we saw the change */
02040    }
02041 
02042    AST_LIST_UNLOCK(&hints);
02043 }

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

Checks to see if a number should be ignored.

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

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

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

04518 {
04519    struct ast_context *con = ast_context_find(context);
04520    if (con) {
04521       struct ast_ignorepat *pat;
04522       for (pat = con->ignorepats; pat; pat = pat->next) {
04523          if (ast_extension_match(pat->pattern, pattern))
04524             return 1;
04525       }
04526    }
04527 
04528    return 0;
04529 }

AST_LIST_HEAD ( store_hints  ,
store_hint   
)

static AST_LIST_HEAD_STATIC ( hints  ,
ast_hint   
) [static]

static AST_LIST_HEAD_STATIC ( switches  ,
ast_switch   
) [static]

static AST_LIST_HEAD_STATIC ( apps  ,
ast_app   
) [static]

static AST_LIST_HEAD_STATIC ( acf_root  ,
ast_custom_function   
) [static]

int ast_lock_context ( struct ast_context con  ) 

Locks a given context.

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

Definition at line 6086 of file pbx.c.

References ast_mutex_lock(), and ast_context::lock.

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

06087 {
06088    return ast_mutex_lock(&con->lock);
06089 }

int ast_lock_contexts ( void   ) 

Locks the context list.

Return values:
0 on success
-1 on error

Definition at line 6073 of file pbx.c.

References ast_mutex_lock().

Referenced by _macro_exec(), ast_context_lockmacro(), ast_context_unlockmacro(), complete_context_add_extension(), complete_context_add_extension_deprecated(), complete_context_add_ignorepat(), complete_context_add_ignorepat_deprecated(), complete_context_add_include(), complete_context_add_include_deprecated(), complete_context_dont_include_deprecated(), complete_context_remove_extension(), complete_context_remove_extension_deprecated(), complete_context_remove_ignorepat(), complete_context_remove_ignorepat_deprecated(), complete_context_remove_include(), complete_show_dialplan_context(), dundi_precache_full(), find_context_locked(), find_matching_endwhile(), handle_save_dialplan(), and show_dialplan_helper().

06074 {
06075    return ast_mutex_lock(&conlock);
06076 }

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

Looks to see if adding anything to this extension might match something. (exists ^ canmatch).

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

References E_MATCHMORE, and pbx_extension_helper().

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

02288 {
02289    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE);
02290 }

void ast_merge_contexts_and_delete ( struct ast_context **  extcontexts,
const char *  registrar 
)

Merge the temporary contexts into a global contexts list and delete from the global list the ones that are being added.

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

References __ast_context_destroy(), ast_calloc, AST_EXTENSION_REMOVED, ast_hint_extension(), AST_LIST_HEAD_INIT_VALUE, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_state_cb::callback, ast_hint::callbacks, store_hint::callbacks, store_hint::context, contexts, ast_state_cb::data, store_hint::exten, ast_hint::exten, ast_exten::exten, free, store_hint::laststate, ast_hint::laststate, LOG_WARNING, ast_context::next, ast_state_cb::next, ast_exten::parent, and ast_context::registrar.

Referenced by pbx_load_module().

03913 {
03914    struct ast_context *tmp, *lasttmp = NULL;
03915    struct store_hints store = AST_LIST_HEAD_INIT_VALUE;
03916    struct store_hint *this;
03917    struct ast_hint *hint;
03918    struct ast_exten *exten;
03919    int length;
03920    struct ast_state_cb *thiscb, *prevcb;
03921 
03922    /* it is very important that this function hold the hint list lock _and_ the conlock
03923       during its operation; not only do we need to ensure that the list of contexts
03924       and extensions does not change, but also that no hint callbacks (watchers) are
03925       added or removed during the merge/delete process
03926 
03927       in addition, the locks _must_ be taken in this order, because there are already
03928       other code paths that use this order
03929    */
03930    ast_mutex_lock(&conlock);
03931    AST_LIST_LOCK(&hints);
03932 
03933    /* preserve all watchers for hints associated with this registrar */
03934    AST_LIST_TRAVERSE(&hints, hint, list) {
03935       if (hint->callbacks && !strcmp(registrar, hint->exten->parent->registrar)) {
03936          length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2 + sizeof(*this);
03937          if (!(this = ast_calloc(1, length)))
03938             continue;
03939          this->callbacks = hint->callbacks;
03940          hint->callbacks = NULL;
03941          this->laststate = hint->laststate;
03942          this->context = this->data;
03943          strcpy(this->data, hint->exten->parent->name);
03944          this->exten = this->data + strlen(this->context) + 1;
03945          strcpy(this->exten, hint->exten->exten);
03946          AST_LIST_INSERT_HEAD(&store, this, list);
03947       }
03948    }
03949 
03950    tmp = *extcontexts;
03951    if (registrar) {
03952       /* XXX remove previous contexts from same registrar */
03953       if (option_debug)
03954          ast_log(LOG_DEBUG, "must remove any reg %s\n", registrar);
03955       __ast_context_destroy(NULL,registrar);
03956       while (tmp) {
03957          lasttmp = tmp;
03958          tmp = tmp->next;
03959       }
03960    } else {
03961       /* XXX remove contexts with the same name */
03962       while (tmp) {
03963          ast_log(LOG_WARNING, "must remove %s  reg %s\n", tmp->name, tmp->registrar);
03964          __ast_context_destroy(tmp,tmp->registrar);
03965          lasttmp = tmp;
03966          tmp = tmp->next;
03967       }
03968    }
03969    if (lasttmp) {
03970       lasttmp->next = contexts;
03971       contexts = *extcontexts;
03972       *extcontexts = NULL;
03973    } else
03974       ast_log(LOG_WARNING, "Requested contexts didn't get merged\n");
03975 
03976    /* restore the watchers for hints that can be found; notify those that
03977       cannot be restored
03978    */
03979    while ((this = AST_LIST_REMOVE_HEAD(&store, list))) {
03980       exten = ast_hint_extension(NULL, this->context, this->exten);
03981       /* Find the hint in the list of hints */
03982       AST_LIST_TRAVERSE(&hints, hint, list) {
03983          if (hint->exten == exten)
03984             break;
03985       }
03986       if (!exten || !hint) {
03987          /* this hint has been removed, notify the watchers */
03988          prevcb = NULL;
03989          thiscb = this->callbacks;
03990          while (thiscb) {
03991             prevcb = thiscb;
03992             thiscb = thiscb->next;
03993             prevcb->callback(this->context, this->exten, AST_EXTENSION_REMOVED, prevcb->data);
03994             free(prevcb);
03995             }
03996       } else {
03997          thiscb = this->callbacks;
03998          while (thiscb->next)
03999             thiscb = thiscb->next;
04000          thiscb->next = hint->callbacks;
04001          hint->callbacks = this->callbacks;
04002          hint->laststate = this->laststate;
04003       }
04004       free(this);
04005    }
04006 
04007    AST_LIST_UNLOCK(&hints);
04008    ast_mutex_unlock(&conlock);
04009 
04010    return;
04011 }

AST_MUTEX_DEFINE_STATIC ( conlock   ) 

Lock for the ast_context list

AST_MUTEX_DEFINE_STATIC ( maxcalllock   ) 

AST_MUTEX_DEFINE_STATIC ( globalslock   ) 

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

Definition at line 6286 of file pbx.c.

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

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

06287 {
06288    char *exten, *pri, *context;
06289    char *stringp;
06290    int ipri;
06291    int mode = 0;
06292 
06293    if (ast_strlen_zero(goto_string)) {
06294       ast_log(LOG_WARNING, "Goto requires an argument (optional context|optional extension|priority)\n");
06295       return -1;
06296    }
06297    stringp = ast_strdupa(goto_string);
06298    context = strsep(&stringp, "|"); /* guaranteed non-null */
06299    exten = strsep(&stringp, "|");
06300    pri = strsep(&stringp, "|");
06301    if (!exten) {  /* Only a priority in this one */
06302       pri = context;
06303       exten = NULL;
06304       context = NULL;
06305    } else if (!pri) {   /* Only an extension and priority in this one */
06306       pri = exten;
06307       exten = context;
06308       context = NULL;
06309    }
06310    if (*pri == '+') {
06311       mode = 1;
06312       pri++;
06313    } else if (*pri == '-') {
06314       mode = -1;
06315       pri++;
06316    }
06317    if (sscanf(pri, "%d", &ipri) != 1) {
06318       if ((ipri = ast_findlabel_extension(chan, context ? context : chan->context, exten ? exten : chan->exten,
06319          pri, chan->cid.cid_num)) < 1) {
06320          ast_log(LOG_WARNING, "Priority '%s' must be a number > 0, or valid label\n", pri);
06321          return -1;
06322       } else
06323          mode = 0;
06324    }
06325    /* At this point we have a priority and maybe an extension and a context */
06326 
06327    if (mode)
06328       ipri = chan->priority + (ipri * mode);
06329 
06330    ast_explicit_goto(chan, context, exten, ipri);
06331    ast_cdr_update(chan);
06332    return 0;
06333 
06334 }

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

Synchronously or asynchronously make an outbound call and send it to a particular application with given extension

Definition at line 5122 of file pbx.c.

References __ast_request_and_dial(), ast_calloc, ast_cdr_alloc(), ast_cdr_disposition(), ast_cdr_failed(), ast_cdr_init(), ast_cdr_setaccount(), ast_cdr_start(), ast_channel_lock, ast_channel_unlock, ast_hangup(), ast_log(), ast_pbx_outgoing_cdr_failed(), ast_pbx_run_app(), ast_pthread_create, ast_set_variables(), AST_STATE_UP, ast_strlen_zero(), ast_variables_destroy(), ast_verbose(), async_wait(), ast_channel::cdr, async_stat::chan, free, LOG_WARNING, option_verbose, ast_channel::pbx, outgoing_helper::vars, and VERBOSE_PREFIX_4.

Referenced by action_originate(), attempt_thread(), fast_originate(), and orig_app().

05123 {
05124    struct ast_channel *chan;
05125    struct app_tmp *tmp;
05126    int res = -1, cdr_res = -1;
05127    struct outgoing_helper oh;
05128    pthread_attr_t attr;
05129 
05130    memset(&oh, 0, sizeof(oh));
05131    oh.vars = vars;
05132    oh.account = account;
05133 
05134    if (locked_channel)
05135       *locked_channel = NULL;
05136    if (ast_strlen_zero(app)) {
05137       res = -1;
05138       goto outgoing_app_cleanup;
05139    }
05140    if (sync) {
05141       chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
05142       if (chan) {
05143          if (chan->cdr) { /* check if the channel already has a cdr record, if not give it one */
05144             ast_log(LOG_WARNING, "%s already has a call record??\n", chan->name);
05145          } else {
05146             chan->cdr = ast_cdr_alloc();   /* allocate a cdr for the channel */
05147             if(!chan->cdr) {
05148                /* allocation of the cdr failed */
05149                free(chan->pbx);
05150                res = -1;
05151                goto outgoing_app_cleanup;
05152             }
05153             /* allocation of the cdr was successful */
05154             ast_cdr_init(chan->cdr, chan);  /* initialize our channel's cdr */
05155             ast_cdr_start(chan->cdr);
05156          }
05157          ast_set_variables(chan, vars);
05158          if (account)
05159             ast_cdr_setaccount(chan, account);
05160          if (chan->_state == AST_STATE_UP) {
05161             res = 0;
05162             if (option_verbose > 3)
05163                ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", chan->name);
05164             tmp = ast_calloc(1, sizeof(*tmp));
05165             if (!tmp)
05166                res = -1;
05167             else {
05168                ast_copy_string(tmp->app, app, sizeof(tmp->app));
05169                if (appdata)
05170                   ast_copy_string(tmp->data, appdata, sizeof(tmp->data));
05171                tmp->chan = chan;
05172                if (sync > 1) {
05173                   if (locked_channel)
05174                      ast_channel_unlock(chan);
05175                   ast_pbx_run_app(tmp);
05176                } else {
05177                   pthread_attr_init(&attr);
05178                   pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
05179                   if (locked_channel)
05180                      ast_channel_lock(chan);
05181                   if (ast_pthread_create(&tmp->t, &attr, ast_pbx_run_app, tmp)) {
05182                      ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno));
05183                      free(tmp);
05184                      if (locked_channel)
05185                         ast_channel_unlock(chan);
05186                      ast_hangup(chan);
05187                      res = -1;
05188                   } else {
05189                      if (locked_channel)
05190                         *locked_channel = chan;
05191                   }
05192                   pthread_attr_destroy(&attr);
05193                }
05194             }
05195          } else {
05196             if (option_verbose > 3)
05197                ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", chan->name);
05198             if (chan->cdr) { /* update the cdr */
05199                /* here we update the status of the call, which sould be busy.
05200                 * if that fails then we set the status to failed */
05201                if (ast_cdr_disposition(chan->cdr, chan->hangupcause))
05202                   ast_cdr_failed(chan->cdr);
05203             }
05204             ast_hangup(chan);
05205          }
05206       }
05207 
05208       if (res < 0) { /* the call failed for some reason */
05209          if (*reason == 0) { /* if the call failed (not busy or no answer)
05210                         * update the cdr with the failed message */
05211             cdr_res = ast_pbx_outgoing_cdr_failed();
05212             if (cdr_res != 0) {
05213                res = cdr_res;
05214                goto outgoing_app_cleanup;
05215             }
05216          }
05217       }
05218 
05219    } else {
05220       struct async_stat *as;
05221       if (!(as = ast_calloc(1, sizeof(*as)))) {
05222          res = -1;
05223          goto outgoing_app_cleanup;
05224       }
05225       chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
05226       if (!chan) {
05227          free(as);
05228          res = -1;
05229          goto outgoing_app_cleanup;
05230       }
05231       as->chan = chan;
05232       ast_copy_string(as->app, app, sizeof(as->app));
05233       if (appdata)
05234          ast_copy_string(as->appdata,  appdata, sizeof(as->appdata));
05235       as->timeout = timeout;
05236       ast_set_variables(chan, vars);
05237       if (account)
05238          ast_cdr_setaccount(chan, account);
05239       /* Start a new thread, and get something handling this channel. */
05240       pthread_attr_init(&attr);
05241       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
05242       if (locked_channel)
05243          ast_channel_lock(chan);
05244       if (ast_pthread_create(&as->p, &attr, async_wait, as)) {
05245          ast_log(LOG_WARNING, "Failed to start async wait\n");
05246          free(as);
05247          if (locked_channel)
05248             ast_channel_unlock(chan);
05249          ast_hangup(chan);
05250          res = -1;
05251          pthread_attr_destroy(&attr);
05252          goto outgoing_app_cleanup;
05253       } else {
05254          if (locked_channel)
05255             *locked_channel = chan;
05256       }
05257       pthread_attr_destroy(&attr);
05258       res = 0;
05259    }
05260 outgoing_app_cleanup:
05261    ast_variables_destroy(vars);
05262    return res;
05263 }

static int ast_pbx_outgoing_cdr_failed ( void   )  [static]

Function to post an empty cdr after a spool call fails.

This function posts an empty cdr for a failed spool call

Definition at line 4941 of file pbx.c.

References ast_cdr_detach(), ast_cdr_end(), ast_cdr_failed(), ast_cdr_init(), ast_cdr_start(), ast_channel_alloc(), ast_channel_free(), AST_STATE_DOWN, and ast_channel::cdr.

Referenced by ast_pbx_outgoing_app(), and ast_pbx_outgoing_exten().

04942 {
04943    /* allocate a channel */
04944    struct ast_channel *chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, 0);
04945 
04946    if (!chan)
04947       return -1;  /* failure */
04948 
04949    if (!chan->cdr) {
04950       /* allocation of the cdr failed */
04951       ast_channel_free(chan);   /* free the channel */
04952       return -1;                /* return failure */
04953    }
04954 
04955    /* allocation of the cdr was successful */
04956    ast_cdr_init(chan->cdr, chan);  /* initialize our channel's cdr */
04957    ast_cdr_start(chan->cdr);       /* record the start and stop time */
04958    ast_cdr_end(chan->cdr);
04959    ast_cdr_failed(chan->cdr);      /* set the status to failed */
04960    ast_cdr_detach(chan->cdr);      /* post and free the record */
04961    ast_channel_free(chan);         /* free the channel */
04962 
04963    return 0;  /* success */
04964 }

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

Synchronously or asynchronously make an outbound call and send it to a particular extension

Definition at line 4966 of file pbx.c.

References __ast_request_and_dial(), ast_channel::_state, ast_calloc, ast_cdr_disposition(), ast_cdr_failed(), ast_cdr_setaccount(), ast_channel_alloc(), ast_channel_lock, ast_channel_unlock, ast_exists_extension(), ast_hangup(), ast_log(), ast_pbx_outgoing_cdr_failed(), ast_pbx_run(), ast_pbx_start(), ast_pthread_create, ast_request_and_dial(), ast_set_variables(), AST_STATE_DOWN, AST_STATE_UP, ast_strlen_zero(), ast_variables_destroy(), ast_verbose(), async_wait(), ast_channel::cdr, ast_channel::context, free, ast_channel::hangupcause, LOAD_OH, LOG_ERROR, LOG_WARNING, option_verbose, set_ext_pri(), outgoing_helper::vars, and VERBOSE_PREFIX_4.

Referenced by action_originate(), attempt_thread(), fast_originate(), and orig_exten().

04967 {
04968    struct ast_channel *chan;
04969    struct async_stat *as;
04970    int res = -1, cdr_res = -1;
04971    struct outgoing_helper oh;
04972    pthread_attr_t attr;
04973 
04974    if (sync) {
04975       LOAD_OH(oh);
04976       chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
04977       if (channel) {
04978          *channel = chan;
04979          if (chan)
04980             ast_channel_lock(chan);
04981       }
04982       if (chan) {
04983          if (chan->_state == AST_STATE_UP) {
04984                res = 0;
04985             if (option_verbose > 3)
04986                ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", chan->name);
04987 
04988             if (sync > 1) {
04989                if (channel)
04990                   ast_channel_unlock(chan);
04991                if (ast_pbx_run(chan)) {
04992                   ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name);
04993                   if (channel)
04994                      *channel = NULL;
04995                   ast_hangup(chan);
04996                   res = -1;
04997                }
04998             } else {
04999                if (ast_pbx_start(chan)) {
05000                   ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name);
05001                   if (channel) {
05002                      *channel = NULL;
05003                      ast_channel_unlock(chan);
05004                   }
05005                   ast_hangup(chan);
05006                   res = -1;
05007                }
05008             }
05009          } else {
05010             if (option_verbose > 3)
05011                ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", chan->name);
05012 
05013             if (chan->cdr) { /* update the cdr */
05014                /* here we update the status of the call, which sould be busy.
05015                 * if that fails then we set the status to failed */
05016                if (ast_cdr_disposition(chan->cdr, chan->hangupcause))
05017                   ast_cdr_failed(chan->cdr);
05018             }
05019 
05020             if (channel) {
05021                *channel = NULL;
05022                ast_channel_unlock(chan);
05023             }
05024             ast_hangup(chan);
05025          }
05026       }
05027 
05028       if (res < 0) { /* the call failed for some reason */
05029          if (*reason == 0) { /* if the call failed (not busy or no answer)
05030                         * update the cdr with the failed message */
05031             cdr_res = ast_pbx_outgoing_cdr_failed();
05032             if (cdr_res != 0) {
05033                res = cdr_res;
05034                goto outgoing_exten_cleanup;
05035             }
05036          }
05037 
05038          /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */
05039          /* check if "failed" exists */
05040          if (ast_exists_extension(chan, context, "failed", 1, NULL)) {
05041             chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "OutgoingSpoolFailed");
05042             if (chan) {
05043                if (!ast_strlen_zero(context))
05044                   ast_copy_string(chan->context, context, sizeof(chan->context));
05045                set_ext_pri(chan, "failed", 1);
05046                ast_set_variables(chan, vars);
05047                if (account)
05048                   ast_cdr_setaccount(chan, account);
05049                ast_pbx_run(chan);
05050             }
05051          }
05052       }
05053    } else {
05054       if (!(as = ast_calloc(1, sizeof(*as)))) {
05055          res = -1;
05056          goto outgoing_exten_cleanup;
05057       }
05058       chan = ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name);
05059       if (channel) {
05060          *channel = chan;
05061          if (chan)
05062             ast_channel_lock(chan);
05063       }
05064       if (!chan) {
05065          free(as);
05066          res = -1;
05067          goto outgoing_exten_cleanup;
05068       }
05069       as->chan = chan;
05070       ast_copy_string(as->context, context, sizeof(as->context));
05071       set_ext_pri(as->chan,  exten, priority);
05072       as->timeout = timeout;
05073       ast_set_variables(chan, vars);
05074       if (account)
05075          ast_cdr_setaccount(chan, account);
05076       pthread_attr_init(&attr);
05077       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
05078       if (ast_pthread_create(&as->p, &attr, async_wait, as)) {
05079          ast_log(LOG_WARNING, "Failed to start async wait\n");
05080          free(as);
05081          if (channel) {
05082             *channel = NULL;
05083             ast_channel_unlock(chan);
05084          }
05085          ast_hangup(chan);
05086          res = -1;
05087          pthread_attr_destroy(&attr);
05088          goto outgoing_exten_cleanup;
05089       }
05090       pthread_attr_destroy(&attr);
05091       res = 0;
05092    }
05093 outgoing_exten_cleanup:
05094    ast_variables_destroy(vars);
05095    return res;
05096 }

enum ast_pbx_result ast_pbx_run ( struct ast_channel c  ) 

Execute the PBX in the current thread.

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

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

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

02644 {
02645    enum ast_pbx_result res = AST_PBX_SUCCESS;
02646 
02647    if (increase_call_count(c))
02648       return AST_PBX_CALL_LIMIT;
02649 
02650    res = __ast_pbx_run(c);
02651    decrease_call_count();
02652 
02653    return res;
02654 }

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

run the application and free the descriptor once done

Definition at line 5106 of file pbx.c.

References app_tmp::app, app, ast_hangup(), ast_log(), ast_verbose(), app_tmp::chan, app_tmp::data, free, LOG_WARNING, option_verbose, pbx_exec(), pbx_findapp(), and VERBOSE_PREFIX_4.

Referenced by ast_pbx_outgoing_app().

05107 {
05108    struct app_tmp *tmp = data;
05109    struct ast_app *app;
05110    app = pbx_findapp(tmp->app);
05111    if (app) {
05112       if (option_verbose > 3)
05113          ast_verbose(VERBOSE_PREFIX_4 "Launching %s(%s) on %s\n", tmp->app, tmp->data, tmp->chan->name);
05114       pbx_exec(tmp->chan, app, tmp->data);
05115    } else
05116       ast_log(LOG_WARNING, "No such application '%s'\n", tmp->app);
05117    ast_hangup(tmp->chan);
05118    free(tmp);
05119    return NULL;
05120 }

enum ast_pbx_result ast_pbx_start ( struct ast_channel c  ) 

Create a new thread and start the PBX.

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

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

Referenced by __oh323_new(), alsa_new(), ast_async_goto(), ast_iax2_new(), ast_pbx_outgoing_exten(), check_goto_on_transfer(), do_parking_thread(), gtalk_new(), gtalk_newcall(), handle_request_invite(), local_call(), mgcp_new(), nbs_new(), oss_new(), pbx_start_chan(), phone_new(), rpt_call(), sip_new(), skinny_new(), and zt_new().

02618 {
02619    pthread_t t;
02620    pthread_attr_t attr;
02621 
02622    if (!c) {
02623       ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
02624       return AST_PBX_FAILED;
02625    }
02626 
02627    if (increase_call_count(c))
02628       return AST_PBX_CALL_LIMIT;
02629 
02630    /* Start a new thread, and get something handling this channel. */
02631    pthread_attr_init(&attr);
02632    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
02633    if (ast_pthread_create(&t, &attr, pbx_thread, c)) {
02634       ast_log(LOG_WARNING, "Failed to create new channel thread\n");
02635       pthread_attr_destroy(&attr);
02636       return AST_PBX_FAILED;
02637    }
02638    pthread_attr_destroy(&attr);
02639 
02640    return AST_PBX_SUCCESS;
02641 }

int ast_register_application ( const char *  app,
int(*)(struct ast_channel *, void *)  execute,
const char *  synopsis,
const char *  description 
)

Register an application.

Parameters:
app Short name of the application
execute a function callback to execute the application. It should return non-zero if the channel needs to be hung up.
synopsis a short description (one line synopsis) of the application
description long description with all of the details about the use of the application
This registers an application with Asterisk's internal application list.
Note:
The individual applications themselves are responsible for registering and unregistering and unregistering their own CLI commands.
Return values:
0 success
-1 failure.

Definition at line 2945 of file pbx.c.

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

Referenced by load_module(), and load_pbx().

02946 {
02947    struct ast_app *tmp, *cur = NULL;
02948    char tmps[80];
02949    int length;
02950 
02951    AST_LIST_LOCK(&apps);
02952    AST_LIST_TRAVERSE(&apps, tmp, list) {
02953       if (!strcasecmp(app, tmp->name)) {
02954          ast_log(LOG_WARNING, "Already have an application '%s'\n", app);
02955          AST_LIST_UNLOCK(&apps);
02956          return -1;
02957       }
02958    }
02959 
02960    length = sizeof(*tmp) + strlen(app) + 1;
02961 
02962    if (!(tmp = ast_calloc(1, length))) {
02963       AST_LIST_UNLOCK(&apps);
02964       return -1;
02965    }
02966 
02967    strcpy(tmp->name, app);
02968    tmp->execute = execute;
02969    tmp->synopsis = synopsis;
02970    tmp->description = description;
02971 
02972    /* Store in alphabetical order */
02973    AST_LIST_TRAVERSE_SAFE_BEGIN(&apps, cur, list) {
02974       if (strcasecmp(tmp->name, cur->name) < 0) {
02975          AST_LIST_INSERT_BEFORE_CURRENT(&apps, tmp, list);
02976          break;
02977       }
02978    }
02979    AST_LIST_TRAVERSE_SAFE_END
02980    if (!cur)
02981       AST_LIST_INSERT_TAIL(&apps, tmp, list);
02982 
02983    if (option_verbose > 1)
02984       ast_verbose( VERBOSE_PREFIX_2 "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps)));
02985 
02986    AST_LIST_UNLOCK(&apps);
02987 
02988    return 0;
02989 }

int ast_register_switch ( struct ast_switch sw  ) 

Register an alternative dialplan switch.

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

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

Referenced by load_module().

02996 {
02997    struct ast_switch *tmp;
02998 
02999    AST_LIST_LOCK(&switches);
03000    AST_LIST_TRAVERSE(&switches, tmp, list) {
03001       if (!strcasecmp(tmp->name, sw->name)) {
03002          AST_LIST_UNLOCK(&switches);
03003          ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name);
03004          return -1;
03005       }
03006    }
03007    AST_LIST_INSERT_TAIL(&switches, sw, list);
03008    AST_LIST_UNLOCK(&switches);
03009 
03010    return 0;
03011 }

static int ast_remove_hint ( struct ast_exten e  )  [static]

ast_remove_hint: Remove hint from extension

Definition at line 2213 of file pbx.c.

References AST_EXTENSION_DEACTIVATED, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_state_cb::callback, ast_hint::callbacks, ast_state_cb::data, ast_exten::exten, ast_hint::exten, free, ast_state_cb::next, and ast_exten::parent.

Referenced by destroy_exten().

02214 {
02215    /* Cleanup the Notifys if hint is removed */
02216    struct ast_hint *hint;
02217    struct ast_state_cb *cblist, *cbprev;
02218    int res = -1;
02219 
02220    if (!e)
02221       return -1;
02222 
02223    AST_LIST_LOCK(&hints);
02224    AST_LIST_TRAVERSE_SAFE_BEGIN(&hints, hint, list) {
02225       if (hint->exten == e) {
02226          cbprev = NULL;
02227          cblist = hint->callbacks;
02228          while (cblist) {
02229             /* Notify with -1 and remove all callbacks */
02230             cbprev = cblist;
02231             cblist = cblist->next;
02232             cbprev->callback(hint->exten->parent->name, hint->exten->exten, AST_EXTENSION_DEACTIVATED, cbprev->data);
02233             free(cbprev);
02234             }
02235             hint->callbacks = NULL;
02236          AST_LIST_REMOVE_CURRENT(&hints, list);
02237             free(hint);
02238             res = 0;
02239          break;
02240       }
02241    }
02242    AST_LIST_TRAVERSE_SAFE_END
02243    AST_LIST_UNLOCK(&hints);
02244 
02245    return res;
02246 }

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

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

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

References E_SPAWN, and pbx_extension_helper().

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

02293 {
02294    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN);
02295 }

int ast_unlock_context ( struct ast_context con  ) 

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

Definition at line 6091 of file pbx.c.

References ast_mutex_unlock(), and ast_context::lock.

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

06092 {
06093    return ast_mutex_unlock(&con->lock);
06094 }

int ast_unlock_contexts ( void   ) 

Unlocks contexts.

Return values:
0 on success
-1 on failure

Definition at line 6078 of file pbx.c.

References ast_mutex_unlock().

Referenced by _macro_exec(), ast_add_extension(), ast_context_add_ignorepat(), ast_context_add_include(), ast_context_add_switch(), ast_context_lockmacro(), ast_context_remove_extension(), ast_context_remove_ignorepat(), ast_context_remove_include(), ast_context_remove_switch(), ast_context_unlockmacro(), complete_context_add_extension(), complete_context_add_extension_deprecated(), complete_context_add_ignorepat(), complete_context_add_ignorepat_deprecated(), complete_context_add_include(), complete_context_add_include_deprecated(), complete_context_dont_include_deprecated(), complete_context_remove_extension(), complete_context_remove_extension_deprecated(), complete_context_remove_ignorepat(), complete_context_remove_ignorepat_deprecated(), complete_context_remove_include(), complete_show_dialplan_context(), dundi_precache_full(), find_context_locked(), find_matching_endwhile(), handle_save_dialplan(), and show_dialplan_helper().

06079 {
06080    return ast_mutex_unlock(&conlock);
06081 }

int ast_unregister_application ( const char *  app  ) 

Unregister an application.

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

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

Referenced by __unload_module(), and unload_module().

03827 {
03828    struct ast_app *tmp;
03829 
03830    AST_LIST_LOCK(&apps);
03831    AST_LIST_TRAVERSE_SAFE_BEGIN(&apps, tmp, list) {
03832       if (!strcasecmp(app, tmp->name)) {
03833          AST_LIST_REMOVE_CURRENT(&apps, list);
03834          if (option_verbose > 1)
03835             ast_verbose( VERBOSE_PREFIX_2 "Unregistered application '%s'\n", tmp->name);
03836          free(tmp);
03837          break;
03838       }
03839    }
03840    AST_LIST_TRAVERSE_SAFE_END
03841    AST_LIST_UNLOCK(&apps);
03842 
03843    return tmp ? 0 : -1;
03844 }

void ast_unregister_switch ( struct ast_switch sw  ) 

Unregister an alternative switch.

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

Returns:
nothing

Definition at line 3013 of file pbx.c.

References AST_LIST_LOCK, AST_LIST_REMOVE, and AST_LIST_UNLOCK.

Referenced by __unload_module(), and unload_module().

03014 {
03015    AST_LIST_LOCK(&switches);
03016    AST_LIST_REMOVE(&switches, sw, list);
03017    AST_LIST_UNLOCK(&switches);
03018 }

struct ast_exten* ast_walk_context_extensions ( struct ast_context con,
struct ast_exten exten 
)

Definition at line 6200 of file pbx.c.

References exten, and ast_context::root.

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

06202 {
06203    if (!exten)
06204       return con ? con->root : NULL;
06205    else
06206       return exten->next;
06207 }

struct ast_ignorepat* ast_walk_context_ignorepats ( struct ast_context con,
struct ast_ignorepat ip 
)

Definition at line 6233 of file pbx.c.

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

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

06235 {
06236    if (!ip)
06237       return con ? con->ignorepats : NULL;
06238    else
06239       return ip->next;
06240 }

struct ast_include* ast_walk_context_includes ( struct ast_context con,
struct ast_include inc 
)

Definition at line 6224 of file pbx.c.

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

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

06226 {
06227    if (!inc)
06228       return con ? con->includes : NULL;
06229    else
06230       return inc->next;
06231 }

struct ast_sw* ast_walk_context_switches ( struct ast_context con,
struct ast_sw sw 
)

Definition at line 6209 of file pbx.c.

References AST_LIST_FIRST, and AST_LIST_NEXT.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06211 {
06212    if (!sw)
06213       return con ? AST_LIST_FIRST(&con->alts) : NULL;
06214    else
06215       return AST_LIST_NEXT(sw, list);
06216 }

struct ast_context* ast_walk_contexts ( struct ast_context con  ) 

Definition at line 6195 of file pbx.c.

References contexts, and ast_context::next.

Referenced by _macro_exec(), ast_context_find(), ast_context_lockmacro(), ast_context_unlockmacro(), complete_context_add_extension(), complete_context_add_extension_deprecated(), complete_context_add_ignorepat(), complete_context_add_ignorepat_deprecated(), complete_context_add_include(), complete_context_add_include_deprecated(), complete_context_dont_include_deprecated(), complete_context_remove_extension(), complete_context_remove_extension_deprecated(), complete_context_remove_ignorepat(), complete_context_remove_ignorepat_deprecated(), complete_context_remove_include(), complete_show_dialplan_context(), dundi_precache_full(), find_context_locked(), find_matching_endwhile(), find_matching_priority(), handle_save_dialplan(), pbx_find_extension(), pbx_load_module(), and show_dialplan_helper().

06196 {
06197    return con ? con->next : contexts;
06198 }

struct ast_exten* ast_walk_extension_priorities ( struct ast_exten exten,
struct ast_exten priority 
)

Definition at line 6218 of file pbx.c.

References exten, and ast_exten::priority.

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

06220 {
06221    return priority ? priority->peer : exten;
06222 }

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

Definition at line 4878 of file pbx.c.

References ast_channel::_state, app, async_stat::app, async_stat::appdata, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_FRAME_CONTROL, ast_frfree(), ast_hangup(), ast_log(), ast_pbx_run(), ast_read(), AST_STATE_UP, ast_strlen_zero(), ast_verbose(), ast_waitfor(), async_stat::chan, ast_channel::context, async_stat::context, ast_channel::exten, async_stat::exten, f, free, LOG_ERROR, LOG_WARNING, option_verbose, pbx_exec(), pbx_findapp(), ast_channel::priority, async_stat::priority, async_stat::timeout, timeout, and VERBOSE_PREFIX_3.

Referenced by ast_pbx_outgoing_app(), and ast_pbx_outgoing_exten().

04879 {
04880    struct async_stat *as = data;
04881    struct ast_channel *chan = as->chan;
04882    int timeout = as->timeout;
04883    int res;
04884    struct ast_frame *f;
04885    struct ast_app *app;
04886 
04887    while (timeout && (chan->_state != AST_STATE_UP)) {
04888       res = ast_waitfor(chan, timeout);
04889       if (res < 1)
04890          break;
04891       if (timeout > -1)
04892          timeout = res;
04893       f = ast_read(chan);
04894       if (!f)
04895          break;
04896       if (f->frametype == AST_FRAME_CONTROL) {
04897          if ((f->subclass == AST_CONTROL_BUSY)  ||
04898              (f->subclass == AST_CONTROL_CONGESTION) ) {
04899             ast_frfree(f);
04900             break;
04901          }
04902       }
04903       ast_frfree(f);
04904    }
04905    if (chan->_state == AST_STATE_UP) {
04906       if (!ast_strlen_zero(as->app)) {
04907          app = pbx_findapp(as->app);
04908          if (app) {
04909             if (option_verbose > 2)
04910                ast_verbose(VERBOSE_PREFIX_3 "Launching %s(%s) on %s\n", as->app, as->appdata, chan->name);
04911             pbx_exec(chan, app, as->appdata);
04912          } else
04913             ast_log(LOG_WARNING, "No such application '%s'\n", as->app);
04914       } else {
04915          if (!ast_strlen_zero(as->context))
04916             ast_copy_string(chan->context, as->context, sizeof(chan->context));
04917          if (!ast_strlen_zero(as->exten))
04918             ast_copy_string(chan->exten, as->exten, sizeof(chan->exten));
04919          if (as->priority > 0)
04920             chan->priority = as->priority;
04921          /* Run the PBX */
04922          if (ast_pbx_run(chan)) {
04923             ast_log(LOG_ERROR, "Failed to start PBX on %s\n", chan->name);
04924          } else {
04925             /* PBX will have taken care of this */
04926             chan = NULL;
04927          }
04928       }
04929    }
04930    free(as);
04931    if (chan)
04932       ast_hangup(chan);
04933    return NULL;
04934 }

static int collect_digits ( struct ast_channel c,
int  waittime,
char *  buf,
int  buflen,
int  pos 
) [static]

collect digits from the channel into the buffer, return -1 on error, 0 on timeout or done.

Definition at line 2308 of file pbx.c.

References ast_channel::_softhangup, ast_matchmore_extension(), AST_SOFTHANGUP_ASYNCGOTO, ast_waitfordigit(), ast_channel::cid, ast_callerid::cid_num, ast_channel::context, ast_pbx::dtimeout, and ast_channel::pbx.

02309 {
02310    int digit;
02311 
02312    buf[pos] = '\0';  /* make sure it is properly terminated */
02313    while (ast_matchmore_extension(c, c->context, buf, 1, c->cid.cid_num)) {
02314       /* As long as we're willing to wait, and as long as it's not defined,
02315          keep reading digits until we can't possibly get a right answer anymore.  */
02316       digit = ast_waitfordigit(c, waittime * 1000);
02317       if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
02318          c->_softhangup = 0;
02319       } else {
02320          if (!digit) /* No entry */
02321             break;
02322          if (digit < 0) /* Error, maybe a  hangup */
02323             return -1;
02324          if (pos < buflen - 1) { /* XXX maybe error otherwise ? */
02325             buf[pos++] = digit;
02326             buf[pos] = '\0';
02327          }
02328          waittime = c->pbx->dtimeout;
02329       }
02330    }
02331    return 0;
02332 }

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

Definition at line 3071 of file pbx.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, and strdup.

03072 {
03073    struct ast_app *a;
03074    char *ret = NULL;
03075    int which = 0;
03076    int wordlen = strlen(word);
03077 
03078    /* return the n-th [partial] matching entry */
03079    AST_LIST_LOCK(&apps);
03080    AST_LIST_TRAVERSE(&apps, a, list) {
03081       if (!strncasecmp(word, a->name, wordlen) && ++which > state) {
03082          ret = strdup(a->name);
03083          break;
03084       }
03085    }
03086    AST_LIST_UNLOCK(&apps);
03087 
03088    return ret;
03089 }

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

Definition at line 3432 of file pbx.c.

References ast_cli_complete().

03433 {
03434    static char* choices[] = { "like", "describing", NULL };
03435 
03436    return (pos != 3) ? NULL : ast_cli_complete(word, choices, state);
03437 }

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

Definition at line 3425 of file pbx.c.

References ast_cli_complete().

03426 {
03427    static char* choices[] = { "like", "describing", NULL };
03428 
03429    return (pos != 2) ? NULL : ast_cli_complete(word, choices, state);
03430 }

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

Definition at line 3442 of file pbx.c.

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

03444 {
03445    struct ast_context *c = NULL;
03446    char *ret = NULL;
03447    int which = 0;
03448    int wordlen;
03449 
03450    /* we are do completion of [exten@]context on second position only */
03451    if (pos != 2)
03452       return NULL;
03453 
03454    ast_lock_contexts();
03455 
03456    wordlen = strlen(word);
03457 
03458    /* walk through all contexts and return the n-th match */
03459    while ( (c = ast_walk_contexts(c)) ) {
03460       if (!strncasecmp(word, ast_get_context_name(c), wordlen) && ++which > state) {
03461          ret = ast_strdup(ast_get_context_name(c));
03462          break;
03463       }
03464    }
03465 
03466    ast_unlock_contexts();
03467 
03468    return ret;
03469 }

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

Definition at line 1413 of file pbx.c.

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

01414 {
01415    struct ast_custom_function *acf;
01416    char *ret = NULL;
01417    int which = 0;
01418    int wordlen = strlen(word);
01419 
01420    /* case-insensitive for convenience in this 'complete' function */
01421    AST_LIST_LOCK(&acf_root);
01422    AST_LIST_TRAVERSE(&acf_root, acf, acflist) {
01423       if (!strncasecmp(word, acf->name, wordlen) && ++which > state) {
01424          ret = strdup(acf->name);
01425          break;
01426       }
01427    }
01428    AST_LIST_UNLOCK(&acf_root);
01429 
01430    return ret;
01431 }

static void decrease_call_count ( void   )  [static]

Definition at line 2579 of file pbx.c.

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

Referenced by ast_pbx_run(), and pbx_thread().

02580 {
02581    ast_mutex_lock(&maxcalllock);
02582    if (countcalls > 0)
02583       countcalls--;
02584    ast_mutex_unlock(&maxcalllock);
02585 }

static void destroy_exten ( struct ast_exten e  )  [static]

Definition at line 2587 of file pbx.c.

References ast_remove_hint(), free, ast_exten::priority, and PRIORITY_HINT.

Referenced by __ast_context_destroy(), and ast_context_remove_extension2().

02588 {
02589    if (e->priority == PRIORITY_HINT)
02590       ast_remove_hint(e);
02591 
02592    if (e->datad)
02593       e->datad(e->data);
02594    free(e);
02595 }

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

the full routine to compare extensions in rules.

Definition at line 719 of file pbx.c.

References ext_cmp1().

Referenced by ast_add_extension2().

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

static int ext_cmp1 ( const char **  p  )  [static]

helper functions to sort extensions and patterns in the desired way, so that more specific patterns appear first.

ext_cmp1 compares individual characters (or sets of), returning an int where bits 0-7 are the ASCII code of the first char in the set, while bit 8-15 are the cardinality of the set minus 1. This way more specific patterns (smaller cardinality) appear first. Wildcards have a special value, so that we can directly compare them to sets by subtracting the two values. In particular: 0x000xx one character, xx 0x0yyxx yy character set starting with xx 0x10000 '.' (one or more of anything) 0x20000 '!' (zero or more of anything) 0x30000 NUL (end of string) 0x40000 error in set. The pointer to the string is advanced according to needs. NOTES: 1. the empty set is equivalent to NUL. 2. given that a full set has always 0 as the first element, we could encode the special cases as 0xffXX where XX is 1, 2, 3, 4 as used above.

Definition at line 647 of file pbx.c.

References ast_log(), and LOG_WARNING.

Referenced by ext_cmp().

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

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

copy a string skipping whitespace

Definition at line 4630 of file pbx.c.

Referenced by ast_add_extension2().

04631 {
04632    int count=0;
04633 
04634    while (*src && (count < len - 1)) {
04635       switch(*src) {
04636       case ' ':
04637          /* otherwise exten => [a-b],1,... doesn't work */
04638          /*    case '-': */
04639          /* Ignore */
04640          break;
04641       default:
04642          *dst = *src;
04643          dst++;
04644       }
04645       src++;
04646       count++;
04647    }
04648    *dst = '\0';
04649 
04650    return count;
04651 }

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

Definition at line 868 of file pbx.c.

References _extension_match_core(), ast_add_profile(), and ast_mark().

Referenced by ast_extension_close(), ast_extension_match(), and pbx_find_extension().

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

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

Definition at line 2671 of file pbx.c.

References ast_get_context_name(), ast_lock_contexts(), ast_unlock_contexts(), and ast_walk_contexts().

Referenced by ast_add_extension(), ast_context_add_ignorepat(), ast_context_add_include(), ast_context_add_switch(), ast_context_remove_extension(), ast_context_remove_ignorepat(), ast_context_remove_include(), and ast_context_remove_switch().

02672 {
02673    struct ast_context *c = NULL;
02674 
02675    ast_lock_contexts();
02676    while ( (c = ast_walk_contexts(c)) ) {
02677       if (!strcmp(ast_get_context_name(c), context))
02678          return c;
02679    }
02680    ast_unlock_contexts();
02681 
02682    return NULL;
02683 }

static char* func_args ( char *  function  )  [static]

return a pointer to the arguments of the function, and terminates the function name with '\0'

Definition at line 1506 of file pbx.c.

References ast_log(), and LOG_WARNING.

Referenced by ast_func_read(), and ast_func_write().

01507 {
01508    char *args = strchr(function, '(');
01509 
01510    if (!args)
01511       ast_log(LOG_WARNING, "Function doesn't contain parentheses.  Assuming null argument.\n");
01512    else {
01513       char *p;
01514       *args++ = '\0';
01515       if ((p = strrchr(args, ')')) )
01516          *p = '\0';
01517       else
01518          ast_log(LOG_WARNING, "Can't find trailing parenthesis?\n");
01519    }
01520    return args;
01521 }

static unsigned get_range ( char *  src,
int  max,
char *const   names[],
const char *  msg 
) [static]

helper function to return a range up to max (7, 12, 31 respectively). names, if supplied, is an array of names that should be mapped to numbers.

Definition at line 4052 of file pbx.c.

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

Referenced by ast_build_timing().

04053 {
04054    int s, e; /* start and ending position */
04055    unsigned int mask = 0;
04056 
04057    /* Check for whole range */
04058    if (ast_strlen_zero(src) || !strcmp(src, "*")) {
04059       s = 0;
04060       e = max - 1;
04061    } else {
04062       /* Get start and ending position */
04063       char *c = strchr(src, '-');
04064       if (c)
04065          *c++ = '\0';
04066       /* Find the start */
04067       s = lookup_name(src, names, max);
04068       if (!s) {
04069          ast_log(LOG_WARNING, "Invalid %s '%s', assuming none\n", msg, src);
04070          return 0;
04071       }
04072       s--;
04073       if (c) { /* find end of range */
04074          e = lookup_name(c, names, max);
04075          if (!e) {
04076             ast_log(LOG_WARNING, "Invalid end %s '%s', assuming none\n", msg, c);
04077             return 0;
04078          }
04079          e--;
04080       } else
04081          e = s;
04082    }
04083    /* Fill the mask. Remember that ranges are cyclic */
04084    mask = 1 << e; /* initialize with last element */
04085    while (s != e) {
04086       if (s >= max) {
04087          s = 0;
04088          mask |= (1 << s);
04089       } else {
04090          mask |= (1 << s);
04091          s++;
04092       }
04093    }
04094    return mask;
04095 }

static void get_timerange ( struct ast_timing i,
char *  times 
) [static]

store a bitmask of valid times, one bit each 2 minute

Definition at line 4098 of file pbx.c.

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

Referenced by ast_build_timing().

04099 {
04100    char *e;
04101    int x;
04102    int s1, s2;
04103    int e1, e2;
04104    /* int cth, ctm; */
04105 
04106    /* start disabling all times, fill the fields with 0's, as they may contain garbage */
04107    memset(i->minmask, 0, sizeof(i->minmask));
04108 
04109    /* 2-minutes per bit, since the mask has only 32 bits :( */
04110    /* Star is all times */
04111    if (ast_strlen_zero(times) || !strcmp(times, "*")) {
04112       for (x=0; x<24; x++)
04113          i->minmask[x] = 0x3fffffff; /* 30 bits */
04114       return;
04115    }
04116    /* Otherwise expect a range */
04117    e = strchr(times, '-');
04118    if (!e) {
04119       ast_log(LOG_WARNING, "Time range is not valid. Assuming no restrictions based on time.\n");
04120       return;
04121    }
04122    *e++ = '\0';
04123    /* XXX why skip non digits ? */
04124    while (*e && !isdigit(*e))
04125       e++;
04126    if (!*e) {
04127       ast_log(LOG_WARNING, "Invalid time range.  Assuming no restrictions based on time.\n");
04128       return;
04129    }
04130    if (sscanf(times, "%d:%d", &s1, &s2) != 2) {
04131       ast_log(LOG_WARNING, "%s isn't a time.  Assuming no restrictions based on time.\n", times);
04132       return;
04133    }
04134    if (sscanf(e, "%d:%d", &e1, &e2) != 2) {
04135       ast_log(LOG_WARNING, "%s isn't a time.  Assuming no restrictions based on time.\n", e);
04136       return;
04137    }
04138    /* XXX this needs to be optimized */
04139 #if 1
04140    s1 = s1 * 30 + s2/2;
04141    if ((s1 < 0) || (s1 >= 24*30)) {
04142       ast_log(LOG_WARNING, "%s isn't a valid start time. Assuming no time.\n", times);
04143       return;
04144    }
04145    e1 = e1 * 30 + e2/2;
04146    if ((e1 < 0) || (e1 >= 24*30)) {
04147       ast_log(LOG_WARNING, "%s isn't a valid end time. Assuming no time.\n", e);
04148       return;
04149    }
04150    /* Go through the time and enable each appropriate bit */
04151    for (x=s1;x != e1;x = (x + 1) % (24 * 30)) {
04152       i->minmask[x/30] |= (1 << (x % 30));
04153    }
04154    /* Do the last one */
04155    i->minmask[x/30] |= (1 << (x % 30));
04156 #else
04157    for (cth=0; cth<24; cth++) {
04158       /* Initialize masks to blank */
04159       i->minmask[cth] = 0;
04160       for (ctm=0; ctm<30; ctm++) {
04161          if (
04162          /* First hour with more than one hour */
04163                (((cth == s1) && (ctm >= s2)) &&
04164                 ((cth < e1)))
04165          /* Only one hour */
04166          ||    (((cth == s1) && (ctm >= s2)) &&
04167                 ((cth == e1) && (ctm <= e2)))
04168          /* In between first and last hours (more than 2 hours) */
04169          ||    ((cth > s1) &&
04170                 (cth < e1))
04171          /* Last hour with more than one hour */
04172          ||    ((cth > s1) &&
04173                 ((cth == e1) && (ctm <= e2)))
04174          )
04175             i->minmask[cth] |= (1 << (ctm / 2));
04176       }
04177    }
04178 #endif
04179    /* All done */
04180    return;
04181 }

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

Definition at line 3727 of file pbx.c.

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

03728 {
03729    if (argc != 5)
03730       return RESULT_SHOWUSAGE;
03731 
03732    pbx_builtin_setvar_helper(NULL, argv[3], argv[4]);
03733    ast_cli(fd, "\n    -- Global variable %s set to %s\n", argv[3], argv[4]);
03734 
03735    return RESULT_SUCCESS;
03736 }

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

CLI support for setting global variables.

Definition at line 3715 of file pbx.c.

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

03716 {
03717    if (argc != 4)
03718       return RESULT_SHOWUSAGE;
03719 
03720    pbx_builtin_setvar_helper(NULL, argv[2], argv[3]);
03721    ast_cli(fd, "\n    -- Global variable %s set to %s\n", argv[2], argv[3]);
03722 
03723    return RESULT_SUCCESS;
03724 }

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

Definition at line 3161 of file pbx.c.

References ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_MAX_APP, COLOR_CYAN, COLOR_MAGENTA, ast_app::description, RESULT_SHOWUSAGE, ast_app::synopsis, and term_color().

03162 {
03163    struct ast_app *a;
03164    int app, no_registered_app = 1;
03165 
03166    if (argc < 4)
03167       return RESULT_SHOWUSAGE;
03168 
03169    /* ... go through all applications ... */
03170    AST_LIST_LOCK(&apps);
03171    AST_LIST_TRAVERSE(&apps, a, list) {
03172       /* ... compare this application name with all arguments given
03173        * to 'show application' command ... */
03174       for (app = 3; app < argc; app++) {
03175          if (!strcasecmp(a->name, argv[app])) {
03176             /* Maximum number of characters added by terminal coloring is 22 */
03177             char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40];
03178             char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL;
03179             int synopsis_size, description_size;
03180 
03181             no_registered_app = 0;
03182 
03183             if (a->synopsis)
03184                synopsis_size = strlen(a->synopsis) + 23;
03185             else
03186                synopsis_size = strlen("Not available") + 23;
03187             synopsis = alloca(synopsis_size);
03188 
03189             if (a->description)
03190                description_size = strlen(a->description) + 23;
03191             else
03192                description_size = strlen("Not available") + 23;
03193             description = alloca(description_size);
03194 
03195             if (synopsis && description) {
03196                snprintf(info, 64 + AST_MAX_APP, "\n  -= Info about application '%s' =- \n\n", a->name);
03197                term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22);
03198                term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
03199                term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
03200                term_color(synopsis,
03201                            a->synopsis ? a->synopsis : "Not available",
03202                            COLOR_CYAN, 0, synopsis_size);
03203                term_color(description,
03204                            a->description ? a->description : "Not available",
03205                            COLOR_CYAN, 0, description_size);
03206 
03207                ast_cli(fd,"%s%s%s\n\n%s%s\n", infotitle, syntitle, synopsis, destitle, description);
03208             } else {
03209                /* ... one of our applications, show info ...*/
03210                ast_cli(fd,"\n  -= Info about application '%s' =- \n\n"
03211                   "[Synopsis]\n  %s\n\n"
03212                   "[Description]\n%s\n",
03213                   a->name,
03214                   a->synopsis ? a->synopsis : "Not available",
03215                   a->description ? a->description : "Not available");
03216             }
03217          }
03218       }
03219    }
03220    AST_LIST_UNLOCK(&apps);
03221 
03222    /* we found at least one app? no? */
03223    if (no_registered_app) {
03224       ast_cli(fd, "Your application(s) is (are) not registered\n");
03225       return RESULT_FAILURE;
03226    }
03227 
03228    return RESULT_SUCCESS;
03229 }

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

Definition at line 3091 of file pbx.c.

References ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_MAX_APP, COLOR_CYAN, COLOR_MAGENTA, ast_app::description, RESULT_SHOWUSAGE, ast_app::synopsis, and term_color().

03092 {
03093    struct ast_app *a;
03094    int app, no_registered_app = 1;
03095 
03096    if (argc < 3)
03097       return RESULT_SHOWUSAGE;
03098 
03099    /* ... go through all applications ... */
03100    AST_LIST_LOCK(&apps);
03101    AST_LIST_TRAVERSE(&apps, a, list) {
03102       /* ... compare this application name with all arguments given
03103        * to 'show application' command ... */
03104       for (app = 2; app < argc; app++) {
03105          if (!strcasecmp(a->name, argv[app])) {
03106             /* Maximum number of characters added by terminal coloring is 22 */
03107             char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40];
03108             char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL;
03109             int synopsis_size, description_size;
03110 
03111             no_registered_app = 0;
03112 
03113             if (a->synopsis)
03114                synopsis_size = strlen(a->synopsis) + 23;
03115             else
03116                synopsis_size = strlen("Not available") + 23;
03117             synopsis = alloca(synopsis_size);
03118 
03119             if (a->description)
03120                description_size = strlen(a->description) + 23;
03121             else
03122                description_size = strlen("Not available") + 23;
03123             description = alloca(description_size);
03124 
03125             if (synopsis && description) {
03126                snprintf(info, 64 + AST_MAX_APP, "\n  -= Info about application '%s' =- \n\n", a->name);
03127                term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22);
03128                term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
03129                term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
03130                term_color(synopsis,
03131                            a->synopsis ? a->synopsis : "Not available",
03132                            COLOR_CYAN, 0, synopsis_size);
03133                term_color(description,
03134                            a->description ? a->description : "Not available",
03135                            COLOR_CYAN, 0, description_size);
03136 
03137                ast_cli(fd,"%s%s%s\n\n%s%s\n", infotitle, syntitle, synopsis, destitle, description);
03138             } else {
03139                /* ... one of our applications, show info ...*/
03140                ast_cli(fd,"\n  -= Info about application '%s' =- \n\n"
03141                   "[Synopsis]\n  %s\n\n"
03142                   "[Description]\n%s\n",
03143                   a->name,
03144                   a->synopsis ? a->synopsis : "Not available",
03145                   a->description ? a->description : "Not available");
03146             }
03147          }
03148       }
03149    }
03150    AST_LIST_UNLOCK(&apps);
03151 
03152    /* we found at least one app? no? */
03153    if (no_registered_app) {
03154       ast_cli(fd, "Your application(s) is (are) not registered\n");
03155       return RESULT_FAILURE;
03156    }
03157 
03158    return RESULT_SUCCESS;
03159 }

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

Definition at line 3356 of file pbx.c.

References ast_cli(), AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_app::description, strcasestr(), and ast_app::synopsis.

03357 {
03358    struct ast_app *a;
03359    int like = 0, describing = 0;
03360    int total_match = 0;    /* Number of matches in like clause */
03361    int total_apps = 0;  /* Number of apps registered */
03362 
03363    AST_LIST_LOCK(&apps);
03364 
03365    if (AST_LIST_EMPTY(&apps)) {
03366       ast_cli(fd, "There are no registered applications\n");
03367       AST_LIST_UNLOCK(&apps);
03368       return -1;
03369    }
03370 
03371    /* core list applications like <keyword> */
03372    if ((argc == 5) && (!strcmp(argv[3], "like"))) {
03373       like = 1;
03374    } else if ((argc > 4) && (!strcmp(argv[3], "describing"))) {
03375       describing = 1;
03376    }
03377 
03378    /* core list applications describing <keyword1> [<keyword2>] [...] */
03379    if ((!like) && (!describing)) {
03380       ast_cli(fd, "    -= Registered Asterisk Applications =-\n");
03381    } else {
03382       ast_cli(fd, "    -= Matching Asterisk Applications =-\n");
03383    }
03384 
03385    AST_LIST_TRAVERSE(&apps, a, list) {
03386       int printapp = 0;
03387       total_apps++;
03388       if (like) {
03389          if (strcasestr(a->name, argv[4])) {
03390             printapp = 1;
03391             total_match++;
03392          }
03393       } else if (describing) {
03394          if (a->description) {
03395             /* Match all words on command line */
03396             int i;
03397             printapp = 1;
03398             for (i = 4; i < argc; i++) {
03399                if (!strcasestr(a->description, argv[i])) {
03400                   printapp = 0;
03401                } else {
03402                   total_match++;
03403                }
03404             }
03405          }
03406       } else {
03407          printapp = 1;
03408       }
03409 
03410       if (printapp) {
03411          ast_cli(fd,"  %20s: %s\n", a->name, a->synopsis ? a->synopsis : "<Synopsis not available>");
03412       }
03413    }
03414    if ((!like) && (!describing)) {
03415       ast_cli(fd, "    -= %d Applications Registered =-\n",total_apps);
03416    } else {
03417       ast_cli(fd, "    -= %d Applications Matching =-\n",total_match);
03418    }
03419 
03420    AST_LIST_UNLOCK(&apps);
03421 
03422    return RESULT_SUCCESS;
03423 }

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

Definition at line 3288 of file pbx.c.

References ast_cli(), AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_app::description, strcasestr(), and ast_app::synopsis.

03289 {
03290    struct ast_app *a;
03291    int like = 0, describing = 0;
03292    int total_match = 0;    /* Number of matches in like clause */
03293    int total_apps = 0;  /* Number of apps registered */
03294 
03295    AST_LIST_LOCK(&apps);
03296 
03297    if (AST_LIST_EMPTY(&apps)) {
03298       ast_cli(fd, "There are no registered applications\n");
03299       AST_LIST_UNLOCK(&apps);
03300       return -1;
03301    }
03302 
03303    /* show applications like <keyword> */
03304    if ((argc == 4) && (!strcmp(argv[2], "like"))) {
03305       like = 1;
03306    } else if ((argc > 3) && (!strcmp(argv[2], "describing"))) {
03307       describing = 1;
03308    }
03309 
03310    /* show applications describing <keyword1> [<keyword2>] [...] */
03311    if ((!like) && (!describing)) {
03312       ast_cli(fd, "    -= Registered Asterisk Applications =-\n");
03313    } else {
03314       ast_cli(fd, "    -= Matching Asterisk Applications =-\n");
03315    }
03316 
03317    AST_LIST_TRAVERSE(&apps, a, list) {
03318       int printapp = 0;
03319       total_apps++;
03320       if (like) {
03321          if (strcasestr(a->name, argv[3])) {
03322             printapp = 1;
03323             total_match++;
03324          }
03325       } else if (describing) {
03326          if (a->description) {
03327             /* Match all words on command line */
03328             int i;
03329             printapp = 1;
03330             for (i = 3; i < argc; i++) {
03331                if (!strcasestr(a->description, argv[i])) {
03332                   printapp = 0;
03333                } else {
03334                   total_match++;
03335                }
03336             }
03337          }
03338       } else {
03339          printapp = 1;
03340       }
03341 
03342       if (printapp) {
03343          ast_cli(fd,"  %20s: %s\n", a->name, a->synopsis ? a->synopsis : "<Synopsis not available>");
03344       }
03345    }
03346    if ((!like) && (!describing)) {
03347       ast_cli(fd, "    -= %d Applications Registered =-\n",total_apps);
03348    } else {
03349       ast_cli(fd, "    -= %d Applications Matching =-\n",total_match);
03350    }
03351 
03352    AST_LIST_UNLOCK(&apps);
03353 
03354    return RESULT_SUCCESS;
03355 }

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

Definition at line 3642 of file pbx.c.

References ast_cli(), AST_PBX_MAX_STACK, ast_strdupa, ast_strlen_zero(), context, exten, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, show_dialplan_helper(), and strsep().

03643 {
03644    char *exten = NULL, *context = NULL;
03645    /* Variables used for different counters */
03646    struct dialplan_counters counters;
03647 
03648    const char *incstack[AST_PBX_MAX_STACK];
03649    memset(&counters, 0, sizeof(counters));
03650 
03651    if (argc != 2 && argc != 3)
03652       return RESULT_SHOWUSAGE;
03653 
03654    /* we obtain [exten@]context? if yes, split them ... */
03655    if (argc == 3) {
03656       if (strchr(argv[2], '@')) {   /* split into exten & context */
03657          context = ast_strdupa(argv[2]);
03658          exten = strsep(&context, "@");
03659          /* change empty strings to NULL */
03660          if (ast_strlen_zero(exten))
03661             exten = NULL;
03662       } else { /* no '@' char, only context given */
03663          context = argv[2];
03664       }
03665       if (ast_strlen_zero(context))
03666          context = NULL;
03667    }
03668    /* else Show complete dial plan, context and exten are NULL */
03669    show_dialplan_helper(fd, context, exten, &counters, NULL, 0, incstack);
03670 
03671    /* check for input failure and throw some error messages */
03672    if (context && !counters.context_existence) {
03673       ast_cli(fd, "There is no existence of '%s' context\n", context);
03674       return RESULT_FAILURE;
03675    }
03676 
03677    if (exten && !counters.extension_existence) {
03678       if (context)
03679          ast_cli(fd, "There is no existence of %s@%s extension\n",
03680             exten, context);
03681       else
03682          ast_cli(fd,
03683             "There is no existence of '%s' extension in all contexts\n",
03684             exten);
03685       return RESULT_FAILURE;
03686    }
03687 
03688    ast_cli(fd,"-= %d %s (%d %s) in %d %s. =-\n",
03689             counters.total_exten, counters.total_exten == 1 ? "extension" : "extensions",
03690             counters.total_prio, counters.total_prio == 1 ? "priority" : "priorities",
03691             counters.total_context, counters.total_context == 1 ? "context" : "contexts");
03692 
03693    /* everything ok */
03694    return RESULT_SUCCESS;
03695 }

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

Definition at line 1357 of file pbx.c.

References ast_cli(), ast_custom_function_find(), AST_MAX_APP, COLOR_CYAN, COLOR_MAGENTA, ast_custom_function::desc, ast_custom_function::name, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, ast_custom_function::synopsis, ast_custom_function::syntax, and term_color().

01358 {
01359    struct ast_custom_function *acf;
01360    /* Maximum number of characters added by terminal coloring is 22 */
01361    char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40];
01362    char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL;
01363    char stxtitle[40], *syntax = NULL;
01364    int synopsis_size, description_size, syntax_size;
01365 
01366    if (argc < 4)
01367       return RESULT_SHOWUSAGE;
01368 
01369    if (!(acf = ast_custom_function_find(argv[3]))) {
01370       ast_cli(fd, "No function by that name registered.\n");
01371       return RESULT_FAILURE;
01372 
01373    }
01374 
01375    if (acf->synopsis)
01376       synopsis_size = strlen(acf->synopsis) + 23;
01377    else
01378       synopsis_size = strlen("Not available") + 23;
01379    synopsis = alloca(synopsis_size);
01380 
01381    if (acf->desc)
01382       description_size = strlen(acf->desc) + 23;
01383    else
01384       description_size = strlen("Not available") + 23;
01385    description = alloca(description_size);
01386 
01387    if (acf->syntax)
01388       syntax_size = strlen(acf->syntax) + 23;
01389    else
01390       syntax_size = strlen("Not available") + 23;
01391    syntax = alloca(syntax_size);
01392 
01393    snprintf(info, 64 + AST_MAX_APP, "\n  -= Info about function '%s' =- \n\n", acf->name);
01394    term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22);
01395    term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40);
01396    term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
01397    term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
01398    term_color(syntax,
01399          acf->syntax ? acf->syntax : "Not available",
01400          COLOR_CYAN, 0, syntax_size);
01401    term_color(synopsis,
01402          acf->synopsis ? acf->synopsis : "Not available",
01403          COLOR_CYAN, 0, synopsis_size);
01404    term_color(description,
01405          acf->desc ? acf->desc : "Not available",
01406          COLOR_CYAN, 0, description_size);
01407 
01408    ast_cli(fd,"%s%s%s\n\n%s%s\n\n%s%s\n", infotitle, stxtitle, syntax, syntitle, synopsis, destitle, description);
01409 
01410    return RESULT_SUCCESS;
01411 }

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

Definition at line 1301 of file pbx.c.

References ast_cli(), ast_custom_function_find(), AST_MAX_APP, COLOR_CYAN, COLOR_MAGENTA, ast_custom_function::desc, ast_custom_function::name, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, ast_custom_function::synopsis, ast_custom_function::syntax, and term_color().

01302 {
01303    struct ast_custom_function *acf;
01304    /* Maximum number of characters added by terminal coloring is 22 */
01305    char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40];
01306    char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL;
01307    char stxtitle[40], *syntax = NULL;
01308    int synopsis_size, description_size, syntax_size;
01309 
01310    if (argc < 3)
01311       return RESULT_SHOWUSAGE;
01312 
01313    if (!(acf = ast_custom_function_find(argv[2]))) {
01314       ast_cli(fd, "No function by that name registered.\n");
01315       return RESULT_FAILURE;
01316 
01317    }
01318 
01319    if (acf->synopsis)
01320       synopsis_size = strlen(acf->synopsis) + 23;
01321    else
01322       synopsis_size = strlen("Not available") + 23;
01323    synopsis = alloca(synopsis_size);
01324 
01325    if (acf->desc)
01326       description_size = strlen(acf->desc) + 23;
01327    else
01328       description_size = strlen("Not available") + 23;
01329    description = alloca(description_size);
01330 
01331    if (acf->syntax)
01332       syntax_size = strlen(acf->syntax) + 23;
01333    else
01334       syntax_size = strlen("Not available") + 23;
01335    syntax = alloca(syntax_size);
01336 
01337    snprintf(info, 64 + AST_MAX_APP, "\n  -= Info about function '%s' =- \n\n", acf->name);
01338    term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22);
01339    term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40);
01340    term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
01341    term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
01342    term_color(syntax,
01343          acf->syntax ? acf->syntax : "Not available",
01344          COLOR_CYAN, 0, syntax_size);
01345    term_color(synopsis,
01346          acf->synopsis ? acf->synopsis : "Not available",
01347          COLOR_CYAN, 0, synopsis_size);
01348    term_color(description,
01349          acf->desc ? acf->desc : "Not available",
01350          COLOR_CYAN, 0, description_size);
01351 
01352    ast_cli(fd,"%s%s%s\n\n%s%s\n\n%s%s\n", infotitle, stxtitle, syntax, syntitle, synopsis, destitle, description);
01353 
01354    return RESULT_SUCCESS;
01355 }

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

Definition at line 1273 of file pbx.c.

References ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_custom_function::name, RESULT_SHOWUSAGE, RESULT_SUCCESS, ast_custom_function::synopsis, and ast_custom_function::syntax.

01274 {
01275    struct ast_custom_function *acf;
01276    int count_acf = 0;
01277    int like = 0;
01278 
01279    if (argc == 5 && (!strcmp(argv[3], "like")) ) {
01280       like = 1;
01281    } else if (argc != 3) {
01282       return RESULT_SHOWUSAGE;
01283    }
01284 
01285    ast_cli(fd, "%s Custom Functions:\n--------------------------------------------------------------------------------\n", like ? "Matching" : "Installed");
01286 
01287    AST_LIST_LOCK(&acf_root);
01288    AST_LIST_TRAVERSE(&acf_root, acf, acflist) {
01289       if (!like || strstr(acf->name, argv[4])) {
01290          count_acf++;
01291          ast_cli(fd, "%-20.20s  %-35.35s  %s\n", acf->name, acf->syntax, acf->synopsis);
01292       }
01293    }
01294    AST_LIST_UNLOCK(&acf_root);
01295 
01296    ast_cli(fd, "%d %scustom functions installed.\n", count_acf, like ? "matching " : "");
01297 
01298    return RESULT_SUCCESS;
01299 }

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

Definition at line 1246 of file pbx.c.

References ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_custom_function::name, RESULT_SHOWUSAGE, RESULT_SUCCESS, ast_custom_function::synopsis, and ast_custom_function::syntax.

01247 {
01248    struct ast_custom_function *acf;
01249    int count_acf = 0;
01250    int like = 0;
01251 
01252    if (argc == 4 && (!strcmp(argv[2], "like")) ) {
01253       like = 1;
01254    } else if (argc != 2) {
01255       return RESULT_SHOWUSAGE;
01256    }
01257 
01258    ast_cli(fd, "%s Custom Functions:\n--------------------------------------------------------------------------------\n", like ? "Matching" : "Installed");
01259 
01260    AST_LIST_LOCK(&acf_root);
01261    AST_LIST_TRAVERSE(&acf_root, acf, acflist) {
01262       if (!like || strstr(acf->name, argv[3])) {
01263          count_acf++;
01264          ast_cli(fd, "%-20.20s  %-35.35s  %s\n", acf->name, acf->syntax, acf->synopsis);
01265       }
01266    }
01267    AST_LIST_UNLOCK(&acf_root);
01268 
01269    ast_cli(fd, "%d %scustom functions installed.\n", count_acf, like ? "matching " : "");
01270 
01271    return RESULT_SUCCESS;
01272 }

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

CLI support for listing global variables in a parseable way.

Definition at line 3698 of file pbx.c.

References ast_cli(), AST_LIST_TRAVERSE, ast_mutex_lock(), ast_mutex_unlock(), ast_var_name(), ast_var_value(), and RESULT_SUCCESS.

03699 {
03700    int i = 0;
03701    struct ast_var_t *newvariable;
03702 
03703    ast_mutex_lock(&globalslock);
03704    AST_LIST_TRAVERSE (&globals, newvariable, entries) {
03705       i++;
03706       ast_cli(fd, "   %s=%s\n", ast_var_name(newvariable), ast_var_value(newvariable));
03707    }
03708    ast_mutex_unlock(&globalslock);
03709    ast_cli(fd, "\n    -- %d variables\n", i);
03710 
03711    return RESULT_SUCCESS;
03712 }

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

handle_show_hints: CLI support for listing registered dial plan hints

Definition at line 3232 of file pbx.c.

References ast_cli(), ast_extension_state2str(), ast_get_context_name(), ast_get_extension_app(), ast_get_extension_context(), ast_get_extension_name(), AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_hint::callbacks, ast_hint::exten, ast_hint::laststate, ast_state_cb::next, and RESULT_SUCCESS.

03233 {
03234    struct ast_hint *hint;
03235    int num = 0;
03236    int watchers;
03237    struct ast_state_cb *watcher;
03238 
03239    if (AST_LIST_EMPTY(&hints)) {
03240       ast_cli(fd, "There are no registered dialplan hints\n");
03241       return RESULT_SUCCESS;
03242    }
03243    /* ... we have hints ... */
03244    ast_cli(fd, "\n    -= Registered Asterisk Dial Plan Hints =-\n");
03245    AST_LIST_LOCK(&hints);
03246    AST_LIST_TRAVERSE(&hints, hint, list) {
03247       watchers = 0;
03248       for (watcher = hint->callbacks; watcher; watcher = watcher->next)
03249          watchers++;
03250       ast_cli(fd, "   %20s@%-20.20s: %-20.20s  State:%-15.15s Watchers %2d\n",
03251          ast_get_extension_name(hint->exten),
03252          ast_get_context_name(ast_get_extension_context(hint->exten)),
03253          ast_get_extension_app(hint->exten),
03254          ast_extension_state2str(hint->laststate), watchers);
03255       num++;
03256    }
03257    ast_cli(fd, "----------------\n");
03258    ast_cli(fd, "- %d hints registered\n", num);
03259    AST_LIST_UNLOCK(&hints);
03260    return RESULT_SUCCESS;
03261 }

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

handle_show_switches: CLI support for listing registered dial plan switches

Definition at line 3264 of file pbx.c.

References ast_cli(), AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_switch::description, ast_switch::name, and RESULT_SUCCESS.

03265 {
03266    struct ast_switch *sw;
03267 
03268    AST_LIST_LOCK(&switches);
03269 
03270    if (AST_LIST_EMPTY(&switches)) {
03271       AST_LIST_UNLOCK(&switches);
03272       ast_cli(fd, "There are no registered alternative switches\n");
03273       return RESULT_SUCCESS;
03274    }
03275 
03276    ast_cli(fd, "\n    -= Registered Asterisk Alternative Switches =-\n");
03277    AST_LIST_TRAVERSE(&switches, sw, list)
03278       ast_cli(fd, "%s: %s\n", sw->name, sw->description);
03279 
03280    AST_LIST_UNLOCK(&switches);
03281 
03282    return RESULT_SUCCESS;
03283 }

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

Definition at line 578 of file pbx.c.

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

00579 {
00580    if (!i->hastime)
00581       return 1;
00582 
00583    return ast_check_timing(&(i->timing));
00584 }

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

Definition at line 2554 of file pbx.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), countcalls, getloadavg(), LOG_NOTICE, option_maxcalls, and option_maxload.

Referenced by ast_pbx_run(), and ast_pbx_start().

02555 {
02556    int failed = 0;
02557    double curloadavg;
02558    ast_mutex_lock(&maxcalllock);
02559    if (option_maxcalls) {
02560       if (countcalls >= option_maxcalls) {
02561          ast_log(LOG_NOTICE, "Maximum call limit of %d calls exceeded by '%s'!\n", option_maxcalls, c->name);
02562          failed = -1;
02563       }
02564    }
02565    if (option_maxload) {
02566       getloadavg(&curloadavg, 1);
02567       if (curloadavg >= option_maxload) {
02568          ast_log(LOG_NOTICE, "Maximum loadavg limit of %f load exceeded by '%s' (currently %f)!\n", option_maxload, c->name, curloadavg);
02569          failed = -1;
02570       }
02571    }
02572    if (!failed)
02573       countcalls++;
02574    ast_mutex_unlock(&maxcalllock);
02575 
02576    return failed;
02577 }

int load_pbx ( void   ) 

Provided by pbx.c

Definition at line 6047 of file pbx.c.

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

Referenced by main().

06048 {
06049    int x;
06050 
06051    /* Initialize the PBX */
06052    if (option_verbose) {
06053       ast_verbose( "Asterisk PBX Core Initializing\n");
06054       ast_verbose( "Registering builtin applications:\n");
06055    }
06056    ast_cli_register_multiple(pbx_cli, sizeof(pbx_cli) / sizeof(struct ast_cli_entry));
06057 
06058    /* Register builtin applications */
06059    for (x=0; x<sizeof(builtins) / sizeof(struct pbx_builtin); x++) {
06060       if (option_verbose)
06061          ast_verbose( VERBOSE_PREFIX_1 "[%s]\n", builtins[x].name);
06062       if (ast_register_application(builtins[x].name, builtins[x].execute, builtins[x].synopsis, builtins[x].description)) {
06063          ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name);
06064          return -1;
06065       }
06066    }
06067    return 0;
06068 }

static int lookup_name ( const char *  s,
char *const   names[],
int  max 
) [static]

Helper for get_range. return the index of the matching entry, starting from 1. If names is not supplied, try numeric values.

Definition at line 4034 of file pbx.c.

Referenced by get_range().

04035 {
04036    int i;
04037 
04038    if (names) {
04039       for (i = 0; names[i]; i++) {
04040          if (!strcasecmp(s, names[i]))
04041             return i+1;
04042       }
04043    } else if (sscanf(s, "%d", &i) == 1 && i >= 1 && i <= max) {
04044       return i;
04045    }
04046    return 0; /* error return */
04047 }

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

Definition at line 910 of file pbx.c.

References ast_extension_match(), and ast_strlen_zero().

Referenced by pbx_find_extension().

00911 {
00912    /* If the Caller*ID pattern is empty, then we're matching NO Caller*ID, so
00913       failing to get a number should count as a match, otherwise not */
00914 
00915    if (ast_strlen_zero(callerid))
00916       return ast_strlen_zero(cidpattern) ? 1 : 0;
00917 
00918    return ast_extension_match(cidpattern, callerid);
00919 }

static int parse_variable_name ( char *  var,
int *  offset,
int *  length,
int *  isfunc 
) [static]

extract offset:length from variable name. Returns 1 if there is a offset:length part, which is trimmed off (values go into variables)

Definition at line 1062 of file pbx.c.

Referenced by pbx_retrieve_variable(), and pbx_substitute_variables_helper_full().

01063 {
01064    int parens=0;
01065 
01066    *offset = 0;
01067    *length = INT_MAX;
01068    *isfunc = 0;
01069    for (; *var; var++) {
01070       if (*var == '(') {
01071          (*isfunc)++;
01072          parens++;
01073       } else if (*var == ')') {
01074          parens--;
01075       } else if (*var == ':' && parens == 0) {
01076          *var++ = '\0';
01077          sscanf(var, "%d:%d", offset, length);
01078          return 1; /* offset:length valid */
01079       }
01080    }
01081    return 0;
01082 }

void pbx_builtin_clear_globals ( void   ) 

Definition at line 5949 of file pbx.c.

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

Referenced by handle_reload_extensions(), and reload().

05950 {
05951    struct ast_var_t *vardata;
05952 
05953    ast_mutex_lock(&globalslock);
05954    while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries)))
05955       ast_var_delete(vardata);
05956    ast_mutex_unlock(&globalslock);
05957 }

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

Definition at line 5749 of file pbx.c.

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

Referenced by __login_exec(), _macro_exec(), _while_exec(), agent_hangup(), agent_read(), agentmonitoroutgoing_exec(), ast_bridge_call(), ast_channel_bridge(), ast_feature_interpret(), ast_monitor_stop(), ast_park_call(), builtin_automonitor(), check_goto_on_transfer(), common_exec(), conf_exec(), conf_run(), dundi_exec(), dundi_helper(), get_also_info(), get_index(), get_refer_info(), global_read(), iax2_exec(), import_ch(), leave_voicemail(), local_hangup(), misdn_answer(), misdn_hangup(), morsecode_exec(), notify_new_message(), oh323_call(), oh323_hangup(), pickup_by_mark(), pop_exec(), queue_exec(), real_ctx(), retrydial_exec(), return_exec(), run_agi(), rxfax_exec(), set_config_flags(), sip_addheader(), sla_trunk_exec(), speech_background(), try_calling(), try_suggested_sip_codec(), txfax_exec(), wait_for_answer(), zt_call(), and zt_hangup().

05750 {
05751    struct ast_var_t *variables;
05752    const char *ret = NULL;
05753    int i;
05754    struct varshead *places[2] = { NULL, &globals };
05755 
05756    if (!name)
05757       return NULL;
05758    if (chan)
05759       places[0] = &chan->varshead;
05760 
05761    for (i = 0; i < 2; i++) {
05762       if (!places[i])
05763          continue;
05764       if (places[i] == &globals)
05765          ast_mutex_lock(&globalslock);
05766       AST_LIST_TRAVERSE(places[i], variables, entries) {
05767          if (!strcmp(name, ast_var_name(variables))) {
05768             ret = ast_var_value(variables);
05769             break;
05770          }
05771       }
05772       if (places[i] == &globals)
05773          ast_mutex_unlock(&globalslock);
05774       if (ret)
05775          break;
05776    }
05777 
05778    return ret;
05779 }

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

Definition at line 5969 of file pbx.c.

References ast_log(), ast_strdupa, ast_strlen_zero(), LOG_WARNING, pbx_builtin_goto(), pbx_checkcondition(), and strsep().

05970 {
05971    char *condition, *branch1, *branch2, *branch;
05972    int rc;
05973    char *stringp;
05974 
05975    if (ast_strlen_zero(data)) {
05976       ast_log(LOG_WARNING, "Ignoring, since there is no variable to check\n");
05977       return 0;
05978    }
05979 
05980    stringp = ast_strdupa(data);
05981    condition = strsep(&stringp,"?");
05982    branch1 = strsep(&stringp,":");
05983    branch2 = strsep(&stringp,"");
05984    branch = pbx_checkcondition(condition) ? branch1 : branch2;
05985 
05986    if (ast_strlen_zero(branch)) {
05987       if (option_debug)
05988          ast_log(LOG_DEBUG, "Not taking any branch\n");
05989       return 0;
05990    }
05991 
05992    rc = pbx_builtin_goto(chan, branch);
05993 
05994    return rc;
05995 }

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

Definition at line 5888 of file pbx.c.

References ast_channel_unlock, ast_get_channel_by_name_locked(), ast_log(), ast_strdupa, ast_strlen_zero(), LOG_WARNING, pbx_builtin_setvar_helper(), pbx_substitute_variables_helper(), s, strsep(), and VAR_BUF_SIZE.

05889 {
05890    char *name;
05891    char *value;
05892    char *channel;
05893    char tmp[VAR_BUF_SIZE]="";
05894 
05895    if (ast_strlen_zero(data)) {
05896       ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n");
05897       return 0;
05898    }
05899 
05900    value = ast_strdupa(data);
05901    name = strsep(&value,"=");
05902    channel = strsep(&value,"|");
05903    if (channel && value && name) { /*! \todo XXX should do !ast_strlen_zero(..) of the args ? */
05904       struct ast_channel *chan2 = ast_get_channel_by_name_locked(channel);
05905       if (chan2) {
05906          char *s = alloca(strlen(value) + 4);
05907          if (s) {
05908             sprintf(s, "${%s}", value);
05909             pbx_substitute_variables_helper(chan2, s, tmp, sizeof(tmp) - 1);
05910          }
05911          ast_channel_unlock(chan2);
05912       }
05913       pbx_builtin_setvar_helper(chan, name, tmp);
05914    }
05915 
05916    return(0);
05917 }

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

Definition at line 5944 of file pbx.c.

05945 {
05946    return 0;
05947 }

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

Definition at line 5781 of file pbx.c.

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

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

05782 {
05783    struct ast_var_t *newvariable;
05784    struct varshead *headp;
05785 
05786    if (name[strlen(name)-1] == ')') {
05787       char *function = ast_strdupa(name);
05788 
05789       ast_log(LOG_WARNING, "Cannot push a value onto a function\n");
05790       ast_func_write(chan, function, value);
05791       return;
05792    }
05793 
05794    headp = (chan) ? &chan->varshead : &globals;
05795 
05796    if (value) {
05797       if ((option_verbose > 1) && (headp == &globals))
05798          ast_verbose(VERBOSE_PREFIX_2 "Setting global variable '%s' to '%s'\n", name, value);
05799       newvariable = ast_var_assign(name, value);
05800       if (headp == &globals)
05801          ast_mutex_lock(&globalslock);
05802       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
05803       if (headp == &globals)
05804          ast_mutex_unlock(&globalslock);
05805    }
05806 }

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

Definition at line 6029 of file pbx.c.

References ast_say_character_str().

06030 {
06031    int res = 0;
06032 
06033    if (data)
06034       res = ast_say_character_str(chan, data, "", chan->language);
06035    return res;
06036 }

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

Definition at line 6020 of file pbx.c.

References ast_say_digit_str().

06021 {
06022    int res = 0;
06023 
06024    if (data)
06025       res = ast_say_digit_str(chan, data, "", chan->language);
06026    return res;
06027 }

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

Definition at line 5997 of file pbx.c.

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

05998 {
05999    char tmp[256];
06000    char *number = tmp;
06001    char *options;
06002 
06003    if (ast_strlen_zero(data)) {
06004       ast_log(LOG_WARNING, "SayNumber requires an argument (number)\n");
06005       return -1;
06006    }
06007    ast_copy_string(tmp, data, sizeof(tmp));
06008    strsep(&number, "|");
06009    options = strsep(&number, "|");
06010    if (options) {
06011       if ( strcasecmp(options, "f") && strcasecmp(options,"m") &&
06012          strcasecmp(options, "c") && strcasecmp(options, "n") ) {
06013          ast_log(LOG_WARNING, "SayNumber gender option is either 'f', 'm', 'c' or 'n'\n");
06014          return -1;
06015       }
06016    }
06017    return ast_say_number(chan, atoi(tmp), "", chan->language, options);
06018 }

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

Definition at line 6038 of file pbx.c.

References ast_say_phonetic_str().

06039 {
06040    int res = 0;
06041 
06042    if (data)
06043       res = ast_say_phonetic_str(chan, data, "", chan->language);
06044    return res;
06045 }

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

Definition at line 5722 of file pbx.c.

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

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

05723 {
05724    struct ast_var_t *variables;
05725    const char *var, *val;
05726    int total = 0;
05727 
05728    if (!chan)
05729       return 0;
05730 
05731    memset(buf, 0, size);
05732 
05733    AST_LIST_TRAVERSE(&chan->varshead, variables, entries) {
05734       if ((var=ast_var_name(variables)) && (val=ast_var_value(variables))
05735          /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */
05736          ) {
05737          if (ast_build_string(&buf, &size, "%s=%s\n", var, val)) {
05738             ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
05739             break;
05740          } else
05741             total++;
05742       } else
05743          break;
05744    }
05745 
05746    return total;
05747 }

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

Todo:
XXX overwrites data ?

Todo:
XXX watch out, leading whitespace ?

Definition at line 5920 of file pbx.c.

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

05921 {
05922    char *name;
05923    char *stringp = data;
05924    static int dep_warning = 0;
05925 
05926    if (ast_strlen_zero(data)) {
05927       ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n");
05928       return 0;
05929    }
05930 
05931    name = strsep(&stringp, "=");
05932 
05933    if (!dep_warning) {
05934       dep_warning = 1;
05935       ast_log(LOG_WARNING, "SetGlobalVar is deprecated.  Please use Set(GLOBAL(%s)=%s) instead.\n", name, stringp);
05936    }
05937 
05938    /*! \todo XXX watch out, leading whitespace ? */
05939    pbx_builtin_setvar_helper(NULL, name, stringp);
05940 
05941    return(0);
05942 }

int pbx_builtin_setvar ( struct ast_channel ,
void *   
)

Definition at line 5853 of file pbx.c.

References ast_app_separate_args(), ast_log(), ast_strdupa, ast_strlen_zero(), LOG_WARNING, and pbx_builtin_setvar_helper().

Referenced by ast_compile_ael2().

05854 {
05855    char *name, *value, *mydata;
05856    int argc;
05857    char *argv[24];      /* this will only support a maximum of 24 variables being set in a single operation */
05858    int global = 0;
05859    int x;
05860 
05861    if (ast_strlen_zero(data)) {
05862       ast_log(LOG_WARNING, "Set requires at least one variable name/value pair.\n");
05863       return 0;
05864    }
05865 
05866    mydata = ast_strdupa(data);
05867    argc = ast_app_separate_args(mydata, '|', argv, sizeof(argv) / sizeof(argv[0]));
05868 
05869    /* check for a trailing flags argument */
05870    if ((argc > 1) && !strchr(argv[argc-1], '=')) {
05871       argc--;
05872       if (strchr(argv[argc], 'g'))
05873          global = 1;
05874    }
05875 
05876    for (x = 0; x < argc; x++) {
05877       name = argv[x];
05878       if ((value = strchr(name, '='))) {
05879          *value++ = '\0';
05880          pbx_builtin_setvar_helper((global) ? NULL : chan, name, value);
05881       } else
05882          ast_log(LOG_WARNING, "Ignoring entry '%s' with no = (and not last 'options' entry)\n", name);
05883    }
05884 
05885    return(0);
05886 }

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

Definition at line 5808 of file pbx.c.

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

Referenced by __oh323_new(), _macro_exec(), _while_exec(), acf_odbc_read(), acf_odbc_write(), action_setvar(), agi_exec_full(), aji_status_exec(), aMYSQL_fetch(), app_exec(), aqm_exec(), array(), ast_bridge_call(), ast_channel_bridge(), ast_feature_request_and_dial(), ast_iax2_new(), ast_monitor_start(), ast_set_variables(), background_detect_exec(), builtin_automonitor(), builtin_blindtransfer(), cb_events(), chanavail_exec(), controlplayback_exec(), count_exec(), disa_exec(), do_waiting(), export_aoc_vars(), export_ch(), function_db_delete(), function_db_exists(), function_db_read(), global_write(), handle_request_bye(), handle_request_refer(), handle_set_global(), handle_set_global_deprecated(), handle_setvariable(), hasvoicemail_exec(), isAnsweringMachine(), leave_voicemail(), local_hangup(), lookupblacklist_exec(), misdn_call(), mixmonitor_exec(), mwanalyze_exec(), MYSQL_exec(), nv_background_detect_exec(), nv_detectfax_exec(), ospauth_exec(), ospfinished_exec(), osplookup_exec(), ospnext_exec(), park_exec(), parse_moved_contact(), pbx_builtin_importvar(), pbx_builtin_setglobalvar(), pbx_builtin_setvar(), pbx_extension_helper(), pbx_load_config(), phase_e_handler(), play_message_datetime(), playback_exec(), pop_exec(), pqm_exec(), prep_email_sub_vars(), privacy_exec(), process_ast_dsp(), read_exec(), readfile_exec(), realtime_exec(), realtime_update_exec(), record_exec(), return_exec(), rqm_exec(), sendimage_exec(), sendtext_exec(), sendurl_exec(), set(), set_agentbycallerid(), set_asterisk_int(), set_queue_result(), sip_addheader(), sip_hangup(), sip_new(), sla_calc_trunk_timeouts(), sla_station_exec(), sla_trunk_exec(), socket_process(), speech_create(), ss_thread(), start_monitor_exec(), system_exec_helper(), transfer_exec(), try_calling(), tryexec_exec(), upqm_exec(), vm_box_exists(), vm_exec(), vmauthenticate(), zt_handle_dtmfup(), and zt_new().

05809 {
05810    struct ast_var_t *newvariable;
05811    struct varshead *headp;
05812    const char *nametail = name;
05813 
05814    /* XXX may need locking on the channel ? */
05815    if (name[strlen(name)-1] == ')') {
05816       char *function = ast_strdupa(name);
05817 
05818       ast_func_write(chan, function, value);
05819       return;
05820    }
05821 
05822    headp = (chan) ? &chan->varshead : &globals;
05823 
05824    /* For comparison purposes, we have to strip leading underscores */
05825    if (*nametail == '_') {
05826       nametail++;
05827       if (*nametail == '_')
05828          nametail++;
05829    }
05830 
05831    if (headp == &globals)
05832       ast_mutex_lock(&globalslock);
05833    AST_LIST_TRAVERSE (headp, newvariable, entries) {
05834       if (strcasecmp(ast_var_name(newvariable), nametail) == 0) {
05835          /* there is already such a variable, delete it */
05836          AST_LIST_REMOVE(headp, newvariable, entries);
05837          ast_var_delete(newvariable);
05838          break;
05839       }
05840    }
05841 
05842    if (value) {
05843       if ((option_verbose > 1) && (headp == &globals))
05844          ast_verbose(VERBOSE_PREFIX_2 "Setting global variable '%s' to '%s'\n", name, value);
05845       newvariable = ast_var_assign(name, value);
05846       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
05847    }
05848 
05849    if (headp == &globals)
05850       ast_mutex_unlock(&globalslock);
05851 }

int pbx_checkcondition ( const char *  condition  ) 

Evaluate a condition.

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

References ast_strlen_zero().

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

05960 {
05961    if (ast_strlen_zero(condition))  /* NULL or empty strings are false */
05962       return 0;
05963    else if (*condition >= '0' && *condition <= '9')   /* Numbers are evaluated for truth */
05964       return atoi(condition);
05965    else  /* Strings are true */
05966       return 1;
05967 }

static void pbx_destroy ( struct ast_pbx p  )  [static]

Definition at line 586 of file pbx.c.

References free.

00587 {
00588    free(p);
00589 }

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

References app, ast_channel::appl, ast_cdr_setapp(), ast_check_hangup(), ast_channel::cdr, and ast_channel::data.

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

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

static int pbx_extension_helper ( struct ast_channel c,
struct ast_context con,
const char *  context,
const char *  exten,
int  priority,
const char *  label,
const char *  callerid,
enum ext_match_t  action 
) [static]

The return value depends on the action:.

E_MATCH, E_CANMATCH, E_MATCHMORE require a real match, and return 0 on failure, -1 on match; E_FINDLABEL maps the label to a priority, and returns the priority on success, ... XXX E_SPAWN, spawn an application, and return 0 on success, -1 on failure.

Definition at line 1777 of file pbx.c.

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

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

01780 {
01781    struct ast_exten *e;
01782    struct ast_app *app;
01783    int res;
01784    struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */
01785    char passdata[EXT_DATA_SIZE];
01786 
01787    int matching_action = (action == E_MATCH || action == E_CANMATCH || action == E_MATCHMORE);
01788 
01789    ast_mutex_lock(&conlock);
01790    e = pbx_find_extension(c, con, &q, context, exten, priority, label, callerid, action);
01791    if (e) {
01792       if (matching_action) {
01793          ast_mutex_unlock(&conlock);
01794          return -1;  /* success, we found it */
01795       } else if (action == E_FINDLABEL) { /* map the label to a priority */
01796          res = e->priority;
01797          ast_mutex_unlock(&conlock);
01798          return res; /* the priority we were looking for */
01799       } else { /* spawn */
01800          app = pbx_findapp(e->app);
01801          ast_mutex_unlock(&conlock);
01802          if (!app) {
01803             ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority);
01804             return -1;
01805          }
01806          if (c->context != context)
01807             ast_copy_string(c->context, context, sizeof(c->context));
01808          if (c->exten != exten)
01809             ast_copy_string(c->exten, exten, sizeof(c->exten));
01810          c->priority = priority;
01811          pbx_substitute_variables(passdata, sizeof(passdata), c, e);
01812          if (option_debug) {
01813             char atmp[80];
01814             char atmp2[EXT_DATA_SIZE+100];
01815             ast_log(LOG_DEBUG, "Launching '%s'\n", app->name);
01816             snprintf(atmp, sizeof(atmp), "STACK-%s-%s-%d", context, exten, priority);
01817             snprintf(atmp2, sizeof(atmp2), "%s(\"%s\", \"%s\") %s",
01818                app->name, c->name, passdata, "in new stack");
01819             pbx_builtin_setvar_helper(c, atmp, atmp2);
01820          }
01821          if (option_verbose > 2) {
01822             char tmp[80], tmp2[80], tmp3[EXT_DATA_SIZE];
01823             ast_verbose( VERBOSE_PREFIX_3 "Executing [%s@%s:%d] %s(\"%s\", \"%s\") %s\n",
01824                exten, context, priority,
01825                term_color(tmp, app->name, COLOR_BRCYAN, 0, sizeof(tmp)),
01826                term_color(tmp2, c->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)),
01827                term_color(tmp3, passdata, COLOR_BRMAGENTA, 0, sizeof(tmp3)),
01828                "in new stack");
01829          }
01830          manager_event(EVENT_FLAG_CALL, "Newexten",
01831                "Channel: %s\r\n"
01832                "Context: %s\r\n"
01833                "Extension: %s\r\n"
01834                "Priority: %d\r\n"
01835                "Application: %s\r\n"
01836                "AppData: %s\r\n"
01837                "Uniqueid: %s\r\n",
01838                c->name, c->context, c->exten, c->priority, app->name, passdata, c->uniqueid);
01839          return pbx_exec(c, app, passdata);  /* 0 on success, -1 on failure */
01840       }
01841    } else if (q.swo) {  /* not found here, but in another switch */
01842       ast_mutex_unlock(&conlock);
01843       if (matching_action)
01844          return -1;
01845       else {
01846          if (!q.swo->exec) {
01847             ast_log(LOG_WARNING, "No execution engine for switch %s\n", q.swo->name);
01848             res = -1;
01849          }
01850          return q.swo->exec(c, q.foundcontext ? q.foundcontext : context, exten, priority, callerid, q.data);
01851       }
01852    } else { /* not found anywhere, see what happened */
01853       ast_mutex_unlock(&conlock);
01854       switch (q.status) {
01855       case STATUS_NO_CONTEXT:
01856          if (!matching_action)
01857             ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", context);
01858          break;
01859       case STATUS_NO_EXTENSION:
01860          if (!matching_action)
01861             ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, context);
01862          break;
01863       case STATUS_NO_PRIORITY:
01864          if (!matching_action)
01865             ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, context);
01866          break;
01867       case STATUS_NO_LABEL:
01868          if (context)
01869             ast_log(LOG_NOTICE, "No such label '%s' in extension '%s' in context '%s'\n", label, exten, context);
01870          break;
01871       default:
01872          if (option_debug)
01873             ast_log(LOG_DEBUG, "Shouldn't happen!\n");
01874       }
01875 
01876       return (matching_action) ? 0 : -1;
01877    }
01878 }

static struct ast_exten* pbx_find_extension ( struct ast_channel chan,
struct ast_context bypass,
struct pbx_find_info q,
const char *  context,
const char *  exten,
int  priority,
const char *  label,
const char *  callerid,
enum ext_match_t  action 
) [static]

Definition at line 937 of file pbx.c.

References ast_log(), AST_PBX_MAX_STACK, ast_walk_context_extensions(), ast_walk_contexts(), ast_walk_extension_priorities(), ast_exten::cidmatch, pbx_find_info::data, E_FINDLABEL, E_MATCHMORE, ast_exten::exten, extension_match_core(), pbx_find_info::foundcontext, pbx_find_info::incstack, ast_exten::label, LOG_WARNING, match(), matchcid(), ast_exten::matchcid, ast_exten::priority, pbx_find_info::stacklen, pbx_find_info::status, STATUS_NO_CONTEXT, STATUS_NO_EXTENSION, STATUS_NO_LABEL, STATUS_NO_PRIORITY, STATUS_SUCCESS, and pbx_find_info::swo.

Referenced by ast_hint_extension(), and pbx_extension_helper().

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

struct ast_app* pbx_findapp ( const char *  app  ) 

Look up an application.

Parameters:
app name of the app
This function searches for the ast_app structure within the apps that are registered for the one with the name you passed in.

Returns:
the ast_app structure that matches on success, or NULL on failure

Definition at line 550 of file pbx.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, and AST_LIST_UNLOCK.

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

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

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

Definition at line 564 of file pbx.c.

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

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

void pbx_retrieve_variable ( struct ast_channel c,
const char *  var,
char **  ret,
char *  workspace,
int  workspacelen,
struct varshead *  headp 
)

Support for Asterisk built-in variables and functions in the dialplan.

Note:
See also

Definition at line 1134 of file pbx.c.

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

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

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

int pbx_set_autofallthrough ( int  newval  ) 

Set "autofallthrough" flag, if newval is <0, does not acutally set. If set to 1, sets to auto fall through. If newval set to 0, sets to no auto fall through (reads extension instead). Returns previous value.

Definition at line 2661 of file pbx.c.

References autofallthrough.

Referenced by pbx_load_module().

02662 {
02663    int oldval = autofallthrough;
02664    autofallthrough = newval;
02665    return oldval;
02666 }

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

Definition at line 1755 of file pbx.c.

References ast_exten::data, and pbx_substitute_variables_helper().

Referenced by pbx_extension_helper().

01756 {
01757    memset(passdata, 0, datalen);
01758 
01759    /* No variables or expressions in e->data, so why scan it? */
01760    if (e->data && !strchr(e->data, '$') && !strstr(e->data,"${") && !strstr(e->data,"$[") && !strstr(e->data,"$(")) {
01761       ast_copy_string(passdata, e->data, datalen);
01762       return;
01763    }
01764 
01765    pbx_substitute_variables_helper(c, e->data, passdata, datalen - 1);
01766 }

void pbx_substitute_variables_helper ( struct ast_channel c,
const char *  cp1,
char *  cp2,
int  count 
)

Definition at line 1745 of file pbx.c.

References pbx_substitute_variables_helper_full(), and ast_channel::varshead.

Referenced by _macro_exec(), acf_odbc_read(), acf_odbc_write(), add_extensions(), custom_log(), cut_internal(), exec_exec(), function_eval(), handle_getvariablefull(), launch_monitor_thread(), make_email_file(), pbx_builtin_importvar(), pbx_load_config(), pbx_substitute_variables(), realtime_exec(), rpt_do_lstats(), sendpage(), try_calling(), and tryexec_exec().

01746 {
01747    pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count);
01748 }

static void pbx_substitute_variables_helper_full ( struct ast_channel c,
struct varshead *  headp,
const char *  cp1,
char *  cp2,
int  count 
) [static]

Definition at line 1552 of file pbx.c.

References ast_channel_alloc(), ast_channel_free(), ast_expr(), ast_func_read(), ast_log(), ast_strlen_zero(), len, LOG_DEBUG, LOG_ERROR, LOG_NOTICE, offset, option_debug, parse_variable_name(), pbx_retrieve_variable(), substring(), var, VAR_BUF_SIZE, and ast_channel::varshead.

Referenced by pbx_substitute_variables_helper(), and pbx_substitute_variables_varshead().

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

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

Definition at line 1750 of file pbx.c.

References pbx_substitute_variables_helper_full().

Referenced by ast_add_extension2(), dundi_lookup_local(), and loopback_helper().

01751 {
01752    pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count);
01753 }

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

Definition at line 2597 of file pbx.c.

References __ast_pbx_run(), and decrease_call_count().

Referenced by ast_pbx_start().

02598 {
02599    /* Oh joyeous kernel, we're a new thread, with nothing to do but
02600       answer this channel and get it going.
02601    */
02602    /* NOTE:
02603       The launcher of this function _MUST_ increment 'countcalls'
02604       before invoking the function; it will be decremented when the
02605       PBX has finished running on the channel
02606     */
02607    struct ast_channel *c = data;
02608 
02609    __ast_pbx_run(c);
02610    decrease_call_count();
02611 
02612    pthread_exit(NULL);
02613 
02614    return NULL;
02615 }

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

helper function to print an extension

Definition at line 3480 of file pbx.c.

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

Referenced by show_dialplan_helper().

03481 {
03482    int prio = ast_get_extension_priority(e);
03483    if (prio == PRIORITY_HINT) {
03484       snprintf(buf, buflen, "hint: %s",
03485          ast_get_extension_app(e));
03486    } else {
03487       snprintf(buf, buflen, "%d. %s(%s)",
03488          prio, ast_get_extension_app(e),
03489          (char *)ast_get_extension_app_data(e));
03490    }
03491 }

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

Definition at line 2298 of file pbx.c.

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

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

02299 {
02300    ast_copy_string(c->exten, exten, sizeof(c->exten));
02301    c->priority = pri;
02302 }

static int show_dialplan_helper ( int  fd,
const char *  context,
const char *  exten,
struct dialplan_counters dpc,
struct ast_include rinclude,
int  includecount,
const char *  includes[] 
) [static]

Definition at line 3494 of file pbx.c.

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

Referenced by handle_show_dialplan().

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

static char* substring ( const char *  value,
int  offset,
int  length,
char *  workspace,
size_t  workspace_len 
) [static]

takes a substring. It is ok to call with value == workspace.

offset < 0 means start from the end of the string and set the beginning to be that many characters back. length is the length of the substring. A value less than 0 means to leave that many off the end. Always return a copy in workspace.

Definition at line 1092 of file pbx.c.

Referenced by pbx_retrieve_variable(), and pbx_substitute_variables_helper_full().

01093 {
01094    char *ret = workspace;
01095    int lr;  /* length of the input string after the copy */
01096 
01097    ast_copy_string(workspace, value, workspace_len); /* always make a copy */
01098 
01099    lr = strlen(ret); /* compute length after copy, so we never go out of the workspace */
01100 
01101    /* Quick check if no need to do anything */
01102    if (offset == 0 && length >= lr) /* take the whole string */
01103       return ret;
01104 
01105    if (offset < 0)   {  /* translate negative offset into positive ones */
01106       offset = lr + offset;
01107       if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */
01108          offset = 0;
01109    }
01110 
01111    /* too large offset result in empty string so we know what to return */
01112    if (offset >= lr)
01113       return ret + lr;  /* the final '\0' */
01114 
01115    ret += offset;    /* move to the start position */
01116    if (length >= 0 && length < lr - offset)  /* truncate if necessary */
01117       ret[length] = '\0';
01118    else if (length < 0) {
01119       if (lr > offset - length) /* After we remove from the front and from the rear, is there anything left? */
01120          ret[lr + length - offset] = '\0';
01121       else
01122          ret[0] = '\0';
01123    }
01124 
01125    return ret;
01126 }

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

Definition at line 5331 of file pbx.c.

References ast_frfree(), ast_read(), ast_safe_sleep(), ast_strlen_zero(), ast_waitfor(), and f.

Referenced by pbx_builtin_busy(), and pbx_builtin_congestion().

05332 {
05333    int res;
05334    struct ast_frame *f;
05335    int waittime;
05336 
05337    if (ast_strlen_zero(data) || (sscanf(data, "%d", &waittime) != 1) || (waittime < 0))
05338       waittime = -1;
05339    if (waittime > -1) {
05340       ast_safe_sleep(chan, waittime * 1000);
05341    } else do {
05342       res = ast_waitfor(chan, -1);
05343       if (res < 0)
05344          return;
05345       f = ast_read(chan);
05346       if (f)
05347          ast_frfree(f);
05348    } while(f);
05349 }


Variable Documentation

int autofallthrough = 1 [static]

Definition at line 245 of file pbx.c.

Referenced by pbx_set_autofallthrough().

struct pbx_builtin builtins[] [static]

Declaration of builtin applications.

struct ast_cli_entry cli_set_global_deprecated [static]

Initial value:

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

Definition at line 3783 of file pbx.c.

struct ast_cli_entry cli_show_application_deprecated [static]

Initial value:

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

Definition at line 3773 of file pbx.c.

struct ast_cli_entry cli_show_applications_deprecated [static]

Initial value:

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

Definition at line 3743 of file pbx.c.

struct ast_cli_entry cli_show_dialplan_deprecated [static]

Initial value:

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

Definition at line 3778 of file pbx.c.

struct ast_cli_entry cli_show_function_deprecated [static]

Initial value:

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

Definition at line 3768 of file pbx.c.

struct ast_cli_entry cli_show_functions_deprecated [static]

Initial value:

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

Definition at line 3748 of file pbx.c.

struct ast_cli_entry cli_show_globals_deprecated [static]

Initial value:

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

Definition at line 3763 of file pbx.c.

struct ast_cli_entry cli_show_hints_deprecated [static]

Initial value:

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

Definition at line 3758 of file pbx.c.

struct ast_cli_entry cli_show_switches_deprecated [static]

Initial value:

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

Definition at line 3753 of file pbx.c.

struct ast_context* contexts [static]

Definition at line 492 of file pbx.c.

Referenced by __ast_context_create(), __ast_context_destroy(), ast_merge_contexts_and_delete(), and ast_walk_contexts().

int countcalls [static]

Definition at line 248 of file pbx.c.

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

char* days[] [static]

Definition at line 4183 of file pbx.c.

Referenced by ast_build_timing(), and timesub().

struct cfextension_states extension_states[] [static]

Referenced by ast_extension_state2str().

struct varshead globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE [static]

Definition at line 243 of file pbx.c.

char* months[] [static]

Definition at line 4195 of file pbx.c.

Referenced by ast_build_timing().

struct ast_cli_entry pbx_cli[] [static]

Definition at line 3788 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 3057 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 3045 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 3023 of file pbx.c.

char show_dialplan_help[] [static]

Initial value:

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

Definition at line 3053 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 3049 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 3029 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 3041 of file pbx.c.

char show_hints_help[] [static]

Initial value:

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

Definition at line 3037 of file pbx.c.

char show_switches_help[] [static]

Initial value:

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

Definition at line 3033 of file pbx.c.

struct ast_state_cb* statecbs

Definition at line 507 of file pbx.c.

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

int stateid = 1 [static]

Definition at line 499 of file pbx.c.


Generated on Fri Aug 24 02:27:06 2007 for Asterisk - the Open Source PBX by  doxygen 1.5.1