Wed Aug 15 01:25:22 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)
 Main interface to add extensions to the list for out context.
static int ast_add_hint (struct ast_exten *e)
 ast_add_hint: Add hint to hint list, check initial extension state
 AST_APP_OPTIONS (resetcdr_opts,{AST_APP_OPTION('w', AST_CDR_FLAG_POSTED), AST_APP_OPTION('a', AST_CDR_FLAG_LOCKED), AST_APP_OPTION('v', AST_CDR_FLAG_KEEP_VARS),})
 AST_APP_OPTIONS (waitexten_opts,{AST_APP_OPTION_ARG('m', WAITEXTEN_MOH, 0),})
 AST_APP_OPTIONS (background_opts,{AST_APP_OPTION('s', BACKGROUND_SKIP), AST_APP_OPTION('n', BACKGROUND_NOANSWER), AST_APP_OPTION('m', BACKGROUND_MATCHEXTEN), AST_APP_OPTION('p', BACKGROUND_PLAYBACK),})
int ast_async_goto (struct ast_channel *chan, const char *context, const char *exten, int priority)
int ast_async_goto_by_name (const char *channame, const char *context, const char *exten, int priority)
int ast_async_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority)
int ast_build_timing (struct ast_timing *i, const char *info_in)
int ast_canmatch_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
 Looks for a valid matching extension.
static int ast_change_hint (struct ast_exten *oe, struct ast_exten *ne)
 ast_change_hint: Change hint for an extension
int ast_check_timing (const struct ast_timing *i)
int ast_context_add_ignorepat (const char *context, const char *value, const char *registrar)
 Add an ignorepat.
int ast_context_add_ignorepat2 (struct ast_context *con, const char *value, const char *registrar)
int ast_context_add_include (const char *context, const char *include, const char *registrar)
 Add a context include.
int ast_context_add_include2 (struct ast_context *con, const char *value, const char *registrar)
 Add a context include.
int ast_context_add_switch (const char *context, const char *sw, const char *data, int eval, const char *registrar)
 Add a switch.
int ast_context_add_switch2 (struct ast_context *con, const char *value, const char *data, int eval, const char *registrar)
 Adds a switch (first param is a ast_context).
struct ast_contextast_context_create (struct ast_context **extcontexts, const char *name, const char *registrar)
 Register a new context.
void ast_context_destroy (struct ast_context *con, const char *registrar)
 Destroy a context (matches the specified context (or ANY context if NULL).
struct ast_contextast_context_find (const char *name)
 Find a context.
struct ast_contextast_context_find_or_create (struct ast_context **extcontexts, const char *name, const char *registrar)
int ast_context_lockmacro (const char *context)
 locks the macrolock in the given given context
int ast_context_remove_extension (const char *context, const char *extension, int priority, const char *registrar)
 Simply remove extension from context.
int ast_context_remove_extension2 (struct ast_context *con, const char *extension, int priority, const char *registrar)
 This functionc locks given context, search for the right extension and fires out all peer in this extensions with given priority. If priority is set to 0, all peers are removed. After that, unlock context and return.
int ast_context_remove_ignorepat (const char *context, const char *ignorepat, const char *registrar)
int ast_context_remove_ignorepat2 (struct ast_context *con, const char *ignorepat, const char *registrar)
int ast_context_remove_include (const char *context, const char *include, const char *registrar)
 Remove a context include.
int ast_context_remove_include2 (struct ast_context *con, const char *include, const char *registrar)
 Removes an include by an ast_context structure.
int ast_context_remove_switch (const char *context, const char *sw, const char *data, const char *registrar)
 Remove a switch.
int ast_context_remove_switch2 (struct ast_context *con, const char *sw, const char *data, const char *registrar)
 This function locks given context, removes switch, unlock context and return.
int ast_context_unlockmacro (const char *context)
 Unlocks the macrolock in the given context.
int ast_context_verify_includes (struct ast_context *con)
 Verifies includes in an ast_contect structure.
struct
ast_custom_function
ast_custom_function_find (const char *name)
int ast_custom_function_register (struct ast_custom_function *acf)
 Reigster a custom function.
int ast_custom_function_unregister (struct ast_custom_function *acf)
 Unregister a custom function.
int ast_exists_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
 Determine whether an extension exists.
int ast_explicit_goto (struct ast_channel *chan, const char *context, const char *exten, int priority)
int ast_extension_close (const char *pattern, const char *data, int needmore)
int ast_extension_match (const char *pattern, const char *data)
 Determine if a given extension matches a given pattern (in NXX format).
int ast_extension_state (struct ast_channel *c, const char *context, const char *exten)
 ast_extension_state: Check extension state for an extension by using hint
static int ast_extension_state2 (struct ast_exten *e)
 ast_extensions_state2: Check state of extension by using hints
const char * ast_extension_state2str (int extension_state)
 ast_extension_state2str: Return extension_state as string
int ast_extension_state_add (const char *context, const char *exten, ast_state_cb_type callback, void *data)
 ast_extension_state_add: Add watcher for extension states
int ast_extension_state_del (int id, ast_state_cb_type callback)
 ast_extension_state_del: Remove a watcher from the callback list
int ast_findlabel_extension (struct ast_channel *c, const char *context, const char *exten, const char *label, const char *callerid)
 Find the priority of an extension that has the specified label.
int ast_findlabel_extension2 (struct ast_channel *c, struct ast_context *con, const char *exten, const char *label, const char *callerid)
 Find the priority of an extension that has the specified label.
int ast_func_read (struct ast_channel *chan, char *function, char *workspace, size_t len)
 executes a read operation on a function
int ast_func_write (struct ast_channel *chan, char *function, const char *value)
 executes a write operation on a function
const char * ast_get_context_name (struct ast_context *con)
const char * ast_get_context_registrar (struct ast_context *c)
const char * ast_get_extension_app (struct ast_exten *e)
void * ast_get_extension_app_data (struct ast_exten *e)
const char * ast_get_extension_cidmatch (struct ast_exten *e)
struct ast_contextast_get_extension_context (struct ast_exten *exten)
const char * ast_get_extension_label (struct ast_exten *exten)
int ast_get_extension_matchcid (struct ast_exten *e)
const char * ast_get_extension_name (struct ast_exten *exten)
int ast_get_extension_priority (struct ast_exten *exten)
const char * ast_get_extension_registrar (struct ast_exten *e)
int ast_get_hint (char *hint, int hintsize, char *name, int namesize, struct ast_channel *c, const char *context, const char *exten)
 ast_get_hint: Get hint for channel
const char * ast_get_ignorepat_name (struct ast_ignorepat *ip)
const char * ast_get_ignorepat_registrar (struct ast_ignorepat *ip)
const char * ast_get_include_name (struct ast_include *inc)
const char * ast_get_include_registrar (struct ast_include *i)
const char * ast_get_switch_data (struct ast_sw *sw)
const char * ast_get_switch_name (struct ast_sw *sw)
const char * ast_get_switch_registrar (struct ast_sw *sw)
int ast_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority)
static struct ast_extenast_hint_extension (struct ast_channel *c, const char *context, const char *exten)
 ast_hint_extension: Find hint for given extension in context
void ast_hint_state_changed (const char *device)
int ast_ignore_pattern (const char *context, const char *pattern)
 Checks to see if a number should be ignored.
 AST_LIST_HEAD (store_hints, store_hint)
