Mon Mar 20 08:20:28 2006

Asterisk developer's documentation


Main Page | Modules | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

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"

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)
int __ast_goto_if_exists (struct ast_channel *chan, char *context, char *exten, int priority, int async)
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)
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)
int ast_change_hint (struct ast_exten *oe, struct ast_exten *ne)
 ast_change_hint: Change hint for an extension
int ast_check_timing (struct ast_timing *i)
int ast_context_add_ignorepat (const char *con, const char *value, const char *registrar)
int ast_context_add_ignorepat2 (struct ast_context *con, const char *value, const char *registrar)
int ast_context_add_include (const char *context, const char *include, const char *registrar)
int ast_context_add_include2 (struct ast_context *con, const char *value, const char *registrar)
int ast_context_add_switch (const char *context, const char *sw, const char *data, int eval, const char *registrar)
int ast_context_add_switch2 (struct ast_context *con, const char *value, const char *data, int eval, const char *registrar)
ast_contextast_context_create (struct ast_context **extcontexts, const char *name, const char *registrar)
void ast_context_destroy (struct ast_context *con, const char *registrar)
ast_contextast_context_find (const char *name)
int ast_context_remove_extension (const char *context, const char *extension, int priority, const char *registrar)
int ast_context_remove_extension2 (struct ast_context *con, const char *extension, int priority, const char *registrar)
 This functionc locks given context, search for the right extension and fires out all peer in this extensions with given priority. If priority is set to 0, all peers are removed. After that, unlock context and return.
int ast_context_remove_ignorepat (const char *context, const char *ignorepat, const char *registrar)
int ast_context_remove_ignorepat2 (struct ast_context *con, const char *ignorepat, const char *registrar)
int ast_context_remove_include (const char *context, const char *include, const char *registrar)
int ast_context_remove_include2 (struct ast_context *con, const char *include, const char *registrar)
int ast_context_remove_switch (const char *context, const char *sw, const char *data, const char *registrar)
int ast_context_remove_switch2 (struct ast_context *con, const char *sw, const char *data, const char *registrar)
 This function locks given context, removes switch, unlock context and return.
int ast_context_verify_includes (struct ast_context *con)
ast_custom_functionast_custom_function_find (char *name)
int ast_custom_function_register (struct ast_custom_function *acf)
int ast_custom_function_unregister (struct ast_custom_function *acf)
int ast_exec_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
int ast_exists_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
int ast_explicit_goto (struct ast_channel *chan, const char *context, const char *exten, int priority)
int ast_extension_close (const char *pattern, const char *data, int needmore)
int ast_extension_match (const char *pattern, const char *data)
int ast_extension_state (struct ast_channel *c, char *context, char *exten)
 ast_extension_state: Check extension state for an extension by using hint
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)
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)
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)
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)
int ast_remove_hint (struct ast_exten *e)
 ast_remove_hint: Remove hint from extension
int ast_spawn_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
int ast_unlock_context (struct ast_context *con)
int ast_unlock_contexts ()
int ast_unregister_application (const char *app)
void ast_unregister_switch (struct ast_switch *sw)
ast_extenast_walk_context_extensions (struct ast_context *con, struct ast_exten *exten)
ast_ignorepatast_walk_context_ignorepats (struct ast_context *con, struct ast_ignorepat *ip)
ast_includeast_walk_context_includes (struct ast_context *con, struct ast_include *inc)
ast_swast_walk_context_switches (struct ast_context *con, struct ast_sw *sw)
ast_contextast_walk_contexts (struct ast_context *con)
ast_extenast_walk_extension_priorities (struct ast_exten *exten, struct ast_exten *priority)
void * async_wait (void *data)
char * complete_show_application (char *line, char *word, int pos, int state)
char * complete_show_applications (char *line, char *word, int pos, int state)
char * complete_show_dialplan_context (char *line, char *word, int pos, int state)
char * complete_show_function (char *line, char *word, int pos, int state)
void decrease_call_count (void)
void destroy_exten (struct ast_exten *e)
int ext_strncpy (char *dst, const char *src, int len)
unsigned int get_day (char *day)
unsigned int get_dow (char *dow)
 get_dow: Get day of week
unsigned int get_month (char *mon)
void get_timerange (struct ast_timing *i, char *times)
int handle_show_application (int fd, int argc, char *argv[])
int handle_show_applications (int fd, int argc, char *argv[])
int handle_show_dialplan (int fd, int argc, char *argv[])
int handle_show_function (int fd, int argc, char *argv[])
int handle_show_functions (int fd, int argc, char *argv[])
int handle_show_hints (int fd, int argc, char *argv[])
 handle_show_hints: CLI support for listing registred dial plan hints
int handle_show_switches (int fd, int argc, char *argv[])
 handle_show_switches: CLI support for listing registred dial plan switches
int include_valid (struct ast_include *i)
int increase_call_count (const struct ast_channel *c)
int load_pbx (void)
int matchcid (const char *cidpattern, const char *callerid)
void null_datad (void *foo)
int parse_variable_name (char *var, int *offset, int *length, int *isfunc)
int pbx_builtin_answer (struct ast_channel *, void *)
int pbx_builtin_atimeout (struct ast_channel *, void *)
int pbx_builtin_background (struct ast_channel *, void *)
int pbx_builtin_busy (struct ast_channel *, void *)
void pbx_builtin_clear_globals (void)
int pbx_builtin_congestion (struct ast_channel *, void *)
int pbx_builtin_dtimeout (struct ast_channel *, void *)
int pbx_builtin_execiftime (struct ast_channel *, void *)
char * pbx_builtin_getvar_helper (struct ast_channel *chan, const char *name)
int pbx_builtin_goto (struct ast_channel *, void *)
int pbx_builtin_gotoif (struct ast_channel *, void *)
int pbx_builtin_gotoiftime (struct ast_channel *, void *)
int pbx_builtin_hangup (struct ast_channel *, void *)
int pbx_builtin_importvar (struct ast_channel *, void *)
int pbx_builtin_noop (struct ast_channel *, void *)
int pbx_builtin_progress (struct ast_channel *, void *)
void pbx_builtin_pushvar_helper (struct ast_channel *chan, const char *name, const char *value)
int pbx_builtin_resetcdr (struct ast_channel *, void *)
int pbx_builtin_ringing (struct ast_channel *, void *)
int pbx_builtin_rtimeout (struct ast_channel *, void *)
int pbx_builtin_saycharacters (struct ast_channel *, void *)
int pbx_builtin_saydigits (struct ast_channel *, void *)
int pbx_builtin_saynumber (struct ast_channel *, void *)
int pbx_builtin_sayphonetic (struct ast_channel *, void *)
int pbx_builtin_serialize_variables (struct ast_channel *chan, char *buf, size_t size)
int pbx_builtin_setaccount (struct ast_channel *, void *)
int pbx_builtin_setamaflags (struct ast_channel *, void *)
int pbx_builtin_setglobalvar (struct ast_channel *, void *)
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)
int pbx_builtin_setvar_old (struct ast_channel *, void *)
int pbx_builtin_wait (struct ast_channel *, void *)
int pbx_builtin_waitexten (struct ast_channel *, void *)
int pbx_checkcondition (char *condition)
void pbx_destroy (struct ast_pbx *p)
int pbx_exec (struct ast_channel *c, struct ast_app *app, void *data, int newstack)
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)
ast_extenpbx_find_extension (struct ast_channel *chan, struct ast_context *bypass, const char *context, const char *exten, int priority, const char *label, const char *callerid, int action, char *incstack[], int *stacklen, int *status, struct ast_switch **swo, char **data, const char **foundcontext)
ast_apppbx_findapp (const char *app)
 Find application handle in linked list.
ast_switchpbx_findswitch (const char *sw)
void pbx_retrieve_variable (struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp)
 pbx_retrieve_variable: Support for Asterisk built-in variables and functions in the dialplan ---
int pbx_set_autofallthrough (int newval)
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)
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)
void * pbx_thread (void *data)
int show_dialplan_helper (int fd, char *context, char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude, int includecount, char *includes[])
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.
void wait_for_hangup (struct ast_channel *chan, void *data)

Variables

ast_custom_functionacf_root = NULL
ast_appapps = NULL
int autofallthrough = 0
pbx_builtin builtins []
 Declaration of builtin applications.
ast_contextcontexts = NULL
int countcalls = 0
char * days []
varshead globals
ast_hinthints = NULL
char * months []
ast_cli_entry pbx_cli []
char show_application_help []
char show_applications_help []
char show_dialplan_help []
char show_function_help []
char show_functions_help []
char show_hints_help []
char show_switches_help []
ast_state_cbstatecbs = NULL
int stateid = 1
ast_switchswitches = NULL


Detailed Description

Core PBX routines.

Definition in file pbx.c.


Define Documentation

#define AST_PBX_MAX_STACK   128
 

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

Definition at line 556 of file pbx.c.

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

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

#define EXTENSION_MATCH_CORE data,
pattern,
match   ) 
 

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

#define HELPER_CANMATCH   3
 

Definition at line 561 of file pbx.c.

Referenced by ast_canmatch_extension(), and pbx_extension_helper().

#define HELPER_EXEC   2
 

Definition at line 560 of file pbx.c.

Referenced by ast_exec_extension(), and pbx_extension_helper().

#define HELPER_EXISTS   0
 

Definition at line 558 of file pbx.c.

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

#define HELPER_FINDLABEL   5
 

Definition at line 563 of file pbx.c.

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

#define HELPER_MATCHMORE   4
 

Definition at line 562 of file pbx.c.

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

#define HELPER_SPAWN   1
 

Definition at line 559 of file pbx.c.

Referenced by ast_spawn_extension(), and pbx_extension_helper().

#define LOG
 

#define STATUS_NO_CONTEXT   1
 

Definition at line 744 of file pbx.c.

Referenced by pbx_extension_helper().

#define STATUS_NO_EXTENSION   2
 

Definition at line 745 of file pbx.c.

Referenced by pbx_extension_helper().

#define STATUS_NO_LABEL   4
 

Definition at line 747 of file pbx.c.

Referenced by pbx_extension_helper().

#define STATUS_NO_PRIORITY   3
 

Definition at line 746 of file pbx.c.

Referenced by pbx_extension_helper().

#define STATUS_SUCCESS   5
 

Definition at line 748 of file pbx.c.

#define SWITCH_DATA_LENGTH   256
 

Definition at line 77 of file pbx.c.

Referenced by pbx_find_extension().

#define VAR_BUF_SIZE   4096
 

Definition at line 79 of file pbx.c.

Referenced by pbx_substitute_variables_helper_full().

#define VAR_HARDTRAN   3
 

Definition at line 83 of file pbx.c.

#define VAR_NORMAL   1
 

Definition at line 81 of file pbx.c.

#define VAR_SOFTTRAN   2
 

Definition at line 82 of file pbx.c.

#define WAITEXTEN_MOH   (1 << 0)
 

Definition at line 97 of file pbx.c.

Referenced by pbx_builtin_waitexten().


Function Documentation

void __ast_context_destroy struct ast_context con,
const char *  registrar
 

Definition at line 5283 of file pbx.c.

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

