Fri Mar 8 17:30:12 2019

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/stringfields.h"
#include "asterisk/threadstorage.h"
#include "asterisk/astobj2.h"

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_extension_callerid (const char *context, const char *extension, int priority, const char *callerid, int matchcid, const char *registrar)
int ast_context_remove_extension_callerid2 (struct ast_context *con, const char *extension, int priority, const char *callerid, int matchcid, const char *registrar)
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.
enum ast_extension_states ast_devstate_to_extenstate (enum ast_device_state devstate)
 Map devstate to an extension state.
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 void ast_hint_destroy (void *obj)
static struct ast_extenast_hint_extension (struct ast_channel *c, const char *context, const char *exten)
 ast_hint_extension: Find hint for given extension in context
void ast_hint_state_changed (const char *device)
int ast_ignore_pattern (const char *context, const char *pattern)
 Checks to see if a number should be ignored.
 AST_LIST_HEAD (store_hints, store_hint)
static AST_LIST_HEAD_STATIC (switches, ast_switch)
static AST_LIST_HEAD_STATIC (apps, ast_app)
static AST_LIST_HEAD_STATIC (acf_root, ast_custom_function)
int ast_lock_context (struct ast_context *con)
 Locks a given context.
int ast_lock_contexts ()
 Locks the context list.
int ast_matchmore_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
 Looks to see if adding anything to this extension might match something. (exists ^ canmatch).
void ast_merge_contexts_and_delete (struct ast_context **extcontexts, const char *registrar)
 Merge the temporary contexts into a global contexts list and delete from the global list the ones that are being added.
 AST_MUTEX_DEFINE_STATIC (conlock)
 Lock for the ast_context list This lock MUST be recursive, or a deadlock on reload may result. See https://issues.asterisk.org/view.php?id=17643.
 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_init (void)
int ast_pbx_outgoing_app (const char *type, int format, void *data, int timeout, const char *app, const char *appdata, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel)
static int ast_pbx_outgoing_cdr_failed (void)
int ast_pbx_outgoing_exten (const char *type, int format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **channel)
enum ast_pbx_result ast_pbx_run (struct ast_channel *c)
 Execute the PBX in the current thread.
static void * ast_pbx_run_app (void *data)
 run the application and free the descriptor once done
enum ast_pbx_result ast_pbx_start (struct ast_channel *c)
 Create a new thread and start the PBX.
int ast_processed_calls (void)
 Retrieve the total number of calls processed through the PBX since last restart.
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
int ast_spawn_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
 Launch a new extension (i.e. new stack).
 AST_THREADSTORAGE (switch_data, switch_data_init)
int ast_unlock_context (struct ast_context *con)
int ast_unlock_contexts ()
 Unlocks contexts.
int ast_unregister_application (const char *app)
 Unregister an application.
void ast_unregister_switch (struct ast_switch *sw)
 Unregister an alternative switch.
struct ast_extenast_walk_context_extensions (struct ast_context *con, struct ast_exten *exten)
struct ast_ignorepatast_walk_context_ignorepats (struct ast_context *con, struct ast_ignorepat *ip)
struct ast_includeast_walk_context_includes (struct ast_context *con, struct ast_include *inc)
struct ast_swast_walk_context_switches (struct ast_context *con, struct ast_sw *sw)
struct ast_contextast_walk_contexts (struct ast_context *con)
struct ast_extenast_walk_extension_priorities (struct ast_exten *exten, struct ast_exten *priority)
int ast_wrlock_contexts (void)
static void * async_wait (void *data)
static int collect_digits (struct ast_channel *c, int waittime, char *buf, int buflen, int pos)
 collect digits from the channel into the buffer, return -1 on error, 0 on timeout or done.
static char * complete_show_application (const char *line, const char *word, int pos, int state)
static char * complete_show_applications (const char *line, const char *word, int pos, int state)
static char * complete_show_applications_deprecated (const char *line, const char *word, int pos, int state)
static char * complete_show_dialplan_context (const char *line, const char *word, int pos, int state)
static char * complete_show_function (const char *line, const char *word, int pos, int state)
static void decrease_call_count (void)
static void destroy_exten (struct ast_exten *e)
static int ext_cmp (const char *a, const char *b)
 the full routine to compare extensions in rules.
static int ext_cmp1 (const char **p, unsigned char *bitwise)
 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 int find_hint_by_cb_id (void *obj, void *arg, int flags)
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 1 minute
static int handle_set_global (int fd, int argc, char *argv[])
static int handle_set_global_deprecated (int fd, int argc, char *argv[])
 CLI support for setting global variables.
static int handle_show_application (int fd, int argc, char *argv[])
static int handle_show_application_deprecated (int fd, int argc, char *argv[])
static int handle_show_applications (int fd, int argc, char *argv[])
static int handle_show_applications_deprecated (int fd, int argc, char *argv[])
static int handle_show_dialplan (int fd, int argc, char *argv[])
static int handle_show_function (int fd, int argc, char *argv[])
static int handle_show_function_deprecated (int fd, int argc, char *argv[])
static int handle_show_functions (int fd, int argc, char *argv[])
static int handle_show_functions_deprecated (int fd, int argc, char *argv[])
static int handle_show_globals (int fd, int argc, char *argv[])
 CLI support for listing global variables in a parseable way.
static int handle_show_hints (int fd, int argc, char *argv[])
 handle_show_hints: CLI support for listing registered dial plan hints
static int handle_show_switches (int fd, int argc, char *argv[])
 handle_show_switches: CLI support for listing registered dial plan switches
static int hint_cmp (void *obj, void *arg, int flags)
static int hint_hash (const void *hint, const int flags)
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_proceeding (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_saydate (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 *)
static int pbx_builtin_saytime (struct ast_channel *, void *)
int pbx_builtin_serialize_variables (struct ast_channel *chan, char *buf, size_t size)
static int pbx_builtin_setamaflags (struct ast_channel *, void *)
static int pbx_builtin_setglobalvar (struct ast_channel *, void *)
int pbx_builtin_setvar (struct ast_channel *, void *)
void pbx_builtin_setvar_helper (struct ast_channel *chan, const char *name, const char *value)
static int pbx_builtin_wait (struct ast_channel *, void *)
static int pbx_builtin_waitexten (struct ast_channel *, void *)
int pbx_checkcondition (const char *condition)
 Evaluate a condition.
static void pbx_destroy (struct ast_pbx *p)
int pbx_exec (struct ast_channel *c, struct ast_app *app, void *data)
 Execute an application.
static int pbx_extension_helper (struct ast_channel *c, struct ast_context *con, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action)
 The return value depends on the action:.
static struct ast_extenpbx_find_extension (struct ast_channel *chan, struct ast_context *bypass, struct pbx_find_info *q, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action)
struct ast_apppbx_findapp (const char *app)
 Find application handle in linked list.
static struct ast_switchpbx_findswitch (const char *sw)
void pbx_retrieve_variable (struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp)
 pbx_retrieve_variable: Support for Asterisk built-in variables ---
int pbx_set_autofallthrough (int newval)
static void pbx_substitute_variables (char *passdata, int datalen, struct ast_channel *c, struct ast_exten *e)
void pbx_substitute_variables_helper (struct ast_channel *c, const char *cp1, char *cp2, int count)
static void pbx_substitute_variables_helper_full (struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count)
void pbx_substitute_variables_varshead (struct varshead *headp, const char *cp1, char *cp2, int count)
static void * pbx_thread (void *data)
static void print_ext (struct ast_exten *e, char *buf, int buflen)
 helper function to print an extension
static void set_ext_pri (struct ast_channel *c, const char *exten, int pri)
static int show_dialplan_helper (int fd, const char *context, const char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude, int includecount, const char *includes[])
static char * substring (const char *value, int offset, int length, char *workspace, size_t workspace_len)
 takes a substring. It is ok to call with value == workspace.
static void wait_for_hangup (struct ast_channel *chan, void *data)

Variables

static int autofallthrough = 1
static struct pbx_builtin builtins []
 Declaration of builtin applications.
static struct ast_cli_entry cli_set_global_deprecated
static struct ast_cli_entry cli_show_application_deprecated
static struct ast_cli_entry cli_show_applications_deprecated
static struct ast_cli_entry cli_show_dialplan_deprecated
static struct ast_cli_entry cli_show_function_deprecated
static struct ast_cli_entry cli_show_functions_deprecated
static struct ast_cli_entry cli_show_globals_deprecated
static struct ast_cli_entry cli_show_hints_deprecated
static struct ast_cli_entry cli_show_switches_deprecated
static struct ast_contextcontexts
static int countcalls
static char * days []
static struct cfextension_states extension_states []
static struct varshead globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE
static struct ao2_containerhints
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
static int totalcalls

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

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

#define BACKGROUND_MATCHEXTEN   (1 << 2)

Definition at line 91 of file pbx.c.

Referenced by pbx_builtin_background().

#define BACKGROUND_NOANSWER   (1 << 1)

Definition at line 90 of file pbx.c.

Referenced by pbx_builtin_background().

#define BACKGROUND_PLAYBACK   (1 << 3)

Definition at line 92 of file pbx.c.

Referenced by pbx_builtin_background().

#define BACKGROUND_SKIP   (1 << 0)

Definition at line 89 of file pbx.c.

Referenced by pbx_builtin_background().

#define EXT_DATA_SIZE   8192
Note:
I M P O R T A N T :

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

Definition at line 78 of file pbx.c.

Referenced by pbx_extension_helper(), and realtime_exec().

#define SAY_STUBS

Definition at line 55 of file pbx.c.

#define STATUS_NO_CONTEXT   1

Definition at line 964 of file pbx.c.

Referenced by pbx_extension_helper(), and pbx_find_extension().

#define STATUS_NO_EXTENSION   2

Definition at line 965 of file pbx.c.

Referenced by pbx_extension_helper(), and pbx_find_extension().

#define STATUS_NO_LABEL   4

Definition at line 967 of file pbx.c.

Referenced by pbx_extension_helper(), and pbx_find_extension().

#define STATUS_NO_PRIORITY   3

Definition at line 966 of file pbx.c.

Referenced by pbx_extension_helper(), and pbx_find_extension().

#define STATUS_SUCCESS   5

Definition at line 968 of file pbx.c.

Referenced by pbx_find_extension().

#define SWITCH_DATA_LENGTH   256

Definition at line 81 of file pbx.c.

#define VAR_BUF_SIZE   4096
#define VAR_HARDTRAN   3

Definition at line 87 of file pbx.c.

#define VAR_NORMAL   1

Definition at line 85 of file pbx.c.

#define VAR_SOFTTRAN   2

Definition at line 86 of file pbx.c.

#define WAITEXTEN_MOH   (1 << 0)

Definition at line 101 of file pbx.c.

Referenced by pbx_builtin_waitexten().


Enumeration Type Documentation

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

Enumerator:
E_MATCHMORE 
E_CANMATCH 
E_MATCH 
E_MATCH_MASK 
E_SPAWN 
E_FINDLABEL 

Definition at line 807 of file pbx.c.

00807                  {
00808    E_MATCHMORE =  0x00, /* extension can match but only with more 'digits' */
00809    E_CANMATCH =   0x01, /* extension can match with or without more 'digits' */
00810    E_MATCH =   0x02, /* extension is an exact match */
00811    E_MATCH_MASK = 0x03, /* mask for the argument to extension_match_core() */
00812    E_SPAWN =   0x12, /* want to spawn an extension. Requires exact match */
00813    E_FINDLABEL =  0x22  /* returns the priority for a given label. Requires exact match */
00814 };


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

References ast_calloc, ast_log(), ast_mutex_init(), ast_rdlock_contexts(), ast_unlock_contexts(), ast_verbose(), ast_wrlock_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().

03999 {
04000    struct ast_context *tmp, **local_contexts;
04001    int length = sizeof(struct ast_context) + strlen(name) + 1;
04002 
04003    if (!extcontexts) {
04004       ast_rdlock_contexts();
04005       local_contexts = &contexts;
04006    } else
04007       local_contexts = extcontexts;
04008 
04009    for (tmp = *local_contexts; tmp; tmp = tmp->next) {
04010       if (!strcasecmp(tmp->name, name)) {
04011          if (!existsokay) {
04012             ast_log(LOG_WARNING, "Tried to register context '%s', already in use\n", name);
04013             tmp = NULL;
04014          }
04015          if (!extcontexts)
04016             ast_unlock_contexts();
04017          return tmp;
04018       }
04019    }
04020    
04021    if (!extcontexts)
04022       ast_unlock_contexts();
04023 
04024    if ((tmp = ast_calloc(1, length))) {
04025       ast_mutex_init(&tmp->lock);
04026       ast_mutex_init(&tmp->macrolock);
04027       strcpy(tmp->name, name);
04028       tmp->registrar = registrar;
04029       if (!extcontexts)
04030          ast_wrlock_contexts();
04031       tmp->next = *local_contexts;
04032       *local_contexts = tmp;
04033       if (!extcontexts)
04034          ast_unlock_contexts();
04035       if (option_debug)
04036          ast_log(LOG_DEBUG, "Registered context '%s'\n", tmp->name);
04037       if (option_verbose > 2)
04038          ast_verbose( VERBOSE_PREFIX_3 "Registered extension context '%s'\n", tmp->name);
04039    }
04040 
04041    return tmp;
04042 }

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

Definition at line 5416 of file pbx.c.

References AST_LIST_REMOVE_HEAD, ast_log(), ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), 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().

05417 {
05418    struct ast_context *tmp, *tmpl=NULL;
05419    struct ast_include *tmpi;
05420    struct ast_sw *sw;
05421    struct ast_exten *e, *el, *en;
05422    struct ast_ignorepat *ipi;
05423 
05424    for (tmp = contexts; tmp; ) {
05425       struct ast_context *next;  /* next starting point */
05426       for (; tmp; tmpl = tmp, tmp = tmp->next) {
05427          if (option_debug)
05428             ast_log(LOG_DEBUG, "check ctx %s %s\n", tmp->name, tmp->registrar);
05429          if ( (!registrar || !strcasecmp(registrar, tmp->registrar)) &&
05430               (!con || !strcasecmp(tmp->name, con->name)) )
05431             break;   /* found it */
05432       }
05433       if (!tmp)   /* not found, we are done */
05434          break;
05435       ast_mutex_lock(&tmp->lock);
05436       if (option_debug)
05437          ast_log(LOG_DEBUG, "delete ctx %s %s\n", tmp->name, tmp->registrar);
05438       next = tmp->next;
05439       if (tmpl)
05440          tmpl->next = next;
05441       else
05442          contexts = next;
05443       /* Okay, now we're safe to let it go -- in a sense, we were
05444          ready to let it go as soon as we locked it. */
05445       ast_mutex_unlock(&tmp->lock);
05446       for (tmpi = tmp->includes; tmpi; ) { /* Free includes */
05447          struct ast_include *tmpil = tmpi;
05448          tmpi = tmpi->next;
05449          free(tmpil);
05450       }
05451       for (ipi = tmp->ignorepats; ipi; ) { /* Free ignorepats */
05452          struct ast_ignorepat *ipl = ipi;
05453          ipi = ipi->next;
05454          free(ipl);
05455       }
05456       while ((sw = AST_LIST_REMOVE_HEAD(&tmp->alts, list)))
05457          free(sw);
05458       for (e = tmp->root; e;) {
05459          for (en = e->peer; en;) {
05460             el = en;
05461             en = en->peer;
05462             destroy_exten(el);
05463          }
05464          el = e;
05465          e = e->next;
05466          destroy_exten(el);
05467       }
05468       ast_mutex_destroy(&tmp->lock);
05469       free(tmp);
05470       /* if we have a specific match, we are done, otherwise continue */
05471       tmp = con ? NULL : next;
05472    }
05473 }

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

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

06590 {
06591    int (*goto_func)(struct ast_channel *chan, const char *context, const char *exten, int priority);
06592 
06593    if (!chan)
06594       return -2;
06595 
06596    if (context == NULL)
06597       context = chan->context;
06598    if (exten == NULL)
06599       exten = chan->exten;
06600 
06601    goto_func = (async) ? ast_async_goto : ast_explicit_goto;
06602    if (ast_exists_extension(chan, context, exten, priority, chan->cid.cid_num))
06603       return goto_func(chan, context, exten, priority);
06604    else
06605       return -3;
06606 }

static int __ast_pbx_run ( struct ast_channel c  )  [static]

Definition at line 2435 of file pbx.c.

References ast_channel::_softhangup, ast_calloc, ast_cdr_end(), ast_cdr_update(), ast_channel_clear_softhangup(), ast_channel_lock, ast_channel_unlock, ast_clear_flag, ast_copy_string(), ast_exists_extension(), AST_FLAG_BRIDGE_HANGUP_RUN, 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_APPUNLOAD, AST_SOFTHANGUP_ASYNCGOTO, AST_SOFTHANGUP_TIMEOUT, ast_spawn_extension(), ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_verbose(), ast_channel::cdr, ast_channel::cid, ast_callerid::cid_num, collect_digits(), ast_channel::context, ast_pbx::dtimeout, ast_channel::exten, free, 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(), VERBOSE_PREFIX_2, VERBOSE_PREFIX_3, and ast_channel::whentohangup.

Referenced by ast_pbx_run(), and pbx_thread().

02436 {
02437    int found = 0; /* set if we find at least one match */
02438    int res = 0;
02439    int autoloopflag;
02440    int error = 0;    /* set an error conditions */
02441    const char *emc;
02442 
02443    /* A little initial setup here */
02444    if (c->pbx) {
02445       ast_log(LOG_WARNING, "%s already has PBX structure??\n", c->name);
02446       /* XXX and now what ? */
02447       free(c->pbx);
02448    }
02449    if (!(c->pbx = ast_calloc(1, sizeof(*c->pbx))))
02450       return -1;
02451    /* Set reasonable defaults */
02452    c->pbx->rtimeout = 10;
02453    c->pbx->dtimeout = 5;
02454 
02455    autoloopflag = ast_test_flag(c, AST_FLAG_IN_AUTOLOOP);   /* save value to restore at the end */
02456    ast_set_flag(c, AST_FLAG_IN_AUTOLOOP);
02457 
02458    /* Start by trying whatever the channel is set to */
02459    if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) {
02460       /* If not successful fall back to 's' */
02461       if (option_verbose > 1)
02462          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);
02463       /* XXX the original code used the existing priority in the call to
02464        * ast_exists_extension(), and reset it to 1 afterwards.
02465        * I believe the correct thing is to set it to 1 immediately.
02466        */
02467       set_ext_pri(c, "s", 1);
02468       if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) {
02469          /* JK02: And finally back to default if everything else failed */
02470          if (option_verbose > 1)
02471             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);
02472          ast_copy_string(c->context, "default", sizeof(c->context));
02473       }
02474    }
02475    if (c->cdr) {
02476       /* allow CDR variables that have been collected after channel was created to be visible during call */
02477       ast_cdr_update(c);
02478    }
02479    for (;;) {
02480       char dst_exten[256]; /* buffer to accumulate digits */
02481       int pos = 0;      /* XXX should check bounds */
02482       int digit = 0;
02483 
02484       /* loop on priorities in this context/exten */
02485       while (ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) {
02486          found = 1;
02487          if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num))) {
02488             /* Something bad happened, or a hangup has been requested. */
02489             if (strchr("0123456789ABCDEF*#", res)) {
02490                if (option_debug)
02491                   ast_log(LOG_DEBUG, "Oooh, got something to jump out with ('%c')!\n", res);
02492                pos = 0;
02493                dst_exten[pos++] = digit = res;
02494                dst_exten[pos] = '\0';
02495                break;
02496             }
02497             if (res == AST_PBX_KEEPALIVE) {
02498                if (option_debug)
02499                   ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
02500                if (option_verbose > 1)
02501                   ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
02502                error = 1;
02503                break;
02504             }
02505             if (option_debug)
02506                ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
02507             if (option_verbose > 1)
02508                ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
02509             if (c->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) {
02510                ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO);
02511             } else if (c->_softhangup & AST_SOFTHANGUP_TIMEOUT) {
02512                /* atimeout, nothing bad */
02513             } else {
02514                if (c->cdr)
02515                   ast_cdr_update(c);
02516                error = 1;
02517                break;
02518             }
02519          }
02520          if (c->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) {
02521             ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO);
02522          } else if (c->_softhangup & AST_SOFTHANGUP_TIMEOUT && ast_exists_extension(c,c->context,"T",1,c->cid.cid_num)) {
02523             set_ext_pri(c, "T", 0); /* 0 will become 1 with the c->priority++; at the end */
02524             /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
02525             c->whentohangup = 0;
02526             ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
02527          } else if (c->_softhangup) {
02528             if (option_debug)
02529                ast_log(LOG_DEBUG, "Extension %s, priority %d returned normally even though call was hung up\n",
02530                   c->exten, c->priority);
02531             error = 1;
02532             break;
02533          }
02534          c->priority++;
02535       } /* end while  - from here on we can use 'break' to go out */
02536       if (error)
02537          break;
02538 
02539       /* XXX we get here on non-existing extension or a keypress or hangup ? */
02540 
02541       if (!ast_exists_extension(c, c->context, c->exten, 1, c->cid.cid_num)) {
02542          /* If there is no match at priority 1, it is not a valid extension anymore.
02543           * Try to continue at "i", 1 or exit if the latter does not exist.
02544           */
02545          if (ast_exists_extension(c, c->context, "i", 1, c->cid.cid_num)) {
02546             if (option_verbose > 2)
02547                ast_verbose(VERBOSE_PREFIX_3 "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, c->name);
02548             pbx_builtin_setvar_helper(c, "INVALID_EXTEN", c->exten);
02549             set_ext_pri(c, "i", 1);
02550          } else {
02551             ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n",
02552                c->name, c->exten, c->context);
02553             error = 1; /* we know what to do with it */
02554             break;
02555          }
02556       } else if (c->_softhangup & AST_SOFTHANGUP_TIMEOUT) {
02557          /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */
02558          ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
02559       } else { /* keypress received, get more digits for a full extension */
02560          int waittime = 0;
02561          if (digit)
02562             waittime = c->pbx->dtimeout;
02563          else if (!autofallthrough)
02564             waittime = c->pbx->rtimeout;
02565          if (!waittime) {
02566             const char *status = pbx_builtin_getvar_helper(c, "DIALSTATUS");
02567             if (!status)
02568                status = "UNKNOWN";
02569             if (option_verbose > 2)
02570                ast_verbose(VERBOSE_PREFIX_2 "Auto fallthrough, channel '%s' status is '%s'\n", c->name, status);
02571             if (!strcasecmp(status, "CONGESTION"))
02572                res = pbx_builtin_congestion(c, "10");
02573             else if (!strcasecmp(status, "CHANUNAVAIL"))
02574                res = pbx_builtin_congestion(c, "10");
02575             else if (!strcasecmp(status, "BUSY"))
02576                res = pbx_builtin_busy(c, "10");
02577             error = 1; /* XXX disable message */
02578             break;   /* exit from the 'for' loop */
02579          }
02580 
02581          if (collect_digits(c, waittime, dst_exten, sizeof(dst_exten), pos))
02582             break;
02583          if (ast_exists_extension(c, c->context, dst_exten, 1, c->cid.cid_num)) /* Prepare the next cycle */
02584             set_ext_pri(c, dst_exten, 1);
02585          else {
02586             /* No such extension */
02587             if (!ast_strlen_zero(dst_exten)) {
02588                /* An invalid extension */
02589                if (ast_exists_extension(c, c->context, "i", 1, c->cid.cid_num)) {
02590                   if (option_verbose > 2)
02591                      ast_verbose( VERBOSE_PREFIX_3 "Invalid extension '%s' in context '%s' on %s\n", dst_exten, c->context, c->name);
02592                   pbx_builtin_setvar_helper(c, "INVALID_EXTEN", dst_exten);
02593                   set_ext_pri(c, "i", 1);
02594                } else {
02595                   ast_log(LOG_WARNING, "Invalid extension '%s', but no rule 'i' in context '%s'\n", dst_exten, c->context);
02596                   found = 1; /* XXX disable message */
02597                   break;
02598                }
02599             } else {
02600                /* A simple timeout */
02601                if (ast_exists_extension(c, c->context, "t", 1, c->cid.cid_num)) {
02602                   if (option_verbose > 2)
02603                      ast_verbose( VERBOSE_PREFIX_3 "Timeout on %s\n", c->name);
02604                   set_ext_pri(c, "t", 1);
02605                } else {
02606                   ast_log(LOG_WARNING, "Timeout, but no rule 't' in context '%s'\n", c->context);
02607                   found = 1; /* XXX disable message */
02608                   break;
02609                }
02610             }
02611          }
02612          if (c->cdr) {
02613             if (option_verbose > 2)
02614                ast_verbose(VERBOSE_PREFIX_2 "CDR updated on %s\n",c->name);
02615             ast_cdr_update(c);
02616          }
02617       }
02618    }
02619    if (!found && !error)
02620       ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name);
02621    if (res != AST_PBX_KEEPALIVE) {
02622       ast_softhangup(c, AST_SOFTHANGUP_APPUNLOAD);
02623    }
02624    ast_channel_lock(c);
02625    if ((emc = pbx_builtin_getvar_helper(c, "EXIT_MACRO_CONTEXT"))) {
02626       emc = ast_strdupa(emc);
02627    }
02628    ast_channel_unlock(c);
02629    if ((res != AST_PBX_KEEPALIVE) && !ast_test_flag(c, AST_FLAG_BRIDGE_HANGUP_RUN) &&
02630          ((emc && ast_exists_extension(c, emc, "h", 1, c->cid.cid_num)) ||
02631           (ast_exists_extension(c, c->context, "h", 1, c->cid.cid_num) && (emc = c->context)))) {
02632       ast_copy_string(c->context, emc, sizeof(c->context));
02633       set_ext_pri(c, "h", 1);
02634       if (c->cdr && ast_opt_end_cdr_before_h_exten) {
02635          ast_cdr_end(c->cdr);
02636       }
02637       while(ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) {
02638          if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num))) {
02639             /* Something bad happened, or a hangup has been requested. */
02640             if (option_debug)
02641                ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
02642             if (option_verbose > 1)
02643                ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
02644             break;
02645          }
02646          c->priority++;
02647       }
02648    }
02649    ast_set2_flag(c, autoloopflag, AST_FLAG_IN_AUTOLOOP);
02650    ast_clear_flag(c, AST_FLAG_BRIDGE_HANGUP_RUN); /* from one round to the next, make sure this gets cleared */
02651    pbx_destroy(c->pbx);
02652    c->pbx = NULL;
02653    if (res != AST_PBX_KEEPALIVE)
02654       ast_hangup(c);
02655    return 0;
02656 }

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

