Main Page | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

pbx.c File Reference

#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/channel_pvt.h>
#include <asterisk/linkedlists.h>
#include <asterisk/say.h>
#include <asterisk/utils.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <setjmp.h>
#include <ctype.h>
#include <errno.h>
#include <time.h>
#include <sys/time.h>
#include "asterisk.h"

Go to the source code of this file.

Defines

#define EXT_DATA_SIZE   8192
#define AST_PBX_MAX_STACK   128
#define HELPER_EXISTS   0
#define HELPER_SPAWN   1
#define HELPER_EXEC   2
#define HELPER_CANMATCH   3
#define HELPER_MATCHMORE   4
#define EXTENSION_MATCH_CORE(data, pattern, match)
#define STATUS_NO_CONTEXT   1
#define STATUS_NO_EXTENSION   2
#define STATUS_NO_PRIORITY   3
#define STATUS_SUCCESS   4
#define FIND_NEXT
#define LOG

Functions

int pbx_builtin_setvar (struct ast_channel *, void *)
void pbx_builtin_setvar_helper (struct ast_channel *chan, char *name, char *value)
char * pbx_builtin_getvar_helper (struct ast_channel *chan, char *name)
 AST_MUTEX_DEFINE_STATIC (applock)
 AST_MUTEX_DEFINE_STATIC (conlock)
 AST_MUTEX_DEFINE_STATIC (switchlock)
 AST_MUTEX_DEFINE_STATIC (hintlock)
int pbx_exec (struct ast_channel *c, struct ast_app *app, void *data, int newstack)
 executes an application
ast_apppbx_findapp (char *app)
 Look up an application.
int ast_extension_match (char *pattern, char *data)
 Determine if a given extension matches a given pattern (in NXX format).
ast_contextast_context_find (char *name)
 Find a context.
void pbx_substitute_variables_helper (struct ast_channel *c, const char *cp1, char *cp2, int count)
int ast_extension_state (struct ast_channel *c, char *context, char *exten)
 Uses hint and devicestate callback to get the state of an extension.
int ast_device_state_changed (const char *fmt,...)
int ast_extension_state_add (char *context, char *exten, ast_state_cb_type callback, void *data)
 Registers a state change callback.
int ast_extension_state_del (int id, ast_state_cb_type callback)
 Deletes a registered state change callback by ID.
int ast_get_hint (char *hint, int hintsize, struct ast_channel *c, char *context, char *exten)
 If an extension exists, return non-zero.
int ast_exists_extension (struct ast_channel *c, char *context, char *exten, int priority, char *callerid)
 If an extension exists, return non-zero.
int ast_canmatch_extension (struct ast_channel *c, char *context, char *exten, int priority, char *callerid)
 Looks for a valid matching extension.
int ast_matchmore_extension (struct ast_channel *c, char *context, char *exten, int priority, char *callerid)
 Looks to see if adding anything to this extension might match something. (exists ^ canmatch).
int ast_spawn_extension (struct ast_channel *c, char *context, char *exten, int priority, char *callerid)
 Launch a new extension (i.e. new stack).
int ast_pbx_run (struct ast_channel *c)
 Execute the PBX in the current thread.
int ast_pbx_start (struct ast_channel *c)
 Create a new thread and start the PBX (or whatever).
int ast_context_remove_include (char *context, char *include, char *registrar)
 Removes an include.
int ast_context_remove_include2 (struct ast_context *con, char *include, char *registrar)
 Removes an include by an ast_context structure.
int ast_context_remove_switch (char *context, char *sw, char *data, char *registrar)
 Remove a switch.
int ast_context_remove_switch2 (struct ast_context *con, char *sw, char *data, char *registrar)
int ast_context_remove_extension (char *context, char *extension, int priority, char *registrar)
 Simply remove extension from context.
int ast_context_remove_extension2 (struct ast_context *con, char *extension, int priority, char *registrar)
int ast_register_application (char *app, int(*execute)(struct ast_channel *, void *), char *synopsis, char *description)
 Add an application. The function 'execute' should return non-zero if the line needs to be hung up.
int ast_register_switch (struct ast_switch *sw)
 Register an alternative switch.
void ast_unregister_switch (struct ast_switch *sw)
 Unregister an alternative switch.
int ast_unregister_application (char *app)
 Remove an application.
ast_contextast_context_create (struct ast_context **extcontexts, char *name, char *registrar)
 Register a new context.
void __ast_context_destroy (struct ast_context *con, char *registrar)
void ast_merge_contexts_and_delete (struct ast_context **extcontexts, char *registrar)
 Merge the temporary contexts into a global contexts list and delete from the global list the ones that are being added.
int ast_context_add_include (char *context, char *include, char *registrar)
 Add an include.
int ast_context_add_include2 (struct ast_context *con, char *value, char *registrar)
 Add an include.
int ast_context_add_switch (char *context, char *sw, char *data, char *registrar)
 Add a switch.
int ast_context_add_switch2 (struct ast_context *con, char *value, char *data, char *registrar)
 Adds a switch (first param is a ast_context).
int ast_context_remove_ignorepat (char *context, char *ignorepat, char *registrar)
int ast_context_remove_ignorepat2 (struct ast_context *con, char *ignorepat, char *registrar)
int ast_context_add_ignorepat (char *con, char *value, char *registrar)
 Add an ignorepat.
int ast_context_add_ignorepat2 (struct ast_context *con, char *value, char *registrar)
int ast_ignore_pattern (char *context, char *pattern)
 Checks to see if a number should be ignored.
int ast_add_extension (char *context, int replace, char *extension, int priority, char *callerid, char *application, void *data, void(*datad)(void *), char *registrar)
int ast_async_goto (struct ast_channel *chan, char *context, char *exten, int priority)
int ast_async_goto_by_name (char *channame, char *context, char *exten, int priority)
int ast_add_extension2 (struct ast_context *con, int replace, char *extension, int priority, char *callerid, char *application, void *data, void(*datad)(void *), char *registrar)
 Add an extension to an extension context, this time with an ast_context *. CallerID is a pattern to match on callerid, or NULL to not care about callerid.
int ast_pbx_outgoing_exten (char *type, int format, void *data, int timeout, char *context, char *exten, int priority, int *reason, int sync, int callingpres, char *callerid, char *variable, char *account, char *uniqueid)
void * ast_pbx_run_app (void *data)
int ast_pbx_outgoing_app (char *type, int format, void *data, int timeout, char *app, char *appdata, int *reason, int sync, char *callerid, char *variable, char *account, char *uniqueid)
void ast_context_destroy (struct ast_context *con, char *registrar)
 Destroy a context (matches the specified context (or ANY context if NULL).
void pbx_builtin_clear_globals (void)
int load_pbx (void)
int ast_lock_contexts ()
 Locks the contexts.
int ast_unlock_contexts ()
 Unlocks contexts.
int ast_lock_context (struct ast_context *con)
 Locks a given context.
int ast_unlock_context (struct ast_context *con)
 Unlocks the given context.
char * ast_get_context_name (struct ast_context *con)
char * ast_get_extension_name (struct ast_exten *exten)
char * ast_get_include_name (struct ast_include *inc)
char * ast_get_ignorepat_name (struct ast_ignorepat *ip)
int ast_get_extension_priority (struct ast_exten *exten)
char * ast_get_context_registrar (struct ast_context *c)
char * ast_get_extension_registrar (struct ast_exten *e)
char * ast_get_include_registrar (struct ast_include *i)
char * ast_get_ignorepat_registrar (struct ast_ignorepat *ip)
int ast_get_extension_matchcid (struct ast_exten *e)
char * ast_get_extension_cidmatch (struct ast_exten *e)
char * ast_get_extension_app (struct ast_exten *e)
void * ast_get_extension_app_data (struct ast_exten *e)
char * ast_get_switch_name (struct ast_sw *sw)
char * ast_get_switch_data (struct ast_sw *sw)
char * ast_get_switch_registrar (struct ast_sw *sw)
ast_contextast_walk_contexts (struct ast_context *con)
ast_extenast_walk_context_extensions (struct ast_context *con, struct ast_exten *exten)
ast_swast_walk_context_switches (struct ast_context *con, struct ast_sw *sw)
ast_extenast_walk_extension_priorities (struct ast_exten *exten, struct ast_exten *priority)
ast_includeast_walk_context_includes (struct ast_context *con, struct ast_include *inc)
ast_ignorepatast_walk_context_ignorepats (struct ast_context *con, struct ast_ignorepat *ip)
int ast_context_verify_includes (struct ast_context *con)
 Verifies includes in an ast_contect structure.

Variables

ast_switchswitches = NULL
ast_hinthints = NULL
ast_state_cbstatecbs = NULL


Define Documentation

#define AST_PBX_MAX_STACK   128
 

Definition at line 485 of file pbx.c.

#define EXT_DATA_SIZE   8192
 

Definition at line 55 of file pbx.c.

#define EXTENSION_MATCH_CORE data,
pattern,
match   ) 
 

Definition at line 573 of file pbx.c.

Referenced by 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 3075 of file pbx.c.

#define HELPER_CANMATCH   3
 

Definition at line 490 of file pbx.c.

Referenced by ast_canmatch_extension().

#define HELPER_EXEC   2
 

Definition at line 489 of file pbx.c.

#define HELPER_EXISTS   0
 

Definition at line 487 of file pbx.c.

Referenced by ast_exists_extension().

#define HELPER_MATCHMORE   4
 

Definition at line 491 of file pbx.c.

Referenced by ast_matchmore_extension().

#define HELPER_SPAWN   1
 

Definition at line 488 of file pbx.c.

Referenced by ast_spawn_extension().

#define LOG
 

Referenced by ast_add_extension2().

#define STATUS_NO_CONTEXT   1
 

Definition at line 694 of file pbx.c.

#define STATUS_NO_EXTENSION   2
 

Definition at line 695 of file pbx.c.

#define STATUS_NO_PRIORITY   3
 

Definition at line 696 of file pbx.c.

#define STATUS_SUCCESS   4
 

Definition at line 697 of file pbx.c.


Function Documentation

void __ast_context_destroy struct ast_context con,
char *  registrar
 

Definition at line 4283 of file pbx.c.

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

04284 {
04285    struct ast_context *tmp, *tmpl=NULL;
04286    struct ast_include *tmpi, *tmpil= NULL;
04287    struct ast_sw *sw, *swl= NULL;
04288    struct ast_exten *e, *el, *en;
04289    struct ast_ignorepat *ipi, *ipl = NULL;
04290 
04291    ast_mutex_lock(&conlock);
04292    tmp = contexts;
04293    while(tmp) {
04294       if (((tmp->name && con && con->name && !strcasecmp(tmp->name, con->name)) || !con) &&
04295           (!registrar || !strcasecmp(registrar, tmp->registrar))) {
04296          /* Okay, let's lock the structure to be sure nobody else
04297             is searching through it. */
04298          if (ast_mutex_lock(&tmp->lock)) {
04299             ast_log(LOG_WARNING, "Unable to lock context lock\n");
04300             return;
04301          }
04302          if (tmpl)
04303             tmpl->next = tmp->next;
04304          else
04305             contexts = tmp->next;
04306          /* Okay, now we're safe to let it go -- in a sense, we were
04307             ready to let it go as soon as we locked it. */
04308          ast_mutex_unlock(&tmp->lock);
04309          for (tmpi = tmp->includes; tmpi; ) {
04310             /* Free includes */
04311             tmpil = tmpi;
04312             tmpi = tmpi->next;
04313             free(tmpil);
04314          }
04315          for (ipi = tmp->ignorepats; ipi; ) {
04316             /* Free ignorepats */
04317             ipl = ipi;
04318             ipi = ipi->next;
04319             free(ipl);
04320          }
04321          for (sw = tmp->alts; sw; ) {
04322             /* Free switches */
04323             swl = sw;
04324             sw = sw->next;
04325             free(swl);
04326             swl = sw;
04327          }
04328          for (e = tmp->root; e;) {
04329             for (en = e->peer; en;) {
04330                el = en;
04331                en = en->peer;
04332                destroy_exten(el);
04333             }
04334             el = e;
04335             e = e->next;
04336             destroy_exten(el);
04337          }
04338                         ast_mutex_destroy(&tmp->lock);
04339          free(tmp);
04340          if (!con) {
04341             /* Might need to get another one -- restart */
04342             tmp = contexts;
04343             tmpl = NULL;
04344             tmpil = NULL;
04345             continue;
04346          }
04347          ast_mutex_unlock(&conlock);
04348          return;
04349       }
04350       tmpl = tmp;
04351       tmp = tmp->next;
04352    }
04353    ast_mutex_unlock(&conlock);
04354 }

