Sat Mar 24 23:29:52 2007

Asterisk developer's documentation


pbx.c File Reference

Core PBX routines. More...

#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 "asterisk.h"
#include "asterisk/lock.h"
#include "asterisk/cli.h"
#include "asterisk/pbx.h"
#include "asterisk/channel.h"
#include "asterisk/options.h"
#include "asterisk/logger.h"
#include "asterisk/file.h"
#include "asterisk/callerid.h"
#include "asterisk/cdr.h"
#include "asterisk/config.h"
#include "asterisk/term.h"
#include "asterisk/manager.h"
#include "asterisk/ast_expr.h"
#include "asterisk/linkedlists.h"
#include "asterisk/say.h"
#include "asterisk/utils.h"
#include "asterisk/causes.h"
#include "asterisk/musiconhold.h"
#include "asterisk/app.h"
#include "asterisk/devicestate.h"
#include "asterisk/compat.h"

Include dependency graph for pbx.c:

Go to the source code of this file.

Data Structures

struct  app_tmp
struct  ast_app
 ast_app: A registered application More...
struct  ast_context
 ast_context: An extension context More...
struct  ast_exten
 ast_exten: An extension The dialplan is saved as a linked list with each context having it's own linked list of extensions - one item per priority. More...
struct  ast_hint
 Structure for dial plan hints. More...
struct  ast_ignorepat
 ast_ignorepat: Ignore patterns in dial plan More...
struct  ast_include
 ast_include: include= support in extensions.conf More...
struct  ast_state_cb
 ast_state_cb: An extension state notify register item More...
struct  ast_sw
 ast_sw: Switch statement in extensions.conf More...
struct  async_stat
struct  dialplan_counters
struct  pbx_builtin
 Declaration of builtin applications. More...
struct  store_hint

Defines

#define AST_PBX_MAX_STACK   128
#define BACKGROUND_MATCHEXTEN   (1 << 2)
#define BACKGROUND_NOANSWER   (1 << 1)
#define BACKGROUND_PLAYBACK   (1 << 3)
#define BACKGROUND_SKIP   (1 << 0)
#define DONT_HAVE_LENGTH   0x80000000
#define EXT_DATA_SIZE   8192
#define EXTENSION_MATCH_CORE(data, pattern, match)
#define FIND_NEXT
#define HELPER_CANMATCH   3
#define HELPER_EXEC   2
#define HELPER_EXISTS   0
#define HELPER_FINDLABEL   5
#define HELPER_MATCHMORE   4
#define HELPER_SPAWN   1
#define LOG
#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)

Functions

void __ast_context_destroy (struct ast_context *con, const char *registrar)
static int __ast_goto_if_exists (struct ast_channel *chan, char *context, char *exten, int priority, int async)
static int __ast_pbx_run (struct ast_channel *c)
int ast_active_calls (void)
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)
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)
static int ast_add_hint (struct ast_exten *e)
 ast_add_hint: Add hint to hint list, check initial extension state
 AST_APP_OPTIONS (resetcdr_opts,{AST_APP_OPTION('w', AST_CDR_FLAG_POSTED), AST_APP_OPTION('a', AST_CDR_FLAG_LOCKED), AST_APP_OPTION('v', AST_CDR_FLAG_KEEP_VARS),})
 AST_APP_OPTIONS (waitexten_opts,{AST_APP_OPTION_ARG('m', WAITEXTEN_MOH, 1),})
 AST_APP_OPTIONS (background_opts,{AST_APP_OPTION('s', BACKGROUND_SKIP), AST_APP_OPTION('n', BACKGROUND_NOANSWER), AST_APP_OPTION('m', BACKGROUND_MATCHEXTEN), AST_APP_OPTION('p', BACKGROUND_PLAYBACK),})
int ast_async_goto (struct ast_channel *chan, const char *context, const char *exten, int priority)
int ast_async_goto_by_name (const char *channame, const char *context, const char *exten, int priority)
int ast_async_goto_if_exists (struct ast_channel *chan, char *context, char *exten, int priority)
int ast_build_timing (struct ast_timing *i, char *info_in)
int ast_canmatch_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
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 (struct ast_timing *i)
int ast_context_add_ignorepat (const char *con, const char *value, const char *registrar)
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)
int ast_context_add_include2 (struct ast_context *con, const char *value, const char *registrar)
int ast_context_add_switch (const char *context, const char *sw, const char *data, int eval, const char *registrar)
int ast_context_add_switch2 (struct ast_context *con, const char *value, const char *data, int eval, const char *registrar)
ast_contextast_context_create (struct ast_context **extcontexts, const char *name, const char *registrar)
void ast_context_destroy (struct ast_context *con, const char *registrar)
ast_contextast_context_find (const char *name)
int ast_context_remove_extension (const char *context, const char *extension, int priority, const char *registrar)
int ast_context_remove_extension2 (struct ast_context *con, const char *extension, int priority, const char *registrar)
 This functionc locks given context, search for the right extension and fires out all peer in this extensions with given priority. If priority is set to 0, all peers are removed. After that, unlock context and return.
int ast_context_remove_ignorepat (const char *context, const char *ignorepat, const char *registrar)
int ast_context_remove_ignorepat2 (struct ast_context *con, const char *ignorepat, const char *registrar)
int ast_context_remove_include (const char *context, const char *include, const char *registrar)
int ast_context_remove_include2 (struct ast_context *con, const char *include, const char *registrar)
int ast_context_remove_switch (const char *context, const char *sw, const char *data, const char *registrar)
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_verify_includes (struct ast_context *con)
ast_custom_functionast_custom_function_find (char *name)
int ast_custom_function_register (struct ast_custom_function *acf)
int ast_custom_function_unregister (struct ast_custom_function *acf)
int ast_exec_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
int ast_exists_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
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)
int ast_extension_state (struct ast_channel *c, char *context, char *exten)
 ast_extension_state: Check extension state for an extension by using hint
static int ast_extension_state2 (struct ast_exten *e)
 ast_extensions_state2: Check state of extension by using hints
const char * ast_extension_state2str (int extension_state)
 ast_extension_state2str: Return extension_state as string
int ast_extension_state_add (const char *context, const char *exten, ast_state_cb_type callback, void *data)
 ast_extension_state_add: Add watcher for extension states
int ast_extension_state_del (int id, ast_state_cb_type callback)
 ast_extension_state_del: Remove a watcher from the callback list
int ast_findlabel_extension (struct ast_channel *c, const char *context, const char *exten, const char *label, const char *callerid)
int ast_findlabel_extension2 (struct ast_channel *c, struct ast_context *con, const char *exten, const char *label, const char *callerid)
char * ast_func_read (struct ast_channel *chan, const char *in, char *workspace, size_t len)
void ast_func_write (struct ast_channel *chan, const char *in, const char *value)
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)
const char * ast_get_extension_label (struct ast_exten *exten)
int ast_get_extension_matchcid (struct ast_exten *e)
const char * ast_get_extension_name (struct ast_exten *exten)
int ast_get_extension_priority (struct ast_exten *exten)
const char * ast_get_extension_registrar (struct ast_exten *e)
int ast_get_hint (char *hint, int hintsize, char *name, int namesize, struct ast_channel *c, const char *context, const char *exten)
 ast_get_hint: Get hint for channel
const char * ast_get_ignorepat_name (struct ast_ignorepat *ip)
const char * ast_get_ignorepat_registrar (struct ast_ignorepat *ip)
const char * ast_get_include_name (struct ast_include *inc)
const char * ast_get_include_registrar (struct ast_include *i)
const char * ast_get_switch_data (struct ast_sw *sw)
const char * ast_get_switch_name (struct ast_sw *sw)
const char * ast_get_switch_registrar (struct ast_sw *sw)
int ast_goto_if_exists (struct ast_channel *chan, char *context, 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)
 AST_LIST_HEAD (store_hints, store_hint)
int ast_lock_context (struct ast_context *con)
int ast_lock_contexts ()
int ast_matchmore_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
void ast_merge_contexts_and_delete (struct ast_context **extcontexts, const char *registrar)
 AST_MUTEX_DEFINE_STATIC (hintlock)
 AST_MUTEX_DEFINE_STATIC (switchlock)
 AST_MUTEX_DEFINE_STATIC (applock)
 AST_MUTEX_DEFINE_STATIC (conlock)
 AST_MUTEX_DEFINE_STATIC (acflock)
 AST_MUTEX_DEFINE_STATIC (maxcalllock)
 AST_MUTEX_DEFINE_STATIC (globalslock)
int ast_parseable_goto (struct ast_channel *chan, const char *goto_string)
int ast_pbx_outgoing_app (const char *type, int format, void *data, int timeout, const char *app, const char *appdata, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel)
int ast_pbx_outgoing_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)
static void * ast_pbx_run_app (void *data)
enum ast_pbx_result ast_pbx_start (struct ast_channel *c)
int ast_register_application (const char *app, int(*execute)(struct ast_channel *, void *), const char *synopsis, const char *description)
 Dynamically register a new dial plan application.
int ast_register_switch (struct ast_switch *sw)
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)
int ast_unlock_context (struct ast_context *con)
int ast_unlock_contexts ()
int ast_unregister_application (const char *app)
void ast_unregister_switch (struct ast_switch *sw)
ast_extenast_walk_context_extensions (struct ast_context *con, struct ast_exten *exten)
ast_ignorepatast_walk_context_ignorepats (struct ast_context *con, struct ast_ignorepat *ip)
ast_includeast_walk_context_includes (struct ast_context *con, struct ast_include *inc)
ast_swast_walk_context_switches (struct ast_context *con, struct ast_sw *sw)
ast_contextast_walk_contexts (struct ast_context *con)
ast_extenast_walk_extension_priorities (struct ast_exten *exten, struct ast_exten *priority)
static void * async_wait (void *data)
static char * complete_show_application (char *line, char *word, int pos, int state)
static char * complete_show_applications (char *line, char *word, int pos, int state)
static char * complete_show_dialplan_context (char *line, char *word, int pos, int state)
static char * complete_show_function (char *line, char *word, int pos, int state)
static void decrease_call_count (void)
static void destroy_exten (struct ast_exten *e)
static int ext_strncpy (char *dst, const char *src, int len)
static unsigned int get_day (char *day)
static unsigned int get_dow (char *dow)
 get_dow: Get day of week
static unsigned int get_month (char *mon)
static void get_timerange (struct ast_timing *i, char *times)
static int handle_show_application (int fd, int argc, char *argv[])
static int handle_show_applications (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_functions (int fd, int argc, char *argv[])
static int handle_show_hints (int fd, int argc, char *argv[])
 handle_show_hints: CLI support for listing registred dial plan hints
static int handle_show_switches (int fd, int argc, char *argv[])
 handle_show_switches: CLI support for listing registred dial plan switches
static int include_valid (struct ast_include *i)
static int increase_call_count (const struct ast_channel *c)
int load_pbx (void)
static int matchcid (const char *cidpattern, const char *callerid)
static void null_datad (void *foo)
static int parse_variable_name (char *var, int *offset, int *length, int *isfunc)
static int pbx_builtin_answer (struct ast_channel *, void *)
static int pbx_builtin_atimeout (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_dtimeout (struct ast_channel *, void *)
static int pbx_builtin_execiftime (struct ast_channel *, void *)
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_rtimeout (struct ast_channel *, void *)
static int pbx_builtin_saycharacters (struct ast_channel *, void *)
static int pbx_builtin_saydigits (struct ast_channel *, void *)
static int pbx_builtin_saynumber (struct ast_channel *, void *)
static int pbx_builtin_sayphonetic (struct ast_channel *, void *)
int pbx_builtin_serialize_variables (struct ast_channel *chan, char *buf, size_t size)
static int pbx_builtin_setaccount (struct ast_channel *, void *)
static int pbx_builtin_setamaflags (struct ast_channel *, void *)
static int pbx_builtin_setglobalvar (struct ast_channel *, void *)
static int pbx_builtin_setlanguage (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_setvar_old (struct ast_channel *, void *)
static int pbx_builtin_wait (struct ast_channel *, void *)
static int pbx_builtin_waitexten (struct ast_channel *, void *)
int pbx_checkcondition (char *condition)
static void pbx_destroy (struct ast_pbx *p)
int pbx_exec (struct ast_channel *c, struct ast_app *app, void *data, int newstack)
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, int action)
static struct ast_extenpbx_find_extension (struct ast_channel *chan, struct ast_context *bypass, const char *context, const char *exten, int priority, const char *label, const char *callerid, int action, char *incstack[], int *stacklen, int *status, struct ast_switch **swo, char **data, const char **foundcontext)
ast_apppbx_findapp (const char *app)
 Find application handle in linked list.
static struct ast_switchpbx_findswitch (const char *sw)
void pbx_retrieve_variable (struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp)
 pbx_retrieve_variable: Support for Asterisk built-in variables and functions in the dialplan ---
int pbx_set_autofallthrough (int newval)
static void pbx_substitute_variables (char *passdata, int datalen, struct ast_channel *c, struct ast_exten *e)
void pbx_substitute_variables_helper (struct ast_channel *c, const char *cp1, char *cp2, int count)
static void pbx_substitute_variables_helper_full (struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count)
void pbx_substitute_variables_varshead (struct varshead *headp, const char *cp1, char *cp2, int count)
static void * pbx_thread (void *data)
static int show_dialplan_helper (int fd, char *context, char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude, int includecount, char *includes[])
static char * substring (const char *value, int offset, int length, char *workspace, size_t workspace_len)
 takes a substring. It is ok to call with value == workspace.
static void wait_for_hangup (struct ast_channel *chan, void *data)

Variables

static struct ast_custom_functionacf_root = NULL
static struct ast_appapps = NULL
static int autofallthrough = 0
static struct pbx_builtin builtins []
 Declaration of builtin applications.
static struct ast_contextcontexts = NULL
static int countcalls = 0
static char * days []
static struct varshead globals
ast_hinthints = NULL
static char * months []
static struct ast_cli_entry pbx_cli []
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_hints_help []
static char show_switches_help []
ast_state_cbstatecbs = NULL
static int stateid = 1
ast_switchswitches = NULL


Detailed Description

Core PBX routines.

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

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

#define BACKGROUND_MATCHEXTEN   (1 << 2)
 

Definition at line 87 of file pbx.c.

Referenced by pbx_builtin_background().

#define BACKGROUND_NOANSWER   (1 << 1)
 

Definition at line 86 of file pbx.c.

Referenced by pbx_builtin_background().

#define BACKGROUND_PLAYBACK   (1 << 3)
 

Definition at line 88 of file pbx.c.

Referenced by pbx_builtin_background().

#define BACKGROUND_SKIP   (1 << 0)
 

Definition at line 85 of file pbx.c.

Referenced by pbx_builtin_background().

#define DONT_HAVE_LENGTH   0x80000000
 

Definition at line 903 of file pbx.c.

Referenced by parse_variable_name().

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

Referenced by pbx_extension_helper(), and realtime_exec().

#define EXTENSION_MATCH_CORE data,
pattern,
match   ) 
 

Definition at line 625 of file pbx.c.

Referenced by ast_extension_close(), and ast_extension_match().

#define FIND_NEXT
 

Value:

do { \
   c = info; \
   while(*c && (*c != '|')) c++; \
   if (*c) { *c = '\0'; c++; } else c = NULL; \
} while(0)

Definition at line 3830 of file pbx.c.

Referenced by ast_build_timing().

#define HELPER_CANMATCH   3
 

Definition at line 570 of file pbx.c.

Referenced by ast_canmatch_extension(), and pbx_extension_helper().

#define HELPER_EXEC   2
 

Definition at line 569 of file pbx.c.

Referenced by ast_exec_extension(), and pbx_extension_helper().

#define HELPER_EXISTS   0
 

Definition at line 567 of file pbx.c.

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

#define HELPER_FINDLABEL   5
 

Definition at line 572 of file pbx.c.

Referenced by ast_findlabel_extension(), ast_findlabel_extension2(), and pbx_extension_helper().

#define HELPER_MATCHMORE   4
 

Definition at line 571 of file pbx.c.

Referenced by ast_matchmore_extension(), and pbx_extension_helper().

#define HELPER_SPAWN   1
 

Definition at line 568 of file pbx.c.

Referenced by ast_spawn_extension(), and pbx_extension_helper().

#define LOG
 

Referenced by ast_add_extension2().

#define STATUS_NO_CONTEXT   1
 

Definition at line 753 of file pbx.c.

Referenced by pbx_extension_helper(), and pbx_find_extension().

#define STATUS_NO_EXTENSION   2
 

Definition at line 754 of file pbx.c.

Referenced by pbx_extension_helper().

#define STATUS_NO_LABEL   4
 

Definition at line 756 of file pbx.c.

Referenced by pbx_extension_helper().

#define STATUS_NO_PRIORITY   3
 

Definition at line 755 of file pbx.c.

Referenced by pbx_extension_helper().

#define STATUS_SUCCESS   5
 

Definition at line 757 of file pbx.c.

#define SWITCH_DATA_LENGTH   256
 

Definition at line 77 of file pbx.c.

Referenced by ast_context_add_switch2().

#define VAR_BUF_SIZE   4096
 

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

#define VAR_NORMAL   1
 

Definition at line 81 of file pbx.c.

#define VAR_SOFTTRAN   2
 

Definition at line 82 of file pbx.c.

#define WAITEXTEN_MOH   (1 << 0)
 

Definition at line 97 of file pbx.c.

Referenced by pbx_builtin_waitexten().


Function Documentation

void __ast_context_destroy struct ast_context con,
const char *  registrar
 

Definition at line 5308 of file pbx.c.

References ast_context::alts, ast_log(), ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), contexts, destroy_exten(), el, free, ast_context::ignorepats, ast_context::includes, ast_context::lock, LOG_WARNING, ast_context::name, ast_exten::next, ast_sw::next, ast_ignorepat::next, ast_include::next, ast_context::next, ast_exten::peer, ast_context::registrar, and ast_context::root.

Referenced by ast_context_destroy().

05309 {
05310    struct ast_context *tmp, *tmpl=NULL;
05311    struct ast_include *tmpi, *tmpil= NULL;
05312    struct ast_sw *sw, *swl= NULL;
05313    struct ast_exten *e, *el, *en;
05314    struct ast_ignorepat *ipi, *ipl = NULL;
05315 
05316    ast_mutex_lock(&conlock);
05317    tmp = contexts;
05318    while(tmp) {
05319       if (((tmp->name && con && con->name && !strcasecmp(tmp->name, con->name)) || !con) &&
05320           (!registrar || !strcasecmp(registrar, tmp->registrar))) {
05321          /* Okay, let's lock the structure to be sure nobody else
05322             is searching through it. */
05323          if (ast_mutex_lock(&tmp->lock)) {
05324             ast_log(LOG_WARNING, "Unable to lock context lock\n");
05325             return;
05326          }
05327          if (tmpl)
05328             tmpl->next = tmp->next;
05329          else
05330             contexts = tmp->next;
05331          /* Okay, now we're safe to let it go -- in a sense, we were
05332             ready to let it go as soon as we locked it. */
05333          ast_mutex_unlock(&tmp->lock);
05334          for (tmpi = tmp->includes; tmpi; ) {
05335             /* Free includes */
05336             tmpil = tmpi;
05337             tmpi = tmpi->next;
05338             free(tmpil);
05339          }
05340          for (ipi = tmp->ignorepats; ipi; ) {
05341             /* Free ignorepats */
05342             ipl = ipi;
05343             ipi = ipi->next;
05344             free(ipl);
05345          }
05346          for (sw = tmp->alts; sw; ) {
05347             /* Free switches */
05348             swl = sw;
05349             sw = sw->next;
05350             free(swl);
05351             swl = sw;
05352          }
05353          for (e = tmp->root; e;) {
05354             for (en = e->peer; en;) {
05355                el = en;
05356                en = en->peer;
05357                destroy_exten(el);
05358             }
05359             el = e;
05360             e = e->next;
05361             destroy_exten(el);
05362          }
05363          ast_mutex_destroy(&tmp->lock);
05364          free(tmp);
05365          if (!con) {
05366             /* Might need to get another one -- restart */
05367             tmp = contexts;
05368             tmpl = NULL;
05369             tmpil = NULL;
05370             continue;
05371          }
05372          ast_mutex_unlock(&conlock);
05373          return;
05374       }
05375       tmpl = tmp;
05376       tmp = tmp->next;
05377    }
05378    ast_mutex_unlock(&conlock);
05379 }

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

Definition at line 6445 of file pbx.c.

References ast_async_goto(), ast_exists_extension(), ast_explicit_goto(), and ast_channel::context.

Referenced by ast_async_goto_if_exists(), and ast_goto_if_exists().

06446 {
06447    int (*goto_func)(struct ast_channel *chan, const char *context, const char *exten, int priority);
06448 
06449    if (!chan)
06450       return -2;
06451 
06452    goto_func = (async) ? ast_async_goto : ast_explicit_goto;
06453    if (ast_exists_extension(chan, context ? context : chan->context,
06454              exten ? exten : chan->exten, priority,
06455              chan->cid.cid_num))
06456       return goto_func(chan, context ? context : chan->context,
06457              exten ? exten : chan->exten, priority);
06458    else 
06459       return -3;
06460 }

static int __ast_pbx_run struct ast_channel c  )  [static]
 

Definition at line 2235 of file pbx.c.

References ast_channel::amaflags, ast_cdr_alloc(), ast_cdr_init(), ast_cdr_start(), ast_exists_extension(), AST_FLAG_IN_AUTOLOOP, ast_log(), ast_set_flag, ast_spawn_extension(), ast_test_flag, ast_verbose(), ast_channel::cdr, ast_channel::cid, ast_callerid::cid_num, ast_channel::context, ast_pbx::dtimeout, ast_channel::exten, exten, free, LOG_DEBUG, LOG_ERROR, LOG_WARNING, malloc, ast_channel::name, option_verbose, ast_channel::pbx, ast_channel::priority, ast_pbx::rtimeout, ast_cdr::start, and VERBOSE_PREFIX_2.

Referenced by ast_pbx_run(), and pbx_thread().

02236 {
02237    int firstpass = 1;
02238    int digit;
02239    char exten[256];
02240    int pos;
02241    int waittime;
02242    int res=0;
02243    int autoloopflag;
02244 
02245    /* A little initial setup here */
02246    if (c->pbx)
02247       ast_log(LOG_WARNING, "%s already has PBX structure??\n", c->name);
02248    c->pbx = malloc(sizeof(struct ast_pbx));
02249    if (!c->pbx) {
02250       ast_log(LOG_ERROR, "Out of memory\n");
02251       return -1;
02252    }
02253    if (c->amaflags) {
02254       if (!c->cdr) {
02255          c->cdr = ast_cdr_alloc();
02256          if (!c->cdr) {
02257             ast_log(LOG_WARNING, "Unable to create Call Detail Record\n");
02258             free(c->pbx);
02259             return -1;
02260          }
02261          ast_cdr_init(c->cdr, c);
02262       }
02263    }
02264    memset(c->pbx, 0, sizeof(struct ast_pbx));
02265    /* Set reasonable defaults */
02266    c->pbx->rtimeout = 10;
02267    c->pbx->dtimeout = 5;
02268 
02269    autoloopflag = ast_test_flag(c, AST_FLAG_IN_AUTOLOOP);
02270    ast_set_flag(c, AST_FLAG_IN_AUTOLOOP);
02271 
02272    /* Start by trying whatever the channel is set to */
02273    if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) {
02274       /* If not successful fall back to 's' */
02275       if (option_verbose > 1)
02276          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);
02277       ast_copy_string(c->exten, "s", sizeof(c->exten));
02278       if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) {
02279          /* JK02: And finally back to default if everything else failed */
02280          if (option_verbose > 1)
02281             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);
02282          ast_copy_string(c->context, "default", sizeof(c->context));
02283       }
02284       c->priority = 1;
02285    }
02286    if (c->cdr && !c->cdr->start.tv_sec && !c->cdr->start.tv_usec)
02287       ast_cdr_start(c->cdr);
02288    for(;;) {
02289       pos = 0;
02290       digit = 0;
02291       while(ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) {
02292          memset(exten, 0, sizeof(exten));
02293          if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num))) {
02294             /* Something bad happened, or a hangup has been requested. */
02295             if (((res >= '0') && (res <= '9')) || ((res >= 'A') && (res <= 'F')) ||
02296                (res == '*') || (res == '#')) {
02297                ast_log(LOG_DEBUG, "Oooh, got something to jump out with ('%c')!\n", res);
02298                memset(exten, 0, sizeof(exten));
02299                pos = 0;
02300                exten[pos++] = digit = res;
02301                break;
02302             }
02303             switch(res) {
02304             case AST_PBX_KEEPALIVE:
02305                if (option_debug)
02306                   ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
02307                else if (option_verbose > 1)
02308                   ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
02309                goto out;
02310                break;
02311             default:
02312                if (option_debug)
02313                   ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
02314                else if (option_verbose > 1)
02315                   ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
02316                if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
02317                   c->_softhangup =0;
02318                   break;
02319                }
02320                /* atimeout */
02321                if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) {
02322                   break;
02323                }
02324 
02325                if (c->cdr) {
02326                   ast_cdr_update(c);
02327                }
02328                goto out;
02329             }
02330          }
02331          if ((c->_softhangup == AST_SOFTHANGUP_TIMEOUT) && (ast_exists_extension(c,c->context,"T",1,c->cid.cid_num))) {
02332             ast_copy_string(c->exten, "T", sizeof(c->exten));
02333             /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
02334             c->whentohangup = 0;
02335             c->priority = 0;
02336             c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT;
02337          } else if (c->_softhangup) {
02338             ast_log(LOG_DEBUG, "Extension %s, priority %d returned normally even though call was hung up\n",
02339                c->exten, c->priority);
02340             goto out;
02341          }
02342          firstpass = 0;
02343          c->priority++;
02344       }
02345       if (!ast_exists_extension(c, c->context, c->exten, 1, c->cid.cid_num)) {
02346          /* It's not a valid extension anymore */
02347          if (ast_exists_extension(c, c->context, "i", 1, c->cid.cid_num)) {
02348             if (option_verbose > 2)
02349                ast_verbose(VERBOSE_PREFIX_3 "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, c->name);
02350             pbx_builtin_setvar_helper(c, "INVALID_EXTEN", c->exten);
02351             ast_copy_string(c->exten, "i", sizeof(c->exten));
02352             c->priority = 1;
02353          } else {
02354             ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n",
02355                c->name, c->exten, c->context);
02356             goto out;
02357          }
02358       } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) {
02359          /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */
02360          c->_softhangup = 0;
02361       } else {
02362          /* Done, wait for an extension */
02363          waittime = 0;
02364          if (digit)
02365             waittime = c->pbx->dtimeout;
02366          else if (!autofallthrough)
02367             waittime = c->pbx->rtimeout;
02368          if (waittime) {
02369             while (ast_matchmore_extension(c, c->context, exten, 1, c->cid.cid_num)) {
02370                /* As long as we're willing to wait, and as long as it's not defined, 
02371                   keep reading digits until we can't possibly get a right answer anymore.  */
02372                digit = ast_waitfordigit(c, waittime * 1000);
02373                if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
02374                   c->_softhangup = 0;
02375                } else {
02376                   if (!digit)
02377                      /* No entry */
02378                      break;
02379                   if (digit < 0)
02380                      /* Error, maybe a  hangup */
02381                      goto out;
02382                   exten[pos++] = digit;
02383                   waittime = c->pbx->dtimeout;
02384                }
02385             }
02386             if (ast_exists_extension(c, c->context, exten, 1, c->cid.cid_num)) {
02387                /* Prepare the next cycle */
02388                ast_copy_string(c->exten, exten, sizeof(c->exten));
02389                c->priority = 1;
02390             } else {
02391                /* No such extension */
02392                if (!ast_strlen_zero(exten)) {
02393                   /* An invalid extension */
02394                   if (ast_exists_extension(c, c->context, "i", 1, c->cid.cid_num)) {
02395                      if (option_verbose > 2)
02396                         ast_verbose( VERBOSE_PREFIX_3 "Invalid extension '%s' in context '%s' on %s\n", exten, c->context, c->name);
02397                      pbx_builtin_setvar_helper(c, "INVALID_EXTEN", exten);
02398                      ast_copy_string(c->exten, "i", sizeof(c->exten));
02399                      c->priority = 1;
02400                   } else {
02401                      ast_log(LOG_WARNING, "Invalid extension '%s', but no rule 'i' in context '%s'\n", exten, c->context);
02402                      goto out;
02403                   }
02404                } else {
02405                   /* A simple timeout */
02406                   if (ast_exists_extension(c, c->context, "t", 1, c->cid.cid_num)) {
02407                      if (option_verbose > 2)
02408                         ast_verbose( VERBOSE_PREFIX_3 "Timeout on %s\n", c->name);
02409                      ast_copy_string(c->exten, "t", sizeof(c->exten));
02410                      c->priority = 1;
02411                   } else {
02412                      ast_log(LOG_WARNING, "Timeout, but no rule 't' in context '%s'\n", c->context);
02413                      goto out;
02414                   }
02415                }  
02416             }
02417             if (c->cdr) {
02418                if (option_verbose > 2)
02419                   ast_verbose(VERBOSE_PREFIX_2 "CDR updated on %s\n",c->name);   
02420                ast_cdr_update(c);
02421              }
02422          } else {
02423             char *status;
02424 
02425             status = pbx_builtin_getvar_helper(c, "DIALSTATUS");
02426             if (!status)
02427                status = "UNKNOWN";
02428             if (option_verbose > 2)
02429                ast_verbose(VERBOSE_PREFIX_2 "Auto fallthrough, channel '%s' status is '%s'\n", c->name, status);
02430             if (!strcasecmp(status, "CONGESTION"))
02431                res = pbx_builtin_congestion(c, "10");
02432             else if (!strcasecmp(status, "CHANUNAVAIL"))
02433                res = pbx_builtin_congestion(c, "10");
02434             else if (!strcasecmp(status, "BUSY"))
02435                res = pbx_builtin_busy(c, "10");
02436             goto out;
02437          }
02438       }
02439    }
02440    if (firstpass) 
02441       ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name);
02442 out:
02443    if ((res != AST_PBX_KEEPALIVE) && ast_exists_extension(c, c->context, "h", 1, c->cid.cid_num)) {
02444       c->exten[0] = 'h';
02445       c->exten[1] = '\0';
02446       c->priority = 1;
02447       while(ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) {
02448          if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num))) {
02449             /* Something bad happened, or a hangup has been requested. */
02450             if (option_debug)
02451                ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
02452             else if (option_verbose > 1)
02453                ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
02454             break;
02455          }
02456          c->priority++;
02457       }
02458    }
02459    ast_set2_flag(c, autoloopflag, AST_FLAG_IN_AUTOLOOP);
02460 
02461    pbx_destroy(c->pbx);
02462    c->pbx = NULL;
02463    if (res != AST_PBX_KEEPALIVE)
02464       ast_hangup(c);
02465    return 0;
02466 }

