Sat Apr 12 07:12:50 2008

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

Variables

static int autofallthrough = 1
static struct pbx_builtin builtins []
static struct ast_cli_entry cli_set_global_deprecated
static struct ast_cli_entry cli_show_application_deprecated
static struct ast_cli_entry cli_show_applications_deprecated
static struct ast_cli_entry cli_show_dialplan_deprecated
static struct ast_cli_entry cli_show_function_deprecated
static struct ast_cli_entry cli_show_functions_deprecated
static struct ast_cli_entry cli_show_globals_deprecated
static struct ast_cli_entry cli_show_hints_deprecated
static struct ast_cli_entry cli_show_switches_deprecated
static struct ast_contextcontexts
static int countcalls
static char * days []
static struct cfextension_states extension_states []
static struct varshead globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE
static char * months []
static struct ast_cli_entry pbx_cli []
static char set_global_help []
static char show_application_help []
static char show_applications_help []
static char show_dialplan_help []
static char show_function_help []
static char show_functions_help []
static char show_globals_help []
static char show_hints_help []
static char show_switches_help []
struct ast_state_cbstatecbs
static int stateid = 1


Detailed Description

Core PBX routines.

Author:
Mark Spencer <markster@digium.com>

Definition in file pbx.c.


Define Documentation

#define AST_PBX_MAX_STACK   128

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

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

Referenced by pbx_extension_helper(), and pbx_find_extension().

#define STATUS_NO_EXTENSION   2

Definition at line 907 of file pbx.c.

Referenced by pbx_extension_helper(), and pbx_find_extension().

#define STATUS_NO_LABEL   4

Definition at line 909 of file pbx.c.

Referenced by pbx_extension_helper(), and pbx_find_extension().

#define STATUS_NO_PRIORITY   3

Definition at line 908 of file pbx.c.

Referenced by pbx_extension_helper(), and pbx_find_extension().

#define STATUS_SUCCESS   5

Definition at line 910 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

#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

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

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

Referenced by ast_context_create(), and ast_context_find_or_create().

03861 {
03862    struct ast_context *tmp, **local_contexts;
03863    int length = sizeof(struct ast_context) + strlen(name) + 1;
03864 
03865    if (!extcontexts) {
03866       ast_rdlock_contexts();
03867       local_contexts = &contexts;
03868    } else
03869       local_contexts = extcontexts;
03870 
03871    for (tmp = *local_contexts; tmp; tmp = tmp->next) {
03872       if (!strcasecmp(tmp->name, name)) {
03873          if (!existsokay) {
03874             ast_log(LOG_WARNING, "Tried to register context '%s', already in use\n", name);
03875             tmp = NULL;
03876          }
03877          if (!extcontexts)
03878             ast_unlock_contexts();
03879          return tmp;
03880       }
03881    }
03882    
03883    if (!extcontexts)
03884       ast_unlock_contexts();
03885 
03886    if ((tmp = ast_calloc(1, length))) {
03887       ast_mutex_init(&tmp->lock);
03888       ast_mutex_init(&tmp->macrolock);
03889       strcpy(tmp->name, name);
03890       tmp->registrar = registrar;
03891       if (!extcontexts)
03892          ast_wrlock_contexts();
03893       tmp->next = *local_contexts;
03894       *local_contexts = tmp;
03895       if (!extcontexts)
03896          ast_unlock_contexts();
03897       if (option_debug)
03898          ast_log(LOG_DEBUG, "Registered context '%s'\n", tmp->name);
03899       if (option_verbose > 2)
03900          ast_verbose( VERBOSE_PREFIX_3 "Registered extension context '%s'\n", tmp->name);
03901    }
03902 
03903    return tmp;
03904 }

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

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

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

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

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

06337 {
06338    int (*goto_func)(struct ast_channel *chan, const char *context, const char *exten, int priority);
06339 
06340    if (!chan)
06341       return -2;
06342 
06343    if (context == NULL)
06344       context = chan->context;
06345    if (exten == NULL)
06346       exten = chan->exten;
06347 
06348    goto_func = (async) ? ast_async_goto : ast_explicit_goto;
06349    if (ast_exists_extension(chan, context, exten, priority, chan->cid.cid_num))
06350       return goto_func(chan, context, exten, priority);
06351    else
06352       return -3;
06353 }

static int __ast_pbx_run ( struct ast_channel c  )  [static]

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

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

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

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

int ast_active_calls ( void   ) 

Retrieve the number of active calls.

Definition at line 2670 of file pbx.c.

References countcalls.

Referenced by handle_chanlist(), and handle_chanlist_deprecated().

02671 {
02672    return countcalls;
02673 }

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

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

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

04557 {
04558    int ret = -1;
04559    struct ast_context *c = find_context_locked(context);
04560 
04561    if (c) {
04562       ret = ast_add_extension2(c, replace, extension, priority, label, callerid,
04563          application, data, datad, registrar);
04564       ast_unlock_contexts();
04565    }
04566    return ret;
04567 }

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

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

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

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

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