05284 {
05285    struct ast_context *tmp, *tmpl=NULL;
05286    struct ast_include *tmpi, *tmpil= NULL;
05287    struct ast_sw *sw, *swl= NULL;
05288    struct ast_exten *e, *el, *en;
05289    struct ast_ignorepat *ipi, *ipl = NULL;
05290 
05291    ast_mutex_lock(&conlock);
05292    tmp = contexts;
05293    while(tmp) {
05294       if (((tmp->name && con && con->name && !strcasecmp(tmp->name, con->name)) || !con) &&
05295           (!registrar || !strcasecmp(registrar, tmp->registrar))) {
05296          /* Okay, let's lock the structure to be sure nobody else
05297             is searching through it. */
05298          if (ast_mutex_lock(&tmp->lock)) {
05299             ast_log(LOG_WARNING, "Unable to lock context lock\n");
05300             return;
05301          }
05302          if (tmpl)
05303             tmpl->next = tmp->next;
05304          else
05305             contexts = tmp->next;
05306          /* Okay, now we're safe to let it go -- in a sense, we were
05307             ready to let it go as soon as we locked it. */
05308          ast_mutex_unlock(&tmp->lock);
05309          for (tmpi = tmp->includes; tmpi; ) {
05310             /* Free includes */
05311             tmpil = tmpi;
05312             tmpi = tmpi->next;
05313             free(tmpil);
05314          }
05315          for (ipi = tmp->ignorepats; ipi; ) {
05316             /* Free ignorepats */
05317             ipl = ipi;
05318             ipi = ipi->next;
05319             free(ipl);
05320          }
05321          for (sw = tmp->alts; sw; ) {
05322             /* Free switches */
05323             swl = sw;
05324             sw = sw->next;
05325             free(swl);
05326             swl = sw;
05327          }
05328          for (e = tmp->root; e;) {
05329             for (en = e->peer; en;) {
05330                el = en;
05331                en = en->peer;
05332                destroy_exten(el);
05333             }
05334             el = e;
05335             e = e->next;
05336             destroy_exten(el);
05337          }
05338          ast_mutex_destroy(&tmp->lock);
05339          free(tmp);
05340          if (!con) {
05341             /* Might need to get another one -- restart */
05342             tmp = contexts;
05343             tmpl = NULL;
05344             tmpil = NULL;
05345             continue;
05346          }
05347          ast_mutex_unlock(&conlock);
05348          return;
05349       }
05350       tmpl = tmp;
05351       tmp = tmp->next;
05352    }
05353    ast_mutex_unlock(&conlock);
05354 }

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

Definition at line 6405 of file pbx.c.

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

06406 {
06407    int (*goto_func)(struct ast_channel *chan, const char *context, const char *exten, int priority);
06408 
06409    if (!chan)
06410       return -2;
06411 
06412    goto_func = (async) ? ast_async_goto : ast_explicit_goto;
06413    if (ast_exists_extension(chan, context ? context : chan->context,
06414              exten ? exten : chan->exten, priority,
06415              chan->cid.cid_num))
06416       return goto_func(chan, context ? context : chan->context,
06417              exten ? exten : chan->exten, priority);
06418    else 
06419       return -3;
06420 }

int __ast_pbx_run struct ast_channel c  )  [static]
 

Definition at line 2226 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_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, free, LOG_DEBUG, LOG_ERROR, LOG_WARNING, malloc, ast_channel::name, 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().

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

int ast_active_calls void   ) 
 

Definition at line 2550 of file pbx.c.

Referenced by handle_chanlist().

02551 {
02552    return countcalls;
02553 }

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

04486 {
04487    struct ast_context *c;
04488 
04489    if (ast_lock_contexts()) {
04490       errno = EBUSY;
04491       return -1;
04492    }
04493 
04494    c = ast_walk_contexts(NULL);
04495    while (c) {
04496       if (!strcmp(context, ast_get_context_name(c))) {
04497          int ret = ast_add_extension2(c, replace, extension, priority, label, callerid,
04498             application, data, datad, registrar);
04499          ast_unlock_contexts();
04500          return ret;
04501       }
04502       c = ast_walk_contexts(c);
04503    }
04504 
04505    ast_unlock_contexts();
04506    errno = ENOENT;
04507    return -1;
04508 }

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

For details about the arguements, check ast_add_extension()

Definition at line 4623 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, ext_strncpy(), ast_exten::exten, free, globals, ast_exten::label, ast_context::lock, LOG_ERROR, LOG_WARNING, malloc, ast_exten::matchcid, ast_context::name, ast_exten::next, ast_exten::parent, pbx_substitute_variables_varshead(), ast_exten::peer, ast_exten::priority, ast_exten::registrar, ast_context::root, and ast_exten::stuff.

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

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

int ast_add_hint struct ast_exten e  )  [static]
 

ast_add_hint: Add hint to hint list, check initial extension state

Definition at line 2063 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, hints, ast_hint::laststate, LOG_DEBUG, malloc, ast_hint::next, and option_debug.

Referenced by ast_add_extension2().

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

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 4529 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(), misdn_tx2ast_frm(), monitor_handle_owned(), socket_read(), and zt_read().

04530 {
04531    int res = 0;
04532 
04533    ast_mutex_lock(&chan->lock);
04534 
04535    if (chan->pbx) {
04536       /* This channel is currently in the PBX */
04537       ast_explicit_goto(chan, context, exten, priority);
04538       ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO);
04539    } else {
04540       /* In order to do it when the channel doesn't really exist within
04541          the PBX, we have to make a new channel, masquerade, and start the PBX
04542          at the new location */
04543       struct ast_channel *tmpchan;
04544       tmpchan = ast_channel_alloc(0);
04545       if (tmpchan) {
04546          snprintf(tmpchan->name, sizeof(tmpchan->name), "AsyncGoto/%s", chan->name);
04547          ast_setstate(tmpchan, chan->_state);
04548          /* Make formats okay */
04549          tmpchan->readformat = chan->readformat;
04550          tmpchan->writeformat = chan->writeformat;
04551          /* Setup proper location */
04552          ast_explicit_goto(tmpchan,
04553                  (!ast_strlen_zero(context)) ? context : chan->context,
04554                  (!ast_strlen_zero(exten)) ? exten : chan->exten,
04555                  priority);
04556 
04557          /* Masquerade into temp channel */
04558          ast_channel_masquerade(tmpchan, chan);
04559       
04560          /* Grab the locks and get going */
04561          ast_mutex_lock(&tmpchan->lock);
04562          ast_do_masquerade(tmpchan);
04563          ast_mutex_unlock(&tmpchan->lock);
04564          /* Start the PBX going on our stolen channel */
04565          if (ast_pbx_start(tmpchan)) {
04566             ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name);
04567             ast_hangup(tmpchan);
04568             res = -1;
04569          }
04570       } else {
04571          res = -1;
04572       }
04573    }
04574    ast_mutex_unlock(&chan->lock);
04575    return res;
04576 }

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

Definition at line 4578 of file pbx.c.

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

04579 {
04580    struct ast_channel *chan;
04581    int res = -1;
04582 
04583    chan = ast_get_channel_by_name_locked(channame);
04584    if (chan) {
04585       res = ast_async_goto(chan, context, exten, priority);
04586       ast_mutex_unlock(&chan->lock);
04587    }
04588    return res;
04589 }

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

Definition at line 6426 of file pbx.c.

References __ast_goto_if_exists().

06426                                                                                                  {
06427    return __ast_goto_if_exists(chan, context, exten, priority, 1);
06428 }

int ast_build_timing struct ast_timing i,
char *  info_in
 

Definition at line 4062 of file pbx.c.

References ast_strlen_zero(), ast_timing::daymask, ast_timing::dowmask, 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().

04063 {
04064    char info_save[256];
04065    char *info;
04066    char *c;
04067 
04068    /* Check for empty just in case */
04069    if (ast_strlen_zero(info_in))
04070       return 0;
04071    /* make a copy just in case we were passed a static string */
04072    ast_copy_string(info_save, info_in, sizeof(info_save));
04073    info = info_save;
04074    /* Assume everything except time */
04075    i->monthmask = (1 << 12) - 1;
04076    i->daymask = (1 << 30) - 1 + (1 << 30);
04077    i->dowmask = (1 << 7) - 1;
04078    /* Avoid using str tok */
04079    FIND_NEXT;
04080    /* Info has the time range, start with that */
04081    get_timerange(i, info);
04082    info = c;
04083    if (!info)
04084       return 1;
04085    FIND_NEXT;
04086    /* Now check for day of week */
04087    i->dowmask = get_dow(info);
04088 
04089    info = c;
04090    if (!info)
04091       return 1;
04092    FIND_NEXT;
04093    /* Now check for the day of the month */
04094    i->daymask = get_day(info);
04095    info = c;
04096    if (!info)
04097       return 1;
04098    FIND_NEXT;
04099    /* And finally go for the month */
04100    i->monthmask = get_month(info);
04101 
04102    return 1;
04103 }

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

Parameters:
c not really important
context context to serach within
exten extension to check
priority priority of extension path
callerid callerid of extension being searched for If "exten" *could be* a valid extension in this context with or without some more digits, return non-zero. Basically, when this returns 0, no matter what you add to exten, it's not going to be a valid extension anymore

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

02207 {
02208    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, HELPER_CANMATCH);
02209 }

int ast_change_hint struct ast_exten oe,
struct ast_exten ne
[static]
 

ast_change_hint: Change hint for an extension

Definition at line 2106 of file pbx.c.

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

Referenced by ast_add_extension2().

02107 { 
02108    struct ast_hint *list;
02109 
02110    ast_mutex_lock(&hintlock);
02111    list = hints;
02112 
02113    while(list) {
02114       if (list->exten == oe) {
02115             list->exten = ne;
02116          ast_mutex_unlock(&hintlock);  
02117          return 0;
02118       }
02119       list = list->next;
02120    }
02121    ast_mutex_unlock(&hintlock);
02122 
02123    return -1;
02124 }

int ast_check_timing struct ast_timing i  ) 
 

Definition at line 4105 of file pbx.c.

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

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

04106 {
04107    struct tm tm;
04108    time_t t;
04109 
04110    time(&t);
04111    localtime_r(&t,&tm);
04112 
04113    /* If it's not the right month, return */
04114    if (!(i->monthmask & (1 << tm.tm_mon))) {
04115       return 0;
04116    }
04117 
04118    /* If it's not that time of the month.... */
04119    /* Warning, tm_mday has range 1..31! */
04120    if (!(i->daymask & (1 << (tm.tm_mday-1))))
04121       return 0;
04122 
04123    /* If it's not the right day of the week */
04124    if (!(i->dowmask & (1 << tm.tm_wday)))
04125       return 0;
04126 
04127    /* Sanity check the hour just to be safe */
04128    if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) {
04129       ast_log(LOG_WARNING, "Insane time...\n");
04130       return 0;
04131    }
04132 
04133    /* Now the tough part, we calculate if it fits
04134       in the right time based on min/hour */
04135    if (!(i->minmask[tm.tm_hour] & (1 << (tm.tm_min / 2))))
04136       return 0;
04137 
04138    /* If we got this far, then we're good */
04139    return 1;
04140 }

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

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

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

04402 {
04403    struct ast_context *c;
04404 
04405    if (ast_lock_contexts()) {
04406       errno = EBUSY;
04407       return -1;
04408    }
04409 
04410    c = ast_walk_contexts(NULL);
04411    while (c) {
04412       if (!strcmp(ast_get_context_name(c), con)) {
04413          int ret = ast_context_add_ignorepat2(c, value, registrar);
04414          ast_unlock_contexts();
04415          return ret;
04416       } 
04417       c = ast_walk_contexts(c);
04418    }
04419 
04420    ast_unlock_contexts();
04421    errno = ENOENT;
04422    return -1;
04423 }

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

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

04426 {
04427    struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL;
04428    int length;
04429    length = sizeof(struct ast_ignorepat);
04430    length += strlen(value) + 1;
04431    ignorepat = malloc(length);
04432    if (!ignorepat) {
04433       ast_log(LOG_ERROR, "Out of memory\n");
04434       errno = ENOMEM;
04435       return -1;
04436    }
04437    memset(ignorepat, 0, length);
04438    strcpy(ignorepat->pattern, value);
04439    ignorepat->next = NULL;
04440    ignorepat->registrar = registrar;
04441    ast_mutex_lock(&con->lock);
04442    ignorepatc = con->ignorepats;
04443    while(ignorepatc) {
04444       ignorepatl = ignorepatc;
04445       if (!strcasecmp(ignorepatc->pattern, value)) {
04446          /* Already there */
04447          ast_mutex_unlock(&con->lock);
04448          errno = EEXIST;
04449          return -1;
04450       }
04451       ignorepatc = ignorepatc->next;
04452    }
04453    if (ignorepatl) 
04454       ignorepatl->next = ignorepat;
04455    else
04456       con->ignorepats = ignorepat;
04457    ast_mutex_unlock(&con->lock);
04458    return 0;
04459    
04460 }

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

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

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