int ast_add_extension char *  context,
int  replace,
char *  extension,
int  priority,
char *  callerid,
char *  application,
void *  data,
void(*)(void *)  datad,
char *  registrar
 

Parameters:
context context to add the extension to
replace 
extension extension to add
priority priority level of extension addition
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 3667 of file pbx.c.

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

03669 {
03670    struct ast_context *c;
03671 
03672    if (ast_lock_contexts()) {
03673       errno = EBUSY;
03674       return -1;
03675    }
03676 
03677    c = ast_walk_contexts(NULL);
03678    while (c) {
03679       if (!strcmp(context, ast_get_context_name(c))) {
03680          int ret = ast_add_extension2(c, replace, extension, priority, callerid,
03681             application, data, datad, registrar);
03682          ast_unlock_contexts();
03683          return ret;
03684       }
03685       c = ast_walk_contexts(c);
03686    }
03687 
03688    ast_unlock_contexts();
03689    errno = ENOENT;
03690    return -1;
03691 }

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

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

For details about the arguements, check ast_add_extension()

Definition at line 3800 of file pbx.c.

References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_exten::cidmatch, ast_exten::data, ast_exten::datad, ast_exten::exten, free, ast_context::lock, LOG, LOG_ERROR, LOG_WARNING, malloc, ast_exten::matchcid, ast_context::name, ast_exten::next, ast_exten::peer, ast_exten::priority, PRIORITY_HINT, ast_context::registrar, and ast_context::root.

Referenced by ast_add_extension().

03804 {
03805 
03806 #define LOG do {  if (option_debug) {\
03807       if (tmp->matchcid) { \
03808          ast_log(LOG_DEBUG, "Added extension '%s' priority %d (CID match '%s') to %s\n", tmp->exten, tmp->priority, tmp->cidmatch, con->name); \
03809       } else { \
03810          ast_log(LOG_DEBUG, "Added extension '%s' priority %d to %s\n", tmp->exten, tmp->priority, con->name); \
03811       } \
03812    } else if (option_verbose > 2) { \
03813       if (tmp->matchcid) { \
03814          ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d (CID match '%s')to %s\n", tmp->exten, tmp->priority, tmp->cidmatch, con->name); \
03815       } else {  \
03816          ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d to %s\n", tmp->exten, tmp->priority, con->name); \
03817       } \
03818    } } while(0)
03819 
03820    /*
03821     * This is a fairly complex routine.  Different extensions are kept
03822     * in order by the extension number.  Then, extensions of different
03823     * priorities (same extension) are kept in a list, according to the
03824     * peer pointer.
03825     */
03826    struct ast_exten *tmp, *e, *el = NULL, *ep = NULL;
03827    int res;
03828 
03829    /* Be optimistic:  Build the extension structure first */
03830    tmp = malloc(sizeof(struct ast_exten));
03831    if (tmp) {
03832       memset(tmp, 0, sizeof(struct ast_exten));
03833       ext_strncpy(tmp->exten, extension, sizeof(tmp->exten));
03834       tmp->priority = priority;
03835       if (callerid) {
03836          ext_strncpy(tmp->cidmatch, callerid, sizeof(tmp->cidmatch));
03837          tmp->matchcid = 1;
03838       } else {
03839          tmp->cidmatch[0] = '\0';
03840          tmp->matchcid = 0;
03841       }
03842       strncpy(tmp->app, application, sizeof(tmp->app)-1);
03843       tmp->parent = con;
03844       tmp->data = data;
03845       tmp->datad = datad;
03846       tmp->registrar = registrar;
03847       tmp->peer = NULL;
03848       tmp->next =  NULL;
03849    } else {
03850       ast_log(LOG_ERROR, "Out of memory\n");
03851       errno = ENOMEM;
03852       return -1;
03853    }
03854    if (ast_mutex_lock(&con->lock)) {
03855       free(tmp);
03856       /* And properly destroy the data */
03857       datad(data);
03858       ast_log(LOG_WARNING, "Failed to lock context '%s'\n", con->name);
03859       errno = EBUSY;
03860       return -1;
03861    }
03862    e = con->root;
03863    while(e) {
03864       /* Make sure patterns are always last! */
03865       if ((e->exten[0] != '_') && (extension[0] == '_'))
03866          res = -1;
03867       else if ((e->exten[0] == '_') && (extension[0] != '_'))
03868          res = 1;
03869       else
03870          res= strcmp(e->exten, extension);
03871       if (!res) {
03872          if (!e->matchcid && !tmp->matchcid)
03873             res = 0;
03874          else if (tmp->matchcid && !e->matchcid)
03875             res = 1;
03876          else if (e->matchcid && !tmp->matchcid)
03877             res = -1;
03878          else
03879             res = strcasecmp(e->cidmatch, tmp->cidmatch);
03880       }
03881       if (res == 0) {
03882          /* We have an exact match, now we find where we are
03883             and be sure there's no duplicates */
03884          while(e) {
03885             if (e->priority == tmp->priority) {
03886                /* Can't have something exactly the same.  Is this a
03887                   replacement?  If so, replace, otherwise, bonk. */
03888                if (replace) {
03889                   if (ep) {
03890                      /* We're in the peer list, insert ourselves */
03891                      ep->peer = tmp;
03892                      tmp->peer = e->peer;
03893                   } else if (el) {
03894                      /* We're the first extension. Take over e's functions */
03895                      el->next = tmp;
03896                      tmp->next = e->next;
03897                      tmp->peer = e->peer;
03898                   } else {
03899                      /* We're the very first extension.  */
03900                      con->root = tmp;
03901                      tmp->next = e->next;
03902                      tmp->peer = e->peer;
03903                   }
03904                   if (tmp->priority == PRIORITY_HINT)
03905                       ast_change_hint(e,tmp);
03906                   /* Destroy the old one */
03907                   e->datad(e->data);
03908                   free(e);
03909                   ast_mutex_unlock(&con->lock);
03910                   if (tmp->priority == PRIORITY_HINT)
03911                       ast_change_hint(e, tmp);
03912                   /* And immediately return success. */
03913                   LOG;
03914                   return 0;
03915                } else {
03916                   ast_log(LOG_WARNING, "Unable to register extension '%s', priority %d in '%s', already in use\n", tmp->exten, tmp->priority, con->name);
03917                   tmp->datad(tmp->data);
03918                   free(tmp);
03919                   ast_mutex_unlock(&con->lock);
03920                   errno = EEXIST;
03921                   return -1;
03922                }
03923             } else if (e->priority > tmp->priority) {
03924                /* Slip ourselves in just before e */
03925                if (ep) {
03926                   /* Easy enough, we're just in the peer list */
03927                   ep->peer = tmp;
03928                   tmp->peer = e;
03929                } else if (el) {
03930                   /* We're the first extension in this peer list */
03931                   el->next = tmp;
03932                   tmp->next = e->next;
03933                   e->next = NULL;
03934                   tmp->peer = e;
03935                } else {
03936                   /* We're the very first extension altogether */
03937                   tmp->next = con->root->next;
03938                   /* Con->root must always exist or we couldn't get here */
03939                   tmp->peer = con->root;
03940                   con->root = tmp;
03941                }
03942                ast_mutex_unlock(&con->lock);
03943                /* And immediately return success. */
03944                if (tmp->priority == PRIORITY_HINT)
03945                    ast_add_hint(tmp);
03946                
03947                LOG;
03948                return 0;
03949             }
03950             ep = e;
03951             e = e->peer;
03952          }
03953          /* If we make it here, then it's time for us to go at the very end.
03954             ep *must* be defined or we couldn't have gotten here. */
03955          ep->peer = tmp;
03956          ast_mutex_unlock(&con->lock);
03957          if (tmp->priority == PRIORITY_HINT)
03958             ast_add_hint(tmp);
03959          
03960          /* And immediately return success. */
03961          LOG;
03962          return 0;
03963             
03964       } else if (res > 0) {
03965          /* Insert ourselves just before 'e'.  We're the first extension of
03966             this kind */
03967          tmp->next = e;
03968          if (el) {
03969             /* We're in the list somewhere */
03970             el->next = tmp;
03971          } else {
03972             /* We're at the top of the list */
03973             con->root = tmp;
03974          }
03975          ast_mutex_unlock(&con->lock);
03976          if (tmp->priority == PRIORITY_HINT)
03977             ast_add_hint(tmp);
03978 
03979          /* And immediately return success. */
03980          LOG;
03981          return 0;
03982       }        
03983          
03984       el = e;
03985       e = e->next;
03986    }
03987    /* If we fall all the way through to here, then we need to be on the end. */
03988    if (el)
03989       el->next = tmp;
03990    else
03991       con->root = tmp;
03992    ast_mutex_unlock(&con->lock);
03993    if (tmp->priority == PRIORITY_HINT)
03994       ast_add_hint(tmp);
03995    LOG;
03996    return 0;   
03997 }

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

Definition at line 3693 of file pbx.c.

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

Referenced by ast_async_goto_by_name().

03694 {
03695    int res = 0;
03696    ast_mutex_lock(&chan->lock);
03697 
03698    if (chan->pbx) {
03699       /* This channel is currently in the PBX */
03700       if (context && !ast_strlen_zero(context))
03701          strncpy(chan->context, context, sizeof(chan->context) - 1);
03702       if (exten && !ast_strlen_zero(exten))
03703          strncpy(chan->exten, exten, sizeof(chan->context) - 1);
03704       if (priority)
03705          chan->priority = priority - 1;
03706       ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO);
03707    } else {
03708       /* In order to do it when the channel doesn't really exist within
03709          the PBX, we have to make a new channel, masquerade, and start the PBX
03710          at the new location */
03711       struct ast_channel *tmpchan;
03712       tmpchan = ast_channel_alloc(0);
03713       if (tmpchan) {
03714          snprintf(tmpchan->name, sizeof(tmpchan->name), "AsyncGoto/%s", chan->name);
03715          ast_setstate(tmpchan, chan->_state);
03716          /* Make formats okay */
03717          tmpchan->readformat = chan->readformat;
03718          tmpchan->writeformat = chan->writeformat;
03719          /* Setup proper location */
03720          if (context && !ast_strlen_zero(context))
03721             strncpy(tmpchan->context, context, sizeof(tmpchan->context) - 1);
03722          else
03723             strncpy(tmpchan->context, chan->context, sizeof(tmpchan->context) - 1);
03724          if (exten && !ast_strlen_zero(exten))
03725             strncpy(tmpchan->exten, exten, sizeof(tmpchan->exten) - 1);
03726          else
03727             strncpy(tmpchan->exten, chan->exten, sizeof(tmpchan->exten) - 1);
03728          if (priority)
03729             tmpchan->priority = priority;
03730          else
03731             tmpchan->priority = chan->priority;
03732          
03733          /* Masquerade into temp channel */
03734          ast_channel_masquerade(tmpchan, chan);
03735       
03736          /* Grab the locks and get going */
03737          ast_mutex_lock(&tmpchan->lock);
03738          ast_do_masquerade(tmpchan);
03739          ast_mutex_unlock(&tmpchan->lock);
03740          /* Start the PBX going on our stolen channel */
03741          if (ast_pbx_start(tmpchan)) {
03742             ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name);
03743             ast_hangup(tmpchan);
03744             res = -1;
03745          }
03746       } else {
03747          res = -1;
03748       }
03749    }
03750    ast_mutex_unlock(&chan->lock);
03751    return res;
03752 }

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

Definition at line 3754 of file pbx.c.

References ast_async_goto(), ast_channel_walk_locked(), ast_mutex_unlock, ast_channel::lock, and ast_channel::name.

03755 {
03756    struct ast_channel *chan;
03757    int res = -1;
03758 
03759    chan = ast_channel_walk_locked(NULL);
03760    while(chan) {
03761       if (!strcasecmp(channame, chan->name))
03762          break;
03763       ast_mutex_unlock(&chan->lock);
03764       chan = ast_channel_walk_locked(chan);
03765    }
03766    
03767    if (chan) {
03768       res = ast_async_goto(chan, context, exten, priority);
03769       ast_mutex_unlock(&chan->lock);
03770    }
03771    return res;
03772 }

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

