Wed Oct 28 15:49:07 2009

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)
struct 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)
struct 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)
struct 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)
struct ast_extenast_walk_context_extensions (struct ast_context *con, struct ast_exten *exten)
struct ast_ignorepatast_walk_context_ignorepats (struct ast_context *con, struct ast_ignorepat *ip)
struct ast_includeast_walk_context_includes (struct ast_context *con, struct ast_include *inc)
struct ast_swast_walk_context_switches (struct ast_context *con, struct ast_sw *sw)
struct ast_contextast_walk_contexts (struct ast_context *con)
struct ast_extenast_walk_extension_priorities (struct ast_exten *exten, struct ast_exten *priority)
static void * async_wait (void *data)
static 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)
struct ast_apppbx_findapp (const char *app)
 Find application handle in linked list.
static struct ast_switchpbx_findswitch (const char *sw)
void pbx_retrieve_variable (struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp)
 pbx_retrieve_variable: Support for Asterisk built-in variables ---
int pbx_set_autofallthrough (int newval)
static void pbx_substitute_variables (char *passdata, int datalen, struct ast_channel *c, struct ast_exten *e)
void pbx_substitute_variables_helper (struct ast_channel *c, const char *cp1, char *cp2, int count)
static void pbx_substitute_variables_helper_full (struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count)
void pbx_substitute_variables_varshead (struct varshead *headp, const char *cp1, char *cp2, int count)
static void * pbx_thread (void *data)
static 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
struct 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 []
struct ast_state_cbstatecbs = NULL
static int stateid = 1
struct 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 586 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 924 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 646 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 3855 of file pbx.c.

Referenced by ast_build_timing().

#define HELPER_CANMATCH   3

Definition at line 591 of file pbx.c.

Referenced by ast_canmatch_extension(), pbx_extension_helper(), and pbx_find_extension().

#define HELPER_EXEC   2

Definition at line 590 of file pbx.c.

Referenced by ast_exec_extension(), and pbx_extension_helper().

#define HELPER_EXISTS   0

Definition at line 588 of file pbx.c.

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

#define HELPER_FINDLABEL   5

#define HELPER_MATCHMORE   4

Definition at line 592 of file pbx.c.

Referenced by ast_matchmore_extension(), pbx_extension_helper(), and pbx_find_extension().

#define HELPER_SPAWN   1

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

Referenced by pbx_extension_helper(), and pbx_find_extension().

#define STATUS_NO_EXTENSION   2

Definition at line 775 of file pbx.c.

Referenced by pbx_extension_helper(), and pbx_find_extension().

#define STATUS_NO_LABEL   4

Definition at line 777 of file pbx.c.

Referenced by pbx_extension_helper(), and pbx_find_extension().

#define STATUS_NO_PRIORITY   3

Definition at line 776 of file pbx.c.

Referenced by pbx_extension_helper(), and pbx_find_extension().

#define STATUS_SUCCESS   5

Definition at line 778 of file pbx.c.

Referenced by pbx_find_extension().

#define SWITCH_DATA_LENGTH   256

Definition at line 77 of file pbx.c.

Referenced by ast_context_add_switch2(), and pbx_find_extension().

#define VAR_BUF_SIZE   4096

#define VAR_HARDTRAN   3

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

References ast_context::alts, ast_log(), ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), 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(), and ast_merge_contexts_and_delete().

05342 {
05343    struct ast_context *tmp, *tmpl=NULL;
05344    struct ast_include *tmpi, *tmpil= NULL;
05345    struct ast_sw *sw, *swl= NULL;
05346    struct ast_exten *e, *el, *en;
05347    struct ast_ignorepat *ipi, *ipl = NULL;
05348 
05349    ast_mutex_lock(&conlock);
05350    tmp = contexts;
05351    while(tmp) {
05352       if (((tmp->name && con && con->name && !strcasecmp(tmp->name, con->name)) || !con) &&
05353           (!registrar || !strcasecmp(registrar, tmp->registrar))) {
05354          /* Okay, let's lock the structure to be sure nobody else
05355             is searching through it. */
05356          if (ast_mutex_lock(&tmp->lock)) {
05357             ast_log(LOG_WARNING, "Unable to lock context lock\n");
05358             return;
05359          }
05360          if (tmpl)
05361             tmpl->next = tmp->next;
05362          else
05363             contexts = tmp->next;
05364          /* Okay, now we're safe to let it go -- in a sense, we were
05365             ready to let it go as soon as we locked it. */
05366          ast_mutex_unlock(&tmp->lock);
05367          for (tmpi = tmp->includes; tmpi; ) {
05368             /* Free includes */
05369             tmpil = tmpi;
05370             tmpi = tmpi->next;
05371             free(tmpil);
05372          }
05373          for (ipi = tmp->ignorepats; ipi; ) {
05374             /* Free ignorepats */
05375             ipl = ipi;
05376             ipi = ipi->next;
05377             free(ipl);
05378          }
05379          for (sw = tmp->alts; sw; ) {
05380             /* Free switches */
05381             swl = sw;
05382             sw = sw->next;
05383             free(swl);
05384             swl = sw;
05385          }
05386          for (e = tmp->root; e;) {
05387             for (en = e->peer; en;) {
05388                el = en;
05389                en = en->peer;
05390                destroy_exten(el);
05391             }
05392             el = e;
05393             e = e->next;
05394             destroy_exten(el);
05395          }
05396          ast_mutex_destroy(&tmp->lock);
05397          free(tmp);
05398          if (!con) {
05399             /* Might need to get another one -- restart */
05400             tmp = contexts;
05401             tmpl = NULL;
05402             tmpil = NULL;
05403             continue;
05404          }
05405          ast_mutex_unlock(&conlock);
05406          return;
05407       }
05408       tmpl = tmp;
05409       tmp = tmp->next;
05410    }
05411    ast_mutex_unlock(&conlock);
05412 }

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

Definition at line 6478 of file pbx.c.

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

Referenced by ast_async_goto_if_exists(), and ast_goto_if_exists().

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

static int __ast_pbx_run ( struct ast_channel c  )  [static]

Definition at line 2258 of file pbx.c.

References ast_channel::_softhangup, ast_channel::amaflags, ast_cdr_alloc(), ast_cdr_init(), ast_cdr_start(), ast_cdr_update(), ast_exists_extension(), AST_FLAG_IN_AUTOLOOP, ast_hangup(), ast_log(), ast_matchmore_extension(), AST_PBX_KEEPALIVE, ast_set2_flag, ast_set_flag, AST_SOFTHANGUP_ASYNCGOTO, AST_SOFTHANGUP_TIMEOUT, ast_spawn_extension(), ast_strlen_zero(), ast_test_flag, ast_verbose(), ast_waitfordigit(), 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_debug, option_verbose, ast_channel::pbx, pbx_builtin_busy(), pbx_builtin_congestion(), pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), pbx_destroy(), ast_channel::priority, ast_pbx::rtimeout, ast_cdr::start, VERBOSE_PREFIX_2, VERBOSE_PREFIX_3, and ast_channel::whentohangup.

Referenced by ast_pbx_run(), and pbx_thread().

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

int ast_active_calls ( void   ) 

Definition at line 2584 of file pbx.c.

Referenced by handle_chanlist().

02585 {
02586    return countcalls;
02587 }

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

04529 {
04530    struct ast_context *c;
04531 
04532    if (ast_lock_contexts()) {
04533       errno = EBUSY;
04534       return -1;
04535    }
04536 
04537    c = ast_walk_contexts(NULL);
04538    while (c) {
04539       if (!strcmp(context, ast_get_context_name(c))) {
04540          int ret = ast_add_extension2(c, replace, extension, priority, label, callerid,
04541             application, data, datad, registrar);
04542          ast_unlock_contexts();
04543          return ret;
04544       }
04545       c = ast_walk_contexts(c);
04546    }
04547 
04548    ast_unlock_contexts();
04549    errno = ENOENT;
04550    return -1;
04551 }

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

Add an extension to an extension context, this time with an ast_context *. CallerID is a pattern to match on callerid, or NULL to not care about callerid

For details about the arguements, check ast_add_extension()

Definition at line 4666 of file pbx.c.

References ast_exten::app, 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, globals, ast_exten::label, ast_context::lock, LOG, LOG_ERROR, LOG_WARNING, malloc, ast_exten::matchcid, ast_context::name, ast_exten::next, null_datad(), ast_exten::parent, pbx_substitute_variables_varshead(), ast_exten::peer, ast_exten::priority, PRIORITY_HINT, ast_exten::registrar, ast_context::root, ast_exten::stuff, and VAR_BUF_SIZE.

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

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

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

References ast_extension_state2(), ast_get_extension_app(), ast_get_extension_name(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_hint::exten, ast_hint::laststate, list, LOG_DEBUG, malloc, ast_hint::next, and option_debug.

Referenced by ast_add_extension2().

02096 {
02097    struct ast_hint *list;
02098 
02099    if (!e) 
02100       return -1;
02101 
02102    ast_mutex_lock(&hintlock);
02103    list = hints;        
02104 
02105    /* Search if hint exists, do nothing */
02106    while (list) {
02107       if (list->exten == e) {
02108          ast_mutex_unlock(&hintlock);
02109          if (option_debug > 1)
02110             ast_log(LOG_DEBUG, "HINTS: Not re-adding existing hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e));
02111          return -1;
02112       }
02113       list = list->next;    
02114    }
02115 
02116    if (option_debug > 1)
02117       ast_log(LOG_DEBUG, "HINTS: Adding hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e));
02118 
02119    list = malloc(sizeof(struct ast_hint));
02120    if (!list) {
02121       ast_mutex_unlock(&hintlock);
02122       if (option_debug > 1)
02123          ast_log(LOG_DEBUG, "HINTS: Out of memory...\n");
02124       return -1;
02125    }
02126    /* Initialize and insert new item at the top */
02127    memset(list, 0, sizeof(struct ast_hint));
02128    list->exten = e;
02129    list->laststate = ast_extension_state2(e);
02130    list->next = hints;
02131    hints = list;
02132 
02133    ast_mutex_unlock(&hintlock);
02134    return 0;
02135 }

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 4572 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(), i4l_read(), monitor_handle_owned(), process_ast_dsp(), socket_read(), and zt_handle_dtmfup().

04573 {
04574    int res = 0;
04575 
04576    ast_mutex_lock(&chan->lock);
04577 
04578    if (chan->pbx) {
04579       /* This channel is currently in the PBX */
04580       ast_explicit_goto(chan, context, exten, priority);
04581       ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO);
04582    } else {
04583       /* In order to do it when the channel doesn't really exist within
04584          the PBX, we have to make a new channel, masquerade, and start the PBX
04585          at the new location */
04586       struct ast_channel *tmpchan;
04587       tmpchan = ast_channel_alloc(0);
04588       if (tmpchan) {
04589          snprintf(tmpchan->name, sizeof(tmpchan->name), "AsyncGoto/%s", chan->name);
04590          ast_setstate(tmpchan, chan->_state);
04591          /* Make formats okay */
04592          tmpchan->readformat = chan->readformat;
04593          tmpchan->writeformat = chan->writeformat;
04594          /* Setup proper location */
04595          ast_explicit_goto(tmpchan,
04596                  (!ast_strlen_zero(context)) ? context : chan->context,
04597                  (!ast_strlen_zero(exten)) ? exten : chan->exten,
04598                  priority);
04599 
04600          /* Masquerade into temp channel */
04601          ast_channel_masquerade(tmpchan, chan);
04602       
04603          /* Grab the locks and get going */
04604          ast_mutex_lock(&tmpchan->lock);
04605          ast_do_masquerade(tmpchan);
04606          ast_mutex_unlock(&tmpchan->lock);
04607          /* Start the PBX going on our stolen channel */
04608          if (ast_pbx_start(tmpchan)) {
04609             ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name);
04610             ast_hangup(tmpchan);
04611             res = -1;
04612          }
04613       } else {
04614          res = -1;
04615       }
04616    }
04617    ast_mutex_unlock(&chan->lock);
04618    return res;
04619 }

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

Definition at line 4621 of file pbx.c.

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

04622 {
04623    struct ast_channel *chan;
04624    int res = -1;
04625 
04626    chan = ast_get_channel_by_name_locked(channame);
04627    if (chan) {
04628       res = ast_async_goto(chan, context, exten, priority);
04629       ast_mutex_unlock(&chan->lock);
04630    }
04631    return res;
04632 }

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

Definition at line 6499 of file pbx.c.

References __ast_goto_if_exists().

06499                                                                                                  {
06500    return __ast_goto_if_exists(chan, context, exten, priority, 1);
06501 }

int ast_build_timing ( struct ast_timing i,
char *  info_in 
)

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

04106 {
04107    char info_save[256];
04108    char *info;
04109    char *c;
04110 
04111    /* Check for empty just in case */
04112    if (ast_strlen_zero(info_in))
04113       return 0;
04114    /* make a copy just in case we were passed a static string */
04115    ast_copy_string(info_save, info_in, sizeof(info_save));
04116    info = info_save;
04117    /* Assume everything except time */
04118    i->monthmask = (1 << 12) - 1;
04119    i->daymask = (1 << 30) - 1 + (1 << 30);
04120    i->dowmask = (1 << 7) - 1;
04121    /* Avoid using str tok */
04122    FIND_NEXT;
04123    /* Info has the time range, start with that */
04124    get_timerange(i, info);
04125    info = c;
04126    if (!info)
04127       return 1;
04128    FIND_NEXT;
04129    /* Now check for day of week */
04130    i->dowmask = get_dow(info);
04131 
04132    info = c;
04133    if (!info)
04134       return 1;
04135    FIND_NEXT;
04136    /* Now check for the day of the month */
04137    i->daymask = get_day(info);
04138    info = c;
04139    if (!info)
04140       return 1;
04141    FIND_NEXT;
04142    /* And finally go for the month */
04143    i->monthmask = get_month(info);
04144 
04145    return 1;
04146 }

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

Looks for a valid matching extension

Parameters:
c not really important
context context to serach within
exten extension to check
priority priority of extension path
callerid callerid of extension being searched for 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 2238 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().

02239 {
02240    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, HELPER_CANMATCH);
02241 }

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

References ast_mutex_lock(), ast_mutex_unlock(), ast_hint::exten, list, and ast_hint::next.

Referenced by ast_add_extension2().

02139 { 
02140    struct ast_hint *list;
02141 
02142    ast_mutex_lock(&hintlock);
02143    list = hints;
02144 
02145    while(list) {
02146       if (list->exten == oe) {
02147             list->exten = ne;
02148          ast_mutex_unlock(&hintlock);  
02149          return 0;
02150       }
02151       list = list->next;
02152    }
02153    ast_mutex_unlock(&hintlock);
02154 
02155    return -1;
02156 }

int ast_check_timing ( struct ast_timing i  ) 

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