03785 {
03786    struct ast_context *c;
03787 
03788    if (ast_lock_contexts()) {
03789       errno = EBUSY;
03790       return -1;
03791    }
03792 
03793    /* walk contexts ... */
03794    c = ast_walk_contexts(NULL);
03795    while (c) {
03796       /* ... search for the right one ... */
03797       if (!strcmp(ast_get_context_name(c), context)) {
03798          int ret = ast_context_add_include2(c, include, registrar);
03799          /* ... unlock contexts list and return */
03800          ast_unlock_contexts();
03801          return ret;
03802       }
03803       c = ast_walk_contexts(c);
03804    }
03805 
03806    /* we can't find the right context */
03807    ast_unlock_contexts();
03808    errno = ENOENT;
03809    return -1;
03810 }

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

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

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

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

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

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

Definition at line 4225 of file pbx.c.

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

04226 {
04227    struct ast_context *c;
04228 
04229    if (ast_lock_contexts()) {
04230       errno = EBUSY;
04231       return -1;
04232    }
04233 
04234    /* walk contexts ... */
04235    c = ast_walk_contexts(NULL);
04236    while (c) {
04237       /* ... search for the right one ... */
04238       if (!strcmp(ast_get_context_name(c), context)) {
04239          int ret = ast_context_add_switch2(c, sw, data, eval, registrar);
04240          /* ... unlock contexts list and return */
04241          ast_unlock_contexts();
04242          return ret;
04243       }
04244       c = ast_walk_contexts(c);
04245    }
04246 
04247    /* we can't find the right context */
04248    ast_unlock_contexts();
04249    errno = ENOENT;
04250    return -1;
04251 }

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

See ast_context_add_switch()

Definition at line 4260 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, ast_sw::tmpdata, and VERBOSE_PREFIX_3.

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

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

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

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

Definition at line 3628 of file pbx.c.

References ast_log(), ast_mutex_init(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), ast_context::ignorepats, ast_context::includes, ast_context::lock, LOG_DEBUG, LOG_ERROR, LOG_WARNING, malloc, name, ast_context::name, ast_context::next, 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().

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

void ast_context_destroy struct ast_context con,
const char *  registrar
 

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

Definition at line 5356 of file pbx.c.

References __ast_context_destroy().

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

05357 {
05358    __ast_context_destroy(con,registrar);
05359 }

struct ast_context* ast_context_find const char *  name  ) 
 

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

Definition at line 727 of file pbx.c.

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

00728 {
00729    struct ast_context *tmp;
00730    ast_mutex_lock(&conlock);
00731    if (name) {
00732       tmp = contexts;
00733       while(tmp) {
00734          if (!strcasecmp(name, tmp->name))
00735             break;
00736          tmp = tmp->next;
00737       }
00738    } else
00739       tmp = contexts;
00740    ast_mutex_unlock(&conlock);
00741    return tmp;
00742 }

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

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

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

02714 {
02715    struct ast_context *c;
02716 
02717    if (ast_lock_contexts()) return -1;
02718 
02719    /* walk contexts ... */
02720    c = ast_walk_contexts(NULL);
02721    while (c) {
02722       /* ... search for the right one ... */
02723       if (!strcmp(ast_get_context_name(c), context)) {
02724          /* ... remove extension ... */
02725          int ret = ast_context_remove_extension2(c, extension, priority,
02726             registrar);
02727          /* ... unlock contexts list and return */
02728          ast_unlock_contexts();
02729          return ret;
02730       }
02731       c = ast_walk_contexts(c);
02732    }
02733 
02734    /* we can't find the right context */
02735    ast_unlock_contexts();
02736    return -1;
02737 }

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

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

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

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

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

04343 {
04344    struct ast_context *c;
04345 
04346    if (ast_lock_contexts()) {
04347       errno = EBUSY;
04348       return -1;
04349    }
04350 
04351    c = ast_walk_contexts(NULL);
04352    while (c) {
04353       if (!strcmp(ast_get_context_name(c), context)) {
04354          int ret = ast_context_remove_ignorepat2(c, ignorepat, registrar);
04355          ast_unlock_contexts();
04356          return ret;
04357       }
04358       c = ast_walk_contexts(c);
04359    }
04360 
04361    ast_unlock_contexts();
04362    errno = ENOENT;
04363    return -1;
04364 }

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

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

04367 {
04368    struct ast_ignorepat *ip, *ipl = NULL;
04369 
04370    if (ast_mutex_lock(&con->lock)) {
04371       errno = EBUSY;
04372       return -1;
04373    }
04374 
04375    ip = con->ignorepats;
04376    while (ip) {
04377       if (!strcmp(ip->pattern, ignorepat) &&
04378          (!registrar || (registrar == ip->registrar))) {
04379          if (ipl) {
04380             ipl->next = ip->next;
04381             free(ip);
04382          } else {
04383             con->ignorepats = ip->next;
04384             free(ip);
04385          }
04386          ast_mutex_unlock(&con->lock);
04387          return 0;
04388       }
04389       ipl = ip; ip = ip->next;
04390    }
04391 
04392    ast_mutex_unlock(&con->lock);
04393    errno = EINVAL;
04394    return -1;
04395 }

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

See add_include

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

02570 {
02571    struct ast_context *c;
02572 
02573    if (ast_lock_contexts()) return -1;
02574 
02575    /* walk contexts and search for the right one ...*/
02576    c = ast_walk_contexts(NULL);
02577    while (c) {
02578       /* we found one ... */
02579       if (!strcmp(ast_get_context_name(c), context)) {
02580          int ret;
02581          /* remove include from this context ... */   
02582          ret = ast_context_remove_include2(c, include, registrar);
02583 
02584          ast_unlock_contexts();
02585 
02586          /* ... return results */
02587          return ret;
02588       }
02589       c = ast_walk_contexts(c);
02590    }
02591 
02592    /* we can't find the right one context */
02593    ast_unlock_contexts();
02594    return -1;
02595 }

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

See add_include2

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

02606 {
02607    struct ast_include *i, *pi = NULL;
02608 
02609    if (ast_mutex_lock(&con->lock)) return -1;
02610 
02611    /* walk includes */
02612    i = con->includes;
02613    while (i) {
02614       /* find our include */
02615       if (!strcmp(i->name, include) && 
02616          (!registrar || !strcmp(i->registrar, registrar))) {
02617          /* remove from list */
02618          if (pi)
02619             pi->next = i->next;
02620          else
02621             con->includes = i->next;
02622          /* free include and return */
02623          free(i);
02624          ast_mutex_unlock(&con->lock);
02625          return 0;
02626       }
02627       pi = i;
02628       i = i->next;
02629    }
02630 
02631    /* we can't find the right include */
02632    ast_mutex_unlock(&con->lock);
02633    return -1;
02634 }

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

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

02642 {
02643    struct ast_context *c;
02644 
02645    if (ast_lock_contexts()) return -1;
02646 
02647    /* walk contexts and search for the right one ...*/
02648    c = ast_walk_contexts(NULL);
02649    while (c) {
02650       /* we found one ... */
02651       if (!strcmp(ast_get_context_name(c), context)) {
02652          int ret;
02653          /* remove switch from this context ... */ 
02654          ret = ast_context_remove_switch2(c, sw, data, registrar);
02655 
02656          ast_unlock_contexts();
02657 
02658          /* ... return results */
02659          return ret;
02660       }
02661       c = ast_walk_contexts(c);
02662    }
02663 
02664    /* we can't find the right one context */
02665    ast_unlock_contexts();
02666    return -1;
02667 }

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

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

int ast_context_verify_includes struct ast_context con  ) 
 

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

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

06391 {
06392    struct ast_include *inc;
06393    int res = 0;
06394 
06395    for (inc = ast_walk_context_includes(con, NULL); inc; inc = ast_walk_context_includes(con, inc))
06396       if (!ast_context_find(inc->rname)) {
06397          res = -1;
06398          ast_log(LOG_WARNING, "Context '%s' tries includes nonexistent context '%s'\n",
06399                ast_get_context_name(con), inc->rname);
06400       }
06401    return res;
06402 }

struct ast_custom_function* ast_custom_function_find char *  name  ) 
 

Definition at line 1256 of file pbx.c.

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

01257 {
01258    struct ast_custom_function *acfptr;
01259 
01260    /* try to lock functions list ... */
01261    if (ast_mutex_lock(&acflock)) {
01262       ast_log(LOG_ERROR, "Unable to lock function list\n");
01263       return NULL;
01264    }
01265 
01266    for (acfptr = acf_root; acfptr; acfptr = acfptr->next) {
01267       if (!strcmp(name, acfptr->name)) {
01268          break;
01269       }
01270    }
01271 
01272    ast_mutex_unlock(&acflock);
01273    
01274    return acfptr;
01275 }

int ast_custom_function_register struct ast_custom_function acf  ) 
 

Definition at line 1312 of file pbx.c.

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

Referenced by load_module().

01313 {
01314    if (!acf)
01315       return -1;
01316 
01317    /* try to lock functions list ... */
01318    if (ast_mutex_lock(&acflock)) {
01319       ast_log(LOG_ERROR, "Unable to lock function list. Failed registering function %s\n", acf->name);
01320       return -1;
01321    }
01322 
01323    if (ast_custom_function_find(acf->name)) {
01324       ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name);
01325       ast_mutex_unlock(&acflock);
01326       return -1;
01327    }
01328 
01329    acf->next = acf_root;
01330    acf_root = acf;
01331 
01332    ast_mutex_unlock(&acflock);
01333 
01334    if (option_verbose > 1)
01335       ast_verbose(VERBOSE_PREFIX_2 "Registered custom function %s\n", acf->name);
01336 
01337    return 0;
01338 }

int ast_custom_function_unregister struct ast_custom_function acf  ) 
 

Definition at line 1277 of file pbx.c.

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

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

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

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

Definition at line 2221 of file pbx.c.

References HELPER_EXEC, and pbx_extension_helper().

Referenced by loopback_exec().

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

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

Parameters:
c this is not important
context which context to look in
exten which extension to search for
priority priority of the action within the extension
callerid callerid to search for If an extension within the given context(or callerid) with the given priority is found a non zero value will be returned. Otherwise, 0 is returned.

Definition at line 2191 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_tx2ast_frm(), monitor_handle_notowned(), monitor_handle_owned(), parkandannounce_exec(), pbx_builtin_waitexten(), phone_check_exception(), register_peer_exten(), rpt(), rpt_exec(), skinny_ss(), socket_read(), ss_thread(), and zt_read().

02192 {
02193    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, HELPER_EXISTS);
02194 }

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

Definition at line 4510 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_async_goto(), ast_parseable_goto(), builtin_atxfer(), disa_exec(), and handle_setpriority().

04511 {
04512    if (!chan)
04513       return -1;
04514 
04515    if (!ast_strlen_zero(context))
04516       ast_copy_string(chan->context, context, sizeof(chan->context));
04517    if (!ast_strlen_zero(exten))
04518       ast_copy_string(chan->exten, exten, sizeof(chan->exten));
04519    if (priority > -1) {
04520       chan->priority = priority;
04521       /* see flag description in channel.h for explanation */
04522       if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP))
04523          chan->priority--;
04524    }
04525    
04526    return 0;
04527 }

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

Definition at line 706 of file pbx.c.

References ast_strlen_zero(), and EXTENSION_MATCH_CORE.

Referenced by pbx_find_extension(), and realtime_switch_common().

00707 {
00708    int match;
00709    /* If "data" is longer, it can'be a subset of pattern unless
00710       pattern is a pattern match */
00711    if ((strlen(pattern) < strlen(data)) && (pattern[0] != '_'))
00712       return 0;
00713    
00714    if ((ast_strlen_zero((char *)data) || !strncasecmp(pattern, data, strlen(data))) && 
00715       (!needmore || (strlen(pattern) > strlen(data)))) {
00716       return 1;
00717    }
00718    EXTENSION_MATCH_CORE(data,pattern,match);
00719    /* If there's more or we don't care about more, or if it's a possible early match, 
00720       return non-zero; otherwise it's a miss */
00721    if (!needmore || *pattern || match == 2) {
00722       return match;
00723    } else
00724       return 0;
00725 }

int ast_extension_match const char *  pattern,
const char *  extension
 

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

Definition at line 693 of file pbx.c.

References EXTENSION_MATCH_CORE.

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

