Mon May 14 04:51:57 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 3844 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().

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

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

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

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

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

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

06270 {
06271    int (*goto_func)(struct ast_channel *chan, const char *context, const char *exten, int priority);
06272 
06273    if (!chan)
06274       return -2;
06275 
06276    if (context == NULL)
06277       context = chan->context;
06278    if (exten == NULL)
06279       exten = chan->exten;
06280 
06281    goto_func = (async) ? ast_async_goto : ast_explicit_goto;
06282    if (ast_exists_extension(chan, context, exten, priority, chan->cid.cid_num))
06283       return goto_func(chan, context, exten, priority);
06284    else
06285       return -3;
06286 }

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) && ast_exists_extension(c, c->context, "h", 1, c->cid.cid_num)) {
02527       if (c->cdr && ast_opt_end_cdr_before_h_exten)
02528          ast_cdr_end(c->cdr);
02529       set_ext_pri(c, "h", 1);
02530       while(ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) {
02531          if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num))) {
02532             /* Something bad happened, or a hangup has been requested. */
02533             if (option_debug)
02534                ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
02535             if (option_verbose > 1)
02536                ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
02537             break;
02538          }
02539          c->priority++;
02540       }
02541    }
02542    ast_set2_flag(c, autoloopflag, AST_FLAG_IN_AUTOLOOP);
02543 
02544    pbx_destroy(c->pbx);
02545    c->pbx = NULL;
02546    if (res != AST_PBX_KEEPALIVE)
02547       ast_hangup(c);
02548    return 0;
02549 }

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

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

int ast_active_calls ( void   ) 

Retrieve the number of active calls.

Definition at line 2654 of file pbx.c.

References countcalls.

Referenced by handle_chanlist(), and handle_chanlist_deprecated().

02655 {
02656    return countcalls;
02657 }

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

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

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

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

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

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

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

Definition at line 4614 of file pbx.c.

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

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

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

Definition at line 6293 of file pbx.c.

References __ast_goto_if_exists().

Referenced by asyncgoto_exec().

06294 {
06295    return __ast_goto_if_exists(chan, context, exten, priority, 1);
06296 }

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

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

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

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

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

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

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

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

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

Definition at line 4482 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_compile_ael2(), ast_context_add_ignorepat(), and pbx_load_config().

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

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

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

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 4278 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_compile_ael2(), ast_context_add_include(), and pbx_load_config().

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

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

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

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

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 4359 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_compile_ael2(), ast_context_add_switch(), and pbx_load_config().

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

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

References __ast_context_create().

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

03888 {
03889    return __ast_context_create(extcontexts, name, registrar, 0);
03890 }

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

References __ast_context_destroy().

Referenced by cleanup_stale_contexts(), and unload_module().

05339 {
05340    __ast_context_destroy(con,registrar);
05341 }

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

References __ast_context_create().

Referenced by pbx_load_config(), and pbx_load_users().

03893 {
03894    return __ast_context_create(extcontexts, name, registrar, 1);
03895 }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

06255 {
06256    struct ast_include *inc = NULL;
06257    int res = 0;
06258 
06259    while ( (inc = ast_walk_context_includes(con, inc)) )
06260       if (!ast_context_find(inc->rname)) {
06261          res = -1;
06262          ast_log(LOG_WARNING, "Context '%s' tries includes nonexistent context '%s'\n",
06263                ast_get_context_name(con), inc->rname);
06264       }
06265    return res;
06266 }

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(), 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 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(), rpt_exec(), 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 4549 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().

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

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

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

06112 {
06113    return con ? con->name : NULL;
06114 }

const char* ast_get_context_registrar ( struct ast_context c  ) 

Definition at line 6149 of file pbx.c.

References ast_context::registrar.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06150 {
06151    return c ? c->registrar : NULL;
06152 }

const char* ast_get_extension_app ( struct ast_exten e  ) 

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

06180 {
06181    return e ? e->app : NULL;
06182 }

void* ast_get_extension_app_data ( struct ast_exten e  ) 

Definition at line 6184 of file pbx.c.

References ast_exten::data.

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

06185 {
06186    return e ? e->data : NULL;
06187 }

const char* ast_get_extension_cidmatch ( struct ast_exten e  ) 

Definition at line 6174 of file pbx.c.

References ast_exten::cidmatch.

Referenced by find_matching_priority(), and handle_save_dialplan().