02171 {
02172    struct ast_hint *hint;
02173 
02174    if (!e)
02175       return -1;
02176 
02177    AST_LIST_LOCK(&hints);
02178 
02179    /* Search if hint exists, do nothing */
02180    AST_LIST_TRAVERSE(&hints, hint, list) {
02181       if (hint->exten == e) {
02182          AST_LIST_UNLOCK(&hints);
02183          if (option_debug > 1)
02184             ast_log(LOG_DEBUG, "HINTS: Not re-adding existing hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e));
02185          return -1;
02186       }
02187    }
02188 
02189    if (option_debug > 1)
02190       ast_log(LOG_DEBUG, "HINTS: Adding hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e));
02191 
02192    if (!(hint = ast_calloc(1, sizeof(*hint)))) {
02193       AST_LIST_UNLOCK(&hints);
02194       return -1;
02195    }
02196    /* Initialize and insert new item at the top */
02197    hint->exten = e;
02198    hint->laststate = ast_extension_state2(e);
02199    AST_LIST_INSERT_HEAD(&hints, hint, list);
02200 
02201    AST_LIST_UNLOCK(&hints);
02202    return 0;
02203 }

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

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

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

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

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

Definition at line 4638 of file pbx.c.

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

04639 {
04640    struct ast_channel *chan;
04641    int res = -1;
04642 
04643    chan = ast_get_channel_by_name_locked(channame);
04644    if (chan) {
04645       res = ast_async_goto(chan, context, exten, priority);
04646       ast_channel_unlock(chan);
04647    }
04648    return res;
04649 }

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

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

Definition at line 6360 of file pbx.c.

References __ast_goto_if_exists().

Referenced by asyncgoto_exec().

06361 {
06362    return __ast_goto_if_exists(chan, context, exten, priority, 1);
06363 }

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

Definition at line 4230 of file pbx.c.

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

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

04231 {
04232    char info_save[256];
04233    char *info;
04234 
04235    /* Check for empty just in case */
04236    if (ast_strlen_zero(info_in))
04237       return 0;
04238    /* make a copy just in case we were passed a static string */
04239    ast_copy_string(info_save, info_in, sizeof(info_save));
04240    info = info_save;
04241    /* Assume everything except time */
04242    i->monthmask = 0xfff;   /* 12 bits */
04243    i->daymask = 0x7fffffffU; /* 31 bits */
04244    i->dowmask = 0x7f; /* 7 bits */
04245    /* on each call, use strsep() to move info to the next argument */
04246    get_timerange(i, strsep(&info, "|"));
04247    if (info)
04248       i->dowmask = get_range(strsep(&info, "|"), 7, days, "day of week");
04249    if (info)
04250       i->daymask = get_range(strsep(&info, "|"), 31, NULL, "day");
04251    if (info)
04252       i->monthmask = get_range(strsep(&info, "|"), 12, months, "month");
04253    return 1;
04254 }

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

References E_CANMATCH, and pbx_extension_helper().

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

02295 {
02296    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH);
02297 }

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

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

Referenced by add_pri().

02207 {
02208    struct ast_hint *hint;
02209    int res = -1;
02210 
02211    AST_LIST_LOCK(&hints);
02212    AST_LIST_TRAVERSE(&hints, hint, list) {
02213       if (hint->exten == oe) {
02214             hint->exten = ne;
02215          res = 0;
02216          break;
02217       }
02218    }
02219    AST_LIST_UNLOCK(&hints);
02220 
02221    return res;
02222 }

int ast_check_timing ( const struct ast_timing i  ) 

Definition at line 4256 of file pbx.c.

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

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

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

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

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

Referenced by handle_context_add_ignorepat(), and handle_context_add_ignorepat_deprecated().

04491 {
04492    int ret = -1;
04493    struct ast_context *c = find_context_locked(context);
04494 
04495    if (c) {
04496       ret = ast_context_add_ignorepat2(c, value, registrar);
04497       ast_unlock_contexts();
04498    }
04499    return ret;
04500 }

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

Definition at line 4502 of file pbx.c.

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

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

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

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

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

Referenced by handle_context_add_include(), and handle_context_add_include_deprecated().

04037 {
04038    int ret = -1;
04039    struct ast_context *c = find_context_locked(context);
04040 
04041    if (c) {
04042       ret = ast_context_add_include2(c, include, registrar);
04043       ast_unlock_contexts();
04044    }
04045    return ret;
04046 }

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

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

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

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

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

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

04361 {
04362    int ret = -1;
04363    struct ast_context *c = find_context_locked(context);
04364 
04365    if (c) { /* found, add switch to this context */
04366       ret = ast_context_add_switch2(c, sw, data, eval, registrar);
04367       ast_unlock_contexts();
04368    }
04369    return ret;
04370 }

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

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

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

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

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

References __ast_context_create().

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

03907 {
03908    return __ast_context_create(extcontexts, name, registrar, 0);
03909 }

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

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

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

05358 {
05359    ast_wrlock_contexts();
05360    __ast_context_destroy(con,registrar);
05361    ast_unlock_contexts();
05362 }

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.

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

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

00891 {
00892    struct ast_context *tmp = NULL;
00893 
00894    ast_rdlock_contexts();
00895 
00896    while ( (tmp = ast_walk_contexts(tmp)) ) {
00897       if (!name || !strcasecmp(name, tmp->name))
00898          break;
00899    }
00900 
00901    ast_unlock_contexts();
00902 
00903    return tmp;
00904 }

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

Definition at line 3911 of file pbx.c.

References __ast_context_create().

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

03912 {
03913    return __ast_context_create(extcontexts, name, registrar, 1);
03914 }

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

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

Referenced by _macro_exec().

02908 {
02909    struct ast_context *c = NULL;
02910    int ret = -1;
02911 
02912    ast_rdlock_contexts();
02913 
02914    while ((c = ast_walk_contexts(c))) {
02915       if (!strcmp(ast_get_context_name(c), context)) {
02916          ret = 0;
02917          break;
02918       }
02919    }
02920 
02921    ast_unlock_contexts();
02922 
02923    /* if we found context, lock macrolock */
02924    if (ret == 0) 
02925       ret = ast_mutex_lock(&c->macrolock);
02926 
02927    return ret;
02928 }

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

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

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

02809 {
02810    int ret = -1; /* default error return */
02811    struct ast_context *c = find_context_locked(context);
02812 
02813    if (c) { /* ... remove extension ... */
02814       ret = ast_context_remove_extension2(c, extension, priority, registrar);
02815       ast_unlock_contexts();
02816    }
02817    return ret;
02818 }

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

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

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

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

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

Definition at line 4447 of file pbx.c.

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

Referenced by handle_context_remove_ignorepat(), and handle_context_remove_ignorepat_deprecated().

04448 {
04449    int ret = -1;
04450    struct ast_context *c = find_context_locked(context);
04451 
04452    if (c) {
04453       ret = ast_context_remove_ignorepat2(c, ignorepat, registrar);
04454       ast_unlock_contexts();
04455    }
04456    return ret;
04457 }

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

Definition at line 4459 of file pbx.c.

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

Referenced by ast_context_remove_ignorepat().

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

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

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

Referenced by handle_context_dont_include_deprecated(), and handle_context_remove_include().

02705 {
02706    int ret = -1;
02707    struct ast_context *c = find_context_locked(context);
02708 
02709    if (c) {
02710       /* found, remove include from this context ... */
02711       ret = ast_context_remove_include2(c, include, registrar);
02712       ast_unlock_contexts();
02713    }
02714    return ret;
02715 }

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

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

Referenced by ast_context_remove_include().

02726 {
02727    struct ast_include *i, *pi = NULL;
02728    int ret = -1;
02729 
02730    ast_mutex_lock(&con->lock);
02731 
02732    /* find our include */
02733    for (i = con->includes; i; pi = i, i = i->next) {
02734       if (!strcmp(i->name, include) &&
02735             (!registrar || !strcmp(i->registrar, registrar))) {
02736          /* remove from list */
02737          if (pi)
02738             pi->next = i->next;
02739          else
02740             con->includes = i->next;
02741          /* free include and return */
02742          free(i);
02743          ret = 0;
02744          break;
02745       }
02746    }
02747 
02748    ast_mutex_unlock(&con->lock);
02749    return ret;
02750 }

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

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

02758 {
02759    int ret = -1; /* default error return */
02760    struct ast_context *c = find_context_locked(context);
02761 
02762    if (c) {
02763       /* remove switch from this context ... */
02764       ret = ast_context_remove_switch2(c, sw, data, registrar);
02765       ast_unlock_contexts();
02766    }
02767    return ret;
02768 }

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

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

Referenced by ast_context_remove_switch().

02779 {
02780    struct ast_sw *i;
02781    int ret = -1;
02782 
02783    ast_mutex_lock(&con->lock);
02784 
02785    /* walk switches */
02786    AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) {
02787       if (!strcmp(i->name, sw) && !strcmp(i->data, data) &&
02788          (!registrar || !strcmp(i->registrar, registrar))) {
02789          /* found, remove from list */
02790          AST_LIST_REMOVE_CURRENT(&con->alts, list);
02791          free(i); /* free switch and return */
02792          ret = 0;
02793          break;
02794       }
02795    }
02796    AST_LIST_TRAVERSE_SAFE_END
02797 
02798    ast_mutex_unlock(&con->lock);
02799 
02800    return ret;
02801 }

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

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

Referenced by _macro_exec().

02936 {
02937    struct ast_context *c = NULL;
02938    int ret = -1;
02939 
02940    ast_rdlock_contexts();
02941 
02942    while ((c = ast_walk_contexts(c))) {
02943       if (!strcmp(ast_get_context_name(c), context)) {
02944          ret = 0;
02945          break;
02946       }
02947    }
02948 
02949    ast_unlock_contexts();
02950 
02951    /* if we found context, unlock macrolock */
02952    if (ret == 0) 
02953       ret = ast_mutex_unlock(&c->macrolock);
02954 
02955    return ret;
02956 }

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

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

Referenced by pbx_load_module().

06322 {
06323    struct ast_include *inc = NULL;
06324    int res = 0;
06325 
06326    while ( (inc = ast_walk_context_includes(con, inc)) )
06327       if (!ast_context_find(inc->rname)) {
06328          res = -1;
06329          ast_log(LOG_WARNING, "Context '%s' tries includes nonexistent context '%s'\n",
06330                ast_get_context_name(con), inc->rname);
06331       }
06332    return res;
06333 }

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

Definition at line 1443 of file pbx.c.

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

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

01444 {
01445    struct ast_custom_function *acf = NULL;
01446 
01447    AST_LIST_LOCK(&acf_root);
01448    AST_LIST_TRAVERSE(&acf_root, acf, acflist) {
01449       if (!strcmp(name, acf->name))
01450          break;
01451    }
01452    AST_LIST_UNLOCK(&acf_root);
01453 
01454    return acf;
01455 }

int ast_custom_function_register ( struct ast_custom_function acf  ) 

Reigster a custom function.

Definition at line 1479 of file pbx.c.

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

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