Looks for a valid matching extension.

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

Definition at line 1761 of file pbx.c.

References HELPER_CANMATCH.

01762 {
01763    return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_CANMATCH);
01764 }

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

Add an ignorepat.

Parameters:
context which context to add the ignorpattern to
ignorpat 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 3586 of file pbx.c.

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

03587 {
03588    struct ast_context *c;
03589 
03590    if (ast_lock_contexts()) {
03591       errno = EBUSY;
03592       return -1;
03593    }
03594 
03595    c = ast_walk_contexts(NULL);
03596    while (c) {
03597       if (!strcmp(ast_get_context_name(c), con)) {
03598          int ret = ast_context_add_ignorepat2(c, value, registrar);
03599          ast_unlock_contexts();
03600          return ret;
03601       } 
03602       c = ast_walk_contexts(c);
03603    }
03604 
03605    ast_unlock_contexts();
03606    errno = ENOENT;
03607    return -1;
03608 }

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

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

03611 {
03612    struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL;
03613 
03614    ignorepat = malloc(sizeof(struct ast_ignorepat));
03615    if (!ignorepat) {
03616       ast_log(LOG_ERROR, "Out of memory\n");
03617       errno = ENOMEM;
03618       return -1;
03619    }
03620    memset(ignorepat, 0, sizeof(struct ast_ignorepat));
03621    strncpy(ignorepat->pattern, value, sizeof(ignorepat->pattern)-1);
03622    ignorepat->next = NULL;
03623    ignorepat->registrar = registrar;
03624    ast_mutex_lock(&con->lock);
03625    ignorepatc = con->ignorepats;
03626    while(ignorepatc) {
03627       ignorepatl = ignorepatc;
03628       if (!strcasecmp(ignorepatc->pattern, value)) {
03629          /* Already there */
03630          ast_mutex_unlock(&con->lock);
03631          errno = EEXIST;
03632          return -1;
03633       }
03634       ignorepatc = ignorepatc->next;
03635    }
03636    if (ignorepatl) 
03637       ignorepatl->next = ignorepat;
03638    else
03639       con->ignorepats = ignorepat;
03640    ast_mutex_unlock(&con->lock);
03641    return 0;
03642    
03643 }

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

Add an include.

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

Definition at line 3047 of file pbx.c.

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

03048 {
03049    struct ast_context *c;
03050 
03051    if (ast_lock_contexts()) {
03052       errno = EBUSY;
03053       return -1;
03054    }
03055 
03056    /* walk contexts ... */
03057    c = ast_walk_contexts(NULL);
03058    while (c) {
03059       /* ... search for the right one ... */
03060       if (!strcmp(ast_get_context_name(c), context)) {
03061          int ret = ast_context_add_include2(c, include, registrar);
03062          /* ... unlock contexts list and return */
03063          ast_unlock_contexts();
03064          return ret;
03065       }
03066       c = ast_walk_contexts(c);
03067    }
03068 
03069    /* we can't find the right context */
03070    ast_unlock_contexts();
03071    errno = ENOENT;
03072    return -1;
03073 }

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

Add an include.

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

Definition at line 3367 of file pbx.c.

References ast_get_context_name(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_verbose(), free, ast_context::includes, ast_context::lock, LOG_ERROR, malloc, ast_include::name, ast_include::next, option_verbose, ast_include::registrar, ast_include::rname, and VERBOSE_PREFIX_3.

Referenced by ast_context_add_include().

03369 {
03370    struct ast_include *new_include;
03371    char *c;
03372    struct ast_include *i, *il = NULL; /* include, include_last */
03373 
03374    /* allocate new include structure ... */
03375    if (!(new_include = malloc(sizeof(struct ast_include)))) {
03376       ast_log(LOG_ERROR, "Out of memory\n");
03377       errno = ENOMEM;
03378       return -1;
03379    }
03380    
03381    /* ... fill in this structure ... */
03382    memset(new_include, 0, sizeof(struct ast_include));
03383    strncpy(new_include->name, value, sizeof(new_include->name)-1);
03384    strncpy(new_include->rname, value, sizeof(new_include->rname)-1);
03385    c = new_include->rname;
03386    /* Strip off timing info */
03387    while(*c && (*c != '|')) c++; 
03388    /* Process if it's there */
03389    if (*c) {
03390       build_timing(new_include, c+1);
03391       *c = '\0';
03392    }
03393    new_include->next      = NULL;
03394    new_include->registrar = registrar;
03395 
03396    /* ... try to lock this context ... */
03397    if (ast_mutex_lock(&con->lock)) {
03398       free(new_include);
03399       errno = EBUSY;
03400       return -1;
03401    }
03402 
03403    /* ... go to last include and check if context is already included too... */
03404    i = con->includes;
03405    while (i) {
03406       if (!strcasecmp(i->name, new_include->name)) {
03407          free(new_include);
03408          ast_mutex_unlock(&con->lock);
03409          errno = EEXIST;
03410          return -1;
03411       }
03412       il = i;
03413       i = i->next;
03414    }
03415 
03416    /* ... include new context into context list, unlock, return */
03417    if (il)
03418       il->next = new_include;
03419    else
03420       con->includes = new_include;
03421    if (option_verbose > 2)
03422       ast_verbose(VERBOSE_PREFIX_3 "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con)); 
03423    ast_mutex_unlock(&con->lock);
03424 
03425    return 0;
03426 }

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

Add a switch.

Parameters:
context context to which to add the switch
sw switch to add
data data to pass to 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 3433 of file pbx.c.

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

03434 {
03435    struct ast_context *c;
03436 
03437    if (ast_lock_contexts()) {
03438       errno = EBUSY;
03439       return -1;
03440    }
03441 
03442    /* walk contexts ... */
03443    c = ast_walk_contexts(NULL);
03444    while (c) {
03445       /* ... search for the right one ... */
03446       if (!strcmp(ast_get_context_name(c), context)) {
03447          int ret = ast_context_add_switch2(c, sw, data, registrar);
03448          /* ... unlock contexts list and return */
03449          ast_unlock_contexts();
03450          return ret;
03451       }
03452       c = ast_walk_contexts(c);
03453    }
03454 
03455    /* we can't find the right context */
03456    ast_unlock_contexts();
03457    errno = ENOENT;
03458    return -1;
03459 }

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

Adds a switch (first param is a ast_context).

See ast_context_add_switch()

Definition at line 3468 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, free, ast_context::lock, LOG_ERROR, malloc, ast_sw::name, ast_sw::next, option_verbose, ast_sw::registrar, and VERBOSE_PREFIX_3.

Referenced by ast_context_add_switch().

03470 {
03471    struct ast_sw *new_sw;
03472    struct ast_sw *i, *il = NULL; /* sw, sw_last */
03473 
03474    /* allocate new sw structure ... */
03475    if (!(new_sw = malloc(sizeof(struct ast_sw)))) {
03476       ast_log(LOG_ERROR, "Out of memory\n");
03477       errno = ENOMEM;
03478       return -1;
03479    }
03480    
03481    /* ... fill in this structure ... */
03482    memset(new_sw, 0, sizeof(struct ast_sw));
03483    strncpy(new_sw->name, value, sizeof(new_sw->name)-1);
03484    if (data)
03485       strncpy(new_sw->data, data, sizeof(new_sw->data)-1);
03486    else
03487       strncpy(new_sw->data, "", sizeof(new_sw->data)-1);
03488    new_sw->next      = NULL;
03489    new_sw->registrar = registrar;
03490 
03491    /* ... try to lock this context ... */
03492    if (ast_mutex_lock(&con->lock)) {
03493       free(new_sw);
03494       errno = EBUSY;
03495       return -1;
03496    }
03497 
03498    /* ... go to last sw and check if context is already swd too... */
03499    i = con->alts;
03500    while (i) {
03501       if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) {
03502          free(new_sw);
03503          ast_mutex_unlock(&con->lock);
03504          errno = EEXIST;
03505          return -1;
03506       }
03507       il = i;
03508       i = i->next;
03509    }
03510 
03511    /* ... sw new context into context list, unlock, return */
03512    if (il)
03513       il->next = new_sw;
03514    else
03515       con->alts = new_sw;
03516    if (option_verbose > 2)
03517       ast_verbose(VERBOSE_PREFIX_3 "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con)); 
03518    ast_mutex_unlock(&con->lock);
03519 
03520    return 0;
03521 }

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

Register a new context.

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

Definition at line 2970 of file pbx.c.

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

02971 {
02972    struct ast_context *tmp, **local_contexts;
02973    if (!extcontexts) {
02974       local_contexts = &contexts;
02975       ast_mutex_lock(&conlock);
02976    } else
02977       local_contexts = extcontexts;
02978 
02979    tmp = *local_contexts;
02980    while(tmp) {
02981       if (!strcasecmp(tmp->name, name)) {
02982          ast_mutex_unlock(&conlock);
02983          ast_log(LOG_WARNING, "Tried to register context '%s', already in use\n", name);
02984          if (!extcontexts)
02985             ast_mutex_unlock(&conlock);
02986          return NULL;
02987       }
02988       tmp = tmp->next;
02989    }
02990    tmp = malloc(sizeof(struct ast_context));
02991    if (tmp) {
02992       memset(tmp, 0, sizeof(struct ast_context));
02993       ast_mutex_init(&tmp->lock);
02994       strncpy(tmp->name, name, sizeof(tmp->name)-1);
02995       tmp->root = NULL;
02996       tmp->registrar = registrar;
02997       tmp->next = *local_contexts;
02998       tmp->includes = NULL;
02999       tmp->ignorepats = NULL;
03000       *local_contexts = tmp;
03001       if (option_debug)
03002          ast_log(LOG_DEBUG, "Registered context '%s'\n", tmp->name);
03003       else if (option_verbose > 2)
03004          ast_verbose( VERBOSE_PREFIX_3 "Registered extension context '%s'\n", tmp->name);
03005    } else
03006       ast_log(LOG_ERROR, "Out of memory\n");
03007    
03008    if (!extcontexts)
03009       ast_mutex_unlock(&conlock);
03010    return tmp;
03011 }

void ast_context_destroy struct ast_context con,
char *  registrar
 

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

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

Definition at line 4356 of file pbx.c.

References __ast_context_destroy().

04357 {
04358    __ast_context_destroy(con,registrar);
04359 }

struct ast_context* ast_context_find char *  name  ) 
 

Find a context.

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

Definition at line 677 of file pbx.c.

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

Referenced by ast_context_verify_includes(), and ast_ignore_pattern().

00678 {
00679    struct ast_context *tmp;
00680    ast_mutex_lock(&conlock);
00681    if (name) {
00682       tmp = contexts;
00683       while(tmp) {
00684          if (!strcasecmp(name, tmp->name))
00685             break;
00686          tmp = tmp->next;
00687       }
00688    } else
00689       tmp = contexts;
00690    ast_mutex_unlock(&conlock);
00691    return tmp;
00692 }

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

Simply remove extension from context.

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

Definition at line 2169 of file pbx.c.

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

02170 {
02171    struct ast_context *c;
02172 
02173    if (ast_lock_contexts()) return -1;
02174 
02175    /* walk contexts ... */
02176    c = ast_walk_contexts(NULL);
02177    while (c) {
02178       /* ... search for the right one ... */
02179       if (!strcmp(ast_get_context_name(c), context)) {
02180          /* ... remove extension ... */
02181          int ret = ast_context_remove_extension2(c, extension, priority,
02182             registrar);
02183          /* ... unlock contexts list and return */
02184          ast_unlock_contexts();
02185          return ret;
02186       }
02187       c = ast_walk_contexts(c);
02188    }
02189 
02190    /* we can't find the right context */
02191    ast_unlock_contexts();
02192    return -1;
02193 }

int ast_context_remove_extension2 struct ast_context con,
char *  extension,
int  priority,
char *  registrar
 

Definition at line 2205 of file pbx.c.

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

Referenced by ast_context_remove_extension().

02206 {
02207    struct ast_exten *exten, *prev_exten = NULL;
02208 
02209    if (ast_mutex_lock(&con->lock)) return -1;
02210 
02211    /* go through all extensions in context and search the right one ... */
02212    exten = con->root;
02213    while (exten) {
02214 
02215       /* look for right extension */
02216       if (!strcmp(exten->exten, extension) &&
02217          (!registrar || !strcmp(exten->registrar, registrar))) {
02218          struct ast_exten *peer;
02219 
02220          /* should we free all peers in this extension? (priority == 0)? */
02221          if (priority == 0) {
02222             /* remove this extension from context list */
02223             if (prev_exten)
02224                prev_exten->next = exten->next;
02225             else
02226                con->root = exten->next;
02227 
02228             /* fire out all peers */
02229             peer = exten; 
02230             while (peer) {
02231                exten = peer->peer;
02232                
02233                if (!peer->priority==PRIORITY_HINT) 
02234                    ast_remove_hint(peer);
02235 
02236                peer->datad(peer->data);
02237                free(peer);
02238 
02239                peer = exten;
02240             }
02241 
02242             ast_mutex_unlock(&con->lock);
02243             return 0;
02244          } else {
02245             /* remove only extension with exten->priority == priority */
02246             struct ast_exten *previous_peer = NULL;
02247 
02248             peer = exten;
02249             while (peer) {
02250                /* is this our extension? */
02251                if (peer->priority == priority &&
02252                   (!registrar || !strcmp(peer->registrar, registrar) )) {
02253                   /* we are first priority extension? */
02254                   if (!previous_peer) {
02255                      /* exists previous extension here? */
02256                      if (prev_exten) {
02257                         /* yes, so we must change next pointer in
02258                          * previous connection to next peer
02259                          */
02260                         if (peer->peer) {
02261                            prev_exten->next = peer->peer;
02262                            peer->peer->next = exten->next;
02263                         } else
02264                            prev_exten->next = exten->next;
02265                      } else {
02266                         /* no previous extension, we are first
02267                          * extension, so change con->root ...
02268                          */
02269                         if (peer->peer)
02270                            con->root = peer->peer;
02271                         else
02272                            con->root = exten->next; 
02273                      }
02274                   } else {
02275                      /* we are not first priority in extension */
02276                      previous_peer->peer = peer->peer;
02277                   }
02278 
02279                   /* now, free whole priority extension */
02280                   if (peer->priority==PRIORITY_HINT)
02281                       ast_remove_hint(peer);
02282                   peer->datad(peer->data);
02283                   free(peer);
02284 
02285                   ast_mutex_unlock(&con->lock);
02286                   return 0;
02287                } else {
02288                   /* this is not right extension, skip to next peer */
02289                   previous_peer = peer;
02290                   peer = peer->peer;
02291                }
02292             }
02293 
02294             ast_mutex_unlock(&con->lock);
02295             return -1;
02296          }
02297       }
02298 
02299       prev_exten = exten;
02300       exten = exten->next;
02301    }
02302 
02303    /* we can't find right extension */
02304    ast_mutex_unlock(&con->lock);
02305    return -1;
02306 }

int ast_context_remove_ignorepat char *  context,
char *  ignorepat,
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 3527 of file pbx.c.

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

03528 {
03529    struct ast_context *c;
03530 
03531    if (ast_lock_contexts()) {
03532       errno = EBUSY;
03533       return -1;
03534    }
03535 
03536    c = ast_walk_contexts(NULL);
03537    while (c) {
03538       if (!strcmp(ast_get_context_name(c), context)) {
03539          int ret = ast_context_remove_ignorepat2(c, ignorepat, registrar);
03540          ast_unlock_contexts();
03541          return ret;
03542       }
03543       c = ast_walk_contexts(c);
03544    }
03545 
03546    ast_unlock_contexts();
03547    errno = ENOENT;
03548    return -1;
03549 }

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

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

03552 {
03553    struct ast_ignorepat *ip, *ipl = NULL;
03554 
03555    if (ast_mutex_lock(&con->lock)) {
03556       errno = EBUSY;
03557       return -1;
03558    }
03559 
03560    ip = con->ignorepats;
03561    while (ip) {
03562       if (!strcmp(ip->pattern, ignorepat) &&
03563          (!registrar || (registrar == ip->registrar))) {
03564          if (ipl) {
03565             ipl->next = ip->next;
03566             free(ip);
03567          } else {
03568             con->ignorepats = ip->next;
03569             free(ip);
03570          }
03571          ast_mutex_unlock(&con->lock);
03572          return 0;
03573       }
03574       ipl = ip; ip = ip->next;
03575    }
03576 
03577    ast_mutex_unlock(&con->lock);
03578    errno = EINVAL;
03579    return -1;
03580 }

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

Removes an include.

See add_include

Definition at line 2025 of file pbx.c.

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

02026 {
02027    struct ast_context *c;
02028 
02029    if (ast_lock_contexts()) return -1;
02030 
02031    /* walk contexts and search for the right one ...*/
02032    c = ast_walk_contexts(NULL);
02033    while (c) {
02034       /* we found one ... */
02035       if (!strcmp(ast_get_context_name(c), context)) {
02036          int ret;
02037          /* remove include from this context ... */   
02038          ret = ast_context_remove_include2(c, include, registrar);
02039 
02040          ast_unlock_contexts();
02041 
02042          /* ... return results */
02043          return ret;
02044       }
02045       c = ast_walk_contexts(c);
02046    }
02047 
02048    /* we can't find the right one context */
02049    ast_unlock_contexts();
02050    return -1;
02051 }

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

Removes an include by an ast_context structure.

See add_include2

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

02062 {
02063    struct ast_include *i, *pi = NULL;
02064 
02065    if (ast_mutex_lock(&con->lock)) return -1;
02066 
02067    /* walk includes */
02068    i = con->includes;
02069    while (i) {
02070       /* find our include */
02071       if (!strcmp(i->name, include) && 
02072          (!registrar || !strcmp(i->registrar, registrar))) {
02073          /* remove from list */
02074          if (pi)
02075             pi->next = i->next;
02076          else
02077             con->includes = i->next;
02078          /* free include and return */
02079          free(i);
02080          ast_mutex_unlock(&con->lock);
02081          return 0;
02082       }
02083       pi = i;
02084       i = i->next;
02085    }
02086 
02087    /* we can't find the right include */
02088    ast_mutex_unlock(&con->lock);
02089    return -1;
02090 }

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

Remove a switch.

Removes a switch with the given parameters Returns 0 on success, -1 on failure

Definition at line 2097 of file pbx.c.

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

02098 {
02099    struct ast_context *c;
02100 
02101    if (ast_lock_contexts()) return -1;
02102 
02103    /* walk contexts and search for the right one ...*/
02104    c = ast_walk_contexts(NULL);
02105    while (c) {
02106       /* we found one ... */
02107       if (!strcmp(ast_get_context_name(c), context)) {
02108          int ret;
02109          /* remove switch from this context ... */ 
02110          ret = ast_context_remove_switch2(c, sw, data, registrar);
02111 
02112          ast_unlock_contexts();
02113 
02114          /* ... return results */
02115          return ret;
02116       }
02117       c = ast_walk_contexts(c);
02118    }
02119 
02120    /* we can't find the right one context */
02121    ast_unlock_contexts();
02122    return -1;
02123 }

int ast_context_remove_switch2 struct ast_context con,
char *  sw,
char *  data,
char *  registrar
 

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

02134 {
02135    struct ast_sw *i, *pi = NULL;
02136 
02137    if (ast_mutex_lock(&con->lock)) return -1;
02138 
02139    /* walk switchs */
02140    i = con->alts;
02141    while (i) {
02142       /* find our switch */
02143       if (!strcmp(i->name, sw) && !strcmp(i->data, data) && 
02144          (!registrar || !strcmp(i->registrar, registrar))) {
02145          /* remove from list */
02146          if (pi)
02147             pi->next = i->next;
02148          else
02149             con->alts = i->next;
02150          /* free switch and return */
02151          free(i);
02152          ast_mutex_unlock(&con->lock);
02153          return 0;
02154       }
02155       pi = i;
02156       i = i->next;
02157    }
02158 
02159    /* we can't find the right switch */
02160    ast_mutex_unlock(&con->lock);
02161    return -1;
02162 }

int ast_context_verify_includes struct ast_context con  ) 
 