00694 {
00695    int match;
00696    /* If they're the same return */
00697    if (!strcmp(pattern, data))
00698       return 1;
00699    EXTENSION_MATCH_CORE(data,pattern,match);
00700    /* Must be at the end of both */
00701    if (*data || (*pattern && (*pattern != '/')))
00702       match = 0;
00703    return match;
00704 }

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

ast_extension_state: Check extension state for an extension by using hint

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

Definition at line 1863 of file pbx.c.

References ast_extension_state2(), and ast_hint_extension().

Referenced by action_extensionstate(), and handle_request_subscribe().

01864 {
01865    struct ast_exten *e;
01866 
01867    e = ast_hint_extension(c, context, exten);   /* Do we have a hint for this extension ? */ 
01868    if (!e) 
01869       return -1;           /* No hint, return -1 */
01870 
01871    return ast_extension_state2(e);        /* Check all devices in the hint */
01872 }

int ast_extension_state2 struct ast_exten e  )  [static]
 

ast_extensions_state2: Check state of extension by using hints

Definition at line 1776 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_INUSE, and ast_get_extension_app().

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

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

const char* ast_extension_state2str int  extension_state  ) 
 

ast_extension_state2str: Return extension_state as string

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

Definition at line 1850 of file pbx.c.

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

01851 {
01852    int i;
01853 
01854    for (i = 0; (i < (sizeof(extension_states) / sizeof(extension_states[0]))); i++) {
01855       if (extension_states[i].extension_state == extension_state) {
01856          return extension_states[i].text;
01857       }
01858    }
01859    return "Unknown"; 
01860 }

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

ast_extension_state_add: Add watcher for extension states

Parameters:
context which context to look in
exten which extension to get state
callback callback to call if state changed
data to pass to callback The callback is called if the state for extension is changed Return -1 on failure, ID on success

Definition at line 1917 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, malloc, ast_state_cb::next, ast_hint::next, statecbs, and stateid.

Referenced by handle_request_subscribe(), and init_manager().

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

int ast_extension_state_del int  id,
ast_state_cb_type  callback
 

ast_extension_state_del: Remove a watcher from the callback list

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

Definition at line 2000 of file pbx.c.

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

Referenced by __sip_destroy().

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

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

Parameters:
c this is not important
context which context to look in
exten which extension to search for
label label of the action within the extension to match to priority
callerid callerid to search for If an priority which matches given label in extension or -1 if not found. \

Definition at line 2196 of file pbx.c.

References HELPER_FINDLABEL, and pbx_extension_helper().

Referenced by ast_parseable_goto(), and handle_setpriority().

02197 {
02198    return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, HELPER_FINDLABEL);
02199 }

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

Definition at line 2201 of file pbx.c.

References HELPER_FINDLABEL, and pbx_extension_helper().

Referenced by pbx_load_module().

02202 {
02203    return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, HELPER_FINDLABEL);
02204 }

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

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

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

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

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

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

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

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

const char* ast_get_context_name struct ast_context con  ) 
 

Definition at line 6246 of file pbx.c.

References ast_context::name.

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

06247 {
06248    return con ? con->name : NULL;
06249 }

const char* ast_get_context_registrar struct ast_context c  ) 
 

Definition at line 6279 of file pbx.c.

References ast_context::registrar.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06280 {
06281    return c ? c->registrar : NULL;
06282 }

const char* ast_get_extension_app struct ast_exten e  ) 
 

Definition at line 6309 of file pbx.c.

References ast_exten::app.

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

06310 {
06311    return e ? e->app : NULL;
06312 }

void* ast_get_extension_app_data struct ast_exten e  ) 
 

Definition at line 6314 of file pbx.c.

References ast_exten::data.

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

06315 {
06316    return e ? e->data : NULL;
06317 }

const char* ast_get_extension_cidmatch struct ast_exten e  ) 
 

Definition at line 6304 of file pbx.c.

References ast_exten::cidmatch.

Referenced by find_matching_priority(), and handle_save_dialplan().

06305 {
06306    return e ? e->cidmatch : NULL;
06307 }

const char* ast_get_extension_label struct ast_exten exten  ) 
 

Definition at line 6256 of file pbx.c.

References ast_exten::label.

Referenced by show_dialplan_helper().

06257 {
06258    return exten ? exten->label : NULL;
06259 }

int ast_get_extension_matchcid struct ast_exten e  ) 
 

Definition at line 6299 of file pbx.c.

References ast_exten::matchcid.

Referenced by find_matching_priority(), and handle_save_dialplan().

06300 {
06301    return e ? e->matchcid : 0;
06302 }

const char* ast_get_extension_name struct ast_exten exten  ) 
 

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

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

int ast_get_extension_priority struct ast_exten exten  ) 
 

Definition at line 6271 of file pbx.c.

References ast_exten::priority.

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

06272 {
06273    return exten ? exten->priority : -1;
06274 }

const char* ast_get_extension_registrar struct ast_exten e  ) 
 

Definition at line 6284 of file pbx.c.

References ast_exten::registrar.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06285 {
06286    return e ? e->registrar : NULL;
06287 }

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

ast_get_hint: Get hint for channel

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

Definition at line 2172 of file pbx.c.

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

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

02173 {
02174    struct ast_exten *e;
02175    void *tmp;
02176 
02177    e = ast_hint_extension(c, context, exten);
02178    if (e) {
02179       if (hint) 
02180           ast_copy_string(hint, ast_get_extension_app(e), hintsize);
02181       if (name) {
02182          tmp = ast_get_extension_app_data(e);
02183          if (tmp)
02184             ast_copy_string(name, (char *) tmp, namesize);
02185       }
02186        return -1;
02187    }
02188    return 0;   
02189 }

const char* ast_get_ignorepat_name struct ast_ignorepat ip  ) 
 

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

06267 {
06268    return ip ? ip->pattern : NULL;
06269 }

const char* ast_get_ignorepat_registrar struct ast_ignorepat ip  ) 
 

Definition at line 6294 of file pbx.c.

References ast_ignorepat::registrar.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06295 {
06296    return ip ? ip->registrar : NULL;
06297 }

const char* ast_get_include_name struct ast_include inc  ) 
 

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

06262 {
06263    return inc ? inc->name : NULL;
06264 }

const char* ast_get_include_registrar struct ast_include i  ) 
 

Definition at line 6289 of file pbx.c.

References ast_include::registrar.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06290 {
06291    return i ? i->registrar : NULL;
06292 }

const char* ast_get_switch_data struct ast_sw sw  ) 
 

Definition at line 6324 of file pbx.c.

References ast_sw::data.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

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

const char* ast_get_switch_name struct ast_sw sw  ) 
 

Definition at line 6319 of file pbx.c.

References ast_sw::name.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

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

const char* ast_get_switch_registrar struct ast_sw sw  ) 
 

Definition at line 6329 of file pbx.c.

References ast_sw::registrar.

Referenced by handle_save_dialplan(), and show_dialplan_helper().

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

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

Definition at line 6422 of file pbx.c.

References __ast_goto_if_exists().

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

06422                                                                                            {
06423    return __ast_goto_if_exists(chan, context, exten, priority, 0);
06424 }

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

ast_hint_extension: Find hint for given extension in context

Definition at line 1756 of file pbx.c.

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

01757 {
01758    struct ast_exten *e;
01759    struct ast_switch *sw;
01760    char *data;
01761    const char *foundcontext = NULL;
01762    int status = 0;
01763    char *incstack[AST_PBX_MAX_STACK];
01764    int stacklen = 0;
01765 
01766    if (ast_mutex_lock(&conlock)) {
01767       ast_log(LOG_WARNING, "Unable to obtain lock\n");
01768       return NULL;
01769    }
01770    e = pbx_find_extension(c, NULL, context, exten, PRIORITY_HINT, NULL, "", HELPER_EXISTS, incstack, &stacklen, &status, &sw, &data, &foundcontext);
01771    ast_mutex_unlock(&conlock);   
01772    return e;
01773 }

void ast_hint_state_changed const char *  device  ) 
 

Definition at line 1874 of file pbx.c.

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

Referenced by do_state_change().

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

int ast_ignore_pattern const char *  context,
const char *  pattern
 

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

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

04463 {
04464    struct ast_context *con;
04465    struct ast_ignorepat *pat;
04466 
04467    con = ast_context_find(context);
04468    if (con) {
04469       pat = con->ignorepats;
04470       while (pat) {
04471          if (ast_extension_match(pat->pattern, pattern))
04472             return 1;
04473          pat = pat->next;
04474       }
04475    } 
04476    return 0;
04477 }

AST_LIST_HEAD store_hints  ,
store_hint 
 

int ast_lock_context struct ast_context con  ) 
 

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

Definition at line 6233 of file pbx.c.

References ast_mutex_lock(), and ast_context::lock.

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

06234 {
06235    return ast_mutex_lock(&con->lock);
06236 }

int ast_lock_contexts void   ) 
 

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

Definition at line 6220 of file pbx.c.

References ast_mutex_lock().

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

06221 {
06222    return ast_mutex_lock(&conlock);
06223 }

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

Parameters:
c not really important
context context to serach within
exten extension to check
priority priority of extension path
callerid callerid of extension being searched for If "exten" *could match* a valid extension in this context with some more digits, return non-zero. Does NOT return non-zero if this is an exact-match only. Basically, when this returns 0, no matter what you add to exten, it's not going to be a valid extension anymore

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

02212 {
02213    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, HELPER_MATCHMORE);
02214 }

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

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

Definition at line 3687 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, ast_hint::callbacks, calloc, contexts, ast_state_cb::data, ast_hint::exten, ast_exten::exten, free, ast_hint::laststate, LOG_WARNING, ast_context::name, ast_hint::next, ast_context::next, ast_state_cb::next, ast_exten::parent, and ast_context::registrar.

Referenced by pbx_load_module().

03688 {
03689    struct ast_context *tmp, *lasttmp = NULL;
03690    struct store_hints store;
03691    struct store_hint *this;
03692    struct ast_hint *hint;
03693    struct ast_exten *exten;
03694    int length;
03695    struct ast_state_cb *thiscb, *prevcb;
03696 
03697    /* preserve all watchers for hints associated with this registrar */
03698    AST_LIST_HEAD_INIT(&store);
03699    ast_mutex_lock(&hintlock);
03700    for (hint = hints; hint; hint = hint->next) {
03701       if (hint->callbacks && !strcmp(registrar, hint->exten->parent->registrar)) {
03702          length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2 + sizeof(*this);
03703          this = calloc(1, length);
03704          if (!this) {
03705             ast_log(LOG_WARNING, "Could not allocate memory to preserve hint\n");
03706             continue;
03707          }
03708          this->callbacks = hint->callbacks;
03709          hint->callbacks = NULL;
03710          this->laststate = hint->laststate;
03711          this->context = this->data;
03712          strcpy(this->data, hint->exten->parent->name);
03713          this->exten = this->data + strlen(this->context) + 1;
03714          strcpy(this->exten, hint->exten->exten);
03715          AST_LIST_INSERT_HEAD(&store, this, list);
03716       }
03717    }
03718    ast_mutex_unlock(&hintlock);
03719 
03720    tmp = *extcontexts;
03721    ast_mutex_lock(&conlock);
03722    if (registrar) {
03723       __ast_context_destroy(NULL,registrar);
03724       while (tmp) {
03725          lasttmp = tmp;
03726          tmp = tmp->next;
03727       }
03728    } else {
03729       while (tmp) {
03730          __ast_context_destroy(tmp,tmp->registrar);
03731          lasttmp = tmp;
03732          tmp = tmp->next;
03733       }
03734    }
03735    if (lasttmp) {
03736       lasttmp->next = contexts;
03737       contexts = *extcontexts;
03738       *extcontexts = NULL;
03739    } else 
03740       ast_log(LOG_WARNING, "Requested contexts didn't get merged\n");
03741    ast_mutex_unlock(&conlock);
03742 
03743    /* restore the watchers for hints that can be found; notify those that
03744       cannot be restored
03745    */
03746    while ((this = AST_LIST_REMOVE_HEAD(&store, list))) {
03747       exten = ast_hint_extension(NULL, this->context, this->exten);
03748       /* Find the hint in the list of hints */
03749       ast_mutex_lock(&hintlock);
03750       for (hint = hints; hint; hint = hint->next) {
03751          if (hint->exten == exten)
03752             break;
03753       }
03754       if (!exten || !hint) {
03755          /* this hint has been removed, notify the watchers */
03756          prevcb = NULL;
03757          thiscb = this->callbacks;
03758          while (thiscb) {
03759             prevcb = thiscb;      
03760             thiscb = thiscb->next;
03761             prevcb->callback(this->context, this->exten, AST_EXTENSION_REMOVED, prevcb->data);
03762             free(prevcb);
03763             }
03764       } else {
03765          thiscb = this->callbacks;
03766          while (thiscb->next)
03767             thiscb = thiscb->next;
03768          thiscb->next = hint->callbacks;
03769          hint->callbacks = this->callbacks;
03770          hint->laststate = this->laststate;
03771       }
03772       ast_mutex_unlock(&hintlock);
03773       free(this);
03774    }
03775 
03776    return;  
03777 }

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   ) 
 