static AST_LIST_HEAD_STATIC (hints, ast_hint)
static AST_LIST_HEAD_STATIC (switches, ast_switch)
static AST_LIST_HEAD_STATIC (apps, ast_app)
static AST_LIST_HEAD_STATIC (acf_root, ast_custom_function)
int ast_lock_context (struct ast_context *con)
 Locks a given context.
int ast_lock_contexts ()
 Locks the context list.
int ast_matchmore_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
 Looks to see if adding anything to this extension might match something. (exists ^ canmatch).
void ast_merge_contexts_and_delete (struct ast_context **extcontexts, const char *registrar)
 Merge the temporary contexts into a global contexts list and delete from the global list the ones that are being added.
 AST_MUTEX_DEFINE_STATIC (conlock)
 AST_MUTEX_DEFINE_STATIC (maxcalllock)
 AST_MUTEX_DEFINE_STATIC (globalslock)
int ast_parseable_goto (struct ast_channel *chan, const char *goto_string)
int ast_pbx_outgoing_app (const char *type, int format, void *data, int timeout, const char *app, const char *appdata, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel)
static int ast_pbx_outgoing_cdr_failed (void)
int ast_pbx_outgoing_exten (const char *type, int format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **channel)
enum ast_pbx_result ast_pbx_run (struct ast_channel *c)
 Execute the PBX in the current thread.
static void * ast_pbx_run_app (void *data)
 run the application and free the descriptor once done
enum ast_pbx_result ast_pbx_start (struct ast_channel *c)
 Create a new thread and start the PBX.
int ast_register_application (const char *app, int(*execute)(struct ast_channel *, void *), const char *synopsis, const char *description)
 Dynamically register a new dial plan application.
int ast_register_switch (struct ast_switch *sw)
 Register an alternative dialplan switch.
static int ast_remove_hint (struct ast_exten *e)
 ast_remove_hint: Remove hint from extension
int ast_spawn_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
 Launch a new extension (i.e. new stack).
int ast_unlock_context (struct ast_context *con)
int ast_unlock_contexts ()
 Unlocks contexts.
int ast_unregister_application (const char *app)
 Unregister an application.
void ast_unregister_switch (struct ast_switch *sw)
 Unregister an alternative switch.
struct ast_extenast_walk_context_extensions (struct ast_context *con, struct ast_exten *exten)
struct ast_ignorepatast_walk_context_ignorepats (struct ast_context *con, struct ast_ignorepat *ip)
struct ast_includeast_walk_context_includes (struct ast_context *con, struct ast_include *inc)
struct ast_swast_walk_context_switches (struct ast_context *con, struct ast_sw *sw)
struct ast_contextast_walk_contexts (struct ast_context *con)
struct ast_extenast_walk_extension_priorities (struct ast_exten *exten, struct ast_exten *priority)
static void * async_wait (void *data)
static int collect_digits (struct ast_channel *c, int waittime, char *buf, int buflen, int pos)
 collect digits from the channel into the buffer, return -1 on error, 0 on timeout or done.
static char * complete_show_application (const char *line, const char *word, int pos, int state)
static char * complete_show_applications (const char *line, const char *word, int pos, int state)
static char * complete_show_applications_deprecated (const char *line, const char *word, int pos, int state)
static char * complete_show_dialplan_context (const char *line, const char *word, int pos, int state)
static char * complete_show_function (const char *line, const char *word, int pos, int state)
static void decrease_call_count (void)
static void destroy_exten (struct ast_exten *e)
static int ext_cmp (const char *a, const char *b)
 the full routine to compare extensions in rules.
static int ext_cmp1 (const char **p)
 helper functions to sort extensions and patterns in the desired way, so that more specific patterns appear first.
static int ext_strncpy (char *dst, const char *src, int len)
 copy a string skipping whitespace
static int extension_match_core (const char *pattern, const char *data, enum ext_match_t mode)
static struct
ast_context
find_context_locked (const char *context)
static char * func_args (char *function)
 return a pointer to the arguments of the function, and terminates the function name with '\0'
static unsigned get_range (char *src, int max, char *const names[], const char *msg)
 helper function to return a range up to max (7, 12, 31 respectively). names, if supplied, is an array of names that should be mapped to numbers.
static void get_timerange (struct ast_timing *i, char *times)
 store a bitmask of valid times, one bit each 2 minute
static int handle_set_global (int fd, int argc, char *argv[])
static int handle_set_global_deprecated (int fd, int argc, char *argv[])
 CLI support for setting global variables.
static int handle_show_application (int fd, int argc, char *argv[])
static int handle_show_application_deprecated (int fd, int argc, char *argv[])
static int handle_show_applications (int fd, int argc, char *argv[])
static int handle_show_applications_deprecated (int fd, int argc, char *argv[])
static int handle_show_dialplan (int fd, int argc, char *argv[])
static int handle_show_function (int fd, int argc, char *argv[])
static int handle_show_function_deprecated (int fd, int argc, char *argv[])
static int handle_show_functions (int fd, int argc, char *argv[])
static int handle_show_functions_deprecated (int fd, int argc, char *argv[])
static int handle_show_globals (int fd, int argc, char *argv[])
 CLI support for listing global variables in a parseable way.
static int handle_show_hints (int fd, int argc, char *argv[])
 handle_show_hints: CLI support for listing registred dial plan hints
static int handle_show_switches (int fd, int argc, char *argv[])
 handle_show_switches: CLI support for listing registred dial plan switches
static int include_valid (struct ast_include *i)
static int increase_call_count (const struct ast_channel *c)
int load_pbx (void)
static int lookup_name (const char *s, char *const names[], int max)
 Helper for get_range. return the index of the matching entry, starting from 1. If names is not supplied, try numeric values.
static int matchcid (const char *cidpattern, const char *callerid)
static int parse_variable_name (char *var, int *offset, int *length, int *isfunc)
 extract offset:length from variable name. Returns 1 if there is a offset:length part, which is trimmed off (values go into variables)
static int pbx_builtin_answer (struct ast_channel *, void *)
static int pbx_builtin_background (struct ast_channel *, void *)
static int pbx_builtin_busy (struct ast_channel *, void *)
void pbx_builtin_clear_globals (void)
static int pbx_builtin_congestion (struct ast_channel *, void *)
static int pbx_builtin_execiftime (struct ast_channel *, void *)
const char * pbx_builtin_getvar_helper (struct ast_channel *chan, const char *name)
static int pbx_builtin_goto (struct ast_channel *, void *)
static int pbx_builtin_gotoif (struct ast_channel *, void *)
static int pbx_builtin_gotoiftime (struct ast_channel *, void *)
static int pbx_builtin_hangup (struct ast_channel *, void *)
static int pbx_builtin_importvar (struct ast_channel *, void *)
static int pbx_builtin_noop (struct ast_channel *, void *)
static int pbx_builtin_progress (struct ast_channel *, void *)
void pbx_builtin_pushvar_helper (struct ast_channel *chan, const char *name, const char *value)
static int pbx_builtin_resetcdr (struct ast_channel *, void *)
static int pbx_builtin_ringing (struct ast_channel *, void *)
static int pbx_builtin_saycharacters (struct ast_channel *, void *)
static int pbx_builtin_saydigits (struct ast_channel *, void *)
static int pbx_builtin_saynumber (struct ast_channel *, void *)
static int pbx_builtin_sayphonetic (struct ast_channel *, void *)
int pbx_builtin_serialize_variables (struct ast_channel *chan, char *buf, size_t size)
static int pbx_builtin_setamaflags (struct ast_channel *, void *)
static int pbx_builtin_setglobalvar (struct ast_channel *, void *)
int pbx_builtin_setvar (struct ast_channel *, void *)
void pbx_builtin_setvar_helper (struct ast_channel *chan, const char *name, const char *value)
static int pbx_builtin_wait (struct ast_channel *, void *)
static int pbx_builtin_waitexten (struct ast_channel *, void *)
int pbx_checkcondition (const char *condition)
 Evaluate a condition.