Definition at line 825 of file pbx.c.

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

Referenced by extension_match_core().

00826 {
00827    mode &= E_MATCH_MASK;   /* only consider the relevant bits */
00828 
00829    if ( (mode == E_MATCH) && (pattern[0] == '_') && (strcasecmp(pattern,data)==0) ) /* note: if this test is left out, then _x. will not match _x. !!! */
00830       return 1;
00831 
00832    if (pattern[0] != '_') { /* not a pattern, try exact or partial match */
00833       int ld = strlen(data), lp = strlen(pattern);
00834 
00835       if (lp < ld)      /* pattern too short, cannot match */
00836          return 0;
00837       /* depending on the mode, accept full or partial match or both */
00838       if (mode == E_MATCH)
00839          return !strcmp(pattern, data); /* 1 on match, 0 on fail */
00840       if (ld == 0 || !strncasecmp(pattern, data, ld)) /* partial or full match */
00841          return (mode == E_MATCHMORE) ? lp > ld : 1; /* XXX should consider '!' and '/' ? */
00842       else
00843          return 0;
00844    }
00845    pattern++; /* skip leading _ */
00846    /*
00847     * XXX below we stop at '/' which is a separator for the CID info. However we should
00848     * not store '/' in the pattern at all. When we insure it, we can remove the checks.
00849     */
00850    while (*data && *pattern && *pattern != '/') {
00851       const char *end;
00852 
00853       if (*data == '-') { /* skip '-' in data (just a separator) */
00854          data++;
00855          continue;
00856       }
00857       switch (toupper(*pattern)) {
00858       case '[':   /* a range */
00859          end = strchr(pattern+1, ']'); /* XXX should deal with escapes ? */
00860          if (end == NULL) {
00861             ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n");
00862             return 0;   /* unconditional failure */
00863          }
00864          for (pattern++; pattern != end; pattern++) {
00865             if (pattern+2 < end && pattern[1] == '-') { /* this is a range */
00866                if (*data >= pattern[0] && *data <= pattern[2])
00867                   break;   /* match found */
00868                else {
00869                   pattern += 2; /* skip a total of 3 chars */
00870                   continue;
00871                }
00872             } else if (*data == pattern[0])
00873                break;   /* match found */
00874          }
00875          if (pattern == end)
00876             return 0;
00877          pattern = end; /* skip and continue */
00878          break;
00879       case 'N':
00880          if (*data < '2' || *data > '9')
00881             return 0;
00882          break;
00883       case 'X':
00884          if (*data < '0' || *data > '9')
00885             return 0;
00886          break;
00887       case 'Z':
00888          if (*data < '1' || *data > '9')
00889             return 0;
00890          break;
00891       case '.':   /* Must match, even with more digits */
00892          return 1;
00893       case '!':   /* Early match */
00894          return 2;
00895       case ' ':
00896       case '-':   /* Ignore these in patterns */
00897          data--; /* compensate the final data++ */
00898          break;
00899       default:
00900          if (*data != *pattern)
00901             return 0;
00902       }
00903       data++;
00904       pattern++;
00905    }
00906    if (*data)        /* data longer than pattern, no match */
00907       return 0;
00908    /*
00909     * match so far, but ran off the end of the data.
00910     * Depending on what is next, determine match or not.
00911     */
00912    if (*pattern == '\0' || *pattern == '/')  /* exact match */
00913       return (mode == E_MATCHMORE) ? 0 : 1;  /* this is a failure for E_MATCHMORE */
00914    else if (*pattern == '!')        /* early match */
00915       return 2;
00916    else                 /* partial match */
00917       return (mode == E_MATCH) ? 0 : 1;   /* this is a failure for E_MATCH */
00918 }

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

04812 {
04813    struct ast_exten *ep;
04814 
04815    for (ep = NULL; e ; ep = e, e = e->peer) {
04816       if (e->priority >= tmp->priority)
04817          break;
04818    }
04819    if (!e) {   /* go at the end, and ep is surely set because the list is not empty */
04820       ep->peer = tmp;
04821       return 0;   /* success */
04822    }
04823    if (e->priority == tmp->priority) {
04824       /* Can't have something exactly the same.  Is this a
04825          replacement?  If so, replace, otherwise, bonk. */
04826       if (!replace) {
04827          ast_log(LOG_WARNING, "Unable to register extension '%s', priority %d in '%s', already in use\n", tmp->exten, tmp->priority, con->name);
04828          if (tmp->datad)
04829             tmp->datad(tmp->data);
04830          free(tmp);
04831          return -1;
04832       }
04833       /* we are replacing e, so copy the link fields and then update
04834        * whoever pointed to e to point to us
04835        */
04836       tmp->next = e->next; /* not meaningful if we are not first in the peer list */
04837       tmp->peer = e->peer; /* always meaningful */
04838       if (ep)        /* We're in the peer list, just insert ourselves */
04839          ep->peer = tmp;
04840       else if (el)      /* We're the first extension. Take over e's functions */
04841          el->next = tmp;
04842       else        /* We're the very first extension.  */
04843          con->root = tmp;
04844       if (tmp->priority == PRIORITY_HINT)
04845          ast_change_hint(e,tmp);
04846       /* Destroy the old one */
04847       if (e->datad)
04848          e->datad(e->data);
04849       free(e);
04850    } else { /* Slip ourselves in just before e */
04851       tmp->peer = e;
04852       tmp->next = e->next; /* extension chain, or NULL if e is not the first extension */
04853       if (ep)        /* Easy enough, we're just in the peer list */
04854          ep->peer = tmp;
04855       else {         /* we are the first in some peer list, so link in the ext list */
04856          if (el)
04857             el->next = tmp;   /* in the middle... */
04858          else
04859             con->root = tmp; /* ... or at the head */
04860          e->next = NULL;   /* e is no more at the head, so e->next must be reset */
04861       }
04862       /* And immediately return success. */
04863       if (tmp->priority == PRIORITY_HINT)
04864           ast_add_hint(tmp);
04865    }
04866    return 0;
04867 }

int ast_active_calls ( void   ) 

Retrieve the number of active calls.

Definition at line 2764 of file pbx.c.

Referenced by handle_chanlist(), and handle_chanlist_deprecated().

02765 {
02766    return countcalls;
02767 }

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

04682 {
04683    int ret = -1;
04684    struct ast_context *c = find_context_locked(context);
04685 
04686    if (c) {
04687       ret = ast_add_extension2(c, replace, extension, priority, label, callerid,
04688          application, data, datad, registrar);
04689       ast_unlock_contexts();
04690    }
04691    return ret;
04692 }

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 4894 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, 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(), do_parking_thread(), load_config(), park_call_full(), pbx_load_config(), pbx_load_users(), sla_build_station(), and sla_build_trunk().

04898 {
04899    /*
04900     * Sort extensions (or patterns) according to the rules indicated above.
04901     * These are implemented by the function ext_cmp()).
04902     * All priorities for the same ext/pattern/cid are kept in a list,
04903     * using the 'peer' field  as a link field..
04904     */
04905    struct ast_exten *tmp, *e, *el = NULL;
04906    int res;
04907    int length;
04908    char *p;
04909    char expand_buf[VAR_BUF_SIZE] = { 0, };
04910 
04911    /* if we are adding a hint, and there are global variables, and the hint
04912       contains variable references, then expand them
04913    */
04914    ast_mutex_lock(&globalslock);
04915    if (priority == PRIORITY_HINT && AST_LIST_FIRST(&globals) && strstr(application, "${")) {
04916       pbx_substitute_variables_varshead(&globals, application, expand_buf, sizeof(expand_buf));
04917       application = expand_buf;
04918    }
04919    ast_mutex_unlock(&globalslock);
04920 
04921    length = sizeof(struct ast_exten);
04922    length += strlen(extension) + 1;
04923    length += strlen(application) + 1;
04924    if (label)
04925       length += strlen(label) + 1;
04926    if (callerid)
04927       length += strlen(callerid) + 1;
04928    else
04929       length ++;  /* just the '\0' */
04930 
04931    /* Be optimistic:  Build the extension structure first */
04932    if (!(tmp = ast_calloc(1, length)))
04933       return -1;
04934 
04935    /* use p as dst in assignments, as the fields are const char * */
04936    p = tmp->stuff;
04937    if (label) {
04938       tmp->label = p;
04939       strcpy(p, label);
04940       p += strlen(label) + 1;
04941    }
04942    tmp->exten = p;
04943    p += ext_strncpy(p, extension, strlen(extension) + 1) + 1;
04944    tmp->priority = priority;
04945    tmp->cidmatch = p;   /* but use p for assignments below */
04946    if (callerid) {
04947       p += ext_strncpy(p, callerid, strlen(callerid) + 1) + 1;
04948       tmp->matchcid = 1;
04949    } else {
04950       *p++ = '\0';
04951       tmp->matchcid = 0;
04952    }
04953    tmp->app = p;
04954    strcpy(p, application);
04955    tmp->parent = con;
04956    tmp->data = data;
04957    tmp->datad = datad;
04958    tmp->registrar = registrar;
04959 
04960    ast_mutex_lock(&con->lock);
04961    res = 0; /* some compilers will think it is uninitialized otherwise */
04962    for (e = con->root; e; el = e, e = e->next) {   /* scan the extension list */
04963       res = ext_cmp(e->exten, tmp->exten);
04964       if (res == 0) { /* extension match, now look at cidmatch */
04965          if (!e->matchcid && !tmp->matchcid)
04966             res = 0;
04967          else if (tmp->matchcid && !e->matchcid)
04968             res = 1;
04969          else if (e->matchcid && !tmp->matchcid)
04970             res = -1;
04971          else
04972             res = ext_cmp(e->cidmatch, tmp->cidmatch);
04973       }
04974       if (res >= 0)
04975          break;
04976    }
04977    if (e && res == 0) { /* exact match, insert in the pri chain */
04978       res = add_pri(con, tmp, el, e, replace);
04979       ast_mutex_unlock(&con->lock);
04980       if (res < 0) {
04981          errno = EEXIST;   /* XXX do we care ? */
04982          return 0; /* XXX should we return -1 maybe ? */
04983       }
04984    } else {
04985       /*
04986        * not an exact match, this is the first entry with this pattern,
04987        * so insert in the main list right before 'e' (if any)
04988        */
04989       tmp->next = e;
04990       if (el)
04991          el->next = tmp;
04992       else
04993          con->root = tmp;
04994       ast_mutex_unlock(&con->lock);
04995       if (tmp->priority == PRIORITY_HINT)
04996          ast_add_hint(tmp);
04997    }
04998    if (option_debug) {
04999       if (tmp->matchcid) {
05000          if (option_debug)
05001             ast_log(LOG_DEBUG, "Added extension '%s' priority %d (CID match '%s') to %s\n",
05002                tmp->exten, tmp->priority, tmp->cidmatch, con->name);
05003       } else {
05004          if (option_debug)
05005             ast_log(LOG_DEBUG, "Added extension '%s' priority %d to %s\n",
05006                tmp->exten, tmp->priority, con->name);
05007       }
05008    }
05009    if (option_verbose > 2) {
05010       if (tmp->matchcid) {
05011          ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d (CID match '%s')to %s\n",
05012             tmp->exten, tmp->priority, tmp->cidmatch, con->name);
05013       } else {
05014          ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d to %s\n",
05015             tmp->exten, tmp->priority, con->name);
05016       }
05017    }
05018    return 0;
05019 }

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

References ao2_alloc(), ao2_find(), ao2_ref(), ast_extension_state2(), ast_get_extension_app(), ast_get_extension_name(), ast_hint_destroy(), ast_log(), ast_hint::exten, ast_hint::laststate, LOG_DEBUG, and option_debug.

Referenced by add_pri(), and ast_add_extension2().

02259 {
02260    struct ast_hint *hint;
02261 
02262    if (!e) {
02263       return -1;
02264    }
02265 
02266    hint = ao2_find(hints, e, 0);
02267 
02268    if (hint) {
02269       if (option_debug > 1)
02270          ast_log(LOG_DEBUG, "HINTS: Not re-adding existing hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e));
02271       ao2_ref(hint, -1);
02272       return -1;
02273    }
02274 
02275    if (option_debug > 1)
02276       ast_log(LOG_DEBUG, "HINTS: Adding hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e));
02277 
02278    if (!(hint = ao2_alloc(sizeof(*hint), ast_hint_destroy))) {
02279       return -1;
02280    }
02281 
02282    /* Initialize and insert new item at the top */
02283    hint->exten = e;
02284    hint->laststate = ast_extension_state2(e);
02285 
02286    ao2_link(hints, hint);
02287 
02288    ao2_ref(hint, -1);
02289 
02290    return 0;
02291 }

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

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

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

04718 {
04719    int res = 0;
04720 
04721    ast_channel_lock(chan);
04722 
04723    if (chan->pbx) { /* This channel is currently in the PBX */
04724       ast_explicit_goto(chan, context, exten, priority);
04725       ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO);
04726    } else {
04727       /* In order to do it when the channel doesn't really exist within
04728          the PBX, we have to make a new channel, masquerade, and start the PBX
04729          at the new location */
04730       struct ast_channel *tmpchan = ast_channel_alloc(0, chan->_state, 0, 0, chan->accountcode, chan->exten, chan->context, chan->amaflags, "AsyncGoto/%s", chan->name);
04731       if (!tmpchan) {
04732          res = -1;
04733       } else {
04734          if (chan->cdr) {
04735             ast_cdr_discard(tmpchan->cdr);
04736             tmpchan->cdr = ast_cdr_dup(chan->cdr);  /* share the love */
04737          }
04738          /* Make formats okay */
04739          tmpchan->readformat = chan->readformat;
04740          tmpchan->writeformat = chan->writeformat;
04741          /* Setup proper location */
04742          ast_explicit_goto(tmpchan,
04743             S_OR(context, chan->context), S_OR(exten, chan->exten), priority);
04744 
04745          /* Masquerade into temp channel */
04746          if (ast_channel_masquerade(tmpchan, chan)) {
04747             /* Failed to set up the masquerade.  It's probably chan_local
04748              * in the middle of optimizing itself out.  Sad. :( */
04749             ast_hangup(tmpchan);
04750             tmpchan = NULL;
04751             res = -1;
04752          } else {
04753             /* Grab the locks and get going */
04754             ast_channel_lock(tmpchan);
04755             ast_do_masquerade(tmpchan);
04756             ast_channel_unlock(tmpchan);
04757             /* Start the PBX going on our stolen channel */
04758             if (ast_pbx_start(tmpchan)) {
04759                ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name);
04760                ast_hangup(tmpchan);
04761                res = -1;
04762             }
04763          }
04764       }
04765    }
04766    ast_channel_unlock(chan);
04767    return res;
04768 }

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

Definition at line 4770 of file pbx.c.

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

04771 {
04772    struct ast_channel *chan;
04773    int res = -1;
04774 
04775    chan = ast_get_channel_by_name_locked(channame);
04776    if (chan) {
04777       res = ast_async_goto(chan, context, exten, priority);
04778       ast_channel_unlock(chan);
04779    }
04780    return res;
04781 }

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

References __ast_goto_if_exists().

Referenced by asyncgoto_exec().

06614 {
06615    return __ast_goto_if_exists(chan, context, exten, priority, 1);
06616 }

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

Definition at line 4357 of file pbx.c.

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

04358 {
04359    char info_save[256];
04360    char *info;
04361 
04362    /* Check for empty just in case */
04363    if (ast_strlen_zero(info_in))
04364       return 0;
04365    /* make a copy just in case we were passed a static string */
04366    ast_copy_string(info_save, info_in, sizeof(info_save));
04367    info = info_save;
04368    /* Assume everything except time */
04369    i->monthmask = 0xfff;   /* 12 bits */
04370    i->daymask = 0x7fffffffU; /* 31 bits */
04371    i->dowmask = 0x7f; /* 7 bits */
04372    /* on each call, use strsep() to move info to the next argument */
04373    get_timerange(i, strsep(&info, "|"));
04374    if (info)
04375       i->dowmask = get_range(strsep(&info, "|"), 7, days, "day of week");
04376    if (info)
04377       i->daymask = get_range(strsep(&info, "|"), 31, NULL, "day");
04378    if (info)
04379       i->monthmask = get_range(strsep(&info, "|"), 12, months, "month");
04380    return 1;
04381 }

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
Note:
It is possible for autoservice to be started and stopped on c during this function call, it is important that c is not locked prior to calling this. Otherwise a deadlock may occur
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 2381 of file pbx.c.

References E_CANMATCH, and pbx_extension_helper().

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

02382 {
02383    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH);
02384 }

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

References ao2_find(), ao2_lock(), ao2_ref(), ao2_unlock(), and ast_hint::exten.

Referenced by add_pri().

02295 {
02296    struct ast_hint *hint;
02297 
02298    hint = ao2_find(hints, oe, 0);
02299 
02300    if (!hint) {
02301       return -1;
02302    }
02303 
02304    ao2_lock(hint);
02305    hint->exten = ne;
02306    ao2_unlock(hint);
02307    ao2_ref(hint, -1);
02308 
02309    return 0;
02310 }

int ast_check_timing ( const struct ast_timing i  ) 

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

04384 {
04385    struct tm tm;
04386    time_t t = time(NULL);
04387 
04388    ast_localtime(&t, &tm, NULL);
04389 
04390    /* If it's not the right month, return */
04391    if (!(i->monthmask & (1 << tm.tm_mon)))
04392       return 0;
04393 
04394    /* If it's not that time of the month.... */
04395    /* Warning, tm_mday has range 1..31! */
04396    if (!(i->daymask & (1 << (tm.tm_mday-1))))
04397       return 0;
04398 
04399    /* If it's not the right day of the week */
04400    if (!(i->dowmask & (1 << tm.tm_wday)))
04401       return 0;
04402 
04403    /* Sanity check the hour just to be safe */
04404    if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) {
04405       ast_log(LOG_WARNING, "Insane time...\n");
04406       return 0;
04407    }
04408 
04409    /* Now the tough part, we calculate if it fits
04410       in the right time based on min/hour */
04411    if (!(i->minmask[tm.tm_hour * 2 + (tm.tm_min >= 30 ? 1 : 0)] & (1 << (tm.tm_min >= 30 ? tm.tm_min - 30 : tm.tm_min))))
04412       return 0;
04413 
04414    /* If we got this far, then we're good */
04415    return 1;
04416 }

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

04611 {
04612    int ret = -1;
04613    struct ast_context *c = find_context_locked(context);
04614 
04615    if (c) {
04616       ret = ast_context_add_ignorepat2(c, value, registrar);
04617       ast_unlock_contexts();
04618    }
04619    return ret;
04620 }

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

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

04623 {
04624    struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL;
04625    int length;
04626    char *pattern;
04627    length = sizeof(struct ast_ignorepat);
04628    length += strlen(value) + 1;
04629    if (!(ignorepat = ast_calloc(1, length)))
04630       return -1;
04631    /* The cast to char * is because we need to write the initial value.
04632     * The field is not supposed to be modified otherwise.  Also, gcc 4.2
04633     * sees the cast as dereferencing a type-punned pointer and warns about
04634     * it.  This is the workaround (we're telling gcc, yes, that's really
04635     * what we wanted to do).
04636     */
04637    pattern = (char *) ignorepat->pattern;
04638    strcpy(pattern, value);
04639    ignorepat->next = NULL;
04640    ignorepat->registrar = registrar;
04641    ast_mutex_lock(&con->lock);
04642    for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) {
04643       ignorepatl = ignorepatc;
04644       if (!strcasecmp(ignorepatc->pattern, value)) {
04645          /* Already there */
04646          ast_mutex_unlock(&con->lock);
04647          errno = EEXIST;
04648          return -1;
04649       }
04650    }
04651    if (ignorepatl)
04652       ignorepatl->next = ignorepat;
04653    else
04654       con->ignorepats = ignorepat;
04655    ast_mutex_unlock(&con->lock);
04656    return 0;
04657 
04658 }

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

04188 {
04189    int ret = -1;
04190    struct ast_context *c = find_context_locked(context);
04191 
04192    if (c) {
04193       ret = ast_context_add_include2(c, include, registrar);
04194       ast_unlock_contexts();
04195    }
04196    return ret;
04197 }

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