06175 {
06176    return e ? e->cidmatch : NULL;
06177 }

struct ast_context* ast_get_extension_context ( struct ast_exten exten  ) 

Definition at line 6116 of file pbx.c.

References exten.

Referenced by handle_show_hints().

06117 {
06118    return exten ? exten->parent : NULL;
06119 }

const char* ast_get_extension_label ( struct ast_exten exten  ) 

Definition at line 6126 of file pbx.c.

References exten.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06127 {
06128    return exten ? exten->label : NULL;
06129 }

int ast_get_extension_matchcid ( struct ast_exten e  ) 

Definition at line 6169 of file pbx.c.

References ast_exten::matchcid.

Referenced by find_matching_priority(), and handle_save_dialplan().

06170 {
06171    return e ? e->matchcid : 0;
06172 }

const char* ast_get_extension_name ( struct ast_exten exten  ) 

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

06122 {
06123    return exten ? exten->exten : NULL;
06124 }

int ast_get_extension_priority ( struct ast_exten exten  ) 

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

06142 {
06143    return exten ? exten->priority : -1;
06144 }

const char* ast_get_extension_registrar ( struct ast_exten e  ) 

Definition at line 6154 of file pbx.c.

References ast_exten::registrar.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06155 {
06156    return e ? e->registrar : NULL;
06157 }

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

06137 {
06138    return ip ? ip->pattern : NULL;
06139 }

const char* ast_get_ignorepat_registrar ( struct ast_ignorepat ip  ) 

Definition at line 6164 of file pbx.c.

References ast_ignorepat::registrar.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06165 {
06166    return ip ? ip->registrar : NULL;
06167 }

const char* ast_get_include_name ( struct ast_include inc  ) 

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

06132 {
06133    return inc ? inc->name : NULL;
06134 }

const char* ast_get_include_registrar ( struct ast_include i  ) 

Definition at line 6159 of file pbx.c.

References ast_include::registrar.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06160 {
06161    return i ? i->registrar : NULL;
06162 }

const char* ast_get_switch_data ( struct ast_sw sw  ) 

Definition at line 6194 of file pbx.c.

References ast_sw::data.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06195 {
06196    return sw ? sw->data : NULL;
06197 }

const char* ast_get_switch_name ( struct ast_sw sw  ) 

Definition at line 6189 of file pbx.c.

References ast_sw::name.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06190 {
06191    return sw ? sw->name : NULL;
06192 }

const char* ast_get_switch_registrar ( struct ast_sw sw  ) 

Definition at line 6199 of file pbx.c.

References ast_sw::registrar.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06200 {
06201    return sw ? sw->registrar : NULL;
06202 }

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

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

06289 {
06290    return __ast_goto_if_exists(chan, context, exten, priority, 0);
06291 }

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 4515 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_soft_key_event_message(), handle_stimulus_message(), mgcp_ss(), skinny_ss(), and ss_thread().

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

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

06099 {
06100    return ast_mutex_lock(&con->lock);
06101 }

int ast_lock_contexts ( void   ) 

Locks the context list.

Return values:
0 on success
-1 on error

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

06086 {
06087    return ast_mutex_lock(&conlock);
06088 }

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

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

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

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

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

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

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

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

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

References __ast_request_and_dial(), ast_channel::_state, ast_calloc, ast_cdr_alloc(), ast_cdr_disposition(), ast_cdr_failed(), ast_cdr_init(), ast_cdr_setaccount(), ast_cdr_start(), 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, ast_channel::pbx, set_ext_pri(), outgoing_helper::vars, and VERBOSE_PREFIX_4.

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

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

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

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

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

run the application and free the descriptor once done

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

05119 {
05120    struct app_tmp *tmp = data;
05121    struct ast_app *app;
05122    app = pbx_findapp(tmp->app);
05123    if (app) {
05124       if (option_verbose > 3)
05125          ast_verbose(VERBOSE_PREFIX_4 "Launching %s(%s) on %s\n", tmp->app, tmp->data, tmp->chan->name);
05126       pbx_exec(tmp->chan, app, tmp->data);
05127    } else
05128       ast_log(LOG_WARNING, "No such application '%s'\n", tmp->app);
05129    ast_hangup(tmp->chan);
05130    free(tmp);
05131    return NULL;
05132 }

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

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

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

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

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

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

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