Verifies includes in an ast_contect structure.

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

Definition at line 5093 of file pbx.c.

References ast_context_find(), ast_get_context_name(), ast_log(), ast_walk_context_includes(), LOG_WARNING, and ast_include::rname.

05094 {
05095    struct ast_include *inc;
05096    int res = 0;
05097 
05098    for (inc = ast_walk_context_includes(con, NULL); inc; inc = ast_walk_context_includes(con, inc))
05099       if (!ast_context_find(inc->rname)) {
05100          res = -1;
05101          ast_log(LOG_WARNING, "Context '%s' tries includes non-existant context '%s'\n",
05102                ast_get_context_name(con), inc->rname);
05103       }
05104    return res;
05105 }

int ast_device_state_changed const char *  fmt,
  ...
 

Definition at line 1441 of file pbx.c.

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

Referenced by ast_channel_free(), and ast_setstate().

01442 {
01443    struct ast_hint *list;
01444    struct ast_state_cb *cblist;
01445    char hint[AST_MAX_EXTENSION] = "";
01446    char device[AST_MAX_EXTENSION];
01447    char *cur, *rest;
01448    int state;
01449 
01450    va_list ap;
01451 
01452    va_start(ap, fmt);
01453    vsnprintf(device, sizeof(device), fmt, ap);
01454    va_end(ap);
01455 
01456    rest = strchr(device, '-');
01457    if (rest) {
01458       *rest = 0;
01459    }
01460 
01461    ast_mutex_lock(&hintlock);
01462 
01463    list = hints;
01464 
01465    while (list) {
01466 
01467       strncpy(hint, ast_get_extension_app(list->exten), sizeof(hint) - 1);
01468       cur = hint;
01469       do {
01470          rest = strchr(cur, '&');
01471          if (rest) {
01472             *rest = 0;
01473             rest++;
01474          }
01475          
01476          if (!strcmp(cur, device)) {
01477             /* Found extension execute callbacks  */
01478             state = ast_extension_state2(list->exten);
01479             if ((state != -1) && (state != list->laststate)) {
01480                /* For general callbacks */
01481                cblist = statecbs;
01482                while (cblist) {
01483                   cblist->callback(list->exten->parent->name, list->exten->exten, state, cblist->data);
01484                   cblist = cblist->next;
01485                }
01486 
01487                /* For extension callbacks */
01488                cblist = list->callbacks;
01489                while (cblist) {
01490                   cblist->callback(list->exten->parent->name, list->exten->exten, state, cblist->data);
01491                   cblist = cblist->next;
01492                }
01493          
01494                list->laststate = state;
01495             }
01496             break;
01497          }
01498          cur = rest;
01499       } while (cur);
01500       list = list->next;
01501    }
01502    ast_mutex_unlock(&hintlock);
01503    return 1;
01504 }

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

If an extension exists, return non-zero.

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

Definition at line 1756 of file pbx.c.

References HELPER_EXISTS.

Referenced by ast_pbx_outgoing_exten(), and ast_pbx_run().

01757 {
01758    return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_EXISTS);
01759 }

int ast_extension_match char *  pattern,
char *  extension
 

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

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

Definition at line 644 of file pbx.c.

References EXTENSION_MATCH_CORE.

Referenced by ast_ignore_pattern().

00645 {
00646    int match;
00647    /* If they're the same return */
00648    if (!strcmp(pattern, data))
00649       return 1;
00650    EXTENSION_MATCH_CORE(data,pattern,match);
00651    /* Must be at the end of both */
00652    if (*data || (*pattern && (*pattern != '/')))
00653       match = 0;
00654    return match;
00655 }

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

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

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

Definition at line 1430 of file pbx.c.

01431 {
01432    struct ast_exten *e;
01433 
01434    e = ast_hint_extension(c, context, exten);    
01435    if (!e) 
01436       return -1;
01437 
01438    return ast_extension_state2(e);    
01439 }

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

Registers a state change callback.

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

Definition at line 1506 of file pbx.c.

References 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, and ast_hint::next.

Referenced by init_manager().

