Thu Oct 1 13:10:09 2009

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"

Go to the source code of this file.

Data Structures

struct  acf_root
struct  app_tmp
struct  apps
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  hints
struct  pbx_builtin
 Declaration of builtin applications. More...
struct  pbx_find_info
struct  store_hint
struct  store_hints
struct  switches

Defines

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

Enumerations

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

Functions

static struct ast_context__ast_context_create (struct ast_context **extcontexts, const char *name, const char *registrar, int existsokay)
void __ast_context_destroy (struct ast_context *con, const char *registrar)
static int __ast_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority, int async)
static int __ast_pbx_run (struct ast_channel *c)
static int _extension_match_core (const char *pattern, const char *data, enum ext_match_t mode)
static int add_pri (struct ast_context *con, struct ast_exten *tmp, struct ast_exten *el, struct ast_exten *e, int replace)
 add the extension in the priority chain. returns 0 on success, -1 on failure
int ast_active_calls (void)
 Retrieve the number of active calls.
int ast_add_extension (const char *context, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar)
 Add and extension to an extension context.
int ast_add_extension2 (struct ast_context *con, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar)
 Add an extension to an extension context, this time with an ast_context *.
static int ast_add_hint (struct ast_exten *e)
 ast_add_hint: Add hint to hint list, check initial extension state
int ast_async_goto (struct ast_channel *chan, const char *context, const char *exten, int priority)
int ast_async_goto_by_name (const char *channame, const char *context, const char *exten, int priority)
int ast_async_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority)
int ast_build_timing (struct ast_timing *i, const char *info_in)
int ast_canmatch_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
 Looks for a valid matching extension.
static int ast_change_hint (struct ast_exten *oe, struct ast_exten *ne)
 ast_change_hint: Change hint for an extension
int ast_check_timing (const struct ast_timing *i)
int ast_context_add_ignorepat (const char *context, const char *value, const char *registrar)
 Add an ignorepat.
int ast_context_add_ignorepat2 (struct ast_context *con, const char *value, const char *registrar)
int ast_context_add_include (const char *context, const char *include, const char *registrar)
 Add a context include.
int ast_context_add_include2 (struct ast_context *con, const char *value, const char *registrar)
 Add a context include.
int ast_context_add_switch (const char *context, const char *sw, const char *data, int eval, const char *registrar)
 Add a switch.
int ast_context_add_switch2 (struct ast_context *con, const char *value, const char *data, int eval, const char *registrar)
 Adds a switch (first param is a ast_context).
ast_contextast_context_create (struct ast_context **extcontexts, const char *name, const char *registrar)
 Register a new context.
void ast_context_destroy (struct ast_context *con, const char *registrar)
 Destroy a context (matches the specified context (or ANY context if NULL).
ast_contextast_context_find (const char *name)
 Find a context.
ast_contextast_context_find_or_create (struct ast_context **extcontexts, const char *name, const char *registrar)
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.
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)
 Uses hint and devicestate callback to get the state of an extension.
static int ast_extension_state2 (struct ast_exten *e)
 ast_extensions_state2: Check state of extension by using hints
const char * ast_extension_state2str (int extension_state)
 Return string representation of the state of an extension.
int ast_extension_state_add (const char *context, const char *exten, ast_state_cb_type callback, void *data)
 Registers a state change callback.
int ast_extension_state_del (int id, ast_state_cb_type callback)
 Deletes a registered state change callback by ID.
int ast_findlabel_extension (struct ast_channel *c, const char *context, const char *exten, const char *label, const char *callerid)
 Find the priority of an extension that has the specified label.
int ast_findlabel_extension2 (struct ast_channel *c, struct ast_context *con, const char *exten, const char *label, const char *callerid)
 Find the priority of an extension that has the specified label.
int ast_func_read (struct ast_channel *chan, char *function, char *workspace, size_t len)
 executes a read operation on a function
int ast_func_write (struct ast_channel *chan, char *function, const char *value)
 executes a write operation on a function
const char * ast_get_context_name (struct ast_context *con)
const char * ast_get_context_registrar (struct ast_context *c)
const char * ast_get_extension_app (struct ast_exten *e)
void * ast_get_extension_app_data (struct ast_exten *e)
const char * ast_get_extension_cidmatch (struct ast_exten *e)
ast_contextast_get_extension_context (struct ast_exten *exten)
const char * ast_get_extension_label (struct ast_exten *exten)
int ast_get_extension_matchcid (struct ast_exten *e)
const char * ast_get_extension_name (struct ast_exten *exten)
int ast_get_extension_priority (struct ast_exten *exten)
const char * ast_get_extension_registrar (struct ast_exten *e)
int ast_get_hint (char *hint, int hintsize, char *name, int namesize, struct ast_channel *c, const char *context, const char *exten)
 If an extension exists, return non-zero.
const char * ast_get_ignorepat_name (struct ast_ignorepat *ip)
const char * ast_get_ignorepat_registrar (struct ast_ignorepat *ip)
const char * ast_get_include_name (struct ast_include *inc)
const char * ast_get_include_registrar (struct ast_include *i)
const char * ast_get_switch_data (struct ast_sw *sw)
const char * ast_get_switch_name (struct ast_sw *sw)
const char * ast_get_switch_registrar (struct ast_sw *sw)
int ast_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority)
static struct ast_extenast_hint_extension (struct ast_channel *c, const char *context, const char *exten)
 ast_hint_extension: Find hint for given extension in context
void ast_hint_state_changed (const char *device)
int ast_ignore_pattern (const char *context, const char *pattern)
 Checks to see if a number should be ignored.
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.
int ast_parseable_goto (struct ast_channel *chan, const char *goto_string)
int ast_pbx_outgoing_app (const char *type, int format, void *data, int timeout, const char *app, const char *appdata, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel)
static int ast_pbx_outgoing_cdr_failed (void)
int ast_pbx_outgoing_exten (const char *type, int format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **channel)
enum ast_pbx_result ast_pbx_run (struct ast_channel *c)
 Execute the PBX in the current thread.
static void * ast_pbx_run_app (void *data)
 run the application and free the descriptor once done
enum ast_pbx_result ast_pbx_start (struct ast_channel *c)
 Create a new thread and start the PBX.
int ast_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)
 Register an application.
int ast_register_switch (struct ast_switch *sw)
 Register an alternative dialplan switch.
static int ast_remove_hint (struct ast_exten *e)
 ast_remove_hint: Remove hint from extension
int ast_spawn_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
 Launch a new extension (i.e. new stack).
int ast_unlock_context (struct ast_context *con)
int ast_unlock_contexts ()
 Unlocks contexts.
int ast_unregister_application (const char *app)
 Unregister an application.
void ast_unregister_switch (struct ast_switch *sw)
 Unregister an alternative switch.
ast_extenast_walk_context_extensions (struct ast_context *con, struct ast_exten *exten)
ast_ignorepatast_walk_context_ignorepats (struct ast_context *con, struct ast_ignorepat *ip)
ast_includeast_walk_context_includes (struct ast_context *con, struct ast_include *inc)
ast_swast_walk_context_switches (struct ast_context *con, struct ast_sw *sw)
ast_contextast_walk_contexts (struct ast_context *con)
ast_extenast_walk_extension_priorities (struct ast_exten *exten, struct ast_exten *priority)
int ast_wrlock_contexts (void)
static void * async_wait (void *data)
static int collect_digits (struct ast_channel *c, int waittime, char *buf, int buflen, int pos)
 collect digits from the channel into the buffer, return -1 on error, 0 on timeout or done.
static char * complete_show_application (const char *line, const char *word, int pos, int state)
static char * complete_show_applications (const char *line, const char *word, int pos, int state)
static char * complete_show_applications_deprecated (const char *line, const char *word, int pos, int state)
static char * complete_show_dialplan_context (const char *line, const char *word, int pos, int state)
static char * complete_show_function (const char *line, const char *word, int pos, int state)
static void decrease_call_count (void)
static void destroy_exten (struct ast_exten *e)
static int ext_cmp (const char *a, const char *b)
 the full routine to compare extensions in rules.
static int ext_cmp1 (const char **p)
 helper functions to sort extensions and patterns in the desired way, so that more specific patterns appear first.
static int ext_strncpy (char *dst, const char *src, int len)
 copy a string skipping whitespace
static int extension_match_core (const char *pattern, const char *data, enum ext_match_t mode)
static struct ast_contextfind_context_locked (const char *context)
static char * func_args (char *function)
 return a pointer to the arguments of the function, and terminates the function name with '\0'
static unsigned get_range (char *src, int max, char *const names[], const char *msg)
 helper function to return a range up to max (7, 12, 31 respectively). names, if supplied, is an array of names that should be mapped to numbers.
static void get_timerange (struct ast_timing *i, char *times)
 store a bitmask of valid times, one bit each 2 minute
static int handle_set_global (int fd, int argc, char *argv[])
static int handle_set_global_deprecated (int fd, int argc, char *argv[])
 CLI support for setting global variables.
static int handle_show_application (int fd, int argc, char *argv[])
static int handle_show_application_deprecated (int fd, int argc, char *argv[])
static int handle_show_applications (int fd, int argc, char *argv[])
static int handle_show_applications_deprecated (int fd, int argc, char *argv[])
static int handle_show_dialplan (int fd, int argc, char *argv[])
static int handle_show_function (int fd, int argc, char *argv[])
static int handle_show_function_deprecated (int fd, int argc, char *argv[])
static int handle_show_functions (int fd, int argc, char *argv[])
static int handle_show_functions_deprecated (int fd, int argc, char *argv[])
static int handle_show_globals (int fd, int argc, char *argv[])
 CLI support for listing global variables in a parseable way.
static int handle_show_hints (int fd, int argc, char *argv[])
 handle_show_hints: CLI support for listing registered dial plan hints
static int handle_show_switches (int fd, int argc, char *argv[])
 handle_show_switches: CLI support for listing registered dial plan switches
static int include_valid (struct ast_include *i)
static int increase_call_count (const struct ast_channel *c)
int load_pbx (void)
static int lookup_name (const char *s, char *const names[], int max)
 Helper for get_range. return the index of the matching entry, starting from 1. If names is not supplied, try numeric values.
static int matchcid (const char *cidpattern, const char *callerid)
static int parse_variable_name (char *var, int *offset, int *length, int *isfunc)
 extract offset:length from variable name. Returns 1 if there is a offset:length part, which is trimmed off (values go into variables)
static int pbx_builtin_answer (struct ast_channel *, void *)
static int pbx_builtin_background (struct ast_channel *, void *)
static int pbx_builtin_busy (struct ast_channel *, void *)
void pbx_builtin_clear_globals (void)
static int pbx_builtin_congestion (struct ast_channel *, void *)
static int pbx_builtin_execiftime (struct ast_channel *, void *)
const char * pbx_builtin_getvar_helper (struct ast_channel *chan, const char *name)
static int pbx_builtin_goto (struct ast_channel *, void *)
static int pbx_builtin_gotoif (struct ast_channel *, void *)
static int pbx_builtin_gotoiftime (struct ast_channel *, void *)
static int pbx_builtin_hangup (struct ast_channel *, void *)
static int pbx_builtin_importvar (struct ast_channel *, void *)
static int pbx_builtin_noop (struct ast_channel *, void *)
static int pbx_builtin_progress (struct ast_channel *, void *)
void pbx_builtin_pushvar_helper (struct ast_channel *chan, const char *name, const char *value)
static int pbx_builtin_resetcdr (struct ast_channel *, void *)
static int pbx_builtin_ringing (struct ast_channel *, void *)
static int pbx_builtin_saycharacters (struct ast_channel *, void *)
static int pbx_builtin_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)
ast_apppbx_findapp (const char *app)
 Look up an application.
static struct ast_switchpbx_findswitch (const char *sw)
void pbx_retrieve_variable (struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp)
 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 switch_data_init (void)
static void wait_for_hangup (struct ast_channel *chan, void *data)

Variables

static int autofallthrough = 1
static struct ast_app_option background_opts [128] = { [ 's' ] = { .flag = (1 << 0) }, [ 'n' ] = { .flag = (1 << 1) }, [ 'm' ] = { .flag = (1 << 2) }, [ 'p' ] = { .flag = (1 << 3) },}
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 ast_rwlock_t conlock = PTHREAD_RWLOCK_INITIALIZER
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 ast_mutex_t globalslock = { PTHREAD_MUTEX_INITIALIZER , 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, PTHREAD_MUTEX_INITIALIZER }
static ast_mutex_t maxcalllock = { PTHREAD_MUTEX_INITIALIZER , 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, PTHREAD_MUTEX_INITIALIZER }
static char * months []
static struct ast_cli_entry pbx_cli []
static struct ast_app_option resetcdr_opts [128] = { [ 'w' ] = { .flag = (1 << 1) }, [ 'a' ] = { .flag = (1 << 2) }, [ 'v' ] = { .flag = (1 << 0) },}
static char set_global_help []
static char show_application_help []
static char show_applications_help []
static char show_dialplan_help []
static char show_function_help []
static char show_functions_help []
static char show_globals_help []
static char show_hints_help []
static char show_switches_help []
ast_state_cbstatecbs
static int stateid = 1
static struct ast_threadstorage switch_data = { .once = PTHREAD_ONCE_INIT, .key_init = switch_data_init , }
static int totalcalls
static struct ast_app_option waitexten_opts [128] = { [ 'm' ] = { .flag = (1 << 0) , .arg_index = 0 + 1 },}


Detailed Description

Core PBX routines.

Author:
Mark Spencer <markster@digium.com>

Definition in file pbx.c.


Define Documentation

#define AST_PBX_MAX_STACK   128

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

Definition at line 571 of file pbx.c.

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

#define BACKGROUND_MATCHEXTEN   (1 << 2)

Definition at line 90 of file pbx.c.

Referenced by pbx_builtin_background().

#define BACKGROUND_NOANSWER   (1 << 1)

Definition at line 89 of file pbx.c.

Referenced by pbx_builtin_background().

#define BACKGROUND_PLAYBACK   (1 << 3)

Definition at line 91 of file pbx.c.

Referenced by pbx_builtin_background().

#define BACKGROUND_SKIP   (1 << 0)

Definition at line 88 of file pbx.c.

Referenced by pbx_builtin_background().

#define EXT_DATA_SIZE   8192

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

Definition at line 77 of file pbx.c.

Referenced by pbx_extension_helper(), and realtime_exec().

#define SAY_STUBS

Definition at line 55 of file pbx.c.

#define STATUS_NO_CONTEXT   1

Definition at line 934 of file pbx.c.

Referenced by pbx_extension_helper(), and pbx_find_extension().

#define STATUS_NO_EXTENSION   2

Definition at line 935 of file pbx.c.

Referenced by pbx_extension_helper(), and pbx_find_extension().

#define STATUS_NO_LABEL   4

Definition at line 937 of file pbx.c.

Referenced by pbx_extension_helper(), and pbx_find_extension().

#define STATUS_NO_PRIORITY   3

Definition at line 936 of file pbx.c.

Referenced by pbx_extension_helper(), and pbx_find_extension().

#define STATUS_SUCCESS   5

Definition at line 938 of file pbx.c.

Referenced by pbx_find_extension().

#define SWITCH_DATA_LENGTH   256

Definition at line 80 of file pbx.c.

#define VAR_BUF_SIZE   4096

Definition at line 82 of file pbx.c.

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

#define VAR_HARDTRAN   3

Definition at line 86 of file pbx.c.

#define VAR_NORMAL   1

Definition at line 84 of file pbx.c.

#define VAR_SOFTTRAN   2

Definition at line 85 of file pbx.c.

#define WAITEXTEN_MOH   (1 << 0)

Definition at line 100 of file pbx.c.

Referenced by pbx_builtin_waitexten().


Enumeration Type Documentation

enum ext_match_t

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

Enumerator:
E_MATCHMORE 
E_CANMATCH 
E_MATCH 
E_MATCH_MASK 
E_SPAWN 
E_FINDLABEL 

Definition at line 777 of file pbx.c.

00777                  {
00778    E_MATCHMORE =  0x00, /* extension can match but only with more 'digits' */
00779    E_CANMATCH =   0x01, /* extension can match with or without more 'digits' */
00780    E_MATCH =   0x02, /* extension is an exact match */
00781    E_MATCH_MASK = 0x03, /* mask for the argument to extension_match_core() */
00782    E_SPAWN =   0x12, /* want to spawn an extension. Requires exact match */
00783    E_FINDLABEL =  0x22  /* returns the priority for a given label. Requires exact match */
00784 };


Function Documentation

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

Definition at line 3904 of file pbx.c.

References ast_log(), ast_rdlock_contexts(), ast_unlock_contexts(), contexts, local_contexts, LOG_WARNING, ast_context::name, name, and ast_context::next.

Referenced by ast_context_create(), and ast_context_find_or_create().

03905 {
03906    struct ast_context *tmp, **local_contexts;
03907    int length = sizeof(struct ast_context) + strlen(name) + 1;
03908 
03909    if (!extcontexts) {
03910       ast_rdlock_contexts();
03911       local_contexts = &contexts;
03912    } else
03913       local_contexts = extcontexts;
03914 
03915    for (tmp = *local_contexts; tmp; tmp = tmp->next) {
03916       if (!strcasecmp(tmp->name, name)) {
03917          if (!existsokay) {
03918             ast_log(LOG_WARNING, "Tried to register context '%s', already in use\n", name);
03919             tmp = NULL;
03920          }
03921          if (!extcontexts)
03922             ast_unlock_contexts();
03923          return tmp;
03924       }
03925    }
03926    
03927    if (!extcontexts)
03928       ast_unlock_contexts();
03929 
03930    if ((tmp = ast_calloc(1, length))) {
03931       ast_mutex_init(&tmp->lock);
03932       ast_mutex_init(&tmp->macrolock);
03933       strcpy(tmp->name, name);
03934       tmp->registrar = registrar;
03935       if (!extcontexts)
03936          ast_wrlock_contexts();
03937       tmp->next = *local_contexts;
03938       *local_contexts = tmp;
03939       if (!extcontexts)
03940          ast_unlock_contexts();
03941       if (option_debug)
03942          ast_log(LOG_DEBUG, "Registered context '%s'\n", tmp->name);
03943       if (option_verbose > 2)
03944          ast_verbose( VERBOSE_PREFIX_3 "Registered extension context '%s'\n", tmp->name);
03945    }
03946 
03947    return tmp;
03948 }

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

Definition at line 5333 of file pbx.c.

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

Referenced by ast_context_destroy(), and ast_merge_contexts_and_delete().