int ast_parseable_goto struct ast_channel chan,
const char *  goto_string
 

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

06431 {
06432    char *s;
06433    char *exten, *pri, *context;
06434    char *stringp=NULL;
06435    int ipri;
06436    int mode = 0;
06437 
06438    if (ast_strlen_zero(goto_string)) {
06439       ast_log(LOG_WARNING, "Goto requires an argument (optional context|optional extension|priority)\n");
06440       return -1;
06441    }
06442    s = ast_strdupa(goto_string);
06443    stringp=s;
06444    context = strsep(&stringp, "|");
06445    exten = strsep(&stringp, "|");
06446    if (!exten) {
06447       /* Only a priority in this one */
06448       pri = context;
06449       exten = NULL;
06450       context = NULL;
06451    } else {
06452       pri = strsep(&stringp, "|");
06453       if (!pri) {
06454          /* Only an extension and priority in this one */
06455          pri = exten;
06456          exten = context;
06457          context = NULL;
06458       }
06459    }
06460    if (*pri == '+') {
06461       mode = 1;
06462       pri++;
06463    } else if (*pri == '-') {
06464       mode = -1;
06465       pri++;
06466    }
06467    if (sscanf(pri, "%d", &ipri) != 1) {
06468       if ((ipri = ast_findlabel_extension(chan, context ? context : chan->context, (exten && strcasecmp(exten, "BYEXTENSION")) ? exten : chan->exten, 
06469          pri, chan->cid.cid_num)) < 1) {
06470          ast_log(LOG_WARNING, "Priority '%s' must be a number > 0, or valid label\n", pri);
06471          return -1;
06472       } else
06473          mode = 0;
06474    } 
06475    /* At this point we have a priority and maybe an extension and a context */
06476 
06477    if (exten && !strcasecmp(exten, "BYEXTENSION"))
06478       exten = NULL;
06479 
06480    if (mode) 
06481       ipri = chan->priority + (ipri * mode);
06482 
06483    ast_explicit_goto(chan, context, exten, ipri);
06484    ast_cdr_update(chan);
06485    return 0;
06486 
06487 }

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

References __ast_request_and_dial(), ast_channel::_state, app_tmp::app, async_stat::app, async_stat::appdata, ast_cdr_alloc(), ast_cdr_disposition(), ast_cdr_failed(), ast_cdr_init(), ast_cdr_setaccount(), ast_cdr_start(), ast_hangup(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pbx_outgoing_cdr_failed(), ast_pbx_run_app(), ast_pthread_create, ast_set_variables(), ast_strlen_zero(), ast_variables_destroy(), ast_verbose(), async_wait(), ast_channel::cdr, app_tmp::chan, async_stat::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, type, outgoing_helper::vars, and VERBOSE_PREFIX_4.

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

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

int ast_pbx_outgoing_cdr_failed void   ) 
 

Function to update the cdr after a spool call fails.

This function updates the cdr for a failed spool call and takes the channel of the failed call as an argument.

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

04931 {
04932    /* allocate a channel */
04933    struct ast_channel *chan = ast_channel_alloc(0);
04934    if(!chan) {
04935       /* allocation of the channel failed, let some peeps know */
04936       ast_log(LOG_WARNING, "Unable to allocate channel structure for CDR record\n");
04937       return -1;  /* failure */
04938    }
04939 
04940    chan->cdr = ast_cdr_alloc();   /* allocate a cdr for the channel */
04941 
04942    if(!chan->cdr) {
04943       /* allocation of the cdr failed */
04944       ast_log(LOG_WARNING, "Unable to create Call Detail Record\n");
04945       ast_channel_free(chan);   /* free the channel */
04946       return -1;                /* return failure */
04947    }
04948    
04949    /* allocation of the cdr was successful */
04950    ast_cdr_init(chan->cdr, chan);  /* initilize our channel's cdr */
04951    ast_cdr_start(chan->cdr);       /* record the start and stop time */
04952    ast_cdr_end(chan->cdr);
04953    ast_cdr_failed(chan->cdr);      /* set the status to failed */
04954    ast_cdr_detach(chan->cdr);      /* post and free the record */
04955    ast_channel_free(chan);         /* free the channel */
04956    
04957    return 0;  /* success */
04958 }

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 4960 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_strlen_zero(), ast_variables_destroy(), ast_verbose(), async_wait(), ast_channel::cdr, async_stat::chan, ast_channel::context, async_stat::context, ast_channel::exten, async_stat::exten, free, ast_channel::hangupcause, LOAD_OH, ast_channel::lock, LOG_ERROR, LOG_WARNING, malloc, ast_channel::name, option_verbose, async_stat::p, ast_channel::pbx, ast_channel::priority, async_stat::priority, async_stat::timeout, type, and VERBOSE_PREFIX_4.

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

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

enum ast_pbx_result ast_pbx_run struct ast_channel c  ) 
 

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

Definition at line 2537 of file pbx.c.

References __ast_pbx_run(), ast_pbx_result, decrease_call_count(), and increase_call_count().

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

02538 {
02539    enum ast_pbx_result res = AST_PBX_SUCCESS;
02540 
02541    if (increase_call_count(c))
02542       return AST_PBX_CALL_LIMIT;
02543 
02544    res = __ast_pbx_run(c);
02545    decrease_call_count();
02546 
02547    return res;
02548 }

void* ast_pbx_run_app void *  data  )  [static]
 

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

05113 {
05114    struct app_tmp *tmp = data;
05115    struct ast_app *app;
05116    app = pbx_findapp(tmp->app);
05117    if (app) {
05118       if (option_verbose > 3)
05119          ast_verbose(VERBOSE_PREFIX_4 "Launching %s(%s) on %s\n", tmp->app, tmp->data, tmp->chan->name);
05120       pbx_exec(tmp->chan, app, tmp->data, 1);
05121    } else
05122       ast_log(LOG_WARNING, "No such application '%s'\n", tmp->app);
05123    ast_hangup(tmp->chan);
05124    free(tmp);
05125    return NULL;
05126 }

enum ast_pbx_result ast_pbx_start struct ast_channel c  ) 
 

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

Definition at line 2513 of file pbx.c.

References ast_log(), ast_pbx_result, ast_pthread_create, increase_call_count(), LOG_WARNING, and pbx_thread().

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

02514 {
02515    pthread_t t;
02516    pthread_attr_t attr;
02517 
02518    if (!c) {
02519       ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
02520       return AST_PBX_FAILED;
02521    }
02522       
02523    if (increase_call_count(c))
02524       return AST_PBX_CALL_LIMIT;
02525 
02526    /* Start a new thread, and get something handling this channel. */
02527    pthread_attr_init(&attr);
02528    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
02529    if (ast_pthread_create(&t, &attr, pbx_thread, c)) {
02530       ast_log(LOG_WARNING, "Failed to create new channel thread\n");
02531       return AST_PBX_FAILED;
02532    }
02533 
02534    return AST_PBX_SUCCESS;
02535 }

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

Dynamically register a new dial plan application.

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

Definition at line 2854 of file pbx.c.

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

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

int ast_register_switch struct ast_switch sw  ) 
 

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

Definition at line 2908 of file pbx.c.

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

Referenced by load_module().

02909 {
02910    struct ast_switch *tmp, *prev=NULL;
02911    if (ast_mutex_lock(&switchlock)) {
02912       ast_log(LOG_ERROR, "Unable to lock switch lock\n");
02913       return -1;
02914    }
02915    tmp = switches;
02916    while(tmp) {
02917       if (!strcasecmp(tmp->name, sw->name))
02918          break;
02919       prev = tmp;
02920       tmp = tmp->next;
02921    }
02922    if (tmp) {  
02923       ast_mutex_unlock(&switchlock);
02924       ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name);
02925       return -1;
02926    }
02927    sw->next = NULL;
02928    if (prev) 
02929       prev->next = sw;
02930    else
02931       switches = sw;
02932    ast_mutex_unlock(&switchlock);
02933    return 0;
02934 }

int ast_remove_hint struct ast_exten e  )  [static]
 

ast_remove_hint: Remove hint from extension

Definition at line 2127 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, hints, ast_context::name, ast_hint::next, ast_state_cb::next, and ast_exten::parent.

Referenced by ast_context_remove_extension2(), and destroy_exten().

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

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

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

Definition at line 2216 of file pbx.c.

References HELPER_SPAWN, and pbx_extension_helper().

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

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

int ast_unlock_context struct ast_context con  ) 
 

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

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

06239 {
06240    return ast_mutex_unlock(&con->lock);
06241 }

int ast_unlock_contexts void   ) 
 

Returns 0 on success, -1 on failure

Definition at line 6225 of file pbx.c.

References ast_mutex_unlock().

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

06226 {
06227    return ast_mutex_unlock(&conlock);
06228 }

int ast_unregister_application const char *  app  ) 
 

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

Definition at line 3601 of file pbx.c.

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

Referenced by __unload_module(), and unload_module().

03602 {
03603    struct ast_app *tmp, *tmpl = NULL;
03604    if (ast_mutex_lock(&applock)) {
03605       ast_log(LOG_ERROR, "Unable to lock application list\n");
03606       return -1;
03607    }
03608    tmp = apps;
03609    while(tmp) {
03610       if (!strcasecmp(app, tmp->name)) {
03611          if (tmpl)
03612             tmpl->next = tmp->next;
03613          else
03614             apps = tmp->next;
03615          if (option_verbose > 1)
03616             ast_verbose( VERBOSE_PREFIX_2 "Unregistered application '%s'\n", tmp->name);
03617          free(tmp);
03618          ast_mutex_unlock(&applock);
03619          return 0;
03620       }
03621       tmpl = tmp;
03622       tmp = tmp->next;
03623    }
03624    ast_mutex_unlock(&applock);
03625    return -1;
03626 }

void ast_unregister_switch struct ast_switch sw  ) 
 

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

Definition at line 2936 of file pbx.c.

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

Referenced by __unload_module(), and unload_module().

02937 {
02938    struct ast_switch *tmp, *prev=NULL;
02939    if (ast_mutex_lock(&switchlock)) {
02940       ast_log(LOG_ERROR, "Unable to lock switch lock\n");
02941       return;
02942    }
02943    tmp = switches;
02944    while(tmp) {
02945       if (tmp == sw) {
02946          if (prev)
02947             prev->next = tmp->next;
02948          else
02949             switches = tmp->next;
02950          tmp->next = NULL;
02951          break;         
02952       }
02953       prev = tmp;
02954       tmp = tmp->next;
02955    }
02956    ast_mutex_unlock(&switchlock);
02957 }

struct ast_exten* ast_walk_context_extensions struct ast_context con,
struct ast_exten exten
 

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

06347 {
06348    if (!exten)
06349       return con ? con->root : NULL;
06350    else
06351       return exten->next;
06352 }

struct ast_ignorepat* ast_walk_context_ignorepats struct ast_context con,
struct ast_ignorepat ip
 

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

06383 {
06384    if (!ip)
06385       return con ? con->ignorepats : NULL;
06386    else
06387       return ip->next;
06388 }

struct ast_include* ast_walk_context_includes struct ast_context con,
struct ast_include inc
 

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

06374 {
06375    if (!inc)
06376       return con ? con->includes : NULL;
06377    else
06378       return inc->next;
06379 }

struct ast_sw* ast_walk_context_switches struct ast_context con,
struct ast_sw sw
 

Definition at line 6354 of file pbx.c.

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