static void pbx_destroy (struct ast_pbx *p)
int pbx_exec (struct ast_channel *c, struct ast_app *app, void *data)
 Execute an application.
static int pbx_extension_helper (struct ast_channel *c, struct ast_context *con, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action)
 The return value depends on the action:.
static struct ast_extenpbx_find_extension (struct ast_channel *chan, struct ast_context *bypass, struct pbx_find_info *q, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action)
struct ast_apppbx_findapp (const char *app)
 Find application handle in linked list.
static struct
ast_switch
pbx_findswitch (const char *sw)
void pbx_retrieve_variable (struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp)
 pbx_retrieve_variable: Support for Asterisk built-in variables ---
int pbx_set_autofallthrough (int newval)
static void pbx_substitute_variables (char *passdata, int datalen, struct ast_channel *c, struct ast_exten *e)
void pbx_substitute_variables_helper (struct ast_channel *c, const char *cp1, char *cp2, int count)
static void pbx_substitute_variables_helper_full (struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count)
void pbx_substitute_variables_varshead (struct varshead *headp, const char *cp1, char *cp2, int count)
static void * pbx_thread (void *data)
static void print_ext (struct ast_exten *e, char *buf, int buflen)
 helper function to print an extension
static void set_ext_pri (struct ast_channel *c, const char *exten, int pri)
static int show_dialplan_helper (int fd, const char *context, const char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude, int includecount, const char *includes[])
static char * substring (const char *value, int offset, int length, char *workspace, size_t workspace_len)
 takes a substring. It is ok to call with value == workspace.
static void wait_for_hangup (struct ast_channel *chan, void *data)

Variables

static int autofallthrough = 1
static struct pbx_builtin builtins []
 Declaration of builtin applications.
static struct
ast_cli_entry 
cli_set_global_deprecated
static struct
ast_cli_entry 
cli_show_application_deprecated
static struct
ast_cli_entry 
cli_show_applications_deprecated
static struct
ast_cli_entry 
cli_show_dialplan_deprecated
static struct
ast_cli_entry 
cli_show_function_deprecated
static struct
ast_cli_entry 
cli_show_functions_deprecated
static struct
ast_cli_entry 
cli_show_globals_deprecated
static struct
ast_cli_entry 
cli_show_hints_deprecated
static struct
ast_cli_entry 
cli_show_switches_deprecated
static struct
ast_context
contexts
static int countcalls
static char * days []
static struct
cfextension_states 
extension_states []
static struct varshead globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE
static char * months []
static struct
ast_cli_entry 
pbx_cli []
static char set_global_help []
static char show_application_help []
static char show_applications_help []
static char show_dialplan_help []
static char show_function_help []
static char show_functions_help []
static char show_globals_help []
static char show_hints_help []
static char show_switches_help []
struct ast_state_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 544 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 902 of file pbx.c.

Referenced by pbx_extension_helper(), and pbx_find_extension().

#define STATUS_NO_EXTENSION   2

Definition at line 903 of file pbx.c.

Referenced by pbx_extension_helper(), and pbx_find_extension().

#define STATUS_NO_LABEL   4

Definition at line 905 of file pbx.c.

Referenced by pbx_extension_helper(), and pbx_find_extension().

#define STATUS_NO_PRIORITY   3

Definition at line 904 of file pbx.c.

Referenced by pbx_extension_helper(), and pbx_find_extension().

#define STATUS_SUCCESS   5

Definition at line 906 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(), and pbx_find_extension().

#define VAR_BUF_SIZE   4096

Definition at line 82 of file pbx.c.

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

#define 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 749 of file pbx.c.

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


Function Documentation

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

Definition at line 3840 of file pbx.c.

References ast_calloc, ast_log(), ast_mutex_init(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), contexts, ast_context::ignorepats, ast_context::includes, local_contexts, ast_context::lock, LOG_DEBUG, LOG_WARNING, ast_context::next, option_debug, option_verbose, ast_context::registrar, ast_context::root, and VERBOSE_PREFIX_3.

Referenced by ast_context_create(), and ast_context_find_or_create().

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

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

Definition at line 5259 of file pbx.c.

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

Referenced by ast_context_destroy(), and ast_merge_contexts_and_delete().

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

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

Definition at line 6245 of file pbx.c.

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

Referenced by ast_async_goto_if_exists(), and ast_goto_if_exists().

06246 {
06247    int (*goto_func)(struct ast_channel *chan, const char *context, const char *exten, int priority);
06248 
06249    if (!chan)
06250       return -2;
06251 
06252    if (context == NULL)
06253       context = chan->context;
06254    if (exten == NULL)
06255       exten = chan->exten;
06256 
06257    goto_func = (async) ? ast_async_goto : ast_explicit_goto;
06258    if (ast_exists_extension(chan, context, exten, priority, chan->cid.cid_num))
06259       return goto_func(chan, context, exten, priority);
06260    else
06261       return -3;
06262 }

static int __ast_pbx_run ( struct ast_channel c  )  [static]

Definition at line 2328 of file pbx.c.

References ast_channel::_softhangup, ast_channel::amaflags, ast_calloc, AST_CAUSE_NORMAL_CLEARING, ast_cdr_alloc(), ast_cdr_end(), ast_cdr_init(), ast_cdr_start(), ast_cdr_update(), ast_exists_extension(), AST_FLAG_IN_AUTOLOOP, ast_hangup(), ast_log(), ast_opt_end_cdr_before_h_exten, AST_PBX_KEEPALIVE, ast_set2_flag, ast_set_flag, ast_softhangup(), AST_SOFTHANGUP_ASYNCGOTO, AST_SOFTHANGUP_TIMEOUT, ast_spawn_extension(), ast_strlen_zero(), ast_test_flag, ast_verbose(), autofallthrough, ast_channel::cdr, ast_channel::cid, ast_callerid::cid_num, collect_digits(), ast_channel::context, ast_pbx::dtimeout, error(), ast_channel::exten, free, ast_channel::hangupcause, LOG_DEBUG, LOG_WARNING, option_debug, option_verbose, ast_channel::pbx, pbx_builtin_busy(), pbx_builtin_congestion(), pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), pbx_destroy(), ast_channel::priority, ast_pbx::rtimeout, set_ext_pri(), ast_cdr::start, VERBOSE_PREFIX_2, VERBOSE_PREFIX_3, and ast_channel::whentohangup.

Referenced by ast_pbx_run(), and pbx_thread().

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

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

Definition at line 767 of file pbx.c.

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

Referenced by extension_match_core().

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

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

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

Definition at line 4650 of file pbx.c.

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

Referenced by ast_add_extension2().

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

int ast_active_calls ( void   ) 

Retrieve the number of active calls.

Definition at line 2650 of file pbx.c.

Referenced by handle_chanlist(), and handle_chanlist_deprecated().

02651 {
02652    return countcalls;
02653 }

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

Add and extension to an extension context.

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

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

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

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

Main interface to add extensions to the list for out context.

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

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

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

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

Definition at line 4734 of file pbx.c.

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

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

static int ast_add_hint ( struct ast_exten e  )  [static]

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

Definition at line 2152 of file pbx.c.

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

Referenced by add_pri(), and ast_add_extension2().

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

AST_APP_OPTIONS ( resetcdr_opts   ) 