01480 {
01481    struct ast_custom_function *cur;
01482 
01483    if (!acf)
01484       return -1;
01485 
01486    AST_LIST_LOCK(&acf_root);
01487 
01488    if (ast_custom_function_find(acf->name)) {
01489       ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name);
01490       AST_LIST_UNLOCK(&acf_root);
01491       return -1;
01492    }
01493 
01494    /* Store in alphabetical order */
01495    AST_LIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) {
01496       if (strcasecmp(acf->name, cur->name) < 0) {
01497          AST_LIST_INSERT_BEFORE_CURRENT(&acf_root, acf, acflist);
01498          break;
01499       }
01500    }
01501    AST_LIST_TRAVERSE_SAFE_END
01502    if (!cur)
01503       AST_LIST_INSERT_TAIL(&acf_root, acf, acflist);
01504 
01505    AST_LIST_UNLOCK(&acf_root);
01506 
01507    if (option_verbose > 1)
01508       ast_verbose(VERBOSE_PREFIX_2 "Registered custom function %s\n", acf->name);
01509 
01510    return 0;
01511 }

int ast_custom_function_unregister ( struct ast_custom_function acf  ) 

Unregister a custom function.

Definition at line 1457 of file pbx.c.

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

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

01458 {
01459    struct ast_custom_function *cur;
01460 
01461    if (!acf)
01462       return -1;
01463 
01464    AST_LIST_LOCK(&acf_root);
01465    AST_LIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) {
01466       if (cur == acf) {
01467          AST_LIST_REMOVE_CURRENT(&acf_root, acflist);
01468          if (option_verbose > 1)
01469             ast_verbose(VERBOSE_PREFIX_2 "Unregistered custom function %s\n", acf->name);
01470          break;
01471       }
01472    }
01473    AST_LIST_TRAVERSE_SAFE_END
01474    AST_LIST_UNLOCK(&acf_root);
01475 
01476    return acf ? 0 : -1;
01477 }

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

References E_MATCH, and pbx_extension_helper().

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

02280 {
02281    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH);
02282 }

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

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

Definition at line 4569 of file pbx.c.

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

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

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

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

Definition at line 883 of file pbx.c.

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

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.

References E_MATCH, and extension_match_core().

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

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

References ast_extension_state2(), and ast_hint_extension().

Referenced by action_extensionstate(), and handle_request_subscribe().

02004 {
02005    struct ast_exten *e;
02006 
02007    e = ast_hint_extension(c, context, exten);   /* Do we have a hint for this extension ? */
02008    if (!e)
02009       return -1;           /* No hint, return -1 */
02010 
02011    return ast_extension_state2(e);        /* Check all devices in the hint */
02012 }

static int ast_extension_state2 ( struct ast_exten e  )  [static]

ast_extensions_state2: Check state of extension by using hints

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

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

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

References extension_states, and cfextension_states::text.

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

01992 {
01993    int i;
01994 
01995    for (i = 0; (i < (sizeof(extension_states) / sizeof(extension_states[0]))); i++) {
01996       if (extension_states[i].extension_state == extension_state)
01997          return extension_states[i].text;
01998    }
01999    return "Unknown";
02000 }

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

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

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

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

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

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

Referenced by __sip_destroy(), and handle_request_subscribe().

02134 {
02135    struct ast_state_cb **p_cur = NULL; /* address of pointer to us */
02136    int ret = -1;
02137 
02138    if (!id && !callback)
02139       return -1;
02140 
02141    AST_LIST_LOCK(&hints);
02142 
02143    if (!id) {  /* id == 0 is a callback without extension */
02144       for (p_cur = &statecbs; *p_cur; p_cur = &(*p_cur)->next) {
02145          if ((*p_cur)->callback == callback)
02146             break;
02147       }
02148    } else { /* callback with extension, find the callback based on ID */
02149       struct ast_hint *hint;
02150       AST_LIST_TRAVERSE(&hints, hint, list) {
02151          for (p_cur = &hint->callbacks; *p_cur; p_cur = &(*p_cur)->next) {
02152             if ((*p_cur)->id == id)
02153                break;
02154          }
02155          if (*p_cur) /* found in the inner loop */
02156             break;
02157       }
02158    }
02159    if (p_cur && *p_cur) {
02160       struct ast_state_cb *cur = *p_cur;
02161       *p_cur = cur->next;
02162       free(cur);
02163       ret = 0;
02164    }
02165    AST_LIST_UNLOCK(&hints);
02166    return ret;
02167 }

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

References E_FINDLABEL, and pbx_extension_helper().

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

02285 {
02286    return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL);
02287 }

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

References E_FINDLABEL, and pbx_extension_helper().

Referenced by pbx_load_config().

02290 {
02291    return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL);
02292 }

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

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

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

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

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

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

Referenced by pbx_builtin_pushvar_helper(), and pbx_builtin_setvar_helper().

01548 {
01549    char *args = func_args(function);
01550    struct ast_custom_function *acfptr = ast_custom_function_find(function);
01551 
01552    if (acfptr == NULL)
01553       ast_log(LOG_ERROR, "Function %s not registered\n", function);
01554    else if (!acfptr->write)
01555       ast_log(LOG_ERROR, "Function %s cannot be written to\n", function);
01556    else
01557       return acfptr->write(chan, function, args, value);
01558 
01559    return -1;
01560 }

const char* ast_get_context_name ( struct ast_context con  ) 

const char* ast_get_context_registrar ( struct ast_context c  ) 

Definition at line 6216 of file pbx.c.

References ast_context::registrar.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06217 {
06218    return c ? c->registrar : NULL;
06219 }

const char* ast_get_extension_app ( struct ast_exten e  ) 

void* ast_get_extension_app_data ( struct ast_exten e  ) 

Definition at line 6251 of file pbx.c.

References ast_exten::data.

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

06252 {
06253    return e ? e->data : NULL;
06254 }

const char* ast_get_extension_cidmatch ( struct ast_exten e  ) 

Definition at line 6241 of file pbx.c.

References ast_exten::cidmatch.

Referenced by find_matching_priority(), and handle_save_dialplan().

06242 {
06243    return e ? e->cidmatch : NULL;
06244 }

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

Definition at line 6183 of file pbx.c.

References ast_exten::parent.

Referenced by handle_show_hints().

06184 {
06185    return exten ? exten->parent : NULL;
06186 }

const char* ast_get_extension_label ( struct ast_exten exten  ) 

Definition at line 6193 of file pbx.c.

References ast_exten::label.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06194 {
06195    return exten ? exten->label : NULL;
06196 }

int ast_get_extension_matchcid ( struct ast_exten e  ) 

Definition at line 6236 of file pbx.c.

References ast_exten::matchcid.

Referenced by find_matching_priority(), and handle_save_dialplan().

06237 {
06238    return e ? e->matchcid : 0;
06239 }

const char* ast_get_extension_name ( struct ast_exten exten  ) 

int ast_get_extension_priority ( struct ast_exten exten  ) 

Definition at line 6208 of file pbx.c.

References ast_exten::priority.

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

06209 {
06210    return exten ? exten->priority : -1;
06211 }

const char* ast_get_extension_registrar ( struct ast_exten e  ) 

Definition at line 6221 of file pbx.c.

References ast_exten::registrar.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06222 {
06223    return e ? e->registrar : NULL;
06224 }

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

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

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

02263 {
02264    struct ast_exten *e = ast_hint_extension(c, context, exten);
02265 
02266    if (e) {
02267       if (hint)
02268          ast_copy_string(hint, ast_get_extension_app(e), hintsize);
02269       if (name) {
02270          const char *tmp = ast_get_extension_app_data(e);
02271          if (tmp)
02272             ast_copy_string(name, tmp, namesize);
02273       }
02274       return -1;
02275    }
02276    return 0;
02277 }

const char* ast_get_ignorepat_name ( struct ast_ignorepat ip  ) 

Definition at line 6203 of file pbx.c.

References ast_ignorepat::pattern.

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

06204 {
06205    return ip ? ip->pattern : NULL;
06206 }

const char* ast_get_ignorepat_registrar ( struct ast_ignorepat ip  ) 

Definition at line 6231 of file pbx.c.

References ast_ignorepat::registrar.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06232 {
06233    return ip ? ip->registrar : NULL;
06234 }