04149 {
04150    struct tm tm;
04151    time_t t;
04152 
04153    time(&t);
04154    localtime_r(&t,&tm);
04155 
04156    /* If it's not the right month, return */
04157    if (!(i->monthmask & (1 << tm.tm_mon))) {
04158       return 0;
04159    }
04160 
04161    /* If it's not that time of the month.... */
04162    /* Warning, tm_mday has range 1..31! */
04163    if (!(i->daymask & (1 << (tm.tm_mday-1))))
04164       return 0;
04165 
04166    /* If it's not the right day of the week */
04167    if (!(i->dowmask & (1 << tm.tm_wday)))
04168       return 0;
04169 
04170    /* Sanity check the hour just to be safe */
04171    if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) {
04172       ast_log(LOG_WARNING, "Insane time...\n");
04173       return 0;
04174    }
04175 
04176    /* Now the tough part, we calculate if it fits
04177       in the right time based on min/hour */
04178    if (!(i->minmask[tm.tm_hour] & (1 << (tm.tm_min / 2))))
04179       return 0;
04180 
04181    /* If we got this far, then we're good */
04182    return 1;
04183 }

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

Add an ignorepat

Parameters:
context which context to add the ignorpattern to
ignorepat ignorepattern to set up for the extension
registrar registrar of the ignore pattern Adds an ignore pattern to a particular context. Returns 0 on success, -1 on failure

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

04445 {
04446    struct ast_context *c;
04447 
04448    if (ast_lock_contexts()) {
04449       errno = EBUSY;
04450       return -1;
04451    }
04452 
04453    c = ast_walk_contexts(NULL);
04454    while (c) {
04455       if (!strcmp(ast_get_context_name(c), con)) {
04456          int ret = ast_context_add_ignorepat2(c, value, registrar);
04457          ast_unlock_contexts();
04458          return ret;
04459       } 
04460       c = ast_walk_contexts(c);
04461    }
04462 
04463    ast_unlock_contexts();
04464    errno = ENOENT;
04465    return -1;
04466 }

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

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

04469 {
04470    struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL;
04471    int length;
04472    length = sizeof(struct ast_ignorepat);
04473    length += strlen(value) + 1;
04474    ignorepat = malloc(length);
04475    if (!ignorepat) {
04476       ast_log(LOG_ERROR, "Out of memory\n");
04477       errno = ENOMEM;
04478       return -1;
04479    }
04480    memset(ignorepat, 0, length);
04481    strcpy(ignorepat->pattern, value);
04482    ignorepat->next = NULL;
04483    ignorepat->registrar = registrar;
04484    ast_mutex_lock(&con->lock);
04485    ignorepatc = con->ignorepats;
04486    while(ignorepatc) {
04487       ignorepatl = ignorepatc;
04488       if (!strcasecmp(ignorepatc->pattern, value)) {
04489          /* Already there */
04490          ast_mutex_unlock(&con->lock);
04491          errno = EEXIST;
04492          return -1;
04493       }
04494       ignorepatc = ignorepatc->next;
04495    }
04496    if (ignorepatl) 
04497       ignorepatl->next = ignorepat;
04498    else
04499       con->ignorepats = ignorepat;
04500    ast_mutex_unlock(&con->lock);
04501    return 0;
04502    
04503 }

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

Add an include

Parameters:
context context to add include to
include new include to add
registrar who's registering it Adds an include taking a char * string as the context parameter Returns 0 on success, -1 on error

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

03828 {
03829    struct ast_context *c;
03830 
03831    if (ast_lock_contexts()) {
03832       errno = EBUSY;
03833       return -1;
03834    }
03835 
03836    /* walk contexts ... */
03837    c = ast_walk_contexts(NULL);
03838    while (c) {
03839       /* ... search for the right one ... */
03840       if (!strcmp(ast_get_context_name(c), context)) {
03841          int ret = ast_context_add_include2(c, include, registrar);
03842          /* ... unlock contexts list and return */
03843          ast_unlock_contexts();
03844          return ret;
03845       }
03846       c = ast_walk_contexts(c);
03847    }
03848 
03849    /* we can't find the right context */
03850    ast_unlock_contexts();
03851    errno = ENOENT;
03852    return -1;
03853 }

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

Add an include

Parameters:
con context to add the include to
include include to add
registrar who registered the context Adds an include taking a struct ast_context as the first parameter Returns 0 on success, -1 on failure

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

04194 {
04195    struct ast_include *new_include;
04196    char *c;
04197    struct ast_include *i, *il = NULL; /* include, include_last */
04198    int length;
04199    char *p;
04200    
04201    length = sizeof(struct ast_include);
04202    length += 2 * (strlen(value) + 1);
04203 
04204    /* allocate new include structure ... */
04205    if (!(new_include = malloc(length))) {
04206       ast_log(LOG_ERROR, "Out of memory\n");
04207       errno = ENOMEM;
04208       return -1;
04209    }
04210    
04211    /* ... fill in this structure ... */
04212    memset(new_include, 0, length);
04213    p = new_include->stuff;
04214    new_include->name = p;
04215    strcpy(new_include->name, value);
04216    p += strlen(value) + 1;
04217    new_include->rname = p;
04218    strcpy(new_include->rname, value);
04219    c = new_include->rname;
04220    /* Strip off timing info */
04221    while(*c && (*c != '|')) 
04222       c++; 
04223    /* Process if it's there */
04224    if (*c) {
04225            new_include->hastime = ast_build_timing(&(new_include->timing), c+1);
04226       *c = '\0';
04227    }
04228    new_include->next      = NULL;
04229    new_include->registrar = registrar;
04230 
04231    /* ... try to lock this context ... */
04232    if (ast_mutex_lock(&con->lock)) {
04233       free(new_include);
04234       errno = EBUSY;
04235       return -1;
04236    }
04237 
04238    /* ... go to last include and check if context is already included too... */
04239    i = con->includes;
04240    while (i) {
04241       if (!strcasecmp(i->name, new_include->name)) {
04242          free(new_include);
04243          ast_mutex_unlock(&con->lock);
04244          errno = EEXIST;
04245          return -1;
04246       }
04247       il = i;
04248       i = i->next;
04249    }
04250 
04251    /* ... include new context into context list, unlock, return */
04252    if (il)
04253       il->next = new_include;
04254    else
04255       con->includes = new_include;
04256    if (option_verbose > 2)
04257       ast_verbose(VERBOSE_PREFIX_3 "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con)); 
04258    ast_mutex_unlock(&con->lock);
04259 
04260    return 0;
04261 }

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

Add a switch

Parameters:
context context to which to add the switch
sw switch to add
data data to pass to switch
eval whether to evaluate variables when running switch
registrar whoever registered the switch This function registers a switch with the asterisk switch architecture It returns 0 on success, -1 on failure

Definition at line 4268 of file pbx.c.

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

04269 {
04270    struct ast_context *c;
04271 
04272    if (ast_lock_contexts()) {
04273       errno = EBUSY;
04274       return -1;
04275    }
04276 
04277    /* walk contexts ... */
04278    c = ast_walk_contexts(NULL);
04279    while (c) {
04280       /* ... search for the right one ... */
04281       if (!strcmp(ast_get_context_name(c), context)) {
04282          int ret = ast_context_add_switch2(c, sw, data, eval, registrar);
04283          /* ... unlock contexts list and return */
04284          ast_unlock_contexts();
04285          return ret;
04286       }
04287       c = ast_walk_contexts(c);
04288    }
04289 
04290    /* we can't find the right context */
04291    ast_unlock_contexts();
04292    errno = ENOENT;
04293    return -1;
04294 }

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

Adds a switch (first param is a ast_context)

See ast_context_add_switch()

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

04305 {
04306    struct ast_sw *new_sw;
04307    struct ast_sw *i, *il = NULL; /* sw, sw_last */
04308    int length;
04309    char *p;
04310    
04311    length = sizeof(struct ast_sw);
04312    length += strlen(value) + 1;
04313    if (data)
04314       length += strlen(data);
04315    length++;
04316    if (eval) {
04317       /* Create buffer for evaluation of variables */
04318       length += SWITCH_DATA_LENGTH;
04319       length++;
04320    }
04321 
04322    /* allocate new sw structure ... */
04323    if (!(new_sw = malloc(length))) {
04324       ast_log(LOG_ERROR, "Out of memory\n");
04325       errno = ENOMEM;
04326       return -1;
04327    }
04328    
04329    /* ... fill in this structure ... */
04330    memset(new_sw, 0, length);
04331    p = new_sw->stuff;
04332    new_sw->name = p;
04333    strcpy(new_sw->name, value);
04334    p += strlen(value) + 1;
04335    new_sw->data = p;
04336    if (data) {
04337       strcpy(new_sw->data, data);
04338       p += strlen(data) + 1;
04339    } else {
04340       strcpy(new_sw->data, "");
04341       p++;
04342    }
04343    if (eval) 
04344       new_sw->tmpdata = p;
04345    new_sw->next      = NULL;
04346    new_sw->eval     = eval;
04347    new_sw->registrar = registrar;
04348 
04349    /* ... try to lock this context ... */
04350    if (ast_mutex_lock(&con->lock)) {
04351       free(new_sw);
04352       errno = EBUSY;
04353       return -1;
04354    }
04355 
04356    /* ... go to last sw and check if context is already swd too... */
04357    i = con->alts;
04358    while (i) {
04359       if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) {
04360          free(new_sw);
04361          ast_mutex_unlock(&con->lock);
04362          errno = EEXIST;
04363          return -1;
04364       }
04365       il = i;
04366       i = i->next;
04367    }
04368 
04369    /* ... sw new context into context list, unlock, return */
04370    if (il)
04371       il->next = new_sw;
04372    else
04373       con->alts = new_sw;
04374    if (option_verbose > 2)
04375       ast_verbose(VERBOSE_PREFIX_3 "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con)); 
04376    ast_mutex_unlock(&con->lock);
04377 
04378    return 0;
04379 }

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

Register a new context

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

Definition at line 3662 of file pbx.c.

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

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

03663 {
03664    struct ast_context *tmp, **local_contexts;
03665    int length;
03666    length = sizeof(struct ast_context);
03667    length += strlen(name) + 1;
03668    if (!extcontexts) {
03669       local_contexts = &contexts;
03670       ast_mutex_lock(&conlock);
03671    } else
03672       local_contexts = extcontexts;
03673 
03674    tmp = *local_contexts;
03675    while(tmp) {
03676       if (!strcasecmp(tmp->name, name)) {
03677          ast_log(LOG_WARNING, "Tried to register context '%s', already in use\n", name);
03678          if (!extcontexts)
03679             ast_mutex_unlock(&conlock);
03680          return NULL;
03681       }
03682       tmp = tmp->next;
03683    }
03684    tmp = malloc(length);
03685    if (tmp) {
03686       memset(tmp, 0, length);
03687       ast_mutex_init(&tmp->lock);
03688       strcpy(tmp->name, name);
03689       tmp->root = NULL;
03690       tmp->registrar = registrar;
03691       tmp->next = *local_contexts;
03692       tmp->includes = NULL;
03693       tmp->ignorepats = NULL;
03694       *local_contexts = tmp;
03695       if (option_debug)
03696          ast_log(LOG_DEBUG, "Registered context '%s'\n", tmp->name);
03697       if (option_verbose > 2)
03698          ast_verbose( VERBOSE_PREFIX_3 "Registered extension context '%s'\n", tmp->name);
03699    } else
03700       ast_log(LOG_ERROR, "Out of memory\n");
03701    
03702    if (!extcontexts)
03703       ast_mutex_unlock(&conlock);
03704    return tmp;
03705 }

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

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

Parameters:
con context to destroy
registrar who registered it You can optionally leave out either parameter. It will find it based on either the ast_context or the registrar name. Returns nothing

Definition at line 5414 of file pbx.c.

References __ast_context_destroy().

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

05415 {
05416    __ast_context_destroy(con,registrar);
05417 }

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

Find a context

Parameters:
name name of the context to find Will search for the context with the given name. Returns the ast_context on success, NULL on failure.

Definition at line 757 of file pbx.c.

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

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

00758 {
00759    struct ast_context *tmp;
00760    ast_mutex_lock(&conlock);
00761    if (name) {
00762       tmp = contexts;
00763       while(tmp) {
00764          if (!strcasecmp(name, tmp->name))
00765             break;
00766          tmp = tmp->next;
00767       }
00768    } else
00769       tmp = contexts;
00770    ast_mutex_unlock(&conlock);
00771    return tmp;
00772 }

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

Simply remove extension from context

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

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

02748 {
02749    struct ast_context *c;
02750 
02751    if (ast_lock_contexts()) return -1;
02752 
02753    /* walk contexts ... */
02754    c = ast_walk_contexts(NULL);
02755    while (c) {
02756       /* ... search for the right one ... */
02757       if (!strcmp(ast_get_context_name(c), context)) {
02758          /* ... remove extension ... */
02759          int ret = ast_context_remove_extension2(c, extension, priority,
02760             registrar);
02761          /* ... unlock contexts list and return */
02762          ast_unlock_contexts();
02763          return ret;
02764       }
02765       c = ast_walk_contexts(c);
02766    }
02767 
02768    /* we can't find the right context */
02769    ast_unlock_contexts();
02770    return -1;
02771 }

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

References ast_mutex_lock(), ast_mutex_unlock(), ast_remove_hint(), ast_exten::data, ast_exten::datad, ast_exten::exten, 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().

02784 {
02785    struct ast_exten *exten, *prev_exten = NULL;
02786 
02787    if (ast_mutex_lock(&con->lock)) return -1;
02788 
02789    /* go through all extensions in context and search the right one ... */
02790    exten = con->root;
02791    while (exten) {
02792 
02793       /* look for right extension */
02794       if (!strcmp(exten->exten, extension) &&
02795          (!registrar || !strcmp(exten->registrar, registrar))) {
02796          struct ast_exten *peer;
02797 
02798          /* should we free all peers in this extension? (priority == 0)? */
02799          if (priority == 0) {
02800             /* remove this extension from context list */
02801             if (prev_exten)
02802                prev_exten->next = exten->next;
02803             else
02804                con->root = exten->next;
02805 
02806             /* fire out all peers */
02807             peer = exten; 
02808             while (peer) {
02809                exten = peer->peer;
02810                
02811                if (!peer->priority==PRIORITY_HINT) 
02812                    ast_remove_hint(peer);
02813 
02814                peer->datad(peer->data);
02815                free(peer);
02816 
02817                peer = exten;
02818             }
02819 
02820             ast_mutex_unlock(&con->lock);
02821             return 0;
02822          } else {
02823             /* remove only extension with exten->priority == priority */
02824             struct ast_exten *previous_peer = NULL;
02825 
02826             peer = exten;
02827             while (peer) {
02828                /* is this our extension? */
02829                if (peer->priority == priority &&
02830                   (!registrar || !strcmp(peer->registrar, registrar) )) {
02831                   /* we are first priority extension? */
02832                   if (!previous_peer) {
02833                      /* exists previous extension here? */
02834                      if (prev_exten) {
02835                         /* yes, so we must change next pointer in
02836                          * previous connection to next peer
02837                          */
02838                         if (peer->peer) {
02839                            prev_exten->next = peer->peer;
02840                            peer->peer->next = exten->next;
02841                         } else
02842                            prev_exten->next = exten->next;
02843                      } else {
02844                         /* no previous extension, we are first
02845                          * extension, so change con->root ...
02846                          */
02847                         if (peer->peer)
02848                            con->root = peer->peer;
02849                         else
02850                            con->root = exten->next; 
02851                      }
02852                   } else {
02853                      /* we are not first priority in extension */
02854                      previous_peer->peer = peer->peer;
02855                   }
02856 
02857                   /* now, free whole priority extension */
02858                   if (peer->priority==PRIORITY_HINT)
02859                       ast_remove_hint(peer);
02860                   peer->datad(peer->data);
02861                   free(peer);
02862 
02863                   ast_mutex_unlock(&con->lock);
02864                   return 0;
02865                } else {
02866                   /* this is not right extension, skip to next peer */
02867                   previous_peer = peer;
02868                   peer = peer->peer;
02869                }
02870             }
02871 
02872             ast_mutex_unlock(&con->lock);
02873             return -1;
02874          }
02875       }
02876 
02877       prev_exten = exten;
02878       exten = exten->next;
02879    }
02880 
02881    /* we can't find right extension */
02882    ast_mutex_unlock(&con->lock);
02883    return -1;
02884 }

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

04386 {
04387    struct ast_context *c;
04388 
04389    if (ast_lock_contexts()) {
04390       errno = EBUSY;
04391       return -1;
04392    }
04393 
04394    c = ast_walk_contexts(NULL);
04395    while (c) {
04396       if (!strcmp(ast_get_context_name(c), context)) {
04397          int ret = ast_context_remove_ignorepat2(c, ignorepat, registrar);
04398          ast_unlock_contexts();
04399          return ret;
04400       }
04401       c = ast_walk_contexts(c);
04402    }
04403 
04404    ast_unlock_contexts();
04405    errno = ENOENT;
04406    return -1;
04407 }

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

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

04410 {
04411    struct ast_ignorepat *ip, *ipl = NULL;
04412 
04413    if (ast_mutex_lock(&con->lock)) {
04414       errno = EBUSY;
04415       return -1;
04416    }
04417 
04418    ip = con->ignorepats;
04419    while (ip) {
04420       if (!strcmp(ip->pattern, ignorepat) &&
04421          (!registrar || (registrar == ip->registrar))) {
04422          if (ipl) {
04423             ipl->next = ip->next;
04424             free(ip);
04425          } else {
04426             con->ignorepats = ip->next;
04427             free(ip);
04428          }
04429          ast_mutex_unlock(&con->lock);
04430          return 0;
04431       }
04432       ipl = ip; ip = ip->next;
04433    }
04434 
04435    ast_mutex_unlock(&con->lock);
04436    errno = EINVAL;
04437    return -1;
04438 }

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

Removes an include

See add_include

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

02604 {
02605    struct ast_context *c;
02606 
02607    if (ast_lock_contexts()) return -1;
02608 
02609    /* walk contexts and search for the right one ...*/
02610    c = ast_walk_contexts(NULL);
02611    while (c) {
02612       /* we found one ... */
02613       if (!strcmp(ast_get_context_name(c), context)) {
02614          int ret;
02615          /* remove include from this context ... */   
02616          ret = ast_context_remove_include2(c, include, registrar);
02617 
02618          ast_unlock_contexts();
02619 
02620          /* ... return results */
02621          return ret;
02622       }
02623       c = ast_walk_contexts(c);
02624    }
02625 
02626    /* we can't find the right one context */
02627    ast_unlock_contexts();
02628    return -1;
02629 }

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

Removes an include by an ast_context structure

See add_include2

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

02640 {
02641    struct ast_include *i, *pi = NULL;
02642 
02643    if (ast_mutex_lock(&con->lock)) return -1;
02644 
02645    /* walk includes */
02646    i = con->includes;
02647    while (i) {
02648       /* find our include */
02649       if (!strcmp(i->name, include) && 
02650          (!registrar || !strcmp(i->registrar, registrar))) {
02651          /* remove from list */
02652          if (pi)
02653             pi->next = i->next;
02654          else
02655             con->includes = i->next;
02656          /* free include and return */
02657          free(i);
02658          ast_mutex_unlock(&con->lock);
02659          return 0;
02660       }
02661       pi = i;
02662       i = i->next;
02663    }
02664 
02665    /* we can't find the right include */
02666    ast_mutex_unlock(&con->lock);
02667    return -1;
02668 }

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

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

02676 {
02677    struct ast_context *c;
02678 
02679    if (ast_lock_contexts()) return -1;
02680 
02681    /* walk contexts and search for the right one ...*/
02682    c = ast_walk_contexts(NULL);
02683    while (c) {
02684       /* we found one ... */
02685       if (!strcmp(ast_get_context_name(c), context)) {
02686          int ret;
02687          /* remove switch from this context ... */ 
02688          ret = ast_context_remove_switch2(c, sw, data, registrar);
02689 
02690          ast_unlock_contexts();
02691 
02692          /* ... return results */
02693          return ret;
02694       }
02695       c = ast_walk_contexts(c);
02696    }
02697 
02698    /* we can't find the right one context */
02699    ast_unlock_contexts();
02700    return -1;
02701 }

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

02712 {
02713    struct ast_sw *i, *pi = NULL;
02714 
02715    if (ast_mutex_lock(&con->lock)) return -1;
02716 
02717    /* walk switchs */
02718    i = con->alts;
02719    while (i) {
02720       /* find our switch */
02721       if (!strcmp(i->name, sw) && !strcmp(i->data, data) && 
02722          (!registrar || !strcmp(i->registrar, registrar))) {
02723          /* remove from list */
02724          if (pi)
02725             pi->next = i->next;
02726          else
02727             con->alts = i->next;
02728          /* free switch and return */
02729          free(i);
02730          ast_mutex_unlock(&con->lock);
02731          return 0;
02732       }
02733       pi = i;
02734       i = i->next;
02735    }
02736 
02737    /* we can't find the right switch */
02738    ast_mutex_unlock(&con->lock);
02739    return -1;
02740 }

int ast_context_verify_includes ( struct ast_context con  ) 

Verifies includes in an ast_contect structure

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

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

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

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

Definition at line 1287 of file pbx.c.

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

01288 {
01289    struct ast_custom_function *acfptr;
01290 
01291    /* try to lock functions list ... */
01292    if (ast_mutex_lock(&acflock)) {
01293       ast_log(LOG_ERROR, "Unable to lock function list\n");
01294       return NULL;
01295    }
01296 
01297    for (acfptr = acf_root; acfptr; acfptr = acfptr->next) {
01298       if (!strcmp(name, acfptr->name)) {
01299          break;
01300       }
01301    }
01302 
01303    ast_mutex_unlock(&acflock);
01304    
01305    return acfptr;
01306 }

int ast_custom_function_register ( struct ast_custom_function acf  ) 

Definition at line 1343 of file pbx.c.

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

01344 {
01345    if (!acf)
01346       return -1;
01347 
01348    /* try to lock functions list ... */
01349    if (ast_mutex_lock(&acflock)) {
01350       ast_log(LOG_ERROR, "Unable to lock function list. Failed registering function %s\n", acf->name);
01351       return -1;
01352    }
01353 
01354    if (ast_custom_function_find(acf->name)) {
01355       ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name);
01356       ast_mutex_unlock(&acflock);
01357       return -1;
01358    }
01359 
01360    acf->next = acf_root;
01361    acf_root = acf;
01362 
01363    ast_mutex_unlock(&acflock);
01364 
01365    if (option_verbose > 1)
01366       ast_verbose(VERBOSE_PREFIX_2 "Registered custom function %s\n", acf->name);
01367 
01368    return 0;
01369 }