Referenced by handle_save_dialplan(), and show_dialplan_helper().

06356 {
06357    if (!sw)
06358       return con ? con->alts : NULL;
06359    else
06360       return sw->next;
06361 }

struct ast_context* ast_walk_contexts struct ast_context con  ) 
 

Definition at line 6337 of file pbx.c.

References ast_context::next.

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

06338 {
06339    if (!con)
06340       return contexts;
06341    else
06342       return con->next;
06343 }

struct ast_exten* ast_walk_extension_priorities struct ast_exten exten,
struct ast_exten priority
 

Definition at line 6363 of file pbx.c.

References ast_exten::peer.

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

06365 {
06366    if (!priority)
06367       return exten;
06368    else
06369       return priority->peer;
06370 }

void* async_wait void *  data  )  [static]
 

Definition at line 4867 of file pbx.c.

References ast_channel::_state, async_stat::app, async_stat::appdata, ast_frfree(), ast_hangup(), ast_log(), ast_pbx_run(), ast_read(), 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().

04868 {
04869    struct async_stat *as = data;
04870    struct ast_channel *chan = as->chan;
04871    int timeout = as->timeout;
04872    int res;
04873    struct ast_frame *f;
04874    struct ast_app *app;
04875    
04876    while(timeout && (chan->_state != AST_STATE_UP)) {
04877       res = ast_waitfor(chan, timeout);
04878       if (res < 1) 
04879          break;
04880       if (timeout > -1)
04881          timeout = res;
04882       f = ast_read(chan);
04883       if (!f)
04884          break;
04885       if (f->frametype == AST_FRAME_CONTROL) {
04886          if ((f->subclass == AST_CONTROL_BUSY)  ||
04887             (f->subclass == AST_CONTROL_CONGESTION) )
04888                break;
04889       }
04890       ast_frfree(f);
04891    }
04892    if (chan->_state == AST_STATE_UP) {
04893       if (!ast_strlen_zero(as->app)) {
04894          app = pbx_findapp(as->app);
04895          if (app) {
04896             if (option_verbose > 2)
04897                ast_verbose(VERBOSE_PREFIX_3 "Launching %s(%s) on %s\n", as->app, as->appdata, chan->name);
04898             pbx_exec(chan, app, as->appdata, 1);
04899          } else
04900             ast_log(LOG_WARNING, "No such application '%s'\n", as->app);
04901       } else {
04902          if (!ast_strlen_zero(as->context))
04903             ast_copy_string(chan->context, as->context, sizeof(chan->context));
04904          if (!ast_strlen_zero(as->exten))
04905             ast_copy_string(chan->exten, as->exten, sizeof(chan->exten));
04906          if (as->priority > 0)
04907             chan->priority = as->priority;
04908          /* Run the PBX */
04909          if (ast_pbx_run(chan)) {
04910             ast_log(LOG_ERROR, "Failed to start PBX on %s\n", chan->name);
04911          } else {
04912             /* PBX will have taken care of this */
04913             chan = NULL;
04914          }
04915       }
04916          
04917    }
04918    free(as);
04919    if (chan)
04920       ast_hangup(chan);
04921    return NULL;
04922 }

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

Definition at line 3007 of file pbx.c.

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

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

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

Definition at line 3254 of file pbx.c.

References ast_strlen_zero(), and strdup.

03255 {
03256    if (pos == 2) {
03257       if (ast_strlen_zero(word)) {
03258          switch (state) {
03259          case 0:
03260             return strdup("like");
03261          case 1:
03262             return strdup("describing");
03263          default:
03264             return NULL;
03265          }
03266       } else if (! strncasecmp(word, "like", strlen(word))) {
03267          if (state == 0) {
03268             return strdup("like");
03269          } else {
03270             return NULL;
03271          }
03272       } else if (! strncasecmp(word, "describing", strlen(word))) {
03273          if (state == 0) {
03274             return strdup("describing");
03275          } else {
03276             return NULL;
03277          }
03278       }
03279    }
03280    return NULL;
03281 }

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

Definition at line 3286 of file pbx.c.

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

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

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

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

01230 {
01231    struct ast_custom_function *acf;
01232    int which = 0;
01233 
01234    /* try to lock functions list ... */
01235    if (ast_mutex_lock(&acflock)) {
01236       ast_log(LOG_ERROR, "Unable to lock function list\n");
01237       return NULL;
01238    }
01239 
01240    acf = acf_root;
01241    while (acf) {
01242       if (!strncasecmp(word, acf->name, strlen(word))) {
01243          if (++which > state) {
01244             char *ret = strdup(acf->name);
01245             ast_mutex_unlock(&acflock);
01246             return ret;
01247          }
01248       }
01249       acf = acf->next; 
01250    }
01251 
01252    ast_mutex_unlock(&acflock);
01253    return NULL; 
01254 }

void decrease_call_count void   )  [static]
 

Definition at line 2485 of file pbx.c.

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

Referenced by ast_pbx_run(), and pbx_thread().

02486 {
02487    ast_mutex_lock(&maxcalllock);
02488    if (countcalls > 0)
02489       countcalls--;
02490    ast_mutex_unlock(&maxcalllock);
02491 }

void destroy_exten struct ast_exten e  )  [static]
 

Definition at line 5273 of file pbx.c.

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

Referenced by __ast_context_destroy().

05274 {
05275    if (e->priority == PRIORITY_HINT)
05276       ast_remove_hint(e);
05277 
05278    if (e->datad)
05279       e->datad(e->data);
05280    free(e);
05281 }

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

Definition at line 4591 of file pbx.c.

Referenced by ast_add_extension2().

04592 {
04593    int count=0;
04594 
04595    while(*src && (count < len - 1)) {
04596       switch(*src) {
04597       case ' ':
04598          /* otherwise exten => [a-b],1,... doesn't work */
04599          /*    case '-': */
04600          /* Ignore */
04601          break;
04602       default:
04603          *dst = *src;
04604          dst++;
04605       }
04606       src++;
04607       count++;
04608    }
04609    *dst = '\0';
04610 
04611    return count;
04612 }

unsigned int get_day char *  day  )  [static]
 

Definition at line 3957 of file pbx.c.

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

Referenced by ast_build_timing().

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

unsigned int get_dow char *  dow  )  [static]
 

get_dow: Get day of week

Definition at line 3915 of file pbx.c.

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

Referenced by ast_build_timing().

03916 {
03917    char *c;
03918    /* The following line is coincidence, really! */
03919    int s, e, x;
03920    unsigned int mask;
03921 
03922    /* Check for all days */
03923    if (ast_strlen_zero(dow) || !strcmp(dow, "*"))
03924       return (1 << 7) - 1;
03925    /* Get start and ending days */
03926    c = strchr(dow, '-');
03927    if (c) {
03928       *c = '\0';
03929       c++;
03930    } else
03931       c = NULL;
03932    /* Find the start */
03933    s = 0;
03934    while((s < 7) && strcasecmp(dow, days[s])) s++;
03935    if (s >= 7) {
03936       ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", dow);
03937       return 0;
03938    }
03939    if (c) {
03940       e = 0;
03941       while((e < 7) && strcasecmp(c, days[e])) e++;
03942       if (e >= 7) {
03943          ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", c);
03944          return 0;
03945       }
03946    } else
03947       e = s;
03948    mask = 0;
03949    for (x=s; x != e; x = (x + 1) % 7) {
03950       mask |= (1 << x);
03951    }
03952    /* One last one */
03953    mask |= (1 << x);
03954    return mask;
03955 }

unsigned int get_month char *  mon  )  [static]
 

Definition at line 4021 of file pbx.c.

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

Referenced by ast_build_timing().

04022 {
04023    char *c;
04024    /* The following line is coincidence, really! */
04025    int s, e, x;
04026    unsigned int mask;
04027 
04028    /* Check for all days */
04029    if (ast_strlen_zero(mon) || !strcmp(mon, "*")) 
04030       return (1 << 12) - 1;
04031    /* Get start and ending days */
04032    c = strchr(mon, '-');
04033    if (c) {
04034       *c = '\0';
04035       c++;
04036    }
04037    /* Find the start */
04038    s = 0;
04039    while((s < 12) && strcasecmp(mon, months[s])) s++;
04040    if (s >= 12) {
04041       ast_log(LOG_WARNING, "Invalid month '%s', assuming none\n", mon);
04042       return 0;
04043    }
04044    if (c) {
04045       e = 0;
04046       while((e < 12) && strcasecmp(mon, months[e])) e++;
04047       if (e >= 12) {
04048          ast_log(LOG_WARNING, "Invalid month '%s', assuming none\n", c);
04049          return 0;
04050       }
04051    } else
04052       e = s;
04053    mask = 0;
04054    for (x=s; x!=e; x = (x + 1) % 12) {
04055       mask |= (1 << x);
04056    }
04057    /* One last one */
04058    mask |= (1 << x);
04059    return mask;
04060 }

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

Definition at line 3819 of file pbx.c.

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

Referenced by ast_build_timing().

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

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

Definition at line 3039 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, ast_app::synopsis, and term_color().

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

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

Definition at line 3177 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, strcasestr(), and ast_app::synopsis.

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

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

Definition at line 3517 of file pbx.c.

References ast_cli(), ast_strdupa, ast_strlen_zero(), show_dialplan_helper(), and strsep().

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

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

Definition at line 1174 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, ast_custom_function::synopsis, ast_custom_function::syntax, and term_color().

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

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

Definition at line 1160 of file pbx.c.

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

01161 {
01162    struct ast_custom_function *acf;
01163    int count_acf = 0;
01164 
01165    ast_cli(fd, "Installed Custom Functions:\n--------------------------------------------------------------------------------\n");
01166    for (acf = acf_root ; acf; acf = acf->next) {
01167       ast_cli(fd, "%-20.20s  %-35.35s  %s\n", acf->name, acf->syntax, acf->synopsis);
01168       count_acf++;
01169    }
01170    ast_cli(fd, "%d custom functions installed.\n", count_acf);
01171    return 0;
01172 }

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 3117 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, and ast_state_cb::next.

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

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

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

03153 {
03154    struct ast_switch *sw;
03155    if (!switches) {
03156       ast_cli(fd, "There are no registered alternative switches\n");
03157       return RESULT_SUCCESS;
03158    }
03159    /* ... we have applications ... */
03160    ast_cli(fd, "\n    -= Registered Asterisk Alternative Switches =-\n");
03161    if (ast_mutex_lock(&switchlock)) {
03162       ast_log(LOG_ERROR, "Unable to lock switches\n");
03163       return -1;
03164    }
03165    sw = switches;
03166    while (sw) {
03167       ast_cli(fd, "%s: %s\n", sw->name, sw->description);
03168       sw = sw->next;
03169    }
03170    ast_mutex_unlock(&switchlock);
03171    return RESULT_SUCCESS;
03172 }

int include_valid struct ast_include i  )  [inline, static]
 

Definition at line 603 of file pbx.c.

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

Referenced by pbx_find_extension().

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

int increase_call_count const struct ast_channel c  )  [static]
 

Definition at line 2460 of file pbx.c.

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

Referenced by ast_pbx_run(), and ast_pbx_start().

02461 {
02462    int failed = 0;
02463    double curloadavg;
02464    ast_mutex_lock(&maxcalllock);
02465    if (option_maxcalls) {
02466       if (countcalls >= option_maxcalls) {
02467          ast_log(LOG_NOTICE, "Maximum call limit of %d calls exceeded by '%s'!\n", option_maxcalls, c->name);
02468          failed = -1;
02469       }
02470    }
02471    if (option_maxload) {
02472       getloadavg(&curloadavg, 1);
02473       if (curloadavg >= option_maxload) {
02474          ast_log(LOG_NOTICE, "Maximum loadavg limit of %lf load exceeded by '%s' (currently %f)!\n", option_maxload, c->name, curloadavg);
02475          failed = -1;
02476       }
02477    }
02478    if (!failed)
02479       countcalls++;  
02480    ast_mutex_unlock(&maxcalllock);
02481 
02482    return failed;
02483 }

int load_pbx void   ) 
 

Definition at line 6193 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, pbx_cli, and VERBOSE_PREFIX_1.

Referenced by main().