AST_APP_OPTIONS ( waitexten_opts   ) 

AST_APP_OPTIONS ( background_opts   ) 

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

Definition at line 4564 of file pbx.c.

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

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

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

Definition at line 4610 of file pbx.c.

04611 {
04612    struct ast_channel *chan;
04613    int res = -1;
04614 
04615    chan = ast_get_channel_by_name_locked(channame);
04616    if (chan) {
04617       res = ast_async_goto(chan, context, exten, priority);
04618       ast_channel_unlock(chan);
04619    }
04620    return res;
04621 }

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

Definition at line 6269 of file pbx.c.

Referenced by asyncgoto_exec().

06270 {
06271    return __ast_goto_if_exists(chan, context, exten, priority, 1);
06272 }

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

Definition at line 4206 of file pbx.c.

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

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

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

Looks for a valid matching extension.

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

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

02277 {
02278    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH);
02279 }

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

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

Referenced by add_pri().

02189 {
02190    struct ast_hint *hint;
02191    int res = -1;
02192 
02193    AST_LIST_LOCK(&hints);
02194    AST_LIST_TRAVERSE(&hints, hint, list) {
02195       if (hint->exten == oe) {
02196             hint->exten = ne;
02197          res = 0;
02198          break;
02199       }
02200    }
02201    AST_LIST_UNLOCK(&hints);
02202 
02203    return res;
02204 }

int ast_check_timing ( const struct ast_timing i  ) 

Definition at line 4232 of file pbx.c.

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

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

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

Add an ignorepat.

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

Referenced by handle_context_add_ignorepat(), and handle_context_add_ignorepat_deprecated().

04467 {
04468    int ret = -1;
04469    struct ast_context *c = find_context_locked(context);
04470 
04471    if (c) {
04472       ret = ast_context_add_ignorepat2(c, value, registrar);
04473       ast_unlock_contexts();
04474    }
04475    return ret;
04476 }

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

Definition at line 4478 of file pbx.c.

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

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

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

Add a context include.

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

Referenced by handle_context_add_include(), and handle_context_add_include_deprecated().

04013 {
04014    int ret = -1;
04015    struct ast_context *c = find_context_locked(context);
04016 
04017    if (c) {
04018       ret = ast_context_add_include2(c, include, registrar);
04019       ast_unlock_contexts();
04020    }
04021    return ret;
04022 }

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

Add a context include.

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

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

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

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

Add a switch.

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

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

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

Adds a switch (first param is a ast_context).

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

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

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

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

Register a new context.

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

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

03884 {
03885    return __ast_context_create(extcontexts, name, registrar, 0);
03886 }

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

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

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

Referenced by cleanup_stale_contexts(), and unload_module().

05321 {
05322    __ast_context_destroy(con,registrar);
05323 }

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

Find a context.

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

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

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

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

Definition at line 3888 of file pbx.c.

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

03889 {
03890    return __ast_context_create(extcontexts, name, registrar, 1);
03891 }

int ast_context_lockmacro ( const char *  context  ) 

locks the macrolock in the given given context

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

Referenced by _macro_exec().

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

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

Simply remove extension from context.

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

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

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

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

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

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

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

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

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

Definition at line 4423 of file pbx.c.

Referenced by handle_context_remove_ignorepat(), and handle_context_remove_ignorepat_deprecated().

04424 {
04425    int ret = -1;
04426    struct ast_context *c = find_context_locked(context);
04427 
04428    if (c) {
04429       ret = ast_context_remove_ignorepat2(c, ignorepat, registrar);
04430       ast_unlock_contexts();
04431    }
04432    return ret;
04433 }

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

Definition at line 4435 of file pbx.c.

Referenced by ast_context_remove_ignorepat().

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

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

Remove a context include.

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

Definition at line 2684 of file pbx.c.

Referenced by handle_context_dont_include_deprecated(), and handle_context_remove_include().

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

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

Removes an include by an ast_context structure.

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

Definition at line 2705 of file pbx.c.

Referenced by ast_context_remove_include().

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

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

Remove a switch.

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

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

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

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

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

Referenced by ast_context_remove_switch().

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

int ast_context_unlockmacro ( const char *  context  ) 

Unlocks the macrolock in the given context.

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

Referenced by _macro_exec().

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

int ast_context_verify_includes ( struct ast_context con  ) 

Verifies includes in an ast_contect structure.

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

Referenced by pbx_load_module().

06231 {
06232    struct ast_include *inc = NULL;
06233    int res = 0;
06234 
06235    while ( (inc = ast_walk_context_includes(con, inc)) )
06236       if (!ast_context_find(inc->rname)) {
06237          res = -1;
06238          ast_log(LOG_WARNING, "Context '%s' tries includes nonexistent context '%s'\n",
06239                ast_get_context_name(con), inc->rname);
06240       }
06241    return res;
06242 }

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

Definition at line 1427 of file pbx.c.

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

01428 {
01429    struct ast_custom_function *acf = NULL;
01430 
01431    AST_LIST_LOCK(&acf_root);
01432    AST_LIST_TRAVERSE(&acf_root, acf, acflist) {
01433       if (!strcmp(name, acf->name))
01434          break;
01435    }
01436    AST_LIST_UNLOCK(&acf_root);
01437 
01438    return acf;
01439 }

int ast_custom_function_register ( struct ast_custom_function acf  ) 

Reigster a custom function.

Definition at line 1463 of file pbx.c.

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

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

int ast_custom_function_unregister ( struct ast_custom_function acf  ) 

Unregister a custom function.

Definition at line 1441 of file pbx.c.

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

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

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

Determine whether an extension exists.

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

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

02262 {
02263    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH);
02264 }

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

Definition at line 4545 of file pbx.c.

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

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

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

Definition at line 883 of file pbx.c.

Referenced by realtime_switch_common().

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

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

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

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

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

00879 {
00880    return extension_match_core(pattern, data, E_MATCH);
00881 }

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

ast_extension_state: Check extension state for an extension by using hint

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

Definition at line 1985 of file pbx.c.

Referenced by action_extensionstate(), and handle_request_subscribe().

01986 {
01987    struct ast_exten *e;
01988 
01989    e = ast_hint_extension(c, context, exten);   /* Do we have a hint for this extension ? */
01990    if (!e)
01991       return -1;           /* No hint, return -1 */
01992 
01993    return ast_extension_state2(e);        /* Check all devices in the hint */
01994 }

static int ast_extension_state2 ( struct ast_exten e  )  [static]

ast_extensions_state2: Check state of extension by using hints

Definition at line 1888 of file pbx.c.

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

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

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

const char* ast_extension_state2str ( int  extension_state  ) 

ast_extension_state2str: Return extension_state as string

Return string representation of the state of an extension.

Definition at line 1973 of file pbx.c.

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

01974 {
01975    int i;
01976 
01977    for (i = 0; (i < (sizeof(extension_states) / sizeof(extension_states[0]))); i++) {
01978       if (extension_states[i].extension_state == extension_state)
01979          return extension_states[i].text;
01980    }
01981    return "Unknown";
01982 }

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

ast_extension_state_add: Add watcher for extension states

Registers a state change callback.

Definition at line 2040 of file pbx.c.

Referenced by handle_request_subscribe(), and init_manager().

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

int ast_extension_state_del ( int  id,
ast_state_cb_type  callback 
)

ast_extension_state_del: Remove a watcher from the callback list

Deletes a registered state change callback by ID.

Definition at line 2115 of file pbx.c.

Referenced by __sip_destroy(), and handle_request_subscribe().

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

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

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

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

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