const char* ast_get_include_name ( struct ast_include inc  ) 

Definition at line 6198 of file pbx.c.

References ast_include::name.

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

06199 {
06200    return inc ? inc->name : NULL;
06201 }

const char* ast_get_include_registrar ( struct ast_include i  ) 

Definition at line 6226 of file pbx.c.

References ast_include::registrar.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06227 {
06228    return i ? i->registrar : NULL;
06229 }

const char* ast_get_switch_data ( struct ast_sw sw  ) 

Definition at line 6261 of file pbx.c.

References ast_sw::data.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06262 {
06263    return sw ? sw->data : NULL;
06264 }

const char* ast_get_switch_name ( struct ast_sw sw  ) 

Definition at line 6256 of file pbx.c.

References ast_sw::name.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06257 {
06258    return sw ? sw->name : NULL;
06259 }

const char* ast_get_switch_registrar ( struct ast_sw sw  ) 

Definition at line 6266 of file pbx.c.

References ast_sw::registrar.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06267 {
06268    return sw ? sw->registrar : NULL;
06269 }

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

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

ast_hint_extension: Find hint for given extension in context

Definition at line 1893 of file pbx.c.

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

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

01894 {
01895    struct ast_exten *e;
01896    struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */
01897 
01898    ast_rdlock_contexts();
01899    e = pbx_find_extension(c, NULL, &q, context, exten, PRIORITY_HINT, NULL, "", E_MATCH);
01900    ast_unlock_contexts();
01901 
01902    return e;
01903 }

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

Definition at line 2014 of file pbx.c.

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

Referenced by do_state_change().

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

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

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

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

04536 {
04537    struct ast_context *con = ast_context_find(context);
04538    if (con) {
04539       struct ast_ignorepat *pat;
04540       for (pat = con->ignorepats; pat; pat = pat->next) {
04541          if (ast_extension_match(pat->pattern, pattern))
04542             return 1;
04543       }
04544    }
04545 
04546    return 0;
04547 }

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

References ast_mutex_lock(), and ast_context::lock.

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

06166 {
06167    return ast_mutex_lock(&con->lock);
06168 }

int ast_lock_contexts ( void   ) 

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

References E_MATCHMORE, and pbx_extension_helper().

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

02300 {
02301    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE);
02302 }

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

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

Referenced by pbx_load_module().

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

AST_MUTEX_DEFINE_STATIC ( maxcalllock   ) 

AST_MUTEX_DEFINE_STATIC ( globalslock   ) 

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

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

This function will handle locking the channel as needed.

Definition at line 6365 of file pbx.c.

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

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

06366 {
06367    char *exten, *pri, *context;
06368    char *stringp;
06369    int ipri;
06370    int mode = 0;
06371 
06372    if (ast_strlen_zero(goto_string)) {
06373       ast_log(LOG_WARNING, "Goto requires an argument (optional context|optional extension|priority)\n");
06374       return -1;
06375    }
06376    stringp = ast_strdupa(goto_string);
06377    context = strsep(&stringp, "|"); /* guaranteed non-null */
06378    exten = strsep(&stringp, "|");
06379    pri = strsep(&stringp, "|");
06380    if (!exten) {  /* Only a priority in this one */
06381       pri = context;
06382       exten = NULL;
06383       context = NULL;
06384    } else if (!pri) {   /* Only an extension and priority in this one */
06385       pri = exten;
06386       exten = context;
06387       context = NULL;
06388    }
06389    if (*pri == '+') {
06390       mode = 1;
06391       pri++;
06392    } else if (*pri == '-') {
06393       mode = -1;
06394       pri++;
06395    }
06396    if (sscanf(pri, "%d", &ipri) != 1) {
06397       if ((ipri = ast_findlabel_extension(chan, context ? context : chan->context, exten ? exten : chan->exten,
06398          pri, chan->cid.cid_num)) < 1) {
06399          ast_log(LOG_WARNING, "Priority '%s' must be a number > 0, or valid label\n", pri);
06400          return -1;
06401       } else
06402          mode = 0;
06403    }
06404    /* At this point we have a priority and maybe an extension and a context */
06405 
06406    if (mode)
06407       ipri = chan->priority + (ipri * mode);
06408 
06409    ast_explicit_goto(chan, context, exten, ipri);
06410    ast_cdr_update(chan);
06411    return 0;
06412 
06413 }

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

References ast_pbx_outgoing_app2().

Referenced by attempt_thread(), and orig_app().

05295 {
05296     return ast_pbx_outgoing_app2(type, format, data, timeout, app, appdata, reason, sync, 0, cid_num, cid_name, vars, account, locked_channel, NULL);
05297 }

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

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

Definition at line 5151 of file pbx.c.

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

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

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

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 4963 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_app2(), and ast_pbx_outgoing_exten2().

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

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

References ast_pbx_outgoing_exten2().

Referenced by attempt_thread(), and orig_exten().

05124 {
05125     return ast_pbx_outgoing_exten2(type, format, data, timeout, context, exten, priority, reason, sync, 0, cid_num, cid_name, vars, account, channel, NULL);
05126 }

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

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

Definition at line 4988 of file pbx.c.

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

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

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

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

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

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

02658 {
02659    enum ast_pbx_result res = AST_PBX_SUCCESS;
02660 
02661    if (increase_call_count(c))
02662       return AST_PBX_CALL_LIMIT;
02663 
02664    res = __ast_pbx_run(c);
02665    decrease_call_count();
02666 
02667    return res;
02668 }

void* ast_pbx_run_app ( void *  data  ) 

run the application and free the descriptor once done

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

05136 {
05137    struct app_tmp *tmp = data;
05138    struct ast_app *app;
05139    app = pbx_findapp(tmp->app);
05140    if (app) {
05141       if (option_verbose > 3)
05142          ast_verbose(VERBOSE_PREFIX_4 "Launching %s(%s) on %s\n", tmp->app, tmp->data, tmp->chan->name);
05143       pbx_exec(tmp->chan, app, tmp->data);
05144    } else
05145       ast_log(LOG_WARNING, "No such application '%s'\n", tmp->app);
05146    ast_hangup(tmp->chan);
05147    free(tmp);
05148    return NULL;
05149 }

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

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

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

02632 {
02633    pthread_t t;
02634    pthread_attr_t attr;
02635 
02636    if (!c) {
02637       ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
02638       return AST_PBX_FAILED;
02639    }
02640 
02641    if (increase_call_count(c))
02642       return AST_PBX_CALL_LIMIT;
02643 
02644    /* Start a new thread, and get something handling this channel. */
02645    pthread_attr_init(&attr);
02646    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
02647    if (ast_pthread_create(&t, &attr, pbx_thread, c)) {
02648       ast_log(LOG_WARNING, "Failed to create new channel thread\n");
02649       pthread_attr_destroy(&attr);
02650       return AST_PBX_FAILED;
02651    }
02652    pthread_attr_destroy(&attr);
02653 
02654    return AST_PBX_SUCCESS;
02655 }

int ast_rdlock_contexts ( void   ) 

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

Dynamically register a new dial plan application.

Register an application.

Definition at line 2959 of file pbx.c.

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

Referenced by load_module(), and load_pbx().

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

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

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

Referenced by load_module().

03010 {
03011    struct ast_switch *tmp;
03012 
03013    AST_LIST_LOCK(&switches);
03014    AST_LIST_TRAVERSE(&switches, tmp, list) {
03015       if (!strcasecmp(tmp->name, sw->name)) {
03016          AST_LIST_UNLOCK(&switches);
03017          ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name);
03018          return -1;
03019       }
03020    }
03021    AST_LIST_INSERT_TAIL(&switches, sw, list);
03022    AST_LIST_UNLOCK(&switches);
03023 
03024    return 0;
03025 }

static int ast_remove_hint ( struct ast_exten e  )  [static]

ast_remove_hint: Remove hint from extension

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