int ast_custom_function_unregister ( struct ast_custom_function acf  ) 

Definition at line 1308 of file pbx.c.

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

01309 {
01310    struct ast_custom_function *acfptr, *lastacf = NULL;
01311    int res = -1;
01312 
01313    if (!acf)
01314       return -1;
01315 
01316    /* try to lock functions list ... */
01317    if (ast_mutex_lock(&acflock)) {
01318       ast_log(LOG_ERROR, "Unable to lock function list\n");
01319       return -1;
01320    }
01321 
01322    for (acfptr = acf_root; acfptr; acfptr = acfptr->next) {
01323       if (acfptr == acf) {
01324          if (lastacf) {
01325             lastacf->next = acf->next;
01326          } else {
01327             acf_root = acf->next;
01328          }
01329          res = 0;
01330          break;
01331       }
01332       lastacf = acfptr;
01333    }
01334 
01335    ast_mutex_unlock(&acflock);
01336 
01337    if (!res && (option_verbose > 1))
01338       ast_verbose(VERBOSE_PREFIX_2 "Unregistered custom function %s\n", acf->name);
01339 
01340    return res;
01341 }

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

Execute an extension.

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

References HELPER_EXEC, and pbx_extension_helper().

Referenced by loopback_exec().

02254 {
02255    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, HELPER_EXEC);
02256 }

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

If an extension exists, return non-zero

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 2223 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_app_dtget(), ast_pbx_outgoing_exten(), ast_waitstream_exten(), builtin_atxfer(), builtin_blindtransfer(), cb_events(), console_dial(), console_transfer(), disa_exec(), dp_lookup(), dundi_lookup_local(), get_also_info(), get_destination(), get_refer_info(), handle_link_data(), handle_link_phone_dtmf(), i4l_read(), leave_voicemail(), local_alloc(), loopback_exists(), macro_exec(), mgcp_ss(), misdn_overlap_dial_task(), monitor_handle_notowned(), monitor_handle_owned(), parkandannounce_exec(), pbx_builtin_waitexten(), phone_check_exception(), process_ast_dsp(), register_peer_exten(), rpt(), rpt_exec(), skinny_ss(), socket_read(), ss_thread(), and zt_handle_dtmfup().

02224 {
02225    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, HELPER_EXISTS);
02226 }

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

Definition at line 4553 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(), disa_exec(), and handle_setpriority().

04554 {
04555    if (!chan)
04556       return -1;
04557 
04558    if (!ast_strlen_zero(context))
04559       ast_copy_string(chan->context, context, sizeof(chan->context));
04560    if (!ast_strlen_zero(exten))
04561       ast_copy_string(chan->exten, exten, sizeof(chan->exten));
04562    if (priority > -1) {
04563       chan->priority = priority;
04564       /* see flag description in channel.h for explanation */
04565       if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP))
04566          chan->priority--;
04567    }
04568    
04569    return 0;
04570 }

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

Definition at line 736 of file pbx.c.

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

Referenced by pbx_find_extension(), and realtime_switch_common().

00737 {
00738    int match;
00739    /* If "data" is longer, it can'be a subset of pattern unless
00740       pattern is a pattern match */
00741    if ((strlen(pattern) < strlen(data)) && (pattern[0] != '_'))
00742       return 0;
00743    
00744    if ((ast_strlen_zero((char *)data) || !strncasecmp(pattern, data, strlen(data))) && 
00745       (!needmore || (strlen(pattern) > strlen(data)))) {
00746       return 1;
00747    }
00748    EXTENSION_MATCH_CORE(data,pattern,match);
00749    /* If there's more or we don't care about more, or if it's a possible early match, 
00750       return non-zero; otherwise it's a miss */
00751    if (!needmore || *pattern || match == 2) {
00752       return match;
00753    } else
00754       return 0;
00755 }

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

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

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

Definition at line 723 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(), misdn_cfg_is_msn_valid(), pbx_find_extension(), realtime_switch_common(), and show_dialplan_helper().

00724 {
00725    int match;
00726    /* If they're the same return */
00727    if (!strcmp(pattern, data))
00728       return 1;
00729    EXTENSION_MATCH_CORE(data,pattern,match);
00730    /* Must be at the end of both */
00731    if (*data || (*pattern && (*pattern != '/')))
00732       match = 0;
00733    return match;
00734 }

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

ast_extension_state: Check extension state for an extension by using hint

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

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

References ast_extension_state2(), and ast_hint_extension().

Referenced by action_extensionstate(), and handle_request_subscribe().

01896 {
01897    struct ast_exten *e;
01898 
01899    e = ast_hint_extension(c, context, exten);   /* Do we have a hint for this extension ? */ 
01900    if (!e) 
01901       return -1;           /* No hint, return -1 */
01902 
01903    return ast_extension_state2(e);        /* Check all devices in the hint */
01904 }

static int ast_extension_state2 ( struct ast_exten e  )  [static]

ast_extensions_state2: Check state of extension by using hints

Definition at line 1808 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, inuse, and ring().

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

01809 {
01810    char hint[AST_MAX_EXTENSION] = "";    
01811    char *cur, *rest;
01812    int res = -1;
01813    int allunavailable = 1, allbusy = 1, allfree = 1;
01814    int busy = 0, inuse = 0, ring = 0;
01815 
01816    if (!e)
01817       return -1;
01818 
01819    ast_copy_string(hint, ast_get_extension_app(e), sizeof(hint));
01820 
01821    cur = hint;       /* On or more devices separated with a & character */
01822    do {
01823       rest = strchr(cur, '&');
01824       if (rest) {
01825          *rest = 0;
01826          rest++;
01827       }
01828    
01829       res = ast_device_state(cur);
01830       switch (res) {
01831       case AST_DEVICE_NOT_INUSE:
01832          allunavailable = 0;
01833          allbusy = 0;
01834          break;
01835       case AST_DEVICE_INUSE:
01836          inuse = 1;
01837          allunavailable = 0;
01838          allfree = 0;
01839          break;
01840       case AST_DEVICE_RINGING:
01841          ring = 1;
01842          allunavailable = 0;
01843          allfree = 0;
01844          break;
01845       case AST_DEVICE_BUSY:
01846          allunavailable = 0;
01847          allfree = 0;
01848          busy = 1;
01849          break;
01850       case AST_DEVICE_UNAVAILABLE:
01851       case AST_DEVICE_INVALID:
01852          allbusy = 0;
01853          allfree = 0;
01854          break;
01855       default:
01856          allunavailable = 0;
01857          allbusy = 0;
01858          allfree = 0;
01859       }
01860       cur = rest;
01861    } while (cur);
01862 
01863    if (!inuse && ring)
01864       return AST_EXTENSION_RINGING;
01865    if (inuse && ring)
01866       return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING);
01867    if (inuse)
01868       return AST_EXTENSION_INUSE;
01869    if (allfree)
01870       return AST_EXTENSION_NOT_INUSE;
01871    if (allbusy)      
01872       return AST_EXTENSION_BUSY;
01873    if (allunavailable)
01874       return AST_EXTENSION_UNAVAILABLE;
01875    if (busy) 
01876       return AST_EXTENSION_INUSE;
01877    
01878    return AST_EXTENSION_NOT_INUSE;
01879 }