05334 {
05335    struct ast_context *tmp, *tmpl=NULL;
05336    struct ast_include *tmpi;
05337    struct ast_sw *sw;
05338    struct ast_exten *e, *el, *en;
05339    struct ast_ignorepat *ipi;
05340 
05341    for (tmp = contexts; tmp; ) {
05342       struct ast_context *next;  /* next starting point */
05343       for (; tmp; tmpl = tmp, tmp = tmp->next) {
05344          if (option_debug)
05345             ast_log(LOG_DEBUG, "check ctx %s %s\n", tmp->name, tmp->registrar);
05346          if ( (!registrar || !strcasecmp(registrar, tmp->registrar)) &&
05347               (!con || !strcasecmp(tmp->name, con->name)) )
05348             break;   /* found it */
05349       }
05350       if (!tmp)   /* not found, we are done */
05351          break;
05352       ast_mutex_lock(&tmp->lock);
05353       if (option_debug)
05354          ast_log(LOG_DEBUG, "delete ctx %s %s\n", tmp->name, tmp->registrar);
05355       next = tmp->next;
05356       if (tmpl)
05357          tmpl->next = next;
05358       else
05359          contexts = next;
05360       /* Okay, now we're safe to let it go -- in a sense, we were
05361          ready to let it go as soon as we locked it. */
05362       ast_mutex_unlock(&tmp->lock);
05363       for (tmpi = tmp->includes; tmpi; ) { /* Free includes */
05364          struct ast_include *tmpil = tmpi;
05365          tmpi = tmpi->next;
05366          free(tmpil);
05367       }
05368       for (ipi = tmp->ignorepats; ipi; ) { /* Free ignorepats */
05369          struct ast_ignorepat *ipl = ipi;
05370          ipi = ipi->next;
05371          free(ipl);
05372       }
05373       while ((sw = AST_LIST_REMOVE_HEAD(&tmp->alts, list)))
05374          free(sw);
05375       for (e = tmp->root; e;) {
05376          for (en = e->peer; en;) {
05377             el = en;
05378             en = en->peer;
05379             destroy_exten(el);
05380          }
05381          el = e;
05382          e = e->next;
05383          destroy_exten(el);
05384       }
05385       ast_mutex_destroy(&tmp->lock);
05386       free(tmp);
05387       /* if we have a specific match, we are done, otherwise continue */
05388       tmp = con ? NULL : next;
05389    }
05390 }

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

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

06482 {
06483    int (*goto_func)(struct ast_channel *chan, const char *context, const char *exten, int priority);
06484 
06485    if (!chan)
06486       return -2;
06487 
06488    if (context == NULL)
06489       context = chan->context;
06490    if (exten == NULL)
06491       exten = chan->exten;
06492 
06493    goto_func = (async) ? ast_async_goto : ast_explicit_goto;
06494    if (ast_exists_extension(chan, context, exten, priority, chan->cid.cid_num))
06495       return goto_func(chan, context, exten, priority);
06496    else
06497       return -3;
06498 }

static int __ast_pbx_run ( struct ast_channel c  )  [static]

Definition at line 2351 of file pbx.c.

References ast_channel::_softhangup, ast_calloc, ast_copy_string(), ast_exists_extension(), AST_FLAG_IN_AUTOLOOP, ast_log(), AST_PBX_KEEPALIVE, ast_set_flag, AST_SOFTHANGUP_ASYNCGOTO, AST_SOFTHANGUP_TIMEOUT, ast_spawn_extension(), ast_test_flag, ast_verbose(), ast_channel::cid, ast_callerid::cid_num, ast_channel::context, ast_pbx::dtimeout, ast_channel::exten, free, LOG_DEBUG, LOG_WARNING, ast_channel::name, option_debug, option_verbose, ast_channel::pbx, ast_channel::priority, ast_pbx::rtimeout, set_ext_pri(), and VERBOSE_PREFIX_2.

Referenced by ast_pbx_run(), and pbx_thread().

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

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

Definition at line 795 of file pbx.c.

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

Referenced by extension_match_core().

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

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

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

Referenced by ast_add_extension2().

04729 {
04730    struct ast_exten *ep;
04731 
04732    for (ep = NULL; e ; ep = e, e = e->peer) {
04733       if (e->priority >= tmp->priority)
04734          break;
04735    }
04736    if (!e) {   /* go at the end, and ep is surely set because the list is not empty */
04737       ep->peer = tmp;
04738       return 0;   /* success */
04739    }
04740    if (e->priority == tmp->priority) {
04741       /* Can't have something exactly the same.  Is this a
04742          replacement?  If so, replace, otherwise, bonk. */
04743       if (!replace) {
04744          ast_log(LOG_WARNING, "Unable to register extension '%s', priority %d in '%s', already in use\n", tmp->exten, tmp->priority, con->name);
04745          if (tmp->datad)
04746             tmp->datad(tmp->data);
04747          free(tmp);
04748          return -1;
04749       }
04750       /* we are replacing e, so copy the link fields and then update
04751        * whoever pointed to e to point to us
04752        */
04753       tmp->next = e->next; /* not meaningful if we are not first in the peer list */
04754       tmp->peer = e->peer; /* always meaningful */
04755       if (ep)        /* We're in the peer list, just insert ourselves */
04756          ep->peer = tmp;
04757       else if (el)      /* We're the first extension. Take over e's functions */
04758          el->next = tmp;
04759       else        /* We're the very first extension.  */
04760          con->root = tmp;
04761       if (tmp->priority == PRIORITY_HINT)
04762          ast_change_hint(e,tmp);
04763       /* Destroy the old one */
04764       if (e->datad)
04765          e->datad(e->data);
04766       free(e);
04767    } else { /* Slip ourselves in just before e */
04768       tmp->peer = e;
04769       tmp->next = e->next; /* extension chain, or NULL if e is not the first extension */
04770       if (ep)        /* Easy enough, we're just in the peer list */
04771          ep->peer = tmp;
04772       else {         /* we are the first in some peer list, so link in the ext list */
04773          if (el)
04774             el->next = tmp;   /* in the middle... */
04775          else
04776             con->root = tmp; /* ... or at the head */
04777          e->next = NULL;   /* e is no more at the head, so e->next must be reset */
04778       }
04779       /* And immediately return success. */
04780       if (tmp->priority == PRIORITY_HINT)
04781           ast_add_hint(tmp);
04782    }
04783    return 0;
04784 }

int ast_active_calls ( void   ) 

Retrieve the number of active calls.

Definition at line 2675 of file pbx.c.

References countcalls.

Referenced by handle_chanlist(), and handle_chanlist_deprecated().

02676 {
02677    return countcalls;
02678 }

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

04599 {
04600    int ret = -1;
04601    struct ast_context *c = find_context_locked(context);
04602 
04603    if (c) {
04604       ret = ast_add_extension2(c, replace, extension, priority, label, callerid,
04605          application, data, datad, registrar);
04606       ast_unlock_contexts();
04607    }
04608    return ret;
04609 }

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

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

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

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

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

Definition at line 4811 of file pbx.c.

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

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

04815 {
04816    /*
04817     * Sort extensions (or patterns) according to the rules indicated above.
04818     * These are implemented by the function ext_cmp()).
04819     * All priorities for the same ext/pattern/cid are kept in a list,
04820     * using the 'peer' field  as a link field..
04821     */
04822    struct ast_exten *tmp, *e, *el = NULL;
04823    int res;
04824    int length;
04825    char *p;
04826    char expand_buf[VAR_BUF_SIZE] = { 0, };
04827 
04828    /* if we are adding a hint, and there are global variables, and the hint
04829       contains variable references, then expand them
04830    */
04831    ast_mutex_lock(&globalslock);
04832    if (priority == PRIORITY_HINT && AST_LIST_FIRST(&globals) && strstr(application, "${")) {
04833       pbx_substitute_variables_varshead(&globals, application, expand_buf, sizeof(expand_buf));
04834       application = expand_buf;
04835    }
04836    ast_mutex_unlock(&globalslock);
04837 
04838    length = sizeof(struct ast_exten);
04839    length += strlen(extension) + 1;
04840    length += strlen(application) + 1;
04841    if (label)
04842       length += strlen(label) + 1;
04843    if (callerid)
04844       length += strlen(callerid) + 1;
04845    else
04846       length ++;  /* just the '\0' */
04847 
04848    /* Be optimistic:  Build the extension structure first */
04849    if (!(tmp = ast_calloc(1, length)))
04850       return -1;
04851 
04852    /* use p as dst in assignments, as the fields are const char * */
04853    p = tmp->stuff;
04854    if (label) {
04855       tmp->label = p;
04856       strcpy(p, label);
04857       p += strlen(label) + 1;
04858    }
04859    tmp->exten = p;
04860    p += ext_strncpy(p, extension, strlen(extension) + 1) + 1;
04861    tmp->priority = priority;
04862    tmp->cidmatch = p;   /* but use p for assignments below */
04863    if (callerid) {
04864       p += ext_strncpy(p, callerid, strlen(callerid) + 1) + 1;
04865       tmp->matchcid = 1;
04866    } else {
04867       *p++ = '\0';
04868       tmp->matchcid = 0;
04869    }
04870    tmp->app = p;
04871    strcpy(p, application);
04872    tmp->parent = con;
04873    tmp->data = data;
04874    tmp->datad = datad;
04875    tmp->registrar = registrar;
04876 
04877    ast_mutex_lock(&con->lock);
04878    res = 0; /* some compilers will think it is uninitialized otherwise */
04879    for (e = con->root; e; el = e, e = e->next) {   /* scan the extension list */
04880       res = ext_cmp(e->exten, tmp->exten);
04881       if (res == 0) { /* extension match, now look at cidmatch */
04882          if (!e->matchcid && !tmp->matchcid)
04883             res = 0;
04884          else if (tmp->matchcid && !e->matchcid)
04885             res = 1;
04886          else if (e->matchcid && !tmp->matchcid)
04887             res = -1;
04888          else
04889             res = strcasecmp(e->cidmatch, tmp->cidmatch);
04890       }
04891       if (res >= 0)
04892          break;
04893    }
04894    if (e && res == 0) { /* exact match, insert in the pri chain */
04895       res = add_pri(con, tmp, el, e, replace);
04896       ast_mutex_unlock(&con->lock);
04897       if (res < 0) {
04898          errno = EEXIST;   /* XXX do we care ? */
04899          return 0; /* XXX should we return -1 maybe ? */
04900       }
04901    } else {
04902       /*
04903        * not an exact match, this is the first entry with this pattern,
04904        * so insert in the main list right before 'e' (if any)
04905        */
04906       tmp->next = e;
04907       if (el)
04908          el->next = tmp;
04909       else
04910          con->root = tmp;
04911       ast_mutex_unlock(&con->lock);
04912       if (tmp->priority == PRIORITY_HINT)
04913          ast_add_hint(tmp);
04914    }
04915    if (option_debug) {
04916       if (tmp->matchcid) {
04917          if (option_debug)
04918             ast_log(LOG_DEBUG, "Added extension '%s' priority %d (CID match '%s') to %s\n",
04919                tmp->exten, tmp->priority, tmp->cidmatch, con->name);
04920       } else {
04921          if (option_debug)
04922             ast_log(LOG_DEBUG, "Added extension '%s' priority %d to %s\n",
04923                tmp->exten, tmp->priority, con->name);
04924       }
04925    }
04926    if (option_verbose > 2) {
04927       if (tmp->matchcid) {
04928          ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d (CID match '%s')to %s\n",
04929             tmp->exten, tmp->priority, tmp->cidmatch, con->name);
04930       } else {
04931          ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d to %s\n",
04932             tmp->exten, tmp->priority, con->name);
04933       }
04934    }
04935    return 0;
04936 }

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

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

Referenced by ast_add_extension2().

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

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

Definition at line 4634 of file pbx.c.

References ast_channel::_state, ast_channel::accountcode, 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::name, 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_dtmfup(), handle_request_bye(), handle_request_refer(), process_ast_dsp(), and socket_process().

04635 {
04636    int res = 0;
04637 
04638    ast_channel_lock(chan);
04639 
04640    if (chan->pbx) { /* This channel is currently in the PBX */
04641       ast_explicit_goto(chan, context, exten, priority);
04642       ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO);
04643    } else {
04644       /* In order to do it when the channel doesn't really exist within
04645          the PBX, we have to make a new channel, masquerade, and start the PBX
04646          at the new location */
04647       struct ast_channel *tmpchan = ast_channel_alloc(0, chan->_state, 0, 0, chan->accountcode, chan->exten, chan->context, chan->amaflags, "AsyncGoto/%s", chan->name);
04648       if (!tmpchan) {
04649          res = -1;
04650       } else {
04651          if (chan->cdr) {
04652             ast_cdr_discard(tmpchan->cdr);
04653             tmpchan->cdr = ast_cdr_dup(chan->cdr);  /* share the love */
04654          }
04655          /* Make formats okay */
04656          tmpchan->readformat = chan->readformat;
04657          tmpchan->writeformat = chan->writeformat;
04658          /* Setup proper location */
04659          ast_explicit_goto(tmpchan,
04660             S_OR(context, chan->context), S_OR(exten, chan->exten), priority);
04661 
04662          /* Masquerade into temp channel */
04663          if (ast_channel_masquerade(tmpchan, chan)) {
04664             /* Failed to set up the masquerade.  It's probably chan_local
04665              * in the middle of optimizing itself out.  Sad. :( */
04666             ast_hangup(tmpchan);
04667             tmpchan = NULL;
04668             res = -1;
04669          } else {
04670             /* Grab the locks and get going */
04671             ast_channel_lock(tmpchan);
04672             ast_do_masquerade(tmpchan);
04673             ast_channel_unlock(tmpchan);
04674             /* Start the PBX going on our stolen channel */
04675             if (ast_pbx_start(tmpchan)) {
04676                ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name);
04677                ast_hangup(tmpchan);
04678                res = -1;
04679             }
04680          }
04681       }
04682    }
04683    ast_channel_unlock(chan);
04684    return res;
04685 }

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

Definition at line 4687 of file pbx.c.

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

04688 {
04689    struct ast_channel *chan;
04690    int res = -1;
04691 
04692    chan = ast_get_channel_by_name_locked(channame);
04693    if (chan) {
04694       res = ast_async_goto(chan, context, exten, priority);
04695       ast_channel_unlock(chan);
04696    }
04697    return res;
04698 }

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

References __ast_goto_if_exists().

Referenced by asyncgoto_exec().

06506 {
06507    return __ast_goto_if_exists(chan, context, exten, priority, 1);
06508 }

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

Definition at line 4274 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, and months.

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

04275 {
04276    char info_save[256];
04277    char *info;
04278 
04279    /* Check for empty just in case */
04280    if (ast_strlen_zero(info_in))
04281       return 0;
04282    /* make a copy just in case we were passed a static string */
04283    ast_copy_string(info_save, info_in, sizeof(info_save));
04284    info = info_save;
04285    /* Assume everything except time */
04286    i->monthmask = 0xfff;   /* 12 bits */
04287    i->daymask = 0x7fffffffU; /* 31 bits */
04288    i->dowmask = 0x7f; /* 7 bits */
04289    /* on each call, use strsep() to move info to the next argument */
04290    get_timerange(i, strsep(&info, "|"));
04291    if (info)
04292       i->dowmask = get_range(strsep(&info, "|"), 7, days, "day of week");
04293    if (info)
04294       i->daymask = get_range(strsep(&info, "|"), 31, NULL, "day");
04295    if (info)
04296       i->monthmask = get_range(strsep(&info, "|"), 12, months, "month");
04297    return 1;
04298 }

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 2297 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(), phone_check_exception(), skinny_ss(), ss_thread(), and valid_exit().

02298 {
02299    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH);
02300 }

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

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

Referenced by add_pri().

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

int ast_check_timing ( const struct ast_timing i  ) 

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

04301 {
04302    struct tm tm;
04303    time_t t = time(NULL);
04304 
04305    ast_localtime(&t, &tm, NULL);
04306 
04307    /* If it's not the right month, return */
04308    if (!(i->monthmask & (1 << tm.tm_mon)))
04309       return 0;
04310 
04311    /* If it's not that time of the month.... */
04312    /* Warning, tm_mday has range 1..31! */
04313    if (!(i->daymask & (1 << (tm.tm_mday-1))))
04314       return 0;
04315 
04316    /* If it's not the right day of the week */
04317    if (!(i->dowmask & (1 << tm.tm_wday)))
04318       return 0;
04319 
04320    /* Sanity check the hour just to be safe */
04321    if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) {
04322       ast_log(LOG_WARNING, "Insane time...\n");
04323       return 0;
04324    }
04325 
04326    /* Now the tough part, we calculate if it fits
04327       in the right time based on min/hour */
04328    if (!(i->minmask[tm.tm_hour] & (1 << (tm.tm_min / 2))))
04329       return 0;
04330 
04331    /* If we got this far, then we're good */
04332    return 1;
04333 }

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

04528 {
04529    int ret = -1;
04530    struct ast_context *c = find_context_locked(context);
04531 
04532    if (c) {
04533       ret = ast_context_add_ignorepat2(c, value, registrar);
04534       ast_unlock_contexts();
04535    }
04536    return ret;
04537 }

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

Definition at line 4539 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_context_add_ignorepat(), and pbx_load_config().

04540 {
04541    struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL;
04542    int length;
04543    char *pattern;
04544    length = sizeof(struct ast_ignorepat);
04545    length += strlen(value) + 1;
04546    if (!(ignorepat = ast_calloc(1, length)))
04547       return -1;
04548    /* The cast to char * is because we need to write the initial value.
04549     * The field is not supposed to be modified otherwise.  Also, gcc 4.2
04550     * sees the cast as dereferencing a type-punned pointer and warns about
04551     * it.  This is the workaround (we're telling gcc, yes, that's really
04552     * what we wanted to do).
04553     */
04554    pattern = (char *) ignorepat->pattern;
04555    strcpy(pattern, value);
04556    ignorepat->next = NULL;
04557    ignorepat->registrar = registrar;
04558    ast_mutex_lock(&con->lock);
04559    for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) {
04560       ignorepatl = ignorepatc;
04561       if (!strcasecmp(ignorepatc->pattern, value)) {
04562          /* Already there */
04563          ast_mutex_unlock(&con->lock);
04564          errno = EEXIST;
04565          return -1;
04566       }
04567    }
04568    if (ignorepatl)
04569       ignorepatl->next = ignorepat;
04570    else
04571       con->ignorepats = ignorepat;
04572    ast_mutex_unlock(&con->lock);
04573    return 0;
04574 
04575 }

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