02226 {
02227    /* Cleanup the Notifys if hint is removed */
02228    struct ast_hint *hint;
02229    struct ast_state_cb *cblist, *cbprev;
02230    int res = -1;
02231 
02232    if (!e)
02233       return -1;
02234 
02235    AST_LIST_LOCK(&hints);
02236    AST_LIST_TRAVERSE_SAFE_BEGIN(&hints, hint, list) {
02237       if (hint->exten == e) {
02238          cbprev = NULL;
02239          cblist = hint->callbacks;
02240          while (cblist) {
02241             /* Notify with -1 and remove all callbacks */
02242             cbprev = cblist;
02243             cblist = cblist->next;
02244             cbprev->callback(hint->exten->parent->name, hint->exten->exten, AST_EXTENSION_DEACTIVATED, cbprev->data, NULL, NULL);
02245             free(cbprev);
02246             }
02247             hint->callbacks = NULL;
02248          AST_LIST_REMOVE_CURRENT(&hints, list);
02249             free(hint);
02250             res = 0;
02251          break;
02252       }
02253    }
02254    AST_LIST_TRAVERSE_SAFE_END
02255    AST_LIST_UNLOCK(&hints);
02256 
02257    return res;
02258 }

AST_RWLOCK_DEFINE_STATIC ( conlock   ) 

Lock for the ast_context list

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

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

Parameters:
c not important
context which context to generate the extension within
exten new extension to add
priority priority of new extension
callerid callerid of extension
This adds a new extension to the asterisk extension list.

Return values:
0 on success
-1 on failure.

Definition at line 2304 of file pbx.c.

References E_SPAWN, and pbx_extension_helper().

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

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

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

References ast_mutex_unlock(), and ast_context::lock.

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

06171 {
06172    return ast_mutex_unlock(&con->lock);
06173 }

int ast_unlock_contexts ( void   ) 

int ast_unregister_application ( const char *  app  ) 

Unregister an application.

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

Return values:
0 success
-1 failure

Definition at line 3840 of file pbx.c.

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

Referenced by __unload_module(), and unload_module().

03841 {
03842    struct ast_app *tmp;
03843 
03844    AST_LIST_LOCK(&apps);
03845    AST_LIST_TRAVERSE_SAFE_BEGIN(&apps, tmp, list) {
03846       if (!strcasecmp(app, tmp->name)) {
03847          AST_LIST_REMOVE_CURRENT(&apps, list);
03848          if (option_verbose > 1)
03849             ast_verbose( VERBOSE_PREFIX_2 "Unregistered application '%s'\n", tmp->name);
03850          free(tmp);
03851          break;
03852       }
03853    }
03854    AST_LIST_TRAVERSE_SAFE_END
03855    AST_LIST_UNLOCK(&apps);
03856 
03857    return tmp ? 0 : -1;
03858 }

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

References AST_LIST_LOCK, AST_LIST_REMOVE, and AST_LIST_UNLOCK.

Referenced by __unload_module(), and unload_module().

03028 {
03029    AST_LIST_LOCK(&switches);
03030    AST_LIST_REMOVE(&switches, sw, list);
03031    AST_LIST_UNLOCK(&switches);
03032 }

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

Definition at line 6279 of file pbx.c.

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

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

06281 {
06282    if (!exten)
06283       return con ? con->root : NULL;
06284    else
06285       return exten->next;
06286 }

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

Definition at line 6312 of file pbx.c.

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

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

06314 {
06315    if (!ip)
06316       return con ? con->ignorepats : NULL;
06317    else
06318       return ip->next;
06319 }

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

Definition at line 6303 of file pbx.c.

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

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

06305 {
06306    if (!inc)
06307       return con ? con->includes : NULL;
06308    else
06309       return inc->next;
06310 }

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

Definition at line 6288 of file pbx.c.

References AST_LIST_FIRST, and AST_LIST_NEXT.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06290 {
06291    if (!sw)
06292       return con ? AST_LIST_FIRST(&con->alts) : NULL;
06293    else
06294       return AST_LIST_NEXT(sw, list);
06295 }

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

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

Definition at line 6297 of file pbx.c.

References ast_exten::peer.

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

06299 {
06300    return priority ? priority->peer : exten;
06301 }

int ast_wrlock_contexts ( void   ) 

Definition at line 6152 of file pbx.c.

References ast_rwlock_wrlock().

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

06153 {
06154    return ast_rwlock_wrlock(&conlock);
06155 }

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

Definition at line 4900 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_app2(), and ast_pbx_outgoing_exten2().

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

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

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

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

Definition at line 3085 of file pbx.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, and strdup.

03086 {
03087    struct ast_app *a;
03088    char *ret = NULL;
03089    int which = 0;
03090    int wordlen = strlen(word);
03091 
03092    /* return the n-th [partial] matching entry */
03093    AST_LIST_LOCK(&apps);
03094    AST_LIST_TRAVERSE(&apps, a, list) {
03095       if (!strncasecmp(word, a->name, wordlen) && ++which > state) {
03096          ret = strdup(a->name);
03097          break;
03098       }
03099    }
03100    AST_LIST_UNLOCK(&apps);
03101 
03102    return ret;
03103 }

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

Definition at line 3446 of file pbx.c.

References ast_cli_complete().

03447 {
03448    static char* choices[] = { "like", "describing", NULL };
03449 
03450    return (pos != 3) ? NULL : ast_cli_complete(word, choices, state);
03451 }

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

Definition at line 3439 of file pbx.c.

References ast_cli_complete().

03440 {
03441    static char* choices[] = { "like", "describing", NULL };
03442 
03443    return (pos != 2) ? NULL : ast_cli_complete(word, choices, state);
03444 }

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

Definition at line 3456 of file pbx.c.

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

03458 {
03459    struct ast_context *c = NULL;
03460    char *ret = NULL;
03461    int which = 0;
03462    int wordlen;
03463 
03464    /* we are do completion of [exten@]context on second position only */
03465    if (pos != 2)
03466       return NULL;
03467 
03468    ast_rdlock_contexts();
03469 
03470    wordlen = strlen(word);
03471 
03472    /* walk through all contexts and return the n-th match */
03473    while ( (c = ast_walk_contexts(c)) ) {
03474       if (!strncasecmp(word, ast_get_context_name(c), wordlen) && ++which > state) {
03475          ret = ast_strdup(ast_get_context_name(c));
03476          break;
03477       }
03478    }
03479 
03480    ast_unlock_contexts();
03481 
03482    return ret;
03483 }

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

Definition at line 1423 of file pbx.c.

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

01424 {
01425    struct ast_custom_function *acf;
01426    char *ret = NULL;
01427    int which = 0;
01428    int wordlen = strlen(word);
01429 
01430    /* case-insensitive for convenience in this 'complete' function */
01431    AST_LIST_LOCK(&acf_root);
01432    AST_LIST_TRAVERSE(&acf_root, acf, acflist) {
01433       if (!strncasecmp(word, acf->name, wordlen) && ++which > state) {
01434          ret = strdup(acf->name);
01435          break;
01436       }
01437    }
01438    AST_LIST_UNLOCK(&acf_root);
01439 
01440    return ret;
01441 }

static void decrease_call_count ( void   )  [static]

Definition at line 2593 of file pbx.c.

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

Referenced by ast_pbx_run(), and pbx_thread().

02594 {
02595    ast_mutex_lock(&maxcalllock);
02596    if (countcalls > 0)
02597       countcalls--;
02598    ast_mutex_unlock(&maxcalllock);
02599 }

static void destroy_exten ( struct ast_exten e  )  [static]

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

02602 {
02603    if (e->priority == PRIORITY_HINT)
02604       ast_remove_hint(e);
02605 
02606    if (e->datad)
02607       e->datad(e->data);
02608    free(e);
02609 }

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

Referenced by ast_add_extension2().

04653 {
04654    int count=0;
04655 
04656    while (*src && (count < len - 1)) {
04657       switch(*src) {
04658       case ' ':
04659          /* otherwise exten => [a-b],1,... doesn't work */
04660          /*    case '-': */
04661          /* Ignore */
04662          break;
04663       default:
04664          *dst = *src;
04665          dst++;
04666       }
04667       src++;
04668       count++;
04669    }
04670    *dst = '\0';
04671 
04672    return count;
04673 }

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]

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

References ast_log(), and LOG_WARNING.