04427 {
04428    struct ast_include *new_include;
04429    char *c;
04430    struct ast_include *i, *il = NULL; /* include, include_last */
04431    int length;
04432    char *p;
04433 
04434    length = sizeof(struct ast_include);
04435    length += 2 * (strlen(value) + 1);
04436 
04437    /* allocate new include structure ... */
04438    if (!(new_include = ast_calloc(1, length)))
04439       return -1;
04440    /* Fill in this structure. Use 'p' for assignments, as the fields
04441     * in the structure are 'const char *'
04442     */
04443    p = new_include->stuff;
04444    new_include->name = p;
04445    strcpy(p, value);
04446    p += strlen(value) + 1;
04447    new_include->rname = p;
04448    strcpy(p, value);
04449    /* Strip off timing info, and process if it is there */
04450    if ( (c = strchr(p, '|')) ) {
04451       *c++ = '\0';
04452            new_include->hastime = ast_build_timing(&(new_include->timing), c);
04453    }
04454    new_include->next      = NULL;
04455    new_include->registrar = registrar;
04456 
04457    ast_mutex_lock(&con->lock);
04458 
04459    /* ... go to last include and check if context is already included too... */
04460    for (i = con->includes; i; i = i->next) {
04461       if (!strcasecmp(i->name, new_include->name)) {
04462          free(new_include);
04463          ast_mutex_unlock(&con->lock);
04464          errno = EEXIST;
04465          return -1;
04466       }
04467       il = i;
04468    }
04469 
04470    /* ... include new context into context list, unlock, return */
04471    if (il)
04472       il->next = new_include;
04473    else
04474       con->includes = new_include;
04475    if (option_verbose > 2)
04476       ast_verbose(VERBOSE_PREFIX_3 "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con));
04477    ast_mutex_unlock(&con->lock);
04478 
04479    return 0;
04480 }

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

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

04488 {
04489    int ret = -1;
04490    struct ast_context *c = find_context_locked(context);
04491 
04492    if (c) { /* found, add switch to this context */
04493       ret = ast_context_add_switch2(c, sw, data, eval, registrar);
04494       ast_unlock_contexts();
04495    }
04496    return ret;
04497 }

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

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

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

04508 {
04509    struct ast_sw *new_sw;
04510    struct ast_sw *i;
04511    int length;
04512    char *p;
04513 
04514    length = sizeof(struct ast_sw);
04515    length += strlen(value) + 1;
04516    if (data)
04517       length += strlen(data);
04518    length++;
04519 
04520    /* allocate new sw structure ... */
04521    if (!(new_sw = ast_calloc(1, length)))
04522       return -1;
04523    /* ... fill in this structure ... */
04524    p = new_sw->stuff;
04525    new_sw->name = p;
04526    strcpy(new_sw->name, value);
04527    p += strlen(value) + 1;
04528    new_sw->data = p;
04529    if (data) {
04530       strcpy(new_sw->data, data);
04531       p += strlen(data) + 1;
04532    } else {
04533       strcpy(new_sw->data, "");
04534       p++;
04535    }
04536    new_sw->eval     = eval;
04537    new_sw->registrar = registrar;
04538 
04539    /* ... try to lock this context ... */
04540    ast_mutex_lock(&con->lock);
04541 
04542    /* ... go to last sw and check if context is already swd too... */
04543    AST_LIST_TRAVERSE(&con->alts, i, list) {
04544       if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) {
04545          free(new_sw);
04546          ast_mutex_unlock(&con->lock);
04547          errno = EEXIST;
04548          return -1;
04549       }
04550    }
04551 
04552    /* ... sw new context into context list, unlock, return */
04553    AST_LIST_INSERT_TAIL(&con->alts, new_sw, list);
04554 
04555    if (option_verbose > 2)
04556       ast_verbose(VERBOSE_PREFIX_3 "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con));
04557 
04558    ast_mutex_unlock(&con->lock);
04559 
04560    return 0;
04561 }

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

References __ast_context_create().

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

04045 {
04046    return __ast_context_create(extcontexts, name, registrar, 0);
04047 }

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

05476 {
05477    ast_wrlock_contexts();
05478    __ast_context_destroy(con,registrar);
05479    ast_unlock_contexts();
05480 }

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

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

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

00949 {
00950    struct ast_context *tmp = NULL;
00951 
00952    ast_rdlock_contexts();
00953 
00954    while ( (tmp = ast_walk_contexts(tmp)) ) {
00955       if (!name || !strcasecmp(name, tmp->name))
00956          break;
00957    }
00958 
00959    ast_unlock_contexts();
00960 
00961    return tmp;
00962 }

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

Definition at line 4049 of file pbx.c.

References __ast_context_create().

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

04050 {
04051    return __ast_context_create(extcontexts, name, registrar, 1);
04052 }

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

03007 {
03008    struct ast_context *c = NULL;
03009    int ret = -1;
03010 
03011    ast_rdlock_contexts();
03012 
03013    while ((c = ast_walk_contexts(c))) {
03014       if (!strcmp(ast_get_context_name(c), context)) {
03015          ret = 0;
03016          break;
03017       }
03018    }
03019 
03020    ast_unlock_contexts();
03021 
03022    /* if we found context, lock macrolock */
03023    if (ret == 0) 
03024       ret = ast_mutex_lock(&c->macrolock);
03025 
03026    return ret;
03027 }

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 (0 to remove all)
callerid NULL to remove all; non-NULL to match a single record per priority
matchcid non-zero to match callerid element (if non-NULL); 0 to match default case
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 2907 of file pbx.c.

References ast_context_remove_extension_callerid().

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

02908 {
02909    return ast_context_remove_extension_callerid(context, extension, priority, NULL, 0, registrar);
02910 }

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

References ast_context_remove_extension_callerid2().

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

02935 {
02936    return ast_context_remove_extension_callerid2(con, extension, priority, NULL, 0, registrar);
02937 }

int ast_context_remove_extension_callerid ( const char *  context,
const char *  extension,
int  priority,
const char *  callerid,
int  matchcid,
const char *  registrar 
)

Definition at line 2912 of file pbx.c.

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

Referenced by ast_context_remove_extension(), handle_context_remove_extension(), and handle_context_remove_extension_deprecated().

02913 {
02914    int ret = -1; /* default error return */
02915    struct ast_context *c = find_context_locked(context);
02916 
02917    if (c) { /* ... remove extension ... */
02918       ret = ast_context_remove_extension_callerid2(c, extension, priority, callerid, matchcid, registrar);
02919       ast_unlock_contexts();
02920    }
02921    return ret;
02922 }

int ast_context_remove_extension_callerid2 ( struct ast_context con,
const char *  extension,
int  priority,
const char *  callerid,
int  matchcid,
const char *  registrar 
)

Definition at line 2939 of file pbx.c.

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

Referenced by ast_context_remove_extension2(), and ast_context_remove_extension_callerid().

02940 {
02941    struct ast_exten *exten, *prev_exten = NULL;
02942    struct ast_exten *peer;
02943    struct ast_exten *previous_peer = NULL;
02944    struct ast_exten *next_peer = NULL;
02945    int found = 0;
02946 
02947    ast_mutex_lock(&con->lock);
02948 
02949    /* scan the extension list to find first matching extension-registrar */
02950    for (exten = con->root; exten; prev_exten = exten, exten = exten->next) {
02951       if (!strcmp(exten->exten, extension) &&
02952          (!registrar || !strcmp(exten->registrar, registrar)))
02953          break;
02954    }
02955    if (!exten) {
02956       /* we can't find right extension */
02957       ast_mutex_unlock(&con->lock);
02958       return -1;
02959    }
02960 
02961    /* scan the priority list to remove extension with exten->priority == priority */
02962    for (peer = exten, next_peer = exten->peer ? exten->peer : exten->next;
02963          peer && !strcmp(peer->exten, extension);
02964          peer = next_peer, next_peer = next_peer ? (next_peer->peer ? next_peer->peer : next_peer->next) : NULL) {
02965       if ((priority == 0 || peer->priority == priority) &&
02966             (!callerid || !matchcid || (matchcid && !strcmp(peer->cidmatch, callerid))) &&
02967             (!registrar || !strcmp(peer->registrar, registrar) )) {
02968          found = 1;
02969 
02970          /* we are first priority extension? */
02971          if (!previous_peer) {
02972             /*
02973              * We are first in the priority chain, so must update the extension chain.
02974              * The next node is either the next priority or the next extension
02975              */
02976             struct ast_exten *next_node = peer->peer ? peer->peer : peer->next;
02977 
02978             if (!prev_exten) {   /* change the root... */
02979                con->root = next_node;
02980             } else {
02981                prev_exten->next = next_node; /* unlink */
02982             }
02983             if (peer->peer)   { /* update the new head of the pri list */
02984                peer->peer->next = peer->next;
02985             }
02986          } else { /* easy, we are not first priority in extension */
02987             previous_peer->peer = peer->peer;
02988          }
02989 
02990          /* now, free whole priority extension */
02991          destroy_exten(peer);
02992       } else {
02993          previous_peer = peer;
02994       }
02995    }
02996    ast_mutex_unlock(&con->lock);
02997    return found ? 0 : -1;
02998 }

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

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

04568 {
04569    int ret = -1;
04570    struct ast_context *c = find_context_locked(context);
04571 
04572    if (c) {
04573       ret = ast_context_remove_ignorepat2(c, ignorepat, registrar);
04574       ast_unlock_contexts();
04575    }
04576    return ret;
04577 }

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

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

04580 {
04581    struct ast_ignorepat *ip, *ipl = NULL;
04582 
04583    ast_mutex_lock(&con->lock);
04584 
04585    for (ip = con->ignorepats; ip; ip = ip->next) {
04586       if (!strcmp(ip->pattern, ignorepat) &&
04587          (!registrar || (registrar == ip->registrar))) {
04588          if (ipl) {
04589             ipl->next = ip->next;
04590             free(ip);
04591          } else {
04592             con->ignorepats = ip->next;
04593             free(ip);
04594          }
04595          ast_mutex_unlock(&con->lock);
04596          return 0;
04597       }
04598       ipl = ip;
04599    }
04600 
04601    ast_mutex_unlock(&con->lock);
04602    errno = EINVAL;
04603    return -1;
04604 }

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

02804 {
02805    int ret = -1;
02806    struct ast_context *c = find_context_locked(context);
02807 
02808    if (c) {
02809       /* found, remove include from this context ... */
02810       ret = ast_context_remove_include2(c, include, registrar);
02811       ast_unlock_contexts();
02812    }
02813    return ret;
02814 }

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

02825 {
02826    struct ast_include *i, *pi = NULL;
02827    int ret = -1;
02828 
02829    ast_mutex_lock(&con->lock);
02830 
02831    /* find our include */
02832    for (i = con->includes; i; pi = i, i = i->next) {
02833       if (!strcmp(i->name, include) &&
02834             (!registrar || !strcmp(i->registrar, registrar))) {
02835          /* remove from list */
02836          if (pi)
02837             pi->next = i->next;
02838          else
02839             con->includes = i->next;
02840          /* free include and return */
02841          free(i);
02842          ret = 0;
02843          break;
02844       }
02845    }
02846 
02847    ast_mutex_unlock(&con->lock);
02848    return ret;
02849 }

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

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

02857 {
02858    int ret = -1; /* default error return */
02859    struct ast_context *c = find_context_locked(context);
02860 
02861    if (c) {
02862       /* remove switch from this context ... */
02863       ret = ast_context_remove_switch2(c, sw, data, registrar);
02864       ast_unlock_contexts();
02865    }
02866    return ret;
02867 }

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

02878 {
02879    struct ast_sw *i;
02880    int ret = -1;
02881 
02882    ast_mutex_lock(&con->lock);
02883 
02884    /* walk switches */
02885    AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) {
02886       if (!strcmp(i->name, sw) && !strcmp(i->data, data) &&
02887          (!registrar || !strcmp(i->registrar, registrar))) {
02888          /* found, remove from list */
02889          AST_LIST_REMOVE_CURRENT(&con->alts, list);
02890          free(i); /* free switch and return */
02891          ret = 0;
02892          break;
02893       }
02894    }
02895    AST_LIST_TRAVERSE_SAFE_END
02896 
02897    ast_mutex_unlock(&con->lock);
02898 
02899    return ret;
02900 }

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

03035 {
03036    struct ast_context *c = NULL;
03037    int ret = -1;
03038 
03039    ast_rdlock_contexts();
03040 
03041    while ((c = ast_walk_contexts(c))) {
03042       if (!strcmp(ast_get_context_name(c), context)) {
03043          ret = 0;
03044          break;
03045       }
03046    }
03047 
03048    ast_unlock_contexts();
03049 
03050    /* if we found context, unlock macrolock */
03051    if (ret == 0) 
03052       ret = ast_mutex_unlock(&c->macrolock);
03053 
03054    return ret;
03055 }

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

06571 {
06572    struct ast_include *inc = NULL;
06573    int res = 0;
06574 
06575    while ( (inc = ast_walk_context_includes(con, inc)) ) {
06576       if (ast_context_find(inc->rname))
06577          continue;
06578 
06579       res = -1;
06580       ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n",
06581          ast_get_context_name(con), inc->rname);
06582       break;
06583    }
06584 
06585    return res;
06586 }

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

Definition at line 1510 of file pbx.c.

References ast_custom_function::acflist, 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().

01511 {
01512    struct ast_custom_function *acf = NULL;
01513 
01514    AST_LIST_LOCK(&acf_root);
01515    AST_LIST_TRAVERSE(&acf_root, acf, acflist) {
01516       if (!strcmp(name, acf->name))
01517          break;
01518    }
01519    AST_LIST_UNLOCK(&acf_root);
01520 
01521    return acf;
01522 }

int ast_custom_function_register ( struct ast_custom_function acf  ) 

Reigster a custom function.

Definition at line 1546 of file pbx.c.

References ast_custom_function::acflist, 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().

01547 {
01548    struct ast_custom_function *cur;
01549 
01550    if (!acf)
01551       return -1;
01552 
01553    AST_LIST_LOCK(&acf_root);
01554 
01555    if (ast_custom_function_find(acf->name)) {
01556       ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name);
01557       AST_LIST_UNLOCK(&acf_root);
01558       return -1;
01559    }
01560 
01561    /* Store in alphabetical order */
01562    AST_LIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) {
01563       if (strcasecmp(acf->name, cur->name) < 0) {
01564          AST_LIST_INSERT_BEFORE_CURRENT(&acf_root, acf, acflist);
01565          break;
01566       }
01567    }
01568    AST_LIST_TRAVERSE_SAFE_END
01569    if (!cur)
01570       AST_LIST_INSERT_TAIL(&acf_root, acf, acflist);
01571 
01572    AST_LIST_UNLOCK(&acf_root);
01573 
01574    if (option_verbose > 1)
01575       ast_verbose(VERBOSE_PREFIX_2 "Registered custom function %s\n", acf->name);
01576 
01577    return 0;
01578 }

int ast_custom_function_unregister ( struct ast_custom_function acf  ) 

Unregister a custom function.

Definition at line 1524 of file pbx.c.

References ast_custom_function::acflist, 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().

01525 {
01526    struct ast_custom_function *cur;
01527 
01528    if (!acf)
01529       return -1;
01530 
01531    AST_LIST_LOCK(&acf_root);
01532    AST_LIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) {
01533       if (cur == acf) {
01534          AST_LIST_REMOVE_CURRENT(&acf_root, acflist);
01535          if (option_verbose > 1)
01536             ast_verbose(VERBOSE_PREFIX_2 "Unregistered custom function %s\n", acf->name);
01537          break;
01538       }
01539    }
01540    AST_LIST_TRAVERSE_SAFE_END
01541    AST_LIST_UNLOCK(&acf_root);
01542 
01543    return acf ? 0 : -1;
01544 }

enum ast_extension_states ast_devstate_to_extenstate ( enum ast_device_state  devstate  ) 

Map devstate to an extension state.

Parameters:
[in] device state
Returns:
the extension state mapping.

Definition at line 1974 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_TOTAL, AST_DEVICE_UNAVAILABLE, AST_DEVICE_UNKNOWN, AST_EXTENSION_BUSY, AST_EXTENSION_INUSE, AST_EXTENSION_NOT_INUSE, AST_EXTENSION_ONHOLD, AST_EXTENSION_RINGING, and AST_EXTENSION_UNAVAILABLE.

Referenced by ast_extension_state2().

01975 {
01976    switch (devstate) {
01977    case AST_DEVICE_ONHOLD:
01978       return AST_EXTENSION_ONHOLD;
01979    case AST_DEVICE_BUSY:
01980       return AST_EXTENSION_BUSY;
01981    case AST_DEVICE_UNKNOWN:
01982       return AST_EXTENSION_NOT_INUSE;
01983    case AST_DEVICE_UNAVAILABLE:
01984    case AST_DEVICE_INVALID:
01985       return AST_EXTENSION_UNAVAILABLE;
01986    case AST_DEVICE_RINGINUSE:
01987       return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING);
01988    case AST_DEVICE_RINGING:
01989       return AST_EXTENSION_RINGING;
01990    case AST_DEVICE_INUSE:
01991       return AST_EXTENSION_INUSE;
01992    case AST_DEVICE_NOT_INUSE:
01993       return AST_EXTENSION_NOT_INUSE;
01994    case AST_DEVICE_TOTAL: /* not a device state, included for completeness */
01995       break;
01996    }
01997 
01998    return AST_EXTENSION_NOT_INUSE;
01999 }

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
Note:
It is possible for autoservice to be started and stopped on c during this function call, it is important that c is not locked prior to calling this. Otherwise a deadlock may occur
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 2366 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_bridge_call(), ast_pbx_outgoing_exten(), cb_events(), conf_run(), console_dial(), console_dial_deprecated(), console_transfer(), console_transfer_deprecated(), dahdi_handle_dtmf(), dahdi_r2_on_call_offered(), dahdi_r2_on_dnis_digit_received(), disa_exec(), dp_lookup(), dundi_lookup_local(), findmeexec(), get_also_info(), get_destination(), get_refer_info(), handle_link_data(), handle_link_phone_dtmf(), handle_stimulus_message(), leave_voicemail(), local_alloc(), local_call(), local_devicestate(), local_dtmf_helper(), loopback_exists(), metermaidstate(), mgcp_ss(), misdn_overlap_dial_task(), park_space_reserve(), parkandannounce_exec(), pbx_builtin_waitexten(), phone_check_exception(), pri_dchannel(), process_ast_dsp(), register_peer_exten(), rpt_exec(), sip_new(), skinny_ss(), socket_process(), ss_thread(), and waitstream_core().

02367 {
02368    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH);
02369 }

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

References ast_channel_lock, ast_channel_unlock, ast_copy_string(), 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().

04695 {
04696    if (!chan)
04697       return -1;
04698 
04699    ast_channel_lock(chan);
04700 
04701    if (!ast_strlen_zero(context))
04702       ast_copy_string(chan->context, context, sizeof(chan->context));
04703    if (!ast_strlen_zero(exten))
04704       ast_copy_string(chan->exten, exten, sizeof(chan->exten));
04705    if (priority > -1) {
04706       chan->priority = priority;
04707       /* see flag description in channel.h for explanation */
04708       if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP))
04709          chan->priority--;
04710    }
04711 
04712    ast_channel_unlock(chan);
04713 
04714    return 0;
04715 }

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

Definition at line 941 of file pbx.c.

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

Referenced by realtime_switch_common().

00942 {
00943    if (needmore != E_MATCHMORE && needmore != E_CANMATCH)
00944       ast_log(LOG_WARNING, "invalid argument %d\n", needmore);
00945    return extension_match_core(pattern, data, needmore);
00946 }

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

References E_MATCH, and extension_match_core().

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

00937 {
00938    return extension_match_core(pattern, data, E_MATCH);
00939 }

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

References ast_extension_state2(), and ast_hint_extension().

Referenced by action_extensionstate(), and handle_request_subscribe().

02037 {
02038    struct ast_exten *e;
02039 
02040    e = ast_hint_extension(c, context, exten);   /* Do we have a hint for this extension ? */
02041    if (!e)
02042       return -1;           /* No hint, return -1 */
02043 
02044    return ast_extension_state2(e);        /* Check all devices in the hint */
02045 }

static int ast_extension_state2 ( struct ast_exten e  )  [static]

ast_extensions_state2: Check state of extension by using hints

Definition at line 2002 of file pbx.c.

References ast_devstate_aggregate_add(), ast_devstate_aggregate_init(), ast_devstate_aggregate_result(), ast_devstate_to_extenstate(), ast_get_extension_app(), ast_strdupa, and strsep().

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

02003 {
02004    char *hint;
02005    char *cur, *rest;
02006    struct ast_devstate_aggregate agg;
02007 
02008    ast_devstate_aggregate_init(&agg);
02009 
02010    if (!e)
02011       return -1;
02012 
02013    hint = ast_strdupa(ast_get_extension_app(e));
02014 
02015    rest = hint;   /* One or more devices separated with a & character */
02016    while ( (cur = strsep(&rest, "&")) ) {
02017       int res = ast_device_state(cur);
02018       ast_devstate_aggregate_add(&agg, res);
02019    }
02020    return ast_devstate_to_extenstate(ast_devstate_aggregate_result(&agg));
02021 }

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

References extension_states, and cfextension_states::text.

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

02025 {
02026    int i;
02027 
02028    for (i = 0; (i < (sizeof(extension_states) / sizeof(extension_states[0]))); i++) {
02029       if (extension_states[i].extension_state == extension_state)
02030          return extension_states[i].text;
02031    }
02032    return "Unknown";
02033 }

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

References ao2_find(), ao2_lock(), ao2_ref(), ao2_unlock(), ast_calloc, ast_hint_extension(), ast_state_cb::callback, ast_hint::callbacks, ast_state_cb::data, ast_state_cb::id, and ast_state_cb::next.

Referenced by handle_request_subscribe(), and init_manager().

02120 {
02121    struct ast_hint *hint;
02122    struct ast_state_cb *cblist;
02123    struct ast_exten *e;
02124 
02125    /* If there's no context and extension:  add callback to statecbs list */
02126    if (!context && !exten) {
02127       ao2_lock(hints);
02128 
02129       for (cblist = statecbs; cblist; cblist = cblist->next) {
02130          if (cblist->callback == callback) {
02131             cblist->data = data;
02132             ao2_unlock(hints);
02133             return 0;
02134          }
02135       }
02136 
02137       /* Now insert the callback */
02138       if (!(cblist = ast_calloc(1, sizeof(*cblist)))) {
02139          ao2_unlock(hints);
02140          return -1;
02141       }
02142       cblist->id = 0;
02143       cblist->callback = callback;
02144       cblist->data = data;
02145 
02146       cblist->next = statecbs;
02147       statecbs = cblist;
02148 
02149       ao2_unlock(hints);
02150       return 0;
02151    }
02152 
02153    if (!context || !exten)
02154       return -1;
02155 
02156    /* This callback type is for only one hint, so get the hint */
02157    e = ast_hint_extension(NULL, context, exten);
02158    if (!e) {
02159       return -1;
02160    }
02161 
02162    hint = ao2_find(hints, e, 0);
02163 
02164    if (!hint) {
02165       return -1;
02166    }
02167 
02168    /* Now insert the callback in the callback list  */
02169    if (!(cblist = ast_calloc(1, sizeof(*cblist)))) {
02170       ao2_ref(hint, -1);
02171       return -1;
02172    }
02173    cblist->id = stateid++;    /* Unique ID for this callback */
02174    cblist->callback = callback;  /* Pointer to callback routine */
02175    cblist->data = data;    /* Data for the callback */
02176 
02177    ao2_lock(hint);
02178    cblist->next = hint->callbacks;
02179    hint->callbacks = cblist;
02180    ao2_unlock(hint);
02181 
02182    ao2_ref(hint, -1);
02183 
02184    return cblist->id;
02185 }

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

References ao2_callback(), ao2_lock(), ao2_ref(), ao2_unlock(), ast_hint::callbacks, find_hint_by_cb_id(), free, and ast_state_cb::next.

Referenced by __sip_destroy(), and handle_request_subscribe().

02204 {
02205    struct ast_state_cb **p_cur = NULL; /* address of pointer to us */
02206    int ret = -1;
02207 
02208    if (!id && !callback) {
02209       return -1;
02210    }
02211 
02212    if (!id) {  /* id == 0 is a callback without extension */
02213       ao2_lock(hints);
02214       for (p_cur = &statecbs; *p_cur; p_cur = &(*p_cur)->next) {
02215          if ((*p_cur)->callback == callback) {
02216             break;
02217          }
02218       }
02219       if (p_cur && *p_cur) {
02220          struct ast_state_cb *cur = *p_cur;
02221          *p_cur = cur->next;
02222          free(cur);
02223          ret = 0;
02224       }
02225       ao2_unlock(hints);
02226    } else { /* callback with extension, find the callback based on ID */
02227       struct ast_hint *hint;
02228 
02229       hint = ao2_callback(hints, 0, find_hint_by_cb_id, &id);
02230 
02231       if (hint) {
02232          ao2_lock(hint);
02233          for (p_cur = &hint->callbacks; *p_cur; p_cur = &(*p_cur)->next) {
02234             if ((*p_cur)->id == id) {
02235                break;
02236             }
02237          }
02238          if (p_cur && *p_cur) {
02239             struct ast_state_cb *cur = *p_cur;
02240             *p_cur = cur->next;
02241             free(cur);
02242             ret = 0;
02243          }
02244          ao2_unlock(hint);
02245          ao2_ref(hint, -1);
02246       }
02247    }
02248 
02249    return ret;
02250 }

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
Note:
It is possible for autoservice to be started and stopped on c during this function call, it is important that c is not locked prior to calling this. Otherwise a deadlock may occur
Returns:
the priority which matches the given label in the extension or -1 if not found.

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

02372 {
02373    return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL);
02374 }

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:
It is possible for autoservice to be started and stopped on c during this function call, it is important that c is not locked prior to calling this. Otherwise a deadlock may occur
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 2376 of file pbx.c.

References E_FINDLABEL, and pbx_extension_helper().

Referenced by pbx_load_config().

02377 {
02378    return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL);
02379 }

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

01601 {
01602    char *args = func_args(function);
01603    struct ast_custom_function *acfptr = ast_custom_function_find(function);
01604 
01605    if (acfptr == NULL)
01606       ast_log(LOG_ERROR, "Function %s not registered\n", function);
01607    else if (!acfptr->read)
01608       ast_log(LOG_ERROR, "Function %s cannot be read\n", function);
01609    else
01610       return acfptr->read(chan, function, args, workspace, len);
01611    return -1;
01612 }

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

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

Referenced by action_setvar(), pbx_builtin_pushvar_helper(), and pbx_builtin_setvar_helper().

01615 {
01616    char *args = func_args(function);
01617    struct ast_custom_function *acfptr = ast_custom_function_find(function);
01618 
01619    if (acfptr == NULL)
01620       ast_log(LOG_ERROR, "Function %s not registered\n", function);
01621    else if (!acfptr->write)
01622       ast_log(LOG_ERROR, "Function %s cannot be written to\n", function);
01623    else
01624       return acfptr->write(chan, function, args, value);
01625 
01626    return -1;
01627 }

const char* ast_get_context_name ( struct ast_context con  ) 
const char* ast_get_context_registrar ( struct ast_context c  ) 

Definition at line 6465 of file pbx.c.

References ast_context::registrar.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06466 {
06467    return c ? c->registrar : NULL;
06468 }

const char* ast_get_extension_app ( struct ast_exten e  ) 
void* ast_get_extension_app_data ( struct ast_exten e  ) 

Definition at line 6500 of file pbx.c.

References ast_exten::data.

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

06501 {
06502    return e ? e->data : NULL;
06503 }

const char* ast_get_extension_cidmatch ( struct ast_exten e  ) 

Definition at line 6490 of file pbx.c.

References ast_exten::cidmatch.

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

06491 {
06492    return e ? e->cidmatch : NULL;
06493 }

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

Definition at line 6432 of file pbx.c.

References ast_exten::parent.

Referenced by handle_show_hints().

06433 {
06434    return exten ? exten->parent : NULL;
06435 }

const char* ast_get_extension_label ( struct ast_exten exten  ) 

Definition at line 6442 of file pbx.c.

References ast_exten::label.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06443 {
06444    return exten ? exten->label : NULL;
06445 }

int ast_get_extension_matchcid ( struct ast_exten e  ) 

Definition at line 6485 of file pbx.c.

References ast_exten::matchcid.

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

06486 {
06487    return e ? e->matchcid : 0;
06488 }

const char* ast_get_extension_name ( struct ast_exten exten  ) 
int ast_get_extension_priority ( struct ast_exten exten  ) 

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

06458 {
06459    return exten ? exten->priority : -1;
06460 }

const char* ast_get_extension_registrar ( struct ast_exten e  ) 

Definition at line 6470 of file pbx.c.

References ast_exten::registrar.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06471 {
06472    return e ? e->registrar : NULL;
06473 }

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

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

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

02350 {
02351    struct ast_exten *e = ast_hint_extension(c, context, exten);
02352 
02353    if (e) {
02354       if (hint)
02355          ast_copy_string(hint, ast_get_extension_app(e), hintsize);
02356       if (name) {
02357          const char *tmp = ast_get_extension_app_data(e);
02358          if (tmp)
02359             ast_copy_string(name, tmp, namesize);
02360       }
02361       return -1;
02362    }
02363    return 0;
02364 }

const char* ast_get_ignorepat_name ( struct ast_ignorepat ip  ) 

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

06453 {
06454    return ip ? ip->pattern : NULL;
06455 }