06194 {
06195    int x;
06196 
06197    /* Initialize the PBX */
06198    if (option_verbose) {
06199       ast_verbose( "Asterisk PBX Core Initializing\n");
06200       ast_verbose( "Registering builtin applications:\n");
06201    }
06202    AST_LIST_HEAD_INIT_NOLOCK(&globals);
06203    ast_cli_register_multiple(pbx_cli, sizeof(pbx_cli) / sizeof(pbx_cli[0]));
06204 
06205    /* Register builtin applications */
06206    for (x=0; x<sizeof(builtins) / sizeof(struct pbx_builtin); x++) {
06207       if (option_verbose)
06208          ast_verbose( VERBOSE_PREFIX_1 "[%s]\n", builtins[x].name);
06209       if (ast_register_application(builtins[x].name, builtins[x].execute, builtins[x].synopsis, builtins[x].description)) {
06210          ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name);
06211          return -1;
06212       }
06213    }
06214    return 0;
06215 }

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

Definition at line 750 of file pbx.c.

References ast_extension_match(), and ast_strlen_zero().

Referenced by pbx_find_extension().

00751 {
00752    int failresult;
00753    
00754    /* If the Caller*ID pattern is empty, then we're matching NO Caller*ID, so
00755       failing to get a number should count as a match, otherwise not */
00756 
00757    if (!ast_strlen_zero(cidpattern))
00758       failresult = 0;
00759    else
00760       failresult = 1;
00761 
00762    if (!callerid)
00763       return failresult;
00764 
00765    return ast_extension_match(cidpattern, callerid);
00766 }

void null_datad void *  foo  )  [static]
 

Definition at line 4614 of file pbx.c.

04615 {
04616 }

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

Definition at line 896 of file pbx.c.

Referenced by pbx_retrieve_variable(), and pbx_substitute_variables_helper_full().

00897 {
00898    char *varchar, *offsetchar = NULL;
00899    int parens=0;
00900 
00901    *offset = 0;
00902    *length = DONT_HAVE_LENGTH;
00903    *isfunc = 0;
00904    for (varchar=var; *varchar; varchar++) {
00905       switch (*varchar) {
00906       case '(':
00907          (*isfunc)++;
00908          parens++;
00909          break;
00910       case ')':
00911          parens--;
00912          break;
00913       case ':':
00914          if (parens == 0) {
00915             offsetchar = varchar + 1;
00916             *varchar = '\0';
00917             goto pvn_endfor;
00918          }
00919       }
00920    }
00921 pvn_endfor:
00922    if (offsetchar) {
00923       sscanf(offsetchar, "%d:%d", offset, length);
00924       return 1;
00925    } else {
00926       return 0;
00927    }
00928 }

void pbx_builtin_clear_globals void   ) 
 

Definition at line 6083 of file pbx.c.

References AST_LIST_EMPTY, AST_LIST_REMOVE_HEAD, ast_var_delete(), and globals.

Referenced by reload().

06084 {
06085    struct ast_var_t *vardata;
06086    while (!AST_LIST_EMPTY(&globals)) {
06087       vardata = AST_LIST_REMOVE_HEAD(&globals, entries);
06088       ast_var_delete(vardata);
06089    }
06090 }

char* pbx_builtin_getvar_helper struct ast_channel chan,
const char *  name
 

Definition at line 5892 of file pbx.c.

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

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

05893 {
05894    struct ast_var_t *variables;
05895    struct varshead *headp;
05896 
05897    if (chan)
05898       headp=&chan->varshead;
05899    else
05900       headp=&globals;
05901 
05902    if (name) {
05903       AST_LIST_TRAVERSE(headp,variables,entries) {
05904          if (!strcmp(name, ast_var_name(variables)))
05905             return ast_var_value(variables);
05906       }
05907       if (headp != &globals) {
05908          /* Check global variables if we haven't already */
05909          headp = &globals;
05910          AST_LIST_TRAVERSE(headp,variables,entries) {
05911             if (!strcmp(name, ast_var_name(variables)))
05912                return ast_var_value(variables);
05913          }
05914       }
05915    }
05916    return NULL;
05917 }

int pbx_builtin_gotoif struct ast_channel ,
void * 
[static]
 

Definition at line 6111 of file pbx.c.

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

06112 {
06113    char *condition, *branch1, *branch2, *branch;
06114    char *s;
06115    int rc;
06116    char *stringp=NULL;
06117 
06118    if (ast_strlen_zero(data)) {
06119       ast_log(LOG_WARNING, "Ignoring, since there is no variable to check\n");
06120       return 0;
06121    }
06122    
06123    s = ast_strdupa(data);
06124    stringp = s;
06125    condition = strsep(&stringp,"?");
06126    branch1 = strsep(&stringp,":");
06127    branch2 = strsep(&stringp,"");
06128    branch = pbx_checkcondition(condition) ? branch1 : branch2;
06129    
06130    if (ast_strlen_zero(branch)) {
06131       ast_log(LOG_DEBUG, "Not taking any branch\n");
06132       return 0;
06133    }
06134    
06135    rc = pbx_builtin_goto(chan, branch);
06136 
06137    return rc;
06138 }           

int pbx_builtin_importvar struct ast_channel ,
void * 
[static]
 

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

06023 {
06024    char *name;
06025    char *value;
06026    char *stringp=NULL;
06027    char *channel;
06028    struct ast_channel *chan2;
06029    char tmp[VAR_BUF_SIZE]="";
06030    char *s;
06031 
06032    if (ast_strlen_zero(data)) {
06033       ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n");
06034       return 0;
06035    }
06036 
06037    stringp = ast_strdupa(data);
06038    name = strsep(&stringp,"=");
06039    channel = strsep(&stringp,"|"); 
06040    value = strsep(&stringp,"\0");
06041    if (channel && value && name) {
06042       chan2 = ast_get_channel_by_name_locked(channel);
06043       if (chan2) {
06044          s = alloca(strlen(value) + 4);
06045          if (s) {
06046             sprintf(s, "${%s}", value);
06047             pbx_substitute_variables_helper(chan2, s, tmp, sizeof(tmp) - 1);
06048          }
06049          ast_mutex_unlock(&chan2->lock);
06050       }
06051       pbx_builtin_setvar_helper(chan, name, tmp);
06052    }
06053 
06054    return(0);
06055 }

int pbx_builtin_noop struct ast_channel ,
void * 
[static]
 

Definition at line 6077 of file pbx.c.

06078 {
06079    return 0;
06080 }

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

Definition at line 5919 of file pbx.c.

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

Referenced by gosub_exec().

05920 {
05921    struct ast_var_t *newvariable;
05922    struct varshead *headp;
05923 
05924    if (name[strlen(name)-1] == ')') {
05925       ast_log(LOG_WARNING, "Cannot push a value onto a function\n");
05926       return ast_func_write(chan, name, value);
05927    }
05928 
05929    headp = (chan) ? &chan->varshead : &globals;
05930 
05931    if (value) {
05932       if ((option_verbose > 1) && (headp == &globals))
05933          ast_verbose(VERBOSE_PREFIX_2 "Setting global variable '%s' to '%s'\n", name, value);
05934       newvariable = ast_var_assign(name, value);   
05935       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
05936    }
05937 }

int pbx_builtin_saycharacters struct ast_channel ,
void * 
[static]
 

Definition at line 6175 of file pbx.c.

References ast_say_character_str(), and ast_channel::language.

06176 {
06177    int res = 0;
06178 
06179    if (data)
06180       res = ast_say_character_str(chan, (char *)data, "", chan->language);
06181    return res;
06182 }

int pbx_builtin_saydigits struct ast_channel ,
void * 
[static]
 

Definition at line 6166 of file pbx.c.

References ast_say_digit_str(), and ast_channel::language.

06167 {
06168    int res = 0;
06169 
06170    if (data)
06171       res = ast_say_digit_str(chan, (char *)data, "", chan->language);
06172    return res;
06173 }

int pbx_builtin_saynumber struct ast_channel ,
void * 
[static]
 

Definition at line 6140 of file pbx.c.

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

06141 {
06142    int res = 0;
06143    char tmp[256];
06144    char *number = (char *) NULL;
06145    char *options = (char *) NULL;
06146 
06147    
06148    if (ast_strlen_zero(data)) {
06149       ast_log(LOG_WARNING, "SayNumber requires an argument (number)\n");
06150       return -1;
06151    }
06152    ast_copy_string(tmp, (char *) data, sizeof(tmp));
06153    number=tmp;
06154    strsep(&number, "|");
06155    options = strsep(&number, "|");
06156    if (options) { 
06157       if ( strcasecmp(options, "f") && strcasecmp(options,"m") && 
06158          strcasecmp(options, "c") && strcasecmp(options, "n") ) {
06159          ast_log(LOG_WARNING, "SayNumber gender option is either 'f', 'm', 'c' or 'n'\n");
06160          return -1;
06161       }
06162    }
06163    return res = ast_say_number(chan, atoi((char *) tmp), "", chan->language, options);
06164 }

int pbx_builtin_sayphonetic struct ast_channel ,
void * 
[static]
 

Definition at line 6184 of file pbx.c.

References ast_say_phonetic_str(), and ast_channel::language.

06185 {
06186    int res = 0;
06187 
06188    if (data)
06189       res = ast_say_phonetic_str(chan, (char *)data, "", chan->language);
06190    return res;
06191 }

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

Definition at line 5865 of file pbx.c.

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

Referenced by dumpchan_exec(), and handle_showchan().

05866 {
05867    struct ast_var_t *variables;
05868    char *var, *val;
05869    int total = 0;
05870 
05871    if (!chan)
05872       return 0;
05873 
05874    memset(buf, 0, size);
05875 
05876    AST_LIST_TRAVERSE(&chan->varshead, variables, entries) {
05877       if(variables &&
05878          (var=ast_var_name(variables)) && (val=ast_var_value(variables)) &&
05879          !ast_strlen_zero(var) && !ast_strlen_zero(val)) {
05880          if (ast_build_string(&buf, &size, "%s=%s\n", var, val)) {
05881             ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
05882             break;
05883          } else
05884             total++;
05885       } else 
05886          break;
05887    }
05888    
05889    return total;
05890 }

int pbx_builtin_setglobalvar struct ast_channel ,
void * 
[static]
 

Definition at line 6057 of file pbx.c.

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

06058 {
06059    char *name;
06060    char *value;
06061    char *stringp = NULL;
06062 
06063    if (ast_strlen_zero(data)) {
06064       ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n");
06065       return 0;
06066    }
06067 
06068    stringp = data;
06069    name = strsep(&stringp, "=");
06070    value = strsep(&stringp, "\0"); 
06071 
06072    pbx_builtin_setvar_helper(NULL, name, value);
06073 
06074    return(0);
06075 }

int pbx_builtin_setvar struct ast_channel ,
void * 
 

Definition at line 5986 of file pbx.c.

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

05987 {
05988    char *name, *value, *mydata;
05989    int argc;
05990    char *argv[24];      /* this will only support a maximum of 24 variables being set in a single operation */
05991    int global = 0;
05992    int x;
05993 
05994    if (ast_strlen_zero(data)) {
05995       ast_log(LOG_WARNING, "Set requires at least one variable name/value pair.\n");
05996       return 0;
05997    }
05998 
05999    mydata = ast_strdupa(data);
06000    argc = ast_app_separate_args(mydata, '|', argv, sizeof(argv) / sizeof(argv[0]));
06001 
06002    /* check for a trailing flags argument */
06003    if ((argc > 1) && !strchr(argv[argc-1], '=')) {
06004       argc--;
06005       if (strchr(argv[argc], 'g'))
06006          global = 1;
06007    }
06008 
06009    for (x = 0; x < argc; x++) {
06010       name = argv[x];
06011       if ((value = strchr(name, '='))) {
06012          *value = '\0';
06013          value++;
06014          pbx_builtin_setvar_helper((global) ? NULL : chan, name, value);
06015       } else
06016          ast_log(LOG_WARNING, "Ignoring entry '%s' with no = (and not last 'options' entry)\n", name);
06017    }
06018 
06019    return(0);
06020 }

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

Definition at line 5939 of file pbx.c.