Referenced by ast_func_read(), and ast_func_write().

01517 {
01518    char *args = strchr(function, '(');
01519 
01520    if (!args)
01521       ast_log(LOG_WARNING, "Function doesn't contain parentheses.  Assuming null argument.\n");
01522    else {
01523       char *p;
01524       *args++ = '\0';
01525       if ((p = strrchr(args, ')')) )
01526          *p = '\0';
01527       else
01528          ast_log(LOG_WARNING, "Can't find trailing parenthesis?\n");
01529    }
01530    return args;
01531 }

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

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

Referenced by ast_build_timing().

04071 {
04072    int s, e; /* start and ending position */
04073    unsigned int mask = 0;
04074 
04075    /* Check for whole range */
04076    if (ast_strlen_zero(src) || !strcmp(src, "*")) {
04077       s = 0;
04078       e = max - 1;
04079    } else {
04080       /* Get start and ending position */
04081       char *c = strchr(src, '-');
04082       if (c)
04083          *c++ = '\0';
04084       /* Find the start */
04085       s = lookup_name(src, names, max);
04086       if (!s) {
04087          ast_log(LOG_WARNING, "Invalid %s '%s', assuming none\n", msg, src);
04088          return 0;
04089       }
04090       s--;
04091       if (c) { /* find end of range */
04092          e = lookup_name(c, names, max);
04093          if (!e) {
04094             ast_log(LOG_WARNING, "Invalid end %s '%s', assuming none\n", msg, c);
04095             return 0;
04096          }
04097          e--;
04098       } else
04099          e = s;
04100    }
04101    /* Fill the mask. Remember that ranges are cyclic */
04102    mask = 1 << e; /* initialize with last element */
04103    while (s != e) {
04104       if (s >= max) {
04105          s = 0;
04106          mask |= (1 << s);
04107       } else {
04108          mask |= (1 << s);
04109          s++;
04110       }
04111    }
04112    return mask;
04113 }

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

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

Referenced by ast_build_timing().

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

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

Definition at line 3741 of file pbx.c.

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

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

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

CLI support for setting global variables.

Definition at line 3729 of file pbx.c.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

03713 {
03714    int i = 0;
03715    struct ast_var_t *newvariable;
03716 
03717    ast_mutex_lock(&globalslock);
03718    AST_LIST_TRAVERSE (&globals, newvariable, entries) {
03719       i++;
03720       ast_cli(fd, "   %s=%s\n", ast_var_name(newvariable), ast_var_value(newvariable));
03721    }
03722    ast_mutex_unlock(&globalslock);
03723    ast_cli(fd, "\n    -- %d variables\n", i);
03724 
03725    return RESULT_SUCCESS;
03726 }

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

03247 {
03248    struct ast_hint *hint;
03249    int num = 0;
03250    int watchers;
03251    struct ast_state_cb *watcher;
03252 
03253    if (AST_LIST_EMPTY(&hints)) {
03254       ast_cli(fd, "There are no registered dialplan hints\n");
03255       return RESULT_SUCCESS;
03256    }
03257    /* ... we have hints ... */
03258    ast_cli(fd, "\n    -= Registered Asterisk Dial Plan Hints =-\n");
03259    AST_LIST_LOCK(&hints);
03260    AST_LIST_TRAVERSE(&hints, hint, list) {
03261       watchers = 0;
03262       for (watcher = hint->callbacks; watcher; watcher = watcher->next)
03263          watchers++;
03264       ast_cli(fd, "   %20s@%-20.20s: %-20.20s  State:%-15.15s Watchers %2d\n",
03265          ast_get_extension_name(hint->exten),
03266          ast_get_context_name(ast_get_extension_context(hint->exten)),
03267          ast_get_extension_app(hint->exten),
03268          ast_extension_state2str(hint->laststate), watchers);
03269       num++;
03270    }
03271    ast_cli(fd, "----------------\n");
03272    ast_cli(fd, "- %d hints registered\n", num);
03273    AST_LIST_UNLOCK(&hints);
03274    return RESULT_SUCCESS;
03275 }

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

03279 {
03280    struct ast_switch *sw;
03281 
03282    AST_LIST_LOCK(&switches);
03283 
03284    if (AST_LIST_EMPTY(&switches)) {
03285       AST_LIST_UNLOCK(&switches);
03286       ast_cli(fd, "There are no registered alternative switches\n");
03287       return RESULT_SUCCESS;
03288    }
03289 
03290    ast_cli(fd, "\n    -= Registered Asterisk Alternative Switches =-\n");
03291    AST_LIST_TRAVERSE(&switches, sw, list)
03292       ast_cli(fd, "%s: %s\n", sw->name, sw->description);
03293 
03294    AST_LIST_UNLOCK(&switches);
03295 
03296    return RESULT_SUCCESS;
03297 }

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

02569 {
02570    int failed = 0;
02571    double curloadavg;
02572    ast_mutex_lock(&maxcalllock);
02573    if (option_maxcalls) {
02574       if (countcalls >= option_maxcalls) {
02575          ast_log(LOG_NOTICE, "Maximum call limit of %d calls exceeded by '%s'!\n", option_maxcalls, c->name);
02576          failed = -1;
02577       }
02578    }
02579    if (option_maxload) {
02580       getloadavg(&curloadavg, 1);
02581       if (curloadavg >= option_maxload) {
02582          ast_log(LOG_NOTICE, "Maximum loadavg limit of %f load exceeded by '%s' (currently %f)!\n", option_maxload, c->name, curloadavg);
02583          failed = -1;
02584       }
02585    }
02586    if (!failed)
02587       countcalls++;
02588    ast_mutex_unlock(&maxcalllock);
02589 
02590    return failed;
02591 }

int load_pbx ( void   ) 

Provided by pbx.c

Definition at line 6116 of file pbx.c.

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

Referenced by main().

06117 {
06118    int x;
06119 
06120    /* Initialize the PBX */
06121    if (option_verbose) {
06122       ast_verbose( "Asterisk PBX Core Initializing\n");
06123       ast_verbose( "Registering builtin applications:\n");
06124    }
06125    ast_cli_register_multiple(pbx_cli, sizeof(pbx_cli) / sizeof(struct ast_cli_entry));
06126 
06127    /* Register builtin applications */
06128    for (x=0; x<sizeof(builtins) / sizeof(struct pbx_builtin); x++) {
06129       if (option_verbose)
06130          ast_verbose( VERBOSE_PREFIX_1 "[%s]\n", builtins[x].name);
06131       if (ast_register_application(builtins[x].name, builtins[x].execute, builtins[x].synopsis, builtins[x].description)) {
06132          ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name);
06133          return -1;
06134       }
06135    }
06136    return 0;
06137 }

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

Referenced by get_range().

04053 {
04054    int i;
04055 
04056    if (names) {
04057       for (i = 0; names[i]; i++) {
04058          if (!strcasecmp(s, names[i]))
04059             return i+1;
04060       }
04061    } else if (sscanf(s, "%d", &i) == 1 && i >= 1 && i <= max) {
04062       return i;
04063    }
04064    return 0; /* error return */
04065 }

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

Definition at line 912 of file pbx.c.

References ast_extension_match(), and ast_strlen_zero().

Referenced by pbx_find_extension().

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

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

Referenced by pbx_retrieve_variable(), and pbx_substitute_variables_helper_full().

01073 {
01074    int parens=0;
01075 
01076    *offset = 0;
01077    *length = INT_MAX;
01078    *isfunc = 0;
01079    for (; *var; var++) {
01080       if (*var == '(') {
01081          (*isfunc)++;
01082          parens++;
01083       } else if (*var == ')') {
01084          parens--;
01085       } else if (*var == ':' && parens == 0) {
01086          *var++ = '\0';
01087          sscanf(var, "%d:%d", offset, length);
01088          return 1; /* offset:length valid */
01089       }
01090    }
01091    return 0;
01092 }

void pbx_builtin_clear_globals ( void   ) 

Definition at line 6003 of file pbx.c.

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

Referenced by handle_reload_extensions(), and reload().