const char* ast_get_ignorepat_registrar ( struct ast_ignorepat ip  ) 

Definition at line 6480 of file pbx.c.

References ast_ignorepat::registrar.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06481 {
06482    return ip ? ip->registrar : NULL;
06483 }

const char* ast_get_include_name ( struct ast_include inc  ) 

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

06448 {
06449    return inc ? inc->name : NULL;
06450 }

const char* ast_get_include_registrar ( struct ast_include i  ) 

Definition at line 6475 of file pbx.c.

References ast_include::registrar.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06476 {
06477    return i ? i->registrar : NULL;
06478 }

const char* ast_get_switch_data ( struct ast_sw sw  ) 

Definition at line 6510 of file pbx.c.

References ast_sw::data.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06511 {
06512    return sw ? sw->data : NULL;
06513 }

const char* ast_get_switch_name ( struct ast_sw sw  ) 

Definition at line 6505 of file pbx.c.

References ast_sw::name.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06506 {
06507    return sw ? sw->name : NULL;
06508 }

const char* ast_get_switch_registrar ( struct ast_sw sw  ) 

Definition at line 6515 of file pbx.c.

References ast_sw::registrar.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06516 {
06517    return sw ? sw->registrar : NULL;
06518 }

int ast_goto_if_exists ( struct ast_channel chan,
const char *  context,
const char *  exten,
int  priority 
)
static void ast_hint_destroy ( void *  obj  )  [static]

Definition at line 2252 of file pbx.c.

Referenced by ast_add_hint().

02253 {
02254    /* ast_remove_hint() takes care of most things before object destruction */
02255 }

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

01963 {
01964    struct ast_exten *e;
01965    struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */
01966 
01967    ast_rdlock_contexts();
01968    e = pbx_find_extension(c, NULL, &q, context, exten, PRIORITY_HINT, NULL, "", E_MATCH);
01969    ast_unlock_contexts();
01970 
01971    return e;
01972 }

void ast_hint_state_changed ( const char *  device  ) 

Definition at line 2047 of file pbx.c.

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next(), ao2_lock(), ao2_ref(), ao2_unlock(), ast_dynamic_str_create(), ast_dynamic_str_set(), ast_extension_state2(), ast_free, ast_get_extension_app(), ast_rdlock_contexts(), ast_unlock_contexts(), 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(), ast_dynamic_str::str, and strsep().

Referenced by do_state_change().

02048 {
02049    struct ast_hint *hint;
02050    struct ast_dynamic_str *str;
02051    struct ao2_iterator i;
02052 
02053    if (!(str = ast_dynamic_str_create(1024))) {
02054       return;
02055    }
02056 
02057    i = ao2_iterator_init(hints, 0);
02058    for (hint = ao2_iterator_next(&i); hint; ao2_ref(hint, -1), hint = ao2_iterator_next(&i)) {
02059       struct ast_state_cb *cblist;
02060       char *cur, *parse;
02061       int state;
02062 
02063       ast_dynamic_str_set(&str, 0, "%s", ast_get_extension_app(hint->exten));
02064       parse = str->str;
02065 
02066       while ( (cur = strsep(&parse, "&")) ) {
02067          if (!strcasecmp(cur, device)) {
02068             break;
02069          }
02070       }
02071 
02072       if (!cur) {
02073          continue;
02074       }
02075 
02076       /* Get device state for this hint */
02077       state = ast_extension_state2(hint->exten);
02078 
02079       if ((state == -1) || (state == hint->laststate)) {
02080          continue;
02081       }
02082 
02083       /* Device state changed since last check - notify the watchers */
02084 
02085       ast_rdlock_contexts();
02086       ao2_lock(hints);
02087       ao2_lock(hint);
02088 
02089       if (hint->exten == NULL) {
02090          /* the extension has been destroyed */
02091          ao2_unlock(hint);
02092          ao2_unlock(hints);
02093          ast_unlock_contexts();
02094          continue;
02095       }
02096 
02097       /* For general callbacks */
02098       for (cblist = statecbs; cblist; cblist = cblist->next) {
02099          cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data);
02100       }
02101 
02102       /* For extension callbacks */
02103       for (cblist = hint->callbacks; cblist; cblist = cblist->next) {
02104          cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data);
02105       }
02106 
02107       hint->laststate = state;   /* record we saw the change */
02108       ao2_unlock(hint);
02109       ao2_unlock(hints);
02110       ast_unlock_contexts();
02111    }
02112 
02113    ao2_iterator_destroy(&i);
02114    ast_free(str);
02115 }

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

04661 {
04662    struct ast_context *con = ast_context_find(context);
04663    if (con) {
04664       struct ast_ignorepat *pat;
04665       for (pat = con->ignorepats; pat; pat = pat->next) {
04666          if (ast_extension_match(pat->pattern, pattern))
04667             return 1;
04668       }
04669    }
04670 
04671    return 0;
04672 }

AST_LIST_HEAD ( store_hints  ,
store_hint   
)
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 6414 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().

06415 {
06416    return ast_mutex_lock(&con->lock);
06417 }

int ast_lock_contexts ( void   ) 

Locks the context list.

Return values:
0 on success
-1 on error

Definition at line 6391 of file pbx.c.

References ast_mutex_lock().

Referenced by find_matching_endwhile().

06392 {
06393    return ast_mutex_lock(&conlock);
06394 }

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
Note:
It is possible for autoservice to be started and stopped on c during this function call, it is important that c is not locked prior to calling this. Otherwise a deadlock may occur
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 2386 of file pbx.c.

References E_MATCHMORE, and pbx_extension_helper().

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

02387 {
02388    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE);
02389 }

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

References __ast_context_destroy(), ao2_find(), AO2_ITERATOR_DONTLOCK, ao2_iterator_init(), ao2_iterator_next(), ao2_lock(), ao2_ref(), ao2_unlock(), ast_calloc, AST_EXTENSION_REMOVED, AST_LIST_HEAD_INIT_VALUE, AST_LIST_INSERT_HEAD, AST_LIST_REMOVE_HEAD, ast_log(), ast_unlock_contexts(), ast_wrlock_contexts(), ast_state_cb::callback, ast_hint::callbacks, context, ast_state_cb::data, E_MATCH, ast_exten::exten, ast_hint::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().

04068 {
04069    struct ast_context *tmp, *lasttmp = NULL;
04070    struct store_hints store = AST_LIST_HEAD_INIT_VALUE;
04071    struct store_hint *this;
04072    struct ast_hint *hint;
04073    struct ast_exten *exten;
04074    int length;
04075    struct ast_state_cb *thiscb, *prevcb;
04076    struct ao2_iterator i;
04077 
04078    /* it is very important that this function hold the hint list lock _and_ the conlock
04079       during its operation; not only do we need to ensure that the list of contexts
04080       and extensions does not change, but also that no hint callbacks (watchers) are
04081       added or removed during the merge/delete process
04082 
04083       in addition, the locks _must_ be taken in this order, because there are already
04084       other code paths that use this order
04085    */
04086    ast_wrlock_contexts();
04087    ao2_lock(hints);
04088 
04089    /* preserve all watchers for hints associated with this registrar */
04090    i = ao2_iterator_init(hints, AO2_ITERATOR_DONTLOCK);
04091    for (hint = ao2_iterator_next(&i); hint; ao2_ref(hint, -1), hint = ao2_iterator_next(&i)) {
04092       if (hint->callbacks && !strcmp(registrar, hint->exten->parent->registrar)) {
04093          length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2 + sizeof(*this);
04094          if (!(this = ast_calloc(1, length))) {
04095             continue;
04096          }
04097          ao2_lock(hint);
04098 
04099          if (hint->exten == NULL) {
04100             ao2_unlock(hint);
04101             continue;
04102          }
04103 
04104          this->callbacks = hint->callbacks;
04105          hint->callbacks = NULL;
04106          this->laststate = hint->laststate;
04107          ao2_unlock(hint);
04108          this->context = this->data;
04109          strcpy(this->data, hint->exten->parent->name);
04110          this->exten = this->data + strlen(this->context) + 1;
04111          strcpy(this->exten, hint->exten->exten);
04112          AST_LIST_INSERT_HEAD(&store, this, list);
04113       }
04114    }
04115 
04116    tmp = *extcontexts;
04117    if (registrar) {
04118       /* XXX remove previous contexts from same registrar */
04119       if (option_debug)
04120          ast_log(LOG_DEBUG, "must remove any reg %s\n", registrar);
04121       __ast_context_destroy(NULL,registrar);
04122       while (tmp) {
04123          lasttmp = tmp;
04124          tmp = tmp->next;
04125       }
04126    } else {
04127       /* XXX remove contexts with the same name */
04128       while (tmp) {
04129          ast_log(LOG_WARNING, "must remove %s  reg %s\n", tmp->name, tmp->registrar);
04130          __ast_context_destroy(tmp,tmp->registrar);
04131          lasttmp = tmp;
04132          tmp = tmp->next;
04133       }
04134    }
04135    if (lasttmp) {
04136       lasttmp->next = contexts;
04137       contexts = *extcontexts;
04138       *extcontexts = NULL;
04139    } else
04140       ast_log(LOG_WARNING, "Requested contexts didn't get merged\n");
04141 
04142    /* restore the watchers for hints that can be found; notify those that
04143       cannot be restored
04144    */
04145    while ((this = AST_LIST_REMOVE_HEAD(&store, list))) {
04146       struct pbx_find_info q = { .stacklen = 0 };
04147       exten = pbx_find_extension(NULL, NULL, &q, this->context, this->exten, PRIORITY_HINT, NULL, "", E_MATCH);
04148       hint = ao2_find(hints, exten, 0);
04149       if (!exten || !hint) {
04150          /* this hint has been removed, notify the watchers */
04151          prevcb = NULL;
04152          thiscb = this->callbacks;
04153          while (thiscb) {
04154             prevcb = thiscb;
04155             thiscb = thiscb->next;
04156             prevcb->callback(this->context, this->exten, AST_EXTENSION_REMOVED, prevcb->data);
04157             free(prevcb);
04158             }
04159       } else {
04160          thiscb = this->callbacks;
04161          while (thiscb->next) {
04162             thiscb = thiscb->next;
04163          }
04164          ao2_lock(hint);
04165          thiscb->next = hint->callbacks;
04166          hint->callbacks = this->callbacks;
04167          hint->laststate = this->laststate;
04168          ao2_unlock(hint);
04169       }
04170       if (hint) {
04171          ao2_ref(hint, -1);
04172       }
04173       free(this);
04174    }
04175 
04176    ao2_unlock(hints);
04177    ast_unlock_contexts();
04178 
04179    return;
04180 }

AST_MUTEX_DEFINE_STATIC ( conlock   ) 

Lock for the ast_context list This lock MUST be recursive, or a deadlock on reload may result. See https://issues.asterisk.org/view.php?id=17643.

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

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

06619 {
06620    char *exten, *pri, *context;
06621    char *stringp;
06622    int ipri;
06623    int mode = 0;
06624 
06625    if (ast_strlen_zero(goto_string)) {
06626       ast_log(LOG_WARNING, "Goto requires an argument (optional context|optional extension|priority)\n");
06627       return -1;
06628    }
06629    stringp = ast_strdupa(goto_string);
06630    context = strsep(&stringp, "|"); /* guaranteed non-null */
06631    exten = strsep(&stringp, "|");
06632    pri = strsep(&stringp, "|");
06633    if (!exten) {  /* Only a priority in this one */
06634       pri = context;
06635       exten = NULL;
06636       context = NULL;
06637    } else if (!pri) {   /* Only an extension and priority in this one */
06638       pri = exten;
06639       exten = context;
06640       context = NULL;
06641    }
06642    if (*pri == '+') {
06643       mode = 1;
06644       pri++;
06645    } else if (*pri == '-') {
06646       mode = -1;
06647       pri++;
06648    }
06649    if (sscanf(pri, "%30d", &ipri) != 1) {
06650       if ((ipri = ast_findlabel_extension(chan, context ? context : chan->context, exten ? exten : chan->exten,
06651          pri, chan->cid.cid_num)) < 1) {
06652          ast_log(LOG_WARNING, "Priority '%s' must be a number > 0, or valid label\n", pri);
06653          return -1;
06654       } else
06655          mode = 0;
06656    }
06657    /* At this point we have a priority and maybe an extension and a context */
06658 
06659    if (mode)
06660       ipri = chan->priority + (ipri * mode);
06661 
06662    ast_explicit_goto(chan, context, exten, ipri);
06663    return 0;
06664 
06665 }

int ast_pbx_init ( void   ) 

Provided by pbx.c

Definition at line 6681 of file pbx.c.

References ao2_container_alloc(), hint_cmp(), and hint_hash().

Referenced by main().

06682 {
06683    hints = ao2_container_alloc(1, hint_hash, hint_cmp);
06684 
06685    return hints ? 0 : -1;
06686 }

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 5287 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_disposition(), ast_cdr_failed(), ast_cdr_setaccount(), ast_channel_lock, ast_channel_unlock, ast_copy_string(), 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, app_tmp::t, async_stat::timeout, outgoing_helper::vars, and VERBOSE_PREFIX_4.

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

05288 {
05289    struct ast_channel *chan;
05290    struct app_tmp *tmp;
05291    int res = -1, cdr_res = -1;
05292    struct outgoing_helper oh;
05293    pthread_attr_t attr;
05294 
05295    memset(&oh, 0, sizeof(oh));
05296    oh.vars = vars;
05297    oh.account = account;
05298 
05299    if (locked_channel)
05300       *locked_channel = NULL;
05301    if (ast_strlen_zero(app)) {
05302       res = -1;
05303       goto outgoing_app_cleanup;
05304    }
05305    if (sync) {
05306       chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
05307       if (chan) {
05308          ast_set_variables(chan, vars);
05309          if (account)
05310             ast_cdr_setaccount(chan, account);
05311          if (chan->_state == AST_STATE_UP) {
05312             res = 0;
05313             if (option_verbose > 3)
05314                ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", chan->name);
05315             tmp = ast_calloc(1, sizeof(*tmp));
05316             if (!tmp)
05317                res = -1;
05318             else {
05319                ast_copy_string(tmp->app, app, sizeof(tmp->app));
05320                if (appdata)
05321                   ast_copy_string(tmp->data, appdata, sizeof(tmp->data));
05322                tmp->chan = chan;
05323                if (sync > 1) {
05324                   if (locked_channel)
05325                      ast_channel_unlock(chan);
05326                   ast_pbx_run_app(tmp);
05327                } else {
05328                   pthread_attr_init(&attr);
05329                   pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
05330                   if (locked_channel)
05331                      ast_channel_lock(chan);
05332                   if (ast_pthread_create(&tmp->t, &attr, ast_pbx_run_app, tmp)) {
05333                      ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno));
05334                      free(tmp);
05335                      if (locked_channel)
05336                         ast_channel_unlock(chan);
05337                      ast_hangup(chan);
05338                      res = -1;
05339                   } else {
05340                      if (locked_channel)
05341                         *locked_channel = chan;
05342                   }
05343                   pthread_attr_destroy(&attr);
05344                }
05345             }
05346          } else {
05347             if (option_verbose > 3)
05348                ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", chan->name);
05349             if (chan->cdr) { /* update the cdr */
05350                /* here we update the status of the call, which sould be busy.
05351                 * if that fails then we set the status to failed */
05352                if (ast_cdr_disposition(chan->cdr, chan->hangupcause))
05353                   ast_cdr_failed(chan->cdr);
05354             }
05355             ast_hangup(chan);
05356          }
05357       }
05358 
05359       if (res < 0) { /* the call failed for some reason */
05360          if (*reason == 0) { /* if the call failed (not busy or no answer)
05361                         * update the cdr with the failed message */
05362             cdr_res = ast_pbx_outgoing_cdr_failed();
05363             if (cdr_res != 0) {
05364                res = cdr_res;
05365                goto outgoing_app_cleanup;
05366             }
05367          }
05368       }
05369 
05370    } else {
05371       struct async_stat *as;
05372       if (!(as = ast_calloc(1, sizeof(*as)))) {
05373          res = -1;
05374          goto outgoing_app_cleanup;
05375       }
05376       chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
05377       if (!chan) {
05378          free(as);
05379          res = -1;
05380          goto outgoing_app_cleanup;
05381       }
05382       as->chan = chan;
05383       ast_copy_string(as->app, app, sizeof(as->app));
05384       if (appdata)
05385          ast_copy_string(as->appdata,  appdata, sizeof(as->appdata));
05386       as->timeout = timeout;
05387       ast_set_variables(chan, vars);
05388       if (account)
05389          ast_cdr_setaccount(chan, account);
05390       /* Start a new thread, and get something handling this channel. */
05391       pthread_attr_init(&attr);
05392       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
05393       if (locked_channel)
05394          ast_channel_lock(chan);
05395       if (ast_pthread_create(&as->p, &attr, async_wait, as)) {
05396          ast_log(LOG_WARNING, "Failed to start async wait\n");
05397          free(as);
05398          if (locked_channel)
05399             ast_channel_unlock(chan);
05400          ast_hangup(chan);
05401          res = -1;
05402          pthread_attr_destroy(&attr);
05403          goto outgoing_app_cleanup;
05404       } else {
05405          if (locked_channel)
05406             *locked_channel = chan;
05407       }
05408       pthread_attr_destroy(&attr);
05409       res = 0;
05410    }
05411 outgoing_app_cleanup:
05412    ast_variables_destroy(vars);
05413    return res;
05414 }

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

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

Referenced by ast_pbx_outgoing_app(), and ast_pbx_outgoing_exten().

05096 {
05097    /* allocate a channel */
05098    struct ast_channel *chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "%s", "");
05099 
05100    if (!chan)
05101       return -1;  /* failure */
05102 
05103    if (!chan->cdr) {
05104       /* allocation of the cdr failed */
05105       ast_channel_free(chan);   /* free the channel */
05106       return -1;                /* return failure */
05107    }
05108 
05109    /* allocation of the cdr was successful */
05110    ast_cdr_init(chan->cdr, chan);  /* initilize our channel's cdr */
05111    ast_cdr_start(chan->cdr);       /* record the start and stop time */
05112    ast_cdr_end(chan->cdr);
05113    ast_cdr_failed(chan->cdr);      /* set the status to failed */
05114    ast_cdr_detach(chan->cdr);      /* post and free the record */
05115    chan->cdr = NULL;
05116    ast_channel_free(chan);         /* free the channel */
05117 
05118    return 0;  /* success */
05119 }

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 5121 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_copy_string(), 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(), attempt_thread(), fast_originate(), and orig_exten().

05122 {
05123    struct ast_channel *chan;
05124    struct async_stat *as;
05125    int res = -1, cdr_res = -1;
05126    struct outgoing_helper oh;
05127    pthread_attr_t attr;
05128 
05129    if (sync) {
05130       LOAD_OH(oh);
05131       chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
05132       if (channel) {
05133          *channel = chan;
05134          if (chan)
05135             ast_channel_lock(chan);
05136       }
05137       if (chan) {
05138          if (chan->_state == AST_STATE_UP) {
05139                res = 0;
05140             if (option_verbose > 3)
05141                ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", chan->name);
05142 
05143             if (sync > 1) {
05144                if (channel)
05145                   ast_channel_unlock(chan);
05146                if (ast_pbx_run(chan)) {
05147                   ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name);
05148                   if (channel)
05149                      *channel = NULL;
05150                   ast_hangup(chan);
05151                   chan = NULL;
05152                   res = -1;
05153                }
05154             } else {
05155                if (ast_pbx_start(chan)) {
05156                   ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name);
05157                   if (channel) {
05158                      *channel = NULL;
05159                      ast_channel_unlock(chan);
05160                   }
05161                   ast_hangup(chan);
05162                   res = -1;
05163                }
05164                chan = NULL;
05165             }
05166          } else {
05167             if (option_verbose > 3)
05168                ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", chan->name);
05169 
05170             if (chan->cdr) { /* update the cdr */
05171                /* here we update the status of the call, which sould be busy.
05172                 * if that fails then we set the status to failed */
05173                if (ast_cdr_disposition(chan->cdr, chan->hangupcause))
05174                   ast_cdr_failed(chan->cdr);
05175             }
05176 
05177             if (channel) {
05178                *channel = NULL;
05179                ast_channel_unlock(chan);
05180             }
05181             ast_hangup(chan);
05182             chan = NULL;
05183          }
05184       }
05185 
05186       if (res < 0) { /* the call failed for some reason */
05187          if (*reason == 0) { /* if the call failed (not busy or no answer)
05188                         * update the cdr with the failed message */
05189             cdr_res = ast_pbx_outgoing_cdr_failed();
05190             if (cdr_res != 0) {
05191                res = cdr_res;
05192                goto outgoing_exten_cleanup;
05193             }
05194          }
05195 
05196          /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */
05197          /* check if "failed" exists */
05198          if (ast_exists_extension(chan, context, "failed", 1, NULL)) {
05199             chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "OutgoingSpoolFailed");
05200             if (chan) {
05201                char failed_reason[4] = "";
05202                if (!ast_strlen_zero(context))
05203                   ast_copy_string(chan->context, context, sizeof(chan->context));
05204                set_ext_pri(chan, "failed", 1);
05205                ast_set_variables(chan, vars);
05206                snprintf(failed_reason, sizeof(failed_reason), "%d", *reason);
05207                pbx_builtin_setvar_helper(chan, "REASON", failed_reason);
05208                if (account)
05209                   ast_cdr_setaccount(chan, account);
05210                if (ast_pbx_run(chan)) {
05211                   ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name);
05212                   ast_hangup(chan);
05213                }
05214                chan = NULL;
05215             }
05216          }
05217       }
05218    } else {
05219       if (!(as = ast_calloc(1, sizeof(*as)))) {
05220          res = -1;
05221          goto outgoing_exten_cleanup;
05222       }
05223       chan = ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name);
05224       if (channel) {
05225          *channel = chan;
05226          if (chan)
05227             ast_channel_lock(chan);
05228       }
05229       if (!chan) {
05230          free(as);
05231          res = -1;
05232          goto outgoing_exten_cleanup;
05233       }
05234       as->chan = chan;
05235       ast_copy_string(as->context, context, sizeof(as->context));
05236       set_ext_pri(as->chan,  exten, priority);
05237       as->timeout = timeout;
05238       ast_set_variables(chan, vars);
05239       if (account)
05240          ast_cdr_setaccount(chan, account);
05241       pthread_attr_init(&attr);
05242       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
05243       if (ast_pthread_create(&as->p, &attr, async_wait, as)) {
05244          ast_log(LOG_WARNING, "Failed to start async wait\n");
05245          free(as);
05246          if (channel) {
05247             *channel = NULL;
05248             ast_channel_unlock(chan);
05249          }
05250          ast_hangup(chan);
05251          res = -1;
05252          pthread_attr_destroy(&attr);
05253          goto outgoing_exten_cleanup;
05254       }
05255       pthread_attr_destroy(&attr);
05256       res = 0;
05257    }
05258 outgoing_exten_cleanup:
05259    ast_variables_destroy(vars);
05260    return res;
05261 }

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

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

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

02752 {
02753    enum ast_pbx_result res = AST_PBX_SUCCESS;
02754 
02755    if (increase_call_count(c))
02756       return AST_PBX_CALL_LIMIT;
02757 
02758    res = __ast_pbx_run(c);
02759    decrease_call_count();
02760 
02761    return res;
02762 }

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

run the application and free the descriptor once done

Definition at line 5271 of file pbx.c.

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

Referenced by ast_pbx_outgoing_app().

05272 {
05273    struct app_tmp *tmp = data;
05274    struct ast_app *app;
05275    app = pbx_findapp(tmp->app);
05276    if (app) {
05277       if (option_verbose > 3)
05278          ast_verbose(VERBOSE_PREFIX_4 "Launching %s(%s) on %s\n", tmp->app, tmp->data, tmp->chan->name);
05279       pbx_exec(tmp->chan, app, tmp->data);
05280    } else
05281       ast_log(LOG_WARNING, "No such application '%s'\n", tmp->app);
05282    ast_hangup(tmp->chan);
05283    free(tmp);
05284    return NULL;
05285 }

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

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

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

02725 {
02726    pthread_t t;
02727    pthread_attr_t attr;
02728 
02729    if (!c) {
02730       ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
02731       return AST_PBX_FAILED;
02732    }
02733 
02734    if (increase_call_count(c))
02735       return AST_PBX_CALL_LIMIT;
02736 
02737    /* Start a new thread, and get something handling this channel. */
02738    pthread_attr_init(&attr);
02739    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
02740    if (ast_pthread_create(&t, &attr, pbx_thread, c)) {
02741       ast_log(LOG_WARNING, "Failed to create new channel thread\n");
02742       pthread_attr_destroy(&attr);
02743       decrease_call_count();
02744       return AST_PBX_FAILED;
02745    }
02746    pthread_attr_destroy(&attr);
02747 
02748    return AST_PBX_SUCCESS;
02749 }

int ast_processed_calls ( void   ) 

Retrieve the total number of calls processed through the PBX since last restart.

Definition at line 2769 of file pbx.c.

02770 {
02771    return totalcalls;
02772 }

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