04081 {
04082    int ret = -1;
04083    struct ast_context *c = find_context_locked(context);
04084 
04085    if (c) {
04086       ret = ast_context_add_include2(c, include, registrar);
04087       ast_unlock_contexts();
04088    }
04089    return ret;
04090 }

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 4342 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_context_add_include(), and pbx_load_config().

04344 {
04345    struct ast_include *new_include;
04346    char *c;
04347    struct ast_include *i, *il = NULL; /* include, include_last */
04348    int length;
04349    char *p;
04350 
04351    length = sizeof(struct ast_include);
04352    length += 2 * (strlen(value) + 1);
04353 
04354    /* allocate new include structure ... */
04355    if (!(new_include = ast_calloc(1, length)))
04356       return -1;
04357    /* Fill in this structure. Use 'p' for assignments, as the fields
04358     * in the structure are 'const char *'
04359     */
04360    p = new_include->stuff;
04361    new_include->name = p;
04362    strcpy(p, value);
04363    p += strlen(value) + 1;
04364    new_include->rname = p;
04365    strcpy(p, value);
04366    /* Strip off timing info, and process if it is there */
04367    if ( (c = strchr(p, '|')) ) {
04368       *c++ = '\0';
04369            new_include->hastime = ast_build_timing(&(new_include->timing), c);
04370    }
04371    new_include->next      = NULL;
04372    new_include->registrar = registrar;
04373 
04374    ast_mutex_lock(&con->lock);
04375 
04376    /* ... go to last include and check if context is already included too... */
04377    for (i = con->includes; i; i = i->next) {
04378       if (!strcasecmp(i->name, new_include->name)) {
04379          free(new_include);
04380          ast_mutex_unlock(&con->lock);
04381          errno = EEXIST;
04382          return -1;
04383       }
04384       il = i;
04385    }
04386 
04387    /* ... include new context into context list, unlock, return */
04388    if (il)
04389       il->next = new_include;
04390    else
04391       con->includes = new_include;
04392    if (option_verbose > 2)
04393       ast_verbose(VERBOSE_PREFIX_3 "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con));
04394    ast_mutex_unlock(&con->lock);
04395 
04396    return 0;
04397 }

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

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

04405 {
04406    int ret = -1;
04407    struct ast_context *c = find_context_locked(context);
04408 
04409    if (c) { /* found, add switch to this context */
04410       ret = ast_context_add_switch2(c, sw, data, eval, registrar);
04411       ast_unlock_contexts();
04412    }
04413    return ret;
04414 }

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

References ast_context::alts, 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, store_hint::list, ast_context::lock, ast_sw::name, option_verbose, ast_sw::registrar, ast_sw::stuff, and VERBOSE_PREFIX_3.

Referenced by ast_context_add_switch(), and pbx_load_config().

04425 {
04426    struct ast_sw *new_sw;
04427    struct ast_sw *i;
04428    int length;
04429    char *p;
04430 
04431    length = sizeof(struct ast_sw);
04432    length += strlen(value) + 1;
04433    if (data)
04434       length += strlen(data);
04435    length++;
04436 
04437    /* allocate new sw structure ... */
04438    if (!(new_sw = ast_calloc(1, length)))
04439       return -1;
04440    /* ... fill in this structure ... */
04441    p = new_sw->stuff;
04442    new_sw->name = p;
04443    strcpy(new_sw->name, value);
04444    p += strlen(value) + 1;
04445    new_sw->data = p;
04446    if (data) {
04447       strcpy(new_sw->data, data);
04448       p += strlen(data) + 1;
04449    } else {
04450       strcpy(new_sw->data, "");
04451       p++;
04452    }
04453    new_sw->eval     = eval;
04454    new_sw->registrar = registrar;
04455 
04456    /* ... try to lock this context ... */
04457    ast_mutex_lock(&con->lock);
04458 
04459    /* ... go to last sw and check if context is already swd too... */
04460    AST_LIST_TRAVERSE(&con->alts, i, list) {
04461       if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) {
04462          free(new_sw);
04463          ast_mutex_unlock(&con->lock);
04464          errno = EEXIST;
04465          return -1;
04466       }
04467    }
04468 
04469    /* ... sw new context into context list, unlock, return */
04470    AST_LIST_INSERT_TAIL(&con->alts, new_sw, list);
04471 
04472    if (option_verbose > 2)
04473       ast_verbose(VERBOSE_PREFIX_3 "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con));
04474 
04475    ast_mutex_unlock(&con->lock);
04476 
04477    return 0;
04478 }

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

Register a new context.

Parameters:
extcontexts pointer to the ast_context structure pointer
name name of the new context
registrar registrar of the context
This will first search for a context with your name. If it exists already, it will not create a new one. If it does not exist, it will create a new one with the given name and registrar.

Returns:
NULL on failure, and an ast_context structure on success

Definition at line 3950 of file pbx.c.

References __ast_context_create().

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

03951 {
03952    return __ast_context_create(extcontexts, name, registrar, 0);
03953 }

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

05393 {
05394    ast_wrlock_contexts();
05395    __ast_context_destroy(con,registrar);
05396    ast_unlock_contexts();
05397 }

struct ast_context* ast_context_find ( const char *  name  ) 

Find a context.

Parameters:
name name of the context to find
Will search for the context with the given name.

Returns:
the ast_context on success, NULL on failure.

Definition at line 918 of file pbx.c.

References ast_rdlock_contexts(), ast_unlock_contexts(), ast_walk_contexts(), and ast_context::name.

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

00919 {
00920    struct ast_context *tmp = NULL;
00921 
00922    ast_rdlock_contexts();
00923 
00924    while ( (tmp = ast_walk_contexts(tmp)) ) {
00925       if (!name || !strcasecmp(name, tmp->name))
00926          break;
00927    }
00928 
00929    ast_unlock_contexts();
00930 
00931    return tmp;
00932 }

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

Definition at line 3955 of file pbx.c.

References __ast_context_create().

Referenced by pbx_load_config(), and pbx_load_users().

03956 {
03957    return __ast_context_create(extcontexts, name, registrar, 1);
03958 }

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

References ast_get_context_name(), ast_mutex_lock, ast_rdlock_contexts(), ast_unlock_contexts(), ast_walk_contexts(), and ast_context::macrolock.

Referenced by _macro_exec().

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

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

References ast_context_remove_extension_callerid().

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

02819 {
02820    return ast_context_remove_extension_callerid(context, extension, priority, NULL, 0, registrar);
02821 }

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

References ast_context_remove_extension_callerid2().

Referenced by do_parking_thread(), and park_exec().

02846 {
02847    return ast_context_remove_extension_callerid2(con, extension, priority, NULL, 0, registrar);
02848 }

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

02824 {
02825    int ret = -1; /* default error return */
02826    struct ast_context *c = find_context_locked(context);
02827 
02828    if (c) { /* ... remove extension ... */
02829       ret = ast_context_remove_extension_callerid2(c, extension, priority, callerid, matchcid, registrar);
02830       ast_unlock_contexts();
02831    }
02832    return ret;
02833 }

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

References ast_mutex_lock, ast_mutex_unlock, ast_exten::cidmatch, destroy_exten(), exten, ast_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().

02851 {
02852    struct ast_exten *exten, *prev_exten = NULL;
02853    struct ast_exten *peer;
02854    struct ast_exten *previous_peer = NULL;
02855    struct ast_exten *next_peer = NULL;
02856    int found = 0;
02857 
02858    ast_mutex_lock(&con->lock);
02859 
02860    /* scan the extension list to find first matching extension-registrar */
02861    for (exten = con->root; exten; prev_exten = exten, exten = exten->next) {
02862       if (!strcmp(exten->exten, extension) &&
02863          (!registrar || !strcmp(exten->registrar, registrar)))
02864          break;
02865    }
02866    if (!exten) {
02867       /* we can't find right extension */
02868       ast_mutex_unlock(&con->lock);
02869       return -1;
02870    }
02871 
02872    /* scan the priority list to remove extension with exten->priority == priority */
02873    for (peer = exten, next_peer = exten->peer ? exten->peer : exten->next;
02874          peer && !strcmp(peer->exten, extension);
02875          peer = next_peer, next_peer = next_peer ? (next_peer->peer ? next_peer->peer : next_peer->next) : NULL) {
02876       if ((priority == 0 || peer->priority == priority) &&
02877             (!callerid || !matchcid || (matchcid && !strcmp(peer->cidmatch, callerid))) &&
02878             (!registrar || !strcmp(peer->registrar, registrar) )) {
02879          found = 1;
02880 
02881          /* we are first priority extension? */
02882          if (!previous_peer) {
02883             /*
02884              * We are first in the priority chain, so must update the extension chain.
02885              * The next node is either the next priority or the next extension
02886              */
02887             struct ast_exten *next_node = peer->peer ? peer->peer : peer->next;
02888 
02889             if (!prev_exten) {   /* change the root... */
02890                con->root = next_node;
02891             } else {
02892                prev_exten->next = next_node; /* unlink */
02893             }
02894             if (peer->peer)   { /* update the new head of the pri list */
02895                peer->peer->next = peer->next;
02896             }
02897          } else { /* easy, we are not first priority in extension */
02898             previous_peer->peer = peer->peer;
02899          }
02900 
02901          /* now, free whole priority extension */
02902          destroy_exten(peer);
02903       } else {
02904          previous_peer = peer;
02905       }
02906    }
02907    ast_mutex_unlock(&con->lock);
02908    return found ? 0 : -1;
02909 }

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

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

04485 {
04486    int ret = -1;
04487    struct ast_context *c = find_context_locked(context);
04488 
04489    if (c) {
04490       ret = ast_context_remove_ignorepat2(c, ignorepat, registrar);
04491       ast_unlock_contexts();
04492    }
04493    return ret;
04494 }

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

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

04497 {
04498    struct ast_ignorepat *ip, *ipl = NULL;
04499 
04500    ast_mutex_lock(&con->lock);
04501 
04502    for (ip = con->ignorepats; ip; ip = ip->next) {
04503       if (!strcmp(ip->pattern, ignorepat) &&
04504          (!registrar || (registrar == ip->registrar))) {
04505          if (ipl) {
04506             ipl->next = ip->next;
04507             free(ip);
04508          } else {
04509             con->ignorepats = ip->next;
04510             free(ip);
04511          }
04512          ast_mutex_unlock(&con->lock);
04513          return 0;
04514       }
04515       ipl = ip;
04516    }
04517 
04518    ast_mutex_unlock(&con->lock);
04519    errno = EINVAL;
04520    return -1;
04521 }

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

02715 {
02716    int ret = -1;
02717    struct ast_context *c = find_context_locked(context);
02718 
02719    if (c) {
02720       /* found, remove include from this context ... */
02721       ret = ast_context_remove_include2(c, include, registrar);
02722       ast_unlock_contexts();
02723    }
02724    return ret;
02725 }

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

02736 {
02737    struct ast_include *i, *pi = NULL;
02738    int ret = -1;
02739 
02740    ast_mutex_lock(&con->lock);
02741 
02742    /* find our include */
02743    for (i = con->includes; i; pi = i, i = i->next) {
02744       if (!strcmp(i->name, include) &&
02745             (!registrar || !strcmp(i->registrar, registrar))) {
02746          /* remove from list */
02747          if (pi)
02748             pi->next = i->next;
02749          else
02750             con->includes = i->next;
02751          /* free include and return */
02752          free(i);
02753          ret = 0;
02754          break;
02755       }
02756    }
02757 
02758    ast_mutex_unlock(&con->lock);
02759    return ret;
02760 }

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

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

02768 {
02769    int ret = -1; /* default error return */
02770    struct ast_context *c = find_context_locked(context);
02771 
02772    if (c) {
02773       /* remove switch from this context ... */
02774       ret = ast_context_remove_switch2(c, sw, data, registrar);
02775       ast_unlock_contexts();
02776    }
02777    return ret;
02778 }

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

References ast_context::alts, 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_sw::list, ast_context::lock, ast_sw::name, and ast_sw::registrar.

Referenced by ast_context_remove_switch().

02789 {
02790    struct ast_sw *i;
02791    int ret = -1;
02792 
02793    ast_mutex_lock(&con->lock);
02794 
02795    /* walk switches */
02796    AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) {
02797       if (!strcmp(i->name, sw) && !strcmp(i->data, data) &&
02798          (!registrar || !strcmp(i->registrar, registrar))) {
02799          /* found, remove from list */
02800          AST_LIST_REMOVE_CURRENT(&con->alts, list);
02801          free(i); /* free switch and return */
02802          ret = 0;
02803          break;
02804       }
02805    }
02806    AST_LIST_TRAVERSE_SAFE_END
02807 
02808    ast_mutex_unlock(&con->lock);
02809 
02810    return ret;
02811 }

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

References ast_get_context_name(), ast_mutex_unlock, ast_rdlock_contexts(), ast_unlock_contexts(), ast_walk_contexts(), and ast_context::macrolock.

Referenced by _macro_exec().

02946 {
02947    struct ast_context *c = NULL;
02948    int ret = -1;
02949 
02950    ast_rdlock_contexts();
02951 
02952    while ((c = ast_walk_contexts(c))) {
02953       if (!strcmp(ast_get_context_name(c), context)) {
02954          ret = 0;
02955          break;
02956       }
02957    }
02958 
02959    ast_unlock_contexts();
02960 
02961    /* if we found context, unlock macrolock */
02962    if (ret == 0) 
02963       ret = ast_mutex_unlock(&c->macrolock);
02964 
02965    return ret;
02966 }

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

06463 {
06464    struct ast_include *inc = NULL;
06465    int res = 0;
06466 
06467    while ( (inc = ast_walk_context_includes(con, inc)) ) {
06468       if (ast_context_find(inc->rname))
06469          continue;
06470 
06471       res = -1;
06472       ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n",
06473          ast_get_context_name(con), inc->rname);
06474       break;
06475    }
06476 
06477    return res;
06478 }

struct ast_custom_function* ast_custom_function_find ( const char *  name  ) 

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

01481 {
01482    struct ast_custom_function *acf = NULL;
01483 
01484    AST_LIST_LOCK(&acf_root);
01485    AST_LIST_TRAVERSE(&acf_root, acf, acflist) {
01486       if (!strcmp(name, acf->name))
01487          break;
01488    }
01489    AST_LIST_UNLOCK(&acf_root);
01490 
01491    return acf;
01492 }

int ast_custom_function_register ( struct ast_custom_function acf  ) 

Reigster a custom function.

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

01517 {
01518    struct ast_custom_function *cur;
01519 
01520    if (!acf)
01521       return -1;
01522 
01523    AST_LIST_LOCK(&acf_root);
01524 
01525    if (ast_custom_function_find(acf->name)) {
01526       ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name);
01527       AST_LIST_UNLOCK(&acf_root);
01528       return -1;
01529    }
01530 
01531    /* Store in alphabetical order */
01532    AST_LIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) {
01533       if (strcasecmp(acf->name, cur->name) < 0) {
01534          AST_LIST_INSERT_BEFORE_CURRENT(&acf_root, acf, acflist);
01535          break;
01536       }
01537    }
01538    AST_LIST_TRAVERSE_SAFE_END
01539    if (!cur)
01540       AST_LIST_INSERT_TAIL(&acf_root, acf, acflist);
01541 
01542    AST_LIST_UNLOCK(&acf_root);
01543 
01544    if (option_verbose > 1)
01545       ast_verbose(VERBOSE_PREFIX_2 "Registered custom function %s\n", acf->name);
01546 
01547    return 0;
01548 }

int ast_custom_function_unregister ( struct ast_custom_function acf  ) 

Unregister a custom function.

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

01495 {
01496    struct ast_custom_function *cur;
01497 
01498    if (!acf)
01499       return -1;
01500 
01501    AST_LIST_LOCK(&acf_root);
01502    AST_LIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) {
01503       if (cur == acf) {
01504          AST_LIST_REMOVE_CURRENT(&acf_root, acflist);
01505          if (option_verbose > 1)
01506             ast_verbose(VERBOSE_PREFIX_2 "Unregistered custom function %s\n", acf->name);
01507          break;
01508       }
01509    }
01510    AST_LIST_TRAVERSE_SAFE_END
01511    AST_LIST_UNLOCK(&acf_root);
01512 
01513    return acf ? 0 : -1;
01514 }

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

01944 {
01945    switch (devstate) {
01946    case AST_DEVICE_ONHOLD:
01947       return AST_EXTENSION_ONHOLD;
01948    case AST_DEVICE_BUSY:
01949       return AST_EXTENSION_BUSY;
01950    case AST_DEVICE_UNAVAILABLE:
01951    case AST_DEVICE_UNKNOWN:
01952    case AST_DEVICE_INVALID:
01953       return AST_EXTENSION_UNAVAILABLE;
01954    case AST_DEVICE_RINGINUSE:
01955       return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING);
01956    case AST_DEVICE_RINGING:
01957       return AST_EXTENSION_RINGING;
01958    case AST_DEVICE_INUSE:
01959       return AST_EXTENSION_INUSE;
01960    case AST_DEVICE_NOT_INUSE:
01961       return AST_EXTENSION_NOT_INUSE;
01962    case AST_DEVICE_TOTAL: /* not a device state, included for completeness */
01963       break;
01964    }
01965 
01966    return AST_EXTENSION_NOT_INUSE;
01967 }

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 2282 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(), builtin_blindtransfer(), cb_events(), conf_run(), console_dial(), console_dial_deprecated(), console_transfer(), console_transfer_deprecated(), dahdi_handle_dtmfup(), disa_exec(), do_atxfer(), dp_lookup(), dundi_lookup_local(), get_also_info(), get_destination(), get_refer_info(), handle_link_data(), handle_link_phone_dtmf(), handle_stimulus_message(), leave_voicemail(), local_alloc(), local_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(), skinny_ss(), socket_process(), ss_thread(), and waitstream_core().

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

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 4611 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(), disa_exec(), do_atxfer(), and handle_setpriority().

04612 {
04613    if (!chan)
04614       return -1;
04615 
04616    ast_channel_lock(chan);
04617 
04618    if (!ast_strlen_zero(context))
04619       ast_copy_string(chan->context, context, sizeof(chan->context));
04620    if (!ast_strlen_zero(exten))
04621       ast_copy_string(chan->exten, exten, sizeof(chan->exten));
04622    if (priority > -1) {
04623       chan->priority = priority;
04624       /* see flag description in channel.h for explanation */
04625       if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP))
04626          chan->priority--;
04627    }
04628 
04629    ast_channel_unlock(chan);
04630 
04631    return 0;
04632 }

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

Definition at line 911 of file pbx.c.

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