int ast_active_calls void   ) 
 

Definition at line 2559 of file pbx.c.

Referenced by handle_chanlist().

02560 {
02561    return countcalls;
02562 }

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
 

Parameters:
context context to add the extension to
replace 
extension extension to add
priority priority level of extension addition
label extension label
callerid callerid of extension
application application to run on the extension with that priority level
data data to pass to the application
datad 
registrar who registered the extension Add and extension to an extension context. Callerid is a pattern to match CallerID, or NULL to match any callerid Returns 0 on success, -1 on failure

Definition at line 4502 of file pbx.c.

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

Referenced by handle_context_add_extension(), and register_peer_exten().

04504 {
04505    struct ast_context *c;
04506 
04507    if (ast_lock_contexts()) {
04508       errno = EBUSY;
04509       return -1;
04510    }
04511 
04512    c = ast_walk_contexts(NULL);
04513    while (c) {
04514       if (!strcmp(context, ast_get_context_name(c))) {
04515          int ret = ast_add_extension2(c, replace, extension, priority, label, callerid,
04516             application, data, datad, registrar);
04517          ast_unlock_contexts();
04518          return ret;
04519       }
04520       c = ast_walk_contexts(c);
04521    }
04522 
04523    ast_unlock_contexts();
04524    errno = ENOENT;
04525    return -1;
04526 }

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
 

For details about the arguements, check ast_add_extension()

Definition at line 4641 of file pbx.c.

References ast_add_hint(), ast_change_hint(), AST_LIST_FIRST, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_exten::cidmatch, ast_exten::data, ast_exten::datad, el, ext_strncpy(), ast_exten::exten, free, ast_context::lock, LOG, LOG_ERROR, LOG_WARNING, malloc, ast_exten::matchcid, ast_context::name, ast_exten::next, null_datad(), pbx_substitute_variables_varshead(), ast_exten::peer, ast_exten::priority, PRIORITY_HINT, ast_context::registrar, ast_context::root, and VAR_BUF_SIZE.

Referenced by __build_step(), ast_add_extension(), do_parking_thread(), fillin_process(), handle_macro(), load_config(), and pbx_load_module().

04645 {
04646 
04647 #define LOG do {  if (option_debug) {\
04648       if (tmp->matchcid) { \
04649          ast_log(LOG_DEBUG, "Added extension '%s' priority %d (CID match '%s') to %s\n", tmp->exten, tmp->priority, tmp->cidmatch, con->name); \
04650       } else { \
04651          ast_log(LOG_DEBUG, "Added extension '%s' priority %d to %s\n", tmp->exten, tmp->priority, con->name); \
04652       } \
04653    } else if (option_verbose > 2) { \
04654       if (tmp->matchcid) { \
04655          ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d (CID match '%s')to %s\n", tmp->exten, tmp->priority, tmp->cidmatch, con->name); \
04656       } else {  \
04657          ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d to %s\n", tmp->exten, tmp->priority, con->name); \
04658       } \
04659    } } while(0)
04660 
04661    /*
04662     * This is a fairly complex routine.  Different extensions are kept
04663     * in order by the extension number.  Then, extensions of different
04664     * priorities (same extension) are kept in a list, according to the
04665     * peer pointer.
04666     */
04667    struct ast_exten *tmp, *e, *el = NULL, *ep = NULL;
04668    int res;
04669    int length;
04670    char *p;
04671    char expand_buf[VAR_BUF_SIZE] = { 0, };
04672 
04673    /* if we are adding a hint, and there are global variables, and the hint
04674       contains variable references, then expand them
04675    */
04676    ast_mutex_lock(&globalslock);
04677    if ((priority == PRIORITY_HINT) && AST_LIST_FIRST(&globals) && strstr(application, "${")) {
04678       pbx_substitute_variables_varshead(&globals, application, expand_buf, sizeof(expand_buf));
04679       application = expand_buf;
04680    }
04681    ast_mutex_unlock(&globalslock);
04682 
04683    length = sizeof(struct ast_exten);
04684    length += strlen(extension) + 1;
04685    length += strlen(application) + 1;
04686    if (label)
04687       length += strlen(label) + 1;
04688    if (callerid)
04689       length += strlen(callerid) + 1;
04690    else
04691       length ++;
04692 
04693    /* Be optimistic:  Build the extension structure first */
04694    if (datad == NULL)
04695       datad = null_datad;
04696    tmp = malloc(length);
04697    if (tmp) {
04698       memset(tmp, 0, length);
04699       p = tmp->stuff;
04700       if (label) {
04701          tmp->label = p;
04702          strcpy(tmp->label, label);
04703          p += strlen(label) + 1;
04704       }
04705       tmp->exten = p;
04706       p += ext_strncpy(tmp->exten, extension, strlen(extension) + 1) + 1;
04707       tmp->priority = priority;
04708       tmp->cidmatch = p;
04709       if (callerid) {
04710          p += ext_strncpy(tmp->cidmatch, callerid, strlen(callerid) + 1) + 1;
04711          tmp->matchcid = 1;
04712       } else {
04713          tmp->cidmatch[0] = '\0';
04714          tmp->matchcid = 0;
04715          p++;
04716       }
04717       tmp->app = p;
04718       strcpy(tmp->app, application);
04719       tmp->parent = con;
04720       tmp->data = data;
04721       tmp->datad = datad;
04722       tmp->registrar = registrar;
04723       tmp->peer = NULL;
04724       tmp->next =  NULL;
04725    } else {
04726       ast_log(LOG_ERROR, "Out of memory\n");
04727       errno = ENOMEM;
04728       return -1;
04729    }
04730    if (ast_mutex_lock(&con->lock)) {
04731       free(tmp);
04732       /* And properly destroy the data */
04733       datad(data);
04734       ast_log(LOG_WARNING, "Failed to lock context '%s'\n", con->name);
04735       errno = EBUSY;
04736       return -1;
04737    }
04738    e = con->root;
04739    while(e) {
04740       /* Make sure patterns are always last! */
04741       if ((e->exten[0] != '_') && (extension[0] == '_'))
04742          res = -1;
04743       else if ((e->exten[0] == '_') && (extension[0] != '_'))
04744          res = 1;
04745       else
04746          res= strcmp(e->exten, extension);
04747       if (!res) {
04748          if (!e->matchcid && !tmp->matchcid)
04749             res = 0;
04750          else if (tmp->matchcid && !e->matchcid)
04751             res = 1;
04752          else if (e->matchcid && !tmp->matchcid)
04753             res = -1;
04754          else
04755             res = strcasecmp(e->cidmatch, tmp->cidmatch);
04756       }
04757       if (res == 0) {
04758          /* We have an exact match, now we find where we are
04759             and be sure there's no duplicates */
04760          while(e) {
04761             if (e->priority == tmp->priority) {
04762                /* Can't have something exactly the same.  Is this a
04763                   replacement?  If so, replace, otherwise, bonk. */
04764                if (replace) {
04765                   if (ep) {
04766                      /* We're in the peer list, insert ourselves */
04767                      ep->peer = tmp;
04768                      tmp->peer = e->peer;
04769                   } else if (el) {
04770                      /* We're the first extension. Take over e's functions */
04771                      el->next = tmp;
04772                      tmp->next = e->next;
04773                      tmp->peer = e->peer;
04774                   } else {
04775                      /* We're the very first extension.  */
04776                      con->root = tmp;
04777                      tmp->next = e->next;
04778                      tmp->peer = e->peer;
04779                   }
04780                   if (tmp->priority == PRIORITY_HINT)
04781                       ast_change_hint(e,tmp);
04782                   /* Destroy the old one */
04783                   e->datad(e->data);
04784                   free(e);
04785                   ast_mutex_unlock(&con->lock);
04786                   if (tmp->priority == PRIORITY_HINT)
04787                       ast_change_hint(e, tmp);
04788                   /* And immediately return success. */
04789                   LOG;
04790                   return 0;
04791                } else {
04792                   ast_log(LOG_WARNING, "Unable to register extension '%s', priority %d in '%s', already in use\n", tmp->exten, tmp->priority, con->name);
04793                   tmp->datad(tmp->data);
04794                   free(tmp);
04795                   ast_mutex_unlock(&con->lock);
04796                   errno = EEXIST;
04797                   return -1;
04798                }
04799             } else if (e->priority > tmp->priority) {
04800                /* Slip ourselves in just before e */
04801                if (ep) {
04802                   /* Easy enough, we're just in the peer list */
04803                   ep->peer = tmp;
04804                   tmp->peer = e;
04805                } else if (el) {
04806                   /* We're the first extension in this peer list */
04807                   el->next = tmp;
04808                   tmp->next = e->next;
04809                   e->next = NULL;
04810                   tmp->peer = e;
04811                } else {
04812                   /* We're the very first extension altogether */
04813                   tmp->next = con->root->next;
04814                   /* Con->root must always exist or we couldn't get here */
04815                   tmp->peer = con->root;
04816                   con->root = tmp;
04817                }
04818                ast_mutex_unlock(&con->lock);
04819 
04820                /* And immediately return success. */
04821                if (tmp->priority == PRIORITY_HINT)
04822                    ast_add_hint(tmp);
04823                
04824                LOG;
04825                return 0;
04826             }
04827             ep = e;
04828             e = e->peer;
04829          }
04830          /* If we make it here, then it's time for us to go at the very end.
04831             ep *must* be defined or we couldn't have gotten here. */
04832          ep->peer = tmp;
04833          ast_mutex_unlock(&con->lock);
04834          if (tmp->priority == PRIORITY_HINT)
04835             ast_add_hint(tmp);
04836          
04837          /* And immediately return success. */
04838          LOG;
04839          return 0;
04840             
04841       } else if (res > 0) {
04842          /* Insert ourselves just before 'e'.  We're the first extension of
04843             this kind */
04844          tmp->next = e;
04845          if (el) {
04846             /* We're in the list somewhere */
04847             el->next = tmp;
04848          } else {
04849             /* We're at the top of the list */
04850             con->root = tmp;
04851          }
04852          ast_mutex_unlock(&con->lock);
04853          if (tmp->priority == PRIORITY_HINT)
04854             ast_add_hint(tmp);
04855 
04856          /* And immediately return success. */
04857          LOG;
04858          return 0;
04859       }        
04860          
04861       el = e;
04862       e = e->next;
04863    }
04864    /* If we fall all the way through to here, then we need to be on the end. */
04865    if (el)
04866       el->next = tmp;
04867    else
04868       con->root = tmp;
04869    ast_mutex_unlock(&con->lock);
04870    if (tmp->priority == PRIORITY_HINT)
04871       ast_add_hint(tmp);
04872    LOG;
04873    return 0;   
04874 }

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

References ast_extension_state2(), ast_get_extension_app(), ast_get_extension_name(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), hints, list, LOG_DEBUG, malloc, ast_imager::next, and option_debug.

Referenced by ast_add_extension2().

02073 {
02074    struct ast_hint *list;
02075 
02076    if (!e) 
02077       return -1;
02078 
02079    ast_mutex_lock(&hintlock);
02080    list = hints;        
02081 
02082    /* Search if hint exists, do nothing */
02083    while (list) {
02084       if (list->exten == e) {
02085          ast_mutex_unlock(&hintlock);
02086          if (option_debug > 1)
02087             ast_log(LOG_DEBUG, "HINTS: Not re-adding existing hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e));
02088          return -1;
02089       }
02090       list = list->next;    
02091    }
02092 
02093    if (option_debug > 1)
02094       ast_log(LOG_DEBUG, "HINTS: Adding hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e));
02095 
02096    list = malloc(sizeof(struct ast_hint));
02097    if (!list) {
02098       ast_mutex_unlock(&hintlock);
02099       if (option_debug > 1)
02100          ast_log(LOG_DEBUG, "HINTS: Out of memory...\n");
02101       return -1;
02102    }
02103    /* Initialize and insert new item at the top */
02104    memset(list, 0, sizeof(struct ast_hint));
02105    list->exten = e;
02106    list->laststate = ast_extension_state2(e);
02107    list->next = hints;
02108    hints = list;
02109 
02110    ast_mutex_unlock(&hintlock);
02111    return 0;
02112 }

AST_APP_OPTIONS resetcdr_opts   ) 
 

AST_APP_OPTIONS waitexten_opts   ) 
 

AST_APP_OPTIONS background_opts   ) 
 

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

Definition at line 4547 of file pbx.c.

References ast_channel::_state, ast_channel_alloc(), ast_channel_masquerade(), ast_do_masquerade(), ast_explicit_goto(), ast_hangup(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pbx_start(), ast_setstate(), AST_SOFTHANGUP_ASYNCGOTO, ast_softhangup_nolock(), ast_strlen_zero(), ast_channel::context, ast_channel::exten, ast_channel::lock, LOG_WARNING, ast_channel::name, ast_channel::pbx, ast_channel::readformat, and ast_channel::writeformat.

Referenced by __ast_goto_if_exists(), action_redirect(), ast_async_goto_by_name(), builtin_blindtransfer(), console_transfer(), handle_request_bye(), handle_request_refer(), misdn_tx2ast_frm(), monitor_handle_owned(), socket_read(), and zt_read().

04548 {
04549    int res = 0;
04550 
04551    ast_mutex_lock(&chan->lock);
04552 
04553    if (chan->pbx) {
04554       /* This channel is currently in the PBX */
04555       ast_explicit_goto(chan, context, exten, priority);
04556       ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO);
04557    } else {
04558       /* In order to do it when the channel doesn't really exist within
04559          the PBX, we have to make a new channel, masquerade, and start the PBX
04560          at the new location */
04561       struct ast_channel *tmpchan;
04562       tmpchan = ast_channel_alloc(0);
04563       if (tmpchan) {
04564          snprintf(tmpchan->name, sizeof(tmpchan->name), "AsyncGoto/%s", chan->name);
04565          ast_setstate(tmpchan, chan->_state);
04566          /* Make formats okay */
04567          tmpchan->readformat = chan->readformat;
04568          tmpchan->writeformat = chan->writeformat;
04569          /* Setup proper location */
04570          ast_explicit_goto(tmpchan,
04571                  (!ast_strlen_zero(context)) ? context : chan->context,
04572                  (!ast_strlen_zero(exten)) ? exten : chan->exten,
04573                  priority);
04574 
04575          /* Masquerade into temp channel */
04576          ast_channel_masquerade(tmpchan, chan);
04577       
04578          /* Grab the locks and get going */
04579          ast_mutex_lock(&tmpchan->lock);
04580          ast_do_masquerade(tmpchan);
04581          ast_mutex_unlock(&tmpchan->lock);
04582          /* Start the PBX going on our stolen channel */
04583          if (ast_pbx_start(tmpchan)) {
04584             ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name);
04585             ast_hangup(tmpchan);
04586             res = -1;
04587          }
04588       } else {
04589          res = -1;
04590       }
04591    }
04592    ast_mutex_unlock(&chan->lock);
04593    return res;
04594 }

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

Definition at line 4596 of file pbx.c.

References ast_async_goto(), ast_get_channel_by_name_locked(), ast_mutex_unlock(), and ast_channel::lock.

04597 {
04598    struct ast_channel *chan;
04599    int res = -1;
04600 
04601    chan = ast_get_channel_by_name_locked(channame);
04602    if (chan) {
04603       res = ast_async_goto(chan, context, exten, priority);
04604       ast_mutex_unlock(&chan->lock);
04605    }
04606    return res;
04607 }

int ast_async_goto_if_exists struct ast_channel chan,
char *  context,
char *  exten,
int  priority
 

Definition at line 6466 of file pbx.c.

References __ast_goto_if_exists().

06466                                                                                                  {
06467    return __ast_goto_if_exists(chan, context, exten, priority, 1);
06468 }

int ast_build_timing struct ast_timing i,
char *  info_in
 

Definition at line 4080 of file pbx.c.

References ast_strlen_zero(), ast_timing::daymask, ast_timing::dowmask, FIND_NEXT, get_day(), get_dow(), get_month(), get_timerange(), and ast_timing::monthmask.

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

04081 {
04082    char info_save[256];
04083    char *info;
04084    char *c;
04085 
04086    /* Check for empty just in case */
04087    if (ast_strlen_zero(info_in))
04088       return 0;
04089    /* make a copy just in case we were passed a static string */
04090    ast_copy_string(info_save, info_in, sizeof(info_save));
04091    info = info_save;
04092    /* Assume everything except time */
04093    i->monthmask = (1 << 12) - 1;
04094    i->daymask = (1 << 30) - 1 + (1 << 30);
04095    i->dowmask = (1 << 7) - 1;
04096    /* Avoid using str tok */
04097    FIND_NEXT;
04098    /* Info has the time range, start with that */
04099    get_timerange(i, info);
04100    info = c;
04101    if (!info)
04102       return 1;
04103    FIND_NEXT;
04104    /* Now check for day of week */
04105    i->dowmask = get_dow(info);
04106 
04107    info = c;
04108    if (!info)
04109       return 1;
04110    FIND_NEXT;
04111    /* Now check for the day of the month */
04112    i->daymask = get_day(info);
04113    info = c;
04114    if (!info)
04115       return 1;
04116    FIND_NEXT;
04117    /* And finally go for the month */
04118    i->monthmask = get_month(info);
04119 
04120    return 1;
04121 }

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

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

References HELPER_CANMATCH, and pbx_extension_helper().

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

02216 {
02217    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, HELPER_CANMATCH);
02218 }

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

References ast_mutex_lock(), ast_mutex_unlock(), hints, list, and ast_imager::next.

Referenced by ast_add_extension2().

02116 { 
02117    struct ast_hint *list;
02118 
02119    ast_mutex_lock(&hintlock);
02120    list = hints;
02121 
02122    while(list) {
02123       if (list->exten == oe) {
02124             list->exten = ne;
02125          ast_mutex_unlock(&hintlock);  
02126          return 0;
02127       }
02128       list = list->next;
02129    }
02130    ast_mutex_unlock(&hintlock);
02131 
02132    return -1;
02133 }

int ast_check_timing struct ast_timing i  ) 
 

Definition at line 4123 of file pbx.c.

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

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

04124 {
04125    struct tm tm;
04126    time_t t;
04127 
04128    time(&t);
04129    localtime_r(&t,&tm);
04130 
04131    /* If it's not the right month, return */
04132    if (!(i->monthmask & (1 << tm.tm_mon))) {
04133       return 0;
04134    }
04135 
04136    /* If it's not that time of the month.... */
04137    /* Warning, tm_mday has range 1..31! */
04138    if (!(i->daymask & (1 << (tm.tm_mday-1))))
04139       return 0;
04140 
04141    /* If it's not the right day of the week */
04142    if (!(i->dowmask & (1 << tm.tm_wday)))
04143       return 0;
04144 
04145    /* Sanity check the hour just to be safe */
04146    if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) {
04147       ast_log(LOG_WARNING, "Insane time...\n");
04148       return 0;
04149    }
04150 
04151    /* Now the tough part, we calculate if it fits
04152       in the right time based on min/hour */
04153    if (!(i->minmask[tm.tm_hour] & (1 << (tm.tm_min / 2))))
04154       return 0;
04155 
04156    /* If we got this far, then we're good */
04157    return 1;
04158 }

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

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. Returns 0 on success, -1 on failure

Definition at line 4419 of file pbx.c.

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

Referenced by handle_context_add_ignorepat().

04420 {
04421    struct ast_context *c;
04422 
04423    if (ast_lock_contexts()) {
04424       errno = EBUSY;
04425       return -1;
04426    }
04427 
04428    c = ast_walk_contexts(NULL);
04429    while (c) {
04430       if (!strcmp(ast_get_context_name(c), con)) {
04431          int ret = ast_context_add_ignorepat2(c, value, registrar);
04432          ast_unlock_contexts();
04433          return ret;
04434       } 
04435       c = ast_walk_contexts(c);
04436    }
04437 
04438    ast_unlock_contexts();
04439    errno = ENOENT;
04440    return -1;
04441 }

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

Definition at line 4443 of file pbx.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_context::ignorepats, ast_context::lock, LOG_ERROR, malloc, ast_ignorepat::next, ast_ignorepat::pattern, and ast_ignorepat::registrar.

Referenced by ast_context_add_ignorepat(), handle_context(), and pbx_load_module().

04444 {
04445    struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL;
04446    int length;
04447    length = sizeof(struct ast_ignorepat);
04448    length += strlen(value) + 1;
04449    ignorepat = malloc(length);
04450    if (!ignorepat) {
04451       ast_log(LOG_ERROR, "Out of memory\n");
04452       errno = ENOMEM;
04453       return -1;
04454    }
04455    memset(ignorepat, 0, length);
04456    strcpy(ignorepat->pattern, value);
04457    ignorepat->next = NULL;
04458    ignorepat->registrar = registrar;
04459    ast_mutex_lock(&con->lock);
04460    ignorepatc = con->ignorepats;
04461    while(ignorepatc) {
04462       ignorepatl = ignorepatc;
04463       if (!strcasecmp(ignorepatc->pattern, value)) {
04464          /* Already there */
04465          ast_mutex_unlock(&con->lock);
04466          errno = EEXIST;
04467          return -1;
04468       }
04469       ignorepatc = ignorepatc->next;
04470    }
04471    if (ignorepatl) 
04472       ignorepatl->next = ignorepat;
04473    else
04474       con->ignorepats = ignorepat;
04475    ast_mutex_unlock(&con->lock);
04476    return 0;
04477    
04478 }

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

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 Returns 0 on success, -1 on error

Definition at line 3802 of file pbx.c.

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

Referenced by handle_context_add_include().

03803 {
03804    struct ast_context *c;
03805 
03806    if (ast_lock_contexts()) {
03807       errno = EBUSY;
03808       return -1;
03809    }
03810 
03811    /* walk contexts ... */
03812    c = ast_walk_contexts(NULL);
03813    while (c) {
03814       /* ... search for the right one ... */
03815       if (!strcmp(ast_get_context_name(c), context)) {
03816          int ret = ast_context_add_include2(c, include, registrar);
03817          /* ... unlock contexts list and return */
03818          ast_unlock_contexts();
03819          return ret;
03820       }
03821       c = ast_walk_contexts(c);
03822    }
03823 
03824    /* we can't find the right context */
03825    ast_unlock_contexts();
03826    errno = ENOENT;
03827    return -1;
03828 }

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

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 Returns 0 on success, -1 on failure

Definition at line 4167 of file pbx.c.

References ast_build_timing(), ast_get_context_name(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), free, ast_include::hastime, ast_context::includes, ast_context::lock, LOG_ERROR, malloc, 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(), handle_context(), and pbx_load_module().