03059 {
03060    struct ast_app *tmp, *cur = NULL;
03061    char tmps[80];
03062    int length;
03063 
03064    AST_LIST_LOCK(&apps);
03065    AST_LIST_TRAVERSE(&apps, tmp, list) {
03066       if (!strcasecmp(app, tmp->name)) {
03067          ast_log(LOG_WARNING, "Already have an application '%s'\n", app);
03068          AST_LIST_UNLOCK(&apps);
03069          return -1;
03070       }
03071    }
03072 
03073    length = sizeof(*tmp) + strlen(app) + 1;
03074 
03075    if (!(tmp = ast_calloc(1, length))) {
03076       AST_LIST_UNLOCK(&apps);
03077       return -1;
03078    }
03079 
03080    strcpy(tmp->name, app);
03081    tmp->execute = execute;
03082    tmp->synopsis = synopsis;
03083    tmp->description = description;
03084 
03085    /* Store in alphabetical order */
03086    AST_LIST_TRAVERSE_SAFE_BEGIN(&apps, cur, list) {
03087       if (strcasecmp(tmp->name, cur->name) < 0) {
03088          AST_LIST_INSERT_BEFORE_CURRENT(&apps, tmp, list);
03089          break;
03090       }
03091    }
03092    AST_LIST_TRAVERSE_SAFE_END
03093    if (!cur)
03094       AST_LIST_INSERT_TAIL(&apps, tmp, list);
03095 
03096    if (option_verbose > 1)
03097       ast_verbose( VERBOSE_PREFIX_2 "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps)));
03098 
03099    AST_LIST_UNLOCK(&apps);
03100 
03101    return 0;
03102 }

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

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

Referenced by load_module().

03109 {
03110    struct ast_switch *tmp;
03111 
03112    AST_LIST_LOCK(&switches);
03113    AST_LIST_TRAVERSE(&switches, tmp, list) {
03114       if (!strcasecmp(tmp->name, sw->name)) {
03115          AST_LIST_UNLOCK(&switches);
03116          ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name);
03117          return -1;
03118       }
03119    }
03120    AST_LIST_INSERT_TAIL(&switches, sw, list);
03121    AST_LIST_UNLOCK(&switches);
03122 
03123    return 0;
03124 }

static int ast_remove_hint ( struct ast_exten e  )  [static]

ast_remove_hint: Remove hint from extension

Definition at line 2313 of file pbx.c.

References ao2_find(), ao2_lock(), ao2_ref(), ao2_unlink(), ao2_unlock(), AST_EXTENSION_DEACTIVATED, ast_free, ast_state_cb::callback, ast_hint::callbacks, ast_state_cb::data, ast_exten::exten, ast_hint::exten, ast_state_cb::next, and ast_exten::parent.

Referenced by destroy_exten().

02314 {
02315    /* Cleanup the Notifys if hint is removed */
02316    struct ast_hint *hint;
02317    struct ast_state_cb *cblist, *cbprev;
02318 
02319    if (!e) {
02320       return -1;
02321    }
02322 
02323    hint = ao2_find(hints, e, 0);
02324 
02325    if (!hint) {
02326       return -1;
02327    }
02328    ao2_lock(hint);
02329 
02330    cbprev = NULL;
02331    cblist = hint->callbacks;
02332    while (cblist) {
02333       cbprev = cblist;
02334       cblist = cblist->next;
02335       cbprev->callback(hint->exten->parent->name, hint->exten->exten, AST_EXTENSION_DEACTIVATED, cbprev->data);
02336       ast_free(cbprev);
02337    }
02338    hint->callbacks = NULL;
02339    hint->exten = NULL;
02340    ao2_unlink(hints, hint);
02341    ao2_unlock(hint);
02342    ao2_ref(hint, -1);
02343 
02344    return 0;
02345 }

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.

Note:
It is possible for autoservice to be started and stopped on c during this function call, it is important that c is not locked prior to calling this. Otherwise a deadlock may occur
Return values:
0 on success
-1 on failure.

Definition at line 2391 of file pbx.c.

References E_SPAWN, and pbx_extension_helper().

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

02392 {
02393    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN);
02394 }

AST_THREADSTORAGE ( switch_data  ,
switch_data_init   
)
int ast_unlock_context ( struct ast_context con  ) 
Return values:
Unlocks the given context
Parameters:
con context to unlock
Return values:
0 on success
-1 on failure

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

06420 {
06421    return ast_mutex_unlock(&con->lock);
06422 }

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

03979 {
03980    struct ast_app *tmp;
03981 
03982    AST_LIST_LOCK(&apps);
03983    AST_LIST_TRAVERSE_SAFE_BEGIN(&apps, tmp, list) {
03984       if (!strcasecmp(app, tmp->name)) {
03985          AST_LIST_REMOVE_CURRENT(&apps, list);
03986          if (option_verbose > 1)
03987             ast_verbose( VERBOSE_PREFIX_2 "Unregistered application '%s'\n", tmp->name);
03988          free(tmp);
03989          break;
03990       }
03991    }
03992    AST_LIST_TRAVERSE_SAFE_END
03993    AST_LIST_UNLOCK(&apps);
03994 
03995    return tmp ? 0 : -1;
03996 }

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

References AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, and ast_switch::list.

Referenced by __unload_module(), and unload_module().

03127 {
03128    AST_LIST_LOCK(&switches);
03129    AST_LIST_REMOVE(&switches, sw, list);
03130    AST_LIST_UNLOCK(&switches);
03131 }

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

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

06530 {
06531    if (!exten)
06532       return con ? con->root : NULL;
06533    else
06534       return exten->next;
06535 }

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

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

06563 {
06564    if (!ip)
06565       return con ? con->ignorepats : NULL;
06566    else
06567       return ip->next;
06568 }

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

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

06554 {
06555    if (!inc)
06556       return con ? con->includes : NULL;
06557    else
06558       return inc->next;
06559 }

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

Definition at line 6537 of file pbx.c.

References AST_LIST_FIRST, and AST_LIST_NEXT.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06539 {
06540    if (!sw)
06541       return con ? AST_LIST_FIRST(&con->alts) : NULL;
06542    else
06543       return AST_LIST_NEXT(sw, list);
06544 }

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

06548 {
06549    return priority ? priority->peer : exten;
06550 }

int ast_wrlock_contexts ( void   ) 

Definition at line 6401 of file pbx.c.

References ast_mutex_lock().

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

06402 {
06403    return ast_mutex_lock(&conlock);
06404 }

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

Definition at line 5032 of file pbx.c.

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

Referenced by ast_pbx_outgoing_app(), and ast_pbx_outgoing_exten().

05033 {
05034    struct async_stat *as = data;
05035    struct ast_channel *chan = as->chan;
05036    int timeout = as->timeout;
05037    int res;
05038    struct ast_frame *f;
05039    struct ast_app *app;
05040 
05041    while (timeout && (chan->_state != AST_STATE_UP)) {
05042       res = ast_waitfor(chan, timeout);
05043       if (res < 1)
05044          break;
05045       if (timeout > -1)
05046          timeout = res;
05047       f = ast_read(chan);
05048       if (!f)
05049          break;
05050       if (f->frametype == AST_FRAME_CONTROL) {
05051          if ((f->subclass == AST_CONTROL_BUSY)  ||
05052              (f->subclass == AST_CONTROL_CONGESTION) ) {
05053             ast_frfree(f);
05054             break;
05055          }
05056       }
05057       ast_frfree(f);
05058    }
05059    if (chan->_state == AST_STATE_UP) {
05060       if (!ast_strlen_zero(as->app)) {
05061          app = pbx_findapp(as->app);
05062          if (app) {
05063             if (option_verbose > 2)
05064                ast_verbose(VERBOSE_PREFIX_3 "Launching %s(%s) on %s\n", as->app, as->appdata, chan->name);
05065             pbx_exec(chan, app, as->appdata);
05066          } else
05067             ast_log(LOG_WARNING, "No such application '%s'\n", as->app);
05068       } else {
05069          if (!ast_strlen_zero(as->context))
05070             ast_copy_string(chan->context, as->context, sizeof(chan->context));
05071          if (!ast_strlen_zero(as->exten))
05072             ast_copy_string(chan->exten, as->exten, sizeof(chan->exten));
05073          if (as->priority > 0)
05074             chan->priority = as->priority;
05075          /* Run the PBX */
05076          if (ast_pbx_run(chan)) {
05077             ast_log(LOG_ERROR, "Failed to start PBX on %s\n", chan->name);
05078          } else {
05079             /* PBX will have taken care of this */
05080             chan = NULL;
05081          }
05082       }
05083    }
05084    free(as);
05085    if (chan)
05086       ast_hangup(chan);
05087    return NULL;
05088 }

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

References ast_channel::_softhangup, ast_channel_clear_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().

02410 {
02411    int digit;
02412 
02413    buf[pos] = '\0';  /* make sure it is properly terminated */
02414    while (ast_matchmore_extension(c, c->context, buf, 1, c->cid.cid_num)) {
02415       /* As long as we're willing to wait, and as long as it's not defined,
02416          keep reading digits until we can't possibly get a right answer anymore.  */
02417       digit = ast_waitfordigit(c, waittime * 1000);
02418       if (c->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) {
02419          ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO);
02420       } else {
02421          if (!digit) /* No entry */
02422             break;
02423          if (digit < 0) /* Error, maybe a  hangup */
02424             return -1;
02425          if (pos < buflen - 1) { /* XXX maybe error otherwise ? */
02426             buf[pos++] = digit;
02427             buf[pos] = '\0';
02428          }
02429          waittime = c->pbx->dtimeout;
02430       }
02431    }
02432    return 0;
02433 }

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

Definition at line 3191 of file pbx.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, and strdup.

03192 {
03193    struct ast_app *a;
03194    char *ret = NULL;
03195    int which = 0;
03196    int wordlen = strlen(word);
03197 
03198    /* return the n-th [partial] matching entry */
03199    AST_LIST_LOCK(&apps);
03200    AST_LIST_TRAVERSE(&apps, a, list) {
03201       if (!strncasecmp(word, a->name, wordlen) && ++which > state) {
03202          ret = strdup(a->name);
03203          break;
03204       }
03205    }
03206    AST_LIST_UNLOCK(&apps);
03207 
03208    return ret;
03209 }

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

Definition at line 3557 of file pbx.c.

References ast_cli_complete().

03558 {
03559    static char* choices[] = { "like", "describing", NULL };
03560 
03561    return (pos != 3) ? NULL : ast_cli_complete(word, choices, state);
03562 }

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

Definition at line 3550 of file pbx.c.

References ast_cli_complete().

03551 {
03552    static char* choices[] = { "like", "describing", NULL };
03553 
03554    return (pos != 2) ? NULL : ast_cli_complete(word, choices, state);
03555 }

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

Definition at line 3567 of file pbx.c.

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

03569 {
03570    struct ast_context *c = NULL;
03571    char *ret = NULL;
03572    int which = 0;
03573    int wordlen;
03574 
03575    /* we are do completion of [exten@]context on second position only */
03576    if (pos != 2)
03577       return NULL;
03578 
03579    ast_rdlock_contexts();
03580 
03581    wordlen = strlen(word);
03582 
03583    /* walk through all contexts and return the n-th match */
03584    while ( (c = ast_walk_contexts(c)) ) {
03585       if (!strncasecmp(word, ast_get_context_name(c), wordlen) && ++which > state) {
03586          ret = ast_strdup(ast_get_context_name(c));
03587          break;
03588       }
03589    }
03590 
03591    ast_unlock_contexts();
03592 
03593    return ret;
03594 }

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

Definition at line 1490 of file pbx.c.

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

01491 {
01492    struct ast_custom_function *acf;
01493    char *ret = NULL;
01494    int which = 0;
01495    int wordlen = strlen(word);
01496 
01497    /* case-insensitive for convenience in this 'complete' function */
01498    AST_LIST_LOCK(&acf_root);
01499    AST_LIST_TRAVERSE(&acf_root, acf, acflist) {
01500       if (!strncasecmp(word, acf->name, wordlen) && ++which > state) {
01501          ret = strdup(acf->name);
01502          break;
01503       }
01504    }
01505    AST_LIST_UNLOCK(&acf_root);
01506 
01507    return ret;
01508 }

static void decrease_call_count ( void   )  [static]

Definition at line 2686 of file pbx.c.

References ast_mutex_lock(), and ast_mutex_unlock().

Referenced by ast_pbx_run(), ast_pbx_start(), and pbx_thread().

02687 {
02688    ast_mutex_lock(&maxcalllock);
02689    if (countcalls > 0)
02690       countcalls--;
02691    ast_mutex_unlock(&maxcalllock);
02692 }

static void destroy_exten ( struct ast_exten e  )  [static]

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

02695 {
02696    if (e->priority == PRIORITY_HINT)
02697       ast_remove_hint(e);
02698 
02699    if (e->datad)
02700       e->datad(e->data);
02701    free(e);
02702 }

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

the full routine to compare extensions in rules.

Definition at line 768 of file pbx.c.

References ext_cmp1().

Referenced by ast_add_extension2().

00769 {
00770    /* make sure non-patterns come first.
00771     * If a is not a pattern, it either comes first or
00772     * we do a more complex pattern comparison.
00773     */
00774    int ret = 0;
00775 
00776    if (a[0] != '_')
00777       return (b[0] == '_') ? -1 : strcmp(a, b);
00778 
00779    /* Now we know a is a pattern; if b is not, a comes first */
00780    if (b[0] != '_')
00781       return 1;
00782 
00783    /* ok we need full pattern sorting routine.
00784     * skip past the underscores */
00785    ++a; ++b;
00786    do {
00787       unsigned char bitwise[2][32] = { { 0, } };
00788       ret = ext_cmp1(&a, bitwise[0]) - ext_cmp1(&b, bitwise[1]);
00789       if (ret == 0) {
00790          /* Are the classes different, even though they score the same? */
00791          ret = memcmp(bitwise[0], bitwise[1], 32);
00792       }
00793    } while (!ret && a && b);
00794    if (ret == 0) {
00795       return 0;
00796    } else {
00797       return (ret > 0) ? 1 : -1;
00798    }
00799 }

static int ext_cmp1 ( const char **  p,
unsigned char *  bitwise 
) [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.

Note:
If two patterns score the same, the one with the lowest ascii values will compare as coming first.

Definition at line 687 of file pbx.c.

References ast_log(), and LOG_WARNING.

Referenced by ext_cmp().

00688 {
00689    int c, cmin = 0xff, count = 0;
00690    const char *end;
00691 
00692    /* load value and advance pointer */
00693    while ( (c = *(*p)++) && (c == ' ' || c == '-') )
00694       ;  /* ignore some characters */
00695 
00696    /* always return unless we have a set of chars */
00697    switch (c) {
00698    default: /* ordinary character */
00699       bitwise[c / 8] = 1 << (c % 8);
00700       return 0x0100 | (c & 0xff);
00701 
00702    case 'N':   /* 2..9 */
00703       bitwise[6] = 0xfc;
00704       bitwise[7] = 0x03;
00705       return 0x0800 | '2';
00706 
00707    case 'X':   /* 0..9 */
00708       bitwise[6] = 0xff;
00709       bitwise[7] = 0x03;
00710       return 0x0A00 | '0';
00711 
00712    case 'Z':   /* 1..9 */
00713       bitwise[6] = 0xfe;
00714       bitwise[7] = 0x03;
00715       return 0x0900 | '1';
00716 
00717    case '.':   /* wildcard */
00718       return 0x10000;
00719 
00720    case '!':   /* earlymatch */
00721       return 0x20000;   /* less specific than NULL */
00722 
00723    case '\0':  /* empty string */
00724       *p = NULL;
00725       return 0x30000;
00726 
00727    case '[':   /* pattern */
00728       break;
00729    }
00730    /* locate end of set */
00731    end = strchr(*p, ']');  
00732 
00733    if (end == NULL) {
00734       ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n");
00735       return 0x40000;   /* XXX make this entry go last... */
00736    }
00737 
00738    for (; *p < end  ; (*p)++) {
00739       unsigned char c1, c2;   /* first-last char in range */
00740       c1 = (unsigned char)((*p)[0]);
00741       if (*p + 2 < end && (*p)[1] == '-') { /* this is a range */
00742          c2 = (unsigned char)((*p)[2]);
00743          *p += 2;    /* skip a total of 3 chars */
00744       } else {        /* individual character */
00745          c2 = c1;
00746       }
00747       if (c1 < cmin) {
00748          cmin = c1;
00749       }
00750       for (; c1 <= c2; c1++) {
00751          unsigned char mask = 1 << (c1 % 8);
00752          /*!\note If two patterns score the same, the one with the lowest
00753           * ascii values will compare as coming first. */
00754          /* Flag the character as included (used) and count it. */
00755          if (!(bitwise[ c1 / 8 ] & mask)) {
00756             bitwise[ c1 / 8 ] |= mask;
00757             count += 0x100;
00758          }
00759       }
00760    }
00761    (*p)++;
00762    return count == 0 ? 0x30000 : (count | cmin);
00763 }

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

copy a string skipping whitespace

Definition at line 4784 of file pbx.c.

Referenced by ast_add_extension2().

04785 {
04786    int count=0;
04787 
04788    while (*src && (count < len - 1)) {
04789       switch(*src) {
04790       case ' ':
04791          /* otherwise exten => [a-b],1,... doesn't work */
04792          /*    case '-': */
04793          /* Ignore */
04794          break;
04795       default:
04796          *dst = *src;
04797          dst++;
04798       }
04799       src++;
04800       count++;
04801    }
04802    *dst = '\0';
04803 
04804    return count;
04805 }

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

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

00925 {
00926    int i;
00927    static int prof_id = -2;   /* marker for 'unallocated' id */
00928    if (prof_id == -2)
00929       prof_id = ast_add_profile("ext_match", 0);
00930    ast_mark(prof_id, 1);
00931    i = _extension_match_core(pattern, data, mode);
00932    ast_mark(prof_id, 0);
00933    return i;
00934 }

static struct ast_context* find_context_locked ( const char *  context  )  [static, read]
static int find_hint_by_cb_id ( void *  obj,
void *  arg,
int  flags 
) [static]

Definition at line 2187 of file pbx.c.

References ast_hint::callbacks, ast_state_cb::id, and ast_state_cb::next.

Referenced by ast_extension_state_del().

02188 {
02189    const struct ast_hint *hint = obj;
02190    int *id = arg;
02191    struct ast_state_cb *cb;
02192 
02193    for (cb = hint->callbacks; cb; cb = cb->next) {
02194       if (cb->id == *id) {
02195          return CMP_MATCH | CMP_STOP;
02196       }
02197    }
02198 
02199    return 0;
02200 }

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

References ast_log(), and LOG_WARNING.

Referenced by ast_func_read(), and ast_func_write().

01584 {
01585    char *args = strchr(function, '(');
01586 
01587    if (!args)
01588       ast_log(LOG_WARNING, "Function '%s' doesn't contain parentheses.  Assuming null argument.\n", function);
01589    else {
01590       char *p;
01591       *args++ = '\0';
01592       if ((p = strrchr(args, ')')) )
01593          *p = '\0';
01594       else
01595          ast_log(LOG_WARNING, "Can't find trailing parenthesis for function '%s(%s'?\n", function, args);
01596    }
01597    return args;
01598 }

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

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

Referenced by ast_build_timing().

04226 {
04227    int start, end; /* start and ending position */
04228    unsigned int mask = 0;
04229    char *part;
04230 
04231    /* Check for whole range */
04232    if (ast_strlen_zero(src) || !strcmp(src, "*")) {
04233       return (1 << max) - 1;
04234    }
04235 
04236    while ((part = strsep(&src, "&"))) {
04237       /* Get start and ending position */
04238       char *endpart = strchr(part, '-');
04239       if (endpart) {
04240          *endpart++ = '\0';
04241       }
04242       /* Find the start */
04243       if ((start = lookup_name(part, names, max)) < 0) {
04244          ast_log(LOG_WARNING, "Invalid %s '%s', skipping element\n", msg, part);
04245          continue;
04246       }
04247       if (endpart) { /* find end of range */
04248          if ((end = lookup_name(endpart, names, max)) < 0) {
04249             ast_log(LOG_WARNING, "Invalid end %s '%s', skipping element\n", msg, endpart);
04250             continue;
04251          }
04252       } else {
04253          end = start;
04254       }
04255       /* Fill the mask. Remember that ranges are cyclic */
04256       mask |= (1 << end); /* initialize with last element */
04257       while (start != end) {
04258          mask |= (1 << start);
04259          if (++start >= max) {
04260             start = 0;
04261          }
04262       }
04263    }
04264    return mask;
04265 }

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

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

Definition at line 4268 of file pbx.c.

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

Referenced by ast_build_timing().

04269 {
04270    char *endpart, *part;
04271    int x;
04272    int st_h, st_m;
04273    int endh, endm;
04274    int minute_start, minute_end;
04275 
04276    /* start disabling all times, fill the fields with 0's, as they may contain garbage */
04277    memset(i->minmask, 0, sizeof(i->minmask));
04278 
04279    /* 1-minute per bit */
04280    /* Star is all times */
04281    if (ast_strlen_zero(times) || !strcmp(times, "*")) {
04282       /* 48, because each hour takes 2 integers; 30 bits each */
04283       for (x = 0; x < 48; x++) {
04284          i->minmask[x] = 0x3fffffff; /* 30 bits */
04285       }
04286       return;
04287    }
04288    /* Otherwise expect a range */
04289    while ((part = strsep(&times, "&"))) {
04290       if (!(endpart = strchr(part, '-'))) {
04291          if (sscanf(part, "%2d:%2d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) {
04292             ast_log(LOG_WARNING, "%s isn't a valid time.\n", part);
04293             continue;
04294          }
04295          i->minmask[st_h * 2 + (st_m >= 30 ? 1 : 0)] |= (1 << (st_m % 30));
04296          continue;
04297       }
04298       *endpart++ = '\0';
04299       /* why skip non digits? Mostly to skip spaces */
04300       while (*endpart && !isdigit(*endpart)) {
04301          endpart++;
04302       }
04303       if (!*endpart) {
04304          ast_log(LOG_WARNING, "Invalid time range starting with '%s-'.\n", part);
04305          continue;
04306       }
04307       if (sscanf(part, "%2d:%2d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) {
04308          ast_log(LOG_WARNING, "'%s' isn't a valid start time.\n", part);
04309          continue;
04310       }
04311       if (sscanf(endpart, "%2d:%2d", &endh, &endm) != 2 || endh < 0 || endh > 23 || endm < 0 || endm > 59) {
04312          ast_log(LOG_WARNING, "'%s' isn't a valid end time.\n", endpart);
04313          continue;
04314       }
04315       minute_start = st_h * 60 + st_m;
04316       minute_end = endh * 60 + endm;
04317       /* Go through the time and enable each appropriate bit */
04318       for (x = minute_start; x != minute_end; x = (x + 1) % (24 * 60)) {
04319          i->minmask[x / 30] |= (1 << (x % 30));
04320       }
04321       /* Do the last one */
04322       i->minmask[x / 30] |= (1 << (x % 30));
04323    }
04324    /* All done */
04325    return;
04326 }

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

Definition at line 3855 of file pbx.c.

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

03856 {
03857    if (argc != 5)
03858       return RESULT_SHOWUSAGE;
03859 
03860    pbx_builtin_setvar_helper(NULL, argv[3], argv[4]);
03861    ast_cli(fd, "\n    -- Global variable %s set to %s\n", argv[3], argv[4]);
03862 
03863    return RESULT_SUCCESS;
03864 }

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

CLI support for setting global variables.

Definition at line 3843 of file pbx.c.

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

03844 {
03845    if (argc != 4)
03846       return RESULT_SHOWUSAGE;
03847 
03848    pbx_builtin_setvar_helper(NULL, argv[2], argv[3]);
03849    ast_cli(fd, "\n    -- Global variable %s set to %s\n", argv[2], argv[3]);
03850 
03851    return RESULT_SUCCESS;
03852 }

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

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

03282 {
03283    struct ast_app *a;
03284    int app, no_registered_app = 1;
03285 
03286    if (argc < 4)
03287       return RESULT_SHOWUSAGE;
03288 
03289    /* ... go through all applications ... */
03290    AST_LIST_LOCK(&apps);
03291    AST_LIST_TRAVERSE(&apps, a, list) {
03292       /* ... compare this application name with all arguments given
03293        * to 'show application' command ... */
03294       for (app = 3; app < argc; app++) {
03295          if (!strcasecmp(a->name, argv[app])) {
03296             /* Maximum number of characters added by terminal coloring is 22 */
03297             char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40];
03298             char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL;
03299             int synopsis_size, description_size;
03300 
03301             no_registered_app = 0;
03302 
03303             if (a->synopsis)
03304                synopsis_size = strlen(a->synopsis) + 23;
03305             else
03306                synopsis_size = strlen("Not available") + 23;
03307             synopsis = alloca(synopsis_size);
03308 
03309             if (a->description)
03310                description_size = strlen(a->description) + 23;
03311             else
03312                description_size = strlen("Not available") + 23;
03313             description = alloca(description_size);
03314 
03315             if (synopsis && description) {
03316                snprintf(info, 64 + AST_MAX_APP, "\n  -= Info about application '%s' =- \n\n", a->name);
03317                term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22);
03318                term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
03319                term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
03320                term_color(synopsis,
03321                            a->synopsis ? a->synopsis : "Not available",
03322                            COLOR_CYAN, 0, synopsis_size);
03323                term_color(description,
03324                            a->description ? a->description : "Not available",
03325                            COLOR_CYAN, 0, description_size);
03326 
03327                ast_cli(fd,"%s%s%s\n\n%s%s\n", infotitle, syntitle, synopsis, destitle, description);
03328             } else {
03329                /* ... one of our applications, show info ...*/
03330                ast_cli(fd,"\n  -= Info about application '%s' =- \n\n"
03331                   "[Synopsis]\n  %s\n\n"
03332                   "[Description]\n%s\n",
03333                   a->name,
03334                   a->synopsis ? a->synopsis : "Not available",
03335                   a->description ? a->description : "Not available");
03336             }
03337          }
03338       }
03339    }
03340    AST_LIST_UNLOCK(&apps);
03341 
03342    /* we found at least one app? no? */
03343    if (no_registered_app) {
03344       ast_cli(fd, "Your application(s) is (are) not registered\n");
03345       return RESULT_FAILURE;
03346    }
03347 
03348    return RESULT_SUCCESS;
03349 }

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

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

03212 {
03213    struct ast_app *a;
03214    int app, no_registered_app = 1;
03215 
03216    if (argc < 3)
03217       return RESULT_SHOWUSAGE;
03218 
03219    /* ... go through all applications ... */
03220    AST_LIST_LOCK(&apps);
03221    AST_LIST_TRAVERSE(&apps, a, list) {
03222       /* ... compare this application name with all arguments given
03223        * to 'show application' command ... */
03224       for (app = 2; app < argc; app++) {
03225          if (!strcasecmp(a->name, argv[app])) {
03226             /* Maximum number of characters added by terminal coloring is 22 */
03227             char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40];
03228             char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL;
03229             int synopsis_size, description_size;
03230 
03231             no_registered_app = 0;
03232 
03233             if (a->synopsis)
03234                synopsis_size = strlen(a->synopsis) + 23;
03235             else
03236                synopsis_size = strlen("Not available") + 23;
03237             synopsis = alloca(synopsis_size);
03238 
03239             if (a->description)
03240                description_size = strlen(a->description) + 23;
03241             else
03242                description_size = strlen("Not available") + 23;
03243             description = alloca(description_size);
03244 
03245             if (synopsis && description) {
03246                snprintf(info, 64 + AST_MAX_APP, "\n  -= Info about application '%s' =- \n\n", a->name);
03247                term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22);
03248                term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
03249                term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
03250                term_color(synopsis,
03251                            a->synopsis ? a->synopsis : "Not available",
03252                            COLOR_CYAN, 0, synopsis_size);
03253                term_color(description,
03254                            a->description ? a->description : "Not available",
03255                            COLOR_CYAN, 0, description_size);
03256 
03257                ast_cli(fd,"%s%s%s\n\n%s%s\n", infotitle, syntitle, synopsis, destitle, description);
03258             } else {
03259                /* ... one of our applications, show info ...*/
03260                ast_cli(fd,"\n  -= Info about application '%s' =- \n\n"
03261                   "[Synopsis]\n  %s\n\n"
03262                   "[Description]\n%s\n",
03263                   a->name,
03264                   a->synopsis ? a->synopsis : "Not available",
03265                   a->description ? a->description : "Not available");
03266             }
03267          }
03268       }
03269    }
03270    AST_LIST_UNLOCK(&apps);
03271 
03272    /* we found at least one app? no? */
03273    if (no_registered_app) {
03274       ast_cli(fd, "Your application(s) is (are) not registered\n");
03275       return RESULT_FAILURE;
03276    }
03277 
03278    return RESULT_SUCCESS;
03279 }

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

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