01508 {
01509    struct ast_hint *list;
01510    struct ast_state_cb *cblist;
01511    struct ast_exten *e;
01512 
01513    /* No context and extension add callback to statecbs list */
01514    if (!context && !exten) {
01515       ast_mutex_lock(&hintlock);
01516 
01517       cblist = statecbs;
01518       while (cblist) {
01519          if (cblist->callback == callback) {
01520             cblist->data = data;
01521             ast_mutex_unlock(&hintlock);
01522          }
01523          cblist = cblist->next;
01524       }
01525    
01526       /* Now inserts the callback */
01527       cblist = malloc(sizeof(struct ast_state_cb));
01528       if (!cblist) {
01529          ast_mutex_unlock(&hintlock);
01530          return -1;
01531       }
01532       memset(cblist, 0, sizeof(struct ast_state_cb));
01533       cblist->id = 0;
01534       cblist->callback = callback;
01535       cblist->data = data;
01536    
01537             cblist->next = statecbs;
01538       statecbs = cblist;
01539 
01540       ast_mutex_unlock(&hintlock);
01541       return 0;
01542       }
01543 
01544    if (!context || !exten)
01545       return -1;
01546 
01547    /* This callback type is for only one hint */
01548    e = ast_hint_extension(NULL, context, exten);    
01549    if (!e) {
01550       return -1;
01551    }
01552     
01553    ast_mutex_lock(&hintlock);
01554    list = hints;        
01555     
01556    while (list) {
01557       if (list->exten == e)
01558          break;       
01559       list = list->next;    
01560    }
01561 
01562    if (!list) {
01563       ast_mutex_unlock(&hintlock);
01564       return -1;
01565    }
01566 
01567    /* Now inserts the callback */
01568    cblist = malloc(sizeof(struct ast_state_cb));
01569    if (!cblist) {
01570       ast_mutex_unlock(&hintlock);
01571       return -1;
01572    }
01573    memset(cblist, 0, sizeof(struct ast_state_cb));
01574    cblist->id = stateid++;
01575    cblist->callback = callback;
01576    cblist->data = data;
01577 
01578    cblist->next = list->callbacks;
01579    list->callbacks = cblist;
01580 
01581    ast_mutex_unlock(&hintlock);
01582    return cblist->id;
01583 }

int ast_extension_state_del int  id,
ast_state_cb_type  callback
 

Deletes a registered state change callback by ID.

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

Definition at line 1585 of file pbx.c.

References ast_mutex_lock, ast_mutex_unlock, ast_hint::callbacks, free, ast_state_cb::next, and ast_hint::next.

01586 {
01587    struct ast_hint *list;
01588    struct ast_state_cb *cblist, *cbprev;
01589     
01590    if (!id && !callback)
01591       return -1;
01592             
01593    ast_mutex_lock(&hintlock);
01594 
01595    /* id is zero is a callback without extension */
01596    if (!id) {
01597       cbprev = NULL;
01598       cblist = statecbs;
01599       while (cblist) {
01600          if (cblist->callback == callback) {
01601             if (!cbprev)
01602                   statecbs = cblist->next;
01603             else
01604                   cbprev->next = cblist->next;
01605 
01606             free(cblist);
01607 
01608                ast_mutex_unlock(&hintlock);
01609             return 0;
01610             }
01611             cbprev = cblist;
01612             cblist = cblist->next;
01613       }
01614 
01615          ast_mutex_lock(&hintlock);
01616       return -1;
01617    }
01618 
01619    /* id greater than zero is a callback with extension */
01620    list = hints;
01621    while (list) {
01622       cblist = list->callbacks;
01623       cbprev = NULL;
01624       while (cblist) {
01625             if (cblist->id==id) {
01626             if (!cbprev)
01627                   list->callbacks = cblist->next;     
01628             else
01629                   cbprev->next = cblist->next;
01630       
01631             free(cblist);
01632       
01633             ast_mutex_unlock(&hintlock);
01634             return 0;      
01635             }     
01636                cbprev = cblist;           
01637             cblist = cblist->next;
01638       }
01639       list = list->next;
01640    }
01641     
01642    ast_mutex_unlock(&hintlock);
01643    return -1;
01644 }

char* ast_get_context_name struct ast_context con  ) 
 

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

04955 {
04956    return con ? con->name : NULL;
04957 }

char* ast_get_context_registrar struct ast_context c  ) 
 

Definition at line 4982 of file pbx.c.

References ast_context::registrar.

04983 {
04984    return c ? c->registrar : NULL;
04985 }

char* ast_get_extension_app struct ast_exten e  ) 
 

Definition at line 5012 of file pbx.c.

References ast_exten::app.

Referenced by ast_device_state_changed(), and ast_get_hint().

05013 {
05014    return e ? e->app : NULL;
05015 }

void* ast_get_extension_app_data struct ast_exten e  ) 
 

Definition at line 5017 of file pbx.c.

References ast_exten::data.

05018 {
05019    return e ? e->data : NULL;
05020 }

char* ast_get_extension_cidmatch struct ast_exten e  ) 
 

Definition at line 5007 of file pbx.c.

References ast_exten::cidmatch.

05008 {
05009    return e ? e->cidmatch : NULL;
05010 }

int ast_get_extension_matchcid struct ast_exten e  ) 
 

Definition at line 5002 of file pbx.c.

References ast_exten::matchcid.

05003 {
05004    return e ? e->matchcid : 0;
05005 }

char* ast_get_extension_name struct ast_exten exten  ) 
 

Definition at line 4959 of file pbx.c.

References ast_exten::exten.

04960 {
04961    return exten ? exten->exten : NULL;
04962 }

int ast_get_extension_priority struct ast_exten exten  ) 
 

Definition at line 4974 of file pbx.c.

References ast_exten::priority.

04975 {
04976    return exten ? exten->priority : -1;
04977 }

char* ast_get_extension_registrar struct ast_exten e  ) 
 

Definition at line 4987 of file pbx.c.

References ast_exten::registrar.

04988 {
04989    return e ? e->registrar : NULL;
04990 }

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

If an extension exists, return non-zero.

Parameters:
hint buffer for hint
maxlen size of hint 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 1745 of file pbx.c.

References ast_get_extension_app().

01746 {
01747    struct ast_exten *e;
01748    e = ast_hint_extension(c, context, exten);
01749    if (e) { 
01750        strncpy(hint, ast_get_extension_app(e), hintsize - 1);
01751        return -1;
01752    }
01753    return 0;   
01754 }

char* ast_get_ignorepat_name struct ast_ignorepat ip  ) 
 

Definition at line 4969 of file pbx.c.

References ast_ignorepat::pattern.

04970 {
04971    return ip ? ip->pattern : NULL;
04972 }

char* ast_get_ignorepat_registrar struct ast_ignorepat ip  ) 
 

Definition at line 4997 of file pbx.c.

References ast_ignorepat::registrar.

04998 {
04999    return ip ? ip->registrar : NULL;
05000 }

char* ast_get_include_name struct ast_include inc  ) 
 

Definition at line 4964 of file pbx.c.

References ast_include::name.

04965 {
04966    return inc ? inc->name : NULL;
04967 }

char* ast_get_include_registrar struct ast_include i  ) 
 

Definition at line 4992 of file pbx.c.

References ast_include::registrar.

04993 {
04994    return i ? i->registrar : NULL;
04995 }

char* ast_get_switch_data struct ast_sw sw  ) 
 

Definition at line 5027 of file pbx.c.

References ast_sw::data.

05028 {
05029    return sw ? sw->data : NULL;
05030 }

char* ast_get_switch_name struct ast_sw sw  ) 
 

Definition at line 5022 of file pbx.c.

References ast_sw::name.

05023 {
05024    return sw ? sw->name : NULL;
05025 }

char* ast_get_switch_registrar struct ast_sw sw  ) 
 

Definition at line 5032 of file pbx.c.

References ast_sw::registrar.

05033 {
05034    return sw ? sw->registrar : NULL;
05035 }

int ast_ignore_pattern char *  context,
char *  pattern
 

Checks to see if a number should be ignored.

Parameters:
context context to search within
extension 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 3645 of file pbx.c.

References ast_context_find(), ast_extension_match(), and ast_context::ignorepats.

03646 {
03647    struct ast_context *con;
03648    struct ast_ignorepat *pat;
03649 
03650    con = ast_context_find(context);
03651    if (con) {
03652       pat = con->ignorepats;
03653       while (pat) {
03654          if (ast_extension_match(pat->pattern, pattern))
03655             return 1;
03656          pat = pat->next;
03657       }
03658    } 
03659    return 0;
03660 }

int ast_lock_context struct ast_context con  ) 
 

Locks a given context.

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

Definition at line 4941 of file pbx.c.

References ast_mutex_lock, and ast_context::lock.

04942 {
04943    return ast_mutex_lock(&con->lock);
04944 }

int ast_lock_contexts void   ) 
 

Locks the contexts.

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

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

04929 {
04930    return ast_mutex_lock(&conlock);
04931 }

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

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

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

Definition at line 1766 of file pbx.c.

References HELPER_MATCHMORE.

Referenced by ast_pbx_run().

01767 {
01768    return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_MATCHMORE);
01769 }

void ast_merge_contexts_and_delete struct ast_context **  extcontexts,
char *  registrar
 

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

Parameters:
extcontexts pointer to the ast_context structure pointer
registar 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 3015 of file pbx.c.

References __ast_context_destroy(), ast_log(), ast_mutex_lock, ast_mutex_unlock, LOG_WARNING, and ast_context::next.

03015                                                                                       {
03016    struct ast_context *tmp, *lasttmp = NULL;
03017    tmp = *extcontexts;
03018    ast_mutex_lock(&conlock);
03019    if (registrar) {
03020       __ast_context_destroy(NULL,registrar);
03021       while (tmp) {
03022          lasttmp = tmp;
03023          tmp = tmp->next;
03024       }
03025    } else {
03026       while (tmp) {
03027          __ast_context_destroy(tmp,tmp->registrar);
03028          lasttmp = tmp;
03029          tmp = tmp->next;
03030       }
03031    }
03032    if (lasttmp) {
03033       lasttmp->next = contexts;
03034       contexts = *extcontexts;
03035       *extcontexts = NULL;
03036    } else 
03037       ast_log(LOG_WARNING, "Requested contexts didn't get merged\n");
03038    ast_mutex_unlock(&conlock);
03039    return;  
03040 }

AST_MUTEX_DEFINE_STATIC hintlock   ) 
 

AST_MUTEX_DEFINE_STATIC switchlock   ) 
 

AST_MUTEX_DEFINE_STATIC conlock   ) 
 

AST_MUTEX_DEFINE_STATIC applock   ) 
 

int ast_pbx_outgoing_app char *  type,
int  format,
void *  data,
int  timeout,
char *  app,
char *  appdata,
int *  reason,
int  sync,
char *  callerid,
char *  variable,
char *  account,
char *  uniqueid
 

Definition at line 4185 of file pbx.c.

References ast_hangup(), ast_log(), ast_pbx_run_app(), ast_pthread_create(), ast_request_and_dial(), AST_STATE_UP, ast_verbose(), free, LOG_ERROR, LOG_WARNING, malloc, option_verbose, pbx_builtin_setvar(), and VERBOSE_PREFIX_4.