const char* ast_extension_state2str ( int  extension_state  ) 

ast_extension_state2str: Return extension_state as string

Return string of the state of an extension

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

Definition at line 1882 of file pbx.c.

References extension_states, and cfextension_states::text.

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

01883 {
01884    int i;
01885 
01886    for (i = 0; (i < (sizeof(extension_states) / sizeof(extension_states[0]))); i++) {
01887       if (extension_states[i].extension_state == extension_state) {
01888          return extension_states[i].text;
01889       }
01890    }
01891    return "Unknown"; 
01892 }

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

ast_extension_state_add: Add watcher for extension states

Registers a state change callback

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

References ast_hint_extension(), ast_mutex_lock(), ast_mutex_unlock(), ast_state_cb::callback, ast_hint::callbacks, ast_state_cb::data, ast_hint::exten, ast_state_cb::id, list, malloc, ast_hint::next, and ast_state_cb::next.

Referenced by handle_request_subscribe(), and init_manager().

01951 {
01952    struct ast_hint *list;
01953    struct ast_state_cb *cblist;
01954    struct ast_exten *e;
01955 
01956    /* If there's no context and extension:  add callback to statecbs list */
01957    if (!context && !exten) {
01958       ast_mutex_lock(&hintlock);
01959 
01960       cblist = statecbs;
01961       while (cblist) {
01962          if (cblist->callback == callback) {
01963             cblist->data = data;
01964             ast_mutex_unlock(&hintlock);
01965             return 0;
01966          }
01967          cblist = cblist->next;
01968       }
01969    
01970       /* Now insert the callback */
01971       cblist = malloc(sizeof(struct ast_state_cb));
01972       if (!cblist) {
01973          ast_mutex_unlock(&hintlock);
01974          return -1;
01975       }
01976       memset(cblist, 0, sizeof(struct ast_state_cb));
01977       cblist->id = 0;
01978       cblist->callback = callback;
01979       cblist->data = data;
01980    
01981       cblist->next = statecbs;
01982       statecbs = cblist;
01983 
01984       ast_mutex_unlock(&hintlock);
01985       return 0;
01986    }
01987 
01988    if (!context || !exten)
01989       return -1;
01990 
01991    /* This callback type is for only one hint, so get the hint */
01992    e = ast_hint_extension(NULL, context, exten);    
01993    if (!e) {
01994       return -1;
01995    }
01996 
01997    /* Find the hint in the list of hints */
01998    ast_mutex_lock(&hintlock);
01999    list = hints;        
02000 
02001    while (list) {
02002       if (list->exten == e)
02003          break;       
02004       list = list->next;    
02005    }
02006 
02007    if (!list) {
02008       /* We have no hint, sorry */
02009       ast_mutex_unlock(&hintlock);
02010       return -1;
02011    }
02012 
02013    /* Now insert the callback in the callback list  */
02014    cblist = malloc(sizeof(struct ast_state_cb));
02015    if (!cblist) {
02016       ast_mutex_unlock(&hintlock);
02017       return -1;
02018    }
02019    memset(cblist, 0, sizeof(struct ast_state_cb));
02020    cblist->id = stateid++;    /* Unique ID for this callback */
02021    cblist->callback = callback;  /* Pointer to callback routine */
02022    cblist->data = data;    /* Data for the callback */
02023 
02024    cblist->next = list->callbacks;
02025    list->callbacks = cblist;
02026 
02027    ast_mutex_unlock(&hintlock);
02028    return cblist->id;
02029 }

int ast_extension_state_del ( int  id,
ast_state_cb_type  callback 
)

ast_extension_state_del: Remove a watcher from the callback list

Deletes a registered state change callback by ID

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

References ast_mutex_lock(), ast_mutex_unlock(), ast_state_cb::callback, ast_hint::callbacks, free, ast_state_cb::id, list, ast_hint::next, and ast_state_cb::next.

Referenced by __sip_destroy(), and handle_request_subscribe().

02033 {
02034    struct ast_hint *list;
02035    struct ast_state_cb *cblist, *cbprev;
02036 
02037    if (!id && !callback)
02038       return -1;
02039 
02040    ast_mutex_lock(&hintlock);
02041 
02042    /* id is zero is a callback without extension */
02043    if (!id) {
02044       cbprev = NULL;
02045       cblist = statecbs;
02046       while (cblist) {
02047          if (cblist->callback == callback) {
02048             if (!cbprev)
02049                   statecbs = cblist->next;
02050             else
02051                   cbprev->next = cblist->next;
02052 
02053             free(cblist);
02054 
02055                ast_mutex_unlock(&hintlock);
02056             return 0;
02057             }
02058             cbprev = cblist;
02059             cblist = cblist->next;
02060       }
02061 
02062       ast_mutex_unlock(&hintlock);
02063       return -1;
02064    }
02065 
02066    /* id greater than zero is a callback with extension */
02067    /* Find the callback based on ID */
02068    list = hints;
02069    while (list) {
02070       cblist = list->callbacks;
02071       cbprev = NULL;
02072       while (cblist) {
02073             if (cblist->id==id) {
02074             if (!cbprev)
02075                   list->callbacks = cblist->next;     
02076             else
02077                   cbprev->next = cblist->next;
02078       
02079             free(cblist);
02080       
02081             ast_mutex_unlock(&hintlock);
02082             return 0;      
02083             }     
02084             cbprev = cblist;           
02085             cblist = cblist->next;
02086       }
02087       list = list->next;
02088    }
02089 
02090    ast_mutex_unlock(&hintlock);
02091    return -1;
02092 }

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

If an extension exists, return non-zero

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

References HELPER_FINDLABEL, and pbx_extension_helper().

Referenced by ast_parseable_goto(), and handle_setpriority().

02229 {
02230    return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, HELPER_FINDLABEL);
02231 }

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

Definition at line 2233 of file pbx.c.

References HELPER_FINDLABEL, and pbx_extension_helper().

Referenced by pbx_load_module().

02234 {
02235    return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, HELPER_FINDLABEL);
02236 }

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

executes a read operation on a function

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

01372 {
01373    char *args = NULL, *function, *p;
01374    char *ret = "0";
01375    struct ast_custom_function *acfptr;
01376 
01377    function = ast_strdupa(in);
01378    if (!function) {
01379       ast_log(LOG_ERROR, "Out of memory\n");
01380       return ret;
01381    }
01382    if ((args = strchr(function, '('))) {
01383       *args = '\0';
01384       args++;
01385       if ((p = strrchr(args, ')'))) {
01386          *p = '\0';
01387       } else {
01388          ast_log(LOG_WARNING, "Can't find trailing parenthesis?\n");
01389       }
01390    } else {
01391       ast_log(LOG_WARNING, "Function doesn't contain parentheses.  Assuming null argument.\n");
01392    }
01393 
01394    if ((acfptr = ast_custom_function_find(function))) {
01395       /* run the custom function */
01396       if (acfptr->read) {
01397          return acfptr->read(chan, function, args, workspace, len);
01398       } else {
01399          ast_log(LOG_ERROR, "Function %s cannot be read\n", function);
01400       }
01401    } else {
01402       ast_log(LOG_ERROR, "Function %s not registered\n", function);
01403    }
01404    return ret;
01405 }

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

executes a write operation on a function

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

01408 {
01409    char *args = NULL, *function, *p;
01410    struct ast_custom_function *acfptr;
01411 
01412    function = ast_strdupa(in);
01413    if (!function) {
01414       ast_log(LOG_ERROR, "Out of memory\n");
01415       return;
01416    }
01417    if ((args = strchr(function, '('))) {
01418       *args = '\0';
01419       args++;
01420       if ((p = strrchr(args, ')'))) {
01421          *p = '\0';
01422       } else {
01423          ast_log(LOG_WARNING, "Can't find trailing parenthesis?\n");
01424       }
01425    } else {
01426       ast_log(LOG_WARNING, "Function doesn't contain parentheses.  Assuming null argument.\n");
01427    }
01428 
01429    if ((acfptr = ast_custom_function_find(function))) {
01430       /* run the custom function */
01431       if (acfptr->write) {
01432          acfptr->write(chan, function, args, value);
01433       } else {
01434          ast_log(LOG_ERROR, "Function %s is read-only, it cannot be written to\n", function);
01435       }
01436    } else {
01437       ast_log(LOG_ERROR, "Function %s not registered\n", function);
01438    }
01439 }

const char* ast_get_context_name ( struct ast_context con  ) 

const char* ast_get_context_registrar ( struct ast_context c  ) 

Definition at line 6352 of file pbx.c.

References ast_context::registrar.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06353 {
06354    return c ? c->registrar : NULL;
06355 }

const char* ast_get_extension_app ( struct ast_exten e  ) 

void* ast_get_extension_app_data ( struct ast_exten e  ) 

Definition at line 6387 of file pbx.c.

References ast_exten::data.

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

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

const char* ast_get_extension_cidmatch ( struct ast_exten e  ) 

Definition at line 6377 of file pbx.c.

References ast_exten::cidmatch.

Referenced by find_matching_priority(), and handle_save_dialplan().

06378 {
06379    return e ? e->cidmatch : NULL;
06380 }

const char* ast_get_extension_label ( struct ast_exten exten  ) 

Definition at line 6329 of file pbx.c.

References ast_exten::label.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

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

int ast_get_extension_matchcid ( struct ast_exten e  ) 

Definition at line 6372 of file pbx.c.

References ast_exten::matchcid.

Referenced by find_matching_priority(), and handle_save_dialplan().

06373 {
06374    return e ? e->matchcid : 0;
06375 }

const char* ast_get_extension_name ( struct ast_exten exten  ) 

Definition at line 6324 of file pbx.c.

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

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

int ast_get_extension_priority ( struct ast_exten exten  ) 

Definition at line 6344 of file pbx.c.

References ast_exten::priority.

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

06345 {
06346    return exten ? exten->priority : -1;
06347 }

const char* ast_get_extension_registrar ( struct ast_exten e  ) 

Definition at line 6357 of file pbx.c.

References ast_exten::registrar.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

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

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

If an extension exists, return non-zero

Parameters:
hint buffer for hint
maxlen size of hint buffer
name buffer for name portion of hint
maxnamelen size of name buffer
c this is not important
context which context to look in
exten which extension to search for 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 2204 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().

02205 {
02206    struct ast_exten *e;
02207    void *tmp;
02208 
02209    e = ast_hint_extension(c, context, exten);
02210    if (e) {
02211       if (hint) 
02212           ast_copy_string(hint, ast_get_extension_app(e), hintsize);
02213       if (name) {
02214          tmp = ast_get_extension_app_data(e);
02215          if (tmp)
02216             ast_copy_string(name, (char *) tmp, namesize);
02217       }
02218        return -1;
02219    }
02220    return 0;   
02221 }

const char* ast_get_ignorepat_name ( struct ast_ignorepat ip  ) 

Definition at line 6339 of file pbx.c.

References ast_ignorepat::pattern.

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

06340 {
06341    return ip ? ip->pattern : NULL;
06342 }

const char* ast_get_ignorepat_registrar ( struct ast_ignorepat ip  ) 

Definition at line 6367 of file pbx.c.

References ast_ignorepat::registrar.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

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

const char* ast_get_include_name ( struct ast_include inc  ) 

Definition at line 6334 of file pbx.c.

References ast_include::name.

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

06335 {
06336    return inc ? inc->name : NULL;
06337 }

const char* ast_get_include_registrar ( struct ast_include i  ) 

Definition at line 6362 of file pbx.c.

References ast_include::registrar.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

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

const char* ast_get_switch_data ( struct ast_sw sw  ) 

Definition at line 6397 of file pbx.c.

References ast_sw::data.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

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

const char* ast_get_switch_name ( struct ast_sw sw  ) 

Definition at line 6392 of file pbx.c.

References ast_sw::name.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06393 {
06394    return sw ? sw->name : NULL;
06395 }

const char* ast_get_switch_registrar ( struct ast_sw sw  ) 

Definition at line 6402 of file pbx.c.

References ast_sw::registrar.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

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

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

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

ast_hint_extension: Find hint for given extension in context

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

01789 {
01790    struct ast_exten *e;
01791    struct ast_switch *sw;
01792    char *data;
01793    const char *foundcontext = NULL;
01794    int status = 0;
01795    char *incstack[AST_PBX_MAX_STACK];
01796    int stacklen = 0;
01797 
01798    if (ast_mutex_lock(&conlock)) {
01799       ast_log(LOG_WARNING, "Unable to obtain lock\n");
01800       return NULL;
01801    }
01802    e = pbx_find_extension(c, NULL, context, exten, PRIORITY_HINT, NULL, "", HELPER_EXISTS, incstack, &stacklen, &status, &sw, &data, &foundcontext);
01803    ast_mutex_unlock(&conlock);   
01804    return e;
01805 }

void ast_hint_state_changed ( const char *  device  ) 

Definition at line 1906 of file pbx.c.

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

Referenced by do_state_change().

01907 {
01908    struct ast_hint *hint;
01909    struct ast_state_cb *cblist;
01910    char buf[AST_MAX_EXTENSION];
01911    char *parse;
01912    char *cur;
01913    int state;
01914 
01915    ast_mutex_lock(&hintlock);
01916 
01917    for (hint = hints; hint; hint = hint->next) {
01918       ast_copy_string(buf, ast_get_extension_app(hint->exten), sizeof(buf));
01919       parse = buf;
01920       for (cur = strsep(&parse, "&"); cur; cur = strsep(&parse, "&")) {
01921          if (strcasecmp(cur, device))
01922             continue;
01923 
01924          /* Get device state for this hint */
01925          state = ast_extension_state2(hint->exten);
01926          
01927          if ((state == -1) || (state == hint->laststate))
01928             continue;
01929 
01930          /* Device state changed since last check - notify the watchers */
01931          
01932          /* For general callbacks */
01933          for (cblist = statecbs; cblist; cblist = cblist->next)
01934             cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data);
01935          
01936          /* For extension callbacks */
01937          for (cblist = hint->callbacks; cblist; cblist = cblist->next)
01938             cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data);
01939          
01940          hint->laststate = state;
01941          break;
01942       }
01943    }
01944 
01945    ast_mutex_unlock(&hintlock);
01946 }

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

Checks to see if a number should be ignored

Parameters:
context context to search within
pattern to check whether it should be ignored or not Check if a number should be ignored with respect to dialtone cancellation. Returns 0 if the pattern should not be ignored, or non-zero if the pattern should be ignored

Definition at line 4505 of file pbx.c.

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

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