References ast_func_write(), AST_LIST_INSERT_HEAD, AST_LIST_REMOVE, AST_LIST_TRAVERSE, ast_var_assign(), ast_var_delete(), ast_var_name(), ast_verbose(), name, 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_app_group_set_channel(), ast_bridge_call(), ast_iax2_new(), ast_monitor_start(), ast_set_variables(), background_detect_exec(), builtin_blindtransfer(), builtin_function_set(), cb_events(), chanavail_exec(), conf_run(), controlplayback_exec(), count_exec(), curl_exec(), cut_exec(), dial_exec_full(), disa_exec(), do_waiting(), dundi_lookup_exec(), enumlookup_exec(), eval_exec(), function_db_exists(), function_db_read(), get_exec(), get_refer_info(), group_check_exec(), group_count_exec(), group_match_count_exec(), handle_setvariable(), hasvoicemail_exec(), i4l_read(), leave_voicemail(), lookupblacklist_exec(), macro_exec(), math_exec(), md5_exec(), md5check_exec(), misdn_call(), misdn_tx2ast_frm(), mixmonitor_exec(), monitor_handle_owned(), ospfinished_exec(), osplookup_exec(), ospnext_exec(), pbx_builtin_importvar(), pbx_builtin_setglobalvar(), pbx_builtin_setvar(), pbx_extension_helper(), pbx_load_module(), play_message_datetime(), playback_exec(), pop_exec(), pqm_exec(), prep_email_sub_vars(), privacy_exec(), read_exec(), readfile_exec(), realtime_exec(), record_exec(), return_exec(), rqm_exec(), sendimage_exec(), sendtext_exec(), sendurl_exec(), set_agentbycallerid(), set_queue_result(), sip_addheader(), sip_getheader(), sip_new(), sort_exec(), start_monitor_exec(), system_exec_helper(), transfer_exec(), txtcidname_exec(), upqm_exec(), vm_box_exists(), vm_exec(), vmauthenticate(), zt_new(), and zt_read().

05940 {
05941    struct ast_var_t *newvariable;
05942    struct varshead *headp;
05943    const char *nametail = name;
05944 
05945    if (name[strlen(name)-1] == ')')
05946       return ast_func_write(chan, name, value);
05947 
05948    headp = (chan) ? &chan->varshead : &globals;
05949 
05950    /* For comparison purposes, we have to strip leading underscores */
05951    if (*nametail == '_') {
05952       nametail++;
05953       if (*nametail == '_') 
05954          nametail++;
05955    }
05956 
05957    AST_LIST_TRAVERSE (headp, newvariable, entries) {
05958       if (strcasecmp(ast_var_name(newvariable), nametail) == 0) {
05959          /* there is already such a variable, delete it */
05960          AST_LIST_REMOVE(headp, newvariable, entries);
05961          ast_var_delete(newvariable);
05962          break;
05963       }
05964    } 
05965 
05966    if (value) {
05967       if ((option_verbose > 1) && (headp == &globals))
05968          ast_verbose(VERBOSE_PREFIX_2 "Setting global variable '%s' to '%s'\n", name, value);
05969       newvariable = ast_var_assign(name, value);   
05970       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
05971    }
05972 }

int pbx_builtin_setvar_old struct ast_channel ,
void * 
[static]
 

Definition at line 5974 of file pbx.c.

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

05975 {
05976    static int deprecation_warning = 0;
05977 
05978    if (!deprecation_warning) {
05979       ast_log(LOG_WARNING, "SetVar is deprecated, please use Set instead.\n");
05980       deprecation_warning = 1;
05981    }
05982 
05983    return pbx_builtin_setvar(chan, data);
05984 }

int pbx_checkcondition char *  condition  )  [static]
 

Definition at line 6092 of file pbx.c.

Referenced by pbx_builtin_gotoif().

06093 {
06094    if (condition) {
06095       if (*condition == '\0') {
06096          /* Empty strings are false */
06097          return 0;
06098       } else if (*condition >= '0' && *condition <= '9') {
06099          /* Numbers are evaluated for truth */
06100          return atoi(condition);
06101       } else {
06102          /* Strings are true */
06103          return 1;
06104       }
06105    } else {
06106       /* NULL is also false */
06107       return 0;
06108    }
06109 }

void pbx_destroy struct ast_pbx p  )  [static]
 

Definition at line 611 of file pbx.c.

References free.

Referenced by __ast_pbx_run().

00612 {
00613    free(p);
00614 }

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

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

Definition at line 522 of file pbx.c.

References ast_channel::appl, ast_cdr_setapp(), 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().

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

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

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

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

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

Definition at line 768 of file pbx.c.

References ast_context::alts, ast_extension_close(), ast_extension_match(), ast_log(), ast_switch::canmatch, ast_exten::cidmatch, ast_sw::data, ast_sw::eval, ast_switch::exists, ast_exten::exten, HELPER_MATCHMORE, include_valid(), ast_context::includes, ast_exten::label, LOG_WARNING, 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, SWITCH_DATA_LENGTH, and ast_sw::tmpdata.

Referenced by ast_hint_extension(), and pbx_extension_helper().

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

struct ast_app* pbx_findapp const char *  app  ) 
 

Find application handle in linked list.

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

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

00568 {
00569    struct ast_app *tmp;
00570 
00571    if (ast_mutex_lock(&applock)) {
00572       ast_log(LOG_WARNING, "Unable to obtain application lock\n");
00573       return NULL;
00574    }
00575    tmp = apps;
00576    while(tmp) {
00577       if (!strcasecmp(tmp->name, app))
00578          break;
00579       tmp = tmp->next;
00580    }
00581    ast_mutex_unlock(&applock);
00582    return tmp;
00583 }

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

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

00586 {
00587    struct ast_switch *asw;
00588 
00589    if (ast_mutex_lock(&switchlock)) {
00590       ast_log(LOG_WARNING, "Unable to obtain application lock\n");
00591       return NULL;
00592    }
00593    asw = switches;
00594    while(asw) {
00595       if (!strcasecmp(asw->name, sw))
00596          break;
00597       asw = asw->next;
00598    }
00599    ast_mutex_unlock(&switchlock);
00600    return asw;
00601 }

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

pbx_retrieve_variable: Support for Asterisk built-in variables and functions in the dialplan ---

Definition at line 970 of file pbx.c.

References ast_channel::accountcode, ast_get_hint(), AST_LIST_TRAVERSE, ast_log(), 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, parse_variable_name(), ast_channel::priority, substring(), ast_channel::uniqueid, var, and ast_channel::varshead.

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

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

int pbx_set_autofallthrough int  newval  ) 
 

Definition at line 2555 of file pbx.c.

References autofallthrough.

Referenced by pbx_load_module().

02556 {
02557    int oldval;
02558    oldval = autofallthrough;
02559    if (oldval != newval)
02560       autofallthrough = newval;
02561    return oldval;
02562 }

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

Definition at line 1596 of file pbx.c.

References ast_exten::data, and pbx_substitute_variables_helper().

Referenced by pbx_extension_helper().

01597 {
01598    memset(passdata, 0, datalen);
01599       
01600    /* No variables or expressions in e->data, so why scan it? */
01601    if (!strchr(e->data, '$') && !strstr(e->data,"${") && !strstr(e->data,"$[") && !strstr(e->data,"$(")) {
01602       ast_copy_string(passdata, e->data, datalen);
01603       return;
01604    }
01605    
01606    pbx_substitute_variables_helper(c, e->data, passdata, datalen - 1);
01607 }                                                     

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

Definition at line 1586 of file pbx.c.

References pbx_substitute_variables_helper_full(), and ast_channel::varshead.

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

01587 {
01588    pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count);
01589 }

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

Definition at line 1410 of file pbx.c.

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

Referenced by pbx_substitute_variables_helper(), and pbx_substitute_variables_varshead().

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

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

Definition at line 1591 of file pbx.c.

References pbx_substitute_variables_helper_full().

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

01592 {
01593    pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count);
01594 }

void* pbx_thread void *  data  )  [static]
 

Definition at line 2493 of file pbx.c.

References __ast_pbx_run(), and decrease_call_count().

Referenced by ast_pbx_start().

02494 {
02495    /* Oh joyeous kernel, we're a new thread, with nothing to do but
02496       answer this channel and get it going.
02497    */
02498    /* NOTE:
02499       The launcher of this function _MUST_ increment 'countcalls'
02500       before invoking the function; it will be decremented when the
02501       PBX has finished running on the channel
02502     */
02503    struct ast_channel *c = data;
02504 
02505    __ast_pbx_run(c);
02506    decrease_call_count();
02507 
02508    pthread_exit(NULL);
02509 
02510    return NULL;
02511 }

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

Definition at line 3330 of file pbx.c.

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

Referenced by handle_show_dialplan().

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

char* substring const char *  value,
int  offset,
int  length,
char *  workspace,
size_t  workspace_len
[static]
 

takes a substring. It is ok to call with value == workspace.

offset < 0 means start from the end of the string and set the beginning to be that many characters back. length is the length of the substring, -1 means unlimited (we take any negative value). Always return a copy in workspace.

Definition at line 938 of file pbx.c.

Referenced by pbx_retrieve_variable(), and pbx_substitute_variables_helper_full().

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

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

Definition at line 5361 of file pbx.c.

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

Referenced by pbx_builtin_busy(), and pbx_builtin_congestion().

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


Variable Documentation

struct ast_custom_function* acf_root = NULL [static]
 

Definition at line 236 of file pbx.c.

Referenced by ast_custom_function_register(), and ast_custom_function_unregister().

struct ast_app* apps = NULL [static]
 

Definition at line 508 of file pbx.c.

Referenced by ast_register_application(), and ast_unregister_application().

int autofallthrough = 0 [static]
 

Definition at line 230 of file pbx.c.

Referenced by pbx_set_autofallthrough().

struct pbx_builtin builtins[] [static]
 

Declaration of builtin applications.

Referenced by load_pbx().

struct ast_context* contexts = NULL [static]
 

Definition at line 506 of file pbx.c.

Referenced by __ast_context_destroy(), and ast_merge_contexts_and_delete().

int countcalls = 0 [static]
 

Definition at line 233 of file pbx.c.

Referenced by decrease_call_count(), and increase_call_count().

char* days[] [static]
 

Definition at line 3903 of file pbx.c.

Referenced by get_dow().

struct varshead globals [static]
 

Definition at line 228 of file pbx.c.

Referenced by ast_add_extension2(), load_pbx(), pbx_builtin_clear_globals(), and pbx_retrieve_variable().

struct ast_hint* hints = NULL
 

Definition at line 516 of file pbx.c.

Referenced by ast_add_hint(), and ast_remove_hint().

char* months[] [static]
 

Definition at line 4005 of file pbx.c.

Referenced by get_month().

struct ast_cli_entry pbx_cli[] [static]
 

Definition at line 3584 of file pbx.c.

Referenced by load_pbx().

char show_application_help[] [static]
 

Initial value:

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

Definition at line 2962 of file pbx.c.

char show_applications_help[] [static]
 

Initial value:

"Usage: show applications [{like|describing} <text>]\n"
"       List applications which are currently available.\n"
"       If 'like', <text> will be a substring of the app name\n"
"       If 'describing', <text> will be a substring of the description\n"

Definition at line 2974 of file pbx.c.

char show_dialplan_help[] [static]
 

Initial value:

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

Definition at line 2980 of file pbx.c.

char show_function_help[] [static]
 

Initial value:

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

Definition at line 2970 of file pbx.c.

char show_functions_help[] [static]
 

Initial value:

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

Definition at line 2966 of file pbx.c.

char show_hints_help[] [static]
 

Initial value:

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

Definition at line 2988 of file pbx.c.

char show_switches_help[] [static]
 

Initial value:

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

Definition at line 2984 of file pbx.c.

struct ast_state_cb* statecbs = NULL
 

Definition at line 517 of file pbx.c.

Referenced by ast_extension_state_add(), and ast_extension_state_del().

int stateid = 1 [static]
 

Definition at line 515 of file pbx.c.

Referenced by ast_extension_state_add().

struct ast_switch* switches = NULL
 

Definition at line 511 of file pbx.c.

Referenced by ast_register_switch(), and ast_unregister_switch().


Generated on Mon Mar 20 08:20:29 2006 for Asterisk - the Open Source PBX by  doxygen 1.3.9.1