Referenced by realtime_switch_common().

00912 {
00913    if (needmore != E_MATCHMORE && needmore != E_CANMATCH)
00914       ast_log(LOG_WARNING, "invalid argument %d\n", needmore);
00915    return extension_match_core(pattern, data, needmore);
00916 }

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

00907 {
00908    return extension_match_core(pattern, data, E_MATCH);
00909 }

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

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

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

Definition at line 2004 of file pbx.c.

References ast_extension_state2(), and ast_hint_extension().

Referenced by action_extensionstate(), and handle_request_subscribe().

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

static int ast_extension_state2 ( struct ast_exten e  )  [static]

ast_extensions_state2: Check state of extension by using hints

Definition at line 1970 of file pbx.c.

References ast_copy_string(), ast_device_state(), ast_devstate_aggregate_add(), ast_devstate_aggregate_init(), ast_devstate_aggregate_result(), ast_devstate_to_extenstate(), ast_get_extension_app(), and AST_MAX_EXTENSION.

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

01971 {
01972    char hint[AST_MAX_EXTENSION];
01973    char *cur, *rest;
01974    struct ast_devstate_aggregate agg;
01975 
01976    ast_devstate_aggregate_init(&agg);
01977 
01978    if (!e)
01979       return -1;
01980 
01981    ast_copy_string(hint, ast_get_extension_app(e), sizeof(hint));
01982 
01983    rest = hint;   /* One or more devices separated with a & character */
01984    while ( (cur = strsep(&rest, "&")) ) {
01985       int res = ast_device_state(cur);
01986       ast_devstate_aggregate_add(&agg, res);
01987    }
01988    return ast_devstate_to_extenstate(ast_devstate_aggregate_result(&agg));
01989 }

const char* ast_extension_state2str ( int  extension_state  ) 

Return string representation of the state of an extension.

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

Definition at line 1992 of file pbx.c.

References extension_states.

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

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

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

Registers a state change callback.

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

Return values:
-1 on failure
ID on success

Definition at line 2061 of file pbx.c.

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

Referenced by handle_request_subscribe(), and init_manager().

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

int ast_extension_state_del ( int  id,
ast_state_cb_type  callback 
)

Deletes a registered state change callback by ID.

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

Return values:
0 success
-1 failure

Definition at line 2136 of file pbx.c.

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

Referenced by __sip_destroy(), and handle_request_subscribe().

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

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

02288 {
02289    return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL);
02290 }

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

References E_FINDLABEL, and pbx_extension_helper().

Referenced by pbx_load_config().

02293 {
02294    return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL);
02295 }

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

01571 {
01572    char *args = func_args(function);
01573    struct ast_custom_function *acfptr = ast_custom_function_find(function);
01574 
01575    if (acfptr == NULL)
01576       ast_log(LOG_ERROR, "Function %s not registered\n", function);
01577    else if (!acfptr->read)
01578       ast_log(LOG_ERROR, "Function %s cannot be read\n", function);
01579    else
01580       return acfptr->read(chan, function, args, workspace, len);
01581    return -1;
01582 }

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

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

Referenced by pbx_builtin_pushvar_helper(), and pbx_builtin_setvar_helper().

01585 {
01586    char *args = func_args(function);
01587    struct ast_custom_function *acfptr = ast_custom_function_find(function);
01588 
01589    if (acfptr == NULL)
01590       ast_log(LOG_ERROR, "Function %s not registered\n", function);
01591    else if (!acfptr->write)
01592       ast_log(LOG_ERROR, "Function %s cannot be written to\n", function);
01593    else
01594       return acfptr->write(chan, function, args, value);
01595 
01596    return -1;
01597 }

const char* ast_get_context_name ( struct ast_context con  ) 

Definition at line 6319 of file pbx.c.

References ast_context::name.

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

06320 {
06321    return con ? con->name : NULL;
06322 }

const char* ast_get_context_registrar ( struct ast_context c  ) 

Definition at line 6357 of file pbx.c.

References ast_context::registrar.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06358 {
06359    return c ? c->registrar : NULL;
06360 }

const char* ast_get_extension_app ( struct ast_exten e  ) 

Definition at line 6387 of file pbx.c.

References ast_exten::app.

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

06388 {
06389    return e ? e->app : NULL;
06390 }

void* ast_get_extension_app_data ( struct ast_exten e  ) 

Definition at line 6392 of file pbx.c.

References ast_exten::data.

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

06393 {
06394    return e ? e->data : NULL;
06395 }

const char* ast_get_extension_cidmatch ( struct ast_exten e  ) 

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

06383 {
06384    return e ? e->cidmatch : NULL;
06385 }

struct ast_context* ast_get_extension_context ( struct ast_exten exten  ) 

Definition at line 6324 of file pbx.c.

References exten.

Referenced by handle_show_hints().

06325 {
06326    return exten ? exten->parent : NULL;
06327 }

const char* ast_get_extension_label ( struct ast_exten exten  ) 

Definition at line 6334 of file pbx.c.

References exten.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06335 {
06336    return exten ? exten->label : NULL;
06337 }

int ast_get_extension_matchcid ( struct ast_exten e  ) 

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

06378 {
06379    return e ? e->matchcid : 0;
06380 }

const char* ast_get_extension_name ( struct ast_exten exten  ) 

Definition at line 6329 of file pbx.c.

References exten.

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

06330 {
06331    return exten ? exten->exten : NULL;
06332 }

int ast_get_extension_priority ( struct ast_exten exten  ) 

Definition at line 6349 of file pbx.c.

References exten.

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

06350 {
06351    return exten ? exten->priority : -1;
06352 }

const char* ast_get_extension_registrar ( struct ast_exten e  ) 

Definition at line 6362 of file pbx.c.

References ast_exten::registrar.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06363 {
06364    return e ? e->registrar : NULL;
06365 }

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

If an extension exists, return non-zero.

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

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

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

const char* ast_get_ignorepat_name ( struct ast_ignorepat ip  ) 

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

06345 {
06346    return ip ? ip->pattern : NULL;
06347 }

const char* ast_get_ignorepat_registrar ( struct ast_ignorepat ip  ) 

Definition at line 6372 of file pbx.c.

References ast_ignorepat::registrar.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06373 {
06374    return ip ? ip->registrar : NULL;
06375 }

const char* ast_get_include_name ( struct ast_include inc  ) 

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

06340 {
06341    return inc ? inc->name : NULL;
06342 }

const char* ast_get_include_registrar ( struct ast_include i  ) 

Definition at line 6367 of file pbx.c.

References ast_include::registrar.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06368 {
06369    return i ? i->registrar : NULL;
06370 }

const char* ast_get_switch_data ( struct ast_sw sw  ) 

Definition at line 6402 of file pbx.c.

References ast_sw::data.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06403 {
06404    return sw ? sw->data : NULL;
06405 }

const char* ast_get_switch_name ( struct ast_sw sw  ) 

Definition at line 6397 of file pbx.c.

References ast_sw::name.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06398 {
06399    return sw ? sw->name : NULL;
06400 }

const char* ast_get_switch_registrar ( struct ast_sw sw  ) 

Definition at line 6407 of file pbx.c.

References ast_sw::registrar.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06408 {
06409    return sw ? sw->registrar : NULL;
06410 }

int ast_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 6500 of file pbx.c.

References __ast_goto_if_exists().

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

06501 {
06502    return __ast_goto_if_exists(chan, context, exten, priority, 0);
06503 }

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

ast_hint_extension: Find hint for given extension in context

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

01932 {
01933    struct ast_exten *e;
01934    struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */
01935 
01936    ast_rdlock_contexts();
01937    e = pbx_find_extension(c, NULL, &q, context, exten, PRIORITY_HINT, NULL, "", E_MATCH);
01938    ast_unlock_contexts();
01939 
01940    return e;
01941 }

void ast_hint_state_changed ( const char *  device  ) 

Definition at line 2015 of file pbx.c.

References ast_copy_string(), ast_extension_state2(), ast_get_extension_app(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, AST_MAX_EXTENSION, ast_rdlock_contexts(), ast_unlock_contexts(), ast_state_cb::callback, ast_hint::callbacks, ast_state_cb::data, ast_hint::exten, ast_exten::exten, ast_hint::laststate, ast_sw::list, ast_context::name, ast_state_cb::next, ast_exten::parent, parse(), and statecbs.

Referenced by do_state_change().

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

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

04578 {
04579    struct ast_context *con = ast_context_find(context);
04580    if (con) {
04581       struct ast_ignorepat *pat;
04582       for (pat = con->ignorepats; pat; pat = pat->next) {
04583          if (ast_extension_match(pat->pattern, pattern))
04584             return 1;
04585       }
04586    }
04587 
04588    return 0;
04589 }

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

06307 {
06308    return ast_mutex_lock(&con->lock);
06309 }

int ast_lock_contexts ( void   ) 

Locks the context list.

Return values:
0 on success
-1 on error

Definition at line 6283 of file pbx.c.

References ast_rwlock_wrlock, and conlock.

Referenced by find_matching_endwhile().

06284 {
06285    return ast_rwlock_wrlock(&conlock);
06286 }

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

References E_MATCHMORE, and pbx_extension_helper().

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

02303 {
02304    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE);
02305 }

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

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

Referenced by pbx_load_module().

03974 {
03975    struct ast_context *tmp, *lasttmp = NULL;
03976    struct store_hints store = AST_LIST_HEAD_INIT_VALUE;
03977    struct store_hint *this;
03978    struct ast_hint *hint;
03979    struct ast_exten *exten;
03980    int length;
03981    struct ast_state_cb *thiscb, *prevcb;
03982 
03983    /* it is very important that this function hold the hint list lock _and_ the conlock
03984       during its operation; not only do we need to ensure that the list of contexts
03985       and extensions does not change, but also that no hint callbacks (watchers) are
03986       added or removed during the merge/delete process
03987 
03988       in addition, the locks _must_ be taken in this order, because there are already
03989       other code paths that use this order
03990    */
03991    ast_wrlock_contexts();
03992    AST_LIST_LOCK(&hints);
03993 
03994    /* preserve all watchers for hints associated with this registrar */
03995    AST_LIST_TRAVERSE(&hints, hint, list) {
03996       if (hint->callbacks && !strcmp(registrar, hint->exten->parent->registrar)) {
03997          length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2 + sizeof(*this);
03998          if (!(this = ast_calloc(1, length)))
03999             continue;
04000          this->callbacks = hint->callbacks;
04001          hint->callbacks = NULL;
04002          this->laststate = hint->laststate;
04003          this->context = this->data;
04004          strcpy(this->data, hint->exten->parent->name);
04005          this->exten = this->data + strlen(this->context) + 1;
04006          strcpy(this->exten, hint->exten->exten);
04007          AST_LIST_INSERT_HEAD(&store, this, list);
04008       }
04009    }
04010 
04011    tmp = *extcontexts;
04012    if (registrar) {
04013       /* XXX remove previous contexts from same registrar */
04014       if (option_debug)
04015          ast_log(LOG_DEBUG, "must remove any reg %s\n", registrar);
04016       __ast_context_destroy(NULL,registrar);
04017       while (tmp) {
04018          lasttmp = tmp;
04019          tmp = tmp->next;
04020       }
04021    } else {
04022       /* XXX remove contexts with the same name */
04023       while (tmp) {
04024          ast_log(LOG_WARNING, "must remove %s  reg %s\n", tmp->name, tmp->registrar);
04025          __ast_context_destroy(tmp,tmp->registrar);
04026          lasttmp = tmp;
04027          tmp = tmp->next;
04028       }
04029    }
04030    if (lasttmp) {
04031       lasttmp->next = contexts;
04032       contexts = *extcontexts;
04033       *extcontexts = NULL;
04034    } else
04035       ast_log(LOG_WARNING, "Requested contexts didn't get merged\n");
04036 
04037    /* restore the watchers for hints that can be found; notify those that
04038       cannot be restored
04039    */
04040    while ((this = AST_LIST_REMOVE_HEAD(&store, list))) {
04041       struct pbx_find_info q = { .stacklen = 0 };
04042       exten = pbx_find_extension(NULL, NULL, &q, this->context, this->exten, PRIORITY_HINT, NULL, "", E_MATCH);
04043       /* Find the hint in the list of hints */
04044       AST_LIST_TRAVERSE(&hints, hint, list) {
04045          if (hint->exten == exten)
04046             break;
04047       }
04048       if (!exten || !hint) {
04049          /* this hint has been removed, notify the watchers */
04050          prevcb = NULL;
04051          thiscb = this->callbacks;
04052          while (thiscb) {
04053             prevcb = thiscb;
04054             thiscb = thiscb->next;
04055             prevcb->callback(this->context, this->exten, AST_EXTENSION_REMOVED, prevcb->data);
04056             free(prevcb);
04057             }
04058       } else {
04059          thiscb = this->callbacks;
04060          while (thiscb->next)
04061             thiscb = thiscb->next;
04062          thiscb->next = hint->callbacks;
04063          hint->callbacks = this->callbacks;
04064          hint->laststate = this->laststate;
04065       }
04066       free(this);
04067    }
04068 
04069    AST_LIST_UNLOCK(&hints);
04070    ast_unlock_contexts();
04071 
04072    return;
04073 }

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 6510 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, and ast_channel::priority.

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

06511 {
06512    char *exten, *pri, *context;
06513    char *stringp;
06514    int ipri;
06515    int mode = 0;
06516 
06517    if (ast_strlen_zero(goto_string)) {
06518       ast_log(LOG_WARNING, "Goto requires an argument (optional context|optional extension|priority)\n");
06519       return -1;
06520    }
06521    stringp = ast_strdupa(goto_string);
06522    context = strsep(&stringp, "|"); /* guaranteed non-null */
06523    exten = strsep(&stringp, "|");
06524    pri = strsep(&stringp, "|");
06525    if (!exten) {  /* Only a priority in this one */
06526       pri = context;
06527       exten = NULL;
06528       context = NULL;
06529    } else if (!pri) {   /* Only an extension and priority in this one */
06530       pri = exten;
06531       exten = context;
06532       context = NULL;
06533    }
06534    if (*pri == '+') {
06535       mode = 1;
06536       pri++;
06537    } else if (*pri == '-') {
06538       mode = -1;
06539       pri++;
06540    }
06541    if (sscanf(pri, "%30d", &ipri) != 1) {
06542       if ((ipri = ast_findlabel_extension(chan, context ? context : chan->context, exten ? exten : chan->exten,
06543          pri, chan->cid.cid_num)) < 1) {
06544          ast_log(LOG_WARNING, "Priority '%s' must be a number > 0, or valid label\n", pri);
06545          return -1;
06546       } else
06547          mode = 0;
06548    }
06549    /* At this point we have a priority and maybe an extension and a context */
06550 
06551    if (mode)
06552       ipri = chan->priority + (ipri * mode);
06553 
06554    ast_explicit_goto(chan, context, exten, ipri);
06555    return 0;
06556 
06557 }

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

References __ast_request_and_dial(), 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(), async_stat::chan, errno, free, LOG_WARNING, option_verbose, outgoing_helper::vars, and VERBOSE_PREFIX_4.

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

05205 {
05206    struct ast_channel *chan;
05207    struct app_tmp *tmp;
05208    int res = -1, cdr_res = -1;
05209    struct outgoing_helper oh;
05210    pthread_attr_t attr;
05211 
05212    memset(&oh, 0, sizeof(oh));
05213    oh.vars = vars;
05214    oh.account = account;
05215 
05216    if (locked_channel)
05217       *locked_channel = NULL;
05218    if (ast_strlen_zero(app)) {
05219       res = -1;
05220       goto outgoing_app_cleanup;
05221    }
05222    if (sync) {
05223       chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
05224       if (chan) {
05225          ast_set_variables(chan, vars);
05226          if (account)
05227             ast_cdr_setaccount(chan, account);
05228          if (chan->_state == AST_STATE_UP) {
05229             res = 0;
05230             if (option_verbose > 3)
05231                ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", chan->name);
05232             tmp = ast_calloc(1, sizeof(*tmp));
05233             if (!tmp)
05234                res = -1;
05235             else {
05236                ast_copy_string(tmp->app, app, sizeof(tmp->app));
05237                if (appdata)
05238                   ast_copy_string(tmp->data, appdata, sizeof(tmp->data));
05239                tmp->chan = chan;
05240                if (sync > 1) {
05241                   if (locked_channel)
05242                      ast_channel_unlock(chan);
05243                   ast_pbx_run_app(tmp);
05244                } else {
05245                   pthread_attr_init(&attr);
05246                   pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
05247                   if (locked_channel)
05248                      ast_channel_lock(chan);
05249                   if (ast_pthread_create(&tmp->t, &attr, ast_pbx_run_app, tmp)) {
05250                      ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno));
05251                      free(tmp);
05252                      if (locked_channel)
05253                         ast_channel_unlock(chan);
05254                      ast_hangup(chan);
05255                      res = -1;
05256                   } else {
05257                      if (locked_channel)
05258                         *locked_channel = chan;
05259                   }
05260                   pthread_attr_destroy(&attr);
05261                }
05262             }
05263          } else {
05264             if (option_verbose > 3)
05265                ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", chan->name);
05266             if (chan->cdr) { /* update the cdr */
05267                /* here we update the status of the call, which sould be busy.
05268                 * if that fails then we set the status to failed */
05269                if (ast_cdr_disposition(chan->cdr, chan->hangupcause))
05270                   ast_cdr_failed(chan->cdr);
05271             }
05272             ast_hangup(chan);
05273          }
05274       }
05275 
05276       if (res < 0) { /* the call failed for some reason */
05277          if (*reason == 0) { /* if the call failed (not busy or no answer)
05278                         * update the cdr with the failed message */
05279             cdr_res = ast_pbx_outgoing_cdr_failed();
05280             if (cdr_res != 0) {
05281                res = cdr_res;
05282                goto outgoing_app_cleanup;
05283             }
05284          }
05285       }
05286 
05287    } else {
05288       struct async_stat *as;
05289       if (!(as = ast_calloc(1, sizeof(*as)))) {
05290          res = -1;
05291          goto outgoing_app_cleanup;
05292       }
05293       chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
05294       if (!chan) {
05295          free(as);
05296          res = -1;
05297          goto outgoing_app_cleanup;
05298       }
05299       as->chan = chan;
05300       ast_copy_string(as->app, app, sizeof(as->app));
05301       if (appdata)
05302          ast_copy_string(as->appdata,  appdata, sizeof(as->appdata));
05303       as->timeout = timeout;
05304       ast_set_variables(chan, vars);
05305       if (account)
05306          ast_cdr_setaccount(chan, account);
05307       /* Start a new thread, and get something handling this channel. */
05308       pthread_attr_init(&attr);
05309       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
05310       if (locked_channel)
05311          ast_channel_lock(chan);
05312       if (ast_pthread_create(&as->p, &attr, async_wait, as)) {
05313          ast_log(LOG_WARNING, "Failed to start async wait\n");
05314          free(as);
05315          if (locked_channel)
05316             ast_channel_unlock(chan);
05317          ast_hangup(chan);
05318          res = -1;
05319          pthread_attr_destroy(&attr);
05320          goto outgoing_app_cleanup;
05321       } else {
05322          if (locked_channel)
05323             *locked_channel = chan;
05324       }
05325       pthread_attr_destroy(&attr);
05326       res = 0;
05327    }
05328 outgoing_app_cleanup:
05329    ast_variables_destroy(vars);
05330    return res;
05331 }

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