04506 {
04507    struct ast_context *con;
04508    struct ast_ignorepat *pat;
04509 
04510    con = ast_context_find(context);
04511    if (con) {
04512       pat = con->ignorepats;
04513       while (pat) {
04514          if (ast_extension_match(pat->pattern, pattern))
04515             return 1;
04516          pat = pat->next;
04517       }
04518    } 
04519    return 0;
04520 }

AST_LIST_HEAD ( store_hints  ,
store_hint   
)

int ast_lock_context ( struct ast_context con  ) 

Locks a given context

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

Definition at line 6306 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(), macro_exec(), and show_dialplan_helper().

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

int ast_lock_contexts ( void   ) 

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

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

Parameters:
c not really important
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 2243 of file pbx.c.

References HELPER_MATCHMORE, and pbx_extension_helper().

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

02244 {
02245    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, HELPER_MATCHMORE);
02246 }

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

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

Parameters:
extcontexts pointer to the ast_context structure pointer
registrar of the context; if it's set the routine will delete all contexts that belong to that registrar; if NULL only the contexts that are specified in extcontexts

Definition at line 3720 of file pbx.c.

References __ast_context_destroy(), AST_EXTENSION_REMOVED, ast_hint_extension(), AST_LIST_HEAD_INIT, AST_LIST_INSERT_HEAD, AST_LIST_REMOVE_HEAD, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_state_cb::callback, store_hint::callbacks, ast_hint::callbacks, calloc, store_hint::context, ast_state_cb::data, ast_exten::exten, ast_hint::exten, store_hint::exten, free, ast_hint::laststate, store_hint::laststate, LOG_WARNING, ast_context::name, ast_state_cb::next, ast_context::next, ast_hint::next, ast_exten::parent, and ast_context::registrar.

Referenced by pbx_load_module().

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

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

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

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

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

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

References __ast_request_and_dial(), ast_channel::_state, outgoing_helper::account, async_stat::app, app_tmp::app, async_stat::appdata, ast_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, app_tmp::chan, app_tmp::data, free, ast_channel::hangupcause, ast_channel::lock, LOG_ERROR, LOG_WARNING, malloc, ast_channel::name, option_verbose, async_stat::p, ast_channel::pbx, app_tmp::t, async_stat::timeout, outgoing_helper::vars, and VERBOSE_PREFIX_4.

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

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

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

04978 {
04979    /* allocate a channel */
04980    struct ast_channel *chan = ast_channel_alloc(0);
04981    if(!chan) {
04982       /* allocation of the channel failed, let some peeps know */
04983       ast_log(LOG_WARNING, "Unable to allocate channel structure for CDR record\n");
04984       return -1;  /* failure */
04985    }
04986 
04987    chan->cdr = ast_cdr_alloc();   /* allocate a cdr for the channel */
04988 
04989    if(!chan->cdr) {
04990       /* allocation of the cdr failed */
04991       ast_log(LOG_WARNING, "Unable to create Call Detail Record\n");
04992       ast_channel_free(chan);   /* free the channel */
04993       return -1;                /* return failure */
04994    }
04995    
04996    /* allocation of the cdr was successful */
04997    ast_cdr_init(chan->cdr, chan);  /* initilize our channel's cdr */
04998    ast_cdr_start(chan->cdr);       /* record the start and stop time */
04999    ast_cdr_end(chan->cdr);
05000    ast_cdr_failed(chan->cdr);      /* set the status to failed */
05001    ast_cdr_detach(chan->cdr);      /* post and free the record */
05002    ast_channel_free(chan);         /* free the channel */
05003    
05004    return 0;  /* success */
05005 }

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 5007 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, async_stat::context, ast_channel::context, async_stat::exten, ast_channel::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, async_stat::priority, ast_channel::priority, async_stat::timeout, and VERBOSE_PREFIX_4.

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

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

enum ast_pbx_result ast_pbx_run ( struct ast_channel c  ) 

Execute the PBX in the current thread

Parameters:
c channel to run the pbx on
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 2571 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().

02572 {
02573    enum ast_pbx_result res = AST_PBX_SUCCESS;
02574 
02575    if (increase_call_count(c))
02576       return AST_PBX_CALL_LIMIT;
02577 
02578    res = __ast_pbx_run(c);
02579    decrease_call_count();
02580 
02581    return res;
02582 }

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

Definition at line 5167 of file pbx.c.

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

05168 {
05169    struct app_tmp *tmp = data;
05170    struct ast_app *app;
05171    app = pbx_findapp(tmp->app);
05172    if (app) {
05173       if (option_verbose > 3)
05174          ast_verbose(VERBOSE_PREFIX_4 "Launching %s(%s) on %s\n", tmp->app, tmp->data, tmp->chan->name);
05175       pbx_exec(tmp->chan, app, tmp->data, 1);
05176    } else
05177       ast_log(LOG_WARNING, "No such application '%s'\n", tmp->app);
05178    ast_hangup(tmp->chan);
05179    free(tmp);
05180    return NULL;
05181 }

enum ast_pbx_result ast_pbx_start ( struct ast_channel c  ) 

Create a new thread and start the PBX (or whatever)

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

Definition at line 2545 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(), check_goto_on_transfer(), dial_exec_full(), do_parking_thread(), handle_request_invite(), local_call(), mgcp_new(), nbs_new(), oss_new(), pbx_start_chan(), phone_new(), rpt_call(), sip_new(), skinny_new(), vpb_new(), and zt_new().

02546 {
02547    pthread_t t;
02548    pthread_attr_t attr;
02549 
02550    if (!c) {
02551       ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
02552       return AST_PBX_FAILED;
02553    }
02554       
02555    if (increase_call_count(c))
02556       return AST_PBX_CALL_LIMIT;
02557 
02558    /* Start a new thread, and get something handling this channel. */
02559    pthread_attr_init(&attr);
02560    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
02561    if (ast_pthread_create(&t, &attr, pbx_thread, c)) {
02562       ast_log(LOG_WARNING, "Failed to create new channel thread\n");
02563       pthread_attr_destroy(&attr);
02564       return AST_PBX_FAILED;
02565    }
02566    pthread_attr_destroy(&attr);
02567 
02568    return AST_PBX_SUCCESS;
02569 }

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.

Add an application. The function 'execute' should return non-zero if the line needs to be hung up.

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

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

Referenced by load_module(), and load_pbx().

02889 {
02890    struct ast_app *tmp, *prev, *cur;
02891    char tmps[80];
02892    int length;
02893    length = sizeof(struct ast_app);
02894    length += strlen(app) + 1;
02895    if (ast_mutex_lock(&applock)) {
02896       ast_log(LOG_ERROR, "Unable to lock application list\n");
02897       return -1;
02898    }
02899    tmp = apps;
02900    while(tmp) {
02901       if (!strcasecmp(app, tmp->name)) {
02902          ast_log(LOG_WARNING, "Already have an application '%s'\n", app);
02903          ast_mutex_unlock(&applock);
02904          return -1;
02905       }
02906       tmp = tmp->next;
02907    }
02908    tmp = malloc(length);
02909    if (tmp) {
02910       memset(tmp, 0, length);
02911       strcpy(tmp->name, app);
02912       tmp->execute = execute;
02913       tmp->synopsis = synopsis;
02914       tmp->description = description;
02915       /* Store in alphabetical order */
02916       cur = apps;
02917       prev = NULL;
02918       while(cur) {
02919          if (strcasecmp(tmp->name, cur->name) < 0)
02920             break;
02921          prev = cur;
02922          cur = cur->next;
02923       }
02924       if (prev) {
02925          tmp->next = prev->next;
02926          prev->next = tmp;
02927       } else {
02928          tmp->next = apps;
02929          apps = tmp;
02930       }
02931    } else {
02932       ast_log(LOG_ERROR, "Out of memory\n");
02933       ast_mutex_unlock(&applock);
02934       return -1;
02935    }
02936    if (option_verbose > 1)
02937       ast_verbose( VERBOSE_PREFIX_2 "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps)));
02938    ast_mutex_unlock(&applock);
02939    return 0;
02940 }

int ast_register_switch ( struct ast_switch sw  ) 

Register an alternative switch

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

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

Referenced by load_module().

02943 {
02944    struct ast_switch *tmp, *prev=NULL;
02945    if (ast_mutex_lock(&switchlock)) {
02946       ast_log(LOG_ERROR, "Unable to lock switch lock\n");
02947       return -1;
02948    }
02949    tmp = switches;
02950    while(tmp) {
02951       if (!strcasecmp(tmp->name, sw->name))
02952          break;
02953       prev = tmp;
02954       tmp = tmp->next;
02955    }
02956    if (tmp) {  
02957       ast_mutex_unlock(&switchlock);
02958       ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name);
02959       return -1;
02960    }
02961    sw->next = NULL;
02962    if (prev) 
02963       prev->next = sw;
02964    else
02965       switches = sw;
02966    ast_mutex_unlock(&switchlock);
02967    return 0;
02968 }

static int ast_remove_hint ( struct ast_exten e  )  [static]

ast_remove_hint: Remove hint from extension

Definition at line 2159 of file pbx.c.

References AST_EXTENSION_DEACTIVATED, ast_mutex_lock(), ast_mutex_unlock(), ast_state_cb::callback, ast_hint::callbacks, ast_state_cb::data, ast_exten::exten, ast_hint::exten, free, list, ast_context::name, ast_hint::next, ast_state_cb::next, and ast_exten::parent.

Referenced by ast_context_remove_extension2(), and destroy_exten().

02160 {
02161    /* Cleanup the Notifys if hint is removed */
02162    struct ast_hint *list, *prev = NULL;
02163    struct ast_state_cb *cblist, *cbprev;
02164 
02165    if (!e) 
02166       return -1;
02167 
02168    ast_mutex_lock(&hintlock);
02169 
02170    list = hints;    
02171    while(list) {
02172       if (list->exten==e) {
02173          cbprev = NULL;
02174          cblist = list->callbacks;
02175          while (cblist) {
02176             /* Notify with -1 and remove all callbacks */
02177             cbprev = cblist;      
02178             cblist = cblist->next;
02179             cbprev->callback(list->exten->parent->name, list->exten->exten, AST_EXTENSION_DEACTIVATED, cbprev->data);
02180             free(cbprev);
02181             }
02182             list->callbacks = NULL;
02183 
02184             if (!prev)
02185             hints = list->next;
02186             else
02187             prev->next = list->next;
02188             free(list);
02189        
02190          ast_mutex_unlock(&hintlock);
02191          return 0;
02192       } else {
02193          prev = list;
02194          list = list->next;    
02195       }
02196    }
02197 
02198    ast_mutex_unlock(&hintlock);
02199    return -1;
02200 }

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

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

Parameters:
c not important
context which context to generate the extension within
exten new extension to add
priority priority of new extension
callerid callerid of extension This adds a new extension to the asterisk extension list. It returns 0 on success, -1 on failure.

Definition at line 2248 of file pbx.c.

References HELPER_SPAWN, and pbx_extension_helper().

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

02249 {
02250    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, HELPER_SPAWN);
02251 }

int ast_unlock_context ( struct ast_context con  ) 

Unlocks the given context

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

Definition at line 6311 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(), handle_save_dialplan(), macro_exec(), and show_dialplan_helper().

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

int ast_unlock_contexts ( void   ) 

int ast_unregister_application ( const char *  app  ) 

Remove an application

Parameters:
app name of the application (does not have to be the same string as the one that was registered) This unregisters an application from asterisk's internal registration mechanisms. It returns 0 on success, and -1 on failure.

Definition at line 3635 of file pbx.c.

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

03636 {
03637    struct ast_app *tmp, *tmpl = NULL;
03638    if (ast_mutex_lock(&applock)) {
03639       ast_log(LOG_ERROR, "Unable to lock application list\n");
03640       return -1;
03641    }
03642    tmp = apps;
03643    while(tmp) {
03644       if (!strcasecmp(app, tmp->name)) {
03645          if (tmpl)
03646             tmpl->next = tmp->next;
03647          else
03648             apps = tmp->next;
03649          if (option_verbose > 1)
03650             ast_verbose( VERBOSE_PREFIX_2 "Unregistered application '%s'\n", tmp->name);
03651          free(tmp);
03652          ast_mutex_unlock(&applock);
03653          return 0;
03654       }
03655       tmpl = tmp;
03656       tmp = tmp->next;
03657    }
03658    ast_mutex_unlock(&applock);
03659    return -1;
03660 }

void ast_unregister_switch ( struct ast_switch sw  ) 

Unregister an alternative switch

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

Definition at line 2970 of file pbx.c.

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

Referenced by __unload_module(), and unload_module().

02971 {
02972    struct ast_switch *tmp, *prev=NULL;
02973    if (ast_mutex_lock(&switchlock)) {
02974       ast_log(LOG_ERROR, "Unable to lock switch lock\n");
02975       return;
02976    }
02977    tmp = switches;
02978    while(tmp) {
02979       if (tmp == sw) {
02980          if (prev)
02981             prev->next = tmp->next;
02982          else
02983             switches = tmp->next;
02984          tmp->next = NULL;
02985          break;         
02986       }
02987       prev = tmp;
02988       tmp = tmp->next;
02989    }
02990    ast_mutex_unlock(&switchlock);
02991 }

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

Definition at line 6418 of file pbx.c.

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

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

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

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

Definition at line 6454 of file pbx.c.

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

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

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

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

Definition at line 6445 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(), find_matching_priority(), handle_save_dialplan(), and show_dialplan_helper().

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

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

Definition at line 6427 of file pbx.c.

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

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06429 {
06430    if (!sw)
06431       return con ? con->alts : NULL;
06432    else
06433       return sw->next;
06434 }

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

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

Definition at line 6436 of file pbx.c.

References ast_exten::peer.

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

06438 {
06439    if (!priority)
06440       return exten;
06441    else
06442       return priority->peer;
06443 }

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

Definition at line 4913 of file pbx.c.

References ast_channel::_state, async_stat::app, async_stat::appdata, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_FRAME_CONTROL, ast_frfree(), ast_hangup(), ast_log(), ast_pbx_run(), ast_read(), AST_STATE_UP, ast_strlen_zero(), ast_verbose(), ast_waitfor(), async_stat::chan, ast_channel::context, async_stat::context, ast_channel::exten, async_stat::exten, 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().

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

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

Definition at line 3041 of file pbx.c.

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

03043 {
03044    struct ast_app *a;
03045    int which = 0;
03046 
03047    /* try to lock applications list ... */
03048    if (ast_mutex_lock(&applock)) {
03049       ast_log(LOG_ERROR, "Unable to lock application list\n");
03050       return NULL;
03051    }
03052 
03053    /* ... walk all applications ... */
03054    a = apps; 
03055    while (a) {
03056       /* ... check if word matches this application ... */
03057       if (!strncasecmp(word, a->name, strlen(word))) {
03058          /* ... if this is right app serve it ... */
03059          if (++which > state) {
03060             char *ret = strdup(a->name);
03061             ast_mutex_unlock(&applock);
03062             return ret;
03063          }
03064       }
03065       a = a->next; 
03066    }
03067 
03068    /* no application match */
03069    ast_mutex_unlock(&applock);
03070    return NULL; 
03071 }

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