03482 {
03483    struct ast_app *a;
03484    int like = 0, describing = 0;
03485    int total_match = 0;    /* Number of matches in like clause */
03486    int total_apps = 0;  /* Number of apps registered */
03487 
03488    AST_LIST_LOCK(&apps);
03489 
03490    if (AST_LIST_EMPTY(&apps)) {
03491       ast_cli(fd, "There are no registered applications\n");
03492       AST_LIST_UNLOCK(&apps);
03493       return -1;
03494    }
03495 
03496    /* core list applications like <keyword> */
03497    if ((argc == 5) && (!strcmp(argv[3], "like"))) {
03498       like = 1;
03499    } else if ((argc > 4) && (!strcmp(argv[3], "describing"))) {
03500       describing = 1;
03501    }
03502 
03503    /* core list applications describing <keyword1> [<keyword2>] [...] */
03504    if ((!like) && (!describing)) {
03505       ast_cli(fd, "    -= Registered Asterisk Applications =-\n");
03506    } else {
03507       ast_cli(fd, "    -= Matching Asterisk Applications =-\n");
03508    }
03509 
03510    AST_LIST_TRAVERSE(&apps, a, list) {
03511       int printapp = 0;
03512       total_apps++;
03513       if (like) {
03514          if (strcasestr(a->name, argv[4])) {
03515             printapp = 1;
03516             total_match++;
03517          }
03518       } else if (describing) {
03519          if (a->description) {
03520             /* Match all words on command line */
03521             int i;
03522             printapp = 1;
03523             for (i = 4; i < argc; i++) {
03524                if (!strcasestr(a->description, argv[i])) {
03525                   printapp = 0;
03526                } else {
03527                   total_match++;
03528                }
03529             }
03530          }
03531       } else {
03532          printapp = 1;
03533       }
03534 
03535       if (printapp) {
03536          ast_cli(fd,"  %20s: %s\n", a->name, a->synopsis ? a->synopsis : "<Synopsis not available>");
03537       }
03538    }
03539    if ((!like) && (!describing)) {
03540       ast_cli(fd, "    -= %d Applications Registered =-\n",total_apps);
03541    } else {
03542       ast_cli(fd, "    -= %d Applications Matching =-\n",total_match);
03543    }
03544 
03545    AST_LIST_UNLOCK(&apps);
03546 
03547    return RESULT_SUCCESS;
03548 }

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

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

03414 {
03415    struct ast_app *a;
03416    int like = 0, describing = 0;
03417    int total_match = 0;    /* Number of matches in like clause */
03418    int total_apps = 0;  /* Number of apps registered */
03419 
03420    AST_LIST_LOCK(&apps);
03421 
03422    if (AST_LIST_EMPTY(&apps)) {
03423       ast_cli(fd, "There are no registered applications\n");
03424       AST_LIST_UNLOCK(&apps);
03425       return -1;
03426    }
03427 
03428    /* show applications like <keyword> */
03429    if ((argc == 4) && (!strcmp(argv[2], "like"))) {
03430       like = 1;
03431    } else if ((argc > 3) && (!strcmp(argv[2], "describing"))) {
03432       describing = 1;
03433    }
03434 
03435    /* show applications describing <keyword1> [<keyword2>] [...] */
03436    if ((!like) && (!describing)) {
03437       ast_cli(fd, "    -= Registered Asterisk Applications =-\n");
03438    } else {
03439       ast_cli(fd, "    -= Matching Asterisk Applications =-\n");
03440    }
03441 
03442    AST_LIST_TRAVERSE(&apps, a, list) {
03443       int printapp = 0;
03444       total_apps++;
03445       if (like) {
03446          if (strcasestr(a->name, argv[3])) {
03447             printapp = 1;
03448             total_match++;
03449          }
03450       } else if (describing) {
03451          if (a->description) {
03452             /* Match all words on command line */
03453             int i;
03454             printapp = 1;
03455             for (i = 3; i < argc; i++) {
03456                if (!strcasestr(a->description, argv[i])) {
03457                   printapp = 0;
03458                } else {
03459                   total_match++;
03460                }
03461             }
03462          }
03463       } else {
03464          printapp = 1;
03465       }
03466 
03467       if (printapp) {
03468          ast_cli(fd,"  %20s: %s\n", a->name, a->synopsis ? a->synopsis : "<Synopsis not available>");
03469       }
03470    }
03471    if ((!like) && (!describing)) {
03472       ast_cli(fd, "    -= %d Applications Registered =-\n",total_apps);
03473    } else {
03474       ast_cli(fd, "    -= %d Applications Matching =-\n",total_match);
03475    }
03476 
03477    AST_LIST_UNLOCK(&apps);
03478 
03479    return RESULT_SUCCESS;
03480 }

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

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

03771 {
03772    char *exten = NULL, *context = NULL;
03773    /* Variables used for different counters */
03774    struct dialplan_counters counters;
03775 
03776    const char *incstack[AST_PBX_MAX_STACK];
03777    memset(&counters, 0, sizeof(counters));
03778 
03779    if (argc != 2 && argc != 3)
03780       return RESULT_SHOWUSAGE;
03781 
03782    /* we obtain [exten@]context? if yes, split them ... */
03783    if (argc == 3) {
03784       if (strchr(argv[2], '@')) {   /* split into exten & context */
03785          context = ast_strdupa(argv[2]);
03786          exten = strsep(&context, "@");
03787          /* change empty strings to NULL */
03788          if (ast_strlen_zero(exten))
03789             exten = NULL;
03790       } else { /* no '@' char, only context given */
03791          context = argv[2];
03792       }
03793       if (ast_strlen_zero(context))
03794          context = NULL;
03795    }
03796    /* else Show complete dial plan, context and exten are NULL */
03797    show_dialplan_helper(fd, context, exten, &counters, NULL, 0, incstack);
03798 
03799    /* check for input failure and throw some error messages */
03800    if (context && !counters.context_existence) {
03801       ast_cli(fd, "There is no existence of '%s' context\n", context);
03802       return RESULT_FAILURE;
03803    }
03804 
03805    if (exten && !counters.extension_existence) {
03806       if (context)
03807          ast_cli(fd, "There is no existence of %s@%s extension\n",
03808             exten, context);
03809       else
03810          ast_cli(fd,
03811             "There is no existence of '%s' extension in all contexts\n",
03812             exten);
03813       return RESULT_FAILURE;
03814    }
03815 
03816    ast_cli(fd,"-= %d %s (%d %s) in %d %s. =-\n",
03817             counters.total_exten, counters.total_exten == 1 ? "extension" : "extensions",
03818             counters.total_prio, counters.total_prio == 1 ? "priority" : "priorities",
03819             counters.total_context, counters.total_context == 1 ? "context" : "contexts");
03820 
03821    /* everything ok */
03822    return RESULT_SUCCESS;
03823 }

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

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

01435 {
01436    struct ast_custom_function *acf;
01437    /* Maximum number of characters added by terminal coloring is 22 */
01438    char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40];
01439    char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL;
01440    char stxtitle[40], *syntax = NULL;
01441    int synopsis_size, description_size, syntax_size;
01442 
01443    if (argc < 4)
01444       return RESULT_SHOWUSAGE;
01445 
01446    if (!(acf = ast_custom_function_find(argv[3]))) {
01447       ast_cli(fd, "No function by that name registered.\n");
01448       return RESULT_FAILURE;
01449 
01450    }
01451 
01452    if (acf->synopsis)
01453       synopsis_size = strlen(acf->synopsis) + 23;
01454    else
01455       synopsis_size = strlen("Not available") + 23;
01456    synopsis = alloca(synopsis_size);
01457 
01458    if (acf->desc)
01459       description_size = strlen(acf->desc) + 23;
01460    else
01461       description_size = strlen("Not available") + 23;
01462    description = alloca(description_size);
01463 
01464    if (acf->syntax)
01465       syntax_size = strlen(acf->syntax) + 23;
01466    else
01467       syntax_size = strlen("Not available") + 23;
01468    syntax = alloca(syntax_size);
01469 
01470    snprintf(info, 64 + AST_MAX_APP, "\n  -= Info about function '%s' =- \n\n", acf->name);
01471    term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22);
01472    term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40);
01473    term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
01474    term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
01475    term_color(syntax,
01476          acf->syntax ? acf->syntax : "Not available",
01477          COLOR_CYAN, 0, syntax_size);
01478    term_color(synopsis,
01479          acf->synopsis ? acf->synopsis : "Not available",
01480          COLOR_CYAN, 0, synopsis_size);
01481    term_color(description,
01482          acf->desc ? acf->desc : "Not available",
01483          COLOR_CYAN, 0, description_size);
01484 
01485    ast_cli(fd,"%s%s%s\n\n%s%s\n\n%s%s\n", infotitle, stxtitle, syntax, syntitle, synopsis, destitle, description);
01486 
01487    return RESULT_SUCCESS;
01488 }

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

Definition at line 1378 of file pbx.c.

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

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

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

Definition at line 1350 of file pbx.c.

References ast_custom_function::acflist, 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.

01351 {
01352    struct ast_custom_function *acf;
01353    int count_acf = 0;
01354    int like = 0;
01355 
01356    if (argc == 5 && (!strcmp(argv[3], "like")) ) {
01357       like = 1;
01358    } else if (argc != 3) {
01359       return RESULT_SHOWUSAGE;
01360    }
01361 
01362    ast_cli(fd, "%s Custom Functions:\n--------------------------------------------------------------------------------\n", like ? "Matching" : "Installed");
01363 
01364    AST_LIST_LOCK(&acf_root);
01365    AST_LIST_TRAVERSE(&acf_root, acf, acflist) {
01366       if (!like || strstr(acf->name, argv[4])) {
01367          count_acf++;
01368          ast_cli(fd, "%-20.20s  %-35.35s  %s\n", acf->name, acf->syntax, acf->synopsis);
01369       }
01370    }
01371    AST_LIST_UNLOCK(&acf_root);
01372 
01373    ast_cli(fd, "%d %scustom functions installed.\n", count_acf, like ? "matching " : "");
01374 
01375    return RESULT_SUCCESS;
01376 }

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

Definition at line 1323 of file pbx.c.

References ast_custom_function::acflist, 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.

01324 {
01325    struct ast_custom_function *acf;
01326    int count_acf = 0;
01327    int like = 0;
01328 
01329    if (argc == 4 && (!strcmp(argv[2], "like")) ) {
01330       like = 1;
01331    } else if (argc != 2) {
01332       return RESULT_SHOWUSAGE;
01333    }
01334 
01335    ast_cli(fd, "%s Custom Functions:\n--------------------------------------------------------------------------------\n", like ? "Matching" : "Installed");
01336 
01337    AST_LIST_LOCK(&acf_root);
01338    AST_LIST_TRAVERSE(&acf_root, acf, acflist) {
01339       if (!like || strstr(acf->name, argv[3])) {
01340          count_acf++;
01341          ast_cli(fd, "%-20.20s  %-35.35s  %s\n", acf->name, acf->syntax, acf->synopsis);
01342       }
01343    }
01344    AST_LIST_UNLOCK(&acf_root);
01345 
01346    ast_cli(fd, "%d %scustom functions installed.\n", count_acf, like ? "matching " : "");
01347 
01348    return RESULT_SUCCESS;
01349 }

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

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

03827 {
03828    int i = 0;
03829    struct ast_var_t *newvariable;
03830 
03831    ast_mutex_lock(&globalslock);
03832    AST_LIST_TRAVERSE (&globals, newvariable, entries) {
03833       i++;
03834       ast_cli(fd, "   %s=%s\n", ast_var_name(newvariable), ast_var_value(newvariable));
03835    }
03836    ast_mutex_unlock(&globalslock);
03837    ast_cli(fd, "\n    -- %d variables\n", i);
03838 
03839    return RESULT_SUCCESS;
03840 }

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

handle_show_hints: CLI support for listing registered dial plan hints

Definition at line 3352 of file pbx.c.

References ao2_container_count(), ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next(), ao2_ref(), ast_cli(), ast_extension_state2str(), ast_get_context_name(), ast_get_extension_app(), ast_get_extension_context(), ast_get_extension_name(), ast_hint::callbacks, ast_hint::exten, ast_hint::laststate, ast_state_cb::next, and RESULT_SUCCESS.

03353 {
03354    struct ast_hint *hint;
03355    int num = 0;
03356    int watchers;
03357    struct ast_state_cb *watcher;
03358    struct ao2_iterator i;
03359 
03360    if (ao2_container_count(hints) == 0) {
03361       ast_cli(fd, "There are no registered dialplan hints\n");
03362       return RESULT_SUCCESS;
03363    }
03364 
03365    ast_cli(fd, "\n    -= Registered Asterisk Dial Plan Hints =-\n");
03366 
03367    i = ao2_iterator_init(hints, 0);
03368    for (hint = ao2_iterator_next(&i); hint; ao2_ref(hint, -1), hint = ao2_iterator_next(&i)) {
03369       watchers = 0;
03370       for (watcher = hint->callbacks; watcher; watcher = watcher->next) {
03371          watchers++;
03372       }
03373       ast_cli(fd, "   %20s@%-20.20s: %-20.20s  State:%-15.15s Watchers %2d\n",
03374          ast_get_extension_name(hint->exten),
03375          ast_get_context_name(ast_get_extension_context(hint->exten)),
03376          ast_get_extension_app(hint->exten),
03377          ast_extension_state2str(hint->laststate), watchers);
03378       num++;
03379    }
03380    ao2_iterator_destroy(&i);
03381 
03382    ast_cli(fd, "----------------\n");
03383    ast_cli(fd, "- %d hints registered\n", num);
03384 
03385    return RESULT_SUCCESS;
03386 }

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

handle_show_switches: CLI support for listing registered dial plan switches

Definition at line 3389 of file pbx.c.

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

03390 {
03391    struct ast_switch *sw;
03392 
03393    AST_LIST_LOCK(&switches);
03394 
03395    if (AST_LIST_EMPTY(&switches)) {
03396       AST_LIST_UNLOCK(&switches);
03397       ast_cli(fd, "There are no registered alternative switches\n");
03398       return RESULT_SUCCESS;
03399    }
03400 
03401    ast_cli(fd, "\n    -= Registered Asterisk Alternative Switches =-\n");
03402    AST_LIST_TRAVERSE(&switches, sw, list)
03403       ast_cli(fd, "%s: %s\n", sw->name, sw->description);
03404 
03405    AST_LIST_UNLOCK(&switches);
03406 
03407    return RESULT_SUCCESS;
03408 }

static int hint_cmp ( void *  obj,
void *  arg,
int  flags 
) [static]

Definition at line 6673 of file pbx.c.

References ast_hint::exten.

Referenced by ast_pbx_init().

06674 {
06675    const struct ast_hint *hint = obj;
06676    const struct ast_exten *exten = arg;
06677 
06678    return (hint->exten == exten) ? CMP_MATCH | CMP_STOP : 0;
06679 }

static int hint_hash ( const void *  hint,
const int  flags 
) [static]

Definition at line 6667 of file pbx.c.

Referenced by ast_pbx_init().

06668 {
06669    /* Only 1 bucket, not important. */
06670    return 0;
06671 }

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

Definition at line 617 of file pbx.c.

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

Referenced by pbx_find_extension().

00618 {
00619    if (!i->hastime)
00620       return 1;
00621 
00622    return ast_check_timing(&(i->timing));
00623 }

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

Definition at line 2659 of file pbx.c.

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

Referenced by ast_pbx_run(), and ast_pbx_start().

02660 {
02661    int failed = 0;
02662    double curloadavg;
02663    ast_mutex_lock(&maxcalllock);
02664    if (option_maxcalls) {
02665       if (countcalls >= option_maxcalls) {
02666          ast_log(LOG_NOTICE, "Maximum call limit of %d calls exceeded by '%s'!\n", option_maxcalls, c->name);
02667          failed = -1;
02668       }
02669    }
02670    if (option_maxload) {
02671       getloadavg(&curloadavg, 1);
02672       if (curloadavg >= option_maxload) {
02673          ast_log(LOG_NOTICE, "Maximum loadavg limit of %f load exceeded by '%s' (currently %f)!\n", option_maxload, c->name, curloadavg);
02674          failed = -1;
02675       }
02676    }
02677    if (!failed) {
02678       countcalls++;
02679       totalcalls++;
02680    }
02681    ast_mutex_unlock(&maxcalllock);
02682 
02683    return failed;
02684 }

int load_pbx ( void   ) 

Provided by pbx.c

Definition at line 6365 of file pbx.c.

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

Referenced by main().

06366 {
06367    int x;
06368 
06369    /* Initialize the PBX */
06370    if (option_verbose) {
06371       ast_verbose( "Asterisk PBX Core Initializing\n");
06372       ast_verbose( "Registering builtin applications:\n");
06373    }
06374    ast_cli_register_multiple(pbx_cli, sizeof(pbx_cli) / sizeof(struct ast_cli_entry));
06375 
06376    /* Register builtin applications */
06377    for (x=0; x<sizeof(builtins) / sizeof(struct pbx_builtin); x++) {
06378       if (option_verbose)
06379          ast_verbose( VERBOSE_PREFIX_1 "[%s]\n", builtins[x].name);
06380       if (ast_register_application(builtins[x].name, builtins[x].execute, builtins[x].synopsis, builtins[x].description)) {
06381          ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name);
06382          return -1;
06383       }
06384    }
06385    return 0;
06386 }

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

Referenced by get_range().

04204 {
04205    int i;
04206 
04207    if (names && *s > '9') {
04208       for (i = 0; names[i]; i++) {
04209          if (!strcasecmp(s, names[i])) {
04210             return i;
04211          }
04212       }
04213    }
04214    /* Allow months and weekdays to be specified as numbers, as well */
04215    if (sscanf(s, "%2d", &i) == 1 && i >= 1 && i <= max) {
04216       /* What the array offset would have been: "1" would be at offset 0 */
04217       return i - 1;
04218    }
04219    return -1; /* error return */
04220 }

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

Definition at line 970 of file pbx.c.

References ast_extension_match(), and ast_strlen_zero().

Referenced by pbx_find_extension().

00971 {
00972    /* If the Caller*ID pattern is empty, then we're matching NO Caller*ID, so
00973       failing to get a number should count as a match, otherwise not */
00974 
00975    if (ast_strlen_zero(callerid))
00976       return ast_strlen_zero(cidpattern) ? 1 : 0;
00977 
00978    return ast_extension_match(cidpattern, callerid);
00979 }

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

Referenced by pbx_retrieve_variable(), and pbx_substitute_variables_helper_full().

01137 {
01138    int parens=0;
01139 
01140    *offset = 0;
01141    *length = INT_MAX;
01142    *isfunc = 0;
01143    for (; *var; var++) {
01144       if (*var == '(') {
01145          (*isfunc)++;
01146          parens++;
01147       } else if (*var == ')') {
01148          parens--;
01149       } else if (*var == ':' && parens == 0) {
01150          *var++ = '\0';
01151          sscanf(var, "%30d:%30d", offset, length);
01152          return 1; /* offset:length valid */
01153       }
01154    }
01155    return 0;
01156 }

void pbx_builtin_clear_globals ( void   ) 

Definition at line 6167 of file pbx.c.

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

Referenced by handle_reload_extensions(), and reload().

06168 {
06169    struct ast_var_t *vardata;
06170 
06171    ast_mutex_lock(&globalslock);
06172    while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries)))
06173       ast_var_delete(vardata);
06174    ast_mutex_unlock(&globalslock);
06175 }

const char* pbx_builtin_getvar_helper ( struct ast_channel chan,
const char *  name 
)
Note:
Will lock the channel.

Definition at line 5943 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(), 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_call_forward(), ast_monitor_stop(), builtin_automonitor(), check_goto_on_transfer(), common_exec(), conf_exec(), conf_run(), dahdi_call(), dahdi_hangup(), dahdi_r2_answer(), dahdi_r2_get_channel_category(), dundi_exec(), dundi_helper(), feature_check(), feature_interpret(), get_also_info(), get_index(), get_refer_info(), global_read(), iax2_exec(), import_ch(), leave_voicemail(), local_hangup(), macro_fixup(), misdn_answer(), misdn_hangup(), morsecode_exec(), notify_new_message(), oh323_call(), oh323_hangup(), park_call_full(), park_space_reserve(), pbx_builtin_background(), pickup_by_mark(), queue_exec(), real_ctx(), retrydial_exec(), return_exec(), ring_entry(), run_agi(), set_config_flags(), sip_addheader(), sla_trunk_exec(), speech_background(), try_calling(), try_suggested_sip_codec(), update_bridgepeer(), and wait_for_answer().

05944 {
05945    struct ast_var_t *variables;
05946    const char *ret = NULL;
05947    int i;
05948    struct varshead *places[2] = { NULL, &globals };
05949 
05950    if (!name)
05951       return NULL;
05952 
05953    if (chan) {
05954       ast_channel_lock(chan);
05955       places[0] = &chan->varshead;
05956    }
05957 
05958    for (i = 0; i < 2; i++) {
05959       if (!places[i])
05960          continue;
05961       if (places[i] == &globals)
05962          ast_mutex_lock(&globalslock);
05963       AST_LIST_TRAVERSE(places[i], variables, entries) {
05964          if (!strcmp(name, ast_var_name(variables))) {
05965             ret = ast_var_value(variables);
05966             break;
05967          }
05968       }
05969       if (places[i] == &globals)
05970          ast_mutex_unlock(&globalslock);
05971       if (ret)
05972          break;
05973    }
05974 
05975    if (chan)
05976       ast_channel_unlock(chan);
05977 
05978    return ret;
05979 }

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

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

06188 {
06189    char *condition, *branch1, *branch2, *branch;
06190    int rc;
06191    char *stringp;
06192 
06193    if (ast_strlen_zero(data)) {
06194       ast_log(LOG_WARNING, "Ignoring, since there is no variable to check\n");
06195       return 0;
06196    }
06197 
06198    stringp = ast_strdupa(data);
06199    condition = strsep(&stringp,"?");
06200    branch1 = strsep(&stringp,":");
06201    branch2 = strsep(&stringp,"");
06202    branch = pbx_checkcondition(condition) ? branch1 : branch2;
06203 
06204    if (ast_strlen_zero(branch)) {
06205       if (option_debug)
06206          ast_log(LOG_DEBUG, "Not taking any branch\n");
06207       return 0;
06208    }
06209 
06210    rc = pbx_builtin_goto(chan, branch);
06211 
06212    return rc;
06213 }

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

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

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