04186 {
04187    struct ast_channel *chan;
04188    struct async_stat *as;
04189    struct app_tmp *tmp;
04190    char *var, *vartmp;
04191    int res = -1;
04192    pthread_attr_t attr;
04193    
04194    if (!app || ast_strlen_zero(app))
04195       return -1;
04196    if (sync) {
04197       chan = ast_request_and_dial(type, format, data, timeout, reason, 0, callerid, uniqueid);
04198       if (chan) {
04199          pbx_builtin_setaccount(chan, account);
04200          if (variable) {
04201             vartmp = ast_strdupa(variable);
04202             for (var = strtok_r(vartmp, "|", &vartmp); var; var = strtok_r(NULL, "|", &vartmp)) {
04203                pbx_builtin_setvar( chan, var );
04204             }
04205          }
04206          if (chan->_state == AST_STATE_UP) {
04207             res = 0;
04208             if (option_verbose > 3)
04209                ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", chan->name);
04210             tmp = malloc(sizeof(struct app_tmp));
04211             if (tmp) {
04212                memset(tmp, 0, sizeof(struct app_tmp));
04213                strncpy(tmp->app, app, sizeof(tmp->app) - 1);
04214                strncpy(tmp->data, appdata, sizeof(tmp->data) - 1);
04215                tmp->chan = chan;
04216                if (sync > 1) {
04217                   ast_pbx_run_app(tmp);
04218                } else {
04219                   pthread_attr_init(&attr);
04220                   pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
04221                   if (ast_pthread_create(&tmp->t, &attr, ast_pbx_run_app, tmp)) {
04222                      ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno));
04223                      free(tmp);
04224                      ast_hangup(chan);
04225                      res = -1;
04226                   }
04227                }
04228             } else {
04229                ast_log(LOG_ERROR, "Out of memory :(\n");
04230                res = -1;
04231             }
04232          } else {
04233             if (option_verbose > 3)
04234                ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", chan->name);
04235             ast_hangup(chan);
04236          }
04237       }
04238    } else {
04239       as = malloc(sizeof(struct async_stat));
04240       if (!as)
04241          return -1;
04242       memset(as, 0, sizeof(struct async_stat));
04243       chan = ast_request_and_dial(type, format, data, timeout, reason, 0, callerid, uniqueid);
04244       if (!chan) {
04245          free(as);
04246          return -1;
04247       }
04248       pbx_builtin_setaccount(chan, account);
04249       as->chan = chan;
04250       strncpy(as->app, app, sizeof(as->app) - 1);
04251       if (appdata)
04252          strncpy(as->appdata,  appdata, sizeof(as->appdata) - 1);
04253       as->timeout = timeout;
04254       if (variable) {
04255          vartmp = ast_strdupa(variable);
04256          for (var = strtok_r(vartmp, "|", &vartmp); var; var = strtok_r(NULL, "|", &vartmp))
04257             pbx_builtin_setvar( chan, var );
04258       }
04259       /* Start a new thread, and get something handling this channel. */
04260       pthread_attr_init(&attr);
04261       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
04262       if (ast_pthread_create(&as->p, &attr, async_wait, as)) {
04263          ast_log(LOG_WARNING, "Failed to start async wait\n");
04264          free(as);
04265          ast_hangup(chan);
04266          return -1;
04267       }
04268       res = 0;
04269    }
04270    return res;
04271 }

int ast_pbx_outgoing_exten char *  type,
int  format,
void *  data,
int  timeout,
char *  context,
char *  exten,
int  priority,
int *  reason,
int  sync,
int  callingpres,
char *  callerid,
char *  variable,
char *  account,
char *  uniqueid
 

Definition at line 4067 of file pbx.c.

References __ast_request_and_dial(), ast_channel_alloc(), ast_exists_extension(), ast_hangup(), ast_log(), ast_pbx_run(), ast_pbx_start(), ast_pthread_create(), ast_request_and_dial(), AST_STATE_UP, ast_verbose(), ast_channel::context, ast_channel::exten, free, LOAD_OH, LOG_ERROR, LOG_WARNING, malloc, ast_channel::name, option_verbose, pbx_builtin_setvar(), ast_channel::priority, and VERBOSE_PREFIX_4.

04068 {
04069    struct ast_channel *chan;
04070    struct async_stat *as;
04071    int res = -1;
04072    char *var, *tmp;
04073    struct outgoing_helper oh;
04074    pthread_attr_t attr;
04075       
04076    if (sync) {
04077       LOAD_OH(oh);
04078       chan = __ast_request_and_dial(type, format, data, timeout, reason, callingpres, callerid, &oh, uniqueid);
04079       if (chan) {
04080          pbx_builtin_setaccount(chan, account);
04081          if (chan->_state == AST_STATE_UP) {
04082                res = 0;
04083             if (option_verbose > 3)
04084                ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", chan->name);
04085 
04086             if (sync > 1) {
04087                if (ast_pbx_run(chan)) {
04088                   ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name);
04089                   ast_hangup(chan);
04090                   res = -1;
04091                }
04092             } else {
04093                if (ast_pbx_start(chan)) {
04094                   ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name);
04095                   ast_hangup(chan);
04096                   res = -1;
04097                } 
04098             }
04099          } else {
04100             if (option_verbose > 3)
04101                ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", chan->name);
04102             ast_hangup(chan);
04103          }
04104       }
04105 
04106       if(res < 0) { /* the call failed for some reason */
04107          /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */
04108          /* check if "failed" exists */
04109          if (ast_exists_extension(chan, context, "failed", 1, NULL)) {
04110             chan = ast_channel_alloc(0);
04111             if (chan) {
04112                strncpy(chan->name, "OutgoingSpoolFailed", sizeof(chan->name) - 1);
04113                if (context && !ast_strlen_zero(context))
04114                   strncpy(chan->context, context, sizeof(chan->context) - 1);
04115                strncpy(chan->exten, "failed", sizeof(chan->exten) - 1);
04116                chan->priority = 1;
04117                if (variable) {
04118                   tmp = ast_strdupa(variable);
04119                   for (var = strtok_r(tmp, "|", &tmp); var; var = strtok_r(NULL, "|", &tmp)) {
04120                      pbx_builtin_setvar( chan, var );
04121                   }
04122                }
04123                ast_pbx_run(chan);   
04124             } else
04125                ast_log(LOG_WARNING, "Can't allocate the channel structure, skipping execution of extension 'failed'\n");
04126          }
04127       }
04128    } else {
04129       as = malloc(sizeof(struct async_stat));
04130       if (!as)
04131          return -1;
04132       memset(as, 0, sizeof(struct async_stat));
04133       chan = ast_request_and_dial(type, format, data, timeout, reason, callingpres, callerid, uniqueid);
04134       if (!chan) {
04135          free(as);
04136          return -1;
04137       }
04138       pbx_builtin_setaccount(chan, account);
04139       as->chan = chan;
04140       strncpy(as->context, context, sizeof(as->context) - 1);
04141       strncpy(as->exten,  exten, sizeof(as->exten) - 1);
04142       as->priority = priority;
04143       as->timeout = timeout;
04144       if (variable) {
04145          tmp = ast_strdupa(variable);
04146          for (var = strtok_r(tmp, "|", &tmp); var; var = strtok_r(NULL, "|", &tmp))
04147             pbx_builtin_setvar( chan, var );
04148       }
04149       pthread_attr_init(&attr);
04150       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
04151       if (ast_pthread_create(&as->p, &attr, async_wait, as)) {
04152          ast_log(LOG_WARNING, "Failed to start async wait\n");
04153          free(as);
04154          ast_hangup(chan);
04155          return -1;
04156       }
04157       res = 0;
04158    }
04159    return res;
04160 }

int ast_pbx_run struct ast_channel c  ) 
 

Execute the PBX in the current thread.

Parameters:
c channel to run the pbx on This executes the PBX on a given channel. It allocates a new PBX structure for the channel, and provides all PBX functionality.

Definition at line 1776 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_hangup(), ast_log(), ast_matchmore_extension(), AST_PBX_KEEPALIVE, AST_SOFTHANGUP_ASYNCGOTO, AST_SOFTHANGUP_TIMEOUT, ast_spawn_extension(), ast_verbose(), ast_waitfordigit(), ast_channel::callerid, ast_channel::cdr, ast_channel::context, ast_pbx::dtimeout, ast_channel::exten, free, LOG_DEBUG, LOG_ERROR, LOG_WARNING, malloc, ast_channel::name, option_debug, option_verbose, ast_channel::pbx, pbx_builtin_setvar_helper(), ast_channel::priority, ast_pbx::rtimeout, VERBOSE_PREFIX_2, VERBOSE_PREFIX_3, and ast_channel::whentohangup.

Referenced by ast_pbx_outgoing_exten().

01777 {
01778    int firstpass = 1;
01779    char digit;
01780    char exten[256];
01781    int pos;
01782    int waittime;
01783    int res=0;
01784 
01785    /* A little initial setup here */
01786    if (c->pbx)
01787       ast_log(LOG_WARNING, "%s already has PBX structure??\n", c->name);
01788    c->pbx = malloc(sizeof(struct ast_pbx));
01789    if (!c->pbx) {
01790       ast_log(LOG_ERROR, "Out of memory\n");
01791       return -1;
01792    }
01793    if (c->amaflags) {
01794       if (c->cdr) {
01795          ast_log(LOG_WARNING, "%s already has a call record??\n", c->name);
01796       } else {
01797          c->cdr = ast_cdr_alloc();
01798          if (!c->cdr) {
01799             ast_log(LOG_WARNING, "Unable to create Call Detail Record\n");
01800             free(c->pbx);
01801             return -1;
01802          }
01803          ast_cdr_init(c->cdr, c);
01804       }
01805    }
01806    memset(c->pbx, 0, sizeof(struct ast_pbx));
01807    /* Set reasonable defaults */
01808    c->pbx->rtimeout = 10;
01809    c->pbx->dtimeout = 5;
01810 
01811    /* Start by trying whatever the channel is set to */
01812    if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) {
01813       /* JK02: If not successfull fall back to 's' */
01814       if (option_verbose > 1)
01815          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);
01816       strncpy(c->exten, "s", sizeof(c->exten)-1);
01817       if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) {
01818          /* JK02: And finally back to default if everything else failed */
01819          if (option_verbose > 1)
01820             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);
01821          strncpy(c->context, "default", sizeof(c->context)-1);
01822       }
01823       c->priority = 1;
01824    }
01825    if (c->cdr)
01826       ast_cdr_start(c->cdr);
01827    for(;;) {
01828       pos = 0;
01829       digit = 0;
01830       while(ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) {
01831          memset(exten, 0, sizeof(exten));
01832          if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->callerid))) {
01833             /* Something bad happened, or a hangup has been requested. */
01834             if (((res >= '0') && (res <= '9')) || ((res >= 'A') && (res <= 'F')) ||
01835                (res == '*') || (res == '#')) {
01836                ast_log(LOG_DEBUG, "Oooh, got something to jump out with ('%c')!\n", res);
01837                memset(exten, 0, sizeof(exten));
01838                pos = 0;
01839                exten[pos++] = digit = res;
01840                break;
01841             }
01842             switch(res) {
01843             case AST_PBX_KEEPALIVE:
01844                if (option_debug)
01845                   ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
01846                else if (option_verbose > 1)
01847                   ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
01848                goto out;
01849                break;
01850             default:
01851                if (option_debug)
01852                   ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
01853                else if (option_verbose > 1)
01854                   ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
01855                if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
01856                   c->_softhangup =0;
01857                   break;
01858                }
01859                /* atimeout */
01860                if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) {
01861                   break;
01862                }
01863 
01864                if (c->cdr) {
01865                   ast_cdr_update(c);
01866                }
01867                goto out;
01868             }
01869          }
01870          if ((c->_softhangup == AST_SOFTHANGUP_TIMEOUT) && (ast_exists_extension(c,c->context,"T",1,c->callerid))) {
01871             strncpy(c->exten,"T",sizeof(c->exten) - 1);
01872             /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
01873             c->whentohangup = 0;
01874             c->priority = 0;
01875             c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT;
01876          } else if (c->_softhangup) {
01877             ast_log(LOG_DEBUG, "Extension %s, priority %d returned normally even though call was hung up\n",
01878                c->exten, c->priority);
01879             goto out;
01880          }
01881          firstpass = 0;
01882          c->priority++;
01883       }
01884       if (!ast_exists_extension(c, c->context, c->exten, 1, c->callerid)) {
01885          /* It's not a valid extension anymore */
01886          if (ast_exists_extension(c, c->context, "i", 1, c->callerid)) {
01887             if (option_verbose > 2)
01888                ast_verbose(VERBOSE_PREFIX_3 "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, c->name);
01889             pbx_builtin_setvar_helper(c, "INVALID_EXTEN", c->exten);
01890             strncpy(c->exten, "i", sizeof(c->exten)-1);
01891             c->priority = 1;
01892          } else {
01893             ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n",
01894                c->name, c->exten, c->context);
01895             goto out;
01896          }
01897       } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) {
01898          /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */
01899          c->_softhangup = 0;
01900       } else {
01901          /* Done, wait for an extension */
01902          if (digit)
01903             waittime = c->pbx->dtimeout;
01904          else
01905             waittime = c->pbx->rtimeout;
01906          while (ast_matchmore_extension(c, c->context, exten, 1, c->callerid)) {
01907             /* As long as we're willing to wait, and as long as it's not defined, 
01908                keep reading digits until we can't possibly get a right answer anymore.  */
01909             digit = ast_waitfordigit(c, waittime * 1000);
01910             if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
01911                c->_softhangup = 0;
01912             } else {
01913                if (!digit)
01914                   /* No entry */
01915                   break;
01916                if (digit < 0)
01917                   /* Error, maybe a  hangup */
01918                   goto out;
01919                exten[pos++] = digit;
01920                waittime = c->pbx->dtimeout;
01921             }
01922          }
01923          if (ast_exists_extension(c, c->context, exten, 1, c->callerid)) {
01924             /* Prepare the next cycle */
01925             strncpy(c->exten, exten, sizeof(c->exten)-1);
01926             c->priority = 1;
01927          } else {
01928             /* No such extension */
01929             if (!ast_strlen_zero(exten)) {
01930                /* An invalid extension */
01931                if (ast_exists_extension(c, c->context, "i", 1, c->callerid)) {
01932                   if (option_verbose > 2)
01933                      ast_verbose( VERBOSE_PREFIX_3 "Invalid extension '%s' in context '%s' on %s\n", exten, c->context, c->name);
01934                   pbx_builtin_setvar_helper(c, "INVALID_EXTEN", exten);
01935                   strncpy(c->exten, "i", sizeof(c->exten)-1);
01936                   c->priority = 1;
01937                } else {
01938                   ast_log(LOG_WARNING, "Invalid extension '%s', but no rule 'i' in context '%s'\n", exten, c->context);
01939                   goto out;
01940                }
01941             } else {
01942                /* A simple timeout */
01943                if (ast_exists_extension(c, c->context, "t", 1, c->callerid)) {
01944                   if (option_verbose > 2)
01945                      ast_verbose( VERBOSE_PREFIX_3 "Timeout on %s\n", c->name);
01946                   strncpy(c->exten, "t", sizeof(c->exten)-1);
01947                   c->priority = 1;
01948                } else {
01949                   ast_log(LOG_WARNING, "Timeout, but no rule 't' in context '%s'\n", c->context);
01950                   goto out;
01951                }
01952             }  
01953          }
01954          if (c->cdr) {
01955             if (option_verbose > 2)
01956                ast_verbose(VERBOSE_PREFIX_2 "CDR updated on %s\n",c->name);   
01957             ast_cdr_update(c);
01958           }
01959       }
01960    }
01961    if (firstpass) 
01962       ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name);
01963 out:
01964    if ((res != AST_PBX_KEEPALIVE) && ast_exists_extension(c, c->context, "h", 1, c->callerid)) {
01965       c->exten[0] = 'h';
01966       c->exten[1] = '\0';
01967       c->priority = 1;
01968       while(ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) {
01969          if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->callerid))) {
01970             /* Something bad happened, or a hangup has been requested. */
01971             if (option_debug)
01972                ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
01973             else if (option_verbose > 1)
01974                ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
01975             break;
01976          }
01977          c->priority++;
01978       }
01979    }
01980 
01981    pbx_destroy(c->pbx);
01982    c->pbx = NULL;
01983    if (res != AST_PBX_KEEPALIVE)
01984       ast_hangup(c);
01985    return 0;
01986 }