06104 {
06105    return ast_mutex_unlock(&con->lock);
06106 }

int ast_unlock_contexts ( void   ) 

Unlocks contexts.

Return values:
0 on success
-1 on failure

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

06091 {
06092    return ast_mutex_unlock(&conlock);
06093 }

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

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

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

References AST_LIST_LOCK, AST_LIST_REMOVE, and AST_LIST_UNLOCK.

Referenced by __unload_module(), and unload_module().

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

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

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

06214 {
06215    if (!exten)
06216       return con ? con->root : NULL;
06217    else
06218       return exten->next;
06219 }

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

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

06247 {
06248    if (!ip)
06249       return con ? con->ignorepats : NULL;
06250    else
06251       return ip->next;
06252 }

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

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

06238 {
06239    if (!inc)
06240       return con ? con->includes : NULL;
06241    else
06242       return inc->next;
06243 }

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

Definition at line 6221 of file pbx.c.

References AST_LIST_FIRST, and AST_LIST_NEXT.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06223 {
06224    if (!sw)
06225       return con ? AST_LIST_FIRST(&con->alts) : NULL;
06226    else
06227       return AST_LIST_NEXT(sw, list);
06228 }

struct ast_context* ast_walk_contexts ( struct ast_context con  ) 

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

06208 {
06209    return con ? con->next : contexts;
06210 }

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

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

06232 {
06233    return priority ? priority->peer : exten;
06234 }

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

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

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

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

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, and strdup.

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

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

Definition at line 3430 of file pbx.c.

References ast_cli_complete().

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

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

Definition at line 3423 of file pbx.c.

References ast_cli_complete().

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

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

Definition at line 3440 of file pbx.c.

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

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

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

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

Referenced by ast_pbx_run(), and pbx_thread().

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

static void destroy_exten ( struct ast_exten e  )  [static]

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

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

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

Referenced by ast_add_extension2().

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

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

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

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

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

Referenced by ast_build_timing().

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

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

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

Referenced by ast_build_timing().

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

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

Definition at line 3725 of file pbx.c.

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

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

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

CLI support for setting global variables.

Definition at line 3713 of file pbx.c.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

int load_pbx ( void   ) 

Provided by pbx.c

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

06060 {
06061    int x;
06062 
06063    /* Initialize the PBX */
06064    if (option_verbose) {
06065       ast_verbose( "Asterisk PBX Core Initializing\n");
06066       ast_verbose( "Registering builtin applications:\n");
06067    }
06068    ast_cli_register_multiple(pbx_cli, sizeof(pbx_cli) / sizeof(struct ast_cli_entry));
06069 
06070    /* Register builtin applications */
06071    for (x=0; x<sizeof(builtins) / sizeof(struct pbx_builtin); x++) {
06072       if (option_verbose)
06073          ast_verbose( VERBOSE_PREFIX_1 "[%s]\n", builtins[x].name);
06074       if (ast_register_application(builtins[x].name, builtins[x].execute, builtins[x].synopsis, builtins[x].description)) {
06075          ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name);
06076          return -1;
06077       }
06078    }
06079    return 0;
06080 }

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

Referenced by get_range().

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

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

05962 {
05963    struct ast_var_t *vardata;
05964 
05965    ast_mutex_lock(&globalslock);
05966    while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries)))
05967       ast_var_delete(vardata);
05968    ast_mutex_unlock(&globalslock);
05969 }

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

Definition at line 5761 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(), acf_iaxvar_read(), agent_hangup(), agent_read(), agentmonitoroutgoing_exec(), array(), ast_bridge_call(), 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(), hash_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(), try_calling(), try_suggested_sip_codec(), txfax_exec(), wait_for_answer(), zt_call(), and zt_hangup().

05762 {
05763    struct ast_var_t *variables;
05764    const char *ret = NULL;
05765    int i;
05766    struct varshead *places[2] = { NULL, &globals };
05767 
05768    if (!name)
05769       return NULL;
05770    if (chan)
05771       places[0] = &chan->varshead;
05772 
05773    for (i = 0; i < 2; i++) {
05774       if (!places[i])
05775          continue;
05776       if (places[i] == &globals)
05777          ast_mutex_lock(&globalslock);
05778       AST_LIST_TRAVERSE(places[i], variables, entries) {
05779          if (!strcmp(name, ast_var_name(variables))) {
05780             ret = ast_var_value(variables);
05781             break;
05782          }
05783       }
05784       if (places[i] == &globals)
05785          ast_mutex_unlock(&globalslock);
05786       if (ret)
05787          break;
05788    }
05789 
05790    return ret;
05791 }

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