06107 {
06108    char *name;
06109    char *value;
06110    char *channel;
06111    char tmp[VAR_BUF_SIZE]="";
06112 
06113    if (ast_strlen_zero(data)) {
06114       ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n");
06115       return 0;
06116    }
06117 
06118    value = ast_strdupa(data);
06119    name = strsep(&value,"=");
06120    channel = strsep(&value,"|");
06121    if (channel && value && name) { /*! \todo XXX should do !ast_strlen_zero(..) of the args ? */
06122       struct ast_channel *chan2 = ast_get_channel_by_name_locked(channel);
06123       if (chan2) {
06124          char *s = alloca(strlen(value) + 4);
06125          if (s) {
06126             sprintf(s, "${%s}", value);
06127             pbx_substitute_variables_helper(chan2, s, tmp, sizeof(tmp) - 1);
06128          }
06129          ast_channel_unlock(chan2);
06130       }
06131       pbx_builtin_setvar_helper(chan, name, tmp);
06132    }
06133 
06134    return(0);
06135 }

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

Definition at line 6162 of file pbx.c.

06163 {
06164    return 0;
06165 }

void pbx_builtin_pushvar_helper ( struct ast_channel chan,
const char *  name,
const char *  value 
)
Note:
Will lock the channel.

Definition at line 5981 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(), LOG_WARNING, option_verbose, ast_channel::varshead, and VERBOSE_PREFIX_2.

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

05982 {
05983    struct ast_var_t *newvariable;
05984    struct varshead *headp;
05985 
05986    if (name[strlen(name)-1] == ')') {
05987       char *function = ast_strdupa(name);
05988 
05989       ast_log(LOG_WARNING, "Cannot push a value onto a function\n");
05990       ast_func_write(chan, function, value);
05991       return;
05992    }
05993 
05994    if (chan) {
05995       ast_channel_lock(chan);
05996       headp = &chan->varshead;
05997    } else {
05998       ast_mutex_lock(&globalslock);
05999       headp = &globals;
06000    }
06001 
06002    if (value) {
06003       if ((option_verbose > 1) && (headp == &globals))
06004          ast_verbose(VERBOSE_PREFIX_2 "Setting global variable '%s' to '%s'\n", name, value);
06005       newvariable = ast_var_assign(name, value);
06006       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
06007    }
06008 
06009    if (chan)
06010       ast_channel_unlock(chan);
06011    else
06012       ast_mutex_unlock(&globalslock);
06013 }

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

Definition at line 6252 of file pbx.c.

References ast_say_character_str().

06253 {
06254    int res = 0;
06255 
06256    if (data)
06257       res = ast_say_character_str(chan, data, "", chan->language);
06258    return res;
06259 }

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

Definition at line 6270 of file pbx.c.

References AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), ast_say_date, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), LOG_WARNING, parse(), and pbx_builtin_setvar_helper().

06271 {
06272    int res = 0;
06273    char *parse;
06274    int unixdate = 0;
06275    char charascii[2];
06276 
06277    AST_DECLARE_APP_ARGS(args,
06278       AST_APP_ARG(datestr);
06279       AST_APP_ARG(digits);
06280    );
06281 
06282 
06283    if (ast_strlen_zero(data)) {
06284       ast_log(LOG_WARNING, "SayDate requires an argument (date)\n");
06285       return -1;
06286    }
06287 
06288    if (!(parse = ast_strdupa(data))) {
06289       ast_log(LOG_WARNING, "Memory Error!\n");
06290       return -1;
06291    }
06292 
06293    AST_STANDARD_APP_ARGS(args, parse);
06294 
06295    if (!ast_strlen_zero(args.digits) && (strspn(args.digits, "0123456789*#") != strlen(args.digits))) {
06296       ast_log(LOG_WARNING, "SayDate escape digits must be a subset from '0123456789*#'\n");
06297       args.digits = "";
06298    }
06299 
06300    if (sscanf(args.datestr, "%d", &unixdate) != 1) {
06301       ast_log(LOG_WARNING, "Firt argument to SayDate must be numeric (date)\n");
06302       return -1;
06303    }
06304 
06305    res = ast_say_date(chan, (time_t)unixdate, args.digits, chan->language);
06306    if (res > 0) {
06307       if (isdigit(res) || (res == '*') || (res == '#')) {
06308          snprintf(charascii, 2, "%c", res);
06309          pbx_builtin_setvar_helper(chan, "USER_INPUT", charascii);
06310          res = 0;
06311       } else {
06312          ast_log(LOG_WARNING, "SayDate: invalid return value (%d) detected\n", res);
06313       }
06314    }
06315    return res;
06316 }

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

Definition at line 6243 of file pbx.c.

References ast_say_digit_str().

06244 {
06245    int res = 0;
06246 
06247    if (data)
06248       res = ast_say_digit_str(chan, data, "", chan->language);
06249    return res;
06250 }

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

Definition at line 6215 of file pbx.c.

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

06216 {
06217    char tmp[256];
06218    char *number = tmp;
06219    char *options;
06220 
06221    if (ast_strlen_zero(data)) {
06222       ast_log(LOG_WARNING, "SayNumber requires an argument (number)\n");
06223       return -1;
06224    }
06225    ast_copy_string(tmp, data, sizeof(tmp));
06226    strsep(&number, "|");
06227    options = strsep(&number, "|");
06228    if (options) {
06229       if ( strcasecmp(options, "f") && strcasecmp(options,"m") &&
06230          strcasecmp(options, "c") && strcasecmp(options, "n") ) {
06231          ast_log(LOG_WARNING, "SayNumber gender option is either 'f', 'm', 'c' or 'n'\n");
06232          return -1;
06233       }
06234    }
06235 
06236    if (ast_say_number(chan, atoi(tmp), "", chan->language, options)) {
06237       ast_log(LOG_WARNING, "We were unable to say the number %s, is it too large?\n", tmp);
06238    }
06239 
06240    return 0;
06241 }

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

Definition at line 6261 of file pbx.c.

References ast_say_phonetic_str().

06262 {
06263    int res = 0;
06264 
06265    if (data)
06266       res = ast_say_phonetic_str(chan, data, "", chan->language);
06267    return res;
06268 }

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

Definition at line 6318 of file pbx.c.

References AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), ast_say_time, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), LOG_WARNING, parse(), and pbx_builtin_setvar_helper().

06319 {
06320    int res = 0;
06321    char *parse;
06322    int secs = 0;
06323    char charascii[2];
06324 
06325    AST_DECLARE_APP_ARGS(args,
06326       AST_APP_ARG(timestr);
06327       AST_APP_ARG(digits);
06328    );
06329 
06330    if (ast_strlen_zero(data)) {
06331       ast_log(LOG_WARNING, "SayTime requires an argument (time in seconds)\n");
06332       return -1;
06333    }
06334 
06335    if (!(parse = ast_strdupa(data))) {
06336       ast_log(LOG_WARNING, "Memory Error!\n");
06337       return -1;
06338    }
06339 
06340    AST_STANDARD_APP_ARGS(args, parse);
06341 
06342    if (!ast_strlen_zero(args.digits) && (strspn(args.digits, "0123456789*#") != strlen(args.digits))) {
06343       ast_log(LOG_WARNING, "SayTime escape digits must be a subset from '0123456789*#'\n");
06344       args.digits = "";
06345    }
06346 
06347    if (sscanf(args.timestr, "%d", &secs) != 1) {
06348       ast_log(LOG_WARNING, "Firt argument to SayTime must be numeric (time in seconds)\n");
06349       return -1;
06350    }
06351 
06352    res = ast_say_time(chan, (time_t)secs, args.digits, chan->language);
06353    if (res > 0) {
06354       if (isdigit(res) || (res == '*') || (res == '#')) {
06355          snprintf(charascii, 2, "%c", res);
06356          pbx_builtin_setvar_helper(chan, "USER_INPUT", charascii);
06357          res = 0;
06358       } else {
06359          ast_log(LOG_WARNING, "SayTime: invalid return value (%d) detected\n", res);
06360       }
06361    }
06362    return res;
06363 }

int pbx_builtin_serialize_variables ( struct ast_channel chan,
char *  buf,
size_t  size 
)
Note:
Will lock the channel.

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

05913 {
05914    struct ast_var_t *variables;
05915    const char *var, *val;
05916    int total = 0;
05917 
05918    if (!chan)
05919       return 0;
05920 
05921    memset(buf, 0, size);
05922 
05923    ast_channel_lock(chan);
05924 
05925    AST_LIST_TRAVERSE(&chan->varshead, variables, entries) {
05926       if ((var=ast_var_name(variables)) && (val=ast_var_value(variables))
05927          /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */
05928          ) {
05929          if (ast_build_string(&buf, &size, "%s=%s\n", var, val)) {
05930             ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
05931             break;
05932          } else
05933             total++;
05934       } else
05935          break;
05936    }
05937 
05938    ast_channel_unlock(chan);
05939 
05940    return total;
05941 }

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

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

06139 {
06140    char *name;
06141    char *stringp = data;
06142    static int dep_warning = 0;
06143 
06144    if (ast_strlen_zero(data)) {
06145       ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n");
06146       return 0;
06147    }
06148 
06149    name = strsep(&stringp, "=");
06150 
06151    if (!dep_warning) {
06152       dep_warning = 1;
06153       ast_log(LOG_WARNING, "SetGlobalVar is deprecated.  Please use Set(GLOBAL(%s)=%s) instead.\n", name, stringp);
06154    }
06155 
06156    /*! \todo XXX watch out, leading whitespace ? */
06157    pbx_builtin_setvar_helper(NULL, name, stringp);
06158 
06159    return(0);
06160 }

int pbx_builtin_setvar ( struct ast_channel chan,
void *  data 
)
Note:
Will lock the channel.

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

06067 {
06068    char *name, *value, *mydata;
06069    int argc;
06070    char *argv[24];      /* this will only support a maximum of 24 variables being set in a single operation */
06071    int global = 0;
06072    int x;
06073 
06074    if (ast_strlen_zero(data)) {
06075       ast_log(LOG_WARNING, "Set requires at least one variable name/value pair.\n");
06076       return 0;
06077    }
06078 
06079    mydata = ast_strdupa(data);
06080    argc = ast_app_separate_args(mydata, '|', argv, sizeof(argv) / sizeof(argv[0]));
06081 
06082    /* check for a trailing flags argument */
06083    if ((argc > 1) && !strchr(argv[argc-1], '=')) {
06084       argc--;
06085       if (strchr(argv[argc], 'g')) {
06086          ast_log(LOG_WARNING, "The use of the 'g' flag is deprecated.  Please use Set(GLOBAL(foo)=bar) instead\n");
06087          global = 1;
06088       }
06089    }
06090 
06091    if (argc > 1)
06092       ast_log(LOG_WARNING, "Setting multiple variables at once within Set is deprecated.  Please separate each name/value pair into its own line.\n");
06093 
06094    for (x = 0; x < argc; x++) {
06095       name = argv[x];
06096       if ((value = strchr(name, '='))) {
06097          *value++ = '\0';
06098          pbx_builtin_setvar_helper((global) ? NULL : chan, name, value);
06099       } else
06100          ast_log(LOG_WARNING, "Ignoring entry '%s' with no = (and not last 'options' entry)\n", name);
06101    }
06102 
06103    return(0);
06104 }

void pbx_builtin_setvar_helper ( struct ast_channel chan,
const char *  name,
const char *  value 
)
Note:
Will lock the channel.

Definition at line 6015 of file pbx.c.

References ast_channel_lock, ast_channel_unlock, ast_func_write(), AST_LIST_INSERT_HEAD, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_mutex_lock(), ast_mutex_unlock(), ast_strdupa, ast_var_assign(), ast_var_delete(), ast_var_name(), ast_verbose(), option_verbose, ast_channel::varshead, and VERBOSE_PREFIX_2.

Referenced by __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(), aqm_exec(), array(), ast_bridge_call(), ast_iax2_new(), ast_monitor_start(), ast_monitor_stop(), ast_pbx_outgoing_exten(), ast_set_variables(), background_detect_exec(), builtin_automonitor(), builtin_blindtransfer(), cb_events(), chanavail_exec(), conf_run(), controlplayback_exec(), count_exec(), dahdi_handle_dtmf(), dahdi_new(), disa_exec(), do_waiting(), end_bridge_callback(), export_aoc_vars(), export_ch(), feature_request_and_dial(), 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(), macro_fixup(), misdn_call(), mixmonitor_exec(), ospauth_exec(), ospfinished_exec(), osplookup_exec(), ospnext_exec(), park_call_full(), park_exec(), parse_moved_contact(), pbx_builtin_importvar(), pbx_builtin_saydate(), pbx_builtin_saytime(), pbx_builtin_setglobalvar(), pbx_builtin_setvar(), pbx_load_config(), play_message_datetime(), playback_exec(), pop_exec(), pqm_exec(), prep_email_sub_vars(), pri_dchannel(), privacy_exec(), process_ast_dsp(), read_exec(), readfile_exec(), realtime_exec(), realtime_update_exec(), record_exec(), return_exec(), ring_entry(), 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(), update_bridgepeer(), upqm_exec(), vm_box_exists(), vm_exec(), and vmauthenticate().

06016 {
06017    struct ast_var_t *newvariable;
06018    struct varshead *headp;
06019    const char *nametail = name;
06020 
06021    if (name[strlen(name)-1] == ')') {
06022       char *function = ast_strdupa(name);
06023 
06024       ast_func_write(chan, function, value);
06025       return;
06026    }
06027 
06028    if (chan) {
06029       ast_channel_lock(chan);
06030       headp = &chan->varshead;
06031    } else {
06032       ast_mutex_lock(&globalslock);
06033       headp = &globals;
06034    }
06035 
06036    /* For comparison purposes, we have to strip leading underscores */
06037    if (*nametail == '_') {
06038       nametail++;
06039       if (*nametail == '_')
06040          nametail++;
06041    }
06042 
06043    AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) {
06044       if (strcmp(ast_var_name(newvariable), nametail) == 0) {
06045          /* there is already such a variable, delete it */
06046          AST_LIST_REMOVE_CURRENT(headp, entries);
06047          ast_var_delete(newvariable);
06048          break;
06049       }
06050    }
06051    AST_LIST_TRAVERSE_SAFE_END;
06052 
06053    if (value) {
06054       if ((option_verbose > 1) && (headp == &globals))
06055          ast_verbose(VERBOSE_PREFIX_2 "Setting global variable '%s' to '%s'\n", name, value);
06056       newvariable = ast_var_assign(name, value);
06057       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
06058    }
06059 
06060    if (chan)
06061       ast_channel_unlock(chan);
06062    else
06063       ast_mutex_unlock(&globalslock);
06064 }

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

06178 {
06179    if (ast_strlen_zero(condition))  /* NULL or empty strings are false */
06180       return 0;
06181    else if (*condition >= '0' && *condition <= '9')   /* Numbers are evaluated for truth */
06182       return atoi(condition);
06183    else  /* Strings are true */
06184       return 1;
06185 }

static void pbx_destroy ( struct ast_pbx p  )  [static]

Definition at line 625 of file pbx.c.

References free.

Referenced by __ast_pbx_run().

00626 {
00627    free(p);
00628 }

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

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

Referenced by aelsub_exec(), 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().

00554 {
00555    int res;
00556 
00557    const char *saved_c_appl;
00558    const char *saved_c_data;
00559 
00560    if (c->cdr && !ast_check_hangup(c))
00561       ast_cdr_setapp(c->cdr, app->name, data);
00562 
00563    /* save channel values */
00564    saved_c_appl= c->appl;
00565    saved_c_data= c->data;
00566 
00567    c->appl = app->name;
00568    c->data = data;
00569    /* XXX remember what to to when we have linked apps to modules */
00570    if (app->module) {
00571       /* XXX LOCAL_USER_ADD(app->module) */
00572    }
00573    res = app->execute(c, S_OR(data, ""));
00574    if (app->module) {
00575       /* XXX LOCAL_USER_REMOVE(app->module) */
00576    }
00577    /* restore channel values */
00578    c->appl = saved_c_appl;
00579    c->data = saved_c_data;
00580    return res;
00581 }

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

References ast_exten::app, app, ast_copy_string(), 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, S_OR, 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().

01866 {
01867    struct ast_exten *e;
01868    struct ast_app *app;
01869    int res;
01870    struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */
01871    char passdata[EXT_DATA_SIZE];
01872 
01873    int matching_action = (action == E_MATCH || action == E_CANMATCH || action == E_MATCHMORE);
01874 
01875    ast_rdlock_contexts();
01876    e = pbx_find_extension(c, con, &q, context, exten, priority, label, callerid, action);
01877    if (e) {
01878       if (matching_action) {
01879          ast_unlock_contexts();
01880          return -1;  /* success, we found it */
01881       } else if (action == E_FINDLABEL) { /* map the label to a priority */
01882          res = e->priority;
01883          ast_unlock_contexts();
01884          return res; /* the priority we were looking for */
01885       } else { /* spawn */
01886          app = pbx_findapp(e->app);
01887          ast_unlock_contexts();
01888          if (!app) {
01889             ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority);
01890             return -1;
01891          }
01892          if (c->context != context)
01893             ast_copy_string(c->context, context, sizeof(c->context));
01894          if (c->exten != exten)
01895             ast_copy_string(c->exten, exten, sizeof(c->exten));
01896          c->priority = priority;
01897          pbx_substitute_variables(passdata, sizeof(passdata), c, e);
01898          if (option_debug) {
01899             ast_log(LOG_DEBUG, "Launching '%s'\n", app->name);
01900          }
01901          if (option_verbose > 2) {
01902             char tmp[80], tmp2[80], tmp3[EXT_DATA_SIZE];
01903             ast_verbose( VERBOSE_PREFIX_3 "Executing [%s@%s:%d] %s(\"%s\", \"%s\") %s\n",
01904                exten, context, priority,
01905                term_color(tmp, app->name, COLOR_BRCYAN, 0, sizeof(tmp)),
01906                term_color(tmp2, c->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)),
01907                term_color(tmp3, passdata, COLOR_BRMAGENTA, 0, sizeof(tmp3)),
01908                "in new stack");
01909          }
01910          manager_event(EVENT_FLAG_CALL, "Newexten",
01911                "Channel: %s\r\n"
01912                "Context: %s\r\n"
01913                "Extension: %s\r\n"
01914                "Priority: %d\r\n"
01915                "Application: %s\r\n"
01916                "AppData: %s\r\n"
01917                "Uniqueid: %s\r\n",
01918                c->name, c->context, c->exten, c->priority, app->name, passdata, c->uniqueid);
01919          return pbx_exec(c, app, passdata);  /* 0 on success, -1 on failure */
01920       }
01921    } else if (q.swo) {  /* not found here, but in another switch */
01922       ast_unlock_contexts();
01923       if (matching_action) {
01924          return -1;
01925       } else {
01926          if (!q.swo->exec) {
01927             ast_log(LOG_WARNING, "No execution engine for switch %s\n", q.swo->name);
01928             res = -1;
01929          }
01930          return q.swo->exec(c, q.foundcontext ? q.foundcontext : context, exten, priority, callerid, q.data);
01931       }
01932    } else { /* not found anywhere, see what happened */
01933       ast_unlock_contexts();
01934       /* Using S_OR here because Solaris doesn't like NULL being passed to ast_log */
01935       switch (q.status) {
01936       case STATUS_NO_CONTEXT:
01937          if (!matching_action)
01938             ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", S_OR(context, ""));
01939          break;
01940       case STATUS_NO_EXTENSION:
01941          if (!matching_action)
01942             ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, S_OR(context, ""));
01943          break;
01944       case STATUS_NO_PRIORITY:
01945          if (!matching_action)
01946             ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, S_OR(context, ""));
01947          break;
01948       case STATUS_NO_LABEL:
01949          if (context)
01950             ast_log(LOG_NOTICE, "No such label '%s' in extension '%s' in context '%s'\n", label, exten, S_OR(context, ""));
01951          break;
01952       default:
01953          if (option_debug)
01954             ast_log(LOG_DEBUG, "Shouldn't happen!\n");
01955       }
01956 
01957       return (matching_action) ? 0 : -1;
01958    }
01959 }

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

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

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

01001 {
01002    int x, res;
01003    struct ast_context *tmp;
01004    struct ast_exten *e, *eroot;
01005    struct ast_include *i;
01006    struct ast_sw *sw;
01007    char *tmpdata = NULL;
01008 
01009    /* Initialize status if appropriate */
01010    if (q->stacklen == 0) {
01011       q->status = STATUS_NO_CONTEXT;
01012       q->swo = NULL;
01013       q->data = NULL;
01014       q->foundcontext = NULL;
01015    }
01016    /* Check for stack overflow */
01017    if (q->stacklen >= AST_PBX_MAX_STACK) {
01018       ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n");
01019       return NULL;
01020    }
01021    /* Check first to see if we've already been checked */
01022    for (x = 0; x < q->stacklen; x++) {
01023       if (!strcasecmp(q->incstack[x], context))
01024          return NULL;
01025    }
01026    if (bypass) /* bypass means we only look there */
01027       tmp = bypass;
01028    else {   /* look in contexts */
01029       tmp = NULL;
01030       while ((tmp = ast_walk_contexts(tmp)) ) {
01031          if (!strcmp(tmp->name, context))
01032             break;
01033       }
01034       if (!tmp)
01035          return NULL;
01036    }
01037    if (q->status < STATUS_NO_EXTENSION)
01038       q->status = STATUS_NO_EXTENSION;
01039 
01040    /* scan the list trying to match extension and CID */
01041    eroot = NULL;
01042    while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) {
01043       int match = extension_match_core(eroot->exten, exten, action);
01044       /* 0 on fail, 1 on match, 2 on earlymatch */
01045 
01046       if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid)))
01047          continue;   /* keep trying */
01048       if (match == 2 && action == E_MATCHMORE) {
01049          /* We match an extension ending in '!'.
01050           * The decision in this case is final and is NULL (no match).
01051           */
01052          return NULL;
01053       }
01054       /* found entry, now look for the right priority */
01055       if (q->status < STATUS_NO_PRIORITY)
01056          q->status = STATUS_NO_PRIORITY;
01057       e = NULL;
01058       while ( (e = ast_walk_extension_priorities(eroot, e)) ) {
01059          /* Match label or priority */
01060          if (action == E_FINDLABEL) {
01061             if (q->status < STATUS_NO_LABEL)
01062                q->status = STATUS_NO_LABEL;
01063             if (label && e->label && !strcmp(label, e->label))
01064                break;   /* found it */
01065          } else if (e->priority == priority) {
01066             break;   /* found it */
01067          } /* else keep searching */
01068       }
01069       if (e) { /* found a valid match */
01070          q->status = STATUS_SUCCESS;
01071          q->foundcontext = context;
01072          return e;
01073       }
01074    }
01075    /* Check alternative switches */
01076    AST_LIST_TRAVERSE(&tmp->alts, sw, list) {
01077       struct ast_switch *asw = pbx_findswitch(sw->name);
01078       ast_switch_f *aswf = NULL;
01079       char *datap;
01080 
01081       if (!asw) {
01082          ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name);
01083          continue;
01084       }
01085       /* Substitute variables now */
01086       if (sw->eval) {
01087          if (!(tmpdata = ast_threadstorage_get(&switch_data, 512))) {
01088             ast_log(LOG_WARNING, "Can't evaluate switch?!");
01089             continue;
01090          }
01091          pbx_substitute_variables_helper(chan, sw->data, tmpdata, 512);
01092       }
01093 
01094       /* equivalent of extension_match_core() at the switch level */
01095       if (action == E_CANMATCH)
01096          aswf = asw->canmatch;
01097       else if (action == E_MATCHMORE)
01098          aswf = asw->matchmore;
01099       else /* action == E_MATCH */
01100          aswf = asw->exists;
01101       datap = sw->eval ? tmpdata : sw->data;
01102       if (!aswf)
01103          res = 0;
01104       else {
01105          if (chan)
01106             ast_autoservice_start(chan);
01107          res = aswf(chan, context, exten, priority, callerid, datap);
01108          if (chan)
01109             ast_autoservice_stop(chan);
01110       }
01111       if (res) {  /* Got a match */
01112          q->swo = asw;
01113          q->data = datap;
01114          q->foundcontext = context;
01115          /* XXX keep status = STATUS_NO_CONTEXT ? */
01116          return NULL;
01117       }
01118    }
01119    q->incstack[q->stacklen++] = tmp->name;   /* Setup the stack */
01120    /* Now try any includes we have in this context */
01121    for (i = tmp->includes; i; i = i->next) {
01122       if (include_valid(i)) {
01123          if ((e = pbx_find_extension(chan, bypass, q, i->rname, exten, priority, label, callerid, action)))
01124             return e;
01125          if (q->swo)
01126             return NULL;
01127       }
01128    }
01129    return NULL;
01130 }

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

Find application handle in linked list.

Look up an application.

Definition at line 589 of file pbx.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, and AST_LIST_UNLOCK.

Referenced by aelsub_exec(), 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().

00590 {
00591    struct ast_app *tmp;
00592 
00593    AST_LIST_LOCK(&apps);
00594    AST_LIST_TRAVERSE(&apps, tmp, list) {
00595       if (!strcasecmp(tmp->name, app))
00596          break;
00597    }
00598    AST_LIST_UNLOCK(&apps);
00599 
00600    return tmp;
00601 }

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