02267 {
02268    return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL);
02269 }

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

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

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

Referenced by pbx_load_config().

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

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

executes a read operation on a function

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

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

01518 {
01519    char *args = func_args(function);
01520    struct ast_custom_function *acfptr = ast_custom_function_find(function);
01521 
01522    if (acfptr == NULL)
01523       ast_log(LOG_ERROR, "Function %s not registered\n", function);
01524    else if (!acfptr->read)
01525       ast_log(LOG_ERROR, "Function %s cannot be read\n", function);
01526    else
01527       return acfptr->read(chan, function, args, workspace, len);
01528    return -1;
01529 }

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

executes a write operation on a function

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

Referenced by pbx_builtin_pushvar_helper(), and pbx_builtin_setvar_helper().

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

const char* ast_get_context_name ( struct ast_context con  ) 

Definition at line 6087 of file pbx.c.

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

06088 {
06089    return con ? con->name : NULL;
06090 }

const char* ast_get_context_registrar ( struct ast_context c  ) 

Definition at line 6125 of file pbx.c.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06126 {
06127    return c ? c->registrar : NULL;
06128 }

const char* ast_get_extension_app ( struct ast_exten e  ) 

Definition at line 6155 of file pbx.c.

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

06156 {
06157    return e ? e->app : NULL;
06158 }

void* ast_get_extension_app_data ( struct ast_exten e  ) 

Definition at line 6160 of file pbx.c.

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

06161 {
06162    return e ? e->data : NULL;
06163 }

const char* ast_get_extension_cidmatch ( struct ast_exten e  ) 

Definition at line 6150 of file pbx.c.

Referenced by find_matching_priority(), and handle_save_dialplan().

06151 {
06152    return e ? e->cidmatch : NULL;
06153 }

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

Definition at line 6092 of file pbx.c.

Referenced by handle_show_hints().

06093 {
06094    return exten ? exten->parent : NULL;
06095 }

const char* ast_get_extension_label ( struct ast_exten exten  ) 

Definition at line 6102 of file pbx.c.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06103 {
06104    return exten ? exten->label : NULL;
06105 }

int ast_get_extension_matchcid ( struct ast_exten e  ) 

Definition at line 6145 of file pbx.c.

Referenced by find_matching_priority(), and handle_save_dialplan().

06146 {
06147    return e ? e->matchcid : 0;
06148 }

const char* ast_get_extension_name ( struct ast_exten exten  ) 

Definition at line 6097 of file pbx.c.

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

06098 {
06099    return exten ? exten->exten : NULL;
06100 }

int ast_get_extension_priority ( struct ast_exten exten  ) 

Definition at line 6117 of file pbx.c.

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

06118 {
06119    return exten ? exten->priority : -1;
06120 }

const char* ast_get_extension_registrar ( struct ast_exten e  ) 

Definition at line 6130 of file pbx.c.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06131 {
06132    return e ? e->registrar : NULL;
06133 }

int ast_get_hint ( char *  hint,
int  hintsize,
char *  name,
int  namesize,
struct ast_channel c,
const char *  context,
const char *  exten 
)

ast_get_hint: Get hint for channel

If an extension exists, return non-zero.

Definition at line 2244 of file pbx.c.

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

02245 {
02246    struct ast_exten *e = ast_hint_extension(c, context, exten);
02247 
02248    if (e) {
02249       if (hint)
02250          ast_copy_string(hint, ast_get_extension_app(e), hintsize);
02251       if (name) {
02252          const char *tmp = ast_get_extension_app_data(e);
02253          if (tmp)
02254             ast_copy_string(name, tmp, namesize);
02255       }
02256       return -1;
02257    }
02258    return 0;
02259 }

const char* ast_get_ignorepat_name ( struct ast_ignorepat ip  ) 

Definition at line 6112 of file pbx.c.

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

06113 {
06114    return ip ? ip->pattern : NULL;
06115 }

const char* ast_get_ignorepat_registrar ( struct ast_ignorepat ip  ) 

Definition at line 6140 of file pbx.c.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06141 {
06142    return ip ? ip->registrar : NULL;
06143 }

const char* ast_get_include_name ( struct ast_include inc  ) 

Definition at line 6107 of file pbx.c.

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

06108 {
06109    return inc ? inc->name : NULL;
06110 }

const char* ast_get_include_registrar ( struct ast_include i  ) 

Definition at line 6135 of file pbx.c.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06136 {
06137    return i ? i->registrar : NULL;
06138 }

const char* ast_get_switch_data ( struct ast_sw sw  ) 

Definition at line 6170 of file pbx.c.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06171 {
06172    return sw ? sw->data : NULL;
06173 }

const char* ast_get_switch_name ( struct ast_sw sw  ) 

Definition at line 6165 of file pbx.c.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06166 {
06167    return sw ? sw->name : NULL;
06168 }

const char* ast_get_switch_registrar ( struct ast_sw sw  ) 

Definition at line 6175 of file pbx.c.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06176 {
06177    return sw ? sw->registrar : NULL;
06178 }

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

Definition at line 6264 of file pbx.c.

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

06265 {
06266    return __ast_goto_if_exists(chan, context, exten, priority, 0);
06267 }

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

ast_hint_extension: Find hint for given extension in context

Definition at line 1875 of file pbx.c.

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

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

01876 {
01877    struct ast_exten *e;
01878    struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */
01879 
01880    ast_mutex_lock(&conlock);
01881    e = pbx_find_extension(c, NULL, &q, context, exten, PRIORITY_HINT, NULL, "", E_MATCH);
01882    ast_mutex_unlock(&conlock);
01883 
01884    return e;
01885 }

void ast_hint_state_changed ( const char *  device  ) 

Definition at line 1996 of file pbx.c.

Referenced by do_state_change().

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

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

Checks to see if a number should be ignored.

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

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

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

AST_LIST_HEAD ( store_hints  ,
store_hint   
)

static AST_LIST_HEAD_STATIC ( hints  ,
ast_hint   
) [static]

static AST_LIST_HEAD_STATIC ( switches  ,
ast_switch   
) [static]

static AST_LIST_HEAD_STATIC ( apps  ,
ast_app   
) [static]

static AST_LIST_HEAD_STATIC ( acf_root  ,
ast_custom_function   
) [static]

int ast_lock_context ( struct ast_context con  ) 

Locks a given context.

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

Definition at line 6074 of file pbx.c.

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

06075 {
06076    return ast_mutex_lock(&con->lock);
06077 }

int ast_lock_contexts ( void   ) 

Locks the context list.

Return values:
0 on success
-1 on error

Definition at line 6061 of file pbx.c.

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

06062 {
06063    return ast_mutex_lock(&conlock);
06064 }

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

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

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

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

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

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

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

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

Referenced by pbx_load_module().

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

AST_MUTEX_DEFINE_STATIC ( conlock   ) 

Lock for the ast_context list

AST_MUTEX_DEFINE_STATIC ( maxcalllock   ) 

AST_MUTEX_DEFINE_STATIC ( globalslock   ) 

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

Definition at line 6274 of file pbx.c.

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

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

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

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

Definition at line 5116 of file pbx.c.

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

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

static int ast_pbx_outgoing_cdr_failed ( void   )  [static]

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

This function posts an empty cdr for a failed spool call

Definition at line 4935 of file pbx.c.

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

Referenced by ast_pbx_outgoing_app(), and ast_pbx_outgoing_exten().

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

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

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

Definition at line 4960 of file pbx.c.

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

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

enum ast_pbx_result ast_pbx_run ( struct ast_channel c  ) 