Definition at line 3288 of file pbx.c.

References ast_strlen_zero(), and strdup.

03289 {
03290    if (pos == 2) {
03291       if (ast_strlen_zero(word)) {
03292          switch (state) {
03293          case 0:
03294             return strdup("like");
03295          case 1:
03296             return strdup("describing");
03297          default:
03298             return NULL;
03299          }
03300       } else if (! strncasecmp(word, "like", strlen(word))) {
03301          if (state == 0) {
03302             return strdup("like");
03303          } else {
03304             return NULL;
03305          }
03306       } else if (! strncasecmp(word, "describing", strlen(word))) {
03307          if (state == 0) {
03308             return strdup("describing");
03309          } else {
03310             return NULL;
03311          }
03312       }
03313    }
03314    return NULL;
03315 }

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

Definition at line 3320 of file pbx.c.

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

03322 {
03323    struct ast_context *c;
03324    int which = 0;
03325 
03326    /* we are do completion of [exten@]context on second position only */
03327    if (pos != 2) return NULL;
03328 
03329    /* try to lock contexts list ... */
03330    if (ast_lock_contexts()) {
03331       ast_log(LOG_ERROR, "Unable to lock context list\n");
03332       return NULL;
03333    }
03334 
03335    /* ... walk through all contexts ... */
03336    c = ast_walk_contexts(NULL);
03337    while(c) {
03338       /* ... word matches context name? yes? ... */
03339       if (!strncasecmp(word, ast_get_context_name(c), strlen(word))) {
03340          /* ... for serve? ... */
03341          if (++which > state) {
03342             /* ... yes, serve this context name ... */
03343             char *ret = strdup(ast_get_context_name(c));
03344             ast_unlock_contexts();
03345             return ret;
03346          }
03347       }
03348       c = ast_walk_contexts(c);
03349    }
03350 
03351    /* ... unlock and return */
03352    ast_unlock_contexts();
03353    return NULL;
03354 }

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

Definition at line 1260 of file pbx.c.

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

01261 {
01262    struct ast_custom_function *acf;
01263    int which = 0;
01264 
01265    /* try to lock functions list ... */
01266    if (ast_mutex_lock(&acflock)) {
01267       ast_log(LOG_ERROR, "Unable to lock function list\n");
01268       return NULL;
01269    }
01270 
01271    acf = acf_root;
01272    while (acf) {
01273       if (!strncasecmp(word, acf->name, strlen(word))) {
01274          if (++which > state) {
01275             char *ret = strdup(acf->name);
01276             ast_mutex_unlock(&acflock);
01277             return ret;
01278          }
01279       }
01280       acf = acf->next; 
01281    }
01282 
01283    ast_mutex_unlock(&acflock);
01284    return NULL; 
01285 }

static void decrease_call_count ( void   )  [static]

Definition at line 2517 of file pbx.c.

References ast_mutex_lock(), and ast_mutex_unlock().

Referenced by ast_pbx_run(), and pbx_thread().

02518 {
02519    ast_mutex_lock(&maxcalllock);
02520    if (countcalls > 0)
02521       countcalls--;
02522    ast_mutex_unlock(&maxcalllock);
02523 }

static void destroy_exten ( struct ast_exten e  )  [static]

Definition at line 5331 of file pbx.c.

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

Referenced by __ast_context_destroy().

05332 {
05333    if (e->priority == PRIORITY_HINT)
05334       ast_remove_hint(e);
05335 
05336    if (e->datad)
05337       e->datad(e->data);
05338    free(e);
05339 }

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

Definition at line 4634 of file pbx.c.

Referenced by ast_add_extension2().

04635 {
04636    int count=0;
04637 
04638    while(*src && (count < len - 1)) {
04639       switch(*src) {
04640       case ' ':
04641          /* otherwise exten => [a-b],1,... doesn't work */
04642          /*    case '-': */
04643          /* Ignore */
04644          break;
04645       default:
04646          *dst = *src;
04647          dst++;
04648       }
04649       src++;
04650       count++;
04651    }
04652    *dst = '\0';
04653 
04654    return count;
04655 }

static unsigned int get_day ( char *  day  )  [static]

Definition at line 4000 of file pbx.c.

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

Referenced by ast_build_timing().

04001 {
04002    char *c;
04003    /* The following line is coincidence, really! */
04004    int s, e, x;
04005    unsigned int mask;
04006 
04007    /* Check for all days */
04008    if (ast_strlen_zero(day) || !strcmp(day, "*")) {
04009       mask = (1 << 30)  + ((1 << 30) - 1);
04010       return mask;
04011    }
04012    /* Get start and ending days */
04013    c = strchr(day, '-');
04014    if (c) {
04015       *c = '\0';
04016       c++;
04017    }
04018    /* Find the start */
04019    if (sscanf(day, "%2d", &s) != 1) {
04020       ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", day);
04021       return 0;
04022    }
04023    if ((s < 1) || (s > 31)) {
04024       ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", day);
04025       return 0;
04026    }
04027    s--;
04028    if (c) {
04029       if (sscanf(c, "%2d", &e) != 1) {
04030          ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", c);
04031          return 0;
04032       }
04033       if ((e < 1) || (e > 31)) {
04034          ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", c);
04035          return 0;
04036       }
04037       e--;
04038    } else
04039       e = s;
04040    mask = 0;
04041    for (x=s; x!=e; x = (x + 1) % 31) {
04042       mask |= (1 << x);
04043    }
04044    mask |= (1 << x);
04045    return mask;
04046 }

static unsigned int get_dow ( char *  dow  )  [static]

get_dow: Get day of week

Definition at line 3958 of file pbx.c.

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

Referenced by ast_build_timing().

03959 {
03960    char *c;
03961    /* The following line is coincidence, really! */
03962    int s, e, x;
03963    unsigned int mask;
03964 
03965    /* Check for all days */
03966    if (ast_strlen_zero(dow) || !strcmp(dow, "*"))
03967       return (1 << 7) - 1;
03968    /* Get start and ending days */
03969    c = strchr(dow, '-');
03970    if (c) {
03971       *c = '\0';
03972       c++;
03973    } else
03974       c = NULL;
03975    /* Find the start */
03976    s = 0;
03977    while((s < 7) && strcasecmp(dow, days[s])) s++;
03978    if (s >= 7) {
03979       ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", dow);
03980       return 0;
03981    }
03982    if (c) {
03983       e = 0;
03984       while((e < 7) && strcasecmp(c, days[e])) e++;
03985       if (e >= 7) {
03986          ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", c);
03987          return 0;
03988       }
03989    } else
03990       e = s;
03991    mask = 0;
03992    for (x=s; x != e; x = (x + 1) % 7) {
03993       mask |= (1 << x);
03994    }
03995    /* One last one */
03996    mask |= (1 << x);
03997    return mask;
03998 }

static unsigned int get_month ( char *  mon  )  [static]

Definition at line 4064 of file pbx.c.

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

Referenced by ast_build_timing().

04065 {
04066    char *c;
04067    /* The following line is coincidence, really! */
04068    int s, e, x;
04069    unsigned int mask;
04070 
04071    /* Check for all days */
04072    if (ast_strlen_zero(mon) || !strcmp(mon, "*")) 
04073       return (1 << 12) - 1;
04074    /* Get start and ending days */
04075    c = strchr(mon, '-');
04076    if (c) {
04077       *c = '\0';
04078       c++;
04079    }
04080    /* Find the start */
04081    s = 0;
04082    while((s < 12) && strcasecmp(mon, months[s])) s++;
04083    if (s >= 12) {
04084       ast_log(LOG_WARNING, "Invalid month '%s', assuming none\n", mon);
04085       return 0;
04086    }
04087    if (c) {
04088       e = 0;
04089       while((e < 12) && strcasecmp(c, months[e])) e++;
04090       if (e >= 12) {
04091          ast_log(LOG_WARNING, "Invalid month '%s', assuming none\n", c);
04092          return 0;
04093       }
04094    } else
04095       e = s;
04096    mask = 0;
04097    for (x=s; x!=e; x = (x + 1) % 12) {
04098       mask |= (1 << x);
04099    }
04100    /* One last one */
04101    mask |= (1 << x);
04102    return mask;
04103 }

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

Definition at line 3862 of file pbx.c.

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

Referenced by ast_build_timing().

03863 {
03864    char *e;
03865    int x;
03866    int s1, s2;
03867    int e1, e2;
03868    /* int cth, ctm; */
03869 
03870    /* start disabling all times, fill the fields with 0's, as they may contain garbage */
03871    memset(i->minmask, 0, sizeof(i->minmask));
03872    
03873    /* Star is all times */
03874    if (ast_strlen_zero(times) || !strcmp(times, "*")) {
03875       for (x=0; x<24; x++)
03876          i->minmask[x] = (1 << 30) - 1;
03877       return;
03878    }
03879    /* Otherwise expect a range */
03880    e = strchr(times, '-');
03881    if (!e) {
03882       ast_log(LOG_WARNING, "Time range is not valid. Assuming no restrictions based on time.\n");
03883       return;
03884    }
03885    *e = '\0';
03886    e++;
03887    while(*e && !isdigit(*e)) 
03888       e++;
03889    if (!*e) {
03890       ast_log(LOG_WARNING, "Invalid time range.  Assuming no restrictions based on time.\n");
03891       return;
03892    }
03893    if (sscanf(times, "%2d:%2d", &s1, &s2) != 2) {
03894       ast_log(LOG_WARNING, "%s isn't a time.  Assuming no restrictions based on time.\n", times);
03895       return;
03896    }
03897    if (sscanf(e, "%2d:%2d", &e1, &e2) != 2) {
03898       ast_log(LOG_WARNING, "%s isn't a time.  Assuming no restrictions based on time.\n", e);
03899       return;
03900    }
03901 
03902 #if 1
03903    s1 = s1 * 30 + s2/2;
03904    if ((s1 < 0) || (s1 >= 24*30)) {
03905       ast_log(LOG_WARNING, "%s isn't a valid start time. Assuming no time.\n", times);
03906       return;
03907    }
03908    e1 = e1 * 30 + e2/2;
03909    if ((e1 < 0) || (e1 >= 24*30)) {
03910       ast_log(LOG_WARNING, "%s isn't a valid end time. Assuming no time.\n", e);
03911       return;
03912    }
03913    /* Go through the time and enable each appropriate bit */
03914    for (x=s1;x != e1;x = (x + 1) % (24 * 30)) {
03915       i->minmask[x/30] |= (1 << (x % 30));
03916    }
03917    /* Do the last one */
03918    i->minmask[x/30] |= (1 << (x % 30));
03919 #else
03920    for (cth=0; cth<24; cth++) {
03921       /* Initialize masks to blank */
03922       i->minmask[cth] = 0;
03923       for (ctm=0; ctm<30; ctm++) {
03924          if (
03925          /* First hour with more than one hour */
03926                (((cth == s1) && (ctm >= s2)) &&
03927                 ((cth < e1)))
03928          /* Only one hour */
03929          ||    (((cth == s1) && (ctm >= s2)) &&
03930                 ((cth == e1) && (ctm <= e2)))
03931          /* In between first and last hours (more than 2 hours) */
03932          ||    ((cth > s1) &&
03933                 (cth < e1))
03934          /* Last hour with more than one hour */
03935          ||    ((cth > s1) &&
03936                 ((cth == e1) && (ctm <= e2)))
03937          )
03938             i->minmask[cth] |= (1 << (ctm / 2));
03939       }
03940    }
03941 #endif
03942    /* All done */
03943    return;
03944 }

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

Definition at line 3073 of file pbx.c.

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

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

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

Definition at line 3211 of file pbx.c.

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

03212 {
03213    struct ast_app *a;
03214    int like=0, describing=0;
03215    int total_match = 0;    /* Number of matches in like clause */
03216    int total_apps = 0;  /* Number of apps registered */
03217    
03218    /* try to lock applications list ... */
03219    if (ast_mutex_lock(&applock)) {
03220       ast_log(LOG_ERROR, "Unable to lock application list\n");
03221       return -1;
03222    }
03223 
03224    /* ... have we got at least one application (first)? no? */
03225    if (!apps) {
03226       ast_cli(fd, "There are no registered applications\n");
03227       ast_mutex_unlock(&applock);
03228       return -1;
03229    }
03230 
03231    /* show applications like <keyword> */
03232    if ((argc == 4) && (!strcmp(argv[2], "like"))) {
03233       like = 1;
03234    } else if ((argc > 3) && (!strcmp(argv[2], "describing"))) {
03235       describing = 1;
03236    }
03237 
03238    /* show applications describing <keyword1> [<keyword2>] [...] */
03239    if ((!like) && (!describing)) {
03240       ast_cli(fd, "    -= Registered Asterisk Applications =-\n");
03241    } else {
03242       ast_cli(fd, "    -= Matching Asterisk Applications =-\n");
03243    }
03244 
03245    /* ... go through all applications ... */
03246    for (a = apps; a; a = a->next) {
03247       /* ... show informations about applications ... */
03248       int printapp=0;
03249       total_apps++;
03250       if (like) {
03251          if (strcasestr(a->name, argv[3])) {
03252             printapp = 1;
03253             total_match++;
03254          }
03255       } else if (describing) {
03256          if (a->description) {
03257             /* Match all words on command line */
03258             int i;
03259             printapp = 1;
03260             for (i=3; i<argc; i++) {
03261                if (!strcasestr(a->description, argv[i])) {
03262                   printapp = 0;
03263                } else {
03264                   total_match++;
03265                }
03266             }
03267          }
03268       } else {
03269          printapp = 1;
03270       }
03271 
03272       if (printapp) {
03273          ast_cli(fd,"  %20s: %s\n", a->name, a->synopsis ? a->synopsis : "<Synopsis not available>");
03274       }
03275    }
03276    if ((!like) && (!describing)) {
03277       ast_cli(fd, "    -= %d Applications Registered =-\n",total_apps);
03278    } else {
03279       ast_cli(fd, "    -= %d Applications Matching =-\n",total_match);
03280    }
03281    
03282    /* ... unlock and return */
03283    ast_mutex_unlock(&applock);
03284 
03285    return RESULT_SUCCESS;
03286 }

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

Definition at line 3551 of file pbx.c.

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