Definition at line 603 of file pbx.c.

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

Referenced by pbx_find_extension().

00604 {
00605    struct ast_switch *asw;
00606 
00607    AST_LIST_LOCK(&switches);
00608    AST_LIST_TRAVERSE(&switches, asw, list) {
00609       if (!strcasecmp(asw->name, sw))
00610          break;
00611    }
00612    AST_LIST_UNLOCK(&switches);
00613 
00614    return asw;
00615 }

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

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

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

01205 {
01206    const char not_found = '\0';
01207    char *tmpvar;
01208    const char *s; /* the result */
01209    int offset, length;
01210    int i, need_substring;
01211    struct varshead *places[2] = { headp, &globals };  /* list of places where we may look */
01212 
01213    if (c) {
01214       ast_channel_lock(c);
01215       places[0] = &c->varshead;
01216    }
01217    /*
01218     * Make a copy of var because parse_variable_name() modifies the string.
01219     * Then if called directly, we might need to run substring() on the result;
01220     * remember this for later in 'need_substring', 'offset' and 'length'
01221     */
01222    tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */
01223    need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */);
01224 
01225    /*
01226     * Look first into predefined variables, then into variable lists.
01227     * Variable 's' points to the result, according to the following rules:
01228     * s == &not_found (set at the beginning) means that we did not find a
01229     * matching variable and need to look into more places.
01230     * If s != &not_found, s is a valid result string as follows:
01231     * s = NULL if the variable does not have a value;
01232     * you typically do this when looking for an unset predefined variable.
01233     * s = workspace if the result has been assembled there;
01234     * typically done when the result is built e.g. with an snprintf(),
01235     * so we don't need to do an additional copy.
01236     * s != workspace in case we have a string, that needs to be copied
01237     * (the ast_copy_string is done once for all at the end).
01238     * Typically done when the result is already available in some string.
01239     */
01240    s = &not_found;   /* default value */
01241    if (c) { /* This group requires a valid channel */
01242       /* Names with common parts are looked up a piece at a time using strncmp. */
01243       if (!strncmp(var, "CALL", 4)) {
01244          if (!strncmp(var + 4, "ING", 3)) {
01245             if (!strcmp(var + 7, "PRES")) {        /* CALLINGPRES */
01246                snprintf(workspace, workspacelen, "%d", c->cid.cid_pres);
01247                s = workspace;
01248             } else if (!strcmp(var + 7, "ANI2")) {    /* CALLINGANI2 */
01249                snprintf(workspace, workspacelen, "%d", c->cid.cid_ani2);
01250                s = workspace;
01251             } else if (!strcmp(var + 7, "TON")) {     /* CALLINGTON */
01252                snprintf(workspace, workspacelen, "%d", c->cid.cid_ton);
01253                s = workspace;
01254             } else if (!strcmp(var + 7, "TNS")) {     /* CALLINGTNS */
01255                snprintf(workspace, workspacelen, "%d", c->cid.cid_tns);
01256                s = workspace;
01257             }
01258          }
01259       } else if (!strcmp(var, "HINT")) {
01260          s = ast_get_hint(workspace, workspacelen, NULL, 0, c, c->context, c->exten) ? workspace : NULL;
01261       } else if (!strcmp(var, "HINTNAME")) {
01262          s = ast_get_hint(NULL, 0, workspace, workspacelen, c, c->context, c->exten) ? workspace : NULL;
01263       } else if (!strcmp(var, "EXTEN")) {
01264          s = c->exten;
01265       } else if (!strcmp(var, "CONTEXT")) {
01266          s = c->context;
01267       } else if (!strcmp(var, "PRIORITY")) {
01268          snprintf(workspace, workspacelen, "%d", c->priority);
01269          s = workspace;
01270       } else if (!strcmp(var, "CHANNEL")) {
01271          s = c->name;
01272       } else if (!strcmp(var, "UNIQUEID")) {
01273          s = c->uniqueid;
01274       } else if (!strcmp(var, "HANGUPCAUSE")) {
01275          snprintf(workspace, workspacelen, "%d", c->hangupcause);
01276          s = workspace;
01277       } else if (c && !strcmp(var, "HANGUPCAUSESTR")) {
01278          ast_copy_string(workspace, ast_cause2str(c->hangupcause), workspacelen);
01279          *ret = workspace;
01280       }
01281    }
01282    if (s == &not_found) { /* look for more */
01283       if (!strcmp(var, "EPOCH")) {
01284          snprintf(workspace, workspacelen, "%u",(int)time(NULL));
01285          s = workspace;
01286       } else if (!strcmp(var, "SYSTEMNAME")) {
01287          s = ast_config_AST_SYSTEM_NAME;
01288       }
01289    }
01290    /* if not found, look into chanvars or global vars */
01291    for (i = 0; s == &not_found && i < (sizeof(places) / sizeof(places[0])); i++) {
01292       struct ast_var_t *variables;
01293       if (!places[i])
01294          continue;
01295       if (places[i] == &globals)
01296          ast_mutex_lock(&globalslock);
01297       AST_LIST_TRAVERSE(places[i], variables, entries) {
01298          if (strcasecmp(ast_var_name(variables), var)==0) {
01299             s = ast_var_value(variables);
01300             break;
01301          }
01302       }
01303       if (places[i] == &globals)
01304          ast_mutex_unlock(&globalslock);
01305    }
01306    if (s == &not_found || s == NULL)
01307       *ret = NULL;
01308    else {
01309       if (s != workspace)
01310          ast_copy_string(workspace, s, workspacelen);
01311       *ret = workspace;
01312       if (need_substring)
01313          *ret = substring(*ret, offset, length, workspace, workspacelen);
01314    }
01315 
01316    if (c)
01317       ast_channel_unlock(c);
01318 }

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

Referenced by pbx_load_module().

02775 {
02776    int oldval = autofallthrough;
02777    autofallthrough = newval;
02778    return oldval;
02779 }

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

Definition at line 1834 of file pbx.c.

References ast_copy_string(), ast_exten::data, and pbx_substitute_variables_helper().

Referenced by pbx_extension_helper().

01835 {
01836    memset(passdata, 0, datalen);
01837 
01838    /* No variables or expressions in e->data, so why scan it? */
01839    if (e->data && !strchr(e->data, '$') && !strstr(e->data,"${") && !strstr(e->data,"$[") && !strstr(e->data,"$(")) {
01840       ast_copy_string(passdata, e->data, datalen);
01841       return;
01842    }
01843 
01844    pbx_substitute_variables_helper(c, e->data, passdata, datalen - 1);
01845 }

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

References ast_channel_alloc(), ast_channel_free(), ast_copy_string(), ast_expr(), ast_func_read(), ast_log(), ast_strlen_zero(), len(), LOG_DEBUG, LOG_ERROR, LOG_WARNING, 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().

01630 {
01631    /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!!  */
01632    char *cp4;
01633    const char *tmp, *whereweare;
01634    int length, offset, offset2, isfunction;
01635    char *workspace = NULL;
01636    char *ltmp = NULL, *var = NULL;
01637    char *nextvar, *nextexp, *nextthing;
01638    char *vars, *vare;
01639    int pos, brackets, needsub, len;
01640 
01641    *cp2 = 0; /* just in case nothing ends up there */
01642    whereweare=tmp=cp1;
01643    while (!ast_strlen_zero(whereweare) && count) {
01644       /* Assume we're copying the whole remaining string */
01645       pos = strlen(whereweare);
01646       nextvar = NULL;
01647       nextexp = NULL;
01648       nextthing = strchr(whereweare, '$');
01649       if (nextthing) {
01650          switch(nextthing[1]) {
01651          case '{':
01652             nextvar = nextthing;
01653             pos = nextvar - whereweare;
01654             break;
01655          case '[':
01656             nextexp = nextthing;
01657             pos = nextexp - whereweare;
01658             break;
01659          default:
01660             pos = 1;
01661          }
01662       }
01663 
01664       if (pos) {
01665          /* Can't copy more than 'count' bytes */
01666          if (pos > count)
01667             pos = count;
01668 
01669          /* Copy that many bytes */
01670          memcpy(cp2, whereweare, pos);
01671 
01672          count -= pos;
01673          cp2 += pos;
01674          whereweare += pos;
01675          *cp2 = 0;
01676       }
01677 
01678       if (nextvar) {
01679          /* We have a variable.  Find the start and end, and determine
01680             if we are going to have to recursively call ourselves on the
01681             contents */
01682          vars = vare = nextvar + 2;
01683          brackets = 1;
01684          needsub = 0;
01685 
01686          /* Find the end of it */
01687          while (brackets && *vare) {
01688             if ((vare[0] == '$') && (vare[1] == '{')) {
01689                needsub++;
01690             } else if (vare[0] == '{') {
01691                brackets++;
01692             } else if (vare[0] == '}') {
01693                brackets--;
01694             } else if ((vare[0] == '$') && (vare[1] == '['))
01695                needsub++;
01696             vare++;
01697          }
01698          if (brackets)
01699             ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n");
01700          len = vare - vars - 1;
01701 
01702          /* Skip totally over variable string */
01703          whereweare += (len + 3);
01704 
01705          if (!var)
01706             var = alloca(VAR_BUF_SIZE);
01707 
01708          /* Store variable name (and truncate) */
01709          ast_copy_string(var, vars, len + 1);
01710 
01711          /* Substitute if necessary */
01712          if (needsub) {
01713             if (!ltmp)
01714                ltmp = alloca(VAR_BUF_SIZE);
01715 
01716             pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1);
01717             vars = ltmp;
01718          } else {
01719             vars = var;
01720          }
01721 
01722          if (!workspace)
01723             workspace = alloca(VAR_BUF_SIZE);
01724 
01725          workspace[0] = '\0';
01726 
01727          parse_variable_name(vars, &offset, &offset2, &isfunction);
01728          if (isfunction) {
01729             /* Evaluate function */
01730             if (c || !headp)
01731                cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
01732             else {
01733                struct varshead old;
01734                struct ast_channel *c = ast_channel_alloc(0, 0, "", "", "", "", "", 0, "Bogus/%p", vars);
01735                if (c) {
01736                   memcpy(&old, &c->varshead, sizeof(old));
01737                   memcpy(&c->varshead, headp, sizeof(c->varshead));
01738                   cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
01739                   /* Don't deallocate the varshead that was passed in */
01740                   memcpy(&c->varshead, &old, sizeof(c->varshead));
01741                   ast_channel_free(c);
01742                } else
01743                   ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution.  Function results may be blank.\n");
01744             }
01745 
01746             if (option_debug)
01747                ast_log(LOG_DEBUG, "Function result is '%s'\n", cp4 ? cp4 : "(null)");
01748          } else {
01749             /* Retrieve variable value */
01750             pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp);
01751          }
01752          if (cp4) {
01753             cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE);
01754 
01755             length = strlen(cp4);
01756             if (length > count)
01757                length = count;
01758             memcpy(cp2, cp4, length);
01759             count -= length;
01760             cp2 += length;
01761             *cp2 = 0;
01762          }
01763       } else if (nextexp) {
01764          /* We have an expression.  Find the start and end, and determine
01765             if we are going to have to recursively call ourselves on the
01766             contents */
01767          vars = vare = nextexp + 2;
01768          brackets = 1;
01769          needsub = 0;
01770 
01771          /* Find the end of it */
01772          while (brackets && *vare) {
01773             if ((vare[0] == '$') && (vare[1] == '[')) {
01774                needsub++;
01775                brackets++;
01776                vare++;
01777             } else if (vare[0] == '[') {
01778                brackets++;
01779             } else if (vare[0] == ']') {
01780                brackets--;
01781             } else if ((vare[0] == '$') && (vare[1] == '{')) {
01782                needsub++;
01783                vare++;
01784             }
01785             vare++;
01786          }
01787          if (brackets)
01788             ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n");
01789          len = vare - vars - 1;
01790 
01791          /* Skip totally over expression */
01792          whereweare += (len + 3);
01793 
01794          if (!var)
01795             var = alloca(VAR_BUF_SIZE);
01796 
01797          /* Store variable name (and truncate) */
01798          ast_copy_string(var, vars, len + 1);
01799 
01800          /* Substitute if necessary */
01801          if (needsub) {
01802             if (!ltmp)
01803                ltmp = alloca(VAR_BUF_SIZE);
01804 
01805             pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1);
01806             vars = ltmp;
01807          } else {
01808             vars = var;
01809          }
01810 
01811          length = ast_expr(vars, cp2, count);
01812 
01813          if (length) {
01814             if (option_debug)
01815                ast_log(LOG_DEBUG, "Expression result is '%s'\n", cp2);
01816             count -= length;
01817             cp2 += length;
01818             *cp2 = 0;
01819          }
01820       }
01821    }
01822 }

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

Definition at line 1829 of file pbx.c.

References pbx_substitute_variables_helper_full().

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

01830 {
01831    pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count);
01832 }

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

Definition at line 2704 of file pbx.c.

References __ast_pbx_run(), and decrease_call_count().

Referenced by ast_pbx_start().

02705 {
02706    /* Oh joyeous kernel, we're a new thread, with nothing to do but
02707       answer this channel and get it going.
02708    */
02709    /* NOTE:
02710       The launcher of this function _MUST_ increment 'countcalls'
02711       before invoking the function; it will be decremented when the
02712       PBX has finished running on the channel
02713     */
02714    struct ast_channel *c = data;
02715 
02716    __ast_pbx_run(c);
02717    decrease_call_count();
02718 
02719    pthread_exit(NULL);
02720 
02721    return NULL;
02722 }

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

helper function to print an extension

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

03606 {
03607    int prio = ast_get_extension_priority(e);
03608    if (prio == PRIORITY_HINT) {
03609       snprintf(buf, buflen, "hint: %s",
03610          ast_get_extension_app(e));
03611    } else {
03612       snprintf(buf, buflen, "%d. %s(%s)",
03613          prio, ast_get_extension_app(e),
03614          (!ast_strlen_zero(ast_get_extension_app_data(e)) ? (char *)ast_get_extension_app_data(e) : ""));
03615    }
03616 }

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

Definition at line 2397 of file pbx.c.

References ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_channel::exten, and ast_channel::priority.

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

02398 {
02399    ast_channel_lock(c);
02400    ast_copy_string(c->exten, exten, sizeof(c->exten));
02401    c->priority = pri;
02402    ast_channel_unlock(c);
02403 }

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 3619 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(), ast_exten::cidmatch, dialplan_counters::context_existence, el, dialplan_counters::extension_existence, LOG_NOTICE, LOG_WARNING, ast_exten::matchcid, print_ext(), dialplan_counters::total_context, dialplan_counters::total_exten, and dialplan_counters::total_prio.

Referenced by handle_show_dialplan().

03620 {
03621    struct ast_context *c = NULL;
03622    int res = 0, old_total_exten = dpc->total_exten;
03623 
03624    ast_rdlock_contexts();
03625 
03626    /* walk all contexts ... */
03627    while ( (c = ast_walk_contexts(c)) ) {
03628       struct ast_exten *e;
03629       struct ast_include *i;
03630       struct ast_ignorepat *ip;
03631       char buf[256], buf2[256];
03632       int context_info_printed = 0;
03633 
03634       if (context && strcmp(ast_get_context_name(c), context))
03635          continue;   /* skip this one, name doesn't match */
03636 
03637       dpc->context_existence = 1;
03638 
03639       ast_lock_context(c);
03640 
03641       /* are we looking for exten too? if yes, we print context
03642        * only if we find our extension.
03643        * Otherwise print context even if empty ?
03644        * XXX i am not sure how the rinclude is handled.
03645        * I think it ought to go inside.
03646        */
03647       if (!exten) {
03648          dpc->total_context++;
03649          ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
03650             ast_get_context_name(c), ast_get_context_registrar(c));
03651          context_info_printed = 1;
03652       }
03653 
03654       /* walk extensions ... */
03655       e = NULL;
03656       while ( (e = ast_walk_context_extensions(c, e)) ) {
03657          struct ast_exten *p;
03658 
03659          if (exten && !ast_extension_match(ast_get_extension_name(e), exten))
03660             continue;   /* skip, extension match failed */
03661 
03662          dpc->extension_existence = 1;
03663 
03664          /* may we print context info? */
03665          if (!context_info_printed) {
03666             dpc->total_context++;
03667             if (rinclude) { /* TODO Print more info about rinclude */
03668                ast_cli(fd, "[ Included context '%s' created by '%s' ]\n",
03669                   ast_get_context_name(c), ast_get_context_registrar(c));
03670             } else {
03671                ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
03672                   ast_get_context_name(c), ast_get_context_registrar(c));
03673             }
03674             context_info_printed = 1;
03675          }
03676          dpc->total_prio++;
03677 
03678          /* write extension name and first peer */
03679          if (e->matchcid)
03680             snprintf(buf, sizeof(buf), "'%s' (CID match '%s') => ", ast_get_extension_name(e), e->cidmatch);
03681          else
03682             snprintf(buf, sizeof(buf), "'%s' =>", ast_get_extension_name(e));
03683 
03684          print_ext(e, buf2, sizeof(buf2));
03685 
03686          ast_cli(fd, "  %-17s %-45s [%s]\n", buf, buf2,
03687             ast_get_extension_registrar(e));
03688 
03689          dpc->total_exten++;
03690          /* walk next extension peers */
03691          p = e;   /* skip the first one, we already got it */
03692          while ( (p = ast_walk_extension_priorities(e, p)) ) {
03693             const char *el = ast_get_extension_label(p);
03694             dpc->total_prio++;
03695             if (el)
03696                snprintf(buf, sizeof(buf), "   [%s]", el);
03697             else
03698                buf[0] = '\0';
03699             print_ext(p, buf2, sizeof(buf2));
03700 
03701             ast_cli(fd,"  %-17s %-45s [%s]\n", buf, buf2,
03702                ast_get_extension_registrar(p));
03703          }
03704       }
03705 
03706       /* walk included and write info ... */
03707       i = NULL;
03708       while ( (i = ast_walk_context_includes(c, i)) ) {
03709          snprintf(buf, sizeof(buf), "'%s'", ast_get_include_name(i));
03710          if (exten) {
03711             /* Check all includes for the requested extension */
03712             if (includecount >= AST_PBX_MAX_STACK) {
03713                ast_log(LOG_NOTICE, "Maximum include depth exceeded!\n");
03714             } else {
03715                int dupe=0;
03716                int x;
03717                for (x=0;x<includecount;x++) {
03718                   if (!strcasecmp(includes[x], ast_get_include_name(i))) {
03719                      dupe++;
03720                      break;
03721                   }
03722                }
03723                if (!dupe) {
03724                   includes[includecount] = ast_get_include_name(i);
03725                   show_dialplan_helper(fd, ast_get_include_name(i), exten, dpc, i, includecount + 1, includes);
03726                } else {
03727                   ast_log(LOG_WARNING, "Avoiding circular include of %s within %s\n", ast_get_include_name(i), context);
03728                }
03729             }
03730          } else {
03731             ast_cli(fd, "  Include =>        %-45s [%s]\n",
03732                buf, ast_get_include_registrar(i));
03733          }
03734       }
03735 
03736       /* walk ignore patterns and write info ... */
03737       ip = NULL;
03738       while ( (ip = ast_walk_context_ignorepats(c, ip)) ) {
03739          const char *ipname = ast_get_ignorepat_name(ip);
03740          char ignorepat[AST_MAX_EXTENSION];
03741          snprintf(buf, sizeof(buf), "'%s'", ipname);
03742          snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname);
03743          if (!exten || ast_extension_match(ignorepat, exten)) {
03744             ast_cli(fd, "  Ignore pattern => %-45s [%s]\n",
03745                buf, ast_get_ignorepat_registrar(ip));
03746          }
03747       }
03748       if (!rinclude) {
03749          struct ast_sw *sw = NULL;
03750          while ( (sw = ast_walk_context_switches(c, sw)) ) {
03751             snprintf(buf, sizeof(buf), "'%s/%s'",
03752                ast_get_switch_name(sw),
03753                ast_get_switch_data(sw));
03754             ast_cli(fd, "  Alt. Switch =>    %-45s [%s]\n",
03755                buf, ast_get_switch_registrar(sw));
03756          }
03757       }
03758 
03759       ast_unlock_context(c);
03760 
03761       /* if we print something in context, make an empty line */
03762       if (context_info_printed)
03763          ast_cli(fd, "\n");
03764    }
03765    ast_unlock_contexts();
03766 
03767    return (dpc->total_exten == old_total_exten) ? -1 : res;
03768 }

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

References ast_copy_string().

Referenced by pbx_retrieve_variable(), and pbx_substitute_variables_helper_full().

01167 {
01168    char *ret = workspace;
01169    int lr;  /* length of the input string after the copy */
01170 
01171    ast_copy_string(workspace, value, workspace_len); /* always make a copy */
01172 
01173    lr = strlen(ret); /* compute length after copy, so we never go out of the workspace */
01174 
01175    /* Quick check if no need to do anything */
01176    if (offset == 0 && length >= lr) /* take the whole string */
01177       return ret;
01178 
01179    if (offset < 0)   {  /* translate negative offset into positive ones */
01180       offset = lr + offset;
01181       if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */
01182          offset = 0;
01183    }
01184 
01185    /* too large offset result in empty string so we know what to return */
01186    if (offset >= lr)
01187       return ret + lr;  /* the final '\0' */
01188 
01189    ret += offset;    /* move to the start position */
01190    if (length >= 0 && length < lr - offset)  /* truncate if necessary */
01191       ret[length] = '\0';
01192    else if (length < 0) {
01193       if (lr > offset - length) /* After we remove from the front and from the rear, is there anything left? */
01194          ret[lr + length - offset] = '\0';
01195       else
01196          ret[0] = '\0';
01197    }
01198 
01199    return ret;
01200 }

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

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

05483 {
05484    int res;
05485    struct ast_frame *f;
05486    int waittime;
05487 
05488    if (ast_strlen_zero(data) || (sscanf(data, "%30d", &waittime) != 1) || (waittime < 0))
05489       waittime = -1;
05490    if (waittime > -1) {
05491       ast_safe_sleep(chan, waittime * 1000);
05492    } else do {
05493       res = ast_waitfor(chan, -1);
05494       if (res < 0)
05495          return;
05496       f = ast_read(chan);
05497       if (f)
05498          ast_frfree(f);
05499    } while(f);
05500 }


Variable Documentation

int autofallthrough = 1 [static]

Definition at line 247 of file pbx.c.

struct pbx_builtin builtins[] [static]

Declaration of builtin applications.

Referenced by load_pbx().

Initial value:
 {
   { "set", "global", NULL },
   handle_set_global_deprecated, NULL,
        NULL }

Definition at line 3929 of file pbx.c.

Initial value:
 {
   { "show", "application", NULL },
   handle_show_application_deprecated, NULL,
        NULL, complete_show_application }

Definition at line 3919 of file pbx.c.

Initial value:
 {
   { "show", "applications", NULL },
   handle_show_applications_deprecated, NULL,
   NULL, complete_show_applications_deprecated }

Definition at line 3889 of file pbx.c.

Initial value:
 {
   { "show", "dialplan", NULL },
   handle_show_dialplan, NULL,
        NULL, complete_show_dialplan_context }

Definition at line 3924 of file pbx.c.

Initial value:
 {
   { "show" , "function", NULL },
   handle_show_function_deprecated, NULL,
        NULL, complete_show_function }

Definition at line 3914 of file pbx.c.

Initial value:
 {
   { "show", "functions", NULL },
   handle_show_functions_deprecated, NULL,
        NULL }

Definition at line 3894 of file pbx.c.

Initial value:
 {
   { "show", "globals", NULL },
   handle_show_globals, NULL,
        NULL }

Definition at line 3909 of file pbx.c.

Initial value:
 {
   { "show", "hints", NULL },
   handle_show_hints, NULL,
        NULL }

Definition at line 3904 of file pbx.c.

Initial value:
 {
   { "show", "switches", NULL },
   handle_show_switches, NULL,
        NULL }

Definition at line 3899 of file pbx.c.

struct ast_context* contexts [static]

Definition at line 524 of file pbx.c.

int countcalls [static]

Definition at line 250 of file pbx.c.

char* days[] [static]

Definition at line 4328 of file pbx.c.

Referenced by ast_build_timing().

Referenced by ast_extension_state2str().

struct varshead globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE [static]

Definition at line 245 of file pbx.c.

struct ao2_container* hints [static]

Definition at line 543 of file pbx.c.

char* months[] [static]

Definition at line 4340 of file pbx.c.

Referenced by ast_build_timing().

struct ast_cli_entry pbx_cli[] [static]

Definition at line 3934 of file pbx.c.

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 3177 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 3165 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 3143 of file pbx.c.

char show_dialplan_help[] [static]
Initial value:
"Usage: dialplan show [exten@][context]\n"
"       Show dialplan\n"

Definition at line 3173 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 3169 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 3149 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 3161 of file pbx.c.

char show_hints_help[] [static]
Initial value:
"Usage: core show hints\n"
"       List registered hints\n"

Definition at line 3157 of file pbx.c.

char show_switches_help[] [static]
Initial value:
"Usage: core show switches\n"
"       List registered switches\n"

Definition at line 3153 of file pbx.c.

Definition at line 546 of file pbx.c.

int stateid = 1 [static]

Definition at line 535 of file pbx.c.

int totalcalls [static]

Definition at line 251 of file pbx.c.

Referenced by timing_read().


Generated on 8 Mar 2019 for Asterisk - the Open Source PBX by  doxygen 1.6.1