05013 {
05014    /* allocate a channel */
05015    struct ast_channel *chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "%s", "");
05016 
05017    if (!chan)
05018       return -1;  /* failure */
05019 
05020    if (!chan->cdr) {
05021       /* allocation of the cdr failed */
05022       ast_channel_free(chan);   /* free the channel */
05023       return -1;                /* return failure */
05024    }
05025 
05026    /* allocation of the cdr was successful */
05027    ast_cdr_init(chan->cdr, chan);  /* initilize our channel's cdr */
05028    ast_cdr_start(chan->cdr);       /* record the start and stop time */
05029    ast_cdr_end(chan->cdr);
05030    ast_cdr_failed(chan->cdr);      /* set the status to failed */
05031    ast_cdr_detach(chan->cdr);      /* post and free the record */
05032    chan->cdr = NULL;
05033    ast_channel_free(chan);         /* free the channel */
05034 
05035    return 0;  /* success */
05036 }

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 5038 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, ast_channel::context, free, ast_channel::hangupcause, LOAD_OH, LOG_ERROR, LOG_WARNING, ast_channel::name, option_verbose, pbx_builtin_setvar_helper(), set_ext_pri(), outgoing_helper::vars, and VERBOSE_PREFIX_4.

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

05039 {
05040    struct ast_channel *chan;
05041    struct async_stat *as;
05042    int res = -1, cdr_res = -1;
05043    struct outgoing_helper oh;
05044    pthread_attr_t attr;
05045 
05046    if (sync) {
05047       LOAD_OH(oh);
05048       chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
05049       if (channel) {
05050          *channel = chan;
05051          if (chan)
05052             ast_channel_lock(chan);
05053       }
05054       if (chan) {
05055          if (chan->_state == AST_STATE_UP) {
05056                res = 0;
05057             if (option_verbose > 3)
05058                ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", chan->name);
05059 
05060             if (sync > 1) {
05061                if (channel)
05062                   ast_channel_unlock(chan);
05063                if (ast_pbx_run(chan)) {
05064                   ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name);
05065                   if (channel)
05066                      *channel = NULL;
05067                   ast_hangup(chan);
05068                   chan = NULL;
05069                   res = -1;
05070                }
05071             } else {
05072                if (ast_pbx_start(chan)) {
05073                   ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name);
05074                   if (channel) {
05075                      *channel = NULL;
05076                      ast_channel_unlock(chan);
05077                   }
05078                   ast_hangup(chan);
05079                   res = -1;
05080                }
05081                chan = NULL;
05082             }
05083          } else {
05084             if (option_verbose > 3)
05085                ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", chan->name);
05086 
05087             if (chan->cdr) { /* update the cdr */
05088                /* here we update the status of the call, which sould be busy.
05089                 * if that fails then we set the status to failed */
05090                if (ast_cdr_disposition(chan->cdr, chan->hangupcause))
05091                   ast_cdr_failed(chan->cdr);
05092             }
05093 
05094             if (channel) {
05095                *channel = NULL;
05096                ast_channel_unlock(chan);
05097             }
05098             ast_hangup(chan);
05099             chan = NULL;
05100          }
05101       }
05102 
05103       if (res < 0) { /* the call failed for some reason */
05104          if (*reason == 0) { /* if the call failed (not busy or no answer)
05105                         * update the cdr with the failed message */
05106             cdr_res = ast_pbx_outgoing_cdr_failed();
05107             if (cdr_res != 0) {
05108                res = cdr_res;
05109                goto outgoing_exten_cleanup;
05110             }
05111          }
05112 
05113          /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */
05114          /* check if "failed" exists */
05115          if (ast_exists_extension(chan, context, "failed", 1, NULL)) {
05116             chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "OutgoingSpoolFailed");
05117             if (chan) {
05118                char failed_reason[4] = "";
05119                if (!ast_strlen_zero(context))
05120                   ast_copy_string(chan->context, context, sizeof(chan->context));
05121                set_ext_pri(chan, "failed", 1);
05122                ast_set_variables(chan, vars);
05123                snprintf(failed_reason, sizeof(failed_reason), "%d", *reason);
05124                pbx_builtin_setvar_helper(chan, "REASON", failed_reason);
05125                if (account)
05126                   ast_cdr_setaccount(chan, account);
05127                if (ast_pbx_run(chan)) {
05128                   ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name);
05129                   ast_hangup(chan);
05130                }
05131                chan = NULL;
05132             }
05133          }
05134       }
05135    } else {
05136       if (!(as = ast_calloc(1, sizeof(*as)))) {
05137          res = -1;
05138          goto outgoing_exten_cleanup;
05139       }
05140       chan = ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name);
05141       if (channel) {
05142          *channel = chan;
05143          if (chan)
05144             ast_channel_lock(chan);
05145       }
05146       if (!chan) {
05147          free(as);
05148          res = -1;
05149          goto outgoing_exten_cleanup;
05150       }
05151       as->chan = chan;
05152       ast_copy_string(as->context, context, sizeof(as->context));
05153       set_ext_pri(as->chan,  exten, priority);
05154       as->timeout = timeout;
05155       ast_set_variables(chan, vars);
05156       if (account)
05157          ast_cdr_setaccount(chan, account);
05158       pthread_attr_init(&attr);
05159       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
05160       if (ast_pthread_create(&as->p, &attr, async_wait, as)) {
05161          ast_log(LOG_WARNING, "Failed to start async wait\n");
05162          free(as);
05163          if (channel) {
05164             *channel = NULL;
05165             ast_channel_unlock(chan);
05166          }
05167          ast_hangup(chan);
05168          res = -1;
05169          pthread_attr_destroy(&attr);
05170          goto outgoing_exten_cleanup;
05171       }
05172       pthread_attr_destroy(&attr);
05173       res = 0;
05174    }
05175 outgoing_exten_cleanup:
05176    ast_variables_destroy(vars);
05177    return res;
05178 }

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

02663 {
02664    enum ast_pbx_result res = AST_PBX_SUCCESS;
02665 
02666    if (increase_call_count(c))
02667       return AST_PBX_CALL_LIMIT;
02668 
02669    res = __ast_pbx_run(c);
02670    decrease_call_count();
02671 
02672    return res;
02673 }

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

run the application and free the descriptor once done

Definition at line 5188 of file pbx.c.

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

Referenced by ast_pbx_outgoing_app().

05189 {
05190    struct app_tmp *tmp = data;
05191    struct ast_app *app;
05192    app = pbx_findapp(tmp->app);
05193    if (app) {
05194       if (option_verbose > 3)
05195          ast_verbose(VERBOSE_PREFIX_4 "Launching %s(%s) on %s\n", tmp->app, tmp->data, tmp->chan->name);
05196       pbx_exec(tmp->chan, app, tmp->data);
05197    } else
05198       ast_log(LOG_WARNING, "No such application '%s'\n", tmp->app);
05199    ast_hangup(tmp->chan);
05200    free(tmp);
05201    return NULL;
05202 }

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 2635 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(), rpt_call(), sip_new(), and skinny_new().

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

int ast_processed_calls ( void   ) 

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

Definition at line 2680 of file pbx.c.

References totalcalls.

02681 {
02682    return totalcalls;
02683 }

int ast_rdlock_contexts ( void   ) 

Definition at line 6288 of file pbx.c.

References ast_rwlock_rdlock, and conlock.

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

06289 {
06290    return ast_rwlock_rdlock(&conlock);
06291 }

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

Register an application.

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

Definition at line 2969 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, ast_app::list, LOG_WARNING, ast_app::name, option_verbose, ast_app::synopsis, term_color(), and VERBOSE_PREFIX_2.

Referenced by load_module(), and load_pbx().

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

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

03020 {
03021    struct ast_switch *tmp;
03022 
03023    AST_LIST_LOCK(&switches);
03024    AST_LIST_TRAVERSE(&switches, tmp, list) {
03025       if (!strcasecmp(tmp->name, sw->name)) {
03026          AST_LIST_UNLOCK(&switches);
03027          ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name);
03028          return -1;
03029       }
03030    }
03031    AST_LIST_INSERT_TAIL(&switches, sw, list);
03032    AST_LIST_UNLOCK(&switches);
03033 
03034    return 0;
03035 }

static int ast_remove_hint ( struct ast_exten e  )  [static]

ast_remove_hint: Remove hint from extension

Definition at line 2228 of file pbx.c.

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

Referenced by destroy_exten().

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

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

References E_SPAWN, and pbx_extension_helper().

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

02308 {
02309    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN);
02310 }

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

06312 {
06313    return ast_mutex_unlock(&con->lock);
06314 }

int ast_unlock_contexts ( void   ) 

Unlocks contexts.

Return values:
0 on success
-1 on failure

Definition at line 6298 of file pbx.c.

References ast_rwlock_unlock, and conlock.

Referenced by __ast_context_create(), _macro_exec(), ast_add_extension(), ast_context_add_ignorepat(), ast_context_add_include(), ast_context_add_switch(), ast_context_destroy(), ast_context_find(), ast_context_lockmacro(), ast_context_remove_extension_callerid(), ast_context_remove_ignorepat(), ast_context_remove_include(), ast_context_remove_switch(), ast_context_unlockmacro(), ast_hint_extension(), ast_hint_state_changed(), ast_merge_contexts_and_delete(), complete_context_add_extension(), complete_context_add_extension_deprecated(), complete_context_add_ignorepat(), complete_context_add_ignorepat_deprecated(), complete_context_add_include(), complete_context_add_include_deprecated(), complete_context_dont_include_deprecated(), complete_context_remove_extension(), complete_context_remove_extension_deprecated(), complete_context_remove_ignorepat(), complete_context_remove_ignorepat_deprecated(), complete_context_remove_include(), complete_show_dialplan_context(), dundi_precache_full(), find_context_locked(), find_matching_endwhile(), handle_save_dialplan(), pbx_extension_helper(), and show_dialplan_helper().

06299 {
06300    return ast_rwlock_unlock(&conlock);
06301 }

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 3884 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, ast_app::list, ast_app::name, option_verbose, and VERBOSE_PREFIX_2.

Referenced by __unload_module(), and unload_module().

03885 {
03886    struct ast_app *tmp;
03887 
03888    AST_LIST_LOCK(&apps);
03889    AST_LIST_TRAVERSE_SAFE_BEGIN(&apps, tmp, list) {
03890       if (!strcasecmp(app, tmp->name)) {
03891          AST_LIST_REMOVE_CURRENT(&apps, list);
03892          if (option_verbose > 1)
03893             ast_verbose( VERBOSE_PREFIX_2 "Unregistered application '%s'\n", tmp->name);
03894          free(tmp);
03895          break;
03896       }
03897    }
03898    AST_LIST_TRAVERSE_SAFE_END
03899    AST_LIST_UNLOCK(&apps);
03900 
03901    return tmp ? 0 : -1;
03902 }

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

03038 {
03039    AST_LIST_LOCK(&switches);
03040    AST_LIST_REMOVE(&switches, sw, list);
03041    AST_LIST_UNLOCK(&switches);
03042 }

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

Definition at line 6420 of file pbx.c.

References exten, and ast_context::root.

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

06422 {
06423    if (!exten)
06424       return con ? con->root : NULL;
06425    else
06426       return exten->next;
06427 }

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

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

06455 {
06456    if (!ip)
06457       return con ? con->ignorepats : NULL;
06458    else
06459       return ip->next;
06460 }

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

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

06446 {
06447    if (!inc)
06448       return con ? con->includes : NULL;
06449    else
06450       return inc->next;
06451 }

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

Definition at line 6429 of file pbx.c.

References ast_context::alts, AST_LIST_FIRST, AST_LIST_NEXT, and ast_sw::list.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06431 {
06432    if (!sw)
06433       return con ? AST_LIST_FIRST(&con->alts) : NULL;
06434    else
06435       return AST_LIST_NEXT(sw, list);
06436 }

struct ast_context* ast_walk_contexts ( struct ast_context con  ) 

Definition at line 6415 of file pbx.c.

References contexts, and ast_context::next.

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

06416 {
06417    return con ? con->next : contexts;
06418 }

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

Definition at line 6438 of file pbx.c.

References exten, and ast_exten::priority.

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

06440 {
06441    return priority ? priority->peer : exten;
06442 }

int ast_wrlock_contexts ( void   ) 

Definition at line 6293 of file pbx.c.

References ast_rwlock_wrlock, and conlock.

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

06294 {
06295    return ast_rwlock_wrlock(&conlock);
06296 }

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

Definition at line 4949 of file pbx.c.

References ast_channel::_state, app, 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, free, LOG_ERROR, LOG_WARNING, ast_channel::name, option_verbose, pbx_exec(), pbx_findapp(), ast_channel::priority, async_stat::priority, async_stat::timeout, and VERBOSE_PREFIX_3.

Referenced by ast_pbx_outgoing_app(), and ast_pbx_outgoing_exten().

04950 {
04951    struct async_stat *as = data;
04952    struct ast_channel *chan = as->chan;
04953    int timeout = as->timeout;
04954    int res;
04955    struct ast_frame *f;
04956    struct ast_app *app;
04957 
04958    while (timeout && (chan->_state != AST_STATE_UP)) {
04959       res = ast_waitfor(chan, timeout);
04960       if (res < 1)
04961          break;
04962       if (timeout > -1)
04963          timeout = res;
04964       f = ast_read(chan);
04965       if (!f)
04966          break;
04967       if (f->frametype == AST_FRAME_CONTROL) {
04968          if ((f->subclass == AST_CONTROL_BUSY)  ||
04969              (f->subclass == AST_CONTROL_CONGESTION) ) {
04970             ast_frfree(f);
04971             break;
04972          }
04973       }
04974       ast_frfree(f);
04975    }
04976    if (chan->_state == AST_STATE_UP) {
04977       if (!ast_strlen_zero(as->app)) {
04978          app = pbx_findapp(as->app);
04979          if (app) {
04980             if (option_verbose > 2)
04981                ast_verbose(VERBOSE_PREFIX_3 "Launching %s(%s) on %s\n", as->app, as->appdata, chan->name);
04982             pbx_exec(chan, app, as->appdata);
04983          } else
04984             ast_log(LOG_WARNING, "No such application '%s'\n", as->app);
04985       } else {
04986          if (!ast_strlen_zero(as->context))
04987             ast_copy_string(chan->context, as->context, sizeof(chan->context));
04988          if (!ast_strlen_zero(as->exten))
04989             ast_copy_string(chan->exten, as->exten, sizeof(chan->exten));
04990          if (as->priority > 0)
04991             chan->priority = as->priority;
04992          /* Run the PBX */
04993          if (ast_pbx_run(chan)) {
04994             ast_log(LOG_ERROR, "Failed to start PBX on %s\n", chan->name);
04995          } else {
04996             /* PBX will have taken care of this */
04997             chan = NULL;
04998          }
04999       }
05000    }
05001    free(as);
05002    if (chan)
05003       ast_hangup(chan);
05004    return NULL;
05005 }

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

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

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

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

Definition at line 3102 of file pbx.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_app::list, ast_app::name, and strdup.

03103 {
03104    struct ast_app *a;
03105    char *ret = NULL;
03106    int which = 0;
03107    int wordlen = strlen(word);
03108 
03109    /* return the n-th [partial] matching entry */
03110    AST_LIST_LOCK(&apps);
03111    AST_LIST_TRAVERSE(&apps, a, list) {
03112       if (!strncasecmp(word, a->name, wordlen) && ++which > state) {
03113          ret = strdup(a->name);
03114          break;
03115       }
03116    }
03117    AST_LIST_UNLOCK(&apps);
03118 
03119    return ret;
03120 }

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

Definition at line 3463 of file pbx.c.

References ast_cli_complete().

03464 {
03465    static char* choices[] = { "like", "describing", NULL };
03466 
03467    return (pos != 3) ? NULL : ast_cli_complete(word, choices, state);
03468 }

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

Definition at line 3456 of file pbx.c.

References ast_cli_complete().

03457 {
03458    static char* choices[] = { "like", "describing", NULL };
03459 
03460    return (pos != 2) ? NULL : ast_cli_complete(word, choices, state);
03461 }

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

Definition at line 3473 of file pbx.c.

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

03475 {
03476    struct ast_context *c = NULL;
03477    char *ret = NULL;
03478    int which = 0;
03479    int wordlen;
03480 
03481    /* we are do completion of [exten@]context on second position only */
03482    if (pos != 2)
03483       return NULL;
03484 
03485    ast_rdlock_contexts();
03486 
03487    wordlen = strlen(word);
03488 
03489    /* walk through all contexts and return the n-th match */
03490    while ( (c = ast_walk_contexts(c)) ) {
03491       if (!strncasecmp(word, ast_get_context_name(c), wordlen) && ++which > state) {
03492          ret = ast_strdup(ast_get_context_name(c));
03493          break;
03494       }
03495    }
03496 
03497    ast_unlock_contexts();
03498 
03499    return ret;
03500 }

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

Definition at line 1460 of file pbx.c.

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

01461 {
01462    struct ast_custom_function *acf;
01463    char *ret = NULL;
01464    int which = 0;
01465    int wordlen = strlen(word);
01466 
01467    /* case-insensitive for convenience in this 'complete' function */
01468    AST_LIST_LOCK(&acf_root);
01469    AST_LIST_TRAVERSE(&acf_root, acf, acflist) {
01470       if (!strncasecmp(word, acf->name, wordlen) && ++which > state) {
01471          ret = strdup(acf->name);
01472          break;
01473       }
01474    }
01475    AST_LIST_UNLOCK(&acf_root);
01476 
01477    return ret;
01478 }

static void decrease_call_count ( void   )  [static]

Definition at line 2597 of file pbx.c.