04169 {
04170    struct ast_include *new_include;
04171    char *c;
04172    struct ast_include *i, *il = NULL; /* include, include_last */
04173    int length;
04174    char *p;
04175    
04176    length = sizeof(struct ast_include);
04177    length += 2 * (strlen(value) + 1);
04178 
04179    /* allocate new include structure ... */
04180    if (!(new_include = malloc(length))) {
04181       ast_log(LOG_ERROR, "Out of memory\n");
04182       errno = ENOMEM;
04183       return -1;
04184    }
04185    
04186    /* ... fill in this structure ... */
04187    memset(new_include, 0, length);
04188    p = new_include->stuff;
04189    new_include->name = p;
04190    strcpy(new_include->name, value);
04191    p += strlen(value) + 1;
04192    new_include->rname = p;
04193    strcpy(new_include->rname, value);
04194    c = new_include->rname;
04195    /* Strip off timing info */
04196    while(*c && (*c != '|')) 
04197       c++; 
04198    /* Process if it's there */
04199    if (*c) {
04200            new_include->hastime = ast_build_timing(&(new_include->timing), c+1);
04201       *c = '\0';
04202    }
04203    new_include->next      = NULL;
04204    new_include->registrar = registrar;
04205 
04206    /* ... try to lock this context ... */
04207    if (ast_mutex_lock(&con->lock)) {
04208       free(new_include);
04209       errno = EBUSY;
04210       return -1;
04211    }
04212 
04213    /* ... go to last include and check if context is already included too... */
04214    i = con->includes;
04215    while (i) {
04216       if (!strcasecmp(i->name, new_include->name)) {
04217          free(new_include);
04218          ast_mutex_unlock(&con->lock);
04219          errno = EEXIST;
04220          return -1;
04221       }
04222       il = i;
04223       i = i->next;
04224    }
04225 
04226    /* ... include new context into context list, unlock, return */
04227    if (il)
04228       il->next = new_include;
04229    else
04230       con->includes = new_include;
04231    if (option_verbose > 2)
04232       ast_verbose(VERBOSE_PREFIX_3 "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con)); 
04233    ast_mutex_unlock(&con->lock);
04234 
04235    return 0;
04236 }

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

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 It returns 0 on success, -1 on failure

Definition at line 4243 of file pbx.c.

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

04244 {
04245    struct ast_context *c;
04246 
04247    if (ast_lock_contexts()) {
04248       errno = EBUSY;
04249       return -1;
04250    }
04251 
04252    /* walk contexts ... */
04253    c = ast_walk_contexts(NULL);
04254    while (c) {
04255       /* ... search for the right one ... */
04256       if (!strcmp(ast_get_context_name(c), context)) {
04257          int ret = ast_context_add_switch2(c, sw, data, eval, registrar);
04258          /* ... unlock contexts list and return */
04259          ast_unlock_contexts();
04260          return ret;
04261       }
04262       c = ast_walk_contexts(c);
04263    }
04264 
04265    /* we can't find the right context */
04266    ast_unlock_contexts();
04267    errno = ENOENT;
04268    return -1;
04269 }

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

See ast_context_add_switch()

Definition at line 4278 of file pbx.c.

References ast_context::alts, ast_get_context_name(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), ast_sw::data, ast_sw::eval, free, ast_context::lock, LOG_ERROR, malloc, ast_sw::name, ast_sw::next, option_verbose, ast_sw::registrar, ast_sw::stuff, SWITCH_DATA_LENGTH, ast_sw::tmpdata, and VERBOSE_PREFIX_3.

Referenced by ast_context_add_switch(), handle_context(), and pbx_load_module().

04280 {
04281    struct ast_sw *new_sw;
04282    struct ast_sw *i, *il = NULL; /* sw, sw_last */
04283    int length;
04284    char *p;
04285    
04286    length = sizeof(struct ast_sw);
04287    length += strlen(value) + 1;
04288    if (data)
04289       length += strlen(data);
04290    length++;
04291    if (eval) {
04292       /* Create buffer for evaluation of variables */
04293       length += SWITCH_DATA_LENGTH;
04294       length++;
04295    }
04296 
04297    /* allocate new sw structure ... */
04298    if (!(new_sw = malloc(length))) {
04299       ast_log(LOG_ERROR, "Out of memory\n");
04300       errno = ENOMEM;
04301       return -1;
04302    }
04303    
04304    /* ... fill in this structure ... */
04305    memset(new_sw, 0, length);
04306    p = new_sw->stuff;
04307    new_sw->name = p;
04308    strcpy(new_sw->name, value);
04309    p += strlen(value) + 1;
04310    new_sw->data = p;
04311    if (data) {
04312       strcpy(new_sw->data, data);
04313       p += strlen(data) + 1;
04314    } else {
04315       strcpy(new_sw->data, "");
04316       p++;
04317    }
04318    if (eval) 
04319       new_sw->tmpdata = p;
04320    new_sw->next      = NULL;
04321    new_sw->eval     = eval;
04322    new_sw->registrar = registrar;
04323 
04324    /* ... try to lock this context ... */
04325    if (ast_mutex_lock(&con->lock)) {
04326       free(new_sw);
04327       errno = EBUSY;
04328       return -1;
04329    }
04330 
04331    /* ... go to last sw and check if context is already swd too... */
04332    i = con->alts;
04333    while (i) {
04334       if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) {
04335          free(new_sw);
04336          ast_mutex_unlock(&con->lock);
04337          errno = EEXIST;
04338          return -1;
04339       }
04340       il = i;
04341       i = i->next;
04342    }
04343 
04344    /* ... sw new context into context list, unlock, return */
04345    if (il)
04346       il->next = new_sw;
04347    else
04348       con->alts = new_sw;
04349    if (option_verbose > 2)
04350       ast_verbose(VERBOSE_PREFIX_3 "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con)); 
04351    ast_mutex_unlock(&con->lock);
04352 
04353    return 0;
04354 }

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

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. It returns NULL on failure, and an ast_context structure on success

Definition at line 3637 of file pbx.c.

References ast_log(), ast_mutex_init(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), contexts, ast_context::includes, local_contexts, LOG_DEBUG, LOG_ERROR, LOG_WARNING, malloc, ast_context::name, ast_context::next, option_verbose, and VERBOSE_PREFIX_3.

Referenced by do_parking_thread(), handle_context(), handle_macro(), load_config(), pbx_load_module(), reload_config(), and set_config().

03638 {
03639    struct ast_context *tmp, **local_contexts;
03640    int length;
03641    length = sizeof(struct ast_context);
03642    length += strlen(name) + 1;
03643    if (!extcontexts) {
03644       local_contexts = &contexts;
03645       ast_mutex_lock(&conlock);
03646    } else
03647       local_contexts = extcontexts;
03648 
03649    tmp = *local_contexts;
03650    while(tmp) {
03651       if (!strcasecmp(tmp->name, name)) {
03652          ast_mutex_unlock(&conlock);
03653          ast_log(LOG_WARNING, "Tried to register context '%s', already in use\n", name);
03654          if (!extcontexts)
03655             ast_mutex_unlock(&conlock);
03656          return NULL;
03657       }
03658       tmp = tmp->next;
03659    }
03660    tmp = malloc(length);
03661    if (tmp) {
03662       memset(tmp, 0, length);
03663       ast_mutex_init(&tmp->lock);
03664       strcpy(tmp->name, name);
03665       tmp->root = NULL;
03666       tmp->registrar = registrar;
03667       tmp->next = *local_contexts;
03668       tmp->includes = NULL;
03669       tmp->ignorepats = NULL;
03670       *local_contexts = tmp;
03671       if (option_debug)
03672          ast_log(LOG_DEBUG, "Registered context '%s'\n", tmp->name);
03673       else if (option_verbose > 2)
03674          ast_verbose( VERBOSE_PREFIX_3 "Registered extension context '%s'\n", tmp->name);
03675    } else
03676       ast_log(LOG_ERROR, "Out of memory\n");
03677    
03678    if (!extcontexts)
03679       ast_mutex_unlock(&conlock);
03680    return tmp;
03681 }

void ast_context_destroy struct ast_context con,
const char *  registrar
 

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

References __ast_context_destroy().

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

05382 {
05383    __ast_context_destroy(con,registrar);
05384 }

struct ast_context* ast_context_find const char *  name  ) 
 

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

References ast_mutex_lock(), ast_mutex_unlock(), contexts, ast_context::name, and ast_context::next.

Referenced by ast_context_verify_includes(), ast_ignore_pattern(), do_parking_thread(), load_config(), macro_exec(), park_exec(), reload_config(), and set_config().

00737 {
00738    struct ast_context *tmp;
00739    ast_mutex_lock(&conlock);
00740    if (name) {
00741       tmp = contexts;
00742       while(tmp) {
00743          if (!strcasecmp(name, tmp->name))
00744             break;
00745          tmp = tmp->next;
00746       }
00747    } else
00748       tmp = contexts;
00749    ast_mutex_unlock(&conlock);
00750    return tmp;
00751 }

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

Parameters:
context context to remove extension from
extension which extension to remove
priority priority of extension to remove
registrar registrar of the extension This function removes an extension from a given context. Returns 0 on success, -1 on failure

Definition at line 2722 of file pbx.c.

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

Referenced by handle_context_remove_extension(), and register_peer_exten().

02723 {
02724    struct ast_context *c;
02725 
02726    if (ast_lock_contexts()) return -1;
02727 
02728    /* walk contexts ... */
02729    c = ast_walk_contexts(NULL);
02730    while (c) {
02731       /* ... search for the right one ... */
02732       if (!strcmp(ast_get_context_name(c), context)) {
02733          /* ... remove extension ... */
02734          int ret = ast_context_remove_extension2(c, extension, priority,
02735             registrar);
02736          /* ... unlock contexts list and return */
02737          ast_unlock_contexts();
02738          return ret;
02739       }
02740       c = ast_walk_contexts(c);
02741    }
02742 
02743    /* we can't find the right context */
02744    ast_unlock_contexts();
02745    return -1;
02746 }

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

References ast_mutex_lock(), ast_mutex_unlock(), ast_remove_hint(), exten, free, ast_context::lock, ast_exten::next, ast_exten::peer, ast_exten::priority, PRIORITY_HINT, ast_exten::registrar, and ast_context::root.

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

02759 {
02760    struct ast_exten *exten, *prev_exten = NULL;
02761 
02762    if (ast_mutex_lock(&con->lock)) return -1;
02763 
02764    /* go through all extensions in context and search the right one ... */
02765    exten = con->root;
02766    while (exten) {
02767 
02768       /* look for right extension */
02769       if (!strcmp(exten->exten, extension) &&
02770          (!registrar || !strcmp(exten->registrar, registrar))) {
02771          struct ast_exten *peer;
02772 
02773          /* should we free all peers in this extension? (priority == 0)? */
02774          if (priority == 0) {
02775             /* remove this extension from context list */
02776             if (prev_exten)
02777                prev_exten->next = exten->next;
02778             else
02779                con->root = exten->next;
02780 
02781             /* fire out all peers */
02782             peer = exten; 
02783             while (peer) {
02784                exten = peer->peer;
02785                
02786                if (!peer->priority==PRIORITY_HINT) 
02787                    ast_remove_hint(peer);
02788 
02789                peer->datad(peer->data);
02790                free(peer);
02791 
02792                peer = exten;
02793             }
02794 
02795             ast_mutex_unlock(&con->lock);
02796             return 0;
02797          } else {
02798             /* remove only extension with exten->priority == priority */
02799             struct ast_exten *previous_peer = NULL;
02800 
02801             peer = exten;
02802             while (peer) {
02803                /* is this our extension? */
02804                if (peer->priority == priority &&
02805                   (!registrar || !strcmp(peer->registrar, registrar) )) {
02806                   /* we are first priority extension? */
02807                   if (!previous_peer) {
02808                      /* exists previous extension here? */
02809                      if (prev_exten) {
02810                         /* yes, so we must change next pointer in
02811                          * previous connection to next peer
02812                          */
02813                         if (peer->peer) {
02814                            prev_exten->next = peer->peer;
02815                            peer->peer->next = exten->next;
02816                         } else
02817                            prev_exten->next = exten->next;
02818                      } else {
02819                         /* no previous extension, we are first
02820                          * extension, so change con->root ...
02821                          */
02822                         if (peer->peer)
02823                            con->root = peer->peer;
02824                         else
02825                            con->root = exten->next; 
02826                      }
02827                   } else {
02828                      /* we are not first priority in extension */
02829                      previous_peer->peer = peer->peer;
02830                   }
02831 
02832                   /* now, free whole priority extension */
02833                   if (peer->priority==PRIORITY_HINT)
02834                       ast_remove_hint(peer);
02835                   peer->datad(peer->data);
02836                   free(peer);
02837 
02838                   ast_mutex_unlock(&con->lock);
02839                   return 0;
02840                } else {
02841                   /* this is not right extension, skip to next peer */
02842                   previous_peer = peer;
02843                   peer = peer->peer;
02844                }
02845             }
02846 
02847             ast_mutex_unlock(&con->lock);
02848             return -1;
02849          }
02850       }
02851 
02852       prev_exten = exten;
02853       exten = exten->next;
02854    }
02855 
02856    /* we can't find right extension */
02857    ast_mutex_unlock(&con->lock);
02858    return -1;
02859 }

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

Parameters:
context context from which to remove the pattern
ignorepat the pattern to remove
registrar the registrar of the ignore pattern This removes the given ignorepattern Returns 0 on success, -1 on failure

Definition at line 4360 of file pbx.c.

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

Referenced by handle_context_remove_ignorepat().

04361 {
04362    struct ast_context *c;
04363 
04364    if (ast_lock_contexts()) {
04365       errno = EBUSY;
04366       return -1;
04367    }
04368 
04369    c = ast_walk_contexts(NULL);
04370    while (c) {
04371       if (!strcmp(ast_get_context_name(c), context)) {
04372          int ret = ast_context_remove_ignorepat2(c, ignorepat, registrar);
04373          ast_unlock_contexts();
04374          return ret;
04375       }
04376       c = ast_walk_contexts(c);
04377    }
04378 
04379    ast_unlock_contexts();
04380    errno = ENOENT;
04381    return -1;
04382 }

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

Definition at line 4384 of file pbx.c.

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

Referenced by ast_context_remove_ignorepat().

04385 {
04386    struct ast_ignorepat *ip, *ipl = NULL;
04387 
04388    if (ast_mutex_lock(&con->lock)) {
04389       errno = EBUSY;
04390       return -1;
04391    }
04392 
04393    ip = con->ignorepats;
04394    while (ip) {
04395       if (!strcmp(ip->pattern, ignorepat) &&
04396          (!registrar || (registrar == ip->registrar))) {
04397          if (ipl) {
04398             ipl->next = ip->next;
04399             free(ip);
04400          } else {
04401             con->ignorepats = ip->next;
04402             free(ip);
04403          }
04404          ast_mutex_unlock(&con->lock);
04405          return 0;
04406       }
04407       ipl = ip; ip = ip->next;
04408    }
04409 
04410    ast_mutex_unlock(&con->lock);
04411    errno = EINVAL;
04412    return -1;
04413 }

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

See add_include

Definition at line 2578 of file pbx.c.

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

Referenced by handle_context_dont_include().

02579 {
02580    struct ast_context *c;
02581 
02582    if (ast_lock_contexts()) return -1;
02583 
02584    /* walk contexts and search for the right one ...*/
02585    c = ast_walk_contexts(NULL);
02586    while (c) {
02587       /* we found one ... */
02588       if (!strcmp(ast_get_context_name(c), context)) {
02589          int ret;
02590          /* remove include from this context ... */   
02591          ret = ast_context_remove_include2(c, include, registrar);
02592 
02593          ast_unlock_contexts();
02594 
02595          /* ... return results */
02596          return ret;
02597       }
02598       c = ast_walk_contexts(c);
02599    }
02600 
02601    /* we can't find the right one context */
02602    ast_unlock_contexts();
02603    return -1;
02604 }

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

See add_include2

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

02615 {
02616    struct ast_include *i, *pi = NULL;
02617 
02618    if (ast_mutex_lock(&con->lock)) return -1;
02619 
02620    /* walk includes */
02621    i = con->includes;
02622    while (i) {
02623       /* find our include */
02624       if (!strcmp(i->name, include) && 
02625          (!registrar || !strcmp(i->registrar, registrar))) {
02626          /* remove from list */
02627          if (pi)
02628             pi->next = i->next;
02629          else
02630             con->includes = i->next;
02631          /* free include and return */
02632          free(i);
02633          ast_mutex_unlock(&con->lock);
02634          return 0;
02635       }
02636       pi = i;
02637       i = i->next;
02638    }
02639 
02640    /* we can't find the right include */
02641    ast_mutex_unlock(&con->lock);
02642    return -1;
02643 }

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

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

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

02651 {
02652    struct ast_context *c;
02653 
02654    if (ast_lock_contexts()) return -1;
02655 
02656    /* walk contexts and search for the right one ...*/
02657    c = ast_walk_contexts(NULL);
02658    while (c) {
02659       /* we found one ... */
02660       if (!strcmp(ast_get_context_name(c), context)) {
02661          int ret;
02662          /* remove switch from this context ... */ 
02663          ret = ast_context_remove_switch2(c, sw, data, registrar);
02664 
02665          ast_unlock_contexts();
02666 
02667          /* ... return results */
02668          return ret;
02669       }
02670       c = ast_walk_contexts(c);
02671    }
02672 
02673    /* we can't find the right one context */
02674    ast_unlock_contexts();
02675    return -1;
02676 }

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

References ast_context::alts, ast_mutex_lock(), ast_mutex_unlock(), ast_sw::data, free, ast_context::lock, ast_sw::name, ast_sw::next, and ast_sw::registrar.

Referenced by ast_context_remove_switch().

02687 {
02688    struct ast_sw *i, *pi = NULL;
02689 
02690    if (ast_mutex_lock(&con->lock)) return -1;
02691 
02692    /* walk switchs */
02693    i = con->alts;
02694    while (i) {
02695       /* find our switch */
02696       if (!strcmp(i->name, sw) && !strcmp(i->data, data) && 
02697          (!registrar || !strcmp(i->registrar, registrar))) {
02698          /* remove from list */
02699          if (pi)
02700             pi->next = i->next;
02701          else
02702             con->alts = i->next;
02703          /* free switch and return */
02704          free(i);
02705          ast_mutex_unlock(&con->lock);
02706          return 0;
02707       }
02708       pi = i;
02709       i = i->next;
02710    }
02711 
02712    /* we can't find the right switch */
02713    ast_mutex_unlock(&con->lock);
02714    return -1;
02715 }

int ast_context_verify_includes struct ast_context con  ) 
 

Parameters:
con context in which to verify the includes Returns 0 if no problems found, -1 if there were any missing context

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

06431 {
06432    struct ast_include *inc;
06433    int res = 0;
06434 
06435    for (inc = ast_walk_context_includes(con, NULL); inc; inc = ast_walk_context_includes(con, inc))
06436       if (!ast_context_find(inc->rname)) {
06437          res = -1;
06438          ast_log(LOG_WARNING, "Context '%s' tries includes nonexistent context '%s'\n",
06439                ast_get_context_name(con), inc->rname);
06440       }
06441    return res;
06442 }

struct ast_custom_function* ast_custom_function_find char *  name  ) 
 

Definition at line 1265 of file pbx.c.

References acf_root, ast_log(), ast_mutex_lock(), LOG_ERROR, ast_custom_function::name, and ast_custom_function::next.

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

01266 {
01267    struct ast_custom_function *acfptr;
01268 
01269    /* try to lock functions list ... */
01270    if (ast_mutex_lock(&acflock)) {
01271       ast_log(LOG_ERROR, "Unable to lock function list\n");
01272       return NULL;
01273    }
01274 
01275    for (acfptr = acf_root; acfptr; acfptr = acfptr->next) {
01276       if (!strcmp(name, acfptr->name)) {
01277          break;
01278       }
01279    }
01280 
01281    ast_mutex_unlock(&acflock);
01282    
01283    return acfptr;
01284 }

int ast_custom_function_register struct ast_custom_function acf  ) 
 

Definition at line 1321 of file pbx.c.

References acf_root, ast_custom_function_find(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), LOG_ERROR, ast_custom_function::name, ast_custom_function::next, option_verbose, and VERBOSE_PREFIX_2.

Referenced by load_module().

01322 {
01323    if (!acf)
01324       return -1;
01325 
01326    /* try to lock functions list ... */
01327    if (ast_mutex_lock(&acflock)) {
01328       ast_log(LOG_ERROR, "Unable to lock function list. Failed registering function %s\n", acf->name);
01329       return -1;
01330    }
01331 
01332    if (ast_custom_function_find(acf->name)) {
01333       ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name);
01334       ast_mutex_unlock(&acflock);
01335       return -1;
01336    }
01337 
01338    acf->next = acf_root;
01339    acf_root = acf;
01340 
01341    ast_mutex_unlock(&acflock);
01342 
01343    if (option_verbose > 1)
01344       ast_verbose(VERBOSE_PREFIX_2 "Registered custom function %s\n", acf->name);
01345 
01346    return 0;
01347 }

int ast_custom_function_unregister struct ast_custom_function acf  ) 
 

Definition at line 1286 of file pbx.c.

References acf_root, ast_log(), ast_mutex_lock(), LOG_ERROR, and ast_custom_function::next.

Referenced by unload_module().

01287 {
01288    struct ast_custom_function *acfptr, *lastacf = NULL;
01289    int res = -1;
01290 
01291    if (!acf)
01292       return -1;
01293 
01294    /* try to lock functions list ... */
01295    if (ast_mutex_lock(&acflock)) {
01296       ast_log(LOG_ERROR, "Unable to lock function list\n");
01297       return -1;
01298    }
01299 
01300    for (acfptr = acf_root; acfptr; acfptr = acfptr->next) {
01301       if (acfptr == acf) {
01302          if (lastacf) {
01303             lastacf->next = acf->next;
01304          } else {
01305             acf_root = acf->next;
01306          }
01307          res = 0;
01308          break;
01309       }
01310       lastacf = acfptr;
01311    }
01312 
01313    ast_mutex_unlock(&acflock);
01314 
01315    if (!res && (option_verbose > 1))
01316       ast_verbose(VERBOSE_PREFIX_2 "Unregistered custom function %s\n", acf->name);
01317 
01318    return res;
01319 }

int ast_exec_extension struct ast_channel c,
const char *  context,
const char *  exten,
int  priority,
const char *  callerid
 

Parameters:
c channel to execute upon
context which context extension is in
exten extension to execute
priority priority to execute within the given extension
callerid Caller-ID If it's not available, do whatever you should do for default extensions and halt the thread if necessary. This function does not return, except on error.

Definition at line 2230 of file pbx.c.

References HELPER_EXEC, and pbx_extension_helper().

Referenced by loopback_exec().

02231 {
02232    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, HELPER_EXEC);
02233 }

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

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

References HELPER_EXISTS, and pbx_extension_helper().

Referenced by __ast_goto_if_exists(), __ast_pbx_run(), __login_exec(), agentmonitoroutgoing_exec(), ast_pbx_outgoing_exten(), ast_waitstream_exten(), builtin_atxfer(), builtin_blindtransfer(), cb_events(), console_dial(), console_transfer(), dp_lookup(), dundi_lookup_local(), get_also_info(), get_destination(), get_refer_info(), handle_link_data(), handle_link_phone_dtmf(), leave_voicemail(), local_alloc(), loopback_exists(), macro_exec(), mgcp_ss(), misdn_tx2ast_frm(), monitor_handle_notowned(), monitor_handle_owned(), parkandannounce_exec(), pbx_builtin_waitexten(), phone_check_exception(), register_peer_exten(), rpt(), skinny_ss(), socket_read(), ss_thread(), and zt_read().

02201 {
02202    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, HELPER_EXISTS);
02203 }

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

Definition at line 4528 of file pbx.c.

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

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

04529 {
04530    if (!chan)
04531       return -1;
04532 
04533    if (!ast_strlen_zero(context))
04534       ast_copy_string(chan->context, context, sizeof(chan->context));
04535    if (!ast_strlen_zero(exten))
04536       ast_copy_string(chan->exten, exten, sizeof(chan->exten));
04537    if (priority > -1) {
04538       chan->priority = priority;
04539       /* see flag description in channel.h for explanation */
04540       if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP))
04541          chan->priority--;
04542    }
04543    
04544    return 0;
04545 }

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

Definition at line 715 of file pbx.c.

References ast_strlen_zero(), EXTENSION_MATCH_CORE, and match().

Referenced by realtime_switch_common().

00716 {
00717    int match;
00718    /* If "data" is longer, it can'be a subset of pattern unless
00719       pattern is a pattern match */
00720    if ((strlen(pattern) < strlen(data)) && (pattern[0] != '_'))
00721       return 0;
00722    
00723    if ((ast_strlen_zero((char *)data) || !strncasecmp(pattern, data, strlen(data))) && 
00724       (!needmore || (strlen(pattern) > strlen(data)))) {
00725       return 1;
00726    }
00727    EXTENSION_MATCH_CORE(data,pattern,match);
00728    /* If there's more or we don't care about more, or if it's a possible early match, 
00729       return non-zero; otherwise it's a miss */
00730    if (!needmore || *pattern || match == 2) {
00731       return match;
00732    } else
00733       return 0;
00734 }

int ast_extension_match const char *  pattern,
const char *  extension
 

Parameters:
pattern pattern to match
extension extension to check against the pattern. Checks whether or not the given extension matches the given pattern. Returns 1 on match, 0 on failure

Definition at line 702 of file pbx.c.

References EXTENSION_MATCH_CORE, and match().

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

00703 {
00704    int match;
00705    /* If they're the same return */
00706    if (!strcmp(pattern, data))
00707       return 1;
00708    EXTENSION_MATCH_CORE(data,pattern,match);
00709    /* Must be at the end of both */
00710    if (*data || (*pattern && (*pattern != '/')))
00711       match = 0;
00712    return match;
00713 }

int ast_extension_state struct ast_channel c,
char *  context,
char *  exten
 

ast_extension_state: Check extension state for an extension by using hint

Parameters:
c this is not important
context which context to look in
exten which extension to get state Returns extension state !! = AST_EXTENSION_???

Definition at line 1872 of file pbx.c.

References ast_extension_state2(), and ast_hint_extension().

Referenced by action_extensionstate(), and handle_request_subscribe().

01873 {
01874    struct ast_exten *e;
01875 
01876    e = ast_hint_extension(c, context, exten);   /* Do we have a hint for this extension ? */ 
01877    if (!e) 
01878       return -1;           /* No hint, return -1 */
01879 
01880    return ast_extension_state2(e);        /* Check all devices in the hint */
01881 }

static int ast_extension_state2 struct ast_exten e  )  [static]
 

ast_extensions_state2: Check state of extension by using hints

Definition at line 1785 of file pbx.c.

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

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

01786 {
01787    char hint[AST_MAX_EXTENSION] = "";    
01788    char *cur, *rest;
01789    int res = -1;
01790    int allunavailable = 1, allbusy = 1, allfree = 1;
01791    int busy = 0, inuse = 0, ring = 0;
01792 
01793    if (!e)
01794       return -1;
01795 
01796    ast_copy_string(hint, ast_get_extension_app(e), sizeof(hint));
01797 
01798    cur = hint;       /* On or more devices separated with a & character */
01799    do {
01800       rest = strchr(cur, '&');
01801       if (rest) {
01802          *rest = 0;
01803          rest++;
01804       }
01805    
01806       res = ast_device_state(cur);
01807       switch (res) {
01808       case AST_DEVICE_NOT_INUSE:
01809          allunavailable = 0;
01810          allbusy = 0;
01811          break;
01812       case AST_DEVICE_INUSE:
01813          inuse = 1;
01814          allunavailable = 0;
01815          allfree = 0;
01816          break;
01817       case AST_DEVICE_RINGING:
01818          ring = 1;
01819          allunavailable = 0;
01820          allfree = 0;
01821          break;
01822       case AST_DEVICE_BUSY:
01823          allunavailable = 0;
01824          allfree = 0;
01825          busy = 1;
01826          break;
01827       case AST_DEVICE_UNAVAILABLE:
01828       case AST_DEVICE_INVALID:
01829          allbusy = 0;
01830          allfree = 0;
01831          break;
01832       default:
01833          allunavailable = 0;
01834          allbusy = 0;
01835          allfree = 0;
01836       }
01837       cur = rest;
01838    } while (cur);
01839 
01840    if (!inuse && ring)
01841       return AST_EXTENSION_RINGING;
01842    if (inuse && ring)
01843       return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING);
01844    if (inuse)
01845       return AST_EXTENSION_INUSE;
01846    if (allfree)
01847       return AST_EXTENSION_NOT_INUSE;
01848    if (allbusy)      
01849       return AST_EXTENSION_BUSY;
01850    if (allunavailable)
01851       return AST_EXTENSION_UNAVAILABLE;
01852    if (busy) 
01853       return AST_EXTENSION_INUSE;
01854    
01855    return AST_EXTENSION_NOT_INUSE;
01856 }