03552 {
03553    char *exten = NULL, *context = NULL;
03554    /* Variables used for different counters */
03555    struct dialplan_counters counters;
03556    char *incstack[AST_PBX_MAX_STACK];
03557    memset(&counters, 0, sizeof(counters));
03558 
03559    if (argc != 2 && argc != 3) 
03560       return RESULT_SHOWUSAGE;
03561 
03562    /* we obtain [exten@]context? if yes, split them ... */
03563    if (argc == 3) {
03564       char *splitter = ast_strdupa(argv[2]);
03565       /* is there a '@' character? */
03566       if (splitter && strchr(argv[2], '@')) {
03567          /* yes, split into exten & context ... */
03568          exten   = strsep(&splitter, "@");
03569          context = splitter;
03570 
03571          /* check for length and change to NULL if ast_strlen_zero() */
03572          if (ast_strlen_zero(exten))
03573             exten = NULL;
03574          if (ast_strlen_zero(context))
03575             context = NULL;
03576          show_dialplan_helper(fd, context, exten, &counters, NULL, 0, incstack);
03577       } else {
03578          /* no '@' char, only context given */
03579          context = argv[2];
03580          if (ast_strlen_zero(context))
03581             context = NULL;
03582          show_dialplan_helper(fd, context, exten, &counters, NULL, 0, incstack);
03583       }
03584    } else {
03585       /* Show complete dial plan */
03586       show_dialplan_helper(fd, NULL, NULL, &counters, NULL, 0, incstack);
03587    }
03588 
03589    /* check for input failure and throw some error messages */
03590    if (context && !counters.context_existence) {
03591       ast_cli(fd, "There is no existence of '%s' context\n", context);
03592       return RESULT_FAILURE;
03593    }
03594 
03595    if (exten && !counters.extension_existence) {
03596       if (context)
03597          ast_cli(fd, "There is no existence of %s@%s extension\n",
03598             exten, context);
03599       else
03600          ast_cli(fd,
03601             "There is no existence of '%s' extension in all contexts\n",
03602             exten);
03603       return RESULT_FAILURE;
03604    }
03605 
03606    ast_cli(fd,"-= %d %s (%d %s) in %d %s. =-\n",
03607             counters.total_exten, counters.total_exten == 1 ? "extension" : "extensions",
03608             counters.total_prio, counters.total_prio == 1 ? "priority" : "priorities",
03609             counters.total_context, counters.total_context == 1 ? "context" : "contexts");
03610 
03611    /* everything ok */
03612    return RESULT_SUCCESS;
03613 }

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

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

01206 {
01207    struct ast_custom_function *acf;
01208    /* Maximum number of characters added by terminal coloring is 22 */
01209    char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40];
01210    char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL;
01211    char stxtitle[40], *syntax = NULL;
01212    int synopsis_size, description_size, syntax_size;
01213 
01214    if (argc < 3) return RESULT_SHOWUSAGE;
01215 
01216    if (!(acf = ast_custom_function_find(argv[2]))) {
01217       ast_cli(fd, "No function by that name registered.\n");
01218       return RESULT_FAILURE;
01219 
01220    }
01221 
01222    if (acf->synopsis)
01223       synopsis_size = strlen(acf->synopsis) + 23;
01224    else
01225       synopsis_size = strlen("Not available") + 23;
01226    synopsis = alloca(synopsis_size);
01227    
01228    if (acf->desc)
01229       description_size = strlen(acf->desc) + 23;
01230    else
01231       description_size = strlen("Not available") + 23;
01232    description = alloca(description_size);
01233 
01234    if (acf->syntax)
01235       syntax_size = strlen(acf->syntax) + 23;
01236    else
01237       syntax_size = strlen("Not available") + 23;
01238    syntax = alloca(syntax_size);
01239 
01240    snprintf(info, 64 + AST_MAX_APP, "\n  -= Info about function '%s' =- \n\n", acf->name);
01241    term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22);
01242    term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40);
01243    term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
01244    term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
01245    term_color(syntax,
01246          acf->syntax ? acf->syntax : "Not available",
01247          COLOR_CYAN, 0, syntax_size);
01248    term_color(synopsis,
01249          acf->synopsis ? acf->synopsis : "Not available",
01250          COLOR_CYAN, 0, synopsis_size);
01251    term_color(description,
01252          acf->desc ? acf->desc : "Not available",
01253          COLOR_CYAN, 0, description_size);
01254    
01255    ast_cli(fd,"%s%s%s\n\n%s%s\n\n%s%s\n", infotitle, stxtitle, syntax, syntitle, synopsis, destitle, description);
01256 
01257    return RESULT_SUCCESS;
01258 }

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

Definition at line 1189 of file pbx.c.

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

01190 {
01191    struct ast_custom_function *acf;
01192    int count_acf = 0;
01193 
01194    ast_cli(fd, "Installed Custom Functions:\n--------------------------------------------------------------------------------\n");
01195    ast_mutex_lock(&acflock);
01196    for (acf = acf_root ; acf; acf = acf->next) {
01197       ast_cli(fd, "%-20.20s  %-35.35s  %s\n", acf->name, acf->syntax, acf->synopsis);
01198       count_acf++;
01199    }
01200    ast_mutex_unlock(&acflock);
01201    ast_cli(fd, "%d custom functions installed.\n", count_acf);
01202    return 0;
01203 }

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 3151 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, ast_hint::laststate, LOG_ERROR, ast_hint::next, ast_state_cb::next, and RESULT_SUCCESS.

03152 {
03153    struct ast_hint *hint;
03154    int num = 0;
03155    int watchers;
03156    struct ast_state_cb *watcher;
03157 
03158    if (!hints) {
03159       ast_cli(fd, "There are no registered dialplan hints\n");
03160       return RESULT_SUCCESS;
03161    }
03162    /* ... we have hints ... */
03163    ast_cli(fd, "\n    -= Registered Asterisk Dial Plan Hints =-\n");
03164    if (ast_mutex_lock(&hintlock)) {
03165       ast_log(LOG_ERROR, "Unable to lock hints\n");
03166       return -1;
03167    }
03168    hint = hints;
03169    while (hint) {
03170       watchers = 0;
03171       for (watcher = hint->callbacks; watcher; watcher = watcher->next)
03172          watchers++;
03173       ast_cli(fd, "   %-20.20s: %-20.20s  State:%-15.15s Watchers %2d\n",
03174          ast_get_extension_name(hint->exten), ast_get_extension_app(hint->exten),
03175          ast_extension_state2str(hint->laststate), watchers);
03176       num++;
03177       hint = hint->next;
03178    }
03179    ast_cli(fd, "----------------\n");
03180    ast_cli(fd, "- %d hints registered\n", num);
03181    ast_mutex_unlock(&hintlock);
03182    return RESULT_SUCCESS;
03183 }

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 3186 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, and RESULT_SUCCESS.

03187 {
03188    struct ast_switch *sw;
03189    if (!switches) {
03190       ast_cli(fd, "There are no registered alternative switches\n");
03191       return RESULT_SUCCESS;
03192    }
03193    /* ... we have applications ... */
03194    ast_cli(fd, "\n    -= Registered Asterisk Alternative Switches =-\n");
03195    if (ast_mutex_lock(&switchlock)) {
03196       ast_log(LOG_ERROR, "Unable to lock switches\n");
03197       return -1;
03198    }
03199    sw = switches;
03200    while (sw) {
03201       ast_cli(fd, "%s: %s\n", sw->name, sw->description);
03202       sw = sw->next;
03203    }
03204    ast_mutex_unlock(&switchlock);
03205    return RESULT_SUCCESS;
03206 }

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

Definition at line 633 of file pbx.c.

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

Referenced by pbx_find_extension().

00634 {
00635    if (!i->hastime)
00636       return 1;
00637 
00638    return ast_check_timing(&(i->timing));
00639 }

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

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

02493 {
02494    int failed = 0;
02495    double curloadavg;
02496    ast_mutex_lock(&maxcalllock);
02497    if (option_maxcalls) {
02498       if (countcalls >= option_maxcalls) {
02499          ast_log(LOG_NOTICE, "Maximum call limit of %d calls exceeded by '%s'!\n", option_maxcalls, c->name);
02500          failed = -1;
02501       }
02502    }
02503    if (option_maxload) {
02504       getloadavg(&curloadavg, 1);
02505       if (curloadavg >= option_maxload) {
02506          ast_log(LOG_NOTICE, "Maximum loadavg limit of %lf load exceeded by '%s' (currently %f)!\n", option_maxload, c->name, curloadavg);
02507          failed = -1;
02508       }
02509    }
02510    if (!failed)
02511       countcalls++;  
02512    ast_mutex_unlock(&maxcalllock);
02513 
02514    return failed;
02515 }

int load_pbx ( void   ) 

Definition at line 6266 of file pbx.c.

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

Referenced by main().

06267 {
06268    int x;
06269 
06270    /* Initialize the PBX */
06271    if (option_verbose) {
06272       ast_verbose( "Asterisk PBX Core Initializing\n");
06273       ast_verbose( "Registering builtin applications:\n");
06274    }
06275    AST_LIST_HEAD_INIT_NOLOCK(&globals);
06276    ast_cli_register_multiple(pbx_cli, sizeof(pbx_cli) / sizeof(pbx_cli[0]));
06277 
06278    /* Register builtin applications */
06279    for (x=0; x<sizeof(builtins) / sizeof(struct pbx_builtin); x++) {
06280       if (option_verbose)
06281          ast_verbose( VERBOSE_PREFIX_1 "[%s]\n", builtins[x].name);
06282       if (ast_register_application(builtins[x].name, builtins[x].execute, builtins[x].synopsis, builtins[x].description)) {
06283          ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name);
06284          return -1;
06285       }
06286    }
06287    return 0;
06288 }

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

Definition at line 780 of file pbx.c.

References ast_extension_match(), and ast_strlen_zero().

Referenced by pbx_find_extension().

00781 {
00782    int failresult;
00783    
00784    /* If the Caller*ID pattern is empty, then we're matching NO Caller*ID, so
00785       failing to get a number should count as a match, otherwise not */
00786 
00787    if (!ast_strlen_zero(cidpattern))
00788       failresult = 0;
00789    else
00790       failresult = 1;
00791 
00792    if (!callerid)
00793       return failresult;
00794 
00795    return ast_extension_match(cidpattern, callerid);
00796 }

static void null_datad ( void *  foo  )  [static]

Definition at line 4657 of file pbx.c.

Referenced by ast_add_extension2().

04658 {
04659 }

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

Definition at line 926 of file pbx.c.

References DONT_HAVE_LENGTH.

Referenced by pbx_retrieve_variable(), and pbx_substitute_variables_helper_full().

00927 {
00928    char *varchar, *offsetchar = NULL;
00929    int parens=0;
00930 
00931    *offset = 0;
00932    *length = DONT_HAVE_LENGTH;
00933    *isfunc = 0;
00934    for (varchar=var; *varchar; varchar++) {
00935       switch (*varchar) {
00936       case '(':
00937          (*isfunc)++;
00938          parens++;
00939          break;
00940       case ')':
00941          parens--;
00942          break;
00943       case ':':
00944          if (parens == 0) {
00945             offsetchar = varchar + 1;
00946             *varchar = '\0';
00947             goto pvn_endfor;
00948          }
00949       }
00950    }
00951 pvn_endfor:
00952    if (offsetchar) {
00953       sscanf(offsetchar, "%30d:%30d", offset, length);
00954       return 1;
00955    } else {
00956       return 0;
00957    }
00958 }

void pbx_builtin_clear_globals ( void   ) 

Definition at line 6155 of file pbx.c.

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

Referenced by handle_reload_extensions(), and reload().

06156 {
06157    struct ast_var_t *vardata;
06158 
06159    ast_mutex_lock(&globalslock);
06160    while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries)))
06161       ast_var_delete(vardata);
06162    ast_mutex_unlock(&globalslock);
06163 }

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

Definition at line 5950 of file pbx.c.

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

Referenced by __ast_pbx_run(), __login_exec(), _while_exec(), action_getvar(), agentmonitoroutgoing_exec(), ast_bridge_call(), ast_channel_bridge(), ast_feature_interpret(), ast_monitor_stop(), ast_osp_lookup(), builtin_atxfer(), builtin_automonitor(), builtin_blindtransfer(), chanspy_exec(), check_goto_on_transfer(), conf_exec(), conf_run(), dial_exec_full(), do_chanreads(), dundi_exec(), dundi_helper(), get_index(), get_refer_info(), group_check_exec(), group_count_exec(), iax2_exec(), import_ch(), leave_voicemail(), macro_exec(), misdn_answer(), misdn_hangup(), oh323_hangup(), ospfinished_exec(), ospnext_exec(), queue_exec(), retrydial_exec(), return_exec(), set_config_flags(), sip_addheader(), try_calling(), try_suggested_sip_codec(), wait_for_answer(), zt_call(), and zt_hangup().

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

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

Definition at line 6184 of file pbx.c.

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

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

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

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

06095 {
06096    char *name;
06097    char *value;
06098    char *stringp=NULL;
06099    char *channel;
06100    struct ast_channel *chan2;
06101    char tmp[VAR_BUF_SIZE]="";
06102    char *s;
06103 
06104    if (ast_strlen_zero(data)) {
06105       ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n");
06106       return 0;
06107    }
06108 
06109    stringp = ast_strdupa(data);
06110    name = strsep(&stringp,"=");
06111    channel = strsep(&stringp,"|"); 
06112    value = strsep(&stringp,"\0");
06113    if (channel && value && name) {
06114       chan2 = ast_get_channel_by_name_locked(channel);
06115       if (chan2) {
06116          s = alloca(strlen(value) + 4);
06117          if (s) {
06118             sprintf(s, "${%s}", value);
06119             pbx_substitute_variables_helper(chan2, s, tmp, sizeof(tmp) - 1);
06120          }
06121          ast_mutex_unlock(&chan2->lock);
06122       }
06123       pbx_builtin_setvar_helper(chan, name, tmp);
06124    }
06125 
06126    return(0);
06127 }

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

Definition at line 6149 of file pbx.c.

06150 {
06151    return 0;
06152 }

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

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

Referenced by gosub_exec().

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

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

Definition at line 6248 of file pbx.c.

References ast_say_character_str(), and ast_channel::language.

06249 {
06250    int res = 0;
06251 
06252    if (data)
06253       res = ast_say_character_str(chan, (char *)data, "", chan->language);
06254    return res;
06255 }

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

Definition at line 6239 of file pbx.c.

References ast_say_digit_str(), and ast_channel::language.

06240 {
06241    int res = 0;
06242 
06243    if (data)
06244       res = ast_say_digit_str(chan, (char *)data, "", chan->language);
06245    return res;
06246 }

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

Definition at line 6213 of file pbx.c.

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

06214 {
06215    int res = 0;
06216    char tmp[256];
06217    char *number = (char *) NULL;
06218    char *options = (char *) NULL;
06219 
06220    
06221    if (ast_strlen_zero(data)) {
06222       ast_log(LOG_WARNING, "SayNumber requires an argument (number)\n");
06223       return -1;
06224    }
06225    ast_copy_string(tmp, (char *) data, sizeof(tmp));
06226    number=tmp;
06227    strsep(&number, "|");
06228    options = strsep(&number, "|");
06229    if (options) { 
06230       if ( strcasecmp(options, "f") && strcasecmp(options,"m") && 
06231          strcasecmp(options, "c") && strcasecmp(options, "n") ) {
06232          ast_log(LOG_WARNING, "SayNumber gender option is either 'f', 'm', 'c' or 'n'\n");
06233          return -1;
06234       }
06235    }
06236    return res = ast_say_number(chan, atoi((char *) tmp), "", chan->language, options);
06237 }

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