Definition at line 5981 of file pbx.c.

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

05982 {
05983    char *condition, *branch1, *branch2, *branch;
05984    int rc;
05985    char *stringp;
05986 
05987    if (ast_strlen_zero(data)) {
05988       ast_log(LOG_WARNING, "Ignoring, since there is no variable to check\n");
05989       return 0;
05990    }
05991 
05992    stringp = ast_strdupa(data);
05993    condition = strsep(&stringp,"?");
05994    branch1 = strsep(&stringp,":");
05995    branch2 = strsep(&stringp,"");
05996    branch = pbx_checkcondition(condition) ? branch1 : branch2;
05997 
05998    if (ast_strlen_zero(branch)) {
05999       if (option_debug)
06000          ast_log(LOG_DEBUG, "Not taking any branch\n");
06001       return 0;
06002    }
06003 
06004    rc = pbx_builtin_goto(chan, branch);
06005 
06006    return rc;
06007 }

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

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

05901 {
05902    char *name;
05903    char *value;
05904    char *channel;
05905    char tmp[VAR_BUF_SIZE]="";
05906 
05907    if (ast_strlen_zero(data)) {
05908       ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n");
05909       return 0;
05910    }
05911 
05912    value = ast_strdupa(data);
05913    name = strsep(&value,"=");
05914    channel = strsep(&value,"|");
05915    if (channel && value && name) { /*! \todo XXX should do !ast_strlen_zero(..) of the args ? */
05916       struct ast_channel *chan2 = ast_get_channel_by_name_locked(channel);
05917       if (chan2) {
05918          char *s = alloca(strlen(value) + 4);
05919          if (s) {
05920             sprintf(s, "${%s}", value);
05921             pbx_substitute_variables_helper(chan2, s, tmp, sizeof(tmp) - 1);
05922          }
05923          ast_channel_unlock(chan2);
05924       }
05925       pbx_builtin_setvar_helper(chan, name, tmp);
05926    }
05927 
05928    return(0);
05929 }

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

Definition at line 5956 of file pbx.c.

05957 {
05958    return 0;
05959 }

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

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

05794 {
05795    struct ast_var_t *newvariable;
05796    struct varshead *headp;
05797 
05798    if (name[strlen(name)-1] == ')') {
05799       char *function = ast_strdupa(name);
05800 
05801       ast_log(LOG_WARNING, "Cannot push a value onto a function\n");
05802       ast_func_write(chan, function, value);
05803       return;
05804    }
05805 
05806    headp = (chan) ? &chan->varshead : &globals;
05807 
05808    if (value) {
05809       if ((option_verbose > 1) && (headp == &globals))
05810          ast_verbose(VERBOSE_PREFIX_2 "Setting global variable '%s' to '%s'\n", name, value);
05811       newvariable = ast_var_assign(name, value);
05812       if (headp == &globals)
05813          ast_mutex_lock(&globalslock);
05814       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
05815       if (headp == &globals)
05816          ast_mutex_unlock(&globalslock);
05817    }
05818 }

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

Definition at line 6041 of file pbx.c.

References ast_say_character_str().

06042 {
06043    int res = 0;
06044 
06045    if (data)
06046       res = ast_say_character_str(chan, data, "", chan->language);
06047    return res;
06048 }

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

Definition at line 6032 of file pbx.c.

References ast_say_digit_str().

06033 {
06034    int res = 0;
06035 
06036    if (data)
06037       res = ast_say_digit_str(chan, data, "", chan->language);
06038    return res;
06039 }

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

Definition at line 6009 of file pbx.c.

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

06010 {
06011    char tmp[256];
06012    char *number = tmp;
06013    char *options;
06014 
06015    if (ast_strlen_zero(data)) {
06016       ast_log(LOG_WARNING, "SayNumber requires an argument (number)\n");
06017       return -1;
06018    }
06019    ast_copy_string(tmp, data, sizeof(tmp));
06020    strsep(&number, "|");
06021    options = strsep(&number, "|");
06022    if (options) {
06023       if ( strcasecmp(options, "f") && strcasecmp(options,"m") &&
06024          strcasecmp(options, "c") && strcasecmp(options, "n") ) {
06025          ast_log(LOG_WARNING, "SayNumber gender option is either 'f', 'm', 'c' or 'n'\n");
06026          return -1;
06027       }
06028    }
06029    return ast_say_number(chan, atoi(tmp), "", chan->language, options);
06030 }

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