const char* ast_extension_state2str int  extension_state  ) 
 

ast_extension_state2str: Return extension_state as string

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

Definition at line 1859 of file pbx.c.

References extension_states.

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

01860 {
01861    int i;
01862 
01863    for (i = 0; (i < (sizeof(extension_states) / sizeof(extension_states[0]))); i++) {
01864       if (extension_states[i].extension_state == extension_state) {
01865          return extension_states[i].text;
01866       }
01867    }
01868    return "Unknown"; 
01869 }

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

ast_extension_state_add: Add watcher for extension states

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 for extension is changed Return -1 on failure, ID on success

Definition at line 1926 of file pbx.c.

References ast_hint_extension(), ast_mutex_lock(), ast_mutex_unlock(), ast_state_cb::callback, ast_state_cb::data, hints, ast_state_cb::id, list, malloc, ast_state_cb::next, ast_imager::next, and statecbs.

Referenced by handle_request_subscribe(), and init_manager().

01928 {
01929    struct ast_hint *list;
01930    struct ast_state_cb *cblist;
01931    struct ast_exten *e;
01932 
01933    /* If there's no context and extension:  add callback to statecbs list */
01934    if (!context && !exten) {
01935       ast_mutex_lock(&hintlock);
01936 
01937       cblist = statecbs;
01938       while (cblist) {
01939          if (cblist->callback == callback) {
01940             cblist->data = data;
01941             ast_mutex_unlock(&hintlock);
01942             return 0;
01943          }
01944          cblist = cblist->next;
01945       }
01946    
01947       /* Now insert the callback */
01948       cblist = malloc(sizeof(struct ast_state_cb));
01949       if (!cblist) {
01950          ast_mutex_unlock(&hintlock);
01951          return -1;
01952       }
01953       memset(cblist, 0, sizeof(struct ast_state_cb));
01954       cblist->id = 0;
01955       cblist->callback = callback;
01956       cblist->data = data;
01957    
01958       cblist->next = statecbs;
01959       statecbs = cblist;
01960 
01961       ast_mutex_unlock(&hintlock);
01962       return 0;
01963    }
01964 
01965    if (!context || !exten)
01966       return -1;
01967 
01968    /* This callback type is for only one hint, so get the hint */
01969    e = ast_hint_extension(NULL, context, exten);    
01970    if (!e) {
01971       return -1;
01972    }
01973 
01974    /* Find the hint in the list of hints */
01975    ast_mutex_lock(&hintlock);
01976    list = hints;        
01977 
01978    while (list) {
01979       if (list->exten == e)
01980          break;       
01981       list = list->next;    
01982    }
01983 
01984    if (!list) {
01985       /* We have no hint, sorry */
01986       ast_mutex_unlock(&hintlock);
01987       return -1;
01988    }
01989 
01990    /* Now insert the callback in the callback list  */
01991    cblist = malloc(sizeof(struct ast_state_cb));
01992    if (!cblist) {
01993       ast_mutex_unlock(&hintlock);
01994       return -1;
01995    }
01996    memset(cblist, 0, sizeof(struct ast_state_cb));
01997    cblist->id = stateid++;    /* Unique ID for this callback */
01998    cblist->callback = callback;  /* Pointer to callback routine */
01999    cblist->data = data;    /* Data for the callback */
02000 
02001    cblist->next = list->callbacks;
02002    list->callbacks = cblist;
02003 
02004    ast_mutex_unlock(&hintlock);
02005    return cblist->id;
02006 }

int ast_extension_state_del int  id,
ast_state_cb_type  callback
 

ast_extension_state_del: Remove a watcher from the callback list

Parameters:
id of the callback to delete
callback callback Removes the callback from list of callbacks Return 0 on success, -1 on failure

Definition at line 2009 of file pbx.c.

References ast_mutex_lock(), ast_mutex_unlock(), ast_state_cb::callback, free, hints, ast_state_cb::id, list, ast_state_cb::next, ast_imager::next, and statecbs.

Referenced by __sip_destroy().

02010 {
02011    struct ast_hint *list;
02012    struct ast_state_cb *cblist, *cbprev;
02013 
02014    if (!id && !callback)
02015       return -1;
02016 
02017    ast_mutex_lock(&hintlock);
02018 
02019    /* id is zero is a callback without extension */
02020    if (!id) {
02021       cbprev = NULL;
02022       cblist = statecbs;
02023       while (cblist) {
02024          if (cblist->callback == callback) {
02025             if (!cbprev)
02026                   statecbs = cblist->next;
02027             else
02028                   cbprev->next = cblist->next;
02029 
02030             free(cblist);
02031 
02032                ast_mutex_unlock(&hintlock);
02033             return 0;
02034             }
02035             cbprev = cblist;
02036             cblist = cblist->next;
02037       }
02038 
02039       ast_mutex_unlock(&hintlock);
02040       return -1;
02041    }
02042 
02043    /* id greater than zero is a callback with extension */
02044    /* Find the callback based on ID */
02045    list = hints;
02046    while (list) {
02047       cblist = list->callbacks;
02048       cbprev = NULL;
02049       while (cblist) {
02050             if (cblist->id==id) {
02051             if (!cbprev)
02052                   list->callbacks = cblist->next;     
02053             else
02054                   cbprev->next = cblist->next;
02055       
02056             free(cblist);
02057       
02058             ast_mutex_unlock(&hintlock);
02059             return 0;      
02060             }     
02061             cbprev = cblist;           
02062             cblist = cblist->next;
02063       }
02064       list = list->next;
02065    }
02066 
02067    ast_mutex_unlock(&hintlock);
02068    return -1;
02069 }

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

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 If an priority which matches given label in extension or -1 if not found. \

Definition at line 2205 of file pbx.c.

References HELPER_FINDLABEL, and pbx_extension_helper().

Referenced by ast_parseable_goto(), and handle_setpriority().

02206 {
02207    return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, HELPER_FINDLABEL);
02208 }

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

Definition at line 2210 of file pbx.c.

References HELPER_FINDLABEL, and pbx_extension_helper().

Referenced by pbx_load_module().

02211 {
02212    return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, HELPER_FINDLABEL);
02213 }

char* ast_func_read struct ast_channel chan,
const char *  in,
char *  workspace,
size_t  len
 

Parameters:
chan Channel to execute on
in Data containing the function call string
workspace A pointer to safe memory to use for a return value
len the number of bytes in workspace This application executes an function in read mode on a given channel. It returns a pointer to workspace if the buffer contains any new data or NULL if there was a problem.

Definition at line 1349 of file pbx.c.

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

Referenced by handle_getvariable(), and pbx_substitute_variables_helper_full().

01350 {
01351    char *args = NULL, *function, *p;
01352    char *ret = "0";
01353    struct ast_custom_function *acfptr;
01354 
01355    function = ast_strdupa(in);
01356    if (!function) {
01357       ast_log(LOG_ERROR, "Out of memory\n");
01358       return ret;
01359    }
01360    if ((args = strchr(function, '('))) {
01361       *args = '\0';
01362       args++;
01363       if ((p = strrchr(args, ')'))) {
01364          *p = '\0';
01365       } else {
01366          ast_log(LOG_WARNING, "Can't find trailing parenthesis?\n");
01367       }
01368    } else {
01369       ast_log(LOG_WARNING, "Function doesn't contain parentheses.  Assuming null argument.\n");
01370    }
01371 
01372    if ((acfptr = ast_custom_function_find(function))) {
01373       /* run the custom function */
01374       if (acfptr->read) {
01375          return acfptr->read(chan, function, args, workspace, len);
01376       } else {
01377          ast_log(LOG_ERROR, "Function %s cannot be read\n", function);
01378       }
01379    } else {
01380       ast_log(LOG_ERROR, "Function %s not registered\n", function);
01381    }
01382    return ret;
01383 }

void ast_func_write struct ast_channel chan,
const char *  in,
const char *  value
 

Parameters:
chan Channel to execute on
in Data containing the function call string
value A value parameter to pass for writing This application executes an function in write mode on a given channel. It has no return value.

Definition at line 1385 of file pbx.c.

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

Referenced by pbx_builtin_pushvar_helper(), and pbx_builtin_setvar_helper().

01386 {
01387    char *args = NULL, *function, *p;
01388    struct ast_custom_function *acfptr;
01389 
01390    function = ast_strdupa(in);
01391    if (!function) {
01392       ast_log(LOG_ERROR, "Out of memory\n");
01393       return;
01394    }
01395    if ((args = strchr(function, '('))) {
01396       *args = '\0';
01397       args++;
01398       if ((p = strrchr(args, ')'))) {
01399          *p = '\0';
01400       } else {
01401          ast_log(LOG_WARNING, "Can't find trailing parenthesis?\n");
01402       }
01403    } else {
01404       ast_log(LOG_WARNING, "Function doesn't contain parentheses.  Assuming null argument.\n");
01405    }
01406 
01407    if ((acfptr = ast_custom_function_find(function))) {
01408       /* run the custom function */
01409       if (acfptr->write) {
01410          acfptr->write(chan, function, args, value);
01411       } else {
01412          ast_log(LOG_ERROR, "Function %s is read-only, it cannot be written to\n", function);
01413       }
01414    } else {
01415       ast_log(LOG_ERROR, "Function %s not registered\n", function);
01416    }
01417 }

const char* ast_get_context_name struct ast_context con  ) 
 

Definition at line 6286 of file pbx.c.

References ast_context::name.

Referenced by ast_add_extension(), ast_context_add_ignorepat(), ast_context_add_include(), ast_context_add_include2(), ast_context_add_switch(), ast_context_add_switch2(), ast_context_remove_extension(), ast_context_remove_ignorepat(), ast_context_remove_include(), ast_context_remove_switch(), ast_context_verify_includes(), complete_context_add_extension(), complete_context_add_ignorepat(), complete_context_add_include(), complete_context_dont_include(), complete_context_remove_extension(), complete_context_remove_ignorepat(), complete_show_dialplan_context(), dundi_precache_full(), find_matching_endwhile(), handle_save_dialplan(), and show_dialplan_helper().

06287 {
06288    return con ? con->name : NULL;
06289 }

const char* ast_get_context_registrar struct ast_context c  ) 
 

Definition at line 6319 of file pbx.c.

References ast_context::registrar.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06320 {
06321    return c ? c->registrar : NULL;
06322 }

const char* ast_get_extension_app struct ast_exten e  ) 
 

Definition at line 6349 of file pbx.c.

References ast_exten::app.

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

06350 {
06351    return e ? e->app : NULL;
06352 }

void* ast_get_extension_app_data struct ast_exten e  ) 
 

Definition at line 6354 of file pbx.c.

References ast_exten::data.

Referenced by ast_get_hint(), handle_save_dialplan(), and show_dialplan_helper().

06355 {
06356    return e ? e->data : NULL;
06357 }

const char* ast_get_extension_cidmatch struct ast_exten e  ) 
 

Definition at line 6344 of file pbx.c.

References ast_exten::cidmatch.

Referenced by find_matching_priority(), and handle_save_dialplan().

06345 {
06346    return e ? e->cidmatch : NULL;
06347 }

const char* ast_get_extension_label struct ast_exten exten  ) 
 

Definition at line 6296 of file pbx.c.

References exten.

Referenced by show_dialplan_helper().

06297 {
06298    return exten ? exten->label : NULL;
06299 }

int ast_get_extension_matchcid struct ast_exten e  ) 
 

Definition at line 6339 of file pbx.c.

References ast_exten::matchcid.

Referenced by find_matching_priority(), and handle_save_dialplan().

06340 {
06341    return e ? e->matchcid : 0;
06342 }

const char* ast_get_extension_name struct ast_exten exten  ) 
 

Definition at line 6291 of file pbx.c.

References exten.

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

06292 {
06293    return exten ? exten->exten : NULL;
06294 }

int ast_get_extension_priority struct ast_exten exten  ) 
 

Definition at line 6311 of file pbx.c.

References exten.

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

06312 {
06313    return exten ? exten->priority : -1;
06314 }

const char* ast_get_extension_registrar struct ast_exten e  ) 
 

Definition at line 6324 of file pbx.c.

References ast_exten::registrar.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06325 {
06326    return e ? e->registrar : NULL;
06327 }

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

ast_get_hint: Get hint for channel

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

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

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

02182 {
02183    struct ast_exten *e;
02184    void *tmp;
02185 
02186    e = ast_hint_extension(c, context, exten);
02187    if (e) {
02188       if (hint) 
02189           ast_copy_string(hint, ast_get_extension_app(e), hintsize);
02190       if (name) {
02191          tmp = ast_get_extension_app_data(e);
02192          if (tmp)
02193             ast_copy_string(name, (char *) tmp, namesize);
02194       }
02195        return -1;
02196    }
02197    return 0;   
02198 }

const char* ast_get_ignorepat_name struct ast_ignorepat ip  ) 
 

Definition at line 6306 of file pbx.c.

References ast_ignorepat::pattern.

Referenced by complete_context_add_ignorepat(), complete_context_remove_ignorepat(), and handle_save_dialplan().

06307 {
06308    return ip ? ip->pattern : NULL;
06309 }

const char* ast_get_ignorepat_registrar struct ast_ignorepat ip  ) 
 

Definition at line 6334 of file pbx.c.

References ast_ignorepat::registrar.

Referenced by handle_save_dialplan().

06335 {
06336    return ip ? ip->registrar : NULL;
06337 }

const char* ast_get_include_name struct ast_include inc  ) 
 

Definition at line 6301 of file pbx.c.

References ast_include::name.

Referenced by complete_context_add_include(), complete_context_dont_include(), handle_save_dialplan(), and show_dialplan_helper().

06302 {
06303    return inc ? inc->name : NULL;
06304 }

const char* ast_get_include_registrar struct ast_include i  ) 
 

Definition at line 6329 of file pbx.c.

References ast_include::registrar.

Referenced by handle_save_dialplan().

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

const char* ast_get_switch_data struct ast_sw sw  ) 
 

Definition at line 6364 of file pbx.c.

References ast_sw::data.

Referenced by handle_save_dialplan().

06365 {
06366    return sw ? sw->data : NULL;
06367 }

const char* ast_get_switch_name struct ast_sw sw  ) 
 

Definition at line 6359 of file pbx.c.

References ast_sw::name.

Referenced by handle_save_dialplan().

06360 {
06361    return sw ? sw->name : NULL;
06362 }

const char* ast_get_switch_registrar struct ast_sw sw  ) 
 

Definition at line 6369 of file pbx.c.

References ast_sw::registrar.

Referenced by handle_save_dialplan().

06370 {
06371    return sw ? sw->registrar : NULL;
06372 }

int ast_goto_if_exists struct ast_channel chan,
char *  context,
char *  exten,
int  priority
 

Definition at line 6462 of file pbx.c.

References __ast_goto_if_exists().

Referenced by aqm_exec(), background_detect_exec(), chanavail_exec(), controlplayback_exec(), dial_exec_full(), do_directory(), enumlookup_exec(), get_exec(), group_check_exec(), hasvoicemail_exec(), leave_voicemail(), lookupblacklist_exec(), md5check_exec(), onedigit_goto(), ospfinished_exec(), osplookup_exec(), ospnext_exec(), play_mailbox_owner(), playback_exec(), pqm_exec(), privacy_exec(), rqm_exec(), sendimage_exec(), sendtext_exec(), sendurl_exec(), sip_getheader(), system_exec_helper(), transfer_exec(), txtcidname_exec(), upqm_exec(), valid_exit(), vm_box_exists(), vm_exec(), and wait_for_answer().

06462                                                                                            {
06463    return __ast_goto_if_exists(chan, context, exten, priority, 0);
06464 }

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

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_PBX_MAX_STACK, HELPER_EXISTS, LOG_WARNING, pbx_find_extension(), and PRIORITY_HINT.

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

01766 {
01767    struct ast_exten *e;
01768    struct ast_switch *sw;
01769    char *data;
01770    const char *foundcontext = NULL;
01771    int status = 0;
01772    char *incstack[AST_PBX_MAX_STACK];
01773    int stacklen = 0;
01774 
01775    if (ast_mutex_lock(&conlock)) {
01776       ast_log(LOG_WARNING, "Unable to obtain lock\n");
01777       return NULL;
01778    }
01779    e = pbx_find_extension(c, NULL, context, exten, PRIORITY_HINT, NULL, "", HELPER_EXISTS, incstack, &stacklen, &status, &sw, &data, &foundcontext);
01780    ast_mutex_unlock(&conlock);   
01781    return e;
01782 }

void ast_hint_state_changed const char *  device  ) 
 

Definition at line 1883 of file pbx.c.

References ast_extension_state2(), ast_get_extension_app(), AST_MAX_EXTENSION, ast_mutex_lock(), ast_state_cb::callback, ast_hint::callbacks, ast_state_cb::data, ast_hint::exten, ast_exten::exten, hints, ast_hint::laststate, ast_context::name, ast_hint::next, ast_state_cb::next, ast_exten::parent, parse(), statecbs, and strsep().

Referenced by do_state_change().

01884 {
01885    struct ast_hint *hint;
01886    struct ast_state_cb *cblist;
01887    char buf[AST_MAX_EXTENSION];
01888    char *parse;
01889    char *cur;
01890    int state;
01891 
01892    ast_mutex_lock(&hintlock);
01893 
01894    for (hint = hints; hint; hint = hint->next) {
01895       ast_copy_string(buf, ast_get_extension_app(hint->exten), sizeof(buf));
01896       parse = buf;
01897       for (cur = strsep(&parse, "&"); cur; cur = strsep(&parse, "&")) {
01898          if (strcasecmp(cur, device))
01899             continue;
01900 
01901          /* Get device state for this hint */
01902          state = ast_extension_state2(hint->exten);
01903          
01904          if ((state == -1) || (state == hint->laststate))
01905             continue;
01906 
01907          /* Device state changed since last check - notify the watchers */
01908          
01909          /* For general callbacks */
01910          for (cblist = statecbs; cblist; cblist = cblist->next)
01911             cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data);
01912          
01913          /* For extension callbacks */
01914          for (cblist = hint->callbacks; cblist; cblist = cblist->next)
01915             cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data);
01916          
01917          hint->laststate = state;
01918          break;
01919       }
01920    }
01921 
01922    ast_mutex_unlock(&hintlock);
01923 }

int ast_ignore_pattern const char *  context,
const char *  pattern
 

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. Returns 0 if the pattern should not be ignored, or non-zero if the pattern should be ignored

Definition at line 4480 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(), dp_lookup(), dundi_lookup_local(), mgcp_ss(), skinny_ss(), and ss_thread().

04481 {
04482    struct ast_context *con;
04483    struct ast_ignorepat *pat;
04484 
04485    con = ast_context_find(context);
04486    if (con) {
04487       pat = con->ignorepats;
04488       while (pat) {
04489          if (ast_extension_match(pat->pattern, pattern))
04490             return 1;
04491          pat = pat->next;
04492       }
04493    } 
04494    return 0;
04495 }

AST_LIST_HEAD store_hints  ,
store_hint 
 

int ast_lock_context struct ast_context con  ) 
 

Parameters:
con context to lock Locks the context. Returns 0 on success, -1 on failure

Definition at line 6273 of file pbx.c.

References ast_mutex_lock(), and ast_context::lock.

Referenced by complete_context_add_ignorepat(), complete_context_add_include(), complete_context_dont_include(), complete_context_remove_ignorepat(), dundi_precache_full(), find_matching_endwhile(), handle_save_dialplan(), and show_dialplan_helper().

06274 {
06275    return ast_mutex_lock(&con->lock);
06276 }

int ast_lock_contexts void   ) 
 

Locks the context list Returns 0 on success, -1 on error

Definition at line 6260 of file pbx.c.

References ast_mutex_lock().

Referenced by ast_add_extension(), ast_context_add_ignorepat(), ast_context_add_include(), ast_context_add_switch(), ast_context_remove_extension(), ast_context_remove_ignorepat(), ast_context_remove_include(), ast_context_remove_switch(), complete_context_add_extension(), complete_context_add_ignorepat(), complete_context_add_include(), complete_context_dont_include(), complete_context_remove_extension(), complete_context_remove_ignorepat(), complete_show_dialplan_context(), dundi_precache_full(), find_matching_endwhile(), handle_save_dialplan(), and show_dialplan_helper().

06261 {
06262    return ast_mutex_lock(&conlock);
06263 }

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

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

References HELPER_MATCHMORE, and pbx_extension_helper().

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

02221 {
02222    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, HELPER_MATCHMORE);
02223 }

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

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

References AST_LIST_HEAD_INIT, ast_log(), ast_mutex_lock(), ast_hint::callbacks, calloc, store_hint::exten, ast_hint::exten, ast_exten::exten, hints, LOG_WARNING, ast_context::name, ast_hint::next, ast_exten::parent, and ast_context::registrar.

Referenced by pbx_load_module().

03697 {
03698    struct ast_context *tmp, *lasttmp = NULL;
03699    struct store_hints store;
03700    struct store_hint *this;
03701    struct ast_hint *hint;
03702    struct ast_exten *exten;
03703    int length;
03704    struct ast_state_cb *thiscb, *prevcb;
03705 
03706    AST_LIST_HEAD_INIT(&store);
03707 
03708    /* it is very important that this function hold the hintlock _and_ the conlock
03709       during its operation; not only do we need to ensure that the list of contexts
03710       and extensions does not change, but also that no hint callbacks (watchers) are
03711       added or removed during the merge/delete process
03712 
03713       in addition, the locks _must_ be taken in this order, because there are already
03714       other code paths that use this order
03715    */
03716    ast_mutex_lock(&conlock);
03717    ast_mutex_lock(&hintlock);
03718 
03719    /* preserve all watchers for hints associated with this registrar */
03720    for (hint = hints; hint; hint = hint->next) {
03721       if (hint->callbacks && !strcmp(registrar, hint->exten->parent->registrar)) {
03722          length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2 + sizeof(*this);
03723          this = calloc(1, length);
03724          if (!this) {
03725             ast_log(LOG_WARNING, "Could not allocate memory to preserve hint\n");
03726             continue;
03727          }
03728          this->callbacks = hint->callbacks;
03729          hint->callbacks = NULL;
03730          this->laststate = hint->laststate;
03731          this->context = this->data;
03732          strcpy(this->data, hint->exten->parent->name);
03733          this->exten = this->data + strlen(this->context) + 1;
03734          strcpy(this->exten, hint->exten->exten);
03735          AST_LIST_INSERT_HEAD(&store, this, list);
03736       }
03737    }
03738 
03739    tmp = *extcontexts;
03740    if (registrar) {
03741       __ast_context_destroy(NULL,registrar);
03742       while (tmp) {
03743          lasttmp = tmp;
03744          tmp = tmp->next;
03745       }
03746    } else {
03747       while (tmp) {
03748          __ast_context_destroy(tmp,tmp->registrar);
03749          lasttmp = tmp;
03750          tmp = tmp->next;
03751       }
03752    }
03753    if (lasttmp) {
03754       lasttmp->next = contexts;
03755       contexts = *extcontexts;
03756       *extcontexts = NULL;
03757    } else 
03758       ast_log(LOG_WARNING, "Requested contexts didn't get merged\n");
03759 
03760    /* restore the watchers for hints that can be found; notify those that
03761       cannot be restored
03762    */
03763    while ((this = AST_LIST_REMOVE_HEAD(&store, list))) {
03764       exten = ast_hint_extension(NULL, this->context, this->exten);
03765       /* Find the hint in the list of hints */
03766       for (hint = hints; hint; hint = hint->next) {
03767          if (hint->exten == exten)
03768             break;
03769       }
03770       if (!exten || !hint) {
03771          /* this hint has been removed, notify the watchers */
03772          prevcb = NULL;
03773          thiscb = this->callbacks;
03774          while (thiscb) {
03775             prevcb = thiscb;      
03776             thiscb = thiscb->next;
03777             prevcb->callback(this->context, this->exten, AST_EXTENSION_REMOVED, prevcb->data);
03778             free(prevcb);
03779             }
03780       } else {
03781          thiscb = this->callbacks;
03782          while (thiscb->next)
03783             thiscb = thiscb->next;
03784          thiscb->next = hint->callbacks;
03785          hint->callbacks = this->callbacks;
03786          hint->laststate = this->laststate;
03787       }
03788       free(this);
03789    }
03790 
03791    ast_mutex_unlock(&hintlock);
03792    ast_mutex_unlock(&conlock);
03793 
03794    return;  
03795 }

AST_MUTEX_DEFINE_STATIC hintlock   ) 
 

AST_MUTEX_DEFINE_STATIC switchlock   ) 
 

AST_MUTEX_DEFINE_STATIC applock   ) 
 

AST_MUTEX_DEFINE_STATIC conlock   ) 
 

AST_MUTEX_DEFINE_STATIC acflock   ) 
 

Lock for the custom function list

AST_MUTEX_DEFINE_STATIC maxcalllock   ) 
 

AST_MUTEX_DEFINE_STATIC globalslock   ) 
 

int ast_parseable_goto struct ast_channel chan,
const char *  goto_string
 

Definition at line 6470 of file pbx.c.

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

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

06471 {
06472    char *s;
06473    char *exten, *pri, *context;
06474    char *stringp=NULL;
06475    int ipri;
06476    int mode = 0;
06477 
06478    if (ast_strlen_zero(goto_string)) {
06479       ast_log(LOG_WARNING, "Goto requires an argument (optional context|optional extension|priority)\n");
06480       return -1;
06481    }
06482    s = ast_strdupa(goto_string);
06483    stringp=s;
06484    context = strsep(&stringp, "|");
06485    exten = strsep(&stringp, "|");
06486    if (!exten) {
06487       /* Only a priority in this one */
06488       pri = context;
06489       exten = NULL;
06490       context = NULL;
06491    } else {
06492       pri = strsep(&stringp, "|");
06493       if (!pri) {
06494          /* Only an extension and priority in this one */
06495          pri = exten;
06496          exten = context;
06497          context = NULL;
06498       }
06499    }
06500    if (*pri == '+') {
06501       mode = 1;
06502       pri++;
06503    } else if (*pri == '-') {
06504       mode = -1;
06505       pri++;
06506    }
06507    if (sscanf(pri, "%d", &ipri) != 1) {
06508       if ((ipri = ast_findlabel_extension(chan, context ? context : chan->context, (exten && strcasecmp(exten, "BYEXTENSION")) ? exten : chan->exten, 
06509          pri, chan->cid.cid_num)) < 1) {
06510          ast_log(LOG_WARNING, "Priority '%s' must be a number > 0, or valid label\n", pri);
06511          return -1;
06512       } else
06513          mode = 0;
06514    } 
06515    /* At this point we have a priority and maybe an extension and a context */
06516 
06517    if (exten && !strcasecmp(exten, "BYEXTENSION"))
06518       exten = NULL;
06519 
06520    if (mode) 
06521       ipri = chan->priority + (ipri * mode);
06522 
06523    ast_explicit_goto(chan, context, exten, ipri);
06524    ast_cdr_update(chan);
06525    return 0;
06526 
06527 }

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
 