References ast_mutex_lock, ast_mutex_unlock, countcalls, and maxcalllock.

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

02598 {
02599    ast_mutex_lock(&maxcalllock);
02600    if (countcalls > 0)
02601       countcalls--;
02602    ast_mutex_unlock(&maxcalllock);
02603 }

static void destroy_exten ( struct ast_exten e  )  [static]

Definition at line 2605 of file pbx.c.

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

Referenced by __ast_context_destroy(), and ast_context_remove_extension_callerid2().

02606 {
02607    if (e->priority == PRIORITY_HINT)
02608       ast_remove_hint(e);
02609 
02610    if (e->datad)
02611       e->datad(e->data);
02612    free(e);
02613 }

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

the full routine to compare extensions in rules.

Definition at line 745 of file pbx.c.

References ext_cmp1().

Referenced by ast_add_extension2().

00746 {
00747    /* make sure non-patterns come first.
00748     * If a is not a pattern, it either comes first or
00749     * we use strcmp to compare the strings.
00750     */
00751    int ret = 0;
00752 
00753    if (a[0] != '_')
00754       return (b[0] == '_') ? -1 : strcmp(a, b);
00755 
00756    /* Now we know a is a pattern; if b is not, a comes first */
00757    if (b[0] != '_')
00758       return 1;
00759 #if 0 /* old mode for ext matching */
00760    return strcmp(a, b);
00761 #endif
00762    /* ok we need full pattern sorting routine */
00763    while (!ret && a && b)
00764       ret = ext_cmp1(&a) - ext_cmp1(&b);
00765    if (ret == 0)
00766       return 0;
00767    else
00768       return (ret > 0) ? 1 : -1;
00769 }

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

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

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

Definition at line 673 of file pbx.c.

References ast_log(), and LOG_WARNING.

Referenced by ext_cmp().

00674 {
00675    uint32_t chars[8];
00676    int c, cmin = 0xff, count = 0;
00677    const char *end;
00678 
00679    /* load, sign extend and advance pointer until we find
00680     * a valid character.
00681     */
00682    while ( (c = *(*p)++) && (c == ' ' || c == '-') )
00683       ;  /* ignore some characters */
00684 
00685    /* always return unless we have a set of chars */
00686    switch (c) {
00687    default: /* ordinary character */
00688       return 0x0000 | (c & 0xff);
00689 
00690    case 'N':   /* 2..9 */
00691       return 0x0800 | '2' ;
00692 
00693    case 'X':   /* 0..9 */
00694       return 0x0A00 | '0';
00695 
00696    case 'Z':   /* 1..9 */
00697       return 0x0900 | '1';
00698 
00699    case '.':   /* wildcard */
00700       return 0x10000;
00701 
00702    case '!':   /* earlymatch */
00703       return 0x20000;   /* less specific than NULL */
00704 
00705    case '\0':  /* empty string */
00706       *p = NULL;
00707       return 0x30000;
00708 
00709    case '[':   /* pattern */
00710       break;
00711    }
00712    /* locate end of set */
00713    end = strchr(*p, ']');  
00714 
00715    if (end == NULL) {
00716       ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n");
00717       return 0x40000;   /* XXX make this entry go last... */
00718    }
00719 
00720    bzero(chars, sizeof(chars));  /* clear all chars in the set */
00721    for (; *p < end  ; (*p)++) {
00722       unsigned char c1, c2;   /* first-last char in range */
00723       c1 = (unsigned char)((*p)[0]);
00724       if (*p + 2 < end && (*p)[1] == '-') { /* this is a range */
00725          c2 = (unsigned char)((*p)[2]);
00726          *p += 2; /* skip a total of 3 chars */
00727       } else         /* individual character */
00728          c2 = c1;
00729       if (c1 < cmin)
00730          cmin = c1;
00731       for (; c1 <= c2; c1++) {
00732          uint32_t mask = 1 << (c1 % 32);
00733          if ( (chars[ c1 / 32 ] & mask) == 0)
00734             count += 0x100;
00735          chars[ c1 / 32 ] |= mask;
00736       }
00737    }
00738    (*p)++;
00739    return count == 0 ? 0x30000 : (count | cmin);
00740 }

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

copy a string skipping whitespace

Definition at line 4701 of file pbx.c.

Referenced by ast_add_extension2().

04702 {
04703    int count=0;
04704 
04705    while (*src && (count < len - 1)) {
04706       switch(*src) {
04707       case ' ':
04708          /* otherwise exten => [a-b],1,... doesn't work */
04709          /*    case '-': */
04710          /* Ignore */
04711          break;
04712       default:
04713          *dst = *src;
04714          dst++;
04715       }
04716       src++;
04717       count++;
04718    }
04719    *dst = '\0';
04720 
04721    return count;
04722 }

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

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

00895 {
00896    int i;
00897    static int prof_id = -2;   /* marker for 'unallocated' id */
00898    if (prof_id == -2)
00899       prof_id = ast_add_profile("ext_match", 0);
00900    ast_mark(prof_id, 1);
00901    i = _extension_match_core(pattern, data, mode);
00902    ast_mark(prof_id, 0);
00903    return i;
00904 }

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

Definition at line 2695 of file pbx.c.

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

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

02696 {
02697    struct ast_context *c = NULL;
02698 
02699    ast_rdlock_contexts();
02700    while ( (c = ast_walk_contexts(c)) ) {
02701       if (!strcmp(ast_get_context_name(c), context))
02702          return c;
02703    }
02704    ast_unlock_contexts();
02705 
02706    return NULL;
02707 }

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

References ast_log(), and LOG_WARNING.

Referenced by ast_func_read(), and ast_func_write().

01554 {
01555    char *args = strchr(function, '(');
01556 
01557    if (!args)
01558       ast_log(LOG_WARNING, "Function doesn't contain parentheses.  Assuming null argument.\n");
01559    else {
01560       char *p;
01561       *args++ = '\0';
01562       if ((p = strrchr(args, ')')) )
01563          *p = '\0';
01564       else
01565          ast_log(LOG_WARNING, "Can't find trailing parenthesis?\n");
01566    }
01567    return args;
01568 }

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

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

Referenced by ast_build_timing().

04115 {
04116    int s, e; /* start and ending position */
04117    unsigned int mask = 0;
04118 
04119    /* Check for whole range */
04120    if (ast_strlen_zero(src) || !strcmp(src, "*")) {
04121       s = 0;
04122       e = max - 1;
04123    } else {
04124       /* Get start and ending position */
04125       char *c = strchr(src, '-');
04126       if (c)
04127          *c++ = '\0';
04128       /* Find the start */
04129       s = lookup_name(src, names, max);
04130       if (!s) {
04131          ast_log(LOG_WARNING, "Invalid %s '%s', assuming none\n", msg, src);
04132          return 0;
04133       }
04134       s--;
04135       if (c) { /* find end of range */
04136          e = lookup_name(c, names, max);
04137          if (!e) {
04138             ast_log(LOG_WARNING, "Invalid end %s '%s', assuming none\n", msg, c);
04139             return 0;
04140          }
04141          e--;
04142       } else
04143          e = s;
04144    }
04145    /* Fill the mask. Remember that ranges are cyclic */
04146    mask = 1 << e; /* initialize with last element */
04147    while (s != e) {
04148       if (s >= max) {
04149          s = 0;
04150          mask |= (1 << s);
04151       } else {
04152          mask |= (1 << s);
04153          s++;
04154       }
04155    }
04156    return mask;
04157 }

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

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

Definition at line 4160 of file pbx.c.

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

Referenced by ast_build_timing().

04161 {
04162    char *e;
04163    int x;
04164    int s1, s2;
04165    int e1, e2;
04166    /* int cth, ctm; */
04167 
04168    /* start disabling all times, fill the fields with 0's, as they may contain garbage */
04169    memset(i->minmask, 0, sizeof(i->minmask));
04170 
04171    /* 2-minutes per bit, since the mask has only 32 bits :( */
04172    /* Star is all times */
04173    if (ast_strlen_zero(times) || !strcmp(times, "*")) {
04174       for (x=0; x<24; x++)
04175          i->minmask[x] = 0x3fffffff; /* 30 bits */
04176       return;
04177    }
04178    /* Otherwise expect a range */
04179    e = strchr(times, '-');
04180    if (!e) {
04181       ast_log(LOG_WARNING, "Time range is not valid. Assuming no restrictions based on time.\n");
04182       return;
04183    }
04184    *e++ = '\0';
04185    /* XXX why skip non digits ? */
04186    while (*e && !isdigit(*e))
04187       e++;
04188    if (!*e) {
04189       ast_log(LOG_WARNING, "Invalid time range.  Assuming no restrictions based on time.\n");
04190       return;
04191    }
04192    if (sscanf(times, "%2d:%2d", &s1, &s2) != 2) {
04193       ast_log(LOG_WARNING, "%s isn't a time.  Assuming no restrictions based on time.\n", times);
04194       return;
04195    }
04196    if (sscanf(e, "%2d:%2d", &e1, &e2) != 2) {
04197       ast_log(LOG_WARNING, "%s isn't a time.  Assuming no restrictions based on time.\n", e);
04198       return;
04199    }
04200    /* XXX this needs to be optimized */
04201 #if 1
04202    s1 = s1 * 30 + s2/2;
04203    if ((s1 < 0) || (s1 >= 24*30)) {
04204       ast_log(LOG_WARNING, "%s isn't a valid start time. Assuming no time.\n", times);
04205       return;
04206    }
04207    e1 = e1 * 30 + e2/2;
04208    if ((e1 < 0) || (e1 >= 24*30)) {
04209       ast_log(LOG_WARNING, "%s isn't a valid end time. Assuming no time.\n", e);
04210       return;
04211    }
04212    /* Go through the time and enable each appropriate bit */
04213    for (x=s1;x != e1;x = (x + 1) % (24 * 30)) {
04214       i->minmask[x/30] |= (1 << (x % 30));
04215    }
04216    /* Do the last one */
04217    i->minmask[x/30] |= (1 << (x % 30));
04218 #else
04219    for (cth=0; cth<24; cth++) {
04220       /* Initialize masks to blank */
04221       i->minmask[cth] = 0;
04222       for (ctm=0; ctm<30; ctm++) {
04223          if (
04224          /* First hour with more than one hour */
04225                (((cth == s1) && (ctm >= s2)) &&
04226                 ((cth < e1)))
04227          /* Only one hour */
04228          ||    (((cth == s1) && (ctm >= s2)) &&
04229                 ((cth == e1) && (ctm <= e2)))
04230          /* In between first and last hours (more than 2 hours) */
04231          ||    ((cth > s1) &&
04232                 (cth < e1))
04233          /* Last hour with more than one hour */
04234          ||    ((cth > s1) &&
04235                 ((cth == e1) && (ctm <= e2)))
04236          )
04237             i->minmask[cth] |= (1 << (ctm / 2));
04238       }
04239    }
04240 #endif
04241    /* All done */
04242    return;
04243 }

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

Definition at line 3761 of file pbx.c.

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

03762 {
03763    if (argc != 5)
03764       return RESULT_SHOWUSAGE;
03765 
03766    pbx_builtin_setvar_helper(NULL, argv[3], argv[4]);
03767    ast_cli(fd, "\n    -- Global variable %s set to %s\n", argv[3], argv[4]);
03768 
03769    return RESULT_SUCCESS;
03770 }

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

CLI support for setting global variables.

Definition at line 3749 of file pbx.c.

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

03750 {
03751    if (argc != 4)
03752       return RESULT_SHOWUSAGE;
03753 
03754    pbx_builtin_setvar_helper(NULL, argv[2], argv[3]);
03755    ast_cli(fd, "\n    -- Global variable %s set to %s\n", argv[2], argv[3]);
03756 
03757    return RESULT_SUCCESS;
03758 }

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

Definition at line 3192 of file pbx.c.

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

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

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

Definition at line 3122 of file pbx.c.

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

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

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

Definition at line 3387 of file pbx.c.

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

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

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

Definition at line 3319 of file pbx.c.

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

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

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

Definition at line 3676 of file pbx.c.

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

03677 {
03678    char *exten = NULL, *context = NULL;
03679    /* Variables used for different counters */
03680    struct dialplan_counters counters;
03681 
03682    const char *incstack[AST_PBX_MAX_STACK];
03683    memset(&counters, 0, sizeof(counters));
03684 
03685    if (argc != 2 && argc != 3)
03686       return RESULT_SHOWUSAGE;
03687 
03688    /* we obtain [exten@]context? if yes, split them ... */
03689    if (argc == 3) {
03690       if (strchr(argv[2], '@')) {   /* split into exten & context */
03691          context = ast_strdupa(argv[2]);
03692          exten = strsep(&context, "@");
03693          /* change empty strings to NULL */
03694          if (ast_strlen_zero(exten))
03695             exten = NULL;
03696       } else { /* no '@' char, only context given */
03697          context = argv[2];
03698       }
03699       if (ast_strlen_zero(context))
03700          context = NULL;
03701    }
03702    /* else Show complete dial plan, context and exten are NULL */
03703    show_dialplan_helper(fd, context, exten, &counters, NULL, 0, incstack);
03704 
03705    /* check for input failure and throw some error messages */
03706    if (context && !counters.context_existence) {
03707       ast_cli(fd, "There is no existence of '%s' context\n", context);
03708       return RESULT_FAILURE;
03709    }
03710 
03711    if (exten && !counters.extension_existence) {
03712       if (context)
03713          ast_cli(fd, "There is no existence of %s@%s extension\n",
03714             exten, context);
03715       else
03716          ast_cli(fd,
03717             "There is no existence of '%s' extension in all contexts\n",
03718             exten);
03719       return RESULT_FAILURE;
03720    }
03721 
03722    ast_cli(fd,"-= %d %s (%d %s) in %d %s. =-\n",
03723             counters.total_exten, counters.total_exten == 1 ? "extension" : "extensions",
03724             counters.total_prio, counters.total_prio == 1 ? "priority" : "priorities",
03725             counters.total_context, counters.total_context == 1 ? "context" : "contexts");
03726 
03727    /* everything ok */
03728    return RESULT_SUCCESS;
03729 }

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

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

01405 {
01406    struct ast_custom_function *acf;
01407    /* Maximum number of characters added by terminal coloring is 22 */
01408    char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40];
01409    char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL;
01410    char stxtitle[40], *syntax = NULL;
01411    int synopsis_size, description_size, syntax_size;
01412 
01413    if (argc < 4)
01414       return RESULT_SHOWUSAGE;
01415 
01416    if (!(acf = ast_custom_function_find(argv[3]))) {
01417       ast_cli(fd, "No function by that name registered.\n");
01418       return RESULT_FAILURE;
01419 
01420    }
01421 
01422    if (acf->synopsis)
01423       synopsis_size = strlen(acf->synopsis) + 23;
01424    else
01425       synopsis_size = strlen("Not available") + 23;
01426    synopsis = alloca(synopsis_size);
01427 
01428    if (acf->desc)
01429       description_size = strlen(acf->desc) + 23;
01430    else
01431       description_size = strlen("Not available") + 23;
01432    description = alloca(description_size);
01433 
01434    if (acf->syntax)
01435       syntax_size = strlen(acf->syntax) + 23;
01436    else
01437       syntax_size = strlen("Not available") + 23;
01438    syntax = alloca(syntax_size);
01439 
01440    snprintf(info, 64 + AST_MAX_APP, "\n  -= Info about function '%s' =- \n\n", acf->name);
01441    term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22);
01442    term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40);
01443    term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
01444    term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
01445    term_color(syntax,
01446          acf->syntax ? acf->syntax : "Not available",
01447          COLOR_CYAN, 0, syntax_size);
01448    term_color(synopsis,
01449          acf->synopsis ? acf->synopsis : "Not available",
01450          COLOR_CYAN, 0, synopsis_size);
01451    term_color(description,
01452          acf->desc ? acf->desc : "Not available",
01453          COLOR_CYAN, 0, description_size);
01454 
01455    ast_cli(fd,"%s%s%s\n\n%s%s\n\n%s%s\n", infotitle, stxtitle, syntax, syntitle, synopsis, destitle, description);
01456 
01457    return RESULT_SUCCESS;
01458 }

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

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

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

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

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

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

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

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

01294 {
01295    struct ast_custom_function *acf;
01296    int count_acf = 0;
01297    int like = 0;
01298 
01299    if (argc == 4 && (!strcmp(argv[2], "like")) ) {
01300       like = 1;
01301    } else if (argc != 2) {
01302       return RESULT_SHOWUSAGE;
01303    }
01304 
01305    ast_cli(fd, "%s Custom Functions:\n--------------------------------------------------------------------------------\n", like ? "Matching" : "Installed");
01306 
01307    AST_LIST_LOCK(&acf_root);
01308    AST_LIST_TRAVERSE(&acf_root, acf, acflist) {
01309       if (!like || strstr(acf->name, argv[3])) {
01310          count_acf++;
01311          ast_cli(fd, "%-20.20s  %-35.35s  %s\n", acf->name, acf->syntax, acf->synopsis);
01312       }
01313    }
01314    AST_LIST_UNLOCK(&acf_root);
01315 
01316    ast_cli(fd, "%d %scustom functions installed.\n", count_acf, like ? "matching " : "");
01317 
01318    return RESULT_SUCCESS;
01319 }

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

References ast_cli(), AST_LIST_TRAVERSE, ast_mutex_lock, ast_mutex_unlock, ast_var_name(), ast_var_value(), ast_var_t::entries, globals, globalslock, and RESULT_SUCCESS.

03733 {
03734    int i = 0;
03735    struct ast_var_t *newvariable;
03736 
03737    ast_mutex_lock(&globalslock);
03738    AST_LIST_TRAVERSE (&globals, newvariable, entries) {
03739       i++;
03740       ast_cli(fd, "   %s=%s\n", ast_var_name(newvariable), ast_var_value(newvariable));
03741    }
03742    ast_mutex_unlock(&globalslock);
03743    ast_cli(fd, "\n    -- %d variables\n", i);
03744 
03745    return RESULT_SUCCESS;
03746 }

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

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