06004 {
06005    struct ast_var_t *vardata;
06006 
06007    ast_mutex_lock(&globalslock);
06008    while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries)))
06009       ast_var_delete(vardata);
06010    ast_mutex_unlock(&globalslock);
06011 }

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

Note:
Will lock the channel.

Definition at line 5780 of file pbx.c.

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

Referenced by __ast_pbx_run(), __login_exec(), _macro_exec(), _while_exec(), agent_hangup(), agent_read(), agentmonitoroutgoing_exec(), ast_bridge_call(), ast_channel_bridge(), ast_feature_interpret(), ast_monitor_stop(), builtin_automonitor(), check_goto_on_transfer(), common_exec(), conf_exec(), conf_run(), dundi_exec(), dundi_helper(), get_also_info(), get_index(), get_refer_info(), global_read(), iax2_exec(), import_ch(), leave_voicemail(), local_hangup(), misdn_answer(), misdn_hangup(), morsecode_exec(), notify_new_message(), oh323_call(), oh323_hangup(), park_call_full(), pickup_by_mark(), queue_exec(), real_ctx(), retrydial_exec(), return_exec(), 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().

05781 {
05782    struct ast_var_t *variables;
05783    const char *ret = NULL;
05784    int i;
05785    struct varshead *places[2] = { NULL, &globals };
05786 
05787    if (!name)
05788       return NULL;
05789 
05790    if (chan) {
05791       ast_channel_lock(chan);
05792       places[0] = &chan->varshead;
05793    }
05794 
05795    for (i = 0; i < 2; i++) {
05796       if (!places[i])
05797          continue;
05798       if (places[i] == &globals)
05799          ast_mutex_lock(&globalslock);
05800       AST_LIST_TRAVERSE(places[i], variables, entries) {
05801          if (!strcmp(name, ast_var_name(variables))) {
05802             ret = ast_var_value(variables);
05803             break;
05804          }
05805       }
05806       if (places[i] == &globals)
05807          ast_mutex_unlock(&globalslock);
05808       if (ret)
05809          break;
05810    }
05811 
05812    if (chan)
05813       ast_channel_unlock(chan);
05814 
05815    return ret;
05816 }

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

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

06024 {
06025    char *condition, *branch1, *branch2, *branch;
06026    int rc;
06027    char *stringp;
06028 
06029    if (ast_strlen_zero(data)) {
06030       ast_log(LOG_WARNING, "Ignoring, since there is no variable to check\n");
06031       return 0;
06032    }
06033 
06034    stringp = ast_strdupa(data);
06035    condition = strsep(&stringp,"?");
06036    branch1 = strsep(&stringp,":");
06037    branch2 = strsep(&stringp,"");
06038    branch = pbx_checkcondition(condition) ? branch1 : branch2;
06039 
06040    if (ast_strlen_zero(branch)) {
06041       if (option_debug)
06042          ast_log(LOG_DEBUG, "Not taking any branch\n");
06043       return 0;
06044    }
06045 
06046    rc = pbx_builtin_goto(chan, branch);
06047 
06048    return rc;
06049 }

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

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

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

05943 {
05944    char *name;
05945    char *value;
05946    char *channel;
05947    char tmp[VAR_BUF_SIZE]="";
05948 
05949    if (ast_strlen_zero(data)) {
05950       ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n");
05951       return 0;
05952    }
05953 
05954    value = ast_strdupa(data);
05955    name = strsep(&value,"=");
05956    channel = strsep(&value,"|");
05957    if (channel && value && name) { /*! \todo XXX should do !ast_strlen_zero(..) of the args ? */
05958       struct ast_channel *chan2 = ast_get_channel_by_name_locked(channel);
05959       if (chan2) {
05960          char *s = alloca(strlen(value) + 4);
05961          if (s) {
05962             sprintf(s, "${%s}", value);
05963             pbx_substitute_variables_helper(chan2, s, tmp, sizeof(tmp) - 1);
05964          }
05965          ast_channel_unlock(chan2);
05966       }
05967       pbx_builtin_setvar_helper(chan, name, tmp);
05968    }
05969 
05970    return(0);
05971 }

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

Definition at line 5998 of file pbx.c.

05999 {
06000    return 0;
06001 }

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

Note:
Will lock the channel.

Definition at line 5818 of file pbx.c.

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

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

05819 {
05820    struct ast_var_t *newvariable;
05821    struct varshead *headp;
05822 
05823    if (name[strlen(name)-1] == ')') {
05824       char *function = ast_strdupa(name);
05825 
05826       ast_log(LOG_WARNING, "Cannot push a value onto a function\n");
05827       ast_func_write(chan, function, value);
05828       return;
05829    }
05830 
05831    if (chan) {
05832       ast_channel_lock(chan);
05833       headp = &chan->varshead;
05834    } else {
05835       ast_mutex_lock(&globalslock);
05836       headp = &globals;
05837    }
05838 
05839    if (value) {
05840       if ((option_verbose > 1) && (headp == &globals))
05841          ast_verbose(VERBOSE_PREFIX_2 "Setting global variable '%s' to '%s'\n", name, value);
05842       newvariable = ast_var_assign(name, value);
05843       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
05844    }
05845 
05846    if (chan)
05847       ast_channel_unlock(chan);
05848    else
05849       ast_mutex_unlock(&globalslock);
05850 }

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

Definition at line 6090 of file pbx.c.

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

06091 {
06092    int res = 0;
06093 
06094    if (data) {
06095       if (chan->_state != AST_STATE_UP) {
06096           ast_answer(chan);
06097       }
06098       res = ast_say_character_str(chan, data, "", chan->language);
06099    }
06100    return res;
06101 }

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

Definition at line 6077 of file pbx.c.

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

06078 {
06079    int res = 0;
06080 
06081    if (data) {
06082       if (chan->_state != AST_STATE_UP) {
06083           ast_answer(chan);
06084       }
06085       res = ast_say_digit_str(chan, data, "", chan->language);
06086    }
06087    return res;
06088 }

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

Definition at line 6051 of file pbx.c.

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

06052 {
06053    char tmp[256];
06054    char *number = tmp;
06055    char *options;
06056 
06057    if (ast_strlen_zero(data)) {
06058       ast_log(LOG_WARNING, "SayNumber requires an argument (number)\n");
06059       return -1;
06060    }
06061    ast_copy_string(tmp, data, sizeof(tmp));
06062    strsep(&number, "|");
06063    options = strsep(&number, "|");
06064    if (options) {
06065       if ( strcasecmp(options, "f") && strcasecmp(options,"m") &&
06066          strcasecmp(options, "c") && strcasecmp(options, "n") ) {
06067          ast_log(LOG_WARNING, "SayNumber gender option is either 'f', 'm', 'c' or 'n'\n");
06068          return -1;
06069       }
06070    }
06071    if (chan->_state != AST_STATE_UP) {
06072        ast_answer(chan);
06073    }
06074    return ast_say_number(chan, atoi(tmp), "", chan->language, options);
06075 }

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

Definition at line 6103 of file pbx.c.

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

06104 {
06105    int res = 0;
06106 
06107    if (data) {
06108       if (chan->_state != AST_STATE_UP) {
06109           ast_answer(chan);
06110       }
06111       res = ast_say_phonetic_str(chan, data, "", chan->language);
06112    }
06113    return res;
06114 }

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

Note:
Will lock the channel.

Definition at line 5749 of file pbx.c.

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

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

05750 {
05751    struct ast_var_t *variables;
05752    const char *var, *val;
05753    int total = 0;
05754 
05755    if (!chan)
05756       return 0;
05757 
05758    memset(buf, 0, size);
05759 
05760    ast_channel_lock(chan);
05761 
05762    AST_LIST_TRAVERSE(&chan->varshead, variables, entries) {
05763       if ((var=ast_var_name(variables)) && (val=ast_var_value(variables))
05764          /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */
05765          ) {
05766          if (ast_build_string(&buf, &size, "%s=%s\n", var, val)) {
05767             ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
05768             break;
05769          } else
05770             total++;
05771       } else
05772          break;
05773    }
05774 
05775    ast_channel_unlock(chan);
05776 
05777    return total;
05778 }

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

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