Definition at line 5153 of file pbx.c.

References __ast_request_and_dial(), async_stat::app, async_stat::appdata, ast_cdr_alloc(), ast_cdr_disposition(), ast_cdr_failed(), ast_cdr_init(), ast_cdr_setaccount(), ast_cdr_start(), ast_hangup(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pbx_outgoing_cdr_failed(), ast_pbx_run_app(), ast_pthread_create, ast_set_variables(), AST_STATE_UP, ast_strlen_zero(), ast_variables_destroy(), ast_verbose(), async_wait(), ast_channel::cdr, async_stat::chan, free, LOG_ERROR, LOG_WARNING, malloc, ast_channel::name, option_verbose, async_stat::p, ast_channel::pbx, async_stat::timeout, outgoing_helper::vars, and VERBOSE_PREFIX_4.

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

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

int ast_pbx_outgoing_cdr_failed void   ) 
 

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

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

Referenced by ast_pbx_outgoing_app(), and ast_pbx_outgoing_exten().

04950 {
04951    /* allocate a channel */
04952    struct ast_channel *chan = ast_channel_alloc(0);
04953    if(!chan) {
04954       /* allocation of the channel failed, let some peeps know */
04955       ast_log(LOG_WARNING, "Unable to allocate channel structure for CDR record\n");
04956       return -1;  /* failure */
04957    }
04958 
04959    chan->cdr = ast_cdr_alloc();   /* allocate a cdr for the channel */
04960 
04961    if(!chan->cdr) {
04962       /* allocation of the cdr failed */
04963       ast_log(LOG_WARNING, "Unable to create Call Detail Record\n");
04964       ast_channel_free(chan);   /* free the channel */
04965       return -1;                /* return failure */
04966    }
04967    
04968    /* allocation of the cdr was successful */
04969    ast_cdr_init(chan->cdr, chan);  /* initilize our channel's cdr */
04970    ast_cdr_start(chan->cdr);       /* record the start and stop time */
04971    ast_cdr_end(chan->cdr);
04972    ast_cdr_failed(chan->cdr);      /* set the status to failed */
04973    ast_cdr_detach(chan->cdr);      /* post and free the record */
04974    ast_channel_free(chan);         /* free the channel */
04975    
04976    return 0;  /* success */
04977 }

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
 

Definition at line 4979 of file pbx.c.

References __ast_request_and_dial(), ast_channel::_state, ast_cdr_alloc(), ast_cdr_disposition(), ast_cdr_failed(), ast_cdr_init(), ast_cdr_setaccount(), ast_cdr_start(), ast_channel_alloc(), ast_exists_extension(), ast_hangup(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pbx_outgoing_cdr_failed(), ast_pbx_run(), ast_pbx_start(), ast_pthread_create, ast_request_and_dial(), ast_set_variables(), AST_STATE_UP, ast_strlen_zero(), ast_variables_destroy(), ast_verbose(), async_wait(), ast_channel::cdr, async_stat::chan, ast_channel::context, async_stat::context, ast_channel::exten, async_stat::exten, free, ast_channel::hangupcause, LOAD_OH, ast_channel::lock, LOG_ERROR, LOG_WARNING, malloc, ast_channel::name, option_verbose, async_stat::p, ast_channel::pbx, ast_channel::priority, async_stat::priority, async_stat::timeout, outgoing_helper::vars, and VERBOSE_PREFIX_4.

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

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

enum ast_pbx_result ast_pbx_run struct ast_channel c  ) 
 

Parameters:
c channel to run the pbx on
Returns:
Zero on success, non-zero on failure This executes the PBX on a given channel. It allocates a new PBX structure for the channel, and provides all PBX functionality.

Definition at line 2546 of file pbx.c.

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

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

02547 {
02548    enum ast_pbx_result res = AST_PBX_SUCCESS;
02549 
02550    if (increase_call_count(c))
02551       return AST_PBX_CALL_LIMIT;
02552 
02553    res = __ast_pbx_run(c);
02554    decrease_call_count();
02555 
02556    return res;
02557 }

static void* ast_pbx_run_app void *  data  )  [static]
 

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

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

enum ast_pbx_result ast_pbx_start struct ast_channel c  ) 
 

Parameters:
c channel to start the pbx on
Returns:
Zero on success, non-zero on failure

Definition at line 2522 of file pbx.c.

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

Referenced by __oh323_new(), alsa_new(), ast_async_goto(), ast_iax2_new(), ast_modem_new(), ast_pbx_outgoing_exten(), cb_events(), check_goto_on_transfer(), do_immediate_setup(), do_parking_thread(), handle_request_invite(), local_call(), mgcp_new(), nbs_new(), oss_new(), phone_new(), rpt_call(), sip_new(), skinny_new(), vpb_new(), and zt_new().

02523 {
02524    pthread_t t;
02525    pthread_attr_t attr;
02526 
02527    if (!c) {
02528       ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
02529       return AST_PBX_FAILED;
02530    }
02531       
02532    if (increase_call_count(c))
02533       return AST_PBX_CALL_LIMIT;
02534 
02535    /* Start a new thread, and get something handling this channel. */
02536    pthread_attr_init(&attr);
02537    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
02538    if (ast_pthread_create(&t, &attr, pbx_thread, c)) {
02539       ast_log(LOG_WARNING, "Failed to create new channel thread\n");
02540       return AST_PBX_FAILED;
02541    }
02542 
02543    return AST_PBX_SUCCESS;
02544 }

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

Dynamically register a new dial plan application.

Parameters:
app Short name of the application
execute a function callback to execute the application
synopsis a short description of the application
description long description of the application Include a one-line synopsis (e.g. 'hangs up a channel') and a more lengthy, multiline description with more detail, including under what conditions the application will return 0 or -1. This registers an application with asterisks internal application list. Please note: The individual applications themselves are responsible for registering and unregistering CLI commands. It returns 0 on success, -1 on failure.

Definition at line 2863 of file pbx.c.

References apps, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), COLOR_BRCYAN, LOG_ERROR, LOG_WARNING, malloc, ast_app::name, ast_app::next, option_verbose, term_color(), and VERBOSE_PREFIX_2.

Referenced by load_module(), and load_pbx().

02864 {
02865    struct ast_app *tmp, *prev, *cur;
02866    char tmps[80];
02867    int length;
02868    length = sizeof(struct ast_app);
02869    length += strlen(app) + 1;
02870    if (ast_mutex_lock(&applock)) {
02871       ast_log(LOG_ERROR, "Unable to lock application list\n");
02872       return -1;
02873    }
02874    tmp = apps;
02875    while(tmp) {
02876       if (!strcasecmp(app, tmp->name)) {
02877          ast_log(LOG_WARNING, "Already have an application '%s'\n", app);
02878          ast_mutex_unlock(&applock);
02879          return -1;
02880       }
02881       tmp = tmp->next;
02882    }
02883    tmp = malloc(length);
02884    if (tmp) {
02885       memset(tmp, 0, length);
02886       strcpy(tmp->name, app);
02887       tmp->execute = execute;
02888       tmp->synopsis = synopsis;
02889       tmp->description = description;
02890       /* Store in alphabetical order */
02891       cur = apps;
02892       prev = NULL;
02893       while(cur) {
02894          if (strcasecmp(tmp->name, cur->name) < 0)
02895             break;
02896          prev = cur;
02897          cur = cur->next;
02898       }
02899       if (prev) {
02900          tmp->next = prev->next;
02901          prev->next = tmp;
02902       } else {
02903          tmp->next = apps;
02904          apps = tmp;
02905       }
02906    } else {
02907       ast_log(LOG_ERROR, "Out of memory\n");
02908       ast_mutex_unlock(&applock);
02909       return -1;
02910    }
02911    if (option_verbose > 1)
02912       ast_verbose( VERBOSE_PREFIX_2 "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps)));
02913    ast_mutex_unlock(&applock);
02914    return 0;
02915 }

int ast_register_switch struct ast_switch sw  ) 
 

Parameters:
sw switch to register This function registers a populated ast_switch structure with the asterisk switching architecture. It returns 0 on success, and other than 0 on failure

Definition at line 2917 of file pbx.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), LOG_ERROR, LOG_WARNING, ast_switch::name, ast_switch::next, and switches.

Referenced by load_module().

02918 {
02919    struct ast_switch *tmp, *prev=NULL;
02920    if (ast_mutex_lock(&switchlock)) {
02921       ast_log(LOG_ERROR, "Unable to lock switch lock\n");
02922       return -1;
02923    }
02924    tmp = switches;
02925    while(tmp) {
02926       if (!strcasecmp(tmp->name, sw->name))
02927          break;
02928       prev = tmp;
02929       tmp = tmp->next;
02930    }
02931    if (tmp) {  
02932       ast_mutex_unlock(&switchlock);
02933       ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name);
02934       return -1;
02935    }
02936    sw->next = NULL;
02937    if (prev) 
02938       prev->next = sw;
02939    else
02940       switches = sw;
02941    ast_mutex_unlock(&switchlock);
02942    return 0;
02943 }

static int ast_remove_hint struct ast_exten e  )  [static]
 

ast_remove_hint: Remove hint from extension

Definition at line 2136 of file pbx.c.

References AST_EXTENSION_DEACTIVATED, ast_mutex_lock(), ast_mutex_unlock(), ast_state_cb::callback, ast_state_cb::data, free, hints, list, ast_imager::name, ast_hint::next, ast_imager::next, and ast_state_cb::next.

Referenced by ast_context_remove_extension2(), and destroy_exten().

02137 {
02138    /* Cleanup the Notifys if hint is removed */
02139    struct ast_hint *list, *prev = NULL;
02140    struct ast_state_cb *cblist, *cbprev;
02141 
02142    if (!e) 
02143       return -1;
02144 
02145    ast_mutex_lock(&hintlock);
02146 
02147    list = hints;    
02148    while(list) {
02149       if (list->exten==e) {
02150          cbprev = NULL;
02151          cblist = list->callbacks;
02152          while (cblist) {
02153             /* Notify with -1 and remove all callbacks */
02154             cbprev = cblist;      
02155             cblist = cblist->next;
02156             cbprev->callback(list->exten->parent->name, list->exten->exten, AST_EXTENSION_DEACTIVATED, cbprev->data);
02157             free(cbprev);
02158             }
02159             list->callbacks = NULL;
02160 
02161             if (!prev)
02162             hints = list->next;
02163             else
02164             prev->next = list->next;
02165             free(list);
02166        
02167          ast_mutex_unlock(&hintlock);
02168          return 0;
02169       } else {
02170          prev = list;
02171          list = list->next;    
02172       }
02173    }
02174 
02175    ast_mutex_unlock(&hintlock);
02176    return -1;
02177 }

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

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. It returns 0 on success, -1 on failure.

Definition at line 2225 of file pbx.c.

References HELPER_SPAWN, and pbx_extension_helper().

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

02226 {
02227    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, HELPER_SPAWN);
02228 }

int ast_unlock_context struct ast_context con  ) 
 

Parameters:
con context to unlock Unlocks the given context Returns 0 on success, -1 on failure

Definition at line 6278 of file pbx.c.

References ast_mutex_unlock(), and ast_context::lock.

Referenced by complete_context_add_ignorepat(), complete_context_add_include(), complete_context_dont_include(), complete_context_remove_ignorepat(), dundi_precache_full(), find_matching_endwhile(), and handle_save_dialplan().

06279 {
06280    return ast_mutex_unlock(&con->lock);
06281 }

int ast_unlock_contexts void   ) 
 

Returns 0 on success, -1 on failure

Definition at line 6265 of file pbx.c.

References ast_mutex_unlock().

Referenced by ast_add_extension(), ast_context_add_ignorepat(), ast_context_add_include(), ast_context_add_switch(), ast_context_remove_extension(), ast_context_remove_ignorepat(), ast_context_remove_include(), ast_context_remove_switch(), complete_context_add_extension(), complete_context_add_ignorepat(), complete_context_add_include(), complete_context_dont_include(), complete_context_remove_extension(), complete_context_remove_ignorepat(), complete_show_dialplan_context(), dundi_precache_full(), and handle_save_dialplan().

06266 {
06267    return ast_mutex_unlock(&conlock);
06268 }

int ast_unregister_application const char *  app  ) 
 

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 registration mechanisms. It returns 0 on success, and -1 on failure.

Definition at line 3610 of file pbx.c.

References apps, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), free, LOG_ERROR, ast_app::name, ast_app::next, option_verbose, and VERBOSE_PREFIX_2.

Referenced by __unload_module(), and unload_module().

03611 {
03612    struct ast_app *tmp, *tmpl = NULL;
03613    if (ast_mutex_lock(&applock)) {
03614       ast_log(LOG_ERROR, "Unable to lock application list\n");
03615       return -1;
03616    }
03617    tmp = apps;
03618    while(tmp) {
03619       if (!strcasecmp(app, tmp->name)) {
03620          if (tmpl)
03621             tmpl->next = tmp->next;
03622          else
03623             apps = tmp->next;
03624          if (option_verbose > 1)
03625             ast_verbose( VERBOSE_PREFIX_2 "Unregistered application '%s'\n", tmp->name);
03626          free(tmp);
03627          ast_mutex_unlock(&applock);
03628          return 0;
03629       }
03630       tmpl = tmp;
03631       tmp = tmp->next;
03632    }
03633    ast_mutex_unlock(&applock);
03634    return -1;
03635 }

void ast_unregister_switch struct ast_switch sw  ) 
 

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

Definition at line 2945 of file pbx.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), LOG_ERROR, ast_switch::next, and switches.

Referenced by __unload_module(), and unload_module().

02946 {
02947    struct ast_switch *tmp, *prev=NULL;
02948    if (ast_mutex_lock(&switchlock)) {
02949       ast_log(LOG_ERROR, "Unable to lock switch lock\n");
02950       return;
02951    }
02952    tmp = switches;
02953    while(tmp) {
02954       if (tmp == sw) {
02955          if (prev)
02956             prev->next = tmp->next;
02957          else
02958             switches = tmp->next;
02959          tmp->next = NULL;
02960          break;         
02961       }
02962       prev = tmp;
02963       tmp = tmp->next;
02964    }
02965    ast_mutex_unlock(&switchlock);
02966 }

struct ast_exten* ast_walk_context_extensions struct ast_context con,
struct ast_exten exten
 

Definition at line 6385 of file pbx.c.

References exten, and ast_context::root.

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

06387 {
06388    if (!exten)
06389       return con ? con->root : NULL;
06390    else
06391       return exten->next;
06392 }

struct ast_ignorepat* ast_walk_context_ignorepats struct ast_context con,
struct ast_ignorepat ip
 

Definition at line 6421 of file pbx.c.

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

Referenced by complete_context_add_ignorepat(), complete_context_remove_ignorepat(), and handle_save_dialplan().

06423 {
06424    if (!ip)
06425       return con ? con->ignorepats : NULL;
06426    else
06427       return ip->next;
06428 }

struct ast_include* ast_walk_context_includes struct ast_context con,
struct ast_include inc
 

Definition at line 6412 of file pbx.c.

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

Referenced by ast_context_verify_includes(), complete_context_add_include(), complete_context_dont_include(), handle_save_dialplan(), and show_dialplan_helper().

06414 {
06415    if (!inc)
06416       return con ? con->includes : NULL;
06417    else
06418       return inc->next;
06419 }

struct ast_sw* ast_walk_context_switches struct ast_context con,
struct ast_sw sw
 

Definition at line 6394 of file pbx.c.

References ast_context::alts, and ast_sw::next.

Referenced by handle_save_dialplan().

06396 {
06397    if (!sw)
06398       return con ? con->alts : NULL;
06399    else
06400       return sw->next;
06401 }

struct ast_context* ast_walk_contexts struct ast_context con  ) 
 

Definition at line 6377 of file pbx.c.

References contexts, and ast_context::next.

Referenced by ast_add_extension(), ast_context_add_ignorepat(), ast_context_add_include(), ast_context_add_switch(), ast_context_remove_extension(), ast_context_remove_ignorepat(), ast_context_remove_include(), ast_context_remove_switch(), complete_context_add_extension(), complete_context_add_ignorepat(), complete_context_add_include(), complete_context_dont_include(), complete_context_remove_extension(), complete_context_remove_ignorepat(), complete_show_dialplan_context(), dundi_precache_full(), find_matching_endwhile(), handle_save_dialplan(), pbx_load_module(), and show_dialplan_helper().

06378 {
06379    if (!con)
06380       return contexts;
06381    else
06382       return con->next;
06383 }

struct ast_exten* ast_walk_extension_priorities struct ast_exten exten,
struct ast_exten priority
 

Definition at line 6403 of file pbx.c.

References exten, and ast_exten::priority.

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

06405 {
06406    if (!priority)
06407       return exten;
06408    else
06409       return priority->peer;
06410 }

static void* async_wait void *  data  )  [static]
 

Definition at line 4887 of file pbx.c.

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

Referenced by ast_pbx_outgoing_app(), and ast_pbx_outgoing_exten().

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

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

Definition at line 3016 of file pbx.c.

References apps, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), LOG_ERROR, ast_app::name, ast_app::next, and strdup.

03018 {
03019    struct ast_app *a;
03020    int which = 0;
03021 
03022    /* try to lock applications list ... */
03023    if (ast_mutex_lock(&applock)) {
03024       ast_log(LOG_ERROR, "Unable to lock application list\n");
03025       return NULL;
03026    }
03027 
03028    /* ... walk all applications ... */
03029    a = apps; 
03030    while (a) {
03031       /* ... check if word matches this application ... */
03032       if (!strncasecmp(word, a->name, strlen(word))) {
03033          /* ... if this is right app serve it ... */
03034          if (++which > state) {
03035             char *ret = strdup(a->name);
03036             ast_mutex_unlock(&applock);
03037             return ret;
03038          }
03039       }
03040       a = a->next; 
03041    }
03042 
03043    /* no application match */
03044    ast_mutex_unlock(&applock);
03045    return NULL; 
03046 }

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

Definition at line 3263 of file pbx.c.

References ast_strlen_zero(), and strdup.

03264 {
03265    if (pos == 2) {
03266       if (ast_strlen_zero(word)) {
03267          switch (state) {
03268          case 0:
03269             return strdup("like");
03270          case 1:
03271             return strdup("describing");
03272          default:
03273             return NULL;
03274          }
03275       } else if (! strncasecmp(word, "like", strlen(word))) {
03276          if (state == 0) {
03277             return strdup("like");
03278          } else {
03279             return NULL;
03280          }
03281       } else if (! strncasecmp(word, "describing", strlen(word))) {
03282          if (state == 0) {
03283             return strdup("describing");
03284          } else {
03285             return NULL;
03286          }
03287       }
03288    }
03289    return NULL;
03290 }

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

Definition at line 3295 of file pbx.c.

References ast_get_context_name(), ast_lock_contexts(), ast_log(), ast_unlock_contexts(), ast_walk_contexts(), LOG_ERROR, and strdup.

03297 {
03298    struct ast_context *c;
03299    int which = 0;
03300 
03301    /* we are do completion of [exten@]context on second position only */
03302    if (pos != 2) return NULL;
03303 
03304    /* try to lock contexts list ... */
03305    if (ast_lock_contexts()) {
03306       ast_log(LOG_ERROR, "Unable to lock context list\n");
03307       return NULL;
03308    }
03309 
03310    /* ... walk through all contexts ... */
03311    c = ast_walk_contexts(NULL);
03312    while(c) {
03313       /* ... word matches context name? yes? ... */
03314       if (!strncasecmp(word, ast_get_context_name(c), strlen(word))) {
03315          /* ... for serve? ... */
03316          if (++which > state) {
03317             /* ... yes, serve this context name ... */
03318             char *ret = strdup(ast_get_context_name(c));
03319             ast_unlock_contexts();
03320             return ret;
03321          }
03322       }
03323       c = ast_walk_contexts(c);
03324    }
03325 
03326    /* ... unlock and return */
03327    ast_unlock_contexts();
03328    return NULL;
03329 }

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

Definition at line 1238 of file pbx.c.

References acf_root, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), LOG_ERROR, ast_custom_function::name, ast_custom_function::next, and strdup.

01239 {
01240    struct ast_custom_function *acf;
01241    int which = 0;
01242 
01243    /* try to lock functions list ... */
01244    if (ast_mutex_lock(&acflock)) {
01245       ast_log(LOG_ERROR, "Unable to lock function list\n");
01246       return NULL;
01247    }
01248 
01249    acf = acf_root;
01250    while (acf) {
01251       if (!strncasecmp(word, acf->name, strlen(word))) {
01252          if (++which > state) {
01253             char *ret = strdup(acf->name);
01254             ast_mutex_unlock(&acflock);
01255             return ret;
01256          }
01257       }
01258       acf = acf->next; 
01259    }
01260 
01261    ast_mutex_unlock(&acflock);
01262    return NULL; 
01263 }

static void decrease_call_count void   )  [static]
 

Definition at line 2494 of file pbx.c.

References ast_mutex_lock(), and ast_mutex_unlock().

Referenced by ast_pbx_run(), and pbx_thread().

02495 {
02496    ast_mutex_lock(&maxcalllock);
02497    if (countcalls > 0)
02498       countcalls--;
02499    ast_mutex_unlock(&maxcalllock);
02500 }

static void destroy_exten struct ast_exten e  )  [static]
 

Definition at line 5298 of file pbx.c.

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

Referenced by __ast_context_destroy().

05299 {
05300    if (e->priority == PRIORITY_HINT)
05301       ast_remove_hint(e);
05302 
05303    if (e->datad)
05304       e->datad(e->data);
05305    free(e);
05306 }

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

Definition at line 4609 of file pbx.c.

Referenced by ast_add_extension2().

04610 {
04611    int count=0;
04612 
04613    while(*src && (count < len - 1)) {
04614       switch(*src) {
04615       case ' ':
04616          /* otherwise exten => [a-b],1,... doesn't work */
04617          /*    case '-': */
04618          /* Ignore */
04619          break;
04620       default:
04621          *dst = *src;
04622          dst++;
04623       }
04624       src++;
04625       count++;
04626    }
04627    *dst = '\0';
04628 
04629    return count;
04630 }

static unsigned int get_day char *  day  )  [static]
 

Definition at line 3975 of file pbx.c.

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

Referenced by ast_build_timing().

03976 {
03977    char *c;
03978    /* The following line is coincidence, really! */
03979    int s, e, x;
03980    unsigned int mask;
03981 
03982    /* Check for all days */
03983    if (ast_strlen_zero(day) || !strcmp(day, "*")) {
03984       mask = (1 << 30)  + ((1 << 30) - 1);
03985       return mask;
03986    }
03987    /* Get start and ending days */
03988    c = strchr(day, '-');
03989    if (c) {
03990       *c = '\0';
03991       c++;
03992    }
03993    /* Find the start */
03994    if (sscanf(day, "%d", &s) != 1) {
03995       ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", day);
03996       return 0;
03997    }
03998    if ((s < 1) || (s > 31)) {
03999       ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", day);
04000       return 0;
04001    }
04002    s--;
04003    if (c) {
04004       if (sscanf(c, "%d", &e) != 1) {
04005          ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", c);
04006          return 0;
04007       }
04008       if ((e < 1) || (e > 31)) {
04009          ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", c);
04010          return 0;
04011       }
04012       e--;
04013    } else
04014       e = s;
04015    mask = 0;
04016    for (x=s; x!=e; x = (x + 1) % 31) {
04017       mask |= (1 << x);
04018    }
04019    mask |= (1 << x);
04020    return mask;
04021 }

static unsigned int get_dow char *  dow  )  [static]
 

get_dow: Get day of week

Definition at line 3933 of file pbx.c.

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

Referenced by ast_build_timing().

03934 {
03935    char *c;
03936    /* The following line is coincidence, really! */
03937    int s, e, x;
03938    unsigned int mask;
03939 
03940    /* Check for all days */
03941    if (ast_strlen_zero(dow) || !strcmp(dow, "*"))
03942       return (1 << 7) - 1;
03943    /* Get start and ending days */
03944    c = strchr(dow, '-');
03945    if (c) {
03946       *c = '\0';
03947       c++;
03948    } else
03949       c = NULL;
03950    /* Find the start */
03951    s = 0;
03952    while((s < 7) && strcasecmp(dow, days[s])) s++;
03953    if (s >= 7) {
03954       ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", dow);
03955       return 0;
03956    }
03957    if (c) {
03958       e = 0;
03959       while((e < 7) && strcasecmp(c, days[e])) e++;
03960       if (e >= 7) {
03961          ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", c);
03962          return 0;
03963       }
03964    } else
03965       e = s;
03966    mask = 0;
03967    for (x=s; x != e; x = (x + 1) % 7) {
03968       mask |= (1 << x);
03969    }
03970    /* One last one */
03971    mask |= (1 << x);
03972    return mask;
03973 }

static unsigned int get_month char *  mon  )  [static]
 

Definition at line 4039 of file pbx.c.

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

Referenced by ast_build_timing().

04040 {
04041    char *c;
04042    /* The following line is coincidence, really! */
04043    int s, e, x;
04044    unsigned int mask;
04045 
04046    /* Check for all days */
04047    if (ast_strlen_zero(mon) || !strcmp(mon, "*")) 
04048       return (1 << 12) - 1;
04049    /* Get start and ending days */
04050    c = strchr(mon, '-');
04051    if (c) {
04052       *c = '\0';
04053       c++;
04054    }
04055    /* Find the start */
04056    s = 0;
04057    while((s < 12) && strcasecmp(mon, months[s])) s++;
04058    if (s >= 12) {
04059       ast_log(LOG_WARNING, "Invalid month '%s', assuming none\n", mon);
04060       return 0;
04061    }
04062    if (c) {
04063       e = 0;
04064       while((e < 12) && strcasecmp(mon, months[e])) e++;
04065       if (e >= 12) {
04066          ast_log(LOG_WARNING, "Invalid month '%s', assuming none\n", c);
04067          return 0;
04068       }
04069    } else
04070       e = s;
04071    mask = 0;
04072    for (x=s; x!=e; x = (x + 1) % 12) {
04073       mask |= (1 << x);
04074    }
04075    /* One last one */
04076    mask |= (1 << x);
04077    return mask;
04078 }

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

Definition at line 3837 of file pbx.c.

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

Referenced by ast_build_timing().