Definition at line 6050 of file pbx.c.

References ast_say_phonetic_str().

06051 {
06052    int res = 0;
06053 
06054    if (data)
06055       res = ast_say_phonetic_str(chan, data, "", chan->language);
06056    return res;
06057 }

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

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

05735 {
05736    struct ast_var_t *variables;
05737    const char *var, *val;
05738    int total = 0;
05739 
05740    if (!chan)
05741       return 0;
05742 
05743    memset(buf, 0, size);
05744 
05745    AST_LIST_TRAVERSE(&chan->varshead, variables, entries) {
05746       if ((var=ast_var_name(variables)) && (val=ast_var_value(variables))
05747          /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */
05748          ) {
05749          if (ast_build_string(&buf, &size, "%s=%s\n", var, val)) {
05750             ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
05751             break;
05752          } else
05753             total++;
05754       } else
05755          break;
05756    }
05757 
05758    return total;
05759 }

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

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

05933 {
05934    char *name;
05935    char *stringp = data;
05936    static int dep_warning = 0;
05937 
05938    if (ast_strlen_zero(data)) {
05939       ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n");
05940       return 0;
05941    }
05942 
05943    name = strsep(&stringp, "=");
05944 
05945    if (!dep_warning) {
05946       dep_warning = 1;
05947       ast_log(LOG_WARNING, "SetGlobalVar is deprecated.  Please use Set(GLOBAL(%s)=%s) instead.\n", name, stringp);
05948    }
05949 
05950    /*! \todo XXX watch out, leading whitespace ? */
05951    pbx_builtin_setvar_helper(NULL, name, stringp);
05952 
05953    return(0);
05954 }

int pbx_builtin_setvar ( struct ast_channel ,
void *   
)

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

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

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

Definition at line 5820 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_iaxvar_write(), 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_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(), hash_read(), hash_write(), 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_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().

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

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

05972 {
05973    if (ast_strlen_zero(condition))  /* NULL or empty strings are false */
05974       return 0;
05975    else if (*condition >= '0' && *condition <= '9')   /* Numbers are evaluated for truth */
05976       return atoi(condition);
05977    else  /* Strings are true */
05978       return 1;
05979 }

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

References autofallthrough.

Referenced by pbx_load_module().

02660 {
02661    int oldval = autofallthrough;
02662    autofallthrough = newval;
02663    return oldval;
02664 }

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(), 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(), rpt_exec(), 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 2595 of file pbx.c.

References __ast_pbx_run(), and decrease_call_count().

Referenced by ast_pbx_start().

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

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

helper function to print an extension

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

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

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

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

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

05344 {
05345    int res;
05346    struct ast_frame *f;
05347    int waittime;
05348 
05349    if (ast_strlen_zero(data) || (sscanf(data, "%d", &waittime) != 1) || (waittime < 0))
05350       waittime = -1;
05351    if (waittime > -1) {
05352       ast_safe_sleep(chan, waittime * 1000);
05353    } else do {
05354       res = ast_waitfor(chan, -1);
05355       if (res < 0)
05356          return;
05357       f = ast_read(chan);
05358       if (f)
05359          ast_frfree(f);
05360    } while(f);
05361 }


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 3781 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 3771 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 3741 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 3776 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 3766 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 3746 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 3761 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 3756 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 3751 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 4181 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 4193 of file pbx.c.

Referenced by ast_build_timing().

struct ast_cli_entry pbx_cli[] [static]

Definition at line 3786 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 3055 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 3043 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 3021 of file pbx.c.

char show_dialplan_help[] [static]

Initial value:

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

Definition at line 3051 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 3047 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 3027 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 3039 of file pbx.c.

char show_hints_help[] [static]

Initial value:

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

Definition at line 3035 of file pbx.c.

char show_switches_help[] [static]

Initial value:

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

Definition at line 3031 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 Mon May 14 04:52:00 2007 for Asterisk - the Open Source PBX by  doxygen 1.5.1