void* ast_pbx_run_app void *  data  ) 
 

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

04170 {
04171    struct app_tmp *tmp = data;
04172    struct ast_app *app;
04173    app = pbx_findapp(tmp->app);
04174    if (app) {
04175       if (option_verbose > 3)
04176          ast_verbose(VERBOSE_PREFIX_4 "Lauching %s(%s) on %s\n", tmp->app, tmp->data, tmp->chan->name);
04177       pbx_exec(tmp->chan, app, tmp->data, 1);
04178    } else
04179       ast_log(LOG_WARNING, "No such application '%s'\n", tmp->app);
04180    ast_hangup(tmp->chan);
04181    free(tmp);
04182    return NULL;
04183 }

int ast_pbx_start struct ast_channel c  ) 
 

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

Parameters:
c channel to start the pbx on Starts a pbx thread on a given channel It returns -1 on failure, and 0 on success

Definition at line 2001 of file pbx.c.

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

Referenced by ast_async_goto(), and ast_pbx_outgoing_exten().

02002 {
02003    pthread_t t;
02004    pthread_attr_t attr;
02005    if (!c) {
02006       ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
02007       return -1;
02008    }
02009       
02010    /* Start a new thread, and get something handling this channel. */
02011    pthread_attr_init(&attr);
02012    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
02013    if (ast_pthread_create(&t, &attr, pbx_thread, c)) {
02014       ast_log(LOG_WARNING, "Failed to create new channel thread\n");
02015       return -1;
02016    }
02017    return 0;
02018 }

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

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

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

Definition at line 2309 of file pbx.c.

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

Referenced by load_pbx().

02310 {
02311    struct ast_app *tmp, *prev, *cur;
02312    char tmps[80];
02313    if (ast_mutex_lock(&applock)) {
02314       ast_log(LOG_ERROR, "Unable to lock application list\n");
02315       return -1;
02316    }
02317    tmp = apps;
02318    while(tmp) {
02319       if (!strcasecmp(app, tmp->name)) {
02320          ast_log(LOG_WARNING, "Already have an application '%s'\n", app);
02321          ast_mutex_unlock(&applock);
02322          return -1;
02323       }
02324       tmp = tmp->next;
02325    }
02326    tmp = malloc(sizeof(struct ast_app));
02327    if (tmp) {
02328       memset(tmp, 0, sizeof(struct ast_app));
02329       strncpy(tmp->name, app, sizeof(tmp->name)-1);
02330       tmp->execute = execute;
02331       tmp->synopsis = synopsis;
02332       tmp->description = description;
02333       /* Store in alphabetical order */
02334       cur = apps;
02335       prev = NULL;
02336       while(cur) {
02337          if (strcasecmp(tmp->name, cur->name) < 0)
02338             break;
02339          prev = cur;
02340          cur = cur->next;
02341       }
02342       if (prev) {
02343          tmp->next = prev->next;
02344          prev->next = tmp;
02345       } else {
02346          tmp->next = apps;
02347          apps = tmp;
02348       }
02349    } else {
02350       ast_log(LOG_ERROR, "Out of memory\n");
02351       ast_mutex_unlock(&applock);
02352       return -1;
02353    }
02354    if (option_verbose > 1)
02355       ast_verbose( VERBOSE_PREFIX_2 "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps)));
02356    ast_mutex_unlock(&applock);
02357    return 0;
02358 }

int ast_register_switch struct ast_switch sw  ) 
 

Register an alternative switch.

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

Definition at line 2360 of file pbx.c.

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

02361 {
02362    struct ast_switch *tmp, *prev=NULL;
02363    if (ast_mutex_lock(&switchlock)) {
02364       ast_log(LOG_ERROR, "Unable to lock switch lock\n");
02365       return -1;
02366    }
02367    tmp = switches;
02368    while(tmp) {
02369       if (!strcasecmp(tmp->name, sw->name))
02370          break;
02371       prev = tmp;
02372       tmp = tmp->next;
02373    }
02374    if (tmp) {  
02375       ast_mutex_unlock(&switchlock);
02376       ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name);
02377       return -1;
02378    }
02379    sw->next = NULL;
02380    if (prev) 
02381       prev->next = sw;
02382    else
02383       switches = sw;
02384    ast_mutex_unlock(&switchlock);
02385    return 0;
02386 }

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

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

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

Definition at line 1771 of file pbx.c.

References HELPER_SPAWN.

Referenced by ast_pbx_run().

01772 {
01773    return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_SPAWN);
01774 }

int ast_unlock_context struct ast_context con  ) 
 

Unlocks the given context.

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

Definition at line 4946 of file pbx.c.

References ast_mutex_unlock, and ast_context::lock.

04947 {
04948    return ast_mutex_unlock(&con->lock);
04949 }

int ast_unlock_contexts void   ) 
 

Unlocks contexts.

Returns 0 on success, -1 on failure

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

04934 {
04935    return ast_mutex_unlock(&conlock);
04936 }

int ast_unregister_application char *  app  ) 
 

Remove an application.

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

Definition at line 2944 of file pbx.c.

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

02944                                           {
02945    struct ast_app *tmp, *tmpl = NULL;
02946    if (ast_mutex_lock(&applock)) {
02947       ast_log(LOG_ERROR, "Unable to lock application list\n");
02948       return -1;
02949    }
02950    tmp = apps;
02951    while(tmp) {
02952       if (!strcasecmp(app, tmp->name)) {
02953          if (tmpl)
02954             tmpl->next = tmp->next;
02955          else
02956             apps = tmp->next;
02957          if (option_verbose > 1)
02958             ast_verbose( VERBOSE_PREFIX_2 "Unregistered application '%s'\n", tmp->name);
02959          free(tmp);
02960          ast_mutex_unlock(&applock);
02961          return 0;
02962       }
02963       tmpl = tmp;
02964       tmp = tmp->next;
02965    }
02966    ast_mutex_unlock(&applock);
02967    return -1;
02968 }

void ast_unregister_switch struct ast_switch sw  ) 
 

Unregister an alternative switch.

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

Definition at line 2388 of file pbx.c.

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

02389 {
02390    struct ast_switch *tmp, *prev=NULL;
02391    if (ast_mutex_lock(&switchlock)) {
02392       ast_log(LOG_ERROR, "Unable to lock switch lock\n");
02393       return;
02394    }
02395    tmp = switches;
02396    while(tmp) {
02397       if (tmp == sw) {
02398          if (prev)
02399             prev->next = tmp->next;
02400          else
02401             switches = tmp->next;
02402          tmp->next = NULL;
02403          break;         
02404       }
02405       prev = tmp;
02406       tmp = tmp->next;
02407    }
02408    ast_mutex_unlock(&switchlock);
02409 }

struct ast_exten* ast_walk_context_extensions struct ast_context con,
struct ast_exten exten
 

Definition at line 5048 of file pbx.c.

References ast_exten::next.

05050 {
05051    if (!exten)
05052       return con ? con->root : NULL;
05053    else
05054       return exten->next;
05055 }

struct ast_ignorepat* ast_walk_context_ignorepats struct ast_context con,
struct ast_ignorepat ip
 

Definition at line 5084 of file pbx.c.

References ast_ignorepat::next.

05086 {
05087    if (!ip)
05088       return con ? con->ignorepats : NULL;
05089    else
05090       return ip->next;
05091 }

struct ast_include* ast_walk_context_includes struct ast_context con,
struct ast_include inc
 

Definition at line 5075 of file pbx.c.

References ast_include::next.

Referenced by ast_context_verify_includes().

05077 {
05078    if (!inc)
05079       return con ? con->includes : NULL;
05080    else
05081       return inc->next;
05082 }

struct ast_sw* ast_walk_context_switches struct ast_context con,
struct ast_sw sw
 

Definition at line 5057 of file pbx.c.

References ast_sw::next.

05059 {
05060    if (!sw)
05061       return con ? con->alts : NULL;
05062    else
05063       return sw->next;
05064 }

struct ast_context* ast_walk_contexts struct ast_context con  ) 
 

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

05041 {
05042    if (!con)
05043       return contexts;
05044    else
05045       return con->next;
05046 }

struct ast_exten* ast_walk_extension_priorities struct ast_exten exten,
struct ast_exten priority
 

Definition at line 5066 of file pbx.c.

References ast_exten::peer.

05068 {
05069    if (!priority)
05070       return exten;
05071    else
05072       return priority->peer;
05073 }

int load_pbx void   ) 
 

Definition at line 4898 of file pbx.c.

References ast_cli_register(), AST_LIST_HEAD_INIT, ast_log(), ast_register_application(), ast_verbose(), LOG_ERROR, option_verbose, and VERBOSE_PREFIX_1.

Referenced by main().

04899 {
04900    int x;
04901 
04902    /* Initialize the PBX */
04903    if (option_verbose) {
04904       ast_verbose( "Asterisk PBX Core Initializing\n");
04905       ast_verbose( "Registering builtin applications:\n");
04906    }
04907         AST_LIST_HEAD_INIT(&globals);
04908    ast_cli_register(&show_applications_cli);
04909    ast_cli_register(&show_application_cli);
04910    ast_cli_register(&show_dialplan_cli);
04911    ast_cli_register(&show_switches_cli);
04912 
04913    /* Register builtin applications */
04914    for (x=0; x<sizeof(builtins) / sizeof(struct pbx_builtin); x++) {
04915       if (option_verbose)
04916          ast_verbose( VERBOSE_PREFIX_1 "[%s]\n", builtins[x].name);
04917       if (ast_register_application(builtins[x].name, builtins[x].execute, builtins[x].synopsis, builtins[x].description)) {
04918          ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name);
04919          return -1;
04920       }
04921    }
04922    return 0;
04923 }