03838 {
03839    char *e;
03840    int x;
03841    int s1, s2;
03842    int e1, e2;
03843    /* int cth, ctm; */
03844 
03845    /* start disabling all times, fill the fields with 0's, as they may contain garbage */
03846    memset(i->minmask, 0, sizeof(i->minmask));
03847    
03848    /* Star is all times */
03849    if (ast_strlen_zero(times) || !strcmp(times, "*")) {
03850       for (x=0; x<24; x++)
03851          i->minmask[x] = (1 << 30) - 1;
03852       return;
03853    }
03854    /* Otherwise expect a range */
03855    e = strchr(times, '-');
03856    if (!e) {
03857       ast_log(LOG_WARNING, "Time range is not valid. Assuming no restrictions based on time.\n");
03858       return;
03859    }
03860    *e = '\0';
03861    e++;
03862    while(*e && !isdigit(*e)) 
03863       e++;
03864    if (!*e) {
03865       ast_log(LOG_WARNING, "Invalid time range.  Assuming no restrictions based on time.\n");
03866       return;
03867    }
03868    if (sscanf(times, "%d:%d", &s1, &s2) != 2) {
03869       ast_log(LOG_WARNING, "%s isn't a time.  Assuming no restrictions based on time.\n", times);
03870       return;
03871    }
03872    if (sscanf(e, "%d:%d", &e1, &e2) != 2) {
03873       ast_log(LOG_WARNING, "%s isn't a time.  Assuming no restrictions based on time.\n", e);
03874       return;
03875    }
03876 
03877 #if 1
03878    s1 = s1 * 30 + s2/2;
03879    if ((s1 < 0) || (s1 >= 24*30)) {
03880       ast_log(LOG_WARNING, "%s isn't a valid start time. Assuming no time.\n", times);
03881       return;
03882    }
03883    e1 = e1 * 30 + e2/2;
03884    if ((e1 < 0) || (e1 >= 24*30)) {
03885       ast_log(LOG_WARNING, "%s isn't a valid end time. Assuming no time.\n", e);
03886       return;
03887    }
03888    /* Go through the time and enable each appropriate bit */
03889    for (x=s1;x != e1;x = (x + 1) % (24 * 30)) {
03890       i->minmask[x/30] |= (1 << (x % 30));
03891    }
03892    /* Do the last one */
03893    i->minmask[x/30] |= (1 << (x % 30));
03894 #else
03895    for (cth=0; cth<24; cth++) {
03896       /* Initialize masks to blank */
03897       i->minmask[cth] = 0;
03898       for (ctm=0; ctm<30; ctm++) {
03899          if (
03900          /* First hour with more than one hour */
03901                (((cth == s1) && (ctm >= s2)) &&
03902                 ((cth < e1)))
03903          /* Only one hour */
03904          ||    (((cth == s1) && (ctm >= s2)) &&
03905                 ((cth == e1) && (ctm <= e2)))
03906          /* In between first and last hours (more than 2 hours) */
03907          ||    ((cth > s1) &&
03908                 (cth < e1))
03909          /* Last hour with more than one hour */
03910          ||    ((cth > s1) &&
03911                 ((cth == e1) && (ctm <= e2)))
03912          )
03913             i->minmask[cth] |= (1 << (ctm / 2));
03914       }
03915    }
03916 #endif
03917    /* All done */
03918    return;
03919 }

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

Definition at line 3048 of file pbx.c.

References apps, ast_cli(), ast_log(), AST_MAX_APP, ast_mutex_lock(), COLOR_CYAN, COLOR_MAGENTA, ast_app::description, description, LOG_ERROR, ast_app::name, RESULT_SHOWUSAGE, ast_app::synopsis, synopsis, and term_color().

03049 {
03050    struct ast_app *a;
03051    int app, no_registered_app = 1;
03052 
03053    if (argc < 3) return RESULT_SHOWUSAGE;
03054 
03055    /* try to lock applications list ... */
03056    if (ast_mutex_lock(&applock)) {
03057       ast_log(LOG_ERROR, "Unable to lock application list\n");
03058       return -1;
03059    }
03060 
03061    /* ... go through all applications ... */
03062    a = apps; 
03063    while (a) {
03064       /* ... compare this application name with all arguments given
03065        * to 'show application' command ... */
03066       for (app = 2; app < argc; app++) {
03067          if (!strcasecmp(a->name, argv[app])) {
03068             /* Maximum number of characters added by terminal coloring is 22 */
03069             char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40];
03070             char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL;
03071             int synopsis_size, description_size;
03072 
03073             no_registered_app = 0;
03074 
03075             if (a->synopsis)
03076                synopsis_size = strlen(a->synopsis) + 23;
03077             else
03078                synopsis_size = strlen("Not available") + 23;
03079             synopsis = alloca(synopsis_size);
03080 
03081             if (a->description)
03082                description_size = strlen(a->description) + 23;
03083             else
03084                description_size = strlen("Not available") + 23;
03085             description = alloca(description_size);
03086 
03087             if (synopsis && description) {
03088                snprintf(info, 64 + AST_MAX_APP, "\n  -= Info about application '%s' =- \n\n", a->name);
03089                term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22);
03090                term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
03091                term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
03092                term_color(synopsis,
03093                            a->synopsis ? a->synopsis : "Not available",
03094                            COLOR_CYAN, 0, synopsis_size);
03095                term_color(description,
03096                            a->description ? a->description : "Not available",
03097                            COLOR_CYAN, 0, description_size);
03098 
03099                ast_cli(fd,"%s%s%s\n\n%s%s\n", infotitle, syntitle, synopsis, destitle, description);
03100             } else {
03101                /* ... one of our applications, show info ...*/
03102                ast_cli(fd,"\n  -= Info about application '%s' =- \n\n"
03103                   "[Synopsis]\n  %s\n\n"
03104                   "[Description]\n%s\n",
03105                   a->name,
03106                   a->synopsis ? a->synopsis : "Not available",
03107                   a->description ? a->description : "Not available");
03108             }
03109          }
03110       }
03111       a = a->next; 
03112    }
03113 
03114    ast_mutex_unlock(&applock);
03115 
03116    /* we found at least one app? no? */
03117    if (no_registered_app) {
03118       ast_cli(fd, "Your application(s) is (are) not registered\n");
03119       return RESULT_FAILURE;
03120    }
03121 
03122    return RESULT_SUCCESS;
03123 }

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

Definition at line 3186 of file pbx.c.

References apps, ast_cli(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), LOG_ERROR, ast_app::name, ast_app::next, and strcasestr().

03187 {
03188    struct ast_app *a;
03189    int like=0, describing=0;
03190    int total_match = 0;    /* Number of matches in like clause */
03191    int total_apps = 0;  /* Number of apps registered */
03192    
03193    /* try to lock applications list ... */
03194    if (ast_mutex_lock(&applock)) {
03195       ast_log(LOG_ERROR, "Unable to lock application list\n");
03196       return -1;
03197    }
03198 
03199    /* ... have we got at least one application (first)? no? */
03200    if (!apps) {
03201       ast_cli(fd, "There are no registered applications\n");
03202       ast_mutex_unlock(&applock);
03203       return -1;
03204    }
03205 
03206    /* show applications like <keyword> */
03207    if ((argc == 4) && (!strcmp(argv[2], "like"))) {
03208       like = 1;
03209    } else if ((argc > 3) && (!strcmp(argv[2], "describing"))) {
03210       describing = 1;
03211    }
03212 
03213    /* show applications describing <keyword1> [<keyword2>] [...] */
03214    if ((!like) && (!describing)) {
03215       ast_cli(fd, "    -= Registered Asterisk Applications =-\n");
03216    } else {
03217       ast_cli(fd, "    -= Matching Asterisk Applications =-\n");
03218    }
03219 
03220    /* ... go through all applications ... */
03221    for (a = apps; a; a = a->next) {
03222       /* ... show informations about applications ... */
03223       int printapp=0;
03224       total_apps++;
03225       if (like) {
03226          if (strcasestr(a->name, argv[3])) {
03227             printapp = 1;
03228             total_match++;
03229          }
03230       } else if (describing) {
03231          if (a->description) {
03232             /* Match all words on command line */
03233             int i;
03234             printapp = 1;
03235             for (i=3; i<argc; i++) {
03236                if (!strcasestr(a->description, argv[i])) {
03237                   printapp = 0;
03238                } else {
03239                   total_match++;
03240                }
03241             }
03242          }
03243       } else {
03244          printapp = 1;
03245       }
03246 
03247       if (printapp) {
03248          ast_cli(fd,"  %20s: %s\n", a->name, a->synopsis ? a->synopsis : "<Synopsis not available>");
03249       }
03250    }
03251    if ((!like) && (!describing)) {
03252       ast_cli(fd, "    -= %d Applications Registered =-\n",total_apps);
03253    } else {
03254       ast_cli(fd, "    -= %d Applications Matching =-\n",total_match);
03255    }
03256    
03257    /* ... unlock and return */
03258    ast_mutex_unlock(&applock);
03259 
03260    return RESULT_SUCCESS;
03261 }

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

Definition at line 3526 of file pbx.c.

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

03527 {
03528    char *exten = NULL, *context = NULL;
03529    /* Variables used for different counters */
03530    struct dialplan_counters counters;
03531    char *incstack[AST_PBX_MAX_STACK];
03532    memset(&counters, 0, sizeof(counters));
03533 
03534    if (argc != 2 && argc != 3) 
03535       return RESULT_SHOWUSAGE;
03536 
03537    /* we obtain [exten@]context? if yes, split them ... */
03538    if (argc == 3) {
03539       char *splitter = ast_strdupa(argv[2]);
03540       /* is there a '@' character? */
03541       if (splitter && strchr(argv[2], '@')) {
03542          /* yes, split into exten & context ... */
03543          exten   = strsep(&splitter, "@");
03544          context = splitter;
03545 
03546          /* check for length and change to NULL if ast_strlen_zero() */
03547          if (ast_strlen_zero(exten))
03548             exten = NULL;
03549          if (ast_strlen_zero(context))
03550             context = NULL;
03551          show_dialplan_helper(fd, context, exten, &counters, NULL, 0, incstack);
03552       } else {
03553          /* no '@' char, only context given */
03554          context = argv[2];
03555          if (ast_strlen_zero(context))
03556             context = NULL;
03557          show_dialplan_helper(fd, context, exten, &counters, NULL, 0, incstack);
03558       }
03559    } else {
03560       /* Show complete dial plan */
03561       show_dialplan_helper(fd, NULL, NULL, &counters, NULL, 0, incstack);
03562    }
03563 
03564    /* check for input failure and throw some error messages */
03565    if (context && !counters.context_existence) {
03566       ast_cli(fd, "There is no existence of '%s' context\n", context);
03567       return RESULT_FAILURE;
03568    }
03569 
03570    if (exten && !counters.extension_existence) {
03571       if (context)
03572          ast_cli(fd, "There is no existence of %s@%s extension\n",
03573             exten, context);
03574       else
03575          ast_cli(fd,
03576             "There is no existence of '%s' extension in all contexts\n",
03577             exten);
03578       return RESULT_FAILURE;
03579    }
03580 
03581    ast_cli(fd,"-= %d %s (%d %s) in %d %s. =-\n",
03582             counters.total_exten, counters.total_exten == 1 ? "extension" : "extensions",
03583             counters.total_prio, counters.total_prio == 1 ? "priority" : "priorities",
03584             counters.total_context, counters.total_context == 1 ? "context" : "contexts");
03585 
03586    /* everything ok */
03587    return RESULT_SUCCESS;
03588 }

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

Definition at line 1183 of file pbx.c.

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

01184 {
01185    struct ast_custom_function *acf;
01186    /* Maximum number of characters added by terminal coloring is 22 */
01187    char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40];
01188    char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL;
01189    char stxtitle[40], *syntax = NULL;
01190    int synopsis_size, description_size, syntax_size;
01191 
01192    if (argc < 3) return RESULT_SHOWUSAGE;
01193 
01194    if (!(acf = ast_custom_function_find(argv[2]))) {
01195       ast_cli(fd, "No function by that name registered.\n");
01196       return RESULT_FAILURE;
01197 
01198    }
01199 
01200    if (acf->synopsis)
01201       synopsis_size = strlen(acf->synopsis) + 23;
01202    else
01203       synopsis_size = strlen("Not available") + 23;
01204    synopsis = alloca(synopsis_size);
01205    
01206    if (acf->desc)
01207       description_size = strlen(acf->desc) + 23;
01208    else
01209       description_size = strlen("Not available") + 23;
01210    description = alloca(description_size);
01211 
01212    if (acf->syntax)
01213       syntax_size = strlen(acf->syntax) + 23;
01214    else
01215       syntax_size = strlen("Not available") + 23;
01216    syntax = alloca(syntax_size);
01217 
01218    snprintf(info, 64 + AST_MAX_APP, "\n  -= Info about function '%s' =- \n\n", acf->name);
01219    term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22);
01220    term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40);
01221    term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
01222    term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
01223    term_color(syntax,
01224          acf->syntax ? acf->syntax : "Not available",
01225          COLOR_CYAN, 0, syntax_size);
01226    term_color(synopsis,
01227          acf->synopsis ? acf->synopsis : "Not available",
01228          COLOR_CYAN, 0, synopsis_size);
01229    term_color(description,
01230          acf->desc ? acf->desc : "Not available",
01231          COLOR_CYAN, 0, description_size);
01232    
01233    ast_cli(fd,"%s%s%s\n\n%s%s\n\n%s%s\n", infotitle, stxtitle, syntax, syntitle, synopsis, destitle, description);
01234 
01235    return RESULT_SUCCESS;
01236 }

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

Definition at line 1169 of file pbx.c.

References acf_root, ast_cli(), ast_custom_function::name, ast_custom_function::next, ast_custom_function::synopsis, and ast_custom_function::syntax.

01170 {
01171    struct ast_custom_function *acf;
01172    int count_acf = 0;
01173 
01174    ast_cli(fd, "Installed Custom Functions:\n--------------------------------------------------------------------------------\n");
01175    for (acf = acf_root ; acf; acf = acf->next) {
01176       ast_cli(fd, "%-20.20s  %-35.35s  %s\n", acf->name, acf->syntax, acf->synopsis);
01177       count_acf++;
01178    }
01179    ast_cli(fd, "%d custom functions installed.\n", count_acf);
01180    return 0;
01181 }

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

handle_show_hints: CLI support for listing registred dial plan hints

Definition at line 3126 of file pbx.c.

References ast_cli(), ast_extension_state2str(), ast_get_extension_app(), ast_get_extension_name(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_hint::callbacks, ast_hint::exten, hints, ast_hint::laststate, LOG_ERROR, ast_hint::next, ast_state_cb::next, and RESULT_SUCCESS.

03127 {
03128    struct ast_hint *hint;
03129    int num = 0;
03130    int watchers;
03131    struct ast_state_cb *watcher;
03132 
03133    if (!hints) {
03134       ast_cli(fd, "There are no registered dialplan hints\n");
03135       return RESULT_SUCCESS;
03136    }
03137    /* ... we have hints ... */
03138    ast_cli(fd, "\n    -= Registered Asterisk Dial Plan Hints =-\n");
03139    if (ast_mutex_lock(&hintlock)) {
03140       ast_log(LOG_ERROR, "Unable to lock hints\n");
03141       return -1;
03142    }
03143    hint = hints;
03144    while (hint) {
03145       watchers = 0;
03146       for (watcher = hint->callbacks; watcher; watcher = watcher->next)
03147          watchers++;
03148       ast_cli(fd, "   %-20.20s: %-20.20s  State:%-15.15s Watchers %2d\n",
03149          ast_get_extension_name(hint->exten), ast_get_extension_app(hint->exten),
03150          ast_extension_state2str(hint->laststate), watchers);
03151       num++;
03152       hint = hint->next;
03153    }
03154    ast_cli(fd, "----------------\n");
03155    ast_cli(fd, "- %d hints registered\n", num);
03156    ast_mutex_unlock(&hintlock);
03157    return RESULT_SUCCESS;
03158 }

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

handle_show_switches: CLI support for listing registred dial plan switches

Definition at line 3161 of file pbx.c.

References ast_cli(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_switch::description, LOG_ERROR, ast_switch::name, ast_switch::next, RESULT_SUCCESS, and switches.

03162 {
03163    struct ast_switch *sw;
03164    if (!switches) {
03165       ast_cli(fd, "There are no registered alternative switches\n");
03166       return RESULT_SUCCESS;
03167    }
03168    /* ... we have applications ... */
03169    ast_cli(fd, "\n    -= Registered Asterisk Alternative Switches =-\n");
03170    if (ast_mutex_lock(&switchlock)) {
03171       ast_log(LOG_ERROR, "Unable to lock switches\n");
03172       return -1;
03173    }
03174    sw = switches;
03175    while (sw) {
03176       ast_cli(fd, "%s: %s\n", sw->name, sw->description);
03177       sw = sw->next;
03178    }
03179    ast_mutex_unlock(&switchlock);
03180    return RESULT_SUCCESS;
03181 }

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

Definition at line 612 of file pbx.c.

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

00613 {
00614    if (!i->hastime)
00615       return 1;
00616 
00617    return ast_check_timing(&(i->timing));
00618 }

static int increase_call_count const struct ast_channel c  )  [static]
 

Definition at line 2469 of file pbx.c.

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

Referenced by ast_pbx_run(), and ast_pbx_start().

02470 {
02471    int failed = 0;
02472    double curloadavg;
02473    ast_mutex_lock(&maxcalllock);
02474    if (option_maxcalls) {
02475       if (countcalls >= option_maxcalls) {
02476          ast_log(LOG_NOTICE, "Maximum call limit of %d calls exceeded by '%s'!\n", option_maxcalls, c->name);
02477          failed = -1;
02478       }
02479    }
02480    if (option_maxload) {
02481       getloadavg(&curloadavg, 1);
02482       if (curloadavg >= option_maxload) {
02483          ast_log(LOG_NOTICE, "Maximum loadavg limit of %lf load exceeded by '%s' (currently %f)!\n", option_maxload, c->name, curloadavg);
02484          failed = -1;
02485       }
02486    }
02487    if (!failed)
02488       countcalls++;  
02489    ast_mutex_unlock(&maxcalllock);
02490 
02491    return failed;
02492 }

int load_pbx void   ) 
 

Definition at line 6233 of file pbx.c.

References ast_cli_register_multiple(), AST_LIST_HEAD_INIT_NOLOCK, ast_log(), ast_register_application(), ast_verbose(), builtins, description, LOG_ERROR, name, option_verbose, pbx_cli, synopsis, and VERBOSE_PREFIX_1.

06234 {
06235    int x;
06236 
06237    /* Initialize the PBX */
06238    if (option_verbose) {
06239       ast_verbose( "Asterisk PBX Core Initializing\n");
06240       ast_verbose( "Registering builtin applications:\n");
06241    }
06242    AST_LIST_HEAD_INIT_NOLOCK(&globals);
06243    ast_cli_register_multiple(pbx_cli, sizeof(pbx_cli) / sizeof(pbx_cli[0]));
06244 
06245    /* Register builtin applications */
06246    for (x=0; x<sizeof(builtins) / sizeof(struct pbx_builtin); x++) {
06247       if (option_verbose)
06248          ast_verbose( VERBOSE_PREFIX_1 "[%s]\n", builtins[x].name);
06249       if (ast_register_application(builtins[x].name, builtins[x].execute, builtins[x].synopsis, builtins[x].description)) {
06250          ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name);
06251          return -1;
06252       }
06253    }
06254    return 0;
06255 }

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

Definition at line 759 of file pbx.c.

References ast_extension_match(), and ast_strlen_zero().

00760 {
00761    int failresult;
00762    
00763    /* If the Caller*ID pattern is empty, then we're matching NO Caller*ID, so
00764       failing to get a number should count as a match, otherwise not */
00765 
00766    if (!ast_strlen_zero(cidpattern))
00767       failresult = 0;
00768    else
00769       failresult = 1;
00770 
00771    if (!callerid)
00772       return failresult;
00773 
00774    return ast_extension_match(cidpattern, callerid);
00775 }

static void null_datad void *  foo  )  [static]
 

Definition at line 4632 of file pbx.c.

Referenced by ast_add_extension2().

04633 {
04634 }

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

Definition at line 905 of file pbx.c.

References DONT_HAVE_LENGTH.

Referenced by pbx_retrieve_variable(), and pbx_substitute_variables_helper_full().

00906 {
00907    char *varchar, *offsetchar = NULL;
00908    int parens=0;
00909 
00910    *offset = 0;
00911    *length = DONT_HAVE_LENGTH;
00912    *isfunc = 0;
00913    for (varchar=var; *varchar; varchar++) {
00914       switch (*varchar) {
00915       case '(':
00916          (*isfunc)++;
00917          parens++;
00918          break;
00919       case ')':
00920          parens--;
00921          break;
00922       case ':':
00923          if (parens == 0) {
00924             offsetchar = varchar + 1;
00925             *varchar = '\0';
00926             goto pvn_endfor;
00927          }
00928       }
00929    }
00930 pvn_endfor:
00931    if (offsetchar) {
00932       sscanf(offsetchar, "%d:%d", offset, length);
00933       return 1;
00934    } else {
00935       return 0;
00936    }
00937 }

void pbx_builtin_clear_globals void   ) 
 

Definition at line 6122 of file pbx.c.

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

Referenced by reload().

06123 {
06124    struct ast_var_t *vardata;
06125 
06126    ast_mutex_lock(&globalslock);
06127    while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries)))
06128       ast_var_delete(vardata);
06129    ast_mutex_unlock(&globalslock);
06130 }

char* pbx_builtin_getvar_helper struct ast_channel chan,
const char *  name
 

Definition at line 5917 of file pbx.c.

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

Referenced by __login_exec(), action_getvar(), agentmonitoroutgoing_exec(), ast_app_group_get_count(), ast_app_group_match_get_count(), ast_bridge_call(), ast_feature_interpret(), ast_monitor_stop(), ast_osp_lookup(), builtin_atxfer(), builtin_automonitor(), builtin_blindtransfer(), check_goto_on_transfer(), conf_exec(), conf_run(), dial_exec_full(), do_chanreads(), dundi_exec(), dundi_helper(), get_index(), group_check_exec(), group_count_exec(), group_count_function_read(), group_function_read(), iax2_exec(), leave_voicemail(), macro_exec(), misdn_answer(), misdn_hangup(), oh323_hangup(), ospfinished_exec(), ospnext_exec(), queue_exec(), retrydial_exec(), return_exec(), sip_addheader(), try_suggested_sip_codec(), wait_for_answer(), zt_call(), and zt_hangup().

05918 {
05919         struct ast_var_t *variables;
05920         char *ret = NULL;
05921         int i;
05922         struct varshead *places[2] = { NULL, &globals };
05923         
05924         if (!name)
05925                 return NULL;
05926         if (chan)
05927                 places[0] = &chan->varshead;
05928 
05929         for (i = 0; i < 2; i++) {
05930                 if (!places[i])
05931                         continue;
05932                 if (places[i] == &globals)
05933                         ast_mutex_lock(&globalslock);
05934                 AST_LIST_TRAVERSE(places[i], variables, entries) {
05935                         if (!strcmp(name, ast_var_name(variables))) {
05936                                 ret = ast_var_value(variables);
05937                                 break;
05938                         }
05939                 }
05940                 if (places[i] == &globals)
05941                         ast_mutex_unlock(&globalslock);
05942                 if (ret)
05943                         break;
05944         }
05945 
05946         return ret;                
05947 }

static int pbx_builtin_gotoif struct ast_channel ,
void * 
[static]
 

Definition at line 6151 of file pbx.c.

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

06152 {
06153    char *condition, *branch1, *branch2, *branch;
06154    char *s;
06155    int rc;
06156    char *stringp=NULL;
06157 
06158    if (ast_strlen_zero(data)) {
06159       ast_log(LOG_WARNING, "Ignoring, since there is no variable to check\n");
06160       return 0;
06161    }
06162    
06163    s = ast_strdupa(data);
06164    stringp = s;
06165    condition = strsep(&stringp,"?");
06166    branch1 = strsep(&stringp,":");
06167    branch2 = strsep(&stringp,"");
06168    branch = pbx_checkcondition(condition) ? branch1 : branch2;
06169    
06170    if (ast_strlen_zero(branch)) {
06171       ast_log(LOG_DEBUG, "Not taking any branch\n");
06172       return 0;
06173    }
06174    
06175    rc = pbx_builtin_goto(chan, branch);
06176 
06177    return rc;
06178 }           

int pbx_builtin_importvar struct ast_channel ,
void * 
[static]
 

Definition at line 6061 of file pbx.c.

References ast_get_channel_by_name_locked(), ast_log(), ast_mutex_unlock(), ast_strdupa, ast_strlen_zero(), ast_channel::lock, LOG_WARNING, name, pbx_builtin_setvar_helper(), pbx_substitute_variables_helper(), s, strsep(), and VAR_BUF_SIZE.

06062 {
06063    char *name;
06064    char *value;
06065    char *stringp=NULL;
06066    char *channel;
06067    struct ast_channel *chan2;
06068    char tmp[VAR_BUF_SIZE]="";
06069    char *s;
06070 
06071    if (ast_strlen_zero(data)) {
06072       ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n");
06073       return 0;
06074    }
06075 
06076    stringp = ast_strdupa(data);
06077    name = strsep(&stringp,"=");
06078    channel = strsep(&stringp,"|"); 
06079    value = strsep(&stringp,"\0");
06080    if (channel && value && name) {
06081       chan2 = ast_get_channel_by_name_locked(channel);
06082       if (chan2) {
06083          s = alloca(strlen(value) + 4);
06084          if (s) {
06085             sprintf(s, "${%s}", value);
06086             pbx_substitute_variables_helper(chan2, s, tmp, sizeof(tmp) - 1);
06087          }
06088          ast_mutex_unlock(&chan2->lock);
06089       }
06090       pbx_builtin_setvar_helper(chan, name, tmp);
06091    }
06092 
06093    return(0);
06094 }

static int pbx_builtin_noop struct ast_channel ,
void * 
[static]
 

Definition at line 6116 of file pbx.c.

06117 {
06118    return 0;
06119 }

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

Definition at line 5949 of file pbx.c.

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

Referenced by gosub_exec().

05950 {
05951    struct ast_var_t *newvariable;
05952    struct varshead *headp;
05953 
05954    if (name[strlen(name)-1] == ')') {
05955       ast_log(LOG_WARNING, "Cannot push a value onto a function\n");
05956       return ast_func_write(chan, name, value);
05957    }
05958 
05959    headp = (chan) ? &chan->varshead : &globals;
05960 
05961    if (value) {
05962       if ((option_verbose > 1) && (headp == &globals))
05963          ast_verbose(VERBOSE_PREFIX_2 "Setting global variable '%s' to '%s'\n", name, value);
05964       newvariable = ast_var_assign(name, value);
05965       if (headp == &globals)
05966          ast_mutex_lock(&globalslock);
05967       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
05968       if (headp == &globals)
05969          ast_mutex_unlock(&globalslock);
05970    }
05971 }

static int pbx_builtin_saycharacters struct ast_channel ,
void * 
[static]
 

Definition at line 6215 of file pbx.c.

References ast_say_character_str(), and ast_channel::language.

06216 {
06217    int res = 0;
06218 
06219    if (data)
06220       res = ast_say_character_str(chan, (char *)data, "", chan->language);
06221    return res;
06222 }