03264 {
03265    struct ast_hint *hint;
03266    int num = 0;
03267    int watchers;
03268    struct ast_state_cb *watcher;
03269 
03270    if (AST_LIST_EMPTY(&hints)) {
03271       ast_cli(fd, "There are no registered dialplan hints\n");
03272       return RESULT_SUCCESS;
03273    }
03274    /* ... we have hints ... */
03275    ast_cli(fd, "\n    -= Registered Asterisk Dial Plan Hints =-\n");
03276    AST_LIST_LOCK(&hints);
03277    AST_LIST_TRAVERSE(&hints, hint, list) {
03278       watchers = 0;
03279       for (watcher = hint->callbacks; watcher; watcher = watcher->next)
03280          watchers++;
03281       ast_cli(fd, "   %20s@%-20.20s: %-20.20s  State:%-15.15s Watchers %2d\n",
03282          ast_get_extension_name(hint->exten),
03283          ast_get_context_name(ast_get_extension_context(hint->exten)),
03284          ast_get_extension_app(hint->exten),
03285          ast_extension_state2str(hint->laststate), watchers);
03286       num++;
03287    }
03288    ast_cli(fd, "----------------\n");
03289    ast_cli(fd, "- %d hints registered\n", num);
03290    AST_LIST_UNLOCK(&hints);
03291    return RESULT_SUCCESS;
03292 }

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

03296 {
03297    struct ast_switch *sw;
03298 
03299    AST_LIST_LOCK(&switches);
03300 
03301    if (AST_LIST_EMPTY(&switches)) {
03302       AST_LIST_UNLOCK(&switches);
03303       ast_cli(fd, "There are no registered alternative switches\n");
03304       return RESULT_SUCCESS;
03305    }
03306 
03307    ast_cli(fd, "\n    -= Registered Asterisk Alternative Switches =-\n");
03308    AST_LIST_TRAVERSE(&switches, sw, list)
03309       ast_cli(fd, "%s: %s\n", sw->name, sw->description);
03310 
03311    AST_LIST_UNLOCK(&switches);
03312 
03313    return RESULT_SUCCESS;
03314 }

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

Definition at line 603 of file pbx.c.

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

00604 {
00605    if (!i->hastime)
00606       return 1;
00607 
00608    return ast_check_timing(&(i->timing));
00609 }

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

Definition at line 2570 of file pbx.c.

References ast_log(), ast_mutex_lock, ast_mutex_unlock, countcalls, LOG_NOTICE, maxcalllock, ast_channel::name, option_maxcalls, option_maxload, and totalcalls.

Referenced by ast_pbx_run(), and ast_pbx_start().

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

int load_pbx ( void   ) 

Provided by pbx.c

Definition at line 6257 of file pbx.c.

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

Referenced by main().

06258 {
06259    int x;
06260 
06261    /* Initialize the PBX */
06262    if (option_verbose) {
06263       ast_verbose( "Asterisk PBX Core Initializing\n");
06264       ast_verbose( "Registering builtin applications:\n");
06265    }
06266    ast_cli_register_multiple(pbx_cli, sizeof(pbx_cli) / sizeof(struct ast_cli_entry));
06267 
06268    /* Register builtin applications */
06269    for (x=0; x<sizeof(builtins) / sizeof(struct pbx_builtin); x++) {
06270       if (option_verbose)
06271          ast_verbose( VERBOSE_PREFIX_1 "[%s]\n", builtins[x].name);
06272       if (ast_register_application(builtins[x].name, builtins[x].execute, builtins[x].synopsis, builtins[x].description)) {
06273          ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name);
06274          return -1;
06275       }
06276    }
06277    return 0;
06278 }

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

Referenced by get_range().

04097 {
04098    int i;
04099 
04100    if (names) {
04101       for (i = 0; names[i]; i++) {
04102          if (!strcasecmp(s, names[i]))
04103             return i+1;
04104       }
04105    } else if (sscanf(s, "%30d", &i) == 1 && i >= 1 && i <= max) {
04106       return i;
04107    }
04108    return 0; /* error return */
04109 }

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

Definition at line 940 of file pbx.c.

References ast_extension_match(), and ast_strlen_zero().

Referenced by pbx_find_extension().

00941 {
00942    /* If the Caller*ID pattern is empty, then we're matching NO Caller*ID, so
00943       failing to get a number should count as a match, otherwise not */
00944 
00945    if (ast_strlen_zero(callerid))
00946       return ast_strlen_zero(cidpattern) ? 1 : 0;
00947 
00948    return ast_extension_match(cidpattern, callerid);
00949 }

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

Referenced by pbx_retrieve_variable(), and pbx_substitute_variables_helper_full().

01107 {
01108    int parens=0;
01109 
01110    *offset = 0;
01111    *length = INT_MAX;
01112    *isfunc = 0;
01113    for (; *var; var++) {
01114       if (*var == '(') {
01115          (*isfunc)++;
01116          parens++;
01117       } else if (*var == ')') {
01118          parens--;
01119       } else if (*var == ':' && parens == 0) {
01120          *var++ = '\0';
01121          sscanf(var, "%30d:%30d", offset, length);
01122          return 1; /* offset:length valid */
01123       }
01124    }
01125    return 0;
01126 }

void pbx_builtin_clear_globals ( void   ) 

Definition at line 6059 of file pbx.c.

References AST_LIST_REMOVE_HEAD, ast_mutex_lock, ast_mutex_unlock, ast_var_delete(), ast_var_t::entries, globals, and globalslock.

Referenced by handle_reload_extensions(), and reload().

06060 {
06061    struct ast_var_t *vardata;
06062 
06063    ast_mutex_lock(&globalslock);
06064    while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries)))
06065       ast_var_delete(vardata);
06066    ast_mutex_unlock(&globalslock);
06067 }

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

Note:
Will lock the channel.

Definition at line 5836 of file pbx.c.

References ast_channel_lock, ast_channel_unlock, AST_LIST_TRAVERSE, ast_mutex_lock, ast_mutex_unlock, ast_var_name(), ast_var_value(), globals, and globalslock.

Referenced by __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(), dundi_exec(), dundi_helper(), 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(), 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_suggested_sip_codec(), update_bridgepeer(), and wait_for_answer().

05837 {
05838    struct ast_var_t *variables;
05839    const char *ret = NULL;
05840    int i;
05841    struct varshead *places[2] = { NULL, &globals };
05842 
05843    if (!name)
05844       return NULL;
05845 
05846    if (chan) {
05847       ast_channel_lock(chan);
05848       places[0] = &chan->varshead;
05849    }
05850 
05851    for (i = 0; i < 2; i++) {
05852       if (!places[i])
05853          continue;
05854       if (places[i] == &globals)
05855          ast_mutex_lock(&globalslock);
05856       AST_LIST_TRAVERSE(places[i], variables, entries) {
05857          if (!strcmp(name, ast_var_name(variables))) {
05858             ret = ast_var_value(variables);
05859             break;
05860          }
05861       }
05862       if (places[i] == &globals)
05863          ast_mutex_unlock(&globalslock);
05864       if (ret)
05865          break;
05866    }
05867 
05868    if (chan)
05869       ast_channel_unlock(chan);
05870 
05871    return ret;
05872 }

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

Definition at line 6079 of file pbx.c.

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

06080 {
06081    char *condition, *branch1, *branch2, *branch;
06082    int rc;
06083    char *stringp;
06084 
06085    if (ast_strlen_zero(data)) {
06086       ast_log(LOG_WARNING, "Ignoring, since there is no variable to check\n");
06087       return 0;
06088    }
06089 
06090    stringp = ast_strdupa(data);
06091    condition = strsep(&stringp,"?");
06092    branch1 = strsep(&stringp,":");
06093    branch2 = strsep(&stringp,"");
06094    branch = pbx_checkcondition(condition) ? branch1 : branch2;
06095 
06096    if (ast_strlen_zero(branch)) {
06097       if (option_debug)
06098          ast_log(LOG_DEBUG, "Not taking any branch\n");
06099       return 0;
06100    }
06101 
06102    rc = pbx_builtin_goto(chan, branch);
06103 
06104    return rc;
06105 }

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

Definition at line 5998 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, and VAR_BUF_SIZE.

05999 {
06000    char *name;
06001    char *value;
06002    char *channel;
06003    char tmp[VAR_BUF_SIZE]="";
06004 
06005    if (ast_strlen_zero(data)) {
06006       ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n");
06007       return 0;
06008    }
06009 
06010    value = ast_strdupa(data);
06011    name = strsep(&value,"=");
06012    channel = strsep(&value,"|");
06013    if (channel && value && name) { /*! \todo XXX should do !ast_strlen_zero(..) of the args ? */
06014       struct ast_channel *chan2 = ast_get_channel_by_name_locked(channel);
06015       if (chan2) {
06016          char *s = alloca(strlen(value) + 4);
06017          if (s) {
06018             sprintf(s, "${%s}", value);
06019             pbx_substitute_variables_helper(chan2, s, tmp, sizeof(tmp) - 1);
06020          }
06021          ast_channel_unlock(chan2);
06022       }
06023       pbx_builtin_setvar_helper(chan, name, tmp);
06024    }
06025 
06026    return(0);
06027 }

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

Definition at line 6054 of file pbx.c.

06055 {
06056    return 0;
06057 }

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

Note:
Will lock the channel.

Definition at line 5874 of file pbx.c.

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

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

05875 {
05876    struct ast_var_t *newvariable;
05877    struct varshead *headp;
05878 
05879    if (name[strlen(name)-1] == ')') {
05880       char *function = ast_strdupa(name);
05881 
05882       ast_log(LOG_WARNING, "Cannot push a value onto a function\n");
05883       ast_func_write(chan, function, value);
05884       return;
05885    }
05886 
05887    if (chan) {
05888       ast_channel_lock(chan);
05889       headp = &chan->varshead;
05890    } else {
05891       ast_mutex_lock(&globalslock);
05892       headp = &globals;
05893    }
05894 
05895    if (value) {
05896       if ((option_verbose > 1) && (headp == &globals))
05897          ast_verbose(VERBOSE_PREFIX_2 "Setting global variable '%s' to '%s'\n", name, value);
05898       newvariable = ast_var_assign(name, value);
05899       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
05900    }
05901 
05902    if (chan)
05903       ast_channel_unlock(chan);
05904    else
05905       ast_mutex_unlock(&globalslock);
05906 }

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

Definition at line 6144 of file pbx.c.

References ast_say_character_str(), and ast_channel::language.

06145 {
06146    int res = 0;
06147 
06148    if (data)
06149       res = ast_say_character_str(chan, data, "", chan->language);
06150    return res;
06151 }

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

Definition at line 6162 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(), ast_channel::language, LOG_WARNING, parse(), and pbx_builtin_setvar_helper().

06163 {
06164    int res = 0;
06165    char *parse;
06166    int unixdate = 0;
06167    char charascii[2];
06168 
06169    AST_DECLARE_APP_ARGS(args,
06170       AST_APP_ARG(datestr);
06171       AST_APP_ARG(digits);
06172    );
06173 
06174 
06175    if (ast_strlen_zero(data)) {
06176       ast_log(LOG_WARNING, "SayDate requires an argument (date)\n");
06177       return -1;
06178    }
06179 
06180    if (!(parse = ast_strdupa(data))) {
06181       ast_log(LOG_WARNING, "Memory Error!\n");
06182       return -1;
06183    }
06184 
06185    AST_STANDARD_APP_ARGS(args, parse);
06186 
06187    if (!ast_strlen_zero(args.digits) && (strspn(args.digits, "0123456789*#") != strlen(args.digits))) {
06188       ast_log(LOG_WARNING, "SayDate escape digits must be a subset from '0123456789*#'\n");
06189       args.digits = "";
06190    }
06191 
06192    if (sscanf(args.datestr, "%d", &unixdate) != 1) {
06193       ast_log(LOG_WARNING, "Firt argument to SayDate must be numeric (date)\n");
06194       return -1;
06195    }
06196 
06197    res = ast_say_date(chan, (time_t)unixdate, args.digits, chan->language);
06198    if (res > 0) {
06199       if (isdigit(res) || (res == '*') || (res == '#')) {
06200          snprintf(charascii, 2, "%c", res);
06201          pbx_builtin_setvar_helper(chan, "USER_INPUT", charascii);
06202          res = 0;
06203       } else {
06204          ast_log(LOG_WARNING, "SayDate: invalid return value (%d) detected\n", res);
06205       }
06206    }
06207    return res;
06208 }

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

Definition at line 6135 of file pbx.c.

References ast_say_digit_str(), and ast_channel::language.

06136 {
06137    int res = 0;
06138 
06139    if (data)
06140       res = ast_say_digit_str(chan, data, "", chan->language);
06141    return res;
06142 }

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

Definition at line 6107 of file pbx.c.

References ast_copy_string(), ast_log(), ast_say_number(), ast_strlen_zero(), ast_channel::language, and LOG_WARNING.

06108 {
06109    char tmp[256];
06110    char *number = tmp;
06111    char *options;
06112 
06113    if (ast_strlen_zero(data)) {
06114       ast_log(LOG_WARNING, "SayNumber requires an argument (number)\n");
06115       return -1;
06116    }
06117    ast_copy_string(tmp, data, sizeof(tmp));
06118    strsep(&number, "|");
06119    options = strsep(&number, "|");
06120    if (options) {
06121       if ( strcasecmp(options, "f") && strcasecmp(options,"m") &&
06122          strcasecmp(options, "c") && strcasecmp(options, "n") ) {
06123          ast_log(LOG_WARNING, "SayNumber gender option is either 'f', 'm', 'c' or 'n'\n");
06124          return -1;
06125       }
06126    }
06127 
06128    if (ast_say_number(chan, atoi(tmp), "", chan->language, options)) {
06129       ast_log(LOG_WARNING, "We were unable to say the number %s, is it too large?\n", tmp);
06130    }
06131 
06132    return 0;
06133 }

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

Definition at line 6153 of file pbx.c.

References ast_say_phonetic_str(), and ast_channel::language.

06154 {
06155    int res = 0;
06156 
06157    if (data)
06158       res = ast_say_phonetic_str(chan, data, "", chan->language);
06159    return res;
06160 }

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

Definition at line 6210 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(), ast_channel::language, LOG_WARNING, parse(), and pbx_builtin_setvar_helper().

06211 {
06212    int res = 0;
06213    char *parse;
06214    int secs = 0;
06215    char charascii[2];
06216 
06217    AST_DECLARE_APP_ARGS(args,
06218       AST_APP_ARG(timestr);
06219       AST_APP_ARG(digits);
06220    );
06221 
06222    if (ast_strlen_zero(data)) {
06223       ast_log(LOG_WARNING, "SayTime requires an argument (time in seconds)\n");
06224       return -1;
06225    }
06226 
06227    if (!(parse = ast_strdupa(data))) {
06228       ast_log(LOG_WARNING, "Memory Error!\n");
06229       return -1;
06230    }
06231 
06232    AST_STANDARD_APP_ARGS(args, parse);
06233 
06234    if (!ast_strlen_zero(args.digits) && (strspn(args.digits, "0123456789*#") != strlen(args.digits))) {
06235       ast_log(LOG_WARNING, "SayTime escape digits must be a subset from '0123456789*#'\n");
06236       args.digits = "";
06237    }
06238 
06239    if (sscanf(args.timestr, "%d", &secs) != 1) {
06240       ast_log(LOG_WARNING, "Firt argument to SayTime must be numeric (time in seconds)\n");
06241       return -1;
06242    }
06243 
06244    res = ast_say_time(chan, (time_t)secs, args.digits, chan->language);
06245    if (res > 0) {
06246       if (isdigit(res) || (res == '*') || (res == '#')) {
06247          snprintf(charascii, 2, "%c", res);
06248          pbx_builtin_setvar_helper(chan, "USER_INPUT", charascii);
06249          res = 0;
06250       } else {
06251          ast_log(LOG_WARNING, "SayTime: invalid return value (%d) detected\n", res);
06252       }
06253    }
06254    return res;
06255 }

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

Note:
Will lock the channel.

Definition at line 5805 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(), ast_var_t::entries, LOG_ERROR, total, var, and ast_channel::varshead.

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

05806 {
05807    struct ast_var_t *variables;
05808    const char *var, *val;
05809    int total = 0;
05810 
05811    if (!chan)
05812       return 0;
05813 
05814    memset(buf, 0, size);
05815 
05816    ast_channel_lock(chan);
05817 
05818    AST_LIST_TRAVERSE(&chan->varshead, variables, entries) {
05819       if ((var=ast_var_name(variables)) && (val=ast_var_value(variables))
05820          /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */
05821          ) {
05822          if (ast_build_string(&buf, &size, "%s=%s\n", var, val)) {
05823             ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
05824             break;
05825          } else
05826             total++;
05827       } else
05828          break;
05829    }
05830 
05831    ast_channel_unlock(chan);
05832 
05833    return total;
05834 }

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

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

06031 {
06032    char *name;
06033    char *stringp = data;
06034    static int dep_warning = 0;
06035 
06036    if (ast_strlen_zero(data)) {
06037       ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n");
06038       return 0;
06039    }
06040 
06041    name = strsep(&stringp, "=");
06042 
06043    if (!dep_warning) {
06044       dep_warning = 1;
06045       ast_log(LOG_WARNING, "SetGlobalVar is deprecated.  Please use Set(GLOBAL(%s)=%s) instead.\n", name, stringp);
06046    }
06047 
06048    /*! \todo XXX watch out, leading whitespace ? */
06049    pbx_builtin_setvar_helper(NULL, name, stringp);
06050 
06051    return(0);
06052 }

int pbx_builtin_setvar ( struct ast_channel ,
void *   
)

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

05959 {
05960    char *name, *value, *mydata;
05961    int argc;
05962    char *argv[24];      /* this will only support a maximum of 24 variables being set in a single operation */
05963    int global = 0;
05964    int x;
05965 
05966    if (ast_strlen_zero(data)) {
05967       ast_log(LOG_WARNING, "Set requires at least one variable name/value pair.\n");
05968       return 0;
05969    }
05970 
05971    mydata = ast_strdupa(data);
05972    argc = ast_app_separate_args(mydata, '|', argv, sizeof(argv) / sizeof(argv[0]));
05973 
05974    /* check for a trailing flags argument */
05975    if ((argc > 1) && !strchr(argv[argc-1], '=')) {
05976       argc--;
05977       if (strchr(argv[argc], 'g')) {
05978          ast_log(LOG_WARNING, "The use of the 'g' flag is deprecated.  Please use Set(GLOBAL(foo)=bar) instead\n");
05979          global = 1;
05980       }
05981    }
05982 
05983    if (argc > 1)
05984       ast_log(LOG_WARNING, "Setting multiple variables at once within Set is deprecated.  Please separate each name/value pair into its own line.\n");
05985 
05986    for (x = 0; x < argc; x++) {
05987       name = argv[x];
05988       if ((value = strchr(name, '='))) {
05989          *value++ = '\0';
05990          pbx_builtin_setvar_helper((global) ? NULL : chan, name, value);
05991       } else
05992          ast_log(LOG_WARNING, "Ignoring entry '%s' with no = (and not last 'options' entry)\n", name);
05993    }
05994 
05995    return(0);
05996 }

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