Definition at line 6257 of file pbx.c.

References ast_say_phonetic_str(), and ast_channel::language.

06258 {
06259    int res = 0;
06260 
06261    if (data)
06262       res = ast_say_phonetic_str(chan, (char *)data, "", chan->language);
06263    return res;
06264 }

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

Definition at line 5925 of file pbx.c.

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

Referenced by dumpchan_exec(), and handle_showchan().

05926 {
05927    struct ast_var_t *variables;
05928    char *var, *val;
05929    int total = 0;
05930 
05931    if (!chan)
05932       return 0;
05933 
05934    memset(buf, 0, size);
05935 
05936    AST_LIST_TRAVERSE(&chan->varshead, variables, entries) {
05937       if ((var = ast_var_name(variables)) && (val = ast_var_value(variables))) {
05938          if (ast_build_string(&buf, &size, "%s=%s\n", var, val)) {
05939             ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
05940             break;
05941          } else
05942             total++;
05943       } else 
05944          break;
05945    }
05946    
05947    return total;
05948 }

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

Definition at line 6129 of file pbx.c.

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

06130 {
06131    char *name;
06132    char *value;
06133    char *stringp = NULL;
06134 
06135    if (ast_strlen_zero(data)) {
06136       ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n");
06137       return 0;
06138    }
06139 
06140    stringp = data;
06141    name = strsep(&stringp, "=");
06142    value = strsep(&stringp, "\0"); 
06143 
06144    pbx_builtin_setvar_helper(NULL, name, value);
06145 
06146    return(0);
06147 }

int pbx_builtin_setvar ( struct ast_channel chan,
void *  data 
)

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

06059 {
06060    char *name, *value, *mydata;
06061    int argc;
06062    char *argv[24];      /* this will only support a maximum of 24 variables being set in a single operation */
06063    int global = 0;
06064    int x;
06065 
06066    if (ast_strlen_zero(data)) {
06067       ast_log(LOG_WARNING, "Set requires at least one variable name/value pair.\n");
06068       return 0;
06069    }
06070 
06071    mydata = ast_strdupa(data);
06072    argc = ast_app_separate_args(mydata, '|', argv, sizeof(argv) / sizeof(argv[0]));
06073 
06074    /* check for a trailing flags argument */
06075    if ((argc > 1) && !strchr(argv[argc-1], '=')) {
06076       argc--;
06077       if (strchr(argv[argc], 'g'))
06078          global = 1;
06079    }
06080 
06081    for (x = 0; x < argc; x++) {
06082       name = argv[x];
06083       if ((value = strchr(name, '='))) {
06084          *value = '\0';
06085          value++;
06086          pbx_builtin_setvar_helper((global) ? NULL : chan, name, value);
06087       } else
06088          ast_log(LOG_WARNING, "Ignoring entry '%s' with no = (and not last 'options' entry)\n", name);
06089    }
06090 
06091    return(0);
06092 }

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

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

Referenced by __ast_pbx_run(), __login_exec(), _while_exec(), action_setvar(), aPGSQL_connect(), aPGSQL_fetch(), aPGSQL_query(), aqm_exec(), ast_bridge_call(), ast_channel_bridge(), ast_iax2_new(), ast_monitor_start(), ast_set_variables(), background_detect_exec(), builtin_blindtransfer(), builtin_function_set(), cb_events(), chanavail_exec(), conf_run(), controlplayback_exec(), count_exec(), curl_exec(), cut_exec(), dial_exec_full(), disa_exec(), do_waiting(), dundi_lookup_exec(), enumlookup_exec(), eval_exec(), export_ch(), 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(), i4l_read(), leave_voicemail(), lookupblacklist_exec(), macro_exec(), math_exec(), md5_exec(), md5check_exec(), misdn_call(), 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(), process_ast_dsp(), 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_handle_dtmfup(), and zt_new().

06007 {
06008    struct ast_var_t *newvariable;
06009    struct varshead *headp;
06010    const char *nametail = name;
06011 
06012    if (name[strlen(name)-1] == ')')
06013       return ast_func_write(chan, name, value);
06014 
06015    headp = (chan) ? &chan->varshead : &globals;
06016 
06017    /* For comparison purposes, we have to strip leading underscores */
06018    if (*nametail == '_') {
06019       nametail++;
06020       if (*nametail == '_') 
06021          nametail++;
06022    }
06023 
06024    if (headp == &globals)
06025       ast_mutex_lock(&globalslock);
06026    AST_LIST_TRAVERSE (headp, newvariable, entries) {
06027       if (strcasecmp(ast_var_name(newvariable), nametail) == 0) {
06028          /* there is already such a variable, delete it */
06029          AST_LIST_REMOVE(headp, newvariable, entries);
06030          ast_var_delete(newvariable);
06031          break;
06032       }
06033    }
06034    
06035    if (value) {
06036       if ((option_verbose > 1) && (headp == &globals))
06037          ast_verbose(VERBOSE_PREFIX_2 "Setting global variable '%s' to '%s'\n", name, value);
06038       newvariable = ast_var_assign(name, value);   
06039       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
06040    }
06041    
06042    if (headp == &globals)
06043       ast_mutex_unlock(&globalslock);
06044 }

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

Definition at line 6046 of file pbx.c.

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

06047 {
06048    static int deprecation_warning = 0;
06049 
06050    if (!deprecation_warning) {
06051       ast_log(LOG_WARNING, "SetVar is deprecated, please use Set instead.\n");
06052       deprecation_warning = 1;
06053    }
06054 
06055    return pbx_builtin_setvar(chan, data);
06056 }

int pbx_checkcondition ( char *  condition  ) 

Definition at line 6165 of file pbx.c.

Referenced by _while_exec(), builtin_function_if(), execif_exec(), gosubif_exec(), macro_exec(), macroif_exec(), and pbx_builtin_gotoif().

06166 {
06167    if (condition) {
06168       if (*condition == '\0') {
06169          /* Empty strings are false */
06170          return 0;
06171       } else if (*condition >= '0' && *condition <= '9') {
06172          /* Numbers are evaluated for truth */
06173          return atoi(condition);
06174       } else {
06175          /* Strings are true */
06176          return 1;
06177       }
06178    } else {
06179       /* NULL is also false */
06180       return 0;
06181    }
06182 }

static void pbx_destroy ( struct ast_pbx p  )  [static]

Definition at line 641 of file pbx.c.

References free.

Referenced by __ast_pbx_run().

00642 {
00643    free(p);
00644 }

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

executes an application

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

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

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

00556 {
00557    int res;
00558    
00559    char *saved_c_appl;
00560    char *saved_c_data;
00561    
00562    int (*execute)(struct ast_channel *chan, void *data) = app->execute; 
00563 
00564    if (newstack) {
00565       if (c->cdr && !ast_check_hangup(c))
00566          ast_cdr_setapp(c->cdr, app->name, data);
00567 
00568       /* save channel values */
00569       saved_c_appl= c->appl;
00570       saved_c_data= c->data;
00571 
00572       c->appl = app->name;
00573       c->data = data;      
00574       res = execute(c, data);
00575       /* restore channel values */
00576       c->appl= saved_c_appl;
00577       c->data= saved_c_data;
00578       return res;
00579    } else
00580       ast_log(LOG_WARNING, "You really didn't want to call this function with newstack set to 0\n");
00581    return -1;
00582 }

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 1641 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, ast_app::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().

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

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, read]

Definition at line 798 of file pbx.c.

References ast_context::alts, ast_extension_close(), ast_extension_match(), ast_log(), AST_PBX_MAX_STACK, ast_switch::canmatch, ast_exten::cidmatch, ast_sw::data, ast_sw::eval, ast_switch::exists, ast_exten::exten, HELPER_CANMATCH, HELPER_FINDLABEL, HELPER_MATCHMORE, include_valid(), ast_context::includes, ast_exten::label, LOG_WARNING, match(), matchcid(), ast_exten::matchcid, ast_switch::matchmore, ast_sw::name, ast_context::name, ast_context::next, ast_include::next, ast_sw::next, ast_exten::next, pbx_findswitch(), pbx_substitute_variables_helper(), ast_exten::peer, ast_exten::priority, ast_include::rname, ast_context::root, STATUS_NO_CONTEXT, STATUS_NO_EXTENSION, STATUS_NO_LABEL, STATUS_NO_PRIORITY, STATUS_SUCCESS, SWITCH_DATA_LENGTH, and ast_sw::tmpdata.

Referenced by ast_hint_extension(), and pbx_extension_helper().

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

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

Find application handle in linked list.

Look up an application

Parameters:
app name of the app This function searches for the ast_app structure within the apps that are registered for the one with the name you passed in. Returns the ast_app structure that matches on success, or NULL on failure

Definition at line 597 of file pbx.c.

References 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(), dial_exec_full(), dundi_exec(), exec_exec(), execif_exec(), feature_exec_app(), forward_message(), handle_exec(), iax2_exec(), page_exec(), pbx_builtin_execiftime(), pbx_extension_helper(), and realtime_exec().

00598 {
00599    struct ast_app *tmp;
00600 
00601    if (ast_mutex_lock(&applock)) {
00602       ast_log(LOG_WARNING, "Unable to obtain application lock\n");
00603       return NULL;
00604    }
00605    tmp = apps;
00606    while(tmp) {
00607       if (!strcasecmp(tmp->name, app))
00608          break;
00609       tmp = tmp->next;
00610    }
00611    ast_mutex_unlock(&applock);
00612    return tmp;
00613 }

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

Definition at line 615 of file pbx.c.

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

Referenced by pbx_find_extension().

00616 {
00617    struct ast_switch *asw;
00618 
00619    if (ast_mutex_lock(&switchlock)) {
00620       ast_log(LOG_WARNING, "Unable to obtain application lock\n");
00621       return NULL;
00622    }
00623    asw = switches;
00624    while(asw) {
00625       if (!strcasecmp(asw->name, sw))
00626          break;
00627       asw = asw->next;
00628    }
00629    ast_mutex_unlock(&switchlock);
00630    return asw;
00631 }

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

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

Definition at line 999 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, globals, 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 handle_getvariable(), pbx_retrieve_variable(), and pbx_substitute_variables_helper_full().

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

int pbx_set_autofallthrough ( int  newval  ) 

Definition at line 2589 of file pbx.c.

Referenced by pbx_load_module().

02590 {
02591    int oldval;
02592    oldval = autofallthrough;
02593    if (oldval != newval)
02594       autofallthrough = newval;
02595    return oldval;
02596 }

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

Definition at line 1628 of file pbx.c.

References ast_exten::data, and pbx_substitute_variables_helper().

Referenced by pbx_extension_helper().

01629 {
01630    memset(passdata, 0, datalen);
01631       
01632    /* No variables or expressions in e->data, so why scan it? */
01633    if (!strchr(e->data, '$') && !strstr(e->data,"${") && !strstr(e->data,"$[") && !strstr(e->data,"$(")) {
01634       ast_copy_string(passdata, e->data, datalen);
01635       return;
01636    }
01637    
01638    pbx_substitute_variables_helper(c, e->data, passdata, datalen - 1);
01639 }                                                     

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

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

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

01442 {
01443    char *cp4;
01444    const char *tmp, *whereweare;
01445    int length, offset, offset2, isfunction;
01446    char *workspace = NULL;
01447    char *ltmp = NULL, *var = NULL;
01448    char *nextvar, *nextexp, *nextthing;
01449    char *vars, *vare;
01450    int pos, brackets, needsub, len;
01451    
01452    /* Substitutes variables into cp2, based on string cp1, and assuming cp2 to be
01453       zero-filled */
01454    whereweare=tmp=cp1;
01455    while(!ast_strlen_zero(whereweare) && count) {
01456       /* Assume we're copying the whole remaining string */
01457       pos = strlen(whereweare);
01458       nextvar = NULL;
01459       nextexp = NULL;
01460       nextthing = strchr(whereweare, '$');
01461       if (nextthing) {
01462          switch(nextthing[1]) {
01463          case '{':
01464             nextvar = nextthing;
01465             pos = nextvar - whereweare;
01466             break;
01467          case '[':
01468             nextexp = nextthing;
01469             pos = nextexp - whereweare;
01470             break;
01471          }
01472       }
01473 
01474       if (pos) {
01475          /* Can't copy more than 'count' bytes */
01476          if (pos > count)
01477             pos = count;
01478          
01479          /* Copy that many bytes */
01480          memcpy(cp2, whereweare, pos);
01481          
01482          count -= pos;
01483          cp2 += pos;
01484          whereweare += pos;
01485       }
01486       
01487       if (nextvar) {
01488          /* We have a variable.  Find the start and end, and determine
01489             if we are going to have to recursively call ourselves on the
01490             contents */
01491          vars = vare = nextvar + 2;
01492          brackets = 1;
01493          needsub = 0;
01494 
01495          /* Find the end of it */
01496          while (brackets && *vare) {
01497             if ((vare[0] == '$') && (vare[1] == '{')) {
01498                needsub++;
01499             } else if (vare[0] == '{') {
01500                brackets++;
01501             } else if (vare[0] == '}') {
01502                brackets--;
01503             } else if ((vare[0] == '$') && (vare[1] == '['))
01504                needsub++;
01505             vare++;
01506          }
01507          if (brackets)
01508             ast_log(LOG_NOTICE, "Error in extension logic (missing '}')\n");
01509          len = vare - vars - 1;
01510 
01511          /* Skip totally over variable string */
01512          whereweare += (len + 3);
01513 
01514          if (!var)
01515             var = alloca(VAR_BUF_SIZE);
01516 
01517          /* Store variable name (and truncate) */
01518          ast_copy_string(var, vars, len + 1);
01519 
01520          /* Substitute if necessary */
01521          if (needsub) {
01522             if (!ltmp)
01523                ltmp = alloca(VAR_BUF_SIZE);
01524 
01525             memset(ltmp, 0, VAR_BUF_SIZE);
01526             pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1);
01527             vars = ltmp;
01528          } else {
01529             vars = var;
01530          }
01531 
01532          if (!workspace)
01533             workspace = alloca(VAR_BUF_SIZE);
01534 
01535          workspace[0] = '\0';
01536 
01537          parse_variable_name(vars, &offset, &offset2, &isfunction);
01538          if (isfunction) {
01539             /* Evaluate function */
01540             cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE);
01541 
01542             ast_log(LOG_DEBUG, "Function result is '%s'\n", cp4 ? cp4 : "(null)");
01543          } else {
01544             /* Retrieve variable value */
01545             pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp);
01546