static int pbx_builtin_saydigits struct ast_channel ,
void * 
[static]
 

Definition at line 6206 of file pbx.c.

References ast_say_digit_str(), and ast_channel::language.

06207 {
06208    int res = 0;
06209 
06210    if (data)
06211       res = ast_say_digit_str(chan, (char *)data, "", chan->language);
06212    return res;
06213 }

static int pbx_builtin_saynumber struct ast_channel ,
void * 
[static]
 

Definition at line 6180 of file pbx.c.

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

06181 {
06182    int res = 0;
06183    char tmp[256];
06184    char *number = (char *) NULL;
06185    char *options = (char *) NULL;
06186 
06187    
06188    if (ast_strlen_zero(data)) {
06189       ast_log(LOG_WARNING, "SayNumber requires an argument (number)\n");
06190       return -1;
06191    }
06192    ast_copy_string(tmp, (char *) data, sizeof(tmp));
06193    number=tmp;
06194    strsep(&number, "|");
06195    options = strsep(&number, "|");
06196    if (options) { 
06197       if ( strcasecmp(options, "f") && strcasecmp(options,"m") && 
06198          strcasecmp(options, "c") && strcasecmp(options, "n") ) {
06199          ast_log(LOG_WARNING, "SayNumber gender option is either 'f', 'm', 'c' or 'n'\n");
06200          return -1;
06201       }
06202    }
06203    return res = ast_say_number(chan, atoi((char *) tmp), "", chan->language, options);
06204 }

static int pbx_builtin_sayphonetic struct ast_channel ,
void * 
[static]
 

Definition at line 6224 of file pbx.c.

References ast_say_phonetic_str(), and ast_channel::language.

06225 {
06226    int res = 0;
06227 
06228    if (data)
06229       res = ast_say_phonetic_str(chan, (char *)data, "", chan->language);
06230    return res;
06231 }

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

Definition at line 5890 of file pbx.c.

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

Referenced by dumpchan_exec(), and handle_showchan().

05891 {
05892    struct ast_var_t *variables;
05893    char *var, *val;
05894    int total = 0;
05895 
05896    if (!chan)
05897       return 0;
05898 
05899    memset(buf, 0, size);
05900 
05901    AST_LIST_TRAVERSE(&chan->varshead, variables, entries) {
05902       if(variables &&
05903          (var=ast_var_name(variables)) && (val=ast_var_value(variables)) &&
05904          !ast_strlen_zero(var) && !ast_strlen_zero(val)) {
05905          if (ast_build_string(&buf, &size, "%s=%s\n", var, val)) {
05906             ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
05907             break;
05908          } else
05909             total++;
05910       } else 
05911          break;
05912    }
05913    
05914    return total;
05915 }

static int pbx_builtin_setglobalvar struct ast_channel ,
void * 
[static]
 

Definition at line 6096 of file pbx.c.

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

06097 {
06098    char *name;
06099    char *value;
06100    char *stringp = NULL;
06101 
06102    if (ast_strlen_zero(data)) {
06103       ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n");
06104       return 0;
06105    }
06106 
06107    stringp = data;
06108    name = strsep(&stringp, "=");
06109    value = strsep(&stringp, "\0"); 
06110 
06111    pbx_builtin_setvar_helper(NULL, name, value);
06112 
06113    return(0);
06114 }

int pbx_builtin_setvar struct ast_channel ,
void * 
 

Definition at line 6025 of file pbx.c.

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

Referenced by handle_globals(), and pbx_builtin_setvar_old().

06026 {
06027    char *name, *value, *mydata;
06028    int argc;
06029    char *argv[24];      /* this will only support a maximum of 24 variables being set in a single operation */
06030    int global = 0;
06031    int x;
06032 
06033    if (ast_strlen_zero(data)) {
06034       ast_log(LOG_WARNING, "Set requires at least one variable name/value pair.\n");
06035       return 0;
06036    }
06037 
06038    mydata = ast_strdupa(data);
06039    argc = ast_app_separate_args(mydata, '|', argv, sizeof(argv) / sizeof(argv[0]));
06040 
06041    /* check for a trailing flags argument */
06042    if ((argc > 1) && !strchr(argv[argc-1], '=')) {
06043       argc--;
06044       if (strchr(argv[argc], 'g'))
06045          global = 1;
06046    }
06047 
06048    for (x = 0; x < argc; x++) {
06049       name = argv[x];
06050       if ((value = strchr(name, '='))) {
06051          *value = '\0';
06052          value++;
06053          pbx_builtin_setvar_helper((global) ? NULL : chan, name, value);
06054       } else
06055          ast_log(LOG_WARNING, "Ignoring entry '%s' with no = (and not last 'options' entry)\n", name);
06056    }
06057 
06058    return(0);
06059 }

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

Definition at line 5973 of file pbx.c.

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

Referenced by action_setvar(), aPGSQL_connect(), aPGSQL_fetch(), aPGSQL_query(), aqm_exec(), ast_app_group_set_channel(), ast_bridge_call(), ast_iax2_new(), ast_monitor_start(), ast_set_variables(), background_detect_exec(), builtin_blindtransfer(), builtin_function_set(), cb_events(), chanavail_exec(), controlplayback_exec(), count_exec(), curl_exec(), cut_exec(), dundi_lookup_exec(), enumlookup_exec(), eval_exec(), function_db_exists(), function_db_read(), get_exec(), get_refer_info(), group_check_exec(), group_count_exec(), group_match_count_exec(), handle_setvariable(), hasvoicemail_exec(), leave_voicemail(), lookupblacklist_exec(), macro_exec(), math_exec(), md5_exec(), md5check_exec(), misdn_call(), misdn_tx2ast_frm(), mixmonitor_exec(), monitor_handle_owned(), ospfinished_exec(), osplookup_exec(), ospnext_exec(), pbx_builtin_importvar(), pbx_builtin_setglobalvar(), pbx_builtin_setvar(), pbx_extension_helper(), pbx_load_module(), play_message_datetime(), playback_exec(), pop_exec(), pqm_exec(), prep_email_sub_vars(), privacy_exec(), read_exec(), readfile_exec(), realtime_exec(), record_exec(), return_exec(), rqm_exec(), sendimage_exec(), sendtext_exec(), sendurl_exec(), set_agentbycallerid(), set_queue_result(), sip_addheader(), sip_getheader(), sip_new(), sort_exec(), start_monitor_exec(), system_exec_helper(), transfer_exec(), txtcidname_exec(), upqm_exec(), vm_box_exists(), vm_exec(), vmauthenticate(), zt_new(), and zt_read().

05974 {
05975    struct ast_var_t *newvariable;
05976    struct varshead *headp;
05977    const char *nametail = name;
05978 
05979    if (name[strlen(name)-1] == ')')
05980       return ast_func_write(chan, name, value);
05981 
05982    headp = (chan) ? &chan->varshead : &globals;
05983 
05984    /* For comparison purposes, we have to strip leading underscores */
05985    if (*nametail == '_') {
05986       nametail++;
05987       if (*nametail == '_') 
05988          nametail++;
05989    }
05990 
05991    if (headp == &globals)
05992       ast_mutex_lock(&globalslock);
05993    AST_LIST_TRAVERSE (headp, newvariable, entries) {
05994       if (strcasecmp(ast_var_name(newvariable), nametail) == 0) {
05995          /* there is already such a variable, delete it */
05996          AST_LIST_REMOVE(headp, newvariable, entries);
05997          ast_var_delete(newvariable);
05998          break;
05999       }
06000    }
06001    
06002    if (value) {
06003       if ((option_verbose > 1) && (headp == &globals))
06004          ast_verbose(VERBOSE_PREFIX_2 "Setting global variable '%s' to '%s'\n", name, value);
06005       newvariable = ast_var_assign(name, value);   
06006       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
06007    }
06008    
06009    if (headp == &globals)
06010       ast_mutex_unlock(&globalslock);
06011 }

int pbx_builtin_setvar_old struct ast_channel ,
void * 
[static]
 

Definition at line 6013 of file pbx.c.

References ast_log(), LOG_WARNING, and pbx_builtin_setvar().

06014 {
06015    static int deprecation_warning = 0;
06016 
06017    if (!deprecation_warning) {
06018       ast_log(LOG_WARNING, "SetVar is deprecated, please use Set instead.\n");
06019       deprecation_warning = 1;
06020    }
06021 
06022    return pbx_builtin_setvar(chan, data);
06023 }

int pbx_checkcondition char *  condition  ) 
 

Definition at line 6132 of file pbx.c.

Referenced by gosubif_exec(), and pbx_builtin_gotoif().

06133 {
06134    if (condition) {
06135       if (*condition == '\0') {
06136          /* Empty strings are false */
06137          return 0;
06138       } else if (*condition >= '0' && *condition <= '9') {
06139          /* Numbers are evaluated for truth */
06140          return atoi(condition);
06141       } else {
06142          /* Strings are true */
06143          return 1;
06144       }
06145    } else {
06146       /* NULL is also false */
06147       return 0;
06148    }
06149 }

static void pbx_destroy struct ast_pbx p  )  [static]
 

Definition at line 620 of file pbx.c.

References free.

00621 {
00622    free(p);
00623 }

int pbx_exec struct ast_channel c,
struct ast_app app,
void *  data,
int  newstack
 

Parameters:
c channel to execute on
app which app to execute
data the data passed into the app
newstack stack pointer This application executes an application on a given channel. It saves the stack and executes the given appliation passing in the given data. It returns 0 on success, and -1 on failure
Parameters:
c  Channel
app  Application
data  Data for execution
newstack  Force stack increment

Definition at line 531 of file pbx.c.

References app, ast_channel::appl, ast_cdr_setapp(), ast_log(), ast_channel::cdr, ast_channel::data, and LOG_WARNING.

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

00535 {
00536    int res;
00537    
00538    char *saved_c_appl;
00539    char *saved_c_data;
00540    
00541    int (*execute)(struct ast_channel *chan, void *data) = app->execute; 
00542 
00543    if (newstack) {
00544       if (c->cdr)
00545          ast_cdr_setapp(c->cdr, app->name, data);
00546 
00547       /* save channel values */
00548       saved_c_appl= c->appl;
00549       saved_c_data= c->data;
00550 
00551       c->appl = app->name;
00552       c->data = data;      
00553       res = execute(c, data);
00554       /* restore channel values */
00555       c->appl= saved_c_appl;
00556       c->data= saved_c_data;
00557       return res;
00558    } else
00559       ast_log(LOG_WARNING, "You really didn't want to call this function with newstack set to 0\n");
00560    return -1;
00561 }

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,
int  action
[static]
 

Definition at line 1618 of file pbx.c.

References ast_exten::app, app, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_PBX_MAX_STACK, ast_strlen_zero(), ast_verbose(), COLOR_BRCYAN, COLOR_BRMAGENTA, ast_channel::context, EVENT_FLAG_CALL, ast_switch::exec, EXT_DATA_SIZE, ast_channel::exten, HELPER_CANMATCH, HELPER_EXEC, HELPER_EXISTS, HELPER_FINDLABEL, HELPER_MATCHMORE, HELPER_SPAWN, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, manager_event(), ast_switch::name, ast_channel::name, option_debug, option_verbose, pbx_builtin_setvar_helper(), pbx_exec(), pbx_find_extension(), pbx_findapp(), pbx_substitute_variables(), ast_channel::priority, ast_exten::priority, STATUS_NO_CONTEXT, STATUS_NO_EXTENSION, STATUS_NO_LABEL, STATUS_NO_PRIORITY, term_color(), ast_channel::uniqueid, and VERBOSE_PREFIX_3.

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

01619 {
01620    struct ast_exten *e;
01621    struct ast_app *app;
01622    struct ast_switch *sw;
01623    char *data;
01624    const char *foundcontext=NULL;
01625    int newstack = 0;
01626    int res;
01627    int status = 0;
01628    char *incstack[AST_PBX_MAX_STACK];
01629    char passdata[EXT_DATA_SIZE];
01630    int stacklen = 0;
01631    char tmp[80];
01632    char tmp2[80];
01633    char tmp3[EXT_DATA_SIZE];
01634    char atmp[80];
01635    char atmp2[EXT_DATA_SIZE+100];
01636 
01637    if (ast_mutex_lock(&conlock)) {
01638       ast_log(LOG_WARNING, "Unable to obtain lock\n");
01639       if ((action == HELPER_EXISTS) || (action == HELPER_CANMATCH) || (action == HELPER_MATCHMORE))
01640          return 0;
01641       else
01642          return -1;
01643    }
01644    e = pbx_find_extension(c, con, context, exten, priority, label, callerid, action, incstack, &stacklen, &status, &sw, &data, &foundcontext);
01645    if (e) {
01646       switch(action) {
01647       case HELPER_CANMATCH:
01648          ast_mutex_unlock(&conlock);
01649          return -1;
01650       case HELPER_EXISTS:
01651          ast_mutex_unlock(&conlock);
01652          return -1;
01653       case HELPER_FINDLABEL:
01654          res = e->priority;
01655          ast_mutex_unlock(&conlock);
01656          return res;
01657       case HELPER_MATCHMORE:
01658          ast_mutex_unlock(&conlock);
01659          return -1;
01660       case HELPER_SPAWN:
01661          newstack++;
01662          /* Fall through */
01663       case HELPER_EXEC:
01664          app = pbx_findapp(e->app);
01665          ast_mutex_unlock(&conlock);
01666          if (app) {
01667             if (c->context != context)
01668                ast_copy_string(c->context, context, sizeof(c->context));
01669             if (c->exten != exten)
01670                ast_copy_string(c->exten, exten, sizeof(c->exten));
01671             c->priority = priority;
01672             pbx_substitute_variables(passdata, sizeof(passdata), c, e);
01673             if (option_debug) {
01674                   ast_log(LOG_DEBUG, "Launching '%s'\n", app->name);
01675                   snprintf(atmp, 80, "STACK-%s-%s-%d", context, exten, priority);
01676                   snprintf(atmp2, EXT_DATA_SIZE+100, "%s(\"%s\", \"%s\") %s", app->name, c->name, (!ast_strlen_zero(passdata) ? (char *)passdata : ""), (newstack ? "in new stack" : "in same stack"));
01677                   pbx_builtin_setvar_helper(c, atmp, atmp2);
01678             }
01679             if (option_verbose > 2)
01680                   ast_verbose( VERBOSE_PREFIX_3 "Executing %s(\"%s\", \"%s\") %s\n", 
01681                         term_color(tmp, app->name, COLOR_BRCYAN, 0, sizeof(tmp)),
01682                         term_color(tmp2, c->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)),
01683                         term_color(tmp3, (!ast_strlen_zero(passdata) ? (char *)passdata : ""), COLOR_BRMAGENTA, 0, sizeof(tmp3)),
01684                         (newstack ? "in new stack" : "in same stack"));
01685             manager_event(EVENT_FLAG_CALL, "Newexten", 
01686                "Channel: %s\r\n"
01687                "Context: %s\r\n"
01688                "Extension: %s\r\n"
01689                "Priority: %d\r\n"
01690                "Application: %s\r\n"
01691                "AppData: %s\r\n"
01692                "Uniqueid: %s\r\n",
01693                c->name, c->context, c->exten, c->priority, app->name, passdata ? passdata : "(NULL)", c->uniqueid);
01694             res = pbx_exec(c, app, passdata, newstack);
01695             return res;
01696          } else {
01697             ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority);
01698             return -1;
01699          }
01700       default:
01701          ast_log(LOG_WARNING, "Huh (%d)?\n", action);       return -1;
01702       }
01703    } else if (sw) {
01704       switch(action) {
01705       case HELPER_CANMATCH:
01706          ast_mutex_unlock(&conlock);
01707          return -1;
01708       case HELPER_EXISTS:
01709          ast_mutex_unlock(&conlock);
01710          return -1;
01711       case HELPER_MATCHMORE:
01712          ast_mutex_unlock(&conlock);
01713          return -1;
01714       case HELPER_FINDLABEL:
01715          ast_mutex_unlock(&conlock);
01716          return -1;
01717       case HELPER_SPAWN:
01718          newstack++;
01719          /* Fall through */
01720       case HELPER_EXEC:
01721          ast_mutex_unlock(&conlock);
01722          if (sw->exec)
01723             res = sw->exec(c, foundcontext ? foundcontext : context, exten, priority, callerid, newstack, data);
01724          else {
01725             ast_log(LOG_WARNING, "No execution engine for switch %s\n", sw->name);
01726             res = -1;
01727          }
01728          return res;
01729       default:
01730          ast_log(LOG_WARNING, "Huh (%d)?\n", action);
01731          return -1;
01732       }
01733    } else {
01734       ast_mutex_unlock(&conlock);
01735       switch(status) {
01736       case STATUS_NO_CONTEXT:
01737          if ((action != HELPER_EXISTS) && (action != HELPER_MATCHMORE))
01738             ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", context);
01739          break;
01740       case STATUS_NO_EXTENSION:
01741          if ((action != HELPER_EXISTS) && (action !=  HELPER_CANMATCH) && (action != HELPER_MATCHMORE))
01742             ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, context);
01743          break;
01744       case STATUS_NO_PRIORITY:
01745          if ((action != HELPER_EXISTS) && (action !=  HELPER_CANMATCH) && (action != HELPER_MATCHMORE))
01746             ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, context);
01747          break;
01748       case STATUS_NO_LABEL:
01749          if (context)
01750             ast_log(LOG_NOTICE, "No such label '%s' in extension '%s' in context '%s'\n", label, exten, context);
01751          break;
01752       default:
01753          ast_log(LOG_DEBUG, "Shouldn't happen!\n");
01754       }
01755       
01756       if ((action != HELPER_EXISTS) && (action != HELPER_CANMATCH) && (action != HELPER_MATCHMORE))
01757          return -1;
01758       else
01759          return 0;
01760    }
01761 
01762 }

static struct ast_exten* pbx_find_extension struct ast_channel chan,
struct ast_context bypass,
const char *  context,
const char *  exten,
int  priority,
const char *  label,
const char *  callerid,
int  action,
char *  incstack[],
int *  stacklen,
int *  status,
struct ast_switch **  swo,
char **  data,
const char **  foundcontext
[static]
 

Definition at line 777 of file pbx.c.

References ast_log(), AST_PBX_MAX_STACK, LOG_WARNING, and STATUS_NO_CONTEXT.

Referenced by ast_hint_extension(), and pbx_extension_helper().

00778 {
00779    int x, res;
00780    struct ast_context *tmp;
00781    struct ast_exten *e, *eroot;
00782    struct ast_include *i;
00783    struct ast_sw *sw;
00784    struct ast_switch *asw;
00785 
00786    /* Initialize status if appropriate */
00787    if (!*stacklen) {
00788       *status = STATUS_NO_CONTEXT;
00789       *swo = NULL;
00790       *data = NULL;
00791    }
00792    /* Check for stack overflow */
00793    if (*stacklen >= AST_PBX_MAX_STACK) {
00794       ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n");
00795       return NULL;
00796    }
00797    /* Check first to see if we've already been checked */
00798    for (x=0; x<*stacklen; x++) {
00799       if (!strcasecmp(incstack[x], context))
00800          return NULL;
00801    }
00802    if (bypass)
00803       tmp = bypass;
00804    else
00805       tmp = contexts;
00806    while(tmp) {
00807       /* Match context */
00808       if (bypass || !strcmp(tmp->name, context)) {
00809          struct ast_exten *earlymatch = NULL;
00810 
00811          if (*status < STATUS_NO_EXTENSION)
00812             *status = STATUS_NO_EXTENSION;
00813          for (eroot = tmp->root; eroot; eroot=eroot->next) {
00814             int match = 0;
00815             /* Match extension */
00816             if ((((action != HELPER_MATCHMORE) && ast_extension_match(eroot->exten, exten)) ||
00817                  ((action == HELPER_CANMATCH) && (ast_extension_close(eroot->exten, exten, 0))) ||
00818                  ((action == HELPER_MATCHMORE) && (match = ast_extension_close(eroot->exten, exten, 1)))) &&
00819                 (!eroot->matchcid || matchcid(eroot->cidmatch, callerid))) {
00820 
00821                if (action == HELPER_MATCHMORE && match == 2 && !earlymatch) {
00822                   /* It matched an extension ending in a '!' wildcard
00823                      So ignore it for now, unless there's a better match */
00824                   earlymatch = eroot;
00825                } else {
00826                   e = eroot;
00827                   if (*status < STATUS_NO_PRIORITY)
00828                      *status = STATUS_NO_PRIORITY;
00829                   while(e) {
00830                      /* Match priority */
00831                      if (action == HELPER_FINDLABEL) {
00832                         if (*status < STATUS_NO_LABEL)
00833                            *status = STATUS_NO_LABEL;
00834                         if (label && e->label && !strcmp(label, e->label)) {
00835                            *status = STATUS_SUCCESS;
00836                            *foundcontext = context;
00837                            return e;
00838                         }
00839                      } else if (e->priority == priority) {
00840                         *status = STATUS_SUCCESS;
00841                         *foundcontext = context;
00842                         return e;
00843                      }
00844                      e = e->peer;
00845                   }
00846                }
00847             }
00848          }
00849          if (earlymatch) {
00850             /* Bizarre logic for HELPER_MATCHMORE. We return zero to break out 
00851                of the loop waiting for more digits, and _then_ match (normally)
00852                the extension we ended up with. We got an early-matching wildcard
00853                pattern, so return NULL to break out of the loop. */
00854             return NULL;
00855          }
00856          /* Check alternative switches */
00857          sw = tmp->alts;
00858          while(sw) {
00859             if ((asw = pbx_findswitch(sw->name))) {
00860                /* Substitute variables now */
00861                if (sw->eval) 
00862                   pbx_substitute_variables_helper(chan, sw->data, sw->tmpdata, SWITCH_DATA_LENGTH - 1);
00863                if (action == HELPER_CANMATCH)
00864                   res = asw->canmatch ? asw->canmatch(chan, context, exten, priority, callerid, sw->eval ? sw->tmpdata : sw->data) : 0;
00865                else if (action == HELPER_MATCHMORE)
00866                   res = asw->matchmore ? asw->matchmore(chan, context, exten, priority, callerid, sw->eval ? sw->tmpdata : sw->data) : 0;
00867                else
00868                   res = asw->exists ? asw->exists(chan, context, exten, priority, callerid, sw->eval ? sw->tmpdata : sw->data) : 0;
00869                if (res) {
00870                   /* Got a match */
00871                   *swo = asw;
00872                   *data = sw->eval ? sw->tmpdata : sw->data;
00873                   *foundcontext = context;
00874                   return NULL;
00875                }
00876             } else {
00877                ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name);
00878             }
00879             sw = sw->next;
00880          }
00881          /* Setup the stack */
00882          incstack[*stacklen] = tmp->name;
00883          (*stacklen)++;
00884          /* Now try any includes we have in this context */
00885          i = tmp->includes;
00886          while(i) {
00887             if (include_valid(i)) {
00888                if ((e = pbx_find_extension(chan, bypass, i->rname, exten, priority, label, callerid, action, incstack, stacklen, status, swo, data, foundcontext))) 
00889                   return e;
00890                if (*swo) 
00891                   return NULL;
00892             }
00893             i = i->next;
00894          }
00895          break;
00896       }
00897       tmp = tmp->next;
00898    }
00899    return NULL;
00900 }

struct ast_app* pbx_findapp const char *  app  ) 
 

Find application handle in linked list.

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

References apps, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), LOG_WARNING, ast_app::name, and ast_app::next.

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

00577 {
00578    struct ast_app *tmp;
00579 
00580    if (ast_mutex_lock(&applock)) {
00581       ast_log(LOG_WARNING, "Unable to obtain application lock\n");
00582       return NULL;
00583    }
00584    tmp = apps;
00585    while(tmp) {
00586       if (!strcasecmp(tmp->name, app))
00587          break;
00588       tmp = tmp->next;
00589    }
00590    ast_mutex_unlock(&applock);
00591    return tmp;
00592 }

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

Definition at line 594 of file pbx.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), LOG_WARNING, ast_switch::name, ast_switch::next, and switches.

00595 {
00596    struct ast_switch *asw;
00597 
00598    if (ast_mutex_lock(&switchlock)) {
00599       ast_log(LOG_WARNING, "Unable to obtain application lock\n");
00600       return NULL;
00601    }
00602    asw = switches;
00603    while(asw) {
00604       if (!strcasecmp(asw->name, sw))
00605          break;
00606       asw = asw->next;
00607    }
00608    ast_mutex_unlock(&switchlock);
00609    return asw;
00610 }

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 and functions in the dialplan ---

Definition at line 979 of file pbx.c.

References ast_channel::accountcode, ast_get_hint(), AST_LIST_TRAVERSE, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_var_name(), ast_var_value(), ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_ani2, ast_callerid::cid_dnid, ast_callerid::cid_name, ast_callerid::cid_num, ast_callerid::cid_pres, ast_callerid::cid_rdnis, ast_callerid::cid_tns, ast_callerid::cid_ton, ast_channel::context, ast_channel::exten, ast_channel::hangupcause, ast_channel::language, LOG_WARNING, ast_channel::name, offset, parse_variable_name(), pbx_retrieve_variable(), ast_channel::priority, substring(), ast_channel::uniqueid, and ast_channel::varshead.

Referenced by function_fieldqty(), handle_getvariable(), pbx_retrieve_variable(), and pbx_substitute_variables_helper_full().