Execute the PBX in the current thread.

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

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

02638 {
02639    enum ast_pbx_result res = AST_PBX_SUCCESS;
02640 
02641    if (increase_call_count(c))
02642       return AST_PBX_CALL_LIMIT;
02643 
02644    res = __ast_pbx_run(c);
02645    decrease_call_count();
02646 
02647    return res;
02648 }

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

run the application and free the descriptor once done

Definition at line 5100 of file pbx.c.

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

Referenced by ast_pbx_outgoing_app().

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

enum ast_pbx_result ast_pbx_start ( struct ast_channel c  ) 

Create a new thread and start the PBX.

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

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

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

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

Dynamically register a new dial plan application.

Register an application.

Definition at line 2939 of file pbx.c.

Referenced by load_module(), and load_pbx().

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

int ast_register_switch ( struct ast_switch sw  ) 

Register an alternative dialplan switch.

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

Referenced by load_module().

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

static int ast_remove_hint ( struct ast_exten e  )  [static]

ast_remove_hint: Remove hint from extension

Definition at line 2207 of file pbx.c.

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

Referenced by destroy_exten().

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

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

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

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

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

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

int ast_unlock_context ( struct ast_context con  ) 

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

Definition at line 6079 of file pbx.c.

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

06080 {
06081    return ast_mutex_unlock(&con->lock);
06082 }

int ast_unlock_contexts ( void   ) 

Unlocks contexts.

Return values:
0 on success
-1 on failure

Definition at line 6066 of file pbx.c.

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

06067 {
06068    return ast_mutex_unlock(&conlock);
06069 }

int ast_unregister_application ( const char *  app  ) 

Unregister an application.

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

Referenced by __unload_module(), and unload_module().

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

void ast_unregister_switch ( struct ast_switch sw  ) 

Unregister an alternative switch.

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

Returns:
nothing

Definition at line 3007 of file pbx.c.

Referenced by __unload_module(), and unload_module().

03008 {
03009    AST_LIST_LOCK(&switches);
03010    AST_LIST_REMOVE(&switches, sw, list);
03011    AST_LIST_UNLOCK(&switches);
03012 }

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

Definition at line 6188 of file pbx.c.

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

06190 {
06191    if (!exten)
06192       return con ? con->root : NULL;
06193    else
06194       return exten->next;
06195 }

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

Definition at line 6221 of file pbx.c.

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

06223 {
06224    if (!ip)
06225       return con ? con->ignorepats : NULL;
06226    else
06227       return ip->next;
06228 }

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

Definition at line 6212 of file pbx.c.

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

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

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

Definition at line 6197 of file pbx.c.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06199 {
06200    if (!sw)
06201       return con ? AST_LIST_FIRST(&con->alts) : NULL;
06202    else
06203       return AST_LIST_NEXT(sw, list);
06204 }

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

Definition at line 6183 of file pbx.c.

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

06184 {
06185    return con ? con->next : contexts;
06186 }

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

Definition at line 6206 of file pbx.c.

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

06208 {
06209    return priority ? priority->peer : exten;
06210 }

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

Definition at line 4872 of file pbx.c.

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

Referenced by ast_pbx_outgoing_app(), and ast_pbx_outgoing_exten().

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

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

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

Definition at line 2302 of file pbx.c.

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

Referenced by __ast_pbx_run().

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

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

Definition at line 3065 of file pbx.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, and strdup.

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

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

Definition at line 3426 of file pbx.c.

References ast_cli_complete().

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

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

Definition at line 3419 of file pbx.c.

References ast_cli_complete().

03420 {
03421    static char* choices[] = { "like", "describing", NULL };
03422 
03423    return (pos != 2) ? NULL : ast_cli_complete(word, choices, state);
03424 }

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

Definition at line 3436 of file pbx.c.

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

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

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

Definition at line 1407 of file pbx.c.

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

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

static void decrease_call_count ( void   )  [static]

Definition at line 2573 of file pbx.c.

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

Referenced by ast_pbx_run(), and pbx_thread().

02574 {
02575    ast_mutex_lock(&maxcalllock);
02576    if (countcalls > 0)
02577       countcalls--;
02578    ast_mutex_unlock(&maxcalllock);
02579 }

static void destroy_exten ( struct ast_exten e  )  [static]

Definition at line 2581 of file pbx.c.

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

Referenced by __ast_context_destroy(), and ast_context_remove_extension2().

02582 {
02583    if (e->priority == PRIORITY_HINT)
02584       ast_remove_hint(e);
02585 
02586    if (e->datad)
02587       e->datad(e->data);
02588    free(e);
02589 }

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

the full routine to compare extensions in rules.

Definition at line 717 of file pbx.c.

References ext_cmp1().

Referenced by ast_add_extension2().

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

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

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

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

Definition at line 645 of file pbx.c.

References ast_log(), and LOG_WARNING.

Referenced by ext_cmp().

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

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

copy a string skipping whitespace

Definition at line 4624 of file pbx.c.

Referenced by ast_add_extension2().

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

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

Definition at line 866 of file pbx.c.

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

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

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

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

Definition at line 2665 of file pbx.c.

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

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

02666 {
02667    struct ast_context *c = NULL;
02668 
02669    ast_lock_contexts();
02670    while ( (c = ast_walk_contexts(c)) ) {
02671       if (!strcmp(ast_get_context_name(c), context))
02672          return c;
02673    }
02674    ast_unlock_contexts();
02675 
02676    return NULL;
02677 }

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

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

Definition at line 1500 of file pbx.c.

References ast_log(), and LOG_WARNING.

Referenced by ast_func_read(), and ast_func_write().

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

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

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

Definition at line 4046 of file pbx.c.

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

Referenced by ast_build_timing().

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

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

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

Definition at line 4092 of file pbx.c.

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

Referenced by ast_build_timing().

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

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

Definition at line 3721 of file pbx.c.

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

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

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

CLI support for setting global variables.

Definition at line 3709 of file pbx.c.

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

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

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

Definition at line 3155 of file pbx.c.

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

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

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

Definition at line 3085 of file pbx.c.

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

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

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

Definition at line 3350 of file pbx.c.

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

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

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

Definition at line 3282 of file pbx.c.

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

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

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

Definition at line 3636 of file pbx.c.

References ast_cli(), AST_PBX_MAX_STACK, ast_strdupa, ast_strlen_zero(), context, dialplan_counters::context_existence, exten, dialplan_counters::extension_existence, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, show_dialplan_helper(), strsep(), dialplan_counters::total_context, dialplan_counters::total_exten, and dialplan_counters::total_prio.

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

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

Definition at line 1351 of file pbx.c.

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

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

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

Definition at line 1295 of file pbx.c.

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

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

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

Definition at line 1267 of file pbx.c.

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

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

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

Definition at line 1240 of file pbx.c.

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

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

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

CLI support for listing global variables in a parseable way.

Definition at line 3692 of file pbx.c.

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

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

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

handle_show_hints: CLI support for listing registred dial plan hints

Definition at line 3226 of file pbx.c.

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

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

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

handle_show_switches: CLI support for listing registred dial plan switches

Definition at line 3258 of file pbx.c.

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

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

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

Definition at line 576 of file pbx.c.

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

Referenced by pbx_find_extension().

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

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

Definition at line 2548 of file pbx.c.

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

Referenced by ast_pbx_run(), and ast_pbx_start().

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

int load_pbx ( void   ) 

Provided by pbx.c

Definition at line 6035 of file pbx.c.

Referenced by main().