Note:
Will lock the channel.

Definition at line 5908 of file pbx.c.

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

Referenced by __oh323_new(), _macro_exec(), _while_exec(), acf_odbc_read(), acf_odbc_write(), action_setvar(), agi_exec_full(), aji_status_exec(), aqm_exec(), array(), ast_bridge_call(), ast_feature_request_and_dial(), ast_iax2_new(), ast_monitor_start(), ast_pbx_outgoing_exten(), ast_set_variables(), background_detect_exec(), builtin_automonitor(), builtin_blindtransfer(), cb_events(), chanavail_exec(), controlplayback_exec(), count_exec(), dahdi_handle_dtmfup(), dahdi_new(), disa_exec(), do_waiting(), end_bridge_callback(), export_aoc_vars(), export_ch(), function_db_delete(), function_db_exists(), function_db_read(), global_write(), handle_request_bye(), handle_request_refer(), handle_set_global(), handle_set_global_deprecated(), handle_setvariable(), hasvoicemail_exec(), isAnsweringMachine(), leave_voicemail(), local_hangup(), lookupblacklist_exec(), macro_fixup(), misdn_call(), mixmonitor_exec(), ospauth_exec(), ospfinished_exec(), osplookup_exec(), ospnext_exec(), 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(), privacy_exec(), process_ast_dsp(), read_exec(), readfile_exec(), realtime_exec(), realtime_update_exec(), record_exec(), return_exec(), rqm_exec(), sendimage_exec(), sendtext_exec(), sendurl_exec(), set(), set_agentbycallerid(), set_queue_result(), sip_addheader(), sip_hangup(), sip_new(), sla_calc_trunk_timeouts(), sla_station_exec(), sla_trunk_exec(), socket_process(), speech_create(), ss_thread(), start_monitor_exec(), system_exec_helper(), transfer_exec(), tryexec_exec(), update_bridgepeer(), upqm_exec(), vm_box_exists(), vm_exec(), and vmauthenticate().

05909 {
05910    struct ast_var_t *newvariable;
05911    struct varshead *headp;
05912    const char *nametail = name;
05913 
05914    if (name[strlen(name)-1] == ')') {
05915       char *function = ast_strdupa(name);
05916 
05917       ast_func_write(chan, function, value);
05918       return;
05919    }
05920 
05921    if (chan) {
05922       ast_channel_lock(chan);
05923       headp = &chan->varshead;
05924    } else {
05925       ast_mutex_lock(&globalslock);
05926       headp = &globals;
05927    }
05928 
05929    /* For comparison purposes, we have to strip leading underscores */
05930    if (*nametail == '_') {
05931       nametail++;
05932       if (*nametail == '_')
05933          nametail++;
05934    }
05935 
05936    AST_LIST_TRAVERSE (headp, newvariable, entries) {
05937       if (strcasecmp(ast_var_name(newvariable), nametail) == 0) {
05938          /* there is already such a variable, delete it */
05939          AST_LIST_REMOVE(headp, newvariable, entries);
05940          ast_var_delete(newvariable);
05941          break;
05942       }
05943    }
05944 
05945    if (value) {
05946       if ((option_verbose > 1) && (headp == &globals))
05947          ast_verbose(VERBOSE_PREFIX_2 "Setting global variable '%s' to '%s'\n", name, value);
05948       newvariable = ast_var_assign(name, value);
05949       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
05950    }
05951 
05952    if (chan)
05953       ast_channel_unlock(chan);
05954    else
05955       ast_mutex_unlock(&globalslock);
05956 }

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

06070 {
06071    if (ast_strlen_zero(condition))  /* NULL or empty strings are false */
06072       return 0;
06073    else if (*condition >= '0' && *condition <= '9')   /* Numbers are evaluated for truth */
06074       return atoi(condition);
06075    else  /* Strings are true */
06076       return 1;
06077 }

static void pbx_destroy ( struct ast_pbx p  )  [static]

Definition at line 611 of file pbx.c.

References free.

00612 {
00613    free(p);
00614 }

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

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

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

00540 {
00541    int res;
00542 
00543    const char *saved_c_appl;
00544    const char *saved_c_data;
00545 
00546    if (c->cdr && !ast_check_hangup(c))
00547       ast_cdr_setapp(c->cdr, app->name, data);
00548 
00549    /* save channel values */
00550    saved_c_appl= c->appl;
00551    saved_c_data= c->data;
00552 
00553    c->appl = app->name;
00554    c->data = data;
00555    /* XXX remember what to to when we have linked apps to modules */
00556    if (app->module) {
00557       /* XXX LOCAL_USER_ADD(app->module) */
00558    }
00559    res = app->execute(c, S_OR(data, ""));
00560    if (app->module) {
00561       /* XXX LOCAL_USER_REMOVE(app->module) */
00562    }
00563    /* restore channel values */
00564    c->appl = saved_c_appl;
00565    c->data = saved_c_data;
00566    return res;
00567 }

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 1833 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, ast_channel::name, option_debug, option_verbose, pbx_exec(), pbx_find_extension(), pbx_findapp(), pbx_substitute_variables(), ast_channel::priority, ast_exten::priority, pbx_find_info::stacklen, pbx_find_info::status, STATUS_NO_CONTEXT, STATUS_NO_EXTENSION, STATUS_NO_LABEL, STATUS_NO_PRIORITY, pbx_find_info::swo, term_color(), ast_channel::uniqueid, 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().

01836 {
01837    struct ast_exten *e;
01838    struct ast_app *app;
01839    int res;
01840    struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */
01841    char passdata[EXT_DATA_SIZE];
01842 
01843    int matching_action = (action == E_MATCH || action == E_CANMATCH || action == E_MATCHMORE);
01844 
01845    ast_rdlock_contexts();
01846    e = pbx_find_extension(c, con, &q, context, exten, priority, label, callerid, action);
01847    if (e) {
01848       if (matching_action) {
01849          ast_unlock_contexts();
01850          return -1;  /* success, we found it */
01851       } else if (action == E_FINDLABEL) { /* map the label to a priority */
01852          res = e->priority;
01853          ast_unlock_contexts();
01854          return res; /* the priority we were looking for */
01855       } else { /* spawn */
01856          app = pbx_findapp(e->app);
01857          ast_unlock_contexts();
01858          if (!app) {
01859             ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority);
01860             return -1;
01861          }
01862          if (c->context != context)
01863             ast_copy_string(c->context, context, sizeof(c->context));
01864          if (c->exten != exten)
01865             ast_copy_string(c->exten, exten, sizeof(c->exten));
01866          c->priority = priority;
01867          pbx_substitute_variables(passdata, sizeof(passdata), c, e);
01868          if (option_debug) {
01869             ast_log(LOG_DEBUG, "Launching '%s'\n", app->name);
01870          }
01871          if (option_verbose > 2) {
01872             char tmp[80], tmp2[80], tmp3[EXT_DATA_SIZE];
01873             ast_verbose( VERBOSE_PREFIX_3 "Executing [%s@%s:%d] %s(\"%s\", \"%s\") %s\n",
01874                exten, context, priority,
01875                term_color(tmp, app->name, COLOR_BRCYAN, 0, sizeof(tmp)),
01876                term_color(tmp2, c->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)),
01877                term_color(tmp3, passdata, COLOR_BRMAGENTA, 0, sizeof(tmp3)),
01878                "in new stack");
01879          }
01880          manager_event(EVENT_FLAG_CALL, "Newexten",
01881                "Channel: %s\r\n"
01882                "Context: %s\r\n"
01883                "Extension: %s\r\n"
01884                "Priority: %d\r\n"
01885                "Application: %s\r\n"
01886                "AppData: %s\r\n"
01887                "Uniqueid: %s\r\n",
01888                c->name, c->context, c->exten, c->priority, app->name, passdata, c->uniqueid);
01889          return pbx_exec(c, app, passdata);  /* 0 on success, -1 on failure */
01890       }
01891    } else if (q.swo) {  /* not found here, but in another switch */
01892       ast_unlock_contexts();
01893       if (matching_action) {
01894          return -1;
01895       } else {
01896          if (!q.swo->exec) {
01897             ast_log(LOG_WARNING, "No execution engine for switch %s\n", q.swo->name);
01898             res = -1;
01899          }
01900          return q.swo->exec(c, q.foundcontext ? q.foundcontext : context, exten, priority, callerid, q.data);
01901       }
01902    } else { /* not found anywhere, see what happened */
01903       ast_unlock_contexts();
01904       switch (q.status) {
01905       case STATUS_NO_CONTEXT:
01906          if (!matching_action)
01907             ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", context);
01908          break;
01909       case STATUS_NO_EXTENSION:
01910          if (!matching_action)
01911             ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, context);
01912          break;
01913       case STATUS_NO_PRIORITY:
01914          if (!matching_action)
01915             ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, context);
01916          break;
01917       case STATUS_NO_LABEL:
01918          if (context)
01919             ast_log(LOG_NOTICE, "No such label '%s' in extension '%s' in context '%s'\n", label, exten, context);
01920          break;
01921       default:
01922          if (option_debug)
01923             ast_log(LOG_DEBUG, "Shouldn't happen!\n");
01924       }
01925 
01926       return (matching_action) ? 0 : -1;
01927    }
01928 }

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

Definition at line 967 of file pbx.c.

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

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

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

struct ast_app* pbx_findapp ( const char *  app  ) 

Look up an application.

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

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

Definition at line 575 of file pbx.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_sw::list, and ast_app::name.

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

00576 {
00577    struct ast_app *tmp;
00578 
00579    AST_LIST_LOCK(&apps);
00580    AST_LIST_TRAVERSE(&apps, tmp, list) {
00581       if (!strcasecmp(tmp->name, app))
00582          break;
00583    }
00584    AST_LIST_UNLOCK(&apps);
00585 
00586    return tmp;
00587 }

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

Definition at line 589 of file pbx.c.

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

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

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 1174 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, globals, globalslock, ast_channel::hangupcause, ast_channel::name, offset, parse_variable_name(), ast_channel::priority, s, substring(), and ast_channel::uniqueid.

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

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

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

References autofallthrough.

Referenced by pbx_load_module().

02686 {
02687    int oldval = autofallthrough;
02688    autofallthrough = newval;
02689    return oldval;
02690 }

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

Definition at line 1804 of file pbx.c.

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

Referenced by pbx_extension_helper().

01805 {
01806    memset(passdata, 0, datalen);
01807 
01808    /* No variables or expressions in e->data, so why scan it? */
01809    if (e->data && !strchr(e->data, '$') && !strstr(e->data,"${") && !strstr(e->data,"$[") && !strstr(e->data,"$(")) {
01810       ast_copy_string(passdata, e->data, datalen);
01811       return;
01812    }
01813 
01814    pbx_substitute_variables_helper(c, e->data, passdata, datalen - 1);
01815 }

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

Definition at line 1794 of file pbx.c.

References pbx_substitute_variables_helper_full(), and ast_channel::varshead.

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

01795 {
01796    pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count);
01797 }

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

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

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

Definition at line 1799 of file pbx.c.

References pbx_substitute_variables_helper_full().

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

01800 {
01801    pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count);
01802 }

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

Definition at line 2615 of file pbx.c.

References __ast_pbx_run(), and decrease_call_count().

Referenced by ast_pbx_start().

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

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

helper function to print an extension

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

03512 {
03513    int prio = ast_get_extension_priority(e);
03514    if (prio == PRIORITY_HINT) {
03515       snprintf(buf, buflen, "hint: %s",
03516          ast_get_extension_app(e));
03517    } else {
03518       snprintf(buf, buflen, "%d. %s(%s)",
03519          prio, ast_get_extension_app(e),
03520          (!ast_strlen_zero(ast_get_extension_app_data(e)) ? (char *)ast_get_extension_app_data(e) : ""));
03521    }
03522 }

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

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

02314 {
02315    ast_channel_lock(c);
02316    ast_copy_string(c->exten, exten, sizeof(c->exten));
02317    c->priority = pri;
02318    ast_channel_unlock(c);
02319 }

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

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

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

References ast_copy_string().

Referenced by pbx_retrieve_variable(), and pbx_substitute_variables_helper_full().

01137 {
01138    char *ret = workspace;
01139    int lr;  /* length of the input string after the copy */
01140 
01141    ast_copy_string(workspace, value, workspace_len); /* always make a copy */
01142 
01143    lr = strlen(ret); /* compute length after copy, so we never go out of the workspace */
01144 
01145    /* Quick check if no need to do anything */
01146    if (offset == 0 && length >= lr) /* take the whole string */
01147       return ret;
01148 
01149    if (offset < 0)   {  /* translate negative offset into positive ones */
01150       offset = lr + offset;
01151       if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */
01152          offset = 0;
01153    }
01154 
01155    /* too large offset result in empty string so we know what to return */
01156    if (offset >= lr)
01157       return ret + lr;  /* the final '\0' */
01158 
01159    ret += offset;    /* move to the start position */
01160    if (length >= 0 && length < lr - offset)  /* truncate if necessary */
01161       ret[length] = '\0';
01162    else if (length < 0) {
01163       if (lr > offset - length) /* After we remove from the front and from the rear, is there anything left? */
01164          ret[lr + length - offset] = '\0';
01165       else
01166          ret[0] = '\0';
01167    }
01168 
01169    return ret;
01170 }

static void switch_data_init ( void   )  [static]

Definition at line 108 of file pbx.c.

00111 : An extension

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

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

05400 {
05401    int res;
05402    struct ast_frame *f;
05403    int waittime;
05404 
05405    if (ast_strlen_zero(data) || (sscanf(data, "%30d", &waittime) != 1) || (waittime < 0))
05406       waittime = -1;
05407    if (waittime > -1) {
05408       ast_safe_sleep(chan, waittime * 1000);
05409    } else do {
05410       res = ast_waitfor(chan, -1);
05411       if (res < 0)
05412          return;
05413       f = ast_read(chan);
05414       if (f)
05415          ast_frfree(f);
05416    } while(f);
05417 }


Variable Documentation

int autofallthrough = 1 [static]

Definition at line 246 of file pbx.c.

Referenced by pbx_set_autofallthrough().

struct ast_app_option background_opts[128] = { [ 's' ] = { .flag = (1 << 0) }, [ 'n' ] = { .flag = (1 << 1) }, [ 'm' ] = { .flag = (1 << 2) }, [ 'p' ] = { .flag = (1 << 3) },} [static]

Definition at line 98 of file pbx.c.

Referenced by pbx_builtin_background().

struct pbx_builtin builtins[] [static]

Declaration of builtin applications.

struct ast_cli_entry cli_set_global_deprecated [static]

Initial value:

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

Definition at line 3835 of file pbx.c.

struct ast_cli_entry cli_show_application_deprecated [static]

Initial value:

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

Definition at line 3825 of file pbx.c.

struct ast_cli_entry cli_show_applications_deprecated [static]

Initial value:

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

Definition at line 3795 of file pbx.c.

struct ast_cli_entry cli_show_dialplan_deprecated [static]

Initial value:

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

Definition at line 3830 of file pbx.c.

struct ast_cli_entry cli_show_function_deprecated [static]

Initial value:

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

Definition at line 3820 of file pbx.c.

struct ast_cli_entry cli_show_functions_deprecated [static]

Initial value:

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

Definition at line 3800 of file pbx.c.

struct ast_cli_entry cli_show_globals_deprecated [static]

Initial value:

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

Definition at line 3815 of file pbx.c.

struct ast_cli_entry cli_show_hints_deprecated [static]

Initial value:

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

Definition at line 3810 of file pbx.c.

struct ast_cli_entry cli_show_switches_deprecated [static]

Initial value:

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

Definition at line 3805 of file pbx.c.

ast_rwlock_t conlock = PTHREAD_RWLOCK_INITIALIZER [static]

Lock for the ast_context list

Definition at line 518 of file pbx.c.

Referenced by ast_lock_contexts(), ast_rdlock_contexts(), ast_unlock_contexts(), and ast_wrlock_contexts().

struct ast_context* contexts [static]

Definition at line 517 of file pbx.c.

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

int countcalls [static]

Definition at line 249 of file pbx.c.

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

char* days[] [static]

Definition at line 4245 of file pbx.c.

Referenced by ast_build_timing().

struct cfextension_states extension_states[] [static]

Referenced by ast_extension_state2str().

struct varshead globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE [static]

Definition at line 244 of file pbx.c.

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

ast_mutex_t globalslock = { PTHREAD_MUTEX_INITIALIZER , 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, PTHREAD_MUTEX_INITIALIZER } [static]

Definition at line 243 of file pbx.c.

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

ast_mutex_t maxcalllock = { PTHREAD_MUTEX_INITIALIZER , 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, PTHREAD_MUTEX_INITIALIZER } [static]

Definition at line 248 of file pbx.c.

Referenced by decrease_call_count(), and increase_call_count().

char* months[] [static]

Definition at line 4257 of file pbx.c.

Referenced by ast_build_timing().

struct ast_cli_entry pbx_cli[] [static]

Definition at line 3840 of file pbx.c.

Referenced by load_pbx().

struct ast_app_option resetcdr_opts[128] = { [ 'w' ] = { .flag = (1 << 1) }, [ 'a' ] = { .flag = (1 << 2) }, [ 'v' ] = { .flag = (1 << 0) },} [static]

Definition at line 5494 of file pbx.c.

Referenced by pbx_builtin_resetcdr().

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 3088 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 3076 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 3054 of file pbx.c.

char show_dialplan_help[] [static]

Initial value:

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

Definition at line 3084 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 3080 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 3060 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 3072 of file pbx.c.

char show_hints_help[] [static]

Initial value:

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

Definition at line 3068 of file pbx.c.

char show_switches_help[] [static]

Initial value:

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

Definition at line 3064 of file pbx.c.

struct ast_state_cb* statecbs

Definition at line 532 of file pbx.c.

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

int stateid = 1 [static]

Definition at line 524 of file pbx.c.

struct ast_threadstorage switch_data = { .once = PTHREAD_ONCE_INIT, .key_init = switch_data_init , } [static]

Definition at line 108 of file pbx.c.

int totalcalls [static]

Definition at line 250 of file pbx.c.

Referenced by ast_processed_calls(), increase_call_count(), and timing_read().

struct ast_app_option waitexten_opts[128] = { [ 'm' ] = { .flag = (1 << 0) , .arg_index = 0 + 1 },} [static]

Definition at line 104 of file pbx.c.

Referenced by pbx_builtin_waitexten().


Generated on Thu Oct 1 13:10:10 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7