00980 {
00981    char tmpvar[80];
00982    time_t thistime;
00983    struct tm brokentime;
00984    int offset, offset2, isfunc;
00985    struct ast_var_t *variables;
00986 
00987    if (c) 
00988       headp=&c->varshead;
00989    *ret=NULL;
00990    ast_copy_string(tmpvar, var, sizeof(tmpvar));
00991    if (parse_variable_name(tmpvar, &offset, &offset2, &isfunc)) {
00992       pbx_retrieve_variable(c, tmpvar, ret, workspace, workspacelen, headp);
00993       if (!(*ret)) 
00994          return;
00995       *ret = substring(*ret, offset, offset2, workspace, workspacelen);
00996    } else if (c && !strncmp(var, "CALL", 4)) {
00997       if (!strncmp(var + 4, "ER", 2)) {
00998          if (!strncmp(var + 6, "ID", 2)) {
00999             if (!var[8]) {          /* CALLERID */
01000                if (c->cid.cid_num) {
01001                   if (c->cid.cid_name) {
01002                      snprintf(workspace, workspacelen, "\"%s\" <%s>", c->cid.cid_name, c->cid.cid_num);
01003                   } else {
01004                      ast_copy_string(workspace, c->cid.cid_num, workspacelen);
01005                   }
01006                   *ret = workspace;
01007                } else if (c->cid.cid_name) {
01008                   ast_copy_string(workspace, c->cid.cid_name, workspacelen);
01009                   *ret = workspace;
01010                } else
01011                   *ret = NULL;
01012             } else if (!strcmp(var + 8, "NUM")) {
01013                /* CALLERIDNUM */
01014                if (c->cid.cid_num) {
01015                   ast_copy_string(workspace, c->cid.cid_num, workspacelen);
01016                   *ret = workspace;
01017                } else
01018                   *ret = NULL;
01019             } else if (!strcmp(var + 8, "NAME")) {
01020                /* CALLERIDNAME */
01021                if (c->cid.cid_name) {
01022                   ast_copy_string(workspace, c->cid.cid_name, workspacelen);
01023                   *ret = workspace;
01024                } else
01025                   *ret = NULL;
01026             } else
01027                goto icky;
01028          } else if (!strcmp(var + 6, "ANI")) {
01029             /* CALLERANI */
01030             if (c->cid.cid_ani) {
01031                ast_copy_string(workspace, c->cid.cid_ani, workspacelen);
01032                *ret = workspace;
01033             } else
01034                *ret = NULL;
01035          } else
01036             goto icky;
01037       } else if (!strncmp(var + 4, "ING", 3)) {
01038          if (!strcmp(var + 7, "PRES")) {
01039             /* CALLINGPRES */
01040             snprintf(workspace, workspacelen, "%d", c->cid.cid_pres);
01041             *ret = workspace;
01042          } else if (!strcmp(var + 7, "ANI2")) {
01043             /* CALLINGANI2 */
01044             snprintf(workspace, workspacelen, "%d", c->cid.cid_ani2);
01045             *ret = workspace;
01046          } else if (!strcmp(var + 7, "TON")) {
01047             /* CALLINGTON */
01048             snprintf(workspace, workspacelen, "%d", c->cid.cid_ton);
01049             *ret = workspace;
01050          } else if (!strcmp(var + 7, "TNS")) {
01051             /* CALLINGTNS */
01052             snprintf(workspace, workspacelen, "%d", c->cid.cid_tns);
01053             *ret = workspace;
01054          } else
01055             goto icky;
01056       } else
01057          goto icky;
01058    } else if (c && !strcmp(var, "DNID")) {
01059       if (c->cid.cid_dnid) {
01060          ast_copy_string(workspace, c->cid.cid_dnid, workspacelen);
01061          *ret = workspace;
01062       } else
01063          *ret = NULL;
01064    } else if (c && !strcmp(var, "HINT")) {
01065       if (!ast_get_hint(workspace, workspacelen, NULL, 0, c, c->context, c->exten))
01066          *ret = NULL;
01067       else
01068          *ret = workspace;
01069    } else if (c && !strcmp(var, "HINTNAME")) {
01070       if (!ast_get_hint(NULL, 0, workspace, workspacelen, c, c->context, c->exten))
01071          *ret = NULL;
01072       else
01073          *ret = workspace;
01074    } else if (c && !strcmp(var, "EXTEN")) {
01075       ast_copy_string(workspace, c->exten, workspacelen);
01076       *ret = workspace;
01077    } else if (c && !strcmp(var, "RDNIS")) {
01078       if (c->cid.cid_rdnis) {
01079          ast_copy_string(workspace, c->cid.cid_rdnis, workspacelen);
01080          *ret = workspace;
01081       } else
01082          *ret = NULL;
01083    } else if (c && !strcmp(var, "CONTEXT")) {
01084       ast_copy_string(workspace, c->context, workspacelen);
01085       *ret = workspace;
01086    } else if (c && !strcmp(var, "PRIORITY")) {
01087       snprintf(workspace, workspacelen, "%d", c->priority);
01088       *ret = workspace;
01089    } else if (c && !strcmp(var, "CHANNEL")) {
01090       ast_copy_string(workspace, c->name, workspacelen);
01091       *ret = workspace;
01092    } else if (!strcmp(var, "EPOCH")) {
01093       snprintf(workspace, workspacelen, "%u",(int)time(NULL));
01094       *ret = workspace;
01095    } else if (!strcmp(var, "DATETIME")) {
01096       thistime=time(NULL);
01097       localtime_r(&thistime, &brokentime);
01098       snprintf(workspace, workspacelen, "%02d%02d%04d-%02d:%02d:%02d",
01099          brokentime.tm_mday,
01100          brokentime.tm_mon+1,
01101          brokentime.tm_year+1900,
01102          brokentime.tm_hour,
01103          brokentime.tm_min,
01104          brokentime.tm_sec
01105       );
01106       *ret = workspace;
01107    } else if (!strcmp(var, "TIMESTAMP")) {
01108       thistime=time(NULL);
01109       localtime_r(&thistime, &brokentime);
01110       /* 20031130-150612 */
01111       snprintf(workspace, workspacelen, "%04d%02d%02d-%02d%02d%02d",
01112          brokentime.tm_year+1900,
01113          brokentime.tm_mon+1,
01114          brokentime.tm_mday,
01115          brokentime.tm_hour,
01116          brokentime.tm_min,
01117          brokentime.tm_sec
01118       );
01119       *ret = workspace;
01120    } else if (c && !strcmp(var, "UNIQUEID")) {
01121       snprintf(workspace, workspacelen, "%s", c->uniqueid);
01122       *ret = workspace;
01123    } else if (c && !strcmp(var, "HANGUPCAUSE")) {
01124       snprintf(workspace, workspacelen, "%d", c->hangupcause);
01125       *ret = workspace;
01126    } else if (c && !strcmp(var, "ACCOUNTCODE")) {
01127       ast_copy_string(workspace, c->accountcode, workspacelen);
01128       *ret = workspace;
01129    } else if (c && !strcmp(var, "LANGUAGE")) {
01130       ast_copy_string(workspace, c->language, workspacelen);
01131       *ret = workspace;
01132    } else {
01133 icky:
01134       if (headp) {
01135          AST_LIST_TRAVERSE(headp,variables,entries) {
01136 #if 0
01137             ast_log(LOG_WARNING,"Comparing variable '%s' with '%s'\n",var,ast_var_name(variables));
01138 #endif
01139             if (strcasecmp(ast_var_name(variables),var)==0) {
01140                *ret=ast_var_value(variables);
01141                if (*ret) {
01142                   ast_copy_string(workspace, *ret, workspacelen);
01143                   *ret = workspace;
01144                }
01145                break;
01146             }
01147          }
01148       }
01149       if (!(*ret)) {
01150          /* Try globals */
01151          ast_mutex_lock(&globalslock);
01152          AST_LIST_TRAVERSE(&globals,variables,entries) {
01153             if (strcasecmp(ast_var_name(variables),var)==0) {
01154                *ret = ast_var_value(variables);
01155                if (*ret) {
01156                   ast_copy_string(workspace, *ret, workspacelen);
01157                   *ret = workspace;
01158                }
01159             }
01160          }
01161          ast_mutex_unlock(&globalslock);
01162       }
01163    }
01164 }

int pbx_set_autofallthrough int  newval  ) 
 

Definition at line 2564 of file pbx.c.

Referenced by pbx_load_module().

02565 {
02566    int oldval;
02567    oldval = autofallthrough;
02568    if (oldval != newval)
02569       autofallthrough = newval;
02570    return oldval;
02571 }

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

Definition at line 1605 of file pbx.c.

References ast_exten::data, and pbx_substitute_variables_helper().

Referenced by pbx_extension_helper().

01606 {
01607    memset(passdata, 0, datalen);
01608       
01609    /* No variables or expressions in e->data, so why scan it? */
01610    if (!strchr(e->data, '$') && !strstr(e->data,"${") && !strstr(e->data,"$[") && !strstr(e->data,"$(")) {
01611       ast_copy_string(passdata, e->data, datalen);
01612       return;
01613    }
01614    
01615    pbx_substitute_variables_helper(c, e->data, passdata, datalen - 1);
01616 }                                                     

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

Definition at line 1595 of file pbx.c.

References pbx_substitute_variables_helper_full(), and ast_channel::varshead.

Referenced by custom_log(), cut_internal(), eval_exec(), exec_exec(), function_eval(), handle_getvariablefull(), mixmonitor_thread(), pbx_builtin_importvar(), pbx_load_module(), pbx_substitute_variables(), realtime_exec(), sendmail(), and sendpage().

01596 {
01597    pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count);
01598 }

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

References ast_expr(), ast_func_read(), ast_log(), ast_strlen_zero(), LOG_DEBUG, LOG_NOTICE, offset, parse_variable_name(), pbx_retrieve_variable(), substring(), var, and VAR_BUF_SIZE.

Referenced by pbx_substitute_variables_helper(), and pbx_substitute_variables_varshead().

01420 {
01421    char *cp4;
01422    const char *tmp, *whereweare;
01423    int length, offset, offset2, isfunction;
01424    char *workspace = NULL;
01425    char *ltmp = NULL, *var = NULL;
01426    char *nextvar, *nextexp, *nextthing;
01427    char *vars, *vare;
01428    int pos, brackets, needsub, len;
01429    
01430    /* Substitutes variables into cp2, based on string cp1, and assuming cp2 to be
01431       zero-filled */
01432    whereweare=tmp=cp1;
01433    while(!ast_strlen_zero(whereweare) && count) {
01434       /* Assume we're copying the whole remaining string */
01435       pos = strlen(whereweare);
01436       nextvar = NULL;
01437       nextexp = NULL;
01438       nextthing = strchr(whereweare, '$');
01439       if (nextthing) {
01440          switch(nextthing[1]) {
01441          case '{':
01442             nextvar = nextthing;
01443             pos = nextvar - whereweare;
01444             break;
01445          case '[':
01446             nextexp = nextthing;
01447             pos = nextexp - whereweare;
01448             break;
01449          }
01450       }
01451 
01452       if (pos) {
01453          /* Can't copy more than 'count' bytes */
01454          if (pos > count)
01455             pos = count;
01456          
01457          /* Copy that many bytes */
01458          memcpy(cp2, whereweare, pos);
01459          
01460          count -= pos;
01461          cp2 += pos;
01462          whereweare += pos;
01463       }
01464       
01465       if (nextvar) {
01466          /* We have a variable.  Find the start and end, and determine
01467             if we are going to have to recursively call ourselves on the
01468             contents */
01469          vars = vare = nextvar + 2;
01470          brackets = 1;
01471          needsub = 0;
01472 
01473          /* Find the end of it */
01474          while(brackets && *vare) {
01475             if ((vare[0] == '$') && (vare[1] == '{')) {
01476                needsub++;
01477                brackets++;
01478             } else if (vare[0] == '}') {
01479                brackets--;
01480             } else if ((vare[0] == '$') && (vare[1] == '['))
01481                needsub++;
01482             vare++;
01483          }
01484          if (brackets)
01485             ast_log(LOG_NOTICE, "Error in extension logic (missing '}')\n");
01486          len = vare - vars - 1;
01487 
01488          /* Skip totally over variable string */
01489          whereweare += (len + 3);
01490 
01491          if (!var)
01492             var = alloca(VAR_BUF_SIZE);
01493 
01494          /* Store variable name (and truncate) */
01495          ast_copy_string(var, vars, len + 1);
01496 
01497          /* Substitute if necessary */
01498          if (needsub) {
01499             if (!ltmp)
01500                ltmp = alloca(VAR_BUF_SIZE);
01501 
01502             memset(ltmp, 0, VAR_BUF_SIZE);
01503             pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1);
01504             vars = ltmp;
01505          } else {
01506             vars = var;
01507          }
01508 
01509          if (!workspace)
01510             workspace = alloca(VAR_BUF_SIZE);
01511 
01512          workspace[0] = '\0';
01513 
01514          parse_variable_name(vars, &offset, &offset2, &isfunction);
01515          if (isfunction) {
01516             /* Evaluate function */
01517             cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE);
01518 
01519             ast_log(LOG_DEBUG, "Function result is '%s'\n", cp4 ? cp4 : "(null)");
01520          } else {
01521             /* Retrieve variable value */
01522             pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp);
01523          }
01524          if (cp4) {
01525             cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE);
01526 
01527             length = strlen(cp4);
01528             if (length > count)
01529                length = count;
01530             memcpy(cp2, cp4, length);
01531             count -= length;
01532             cp2 += length;
01533          }
01534       } else if (nextexp) {
01535          /* We have an expression.  Find the start and end, and determine
01536             if we are going to have to recursively call ourselves on the
01537             contents */
01538          vars = vare = nextexp + 2;
01539          brackets = 1;
01540          needsub = 0;
01541 
01542          /* Find the end of it */
01543          while(brackets && *vare) {
01544             if ((vare[0] == '$') && (vare[1] == '[')) {
01545                needsub++;
01546                brackets++;
01547                vare++;
01548             } else if (vare[0] == '[') {
01549                brackets++;
01550             } else if (vare[0] == ']') {
01551                brackets--;
01552             } else if ((vare[0] == '$') && (vare[1] == '{')) {
01553                needsub++;
01554                vare++;
01555             }
01556             vare++;
01557          }
01558          if (brackets)
01559             ast_log(LOG_NOTICE, "Error in extension logic (missing ']')\n");
01560          len = vare - vars - 1;
01561          
01562          /* Skip totally over expression */
01563          whereweare += (len + 3);
01564          
01565          if (!var)
01566             var = alloca(VAR_BUF_SIZE);
01567 
01568          /* Store variable name (and truncate) */
01569          ast_copy_string(var, vars, len + 1);
01570          
01571          /* Substitute if necessary */
01572          if (needsub) {
01573             if (!ltmp)
01574                ltmp = alloca(VAR_BUF_SIZE);
01575 
01576             memset(ltmp, 0, VAR_BUF_SIZE);
01577             pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1);
01578             vars = ltmp;
01579          } else {
01580             vars = var;
01581          }
01582 
01583          length = ast_expr(vars, cp2, count);
01584 
01585          if (length) {
01586             ast_log(LOG_DEBUG, "Expression result is '%s'\n", cp2);
01587             count -= length;
01588             cp2 += length;
01589          }
01590       } else
01591          break;
01592    }
01593 }

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

Definition at line 1600 of file pbx.c.

References pbx_substitute_variables_helper_full().

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

01601 {
01602    pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count);
01603 }

static void* pbx_thread void *  data  )  [static]
 

Definition at line 2502 of file pbx.c.

References __ast_pbx_run(), and decrease_call_count().

Referenced by ast_pbx_start().

02503 {
02504    /* Oh joyeous kernel, we're a new thread, with nothing to do but
02505       answer this channel and get it going.
02506    */
02507    /* NOTE:
02508       The launcher of this function _MUST_ increment 'countcalls'
02509       before invoking the function; it will be decremented when the
02510       PBX has finished running on the channel
02511     */
02512    struct ast_channel *c = data;
02513 
02514    __ast_pbx_run(c);
02515    decrease_call_count();
02516 
02517    pthread_exit(NULL);
02518 
02519    return NULL;
02520 }

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

Definition at line 3339 of file pbx.c.

References ast_cli(), ast_extension_match(), ast_get_context_name(), ast_get_context_registrar(), ast_get_extension_app(), ast_get_extension_app_data(), ast_get_extension_label(), ast_get_extension_name(), ast_get_extension_priority(), ast_get_extension_registrar(), ast_get_include_name(), ast_lock_context(), ast_lock_contexts(), ast_log(), AST_PBX_MAX_STACK, ast_walk_context_extensions(), ast_walk_context_includes(), ast_walk_contexts(), ast_walk_extension_priorities(), dialplan_counters::context_existence, dialplan_counters::extension_existence, LOG_NOTICE, LOG_WARNING, PRIORITY_HINT, dialplan_counters::total_context, dialplan_counters::total_exten, and dialplan_counters::total_prio.

Referenced by handle_show_dialplan().

03340 {
03341    struct ast_context *c;
03342    int res=0, old_total_exten = dpc->total_exten;
03343 
03344    /* try to lock contexts */
03345    if (ast_lock_contexts()) {
03346       ast_log(LOG_WARNING, "Failed to lock contexts list\n");
03347       return -1;
03348    }
03349 
03350    /* walk all contexts ... */
03351    for (c = ast_walk_contexts(NULL); c ; c = ast_walk_contexts(c)) {
03352       /* show this context? */
03353       if (!context ||
03354          !strcmp(ast_get_context_name(c), context)) {
03355          dpc->context_existence = 1;
03356 
03357          /* try to lock context before walking in ... */
03358          if (!ast_lock_context(c)) {
03359             struct ast_exten *e;
03360             struct ast_include *i;
03361             struct ast_ignorepat *ip;
03362             struct ast_sw *sw;
03363             char buf[256], buf2[256];
03364             int context_info_printed = 0;
03365 
03366             /* are we looking for exten too? if yes, we print context
03367              * if we our extension only
03368              */
03369             if (!exten) {
03370                dpc->total_context++;
03371                ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
03372                   ast_get_context_name(c), ast_get_context_registrar(c));
03373                context_info_printed = 1;
03374             }
03375 
03376             /* walk extensions ... */
03377             for (e = ast_walk_context_extensions(c, NULL); e; e = ast_walk_context_extensions(c, e)) {
03378                struct ast_exten *p;
03379                int prio;
03380 
03381                /* looking for extension? is this our extension? */
03382                if (exten &&
03383                   !ast_extension_match(ast_get_extension_name(e), exten))
03384                {
03385                   /* we are looking for extension and it's not our
03386                    * extension, so skip to next extension */
03387                   continue;
03388                }
03389 
03390                dpc->extension_existence = 1;
03391 
03392                /* may we print context info? */ 
03393                if (!context_info_printed) {
03394                   dpc->total_context++;
03395                   if (rinclude) {
03396                      /* TODO Print more info about rinclude */
03397                      ast_cli(fd, "[ Included context '%s' created by '%s' ]\n",
03398                         ast_get_context_name(c),
03399                         ast_get_context_registrar(c));
03400                   } else {
03401                      ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
03402                         ast_get_context_name(c),
03403                         ast_get_context_registrar(c));
03404                   }
03405                   context_info_printed = 1;
03406                }
03407                dpc->total_prio++;
03408 
03409                /* write extension name and first peer */ 
03410                bzero(buf, sizeof(buf));      
03411                snprintf(buf, sizeof(buf), "'%s' =>",
03412                   ast_get_extension_name(e));
03413 
03414                prio = ast_get_extension_priority(e);
03415                if (prio == PRIORITY_HINT) {
03416                   snprintf(buf2, sizeof(buf2),
03417                      "hint: %s",
03418                      ast_get_extension_app(e));
03419                } else {
03420                   snprintf(buf2, sizeof(buf2),
03421                      "%d. %s(%s)",
03422                      prio,
03423                      ast_get_extension_app(e),
03424                      (char *)ast_get_extension_app_data(e));
03425                }
03426 
03427                ast_cli(fd, "  %-17s %-45s [%s]\n", buf, buf2,
03428                   ast_get_extension_registrar(e));
03429 
03430                dpc->total_exten++;
03431                /* walk next extension peers */
03432                for (p=ast_walk_extension_priorities(e, e); p; p=ast_walk_extension_priorities(e, p)) {
03433                   dpc->total_prio++;
03434                   bzero((void *)buf2, sizeof(buf2));
03435                   bzero((void *)buf, sizeof(buf));
03436                   if (ast_get_extension_label(p))
03437                      snprintf(buf, sizeof(buf), "   [%s]", ast_get_extension_label(p));
03438                   prio = ast_get_extension_priority(p);
03439                   if (prio == PRIORITY_HINT) {
03440                      snprintf(buf2, sizeof(buf2),
03441                         "hint: %s",
03442                         ast_get_extension_app(p));
03443                   } else {
03444                      snprintf(buf2, sizeof(buf2),
03445                         "%d. %s(%s)",
03446                         prio,
03447                         ast_get_extension_app(p),
03448                         (char *)ast_get_extension_app_data(p));
03449                   }
03450 
03451                   ast_cli(fd,"  %-17s %-45s [%s]\n",
03452                      buf, buf2,
03453                      ast_get_extension_registrar(p));
03454                }
03455             }
03456 
03457             /* walk included and write info ... */
03458             for (i = ast_walk_context_includes(c, NULL); i; i = ast_walk_context_includes(c, i)) {
03459                bzero(buf, sizeof(buf));
03460                snprintf(buf, sizeof(buf), "'%s'",
03461                   ast_get_include_name(i));
03462                if (exten) {
03463                   /* Check all includes for the requested extension */
03464                   if (includecount >= AST_PBX_MAX_STACK) {
03465                      ast_log(LOG_NOTICE, "Maximum include depth exceeded!\n");
03466                   } else {
03467                      int dupe=0;
03468                      int x;
03469                      for (x=0;x<includecount;x++) {
03470                         if (!strcasecmp(includes[x], ast_get_include_name(i))) {
03471                            dupe++;
03472                            break;
03473                         }
03474                      }
03475                      if (!dupe) {
03476                         includes[includecount] = (char *)ast_get_include_name(i);
03477                         show_dialplan_helper(fd, (char *)ast_get_include_name(i), exten, dpc, i, includecount + 1, includes);
03478                      } else {
03479                         ast_log(LOG_WARNING, "Avoiding circular include of %s within %s\n", ast_get_include_name(i), context);
03480                      }
03481                   }
03482                } else {
03483                   ast_cli(fd, "  Include =>        %-45s [%s]\n",
03484                      buf, ast_get_include_registrar(i));
03485                }
03486             }
03487 
03488             /* walk ignore patterns and write info ... */
03489             for (ip=ast_walk_context_ignorepats(c, NULL); ip; ip=ast_walk_context_ignorepats(c, ip)) {
03490                const char *ipname = ast_get_ignorepat_name(ip);
03491                char ignorepat[AST_MAX_EXTENSION];
03492                snprintf(buf, sizeof(buf), "'%s'", ipname);
03493                snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname);
03494                if ((!exten) || ast_extension_match(ignorepat, exten)) {
03495                   ast_cli(fd, "  Ignore pattern => %-45s [%s]\n",
03496                      buf, ast_get_ignorepat_registrar(ip));
03497                }
03498             }
03499             if (!rinclude) {
03500                for (sw = ast_walk_context_switches(c, NULL); sw; sw = ast_walk_context_switches(c, sw)) {
03501                   snprintf(buf, sizeof(buf), "'%s/%s'",
03502                      ast_get_switch_name(sw),
03503                      ast_get_switch_data(sw));
03504                   ast_cli(fd, "  Alt. Switch =>    %-45s [%s]\n",
03505                      buf, ast_get_switch_registrar(sw)); 
03506                }
03507             }
03508    
03509             ast_unlock_context(c);
03510 
03511             /* if we print something in context, make an empty line */
03512             if (context_info_printed) ast_cli(fd, "\r\n");
03513          }
03514       }
03515    }
03516    ast_unlock_contexts();
03517 
03518    if (dpc->total_exten == old_total_exten) {
03519       /* Nothing new under the sun */
03520       return -1;
03521    } else {
03522       return res;
03523    }
03524 }

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, -1 means unlimited (we take any negative value). Always return a copy in workspace.

Definition at line 947 of file pbx.c.

Referenced by pbx_retrieve_variable(), and pbx_substitute_variables_helper_full().

00948 {
00949    char *ret = workspace;
00950    int lr;  /* length of the input string after the copy */
00951 
00952    ast_copy_string(workspace, value, workspace_len); /* always make a copy */
00953 
00954    if (offset == 0 && length < 0)   /* take the whole string */
00955       return ret;
00956 
00957    lr = strlen(ret); /* compute length after copy, so we never go out of the workspace */
00958 
00959    if (offset < 0)   {  /* translate negative offset into positive ones */
00960       offset = lr + offset;
00961       if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */
00962          offset = 0;
00963    }
00964 
00965    /* too large offset result in empty string so we know what to return */
00966    if (offset >= lr)
00967       return ret + lr;  /* the final '\0' */
00968 
00969    ret += offset;    /* move to the start position */
00970    if (length >= 0 && length < lr - offset)  /* truncate if necessary */
00971       ret[length] = '\0';
00972 
00973    return ret;
00974 }

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

Definition at line 5386 of file pbx.c.

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

Referenced by pbx_builtin_busy(), and pbx_builtin_congestion().

05387 {
05388    int res;
05389    struct ast_frame *f;
05390    int waittime;
05391    
05392    if (ast_strlen_zero(data) || (sscanf(data, "%d", &waittime) != 1) || (waittime < 0))
05393       waittime = -1;
05394    if (waittime > -1) {
05395       ast_safe_sleep(chan, waittime * 1000);
05396    } else do {
05397       res = ast_waitfor(chan, -1);
05398       if (res < 0)
05399          return;
05400       f = ast_read(chan);
05401       if (f)
05402          ast_frfree(f);
05403    } while(f);
05404 }


Variable Documentation

struct ast_custom_function* acf_root = NULL [static]
 

Definition at line 237 of file pbx.c.

Referenced by ast_custom_function_find(), ast_custom_function_register(), ast_custom_function_unregister(), complete_show_function(), and handle_show_functions().

struct ast_app* apps = NULL [static]
 

Definition at line 511 of file pbx.c.

Referenced by ast_register_application(), ast_unregister_application(), complete_show_application(), handle_show_application(), handle_show_applications(), and pbx_findapp().

int autofallthrough = 0 [static]
 

Definition at line 231 of file pbx.c.

struct pbx_builtin builtins[] [static]
 

Declaration of builtin applications.

struct ast_context* contexts = NULL [static]
 

Definition at line 509 of file pbx.c.

Referenced by __ast_context_destroy(), ast_context_create(), ast_context_find(), and ast_walk_contexts().

int countcalls = 0 [static]
 

Definition at line 234 of file pbx.c.

char* days[] [static]
 

Definition at line 3921 of file pbx.c.

Referenced by format_uptimestr(), and timesub().

struct varshead globals [static]
 

Definition at line 229 of file pbx.c.

struct ast_hint* hints = NULL
 

Definition at line 525 of file pbx.c.

Referenced by ast_add_hint(), ast_change_hint(), ast_extension_state_add(), ast_extension_state_del(), ast_hint_state_changed(), ast_merge_contexts_and_delete(), ast_remove_hint(), and handle_show_hints().

char* months[] [static]
 

Definition at line 4023 of file pbx.c.

struct ast_cli_entry pbx_cli[] [static]
 

Definition at line 3593 of file pbx.c.

Referenced by load_pbx().

char show_application_help[] [static]
 

Initial value:

 
"Usage: show application <application> [<application> [<application> [...]]]\n"
"       Describes a particular application.\n"

Definition at line 2971 of file pbx.c.

char show_applications_help[] [static]
 

Initial value:

"Usage: 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 2983 of file pbx.c.

char show_dialplan_help[] [static]
 

Initial value:

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

Definition at line 2989 of file pbx.c.

char show_function_help[] [static]
 

Initial value:

"Usage: show function <function>\n"
"       Describe a particular dialplan function.\n"

Definition at line 2979 of file pbx.c.

char show_functions_help[] [static]
 

Initial value:

"Usage: show functions\n"
"       List builtin functions accessable as $(function args)\n"

Definition at line 2975 of file pbx.c.

char show_hints_help[] [static]
 

Initial value:

 
"Usage: show hints\n"
"       Show registered hints\n"

Definition at line 2997 of file pbx.c.

char show_switches_help[] [static]
 

Initial value:

 
"Usage: show switches\n"
"       Show registered switches\n"

Definition at line 2993 of file pbx.c.

struct ast_state_cb* statecbs = NULL
 

Definition at line 526 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_switch* switches = NULL
 

Definition at line 514 of file pbx.c.

Referenced by ast_register_switch(), ast_unregister_switch(), handle_show_switches(), and pbx_findswitch().


Generated on Sat Mar 24 23:29:53 2007 for Asterisk - the Open Source PBX by  doxygen 1.4.6