06036 {
06037    int x;
06038 
06039    /* Initialize the PBX */
06040    if (option_verbose) {
06041       ast_verbose( "Asterisk PBX Core Initializing\n");
06042       ast_verbose( "Registering builtin applications:\n");
06043    }
06044    ast_cli_register_multiple(pbx_cli, sizeof(pbx_cli) / sizeof(struct ast_cli_entry));
06045 
06046    /* Register builtin applications */
06047    for (x=0; x<sizeof(builtins) / sizeof(struct pbx_builtin); x++) {
06048       if (option_verbose)
06049          ast_verbose( VERBOSE_PREFIX_1 "[%s]\n", builtins[x].name);
06050       if (ast_register_application(builtins[x].name, builtins[x].execute, builtins[x].synopsis, builtins[x].description)) {
06051          ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name);
06052          return -1;
06053       }
06054    }
06055    return 0;
06056 }

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

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

Definition at line 4028 of file pbx.c.

Referenced by get_range().

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

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

Definition at line 908 of file pbx.c.

References ast_extension_match(), and ast_strlen_zero().

Referenced by pbx_find_extension().

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

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

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

Definition at line 1060 of file pbx.c.

Referenced by pbx_retrieve_variable(), and pbx_substitute_variables_helper_full().

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

void pbx_builtin_clear_globals ( void   ) 

Definition at line 5937 of file pbx.c.

Referenced by handle_reload_extensions(), and reload().

05938 {
05939    struct ast_var_t *vardata;
05940 
05941    ast_mutex_lock(&globalslock);
05942    while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries)))
05943       ast_var_delete(vardata);
05944    ast_mutex_unlock(&globalslock);
05945 }

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

Definition at line 5737 of file pbx.c.

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

05738 {
05739    struct ast_var_t *variables;
05740    const char *ret = NULL;
05741    int i;
05742    struct varshead *places[2] = { NULL, &globals };
05743 
05744    if (!name)
05745       return NULL;
05746    if (chan)
05747       places[0] = &chan->varshead;
05748 
05749    for (i = 0; i < 2; i++) {
05750       if (!places[i])
05751          continue;
05752       if (places[i] == &globals)
05753          ast_mutex_lock(&globalslock);
05754       AST_LIST_TRAVERSE(places[i], variables, entries) {
05755          if (!strcmp(name, ast_var_name(variables))) {
05756             ret = ast_var_value(variables);
05757             break;
05758          }
05759       }
05760       if (places[i] == &globals)
05761          ast_mutex_unlock(&globalslock);
05762       if (ret)
05763          break;
05764    }
05765 
05766    return ret;
05767 }

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

Definition at line 5957 of file pbx.c.

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

05958 {
05959    char *condition, *branch1, *branch2, *branch;
05960    int rc;
05961    char *stringp;
05962 
05963    if (ast_strlen_zero(data)) {
05964       ast_log(LOG_WARNING, "Ignoring, since there is no variable to check\n");
05965       return 0;
05966    }
05967 
05968    stringp = ast_strdupa(data);
05969    condition = strsep(&stringp,"?");
05970    branch1 = strsep(&stringp,":");
05971    branch2 = strsep(&stringp,"");
05972    branch = pbx_checkcondition(condition) ? branch1 : branch2;
05973 
05974    if (ast_strlen_zero(branch)) {
05975       if (option_debug)
05976          ast_log(LOG_DEBUG, "Not taking any branch\n");
05977       return 0;
05978    }
05979 
05980    rc = pbx_builtin_goto(chan, branch);
05981 
05982    return rc;
05983 }

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

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

Definition at line 5876 of file pbx.c.

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

05877 {
05878    char *name;
05879    char *value;
05880    char *channel;
05881    char tmp[VAR_BUF_SIZE]="";
05882 
05883    if (ast_strlen_zero(data)) {
05884       ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n");
05885       return 0;
05886    }
05887 
05888    value = ast_strdupa(data);
05889    name = strsep(&value,"=");
05890    channel = strsep(&value,"|");
05891    if (channel && value && name) { /*! \todo XXX should do !ast_strlen_zero(..) of the args ? */
05892       struct ast_channel *chan2 = ast_get_channel_by_name_locked(channel);
05893       if (chan2) {
05894          char *s = alloca(strlen(value) + 4);
05895          if (s) {
05896             sprintf(s, "${%s}", value);
05897             pbx_substitute_variables_helper(chan2, s, tmp, sizeof(tmp) - 1);
05898          }
05899          ast_channel_unlock(chan2);
05900       }
05901       pbx_builtin_setvar_helper(chan, name, tmp);
05902    }
05903 
05904    return(0);
05905 }

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

Definition at line 5932 of file pbx.c.

05933 {
05934    return 0;
05935 }

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

Definition at line 5769 of file pbx.c.

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

05770 {
05771    struct ast_var_t *newvariable;
05772    struct varshead *headp;
05773 
05774    if (name[strlen(name)-1] == ')') {
05775       char *function = ast_strdupa(name);
05776 
05777       ast_log(LOG_WARNING, "Cannot push a value onto a function\n");
05778       ast_func_write(chan, function, value);
05779       return;
05780    }
05781 
05782    headp = (chan) ? &chan->varshead : &globals;
05783 
05784    if (value) {
05785       if ((option_verbose > 1) && (headp == &globals))
05786          ast_verbose(VERBOSE_PREFIX_2 "Setting global variable '%s' to '%s'\n", name, value);
05787       newvariable = ast_var_assign(name, value);
05788       if (headp == &globals)
05789          ast_mutex_lock(&globalslock);
05790       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
05791       if (headp == &globals)
05792          ast_mutex_unlock(&globalslock);
05793    }
05794 }

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

Definition at line 6017 of file pbx.c.

References ast_say_character_str().

06018 {
06019    int res = 0;
06020 
06021    if (data)
06022       res = ast_say_character_str(chan, data, "", chan->language);
06023    return res;
06024 }

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

Definition at line 6008 of file pbx.c.

References ast_say_digit_str().

06009 {
06010    int res = 0;
06011 
06012    if (data)
06013       res = ast_say_digit_str(chan, data, "", chan->language);
06014    return res;
06015 }

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

Definition at line 5985 of file pbx.c.

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

05986 {
05987    char tmp[256];
05988    char *number = tmp;
05989    char *options;
05990 
05991    if (ast_strlen_zero(data)) {
05992       ast_log(LOG_WARNING, "SayNumber requires an argument (number)\n");
05993       return -1;
05994    }
05995    ast_copy_string(tmp, data, sizeof(tmp));
05996    strsep(&number, "|");
05997    options = strsep(&number, "|");
05998    if (options) {
05999       if ( strcasecmp(options, "f") && strcasecmp(options,"m") &&
06000          strcasecmp(options, "c") && strcasecmp(options, "n") ) {
06001          ast_log(LOG_WARNING, "SayNumber gender option is either 'f', 'm', 'c' or 'n'\n");
06002          return -1;
06003       }
06004    }
06005    return ast_say_number(chan, atoi(tmp), "", chan->language, options);
06006 }

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

Definition at line 6026 of file pbx.c.

References ast_say_phonetic_str().

06027 {
06028    int res = 0;
06029 
06030    if (data)
06031       res = ast_say_phonetic_str(chan, data, "", chan->language);
06032    return res;
06033 }

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

Definition at line 5710 of file pbx.c.

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