05975 {
05976    char *name;
05977    char *stringp = data;
05978    static int dep_warning = 0;
05979 
05980    if (ast_strlen_zero(data)) {
05981       ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n");
05982       return 0;
05983    }
05984 
05985    name = strsep(&stringp, "=");
05986 
05987    if (!dep_warning) {
05988       dep_warning = 1;
05989       ast_log(LOG_WARNING, "SetGlobalVar is deprecated.  Please use Set(GLOBAL(%s)=%s) instead.\n", name, stringp);
05990    }
05991 
05992    /*! \todo XXX watch out, leading whitespace ? */
05993    pbx_builtin_setvar_helper(NULL, name, stringp);
05994 
05995    return(0);
05996 }

int pbx_builtin_setvar ( struct ast_channel chan,
void *  data 
)

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

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

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

Note:
Will lock the channel.

Definition at line 5852 of file pbx.c.

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

Referenced by __ast_pbx_run(), __login_exec(), __oh323_new(), _macro_exec(), _while_exec(), acf_odbc_read(), acf_odbc_write(), action_setvar(), agi_exec_full(), aji_status_exec(), app_exec(), aqm_exec(), array(), ast_bridge_call(), ast_channel_bridge(), ast_feature_request_and_dial(), ast_iax2_new(), ast_monitor_start(), ast_pbx_outgoing_exten2(), 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_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().

05853 {
05854    struct ast_var_t *newvariable;
05855    struct varshead *headp;
05856    const char *nametail = name;
05857 
05858    if (name[strlen(name)-1] == ')') {
05859       char *function = ast_strdupa(name);
05860 
05861       ast_func_write(chan, function, value);
05862       return;
05863    }
05864 
05865    if (chan) {
05866       ast_channel_lock(chan);
05867       headp = &chan->varshead;
05868    } else {
05869       ast_mutex_lock(&globalslock);
05870       headp = &globals;
05871    }
05872 
05873    /* For comparison purposes, we have to strip leading underscores */
05874    if (*nametail == '_') {
05875       nametail++;
05876       if (*nametail == '_')
05877          nametail++;
05878    }
05879 
05880    AST_LIST_TRAVERSE (headp, newvariable, entries) {
05881       if (strcasecmp(ast_var_name(newvariable), nametail) == 0) {
05882          /* there is already such a variable, delete it */
05883          AST_LIST_REMOVE(headp, newvariable, entries);
05884          ast_var_delete(newvariable);
05885          break;
05886       }
05887    }
05888 
05889    if (value) {
05890       if ((option_verbose > 1) && (headp == &globals))
05891          ast_verbose(VERBOSE_PREFIX_2 "Setting global variable '%s' to '%s'\n", name, value);
05892       newvariable = ast_var_assign(name, value);
05893       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
05894    }
05895 
05896    if (chan)
05897       ast_channel_unlock(chan);
05898    else
05899       ast_mutex_unlock(&globalslock);
05900 }

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

References ast_strlen_zero().

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

06014 {
06015    if (ast_strlen_zero(condition))  /* NULL or empty strings are false */
06016       return 0;
06017    else if (*condition >= '0' && *condition <= '9')   /* Numbers are evaluated for truth */
06018       return atoi(condition);
06019    else  /* Strings are true */
06020       return 1;
06021 }

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.

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

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.

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

Definition at line 1795 of file pbx.c.

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

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

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

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

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

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

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

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.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, and AST_LIST_UNLOCK.

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

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

Note:
Will lock the channel.

Definition at line 1140 of file pbx.c.

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

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

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

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

References autofallthrough.

Referenced by pbx_load_module().

02676 {
02677    int oldval = autofallthrough;
02678    autofallthrough = newval;
02679    return oldval;
02680 }

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

Definition at line 1766 of file pbx.c.

References ast_exten::data, and pbx_substitute_variables_helper().

Referenced by pbx_extension_helper().

01767 {
01768    memset(passdata, 0, datalen);
01769 
01770    /* No variables or expressions in e->data, so why scan it? */
01771    if (e->data && !strchr(e->data, '$') && !strstr(e->data,"${") && !strstr(e->data,"$[") && !strstr(e->data,"$(")) {
01772       ast_copy_string(passdata, e->data, datalen);
01773       return;
01774    }
01775 
01776    pbx_substitute_variables_helper(c, e->data, passdata, datalen - 1);
01777 }

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

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

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

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

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

Definition at line 1761 of file pbx.c.

References pbx_substitute_variables_helper_full().

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

01762 {
01763    pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count);
01764 }

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

Definition at line 2611 of file pbx.c.

References __ast_pbx_run(), and decrease_call_count().

Referenced by ast_pbx_start().

02612 {
02613    /* Oh joyeous kernel, we're a new thread, with nothing to do but
02614       answer this channel and get it going.
02615    */
02616    /* NOTE:
02617       The launcher of this function _MUST_ increment 'countcalls'
02618       before invoking the function; it will be decremented when the
02619       PBX has finished running on the channel
02620     */
02621    struct ast_channel *c = data;
02622 
02623    __ast_pbx_run(c);
02624    decrease_call_count();
02625 
02626    pthread_exit(NULL);
02627 
02628    return NULL;
02629 }

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

helper function to print an extension

Definition at line 3494 of file pbx.c.

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

Referenced by show_dialplan_helper().

03495 {
03496    int prio = ast_get_extension_priority(e);
03497    if (prio == PRIORITY_HINT) {
03498       snprintf(buf, buflen, "hint: %s",
03499          ast_get_extension_app(e));
03500    } else {
03501       snprintf(buf, buflen, "%d. %s(%s)",
03502          prio, ast_get_extension_app(e),
03503          (!ast_strlen_zero(ast_get_extension_app_data(e)) ? (char *)ast_get_extension_app_data(e) : ""));
03504    }
03505 }

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

Definition at line 2310 of file pbx.c.

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

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

02311 {
02312    ast_channel_lock(c);
02313    ast_copy_string(c->exten, exten, sizeof(c->exten));
02314    c->priority = pri;
02315    ast_channel_unlock(c);
02316 }

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

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

Referenced by handle_show_dialplan().

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

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

Referenced by pbx_retrieve_variable(), and pbx_substitute_variables_helper_full().

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

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

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

05365 {
05366    int res;
05367    struct ast_frame *f;
05368    int waittime;
05369 
05370    if (ast_strlen_zero(data) || (sscanf(data, "%d", &waittime) != 1) || (waittime < 0))
05371       waittime = -1;
05372    if (waittime > -1) {
05373       ast_safe_sleep(chan, waittime * 1000);
05374    } else do {
05375       res = ast_waitfor(chan, -1);
05376       if (res < 0)
05377          return;
05378       f = ast_read(chan);
05379       if (f)
05380          ast_frfree(f);
05381    } while(f);
05382 }


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]

Initial value:

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

Definition at line 3797 of file pbx.c.

Initial value:

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

Definition at line 3787 of file pbx.c.

Initial value:

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

Definition at line 3757 of file pbx.c.

Initial value:

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

Definition at line 3792 of file pbx.c.

Initial value:

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

Definition at line 3782 of file pbx.c.

Initial value:

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

Definition at line 3762 of file pbx.c.

Initial value:

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

Definition at line 3777 of file pbx.c.

Initial value:

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

Definition at line 3772 of file pbx.c.

Initial value:

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

Definition at line 3767 of file pbx.c.

struct ast_context* contexts [static]

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

Referenced by ast_build_timing().

Referenced by ast_extension_state2str().

struct varshead globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE [static]

char* months[] [static]

Definition at line 4213 of file pbx.c.

Referenced by ast_build_timing().

struct ast_cli_entry pbx_cli[] [static]

Definition at line 3802 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 3071 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 3059 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 3037 of file pbx.c.

char show_dialplan_help[] [static]

Initial value:

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

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

char show_hints_help[] [static]

Initial value:

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

Definition at line 3051 of file pbx.c.

char show_switches_help[] [static]

Initial value:

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

Definition at line 3047 of file pbx.c.

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 Sat Apr 12 07:12:51 2008 for Asterisk - the Open Source PBX by  doxygen 1.5.5