void pbx_builtin_clear_globals void   ) 
 

Definition at line 4786 of file pbx.c.

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

04787 {
04788    struct ast_var_t *vardata;
04789    while (!AST_LIST_EMPTY(&globals)) {
04790       vardata = AST_LIST_FIRST(&globals);
04791       AST_LIST_REMOVE_HEAD(&globals, entries);
04792       ast_var_delete(vardata);
04793    }
04794 }

char * pbx_builtin_getvar_helper struct ast_channel chan,
char *  name
 

Definition at line 4686 of file pbx.c.

References AST_LIST_TRAVERSE, ast_var_name(), and ast_var_value().

04687 {
04688    struct ast_var_t *variables;
04689    struct varshead *headp;
04690 
04691    if (chan)
04692       headp=&chan->varshead;
04693    else
04694       headp=&globals;
04695 
04696    if (name) {
04697       AST_LIST_TRAVERSE(headp,variables,entries) {
04698          if (!strcmp(name, ast_var_name(variables)))
04699             return ast_var_value(variables);
04700       }
04701       if (headp != &globals) {
04702          /* Check global variables if we haven't already */
04703          headp = &globals;
04704          AST_LIST_TRAVERSE(headp,variables,entries) {
04705             if (!strcmp(name, ast_var_name(variables)))
04706                return ast_var_value(variables);
04707          }
04708       }
04709    }
04710    return NULL;
04711 }

int pbx_builtin_setvar struct ast_channel ,
void * 
 

Definition at line 4739 of file pbx.c.

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

Referenced by __ast_request_and_dial(), ast_pbx_outgoing_app(), and ast_pbx_outgoing_exten().

04740 {
04741    char *name;
04742    char *value;
04743    char *stringp=NULL;
04744                 
04745    if (!data || ast_strlen_zero(data)) {
04746       ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n");
04747       return 0;
04748    }
04749    
04750    stringp=data;
04751    name=strsep(&stringp,"=");
04752    value=strsep(&stringp,"\0"); 
04753    
04754    pbx_builtin_setvar_helper(chan,name,value);
04755          
04756         return(0);
04757 }

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

Definition at line 4713 of file pbx.c.

References AST_LIST_INSERT_HEAD, AST_LIST_REMOVE, AST_LIST_TRAVERSE, ast_var_assign(), ast_var_delete(), ast_var_name(), ast_verbose(), option_verbose, and VERBOSE_PREFIX_3.

Referenced by ast_pbx_run(), and pbx_builtin_setvar().

04714 {
04715    struct ast_var_t *newvariable;
04716    struct varshead *headp;
04717    if (chan)
04718       headp=&chan->varshead;
04719    else
04720       headp=&globals;
04721                 
04722    AST_LIST_TRAVERSE (headp,newvariable,entries) {
04723       if (strcasecmp(ast_var_name(newvariable),name)==0) {
04724          /* there is already such a variable, delete it */
04725          AST_LIST_REMOVE(headp,newvariable,ast_var_t,entries);
04726          ast_var_delete(newvariable);
04727          break;
04728       }
04729    } 
04730    
04731    if (value) {
04732       if ((option_verbose > 1) && (headp == &globals))
04733          ast_verbose(VERBOSE_PREFIX_3 "Setting global variable '%s' to '%s'\n",name, value);
04734       newvariable=ast_var_assign(name,value);   
04735       AST_LIST_INSERT_HEAD(headp,newvariable,entries);
04736    }
04737 }

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

executes an application

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

Definition at line 426 of file pbx.c.

References ast_channel::app, ast_channel::appl, ast_cdr_setapp(), AST_CHANNEL_MAX_STACK, ast_log(), ast_channel::cdr, ast_channel::data, ast_app::execute, ast_channel::jmp, LOG_WARNING, ast_app::name, and ast_channel::stack.

Referenced by ast_pbx_run_app().

00430 {
00431    /* This function is special.  It saves the stack so that no matter
00432       how many times it is called, it returns to the same place */
00433    int res;
00434    
00435    char *saved_c_appl;
00436    char *saved_c_data;
00437    
00438    int stack = c->stack;
00439    int (*execute)(struct ast_channel *chan, void *data) = app->execute; 
00440 
00441    if (newstack && stack > AST_CHANNEL_MAX_STACK - 2) {
00442       /* Don't allow us to go over the max number of stacks we
00443          permit saving. */
00444       ast_log(LOG_WARNING, "Stack overflow, cannot create another stack\n");
00445       return -1;
00446    }
00447    if (newstack && (res = setjmp(c->jmp[++c->stack]))) {
00448       /* Okay, here's where it gets weird.  If newstack is non-zero, 
00449          then we increase the stack increment, but setjmp is not going
00450          to return until longjmp is called -- when the application
00451          exec'd is finished running. */
00452       if (res == 1)
00453          res = 0;
00454       if (c->stack != stack + 1) 
00455          ast_log(LOG_WARNING, "Stack returned to an unexpected place!\n");
00456       else if (c->app[c->stack])
00457          ast_log(LOG_WARNING, "Application may have forgotten to free its memory\n");
00458       c->stack = stack;
00459       return res;
00460    } else {
00461       if (c->cdr)
00462          ast_cdr_setapp(c->cdr, app->name, data);
00463 
00464       /* save channel values */
00465       saved_c_appl= c->appl;
00466       saved_c_data= c->data;
00467 
00468       c->appl = app->name;
00469       c->data = data;      
00470       res = execute(c, data);
00471       /* restore channel values */
00472       c->appl= saved_c_appl;
00473       c->data= saved_c_data;
00474 
00475       /* Any application that returns, we longjmp back, just in case. */
00476       if (c->stack != stack + 1)
00477          ast_log(LOG_WARNING, "Stack is not at expected value\n");
00478       longjmp(c->jmp[stack+1], res);
00479       /* Never returns */
00480    }
00481 }

struct ast_app* pbx_findapp char *  app  ) 
 

Look up an application.

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

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

00494 {
00495    struct ast_app *tmp;
00496 
00497    if (ast_mutex_lock(&applock)) {
00498       ast_log(LOG_WARNING, "Unable to obtain application lock\n");
00499       return NULL;
00500    }
00501    tmp = apps;
00502    while(tmp) {
00503       if (!strcasecmp(tmp->name, app))
00504          break;
00505       tmp = tmp->next;
00506    }
00507    ast_mutex_unlock(&applock);
00508    return tmp;
00509 }

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

Definition at line 1044 of file pbx.c.

References ast_expr(), ast_log(), free, LOG_DEBUG, LOG_NOTICE, and pbx_substitute_variables_helper().

Referenced by pbx_substitute_variables_helper().

01045 {
01046    char *cp4;
01047    const char *tmp, *whereweare;
01048    int length;
01049    char workspace[4096];
01050    char ltmp[4096], var[4096];
01051    char *nextvar, *nextexp;
01052    char *vars, *vare;
01053    int pos, brackets, needsub, len;
01054    
01055    /* Substitutes variables into cp2, based on string cp1, and assuming cp2 to be
01056       zero-filled */
01057    whereweare=tmp=cp1;
01058    while(!ast_strlen_zero(whereweare) && count) {
01059       /* Assume we're copying the whole remaining string */
01060       pos = strlen(whereweare);
01061 
01062       /* Look for a variable */
01063       nextvar = strstr(whereweare, "${");
01064       
01065       /* Look for an expression */
01066       nextexp = strstr(whereweare, "$[");
01067       
01068       /* Pick the first one only */
01069       if (nextvar && nextexp) {
01070          if (nextvar < nextexp)
01071             nextexp = NULL;
01072          else
01073             nextvar = NULL;
01074       }
01075       
01076       /* If there is one, we only go that far */
01077       if (nextvar)
01078          pos = nextvar - whereweare;
01079       else if (nextexp)
01080          pos = nextexp - whereweare;
01081       
01082       /* Can't copy more than 'count' bytes */
01083       if (pos > count)
01084          pos = count;
01085       
01086       /* Copy that many bytes */
01087       memcpy(cp2, whereweare, pos);
01088       
01089       count -= pos;
01090       cp2 += pos;
01091       whereweare += pos;
01092       
01093       if (nextvar) {
01094          /* We have a variable.  Find the start and end, and determine
01095             if we are going to have to recursively call ourselves on the
01096             contents */
01097          vars = vare = nextvar + 2;
01098          brackets = 1;
01099          needsub = 0;
01100          
01101          /* Find the end of it */
01102          while(brackets && *vare) {
01103             if ((vare[0] == '$') && (vare[1] == '{')) {
01104                needsub++;
01105                brackets++;
01106             } else if (vare[0] == '}') {
01107                brackets--;
01108             } else if ((vare[0] == '$') && (vare[1] == '['))
01109                needsub++;
01110             vare++;
01111          }
01112          if (brackets)
01113             ast_log(LOG_NOTICE, "Error in extension logic (missing '}')\n");
01114          len = vare - vars - 1;
01115          
01116          /* Skip totally over variable name */
01117          whereweare += ( len + 3);
01118          
01119          /* Store variable name (and truncate) */
01120          memset(var, 0, sizeof(var));
01121          strncpy(var, vars, sizeof(var) - 1);
01122          var[len] = '\0';
01123          
01124          /* Substitute if necessary */
01125          if (needsub) {
01126             memset(ltmp, 0, sizeof(ltmp));
01127             pbx_substitute_variables_helper(c, var, ltmp, sizeof(ltmp) - 1);
01128             vars = ltmp;
01129          } else {
01130             vars = var;
01131          }
01132          
01133          /* Retrieve variable value */
01134          workspace[0] = '\0';
01135          pbx_substitute_variables_temp(c,vars,&cp4, workspace, sizeof(workspace));
01136          if (cp4) {
01137             length = strlen(cp4);
01138             if (length > count)
01139                length = count;
01140             memcpy(cp2, cp4, length);
01141             count -= length;
01142             cp2 += length;
01143          }
01144          
01145       } else if (nextexp) {
01146          /* We have an expression.  Find the start and end, and determine
01147             if we are going to have to recursively call ourselves on the
01148             contents */
01149          vars = vare = nextexp + 2;
01150          brackets = 1;
01151          needsub = 0;
01152          
01153          /* Find the end of it */
01154          while(brackets && *vare) {
01155             if ((vare[0] == '$') && (vare[1] == '[')) {
01156                needsub++;
01157                brackets++;
01158                vare++;
01159             } else if (vare[0] == '[') {
01160                brackets++;
01161             } else if (vare[0] == ']') {
01162                brackets--;
01163             } else if ((vare[0] == '$') && (vare[1] == '{')) {
01164                needsub++;
01165                vare++;
01166             }
01167             vare++;
01168          }
01169          if (brackets)
01170             ast_log(LOG_NOTICE, "Error in extension logic (missing ']')\n");
01171          len = vare - vars - 1;
01172          
01173          /* Skip totally over variable name */
01174          whereweare += ( len + 3);
01175          
01176          /* Store variable name (and truncate) */
01177          memset(var, 0, sizeof(var));
01178          strncpy(var, vars, sizeof(var) - 1);
01179          var[len] = '\0';
01180          
01181          /* Substitute if necessary */
01182          if (needsub) {
01183             memset(ltmp, 0, sizeof(ltmp));
01184             pbx_substitute_variables_helper(c, var, ltmp, sizeof(ltmp) - 1);
01185             vars = ltmp;
01186          } else {
01187             vars = var;
01188          }
01189 
01190          /* Evaluate expression */        
01191          cp4 = ast_expr(vars);
01192          
01193          ast_log(LOG_DEBUG, "Expression is '%s'\n", cp4);
01194          
01195          if (cp4) {
01196             length = strlen(cp4);
01197             if (length > count)
01198                length = count;
01199             memcpy(cp2, cp4, length);
01200             count -= length;
01201             cp2 += length;
01202             free(cp4);
01203          }
01204          
01205       } else
01206          break;
01207    }
01208 }


Variable Documentation

struct ast_hint* hints = NULL
 

Definition at line 423 of file pbx.c.

struct ast_state_cb* statecbs = NULL
 

Definition at line 424 of file pbx.c.

struct ast_switch* switches = NULL
 

Definition at line 419 of file pbx.c.


Generated on Sat Nov 25 19:10:18 2006 for Asterisk by  doxygen 1.4.2