05711 {
05712    struct ast_var_t *variables;
05713    const char *var, *val;
05714    int total = 0;
05715 
05716    if (!chan)
05717       return 0;
05718 
05719    memset(buf, 0, size);
05720 
05721    AST_LIST_TRAVERSE(&chan->varshead, variables, entries) {
05722       if ((var=ast_var_name(variables)) && (val=ast_var_value(variables))
05723          /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */
05724          ) {
05725          if (ast_build_string(&buf, &size, "%s=%s\n", var, val)) {
05726             ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
05727             break;
05728          } else
05729             total++;
05730       } else
05731          break;
05732    }
05733 
05734    return total;
05735 }

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

Todo:
XXX overwrites data ?

Todo:
XXX watch out, leading whitespace ?

Definition at line 5908 of file pbx.c.

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

05909 {
05910    char *name;
05911    char *stringp = data;
05912    static int dep_warning = 0;
05913 
05914    if (ast_strlen_zero(data)) {
05915       ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n");
05916       return 0;
05917    }
05918 
05919    name = strsep(&stringp, "=");
05920 
05921    if (!dep_warning) {
05922       dep_warning = 1;
05923       ast_log(LOG_WARNING, "SetGlobalVar is deprecated.  Please use Set(GLOBAL(%s)=%s) instead.\n", name, stringp);
05924    }
05925 
05926    /*! \todo XXX watch out, leading whitespace ? */
05927    pbx_builtin_setvar_helper(NULL, name, stringp);
05928 
05929    return(0);
05930 }

int pbx_builtin_setvar ( struct ast_channel chan,
void *  data 
)

Definition at line 5841 of file pbx.c.

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

Referenced by ast_compile_ael2().

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

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

Definition at line 5796 of file pbx.c.

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

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

int pbx_checkcondition ( const char *  condition  ) 

Evaluate a condition.

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

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

05948 {
05949    if (ast_strlen_zero(condition))  /* NULL or empty strings are false */
05950       return 0;
05951    else if (*condition >= '0' && *condition <= '9')   /* Numbers are evaluated for truth */
05952       return atoi(condition);
05953    else  /* Strings are true */
05954       return 1;
05955 }

static void pbx_destroy ( struct ast_pbx p  )  [static]

Definition at line 584 of file pbx.c.

References free.

Referenced by __ast_pbx_run().

00585 {
00586    free(p);
00587 }

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

Execute an application.

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

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

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

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

The return value depends on the action:.

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

Definition at line 1771 of file pbx.c.

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

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

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

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

Definition at line 935 of file pbx.c.

References AST_LIST_TRAVERSE, ast_log(), AST_PBX_MAX_STACK, ast_walk_context_extensions(), ast_walk_contexts(), ast_walk_extension_priorities(), ast_switch::canmatch, ast_exten::cidmatch, ast_sw::data, pbx_find_info::data, E_CANMATCH, E_FINDLABEL, E_MATCHMORE, ast_sw::eval, ast_switch::exists, ast_exten::exten, extension_match_core(), pbx_find_info::foundcontext, include_valid(), ast_context::includes, pbx_find_info::incstack, ast_exten::label, LOG_WARNING, match(), matchcid(), ast_exten::matchcid, ast_switch::matchmore, ast_sw::name, ast_include::next, pbx_findswitch(), pbx_substitute_variables_helper(), ast_exten::priority, ast_include::rname, pbx_find_info::stacklen, pbx_find_info::status, STATUS_NO_CONTEXT, STATUS_NO_EXTENSION, STATUS_NO_LABEL, STATUS_NO_PRIORITY, STATUS_SUCCESS, SWITCH_DATA_LENGTH, and pbx_find_info::swo.

Referenced by ast_hint_extension(), and pbx_extension_helper().

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

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

Find application handle in linked list.

Look up an application.

Definition at line 548 of file pbx.c.

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

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

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

Definition at line 562 of file pbx.c.

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

Referenced by pbx_find_extension().

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

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

pbx_retrieve_variable: Support for Asterisk built-in variables ---

Definition at line 1128 of file pbx.c.

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

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

int pbx_set_autofallthrough ( int  newval  ) 

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

Definition at line 2655 of file pbx.c.

Referenced by pbx_load_module().

02656 {
02657    int oldval = autofallthrough;
02658    autofallthrough = newval;
02659    return oldval;
02660 }

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

Definition at line 1749 of file pbx.c.

References ast_exten::data, and pbx_substitute_variables_helper().

Referenced by pbx_extension_helper().

01750 {
01751    memset(passdata, 0, datalen);
01752 
01753    /* No variables or expressions in e->data, so why scan it? */
01754    if (e->data && !strchr(e->data, '$') && !strstr(e->data,"${") && !strstr(e->data,"$[") && !strstr(e->data,"$(")) {
01755       ast_copy_string(passdata, e->data, datalen);
01756       return;
01757    }
01758 
01759    pbx_substitute_variables_helper(c, e->data, passdata, datalen - 1);
01760 }

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

Definition at line 1739 of file pbx.c.

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

01740 {
01741    pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count);
01742 }

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

Definition at line 1546 of file pbx.c.

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

Referenced by pbx_substitute_variables_helper(), and pbx_substitute_variables_varshead().

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

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

Definition at line 1744 of file pbx.c.

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

01745 {
01746    pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count);
01747 }

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

Definition at line 2591 of file pbx.c.

References __ast_pbx_run(), and decrease_call_count().

Referenced by ast_pbx_start().

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

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

helper function to print an extension

Definition at line 3474 of file pbx.c.

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

Referenced by show_dialplan_helper().

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

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

Definition at line 2292 of file pbx.c.

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

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

02293 {
02294    ast_copy_string(c->exten, exten, sizeof(c->exten));
02295    c->priority = pri;
02296 }

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

Definition at line 3488 of file pbx.c.

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

Referenced by handle_show_dialplan().

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

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

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

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

Definition at line 1090 of file pbx.c.

Referenced by pbx_retrieve_variable(), and pbx_substitute_variables_helper_full().

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

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

Definition at line 5325 of file pbx.c.

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

Referenced by pbx_builtin_busy(), and pbx_builtin_congestion().

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


Variable Documentation

int autofallthrough = 1 [static]

Definition at line 243 of file pbx.c.

Referenced by __ast_pbx_run(), and 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 3777 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 3767 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 3737 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 3772 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 3762 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 3742 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 3757 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 3752 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 3747 of file pbx.c.

struct ast_context* contexts [static]

Definition at line 490 of file pbx.c.

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

int countcalls [static]

Definition at line 246 of file pbx.c.

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

char* days[] [static]

Definition at line 4177 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 241 of file pbx.c.

Referenced by ast_add_extension2(), handle_show_globals(), pbx_builtin_clear_globals(), pbx_builtin_getvar_helper(), pbx_builtin_pushvar_helper(), pbx_builtin_setvar_helper(), and pbx_retrieve_variable().

char* months[] [static]

Definition at line 4189 of file pbx.c.

Referenced by ast_build_timing().

struct ast_cli_entry pbx_cli[] [static]

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

char show_dialplan_help[] [static]

Initial value:

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

Definition at line 3047 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 3043 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 3023 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 3035 of file pbx.c.

char show_hints_help[] [static]

Initial value:

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

Definition at line 3031 of file pbx.c.

char show_switches_help[] [static]

Initial value:

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

Definition at line 3027 of file pbx.c.

struct ast_state_cb* statecbs

Definition at line 505 of file pbx.c.

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

int stateid = 1 [static]

Definition at line 497 of file pbx.c.

Referenced by ast_extension_state_add().


Generated on Wed Aug 15 01:25:23 2007 for Asterisk - the Open Source PBX by  doxygen 1.5.3