Main Page | Alphabetical List | Data Structures | 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 <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.

Data Structures

struct  ast_exten
struct  ast_include
struct  ast_sw
struct  ast_ignorepat
struct  ast_context
struct  ast_app
struct  ast_state_cb
struct  ast_hint
struct  pbx_builtin
struct  async_stat
struct  app_tmp

Defines

#define AST_PBX_MAX_STACK   64
#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)
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 maxlen, 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, int lock)
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 needlock)
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, char *callerid, char *variable, char *account)
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)
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)
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   64
 

Definition at line 409 of file pbx.c.

#define EXTENSION_MATCH_CORE data,
pattern,
match   ) 
 

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

#define HELPER_CANMATCH   3
 

Definition at line 414 of file pbx.c.

Referenced by ast_canmatch_extension().

#define HELPER_EXEC   2
 

Definition at line 413 of file pbx.c.

#define HELPER_EXISTS   0
 

Definition at line 411 of file pbx.c.

Referenced by ast_exists_extension().

#define HELPER_MATCHMORE   4
 

Definition at line 415 of file pbx.c.

Referenced by ast_matchmore_extension().

#define HELPER_SPAWN   1
 

Definition at line 412 of file pbx.c.

Referenced by ast_spawn_extension().

#define LOG
 

#define STATUS_NO_CONTEXT   1
 

Definition at line 614 of file pbx.c.

#define STATUS_NO_EXTENSION   2
 

Definition at line 615 of file pbx.c.

#define STATUS_NO_PRIORITY   3
 

Definition at line 616 of file pbx.c.

#define STATUS_SUCCESS   4
 

Definition at line 617 of file pbx.c.


Function Documentation

void __ast_context_destroy struct ast_context con,
char *  registrar,
int  lock
 

Definition at line 4066 of file pbx.c.

04067 {
04068    struct ast_context *tmp, *tmpl=NULL;
04069    struct ast_include *tmpi, *tmpil= NULL;
04070    struct ast_sw *sw, *swl= NULL;
04071    struct ast_exten *e, *el, *en;
04072    struct ast_ignorepat *ipi, *ipl = NULL;
04073    if (lock)
04074       ast_mutex_lock(&conlock);
04075    tmp = contexts;
04076    while(tmp) {
04077       if (((tmp->name && con && con->name && !strcasecmp(tmp->name, con->name)) || !con) &&
04078           (!registrar || !strcasecmp(registrar, tmp->registrar))) {
04079          /* Okay, let's lock the structure to be sure nobody else
04080             is searching through it. */
04081          if (ast_mutex_lock(&tmp->lock)) {
04082             ast_log(LOG_WARNING, "Unable to lock context lock\n");
04083             return;
04084          }
04085          if (tmpl)
04086             tmpl->next = tmp->next;
04087          else
04088             contexts = tmp->next;
04089          /* Okay, now we're safe to let it go -- in a sense, we were
04090             ready to let it go as soon as we locked it. */
04091          ast_mutex_unlock(&tmp->lock);
04092          for (tmpi = tmp->includes; tmpi; ) {
04093             /* Free includes */
04094             tmpil = tmpi;
04095             tmpi = tmpi->next;
04096             free(tmpil);
04097          }
04098          for (ipi = tmp->ignorepats; ipi; ) {
04099             /* Free ignorepats */
04100             ipl = ipi;
04101             ipi = ipi->next;
04102             free(ipl);
04103          }
04104          for (sw = tmp->alts; sw; ) {
04105             /* Free switches */
04106             swl = sw;
04107             sw = sw->next;
04108             free(swl);
04109             swl = sw;
04110          }
04111          for (e = tmp->root; e;) {
04112             for (en = e->peer; en;) {
04113                el = en;
04114                en = en->peer;
04115                destroy_exten(el);
04116             }
04117             el = e;
04118             e = e->next;
04119             destroy_exten(el);
04120          }
04121          free(tmp);
04122          if (!con) {
04123             /* Might need to get another one -- restart */
04124             tmp = contexts;
04125             tmpl = NULL;
04126             tmpil = NULL;
04127             continue;
04128          }
04129          if (lock)
04130             ast_mutex_unlock(&conlock);
04131          return;
04132       }
04133       tmpl = tmp;
04134       tmp = tmp->next;
04135    }
04136    if (lock)
04137       ast_mutex_unlock(&conlock);
04138 }

int ast_add_extension char *  context,
int  replace,
char *  extension,
int  priority,
char *  callerid,
char *  application,
void *  data,
void(*  datad)(void *),
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 3472 of file pbx.c.

03474 {
03475    struct ast_context *c;
03476 
03477    if (ast_lock_contexts()) {
03478       errno = EBUSY;
03479       return -1;
03480    }
03481 
03482    c = ast_walk_contexts(NULL);
03483    while (c) {
03484       if (!strcmp(context, ast_get_context_name(c))) {
03485          int ret = ast_add_extension2(c, replace, extension, priority, callerid,
03486             application, data, datad, registrar);
03487          ast_unlock_contexts();
03488          return ret;
03489       }
03490       c = ast_walk_contexts(c);
03491    }
03492 
03493    ast_unlock_contexts();
03494    errno = ENOENT;
03495    return -1;
03496 }

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.

For details about the arguements, check ast_add_extension()

Definition at line 3605 of file pbx.c.

Referenced by ast_ignore_pattern().

03609 {
03610 
03611 #define LOG do {  if (option_debug) {\
03612       if (tmp->matchcid) { \
03613          ast_log(LOG_DEBUG, "Added extension '%s' priority %d (CID match '%s') to %s\n", tmp->exten, tmp->priority, tmp->cidmatch, con->name); \
03614       } else { \
03615          ast_log(LOG_DEBUG, "Added extension '%s' priority %d to %s\n", tmp->exten, tmp->priority, con->name); \
03616       } \
03617    } else if (option_verbose > 2) { \
03618       if (tmp->matchcid) { \
03619          ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d (CID match '%s')to %s\n", tmp->exten, tmp->priority, tmp->cidmatch, con->name); \
03620       } else {  \
03621          ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d to %s\n", tmp->exten, tmp->priority, con->name); \
03622       } \
03623    } } while(0)
03624 
03625    /*
03626     * This is a fairly complex routine.  Different extensions are kept
03627     * in order by the extension number.  Then, extensions of different
03628     * priorities (same extension) are kept in a list, according to the
03629     * peer pointer.
03630     */
03631    struct ast_exten *tmp, *e, *el = NULL, *ep = NULL;
03632    int res;
03633    /* Be optimistic:  Build the extension structure first */
03634    tmp = malloc(sizeof(struct ast_exten));
03635    if (tmp) {
03636       memset(tmp, 0, sizeof(struct ast_exten));
03637       ext_strncpy(tmp->exten, extension, sizeof(tmp->exten));
03638       tmp->priority = priority;
03639       if (callerid) {
03640          ext_strncpy(tmp->cidmatch, callerid, sizeof(tmp->cidmatch));
03641          tmp->matchcid = 1;
03642       } else {
03643          strcpy(tmp->cidmatch, "");
03644          tmp->matchcid = 0;
03645       }
03646       strncpy(tmp->app, application, sizeof(tmp->app)-1);
03647       tmp->parent = con;
03648       tmp->data = data;
03649       tmp->datad = datad;
03650       tmp->registrar = registrar;
03651       tmp->peer = NULL;
03652       tmp->next =  NULL;
03653    } else {
03654       ast_log(LOG_ERROR, "Out of memory\n");
03655       errno = ENOMEM;
03656       return -1;
03657    }
03658    if (ast_mutex_lock(&con->lock)) {
03659       free(tmp);
03660       /* And properly destroy the data */
03661       datad(data);
03662       ast_log(LOG_WARNING, "Failed to lock context '%s'\n", con->name);
03663       errno = EBUSY;
03664       return -1;
03665    }
03666    e = con->root;
03667    while(e) {
03668       res= strcasecmp(e->exten, extension);
03669       if (!res) {
03670          if (!e->matchcid && !tmp->matchcid)
03671             res = 0;
03672          else if (tmp->matchcid && !e->matchcid)
03673             res = 1;
03674          else if (e->matchcid && !tmp->matchcid)
03675             res = -1;
03676          else
03677             res = strcasecmp(e->cidmatch, tmp->cidmatch);
03678       }
03679       if (res == 0) {
03680          /* We have an exact match, now we find where we are
03681             and be sure there's no duplicates */
03682          while(e) {
03683             if (e->priority == tmp->priority) {
03684                /* Can't have something exactly the same.  Is this a
03685                   replacement?  If so, replace, otherwise, bonk. */
03686                if (replace) {
03687                   if (ep) {
03688                      /* We're in the peer list, insert ourselves */
03689                      ep->peer = tmp;
03690                      tmp->peer = e->peer;
03691                   } else if (el) {
03692                      /* We're the first extension. Take over e's functions */
03693                      el->next = tmp;
03694                      tmp->next = e->next;
03695                      tmp->peer = e->peer;
03696                   } else {
03697                      /* We're the very first extension.  */
03698                      con->root = tmp;
03699                      tmp->next = e->next;
03700                      tmp->peer = e->peer;
03701                   }
03702                   if (tmp->priority == PRIORITY_HINT)
03703                       ast_change_hint(e,tmp);
03704                   /* Destroy the old one */
03705                   e->datad(e->data);
03706                   free(e);
03707                   ast_mutex_unlock(&con->lock);
03708                   if (tmp->priority == PRIORITY_HINT)
03709                       ast_change_hint(e, tmp);
03710                   /* And immediately return success. */
03711                   LOG;
03712                   return 0;
03713                } else {
03714                   ast_log(LOG_WARNING, "Unable to register extension '%s', priority %d in '%s', already in use\n", tmp->exten, tmp->priority, con->name);
03715                   tmp->datad(tmp->data);
03716                   free(tmp);
03717                   ast_mutex_unlock(&con->lock);
03718                   errno = EEXIST;
03719                   return -1;
03720                }
03721             } else if (e->priority > tmp->priority) {
03722                /* Slip ourselves in just before e */
03723                if (ep) {
03724                   /* Easy enough, we're just in the peer list */
03725                   ep->peer = tmp;
03726                   tmp->peer = e;
03727                } else if (el) {
03728                   /* We're the first extension in this peer list */
03729                   el->next = tmp;
03730                   tmp->next = e->next;
03731                   e->next = NULL;
03732                   tmp->peer = e;
03733                } else {
03734                   /* We're the very first extension altogether */
03735                   tmp->next = con->root->next;
03736                   /* Con->root must always exist or we couldn't get here */
03737                   tmp->peer = con->root;
03738                   con->root = tmp;
03739                }
03740                ast_mutex_unlock(&con->lock);
03741                /* And immediately return success. */
03742                if (tmp->priority == PRIORITY_HINT)
03743                    ast_add_hint(tmp);
03744                
03745                LOG;
03746                return 0;
03747             }
03748             ep = e;
03749             e = e->peer;
03750          }
03751          /* If we make it here, then it's time for us to go at the very end.
03752             ep *must* be defined or we couldn't have gotten here. */
03753          ep->peer = tmp;
03754          ast_mutex_unlock(&con->lock);
03755          if (tmp->priority == PRIORITY_HINT)
03756              ast_add_hint(tmp);
03757          
03758          /* And immediately return success. */
03759          LOG;
03760          return 0;
03761             
03762       } else if (res > 0) {
03763          /* Insert ourselves just before 'e'.  We're the first extension of
03764             this kind */
03765          tmp->next = e;
03766          if (el) {
03767             /* We're in the list somewhere */
03768             el->next = tmp;
03769          } else {
03770             /* We're at the top of the list */
03771             con->root = tmp;
03772          }
03773          ast_mutex_unlock(&con->lock);
03774          if (tmp->priority == PRIORITY_HINT)
03775              ast_add_hint(tmp);
03776 
03777          /* And immediately return success. */
03778          LOG;
03779          return 0;
03780       }        
03781          
03782       el = e;
03783       e = e->next;
03784    }
03785    /* If we fall all the way through to here, then we need to be on the end. */
03786    if (el)
03787       el->next = tmp;
03788    else
03789       con->root = tmp;
03790    ast_mutex_unlock(&con->lock);
03791    if (tmp->priority == PRIORITY_HINT)
03792        ast_add_hint(tmp);
03793    LOG;
03794    return 0;   
03795 }

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

Definition at line 3498 of file pbx.c.

03499 {
03500    int res = 0;
03501    if (needlock)
03502       ast_mutex_lock(&chan->lock);
03503    if (chan->pbx) {
03504       /* This channel is currently in the PBX */
03505       if (context && strlen(context))
03506          strncpy(chan->context, context, sizeof(chan->context) - 1);
03507       if (exten && strlen(exten))
03508          strncpy(chan->exten, exten, sizeof(chan->context) - 1);
03509       if (priority)
03510          chan->priority = priority - 1;
03511       ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO);
03512       if (needlock)
03513          ast_mutex_unlock(&chan->lock);
03514    } else {
03515       /* In order to do it when the channel doesn't really exist within
03516          the PBX, we have to make a new channel, masquerade, and start the PBX
03517          at the new location */
03518       struct ast_channel *tmpchan;
03519       struct ast_frame *f;
03520       tmpchan = ast_channel_alloc(0);
03521       if (tmpchan) {
03522          snprintf(tmpchan->name, sizeof(tmpchan->name), "AsyncGoto/%s", chan->name);
03523          ast_setstate(tmpchan, chan->_state);
03524          /* Make formats okay */
03525          tmpchan->readformat = chan->readformat;
03526          tmpchan->writeformat = chan->writeformat;
03527          /* Setup proper location */
03528          if (context && strlen(context))
03529             strncpy(tmpchan->context, context, sizeof(tmpchan->context) - 1);
03530          else
03531             strncpy(tmpchan->context, chan->context, sizeof(tmpchan->context) - 1);
03532          if (exten && strlen(exten))
03533             strncpy(tmpchan->exten, exten, sizeof(tmpchan->exten) - 1);
03534          else
03535             strncpy(tmpchan->exten, chan->exten, sizeof(tmpchan->exten) - 1);
03536          if (priority)
03537             tmpchan->priority = priority;
03538          else
03539             tmpchan->priority = chan->priority;
03540          
03541          /* Masquerade into temp channel */
03542          ast_channel_masquerade(tmpchan, chan);
03543          
03544          if (needlock)
03545             ast_mutex_unlock(&chan->lock);
03546             
03547          /* Make the masquerade happen by reading a frame from the tmp channel */
03548          f = ast_read(tmpchan);
03549          if (f)
03550             ast_frfree(f);
03551          /* Start the PBX going on our stolen channel */
03552          if (ast_pbx_start(tmpchan)) {
03553             ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name);
03554             ast_hangup(tmpchan);
03555             res = -1;
03556          }
03557       } else {
03558          res = -1;
03559          if (needlock)
03560             ast_mutex_unlock(&chan->lock);
03561       }
03562    }
03563    return res;
03564 }

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

Definition at line 3566 of file pbx.c.

03567 {
03568    struct ast_channel *chan;
03569    chan = ast_channel_walk(NULL);
03570    while(chan) {
03571       if (!strcasecmp(channame, chan->name))
03572          break;
03573       chan = ast_channel_walk(chan);
03574    }
03575    if (chan)
03576       return ast_async_goto(chan, context, exten, priority, 1);
03577    return -1;
03578 }

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

References HELPER_CANMATCH.

01646 {
01647    return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_CANMATCH);
01648 }

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

03394 {
03395    struct ast_context *c;
03396 
03397    if (ast_lock_contexts()) {
03398       errno = EBUSY;
03399       return -1;
03400    }
03401 
03402    c = ast_walk_contexts(NULL);
03403    while (c) {
03404       if (!strcmp(ast_get_context_name(c), con)) {
03405          int ret = ast_context_add_ignorepat2(c, value, registrar);
03406          ast_unlock_contexts();
03407          return ret;
03408       } 
03409       c = ast_walk_contexts(c);
03410    }
03411 
03412    ast_unlock_contexts();
03413    errno = ENOENT;
03414    return -1;
03415 }

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

Definition at line 3417 of file pbx.c.

References ast_mutex_unlock, and ast_context::lock.

03418 {
03419    struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL;
03420    ignorepat = malloc(sizeof(struct ast_ignorepat));
03421    if (!ignorepat) {
03422       ast_log(LOG_ERROR, "Out of memory\n");
03423       errno = ENOMEM;
03424       return -1;
03425    }
03426    memset(ignorepat, 0, sizeof(struct ast_ignorepat));
03427    strncpy(ignorepat->pattern, value, sizeof(ignorepat->pattern)-1);
03428    ignorepat->next = NULL;
03429    ignorepat->registrar = registrar;
03430    ast_mutex_lock(&con->lock);
03431    ignorepatc = con->ignorepats;
03432    while(ignorepatc) {
03433       ignorepatl = ignorepatc;
03434       if (!strcasecmp(ignorepatc->pattern, value)) {
03435          /* Already there */
03436          ast_mutex_unlock(&con->lock);
03437          errno = EEXIST;
03438          return -1;
03439       }
03440       ignorepatc = ignorepatc->next;
03441    }
03442    if (ignorepatl) 
03443       ignorepatl->next = ignorepat;
03444    else
03445       con->ignorepats = ignorepat;
03446    ast_mutex_unlock(&con->lock);
03447    return 0;
03448    
03449 }

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

02858 {
02859    struct ast_context *c;
02860 
02861    if (ast_lock_contexts()) {
02862       errno = EBUSY;
02863       return -1;
02864    }
02865 
02866    /* walk contexts ... */
02867    c = ast_walk_contexts(NULL);
02868    while (c) {
02869       /* ... search for the right one ... */
02870       if (!strcmp(ast_get_context_name(c), context)) {
02871          int ret = ast_context_add_include2(c, include, registrar);
02872          /* ... unlock contexts list and return */
02873          ast_unlock_contexts();
02874          return ret;
02875       }
02876       c = ast_walk_contexts(c);
02877    }
02878 
02879    /* we can't find the right context */
02880    ast_unlock_contexts();
02881    errno = ENOENT;
02882    return -1;
02883 }

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

03176 {
03177    struct ast_include *new_include;
03178    char *c;
03179    struct ast_include *i, *il = NULL; /* include, include_last */
03180 
03181    /* allocate new include structure ... */
03182    if (!(new_include = malloc(sizeof(struct ast_include)))) {
03183       ast_log(LOG_ERROR, "Out of memory\n");
03184       errno = ENOMEM;
03185       return -1;
03186    }
03187    
03188    /* ... fill in this structure ... */
03189    memset(new_include, 0, sizeof(struct ast_include));
03190    strncpy(new_include->name, value, sizeof(new_include->name)-1);
03191    strncpy(new_include->rname, value, sizeof(new_include->rname)-1);
03192    c = new_include->rname;
03193    /* Strip off timing info */
03194    while(*c && (*c != '|')) c++; 
03195    /* Process if it's there */
03196    if (*c) {
03197       build_timing(new_include, c+1);
03198       *c = '\0';
03199    }
03200    new_include->next      = NULL;
03201    new_include->registrar = registrar;
03202 
03203    /* ... try to lock this context ... */
03204    if (ast_mutex_lock(&con->lock)) {
03205       free(new_include);
03206       errno = EBUSY;
03207       return -1;
03208    }
03209 
03210    /* ... go to last include and check if context is already included too... */
03211    i = con->includes;
03212    while (i) {
03213       if (!strcasecmp(i->name, new_include->name)) {
03214          free(new_include);
03215          ast_mutex_unlock(&con->lock);
03216          errno = EEXIST;
03217          return -1;
03218       }
03219       il = i;
03220       i = i->next;
03221    }
03222 
03223    /* ... include new context into context list, unlock, return */
03224    if (il)
03225       il->next = new_include;
03226    else
03227       con->includes = new_include;
03228    if (option_verbose > 2)
03229       ast_verbose(VERBOSE_PREFIX_3 "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con)); 
03230    ast_mutex_unlock(&con->lock);
03231 
03232    return 0;
03233 }

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

03241 {
03242    struct ast_context *c;
03243 
03244    if (ast_lock_contexts()) {
03245       errno = EBUSY;
03246       return -1;
03247    }
03248 
03249    /* walk contexts ... */
03250    c = ast_walk_contexts(NULL);
03251    while (c) {
03252       /* ... search for the right one ... */
03253       if (!strcmp(ast_get_context_name(c), context)) {
03254          int ret = ast_context_add_switch2(c, sw, data, registrar);
03255          /* ... unlock contexts list and return */
03256          ast_unlock_contexts();
03257          return ret;
03258       }
03259       c = ast_walk_contexts(c);
03260    }
03261 
03262    /* we can't find the right context */
03263    ast_unlock_contexts();
03264    errno = ENOENT;
03265    return -1;
03266 }

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

03277 {
03278    struct ast_sw *new_sw;
03279    struct ast_sw *i, *il = NULL; /* sw, sw_last */
03280 
03281    /* allocate new sw structure ... */
03282    if (!(new_sw = malloc(sizeof(struct ast_sw)))) {
03283       ast_log(LOG_ERROR, "Out of memory\n");
03284       errno = ENOMEM;
03285       return -1;
03286    }
03287    
03288    /* ... fill in this structure ... */
03289    memset(new_sw, 0, sizeof(struct ast_sw));
03290    strncpy(new_sw->name, value, sizeof(new_sw->name)-1);
03291    if (data)
03292       strncpy(new_sw->data, data, sizeof(new_sw->data)-1);
03293    else
03294       strncpy(new_sw->data, "", sizeof(new_sw->data)-1);
03295    new_sw->next      = NULL;
03296    new_sw->registrar = registrar;
03297 
03298    /* ... try to lock this context ... */
03299    if (ast_mutex_lock(&con->lock)) {
03300       free(new_sw);
03301       errno = EBUSY;
03302       return -1;
03303    }
03304 
03305    /* ... go to last sw and check if context is already swd too... */
03306    i = con->alts;
03307    while (i) {
03308       if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) {
03309          free(new_sw);
03310          ast_mutex_unlock(&con->lock);
03311          errno = EEXIST;
03312          return -1;
03313       }
03314       il = i;
03315       i = i->next;
03316    }
03317 
03318    /* ... sw new context into context list, unlock, return */
03319    if (il)
03320       il->next = new_sw;
03321    else
03322       con->alts = new_sw;
03323    if (option_verbose > 2)
03324       ast_verbose(VERBOSE_PREFIX_3 "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con)); 
03325    ast_mutex_unlock(&con->lock);
03326 
03327    return 0;
03328 }

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

02781 {
02782    struct ast_context *tmp, **local_contexts;
02783    if (!extcontexts) {
02784       local_contexts = &contexts;
02785       ast_mutex_lock(&conlock);
02786    } else
02787       local_contexts = extcontexts;
02788 
02789    tmp = *local_contexts;
02790    while(tmp) {
02791       if (!strcasecmp(tmp->name, name)) {
02792          ast_mutex_unlock(&conlock);
02793          ast_log(LOG_WARNING, "Tried to register context '%s', already in use\n", name);
02794          if (!extcontexts)
02795             ast_mutex_unlock(&conlock);
02796          return NULL;
02797       }
02798       tmp = tmp->next;
02799    }
02800    tmp = malloc(sizeof(struct ast_context));
02801    if (tmp) {
02802       memset(tmp, 0, sizeof(struct ast_context));
02803       ast_mutex_init(&tmp->lock);
02804       strncpy(tmp->name, name, sizeof(tmp->name)-1);
02805       tmp->root = NULL;
02806       tmp->registrar = registrar;
02807       tmp->next = *local_contexts;
02808       tmp->includes = NULL;
02809       tmp->ignorepats = NULL;
02810       *local_contexts = tmp;
02811       if (option_debug)
02812          ast_log(LOG_DEBUG, "Registered context '%s'\n", tmp->name);
02813       else if (option_verbose > 2)
02814          ast_verbose( VERBOSE_PREFIX_3 "Registered extension context '%s'\n", tmp->name);
02815    } else
02816       ast_log(LOG_ERROR, "Out of memory\n");
02817    
02818    if (!extcontexts)
02819       ast_mutex_unlock(&conlock);
02820    return tmp;
02821 }

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

04141 {
04142    __ast_context_destroy(con,registrar,1);
04143 }

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

References ast_mutex_lock, ast_mutex_unlock, and ast_context::next.

00598 {
00599    struct ast_context *tmp;
00600    ast_mutex_lock(&conlock);
00601    if (name) {
00602       tmp = contexts;
00603       while(tmp) {
00604          if (!strcasecmp(name, tmp->name))
00605             break;
00606          tmp = tmp->next;
00607       }
00608    } else
00609       tmp = contexts;
00610    ast_mutex_unlock(&conlock);
00611    return tmp;
00612 }

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

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

02056 {
02057    struct ast_context *c;
02058 
02059    if (ast_lock_contexts()) return -1;
02060 
02061    /* walk contexts ... */
02062    c = ast_walk_contexts(NULL);
02063    while (c) {
02064       /* ... search for the right one ... */
02065       if (!strcmp(ast_get_context_name(c), context)) {
02066          /* ... remove extension ... */
02067          int ret = ast_context_remove_extension2(c, extension, priority,
02068             registrar);
02069          /* ... unlock contexts list and return */
02070          ast_unlock_contexts();
02071          return ret;
02072       }
02073       c = ast_walk_contexts(c);
02074    }
02075 
02076    /* we can't find the right context */
02077    ast_unlock_contexts();
02078    return -1;
02079 }

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

Definition at line 2091 of file pbx.c.

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

Referenced by ast_context_remove_extension().

02092 {
02093    struct ast_exten *exten, *prev_exten = NULL;
02094 
02095    if (ast_mutex_lock(&con->lock)) return -1;
02096 
02097    /* go through all extensions in context and search the right one ... */
02098    exten = con->root;
02099    while (exten) {
02100 
02101       /* look for right extension */
02102       if (!strcmp(exten->exten, extension) &&
02103          (!strcmp(exten->registrar, registrar) || !registrar)) {
02104          struct ast_exten *peer;
02105 
02106          /* should we free all peers in this extension? (priority == 0)? */
02107          if (priority == 0) {
02108             /* remove this extension from context list */
02109             if (prev_exten)
02110                prev_exten->next = exten->next;
02111             else
02112                con->root = exten->next;
02113 
02114             /* fire out all peers */
02115             peer = exten; 
02116             while (peer) {
02117                exten = peer->peer;
02118                
02119                if (!peer->priority==PRIORITY_HINT) 
02120                    ast_remove_hint(peer);
02121 
02122                peer->datad(peer->data);
02123                free(peer);
02124 
02125                peer = exten;
02126             }
02127 
02128             ast_mutex_unlock(&con->lock);
02129             return 0;
02130          } else {
02131             /* remove only extension with exten->priority == priority */
02132             struct ast_exten *previous_peer = NULL;
02133 
02134             peer = exten;
02135             while (peer) {
02136                /* is this our extension? */
02137                if (peer->priority == priority &&
02138                   (!strcmp(peer->registrar, registrar) || !registrar)) {
02139                   /* we are first priority extension? */
02140                   if (!previous_peer) {
02141                      /* exists previous extension here? */
02142                      if (prev_exten) {
02143                         /* yes, so we must change next pointer in
02144                          * previous connection to next peer
02145                          */
02146                         if (peer->peer) {
02147                            prev_exten->next = peer->peer;
02148                            peer->peer->next = exten->next;
02149                         } else
02150                            prev_exten->next = exten->next;
02151                      } else {
02152                         /* no previous extension, we are first
02153                          * extension, so change con->root ...
02154                          */
02155                         if (peer->peer)
02156                            con->root = peer->peer;
02157                         else
02158                            con->root = exten->next; 
02159                      }
02160                   } else {
02161                      /* we are not first priority in extension */
02162                      previous_peer->peer = peer->peer;
02163                   }
02164 
02165                   /* now, free whole priority extension */
02166                   if (peer->priority==PRIORITY_HINT)
02167                       ast_remove_hint(peer);
02168                   peer->datad(peer->data);
02169                   free(peer);
02170 
02171                   ast_mutex_unlock(&con->lock);
02172                   return 0;
02173                } else {
02174                   /* this is not right extension, skip to next peer */
02175                   previous_peer = peer;
02176                   peer = peer->peer;
02177                }
02178             }
02179 
02180             ast_mutex_unlock(&con->lock);
02181             return -1;
02182          }
02183       }
02184 
02185       prev_exten = exten;
02186       exten = exten->next;
02187    }
02188 
02189    /* we can't find right extension */
02190    ast_mutex_unlock(&con->lock);
02191    return -1;
02192 }

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

03335 {
03336    struct ast_context *c;
03337 
03338    if (ast_lock_contexts()) {
03339       errno = EBUSY;
03340       return -1;
03341    }
03342 
03343    c = ast_walk_contexts(NULL);
03344    while (c) {
03345       if (!strcmp(ast_get_context_name(c), context)) {
03346          int ret = ast_context_remove_ignorepat2(c, ignorepat, registrar);
03347          ast_unlock_contexts();
03348          return ret;
03349       }
03350       c = ast_walk_contexts(c);
03351    }
03352 
03353    ast_unlock_contexts();
03354    errno = ENOENT;
03355    return -1;
03356 }

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

Definition at line 3358 of file pbx.c.

03359 {
03360    struct ast_ignorepat *ip, *ipl = NULL;
03361 
03362    if (ast_mutex_lock(&con->lock)) {
03363       errno = EBUSY;
03364       return -1;
03365    }
03366 
03367    ip = con->ignorepats;
03368    while (ip) {
03369       if (!strcmp(ip->pattern, ignorepat) &&
03370          (registrar == ip->registrar || !registrar)) {
03371          if (ipl) {
03372             ipl->next = ip->next;
03373             free(ip);
03374          } else {
03375             con->ignorepats = ip->next;
03376             free(ip);
03377          }
03378          ast_mutex_unlock(&con->lock);
03379          return 0;
03380       }
03381       ipl = ip; ip = ip->next;
03382    }
03383 
03384    ast_mutex_unlock(&con->lock);
03385    errno = EINVAL;
03386    return -1;
03387 }

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

Removes an include.

See add_include

Definition at line 1911 of file pbx.c.

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

01912 {
01913    struct ast_context *c;
01914 
01915    if (ast_lock_contexts()) return -1;
01916 
01917    /* walk contexts and search for the right one ...*/
01918    c = ast_walk_contexts(NULL);
01919    while (c) {
01920       /* we found one ... */
01921       if (!strcmp(ast_get_context_name(c), context)) {
01922          int ret;
01923          /* remove include from this context ... */   
01924          ret = ast_context_remove_include2(c, include, registrar);
01925 
01926          ast_unlock_contexts();
01927 
01928          /* ... return results */
01929          return ret;
01930       }
01931       c = ast_walk_contexts(c);
01932    }
01933 
01934    /* we can't find the right one context */
01935    ast_unlock_contexts();
01936    return -1;
01937 }

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

References ast_mutex_lock, ast_mutex_unlock, free, ast_context::includes, ast_context::lock, and ast_include::next.

Referenced by ast_context_remove_include().

01948 {
01949    struct ast_include *i, *pi = NULL;
01950 
01951    if (ast_mutex_lock(&con->lock)) return -1;
01952 
01953    /* walk includes */
01954    i = con->includes;
01955    while (i) {
01956       /* find our include */
01957       if (!strcmp(i->name, include) && 
01958          (!strcmp(i->registrar, registrar) || !registrar)) {
01959          /* remove from list */
01960          if (pi)
01961             pi->next = i->next;
01962          else
01963             con->includes = i->next;
01964          /* free include and return */
01965          free(i);
01966          ast_mutex_unlock(&con->lock);
01967          return 0;
01968       }
01969       pi = i;
01970       i = i->next;
01971    }
01972 
01973    /* we can't find the right include */
01974    ast_mutex_unlock(&con->lock);
01975    return -1;
01976 }

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

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

01984 {
01985    struct ast_context *c;
01986 
01987    if (ast_lock_contexts()) return -1;
01988 
01989    /* walk contexts and search for the right one ...*/
01990    c = ast_walk_contexts(NULL);
01991    while (c) {
01992       /* we found one ... */
01993       if (!strcmp(ast_get_context_name(c), context)) {
01994          int ret;
01995          /* remove switch from this context ... */ 
01996          ret = ast_context_remove_switch2(c, sw, data, registrar);
01997 
01998          ast_unlock_contexts();
01999 
02000          /* ... return results */
02001          return ret;
02002       }
02003       c = ast_walk_contexts(c);
02004    }
02005 
02006    /* we can't find the right one context */
02007    ast_unlock_contexts();
02008    return -1;
02009 }

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

Definition at line 2019 of file pbx.c.

References ast_context::alts, ast_mutex_lock, ast_mutex_unlock, free, ast_context::lock, and ast_sw::next.

Referenced by ast_context_remove_switch().

02020 {
02021    struct ast_sw *i, *pi = NULL;
02022 
02023    if (ast_mutex_lock(&con->lock)) return -1;
02024 
02025    /* walk switchs */
02026    i = con->alts;
02027    while (i) {
02028       /* find our switch */
02029       if (!strcmp(i->name, sw) && !strcmp(i->data, data) && 
02030          (!strcmp(i->registrar, registrar) || !registrar)) {
02031          /* remove from list */
02032          if (pi)
02033             pi->next = i->next;
02034          else
02035             con->alts = i->next;
02036          /* free switch and return */
02037          free(i);
02038          ast_mutex_unlock(&con->lock);
02039          return 0;
02040       }
02041       pi = i;
02042       i = i->next;
02043    }
02044 
02045    /* we can't find the right switch */
02046    ast_mutex_unlock(&con->lock);
02047    return -1;
02048 }

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

04742 {
04743    struct ast_include *inc;
04744    int res = 0;
04745 
04746    for (inc = ast_walk_context_includes(con, NULL); inc; inc = ast_walk_context_includes(con, inc))
04747       if (!ast_context_find(inc->rname)) {
04748          res = -1;
04749          ast_log(LOG_WARNING, "Context '%s' tries includes non-existant context '%s'\n",
04750                ast_get_context_name(con), inc->rname);
04751       }
04752    return res;
04753 }

int ast_device_state_changed const char *  fmt,
  ...
 

Definition at line 1321 of file pbx.c.

References ast_get_extension_app(), AST_MAX_EXTENSION, ast_mutex_lock, ast_mutex_unlock, ast_state_cb::callback, hints, and statecbs.

01322 {
01323     struct ast_hint *list;
01324     struct ast_state_cb *cblist;
01325     char hint[AST_MAX_EXTENSION];
01326     char device[AST_MAX_EXTENSION];
01327     char *cur, *rest;
01328     int state;
01329     
01330     va_list ap;
01331 
01332     va_start(ap, fmt);
01333     vsnprintf(device, sizeof(device)-1, fmt, ap);
01334     va_end(ap);
01335 
01336     rest = strchr(device, '-');
01337     if (rest) {
01338    *rest = 0;
01339     }
01340         
01341     ast_mutex_lock(&hintlock);
01342 
01343     list = hints;
01344     
01345     while (list) {
01346    
01347    strcpy(hint, ast_get_extension_app(list->exten));
01348    cur = hint;
01349    do {
01350        rest = strchr(cur, '&');
01351        if (rest) {
01352       *rest = 0;
01353       rest++;
01354        }
01355        
01356        if (!strcmp(cur, device)) {
01357        // Found extension execute callbacks 
01358       state = ast_extension_state2(list->exten);
01359       if ((state != -1) && (state != list->laststate)) {
01360           // For general callbacks
01361           cblist = statecbs;
01362           while (cblist) {
01363          cblist->callback(list->exten->parent->name, list->exten->exten, state, cblist->data);
01364          cblist = cblist->next;
01365           }
01366           
01367           // For extension callbacks
01368              cblist = list->callbacks;
01369           while (cblist) {
01370          cblist->callback(list->exten->parent->name, list->exten->exten, state, cblist->data);
01371          cblist = cblist->next;
01372           }
01373           
01374           list->laststate = state;
01375       }
01376       break;
01377        }
01378        cur = rest;
01379    } while (cur);
01380    
01381    list = list->next;
01382     }
01383 
01384     ast_mutex_unlock(&hintlock);
01385     return 1;
01386 }

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

References HELPER_EXISTS.

Referenced by ast_pbx_run().

01641 {
01642    return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_EXISTS);
01643 }

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

References EXTENSION_MATCH_CORE.

00565 {
00566    int match;
00567    /* If they're the same return */
00568    if (!strcmp(pattern, data))
00569       return 1;
00570    EXTENSION_MATCH_CORE(data,pattern,match);
00571    /* Must be at the end of both */
00572    if (*data || (*pattern && (*pattern != '/')))
00573       match = 0;
00574    return match;
00575 }

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

01311 {
01312     struct ast_exten *e;
01313 
01314     e = ast_hint_extension(c, context, exten);    
01315     if (!e) 
01316    return -1;
01317 
01318     return ast_extension_state2(e);    
01319 }

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

References ast_mutex_lock, ast_mutex_unlock, ast_state_cb_type, ast_state_cb::data, hints, malloc, ast_hint::next, and statecbs.

Referenced by init_manager().

01390 {
01391     struct ast_hint *list;
01392     struct ast_state_cb *cblist;
01393     struct ast_exten *e;
01394 
01395     /* No context and extension add callback to statecbs list */
01396     if (!context && !exten) {
01397    ast_mutex_lock(&hintlock);
01398 
01399    cblist = statecbs;
01400    while (cblist) {
01401        if (cblist->callback == callback) {
01402       cblist->data = data;
01403       ast_mutex_unlock(&hintlock);
01404        }
01405        
01406        cblist = cblist->next;
01407    }
01408    
01409    /* Now inserts the callback */
01410    cblist = malloc(sizeof(struct ast_state_cb));
01411    if (!cblist) {
01412        ast_mutex_unlock(&hintlock);
01413        return -1;
01414    }
01415    memset(cblist, 0, sizeof(struct ast_state_cb));
01416    cblist->id = 0;
01417    cblist->callback = callback;
01418    cblist->data = data;
01419 
01420         cblist->next = statecbs;
01421    statecbs = cblist;
01422 
01423    ast_mutex_unlock(&hintlock);
01424    return 0;
01425     }
01426 
01427     if (!context || !exten)
01428    return -1;
01429 
01430     /* This callback type is for only one hint */
01431     e = ast_hint_extension(NULL, context, exten);    
01432     if (!e) {
01433         return -1;
01434     }
01435     
01436     ast_mutex_lock(&hintlock);
01437     list = hints;        
01438     
01439     while (list) {
01440    if (list->exten == e)
01441        break;      
01442    list = list->next;    
01443     }
01444 
01445     if (!list) {
01446    ast_mutex_unlock(&hintlock);
01447    return -1;
01448     }
01449 
01450     /* Now inserts the callback */
01451     cblist = malloc(sizeof(struct ast_state_cb));
01452     if (!cblist) {
01453    ast_mutex_unlock(&hintlock);
01454    return -1;
01455     }
01456     memset(cblist, 0, sizeof(struct ast_state_cb));
01457     cblist->id = stateid++;
01458     cblist->callback = callback;
01459     cblist->data = data;
01460 
01461     cblist->next = list->callbacks;
01462     list->callbacks = cblist;
01463 
01464     ast_mutex_unlock(&hintlock);
01465     return cblist->id;
01466 }

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

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

01469 {
01470     struct ast_hint *list;
01471     struct ast_state_cb *cblist, *cbprev;
01472     
01473     if (!id && !callback)
01474    return -1;
01475             
01476     ast_mutex_lock(&hintlock);
01477 
01478     /* id is zero is a callback without extension */
01479     if (!id) {
01480    cbprev = NULL;
01481    cblist = statecbs;
01482    while (cblist) {
01483        if (cblist->callback == callback) {
01484       if (!cbprev)
01485           statecbs = cblist->next;
01486       else
01487           cbprev->next = cblist->next;
01488 
01489       free(cblist);
01490 
01491            ast_mutex_unlock(&hintlock);
01492       return 0;
01493        }
01494        cbprev = cblist;
01495        cblist = cblist->next;
01496    }
01497 
01498         ast_mutex_lock(&hintlock);
01499    return -1;
01500     }
01501 
01502     /* id greater zero is a callback with extension */
01503     list = hints;
01504     while (list) {
01505    cblist = list->callbacks;
01506    cbprev = NULL;
01507    while (cblist) {
01508        if (cblist->id==id) {
01509       if (!cbprev)
01510           list->callbacks = cblist->next;    
01511       else
01512           cbprev->next = cblist->next;
01513       
01514       free(cblist);
01515       
01516       ast_mutex_unlock(&hintlock);
01517       return 0;      
01518        }    
01519           cbprev = cblist;          
01520        cblist = cblist->next;
01521    }
01522    list = list->next;
01523     }
01524     
01525     ast_mutex_unlock(&hintlock);
01526     return -1;
01527 }

char* ast_get_context_name struct ast_context con  ) 
 

Definition at line 4612 of file pbx.c.

References ast_ignorepat::pattern.

Referenced by ast_context_remove_extension(), ast_context_remove_include(), ast_context_remove_switch(), and ast_ignore_pattern().

04613 {
04614    return con ? con->name : NULL;
04615 }

char* ast_get_context_registrar struct ast_context c  ) 
 

Definition at line 4640 of file pbx.c.

References ast_ignorepat::registrar.

04641 {
04642    return c ? c->registrar : NULL;
04643 }

char* ast_get_extension_app struct ast_exten e  ) 
 

Definition at line 4660 of file pbx.c.

References ast_sw::data.

Referenced by ast_device_state_changed(), and ast_get_hint().

04661 {
04662    return e ? e->app : NULL;
04663 }

void* ast_get_extension_app_data struct ast_exten e  ) 
 

Definition at line 4665 of file pbx.c.

References ast_sw::registrar.

04666 {
04667    return e ? e->data : NULL;
04668 }

char* ast_get_extension_name struct ast_exten exten  ) 
 

Definition at line 4617 of file pbx.c.

References ast_exten::priority.

04618 {
04619    return exten ? exten->exten : NULL;
04620 }

int ast_get_extension_priority struct ast_exten exten  ) 
 

Definition at line 4632 of file pbx.c.

04633 {
04634    return exten ? exten->priority : -1;
04635 }

char* ast_get_extension_registrar struct ast_exten e  ) 
 

Definition at line 4645 of file pbx.c.

References ast_exten::app.

04646 {
04647    return e ? e->registrar : NULL;
04648 }

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

References ast_get_extension_app().

01630 {
01631    struct ast_exten *e;
01632    e = ast_hint_extension(c, context, exten);
01633    if (e) { 
01634        strncpy(hint, ast_get_extension_app(e), maxlen);
01635        return -1;
01636    }
01637    return 0;   
01638 }

char* ast_get_ignorepat_name struct ast_ignorepat ip  ) 
 

Definition at line 4627 of file pbx.c.

04628 {
04629    return ip ? ip->pattern : NULL;
04630 }

char* ast_get_ignorepat_registrar struct ast_ignorepat ip  ) 
 

Definition at line 4655 of file pbx.c.

References ast_sw::name.

04656 {
04657    return ip ? ip->registrar : NULL;
04658 }

char* ast_get_include_name struct ast_include inc  ) 
 

Definition at line 4622 of file pbx.c.

References ast_context::registrar.

04623 {
04624    return inc ? inc->name : NULL;
04625 }

char* ast_get_include_registrar struct ast_include i  ) 
 

Definition at line 4650 of file pbx.c.

References ast_exten::data.

04651 {
04652    return i ? i->registrar : NULL;
04653 }

char* ast_get_switch_data struct ast_sw sw  ) 
 

Definition at line 4675 of file pbx.c.

04676 {
04677    return sw ? sw->data : NULL;
04678 }

char* ast_get_switch_name struct ast_sw sw  ) 
 

Definition at line 4670 of file pbx.c.

04671 {
04672    return sw ? sw->name : NULL;
04673 }

char* ast_get_switch_registrar struct ast_sw sw  ) 
 

Definition at line 4680 of file pbx.c.

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

04681 {
04682    return sw ? sw->registrar : NULL;
04683 }

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

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

03452 {
03453    struct ast_context *con;
03454    struct ast_ignorepat *pat;
03455    con = ast_context_find(context);
03456    if (con) {
03457       pat = con->ignorepats;
03458       while (pat) {
03459          if (ast_extension_match(pat->pattern, pattern))
03460             return 1;
03461          pat = pat->next;
03462       }
03463    } 
03464    return 0;
03465 }

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

04600 {
04601    return ast_mutex_lock(&con->lock);
04602 }

int ast_lock_contexts void   ) 
 

Locks the contexts.

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

Definition at line 4586 of file pbx.c.

Referenced by ast_context_remove_extension(), ast_context_remove_include(), ast_context_remove_switch(), and ast_ignore_pattern().

04587 {
04588    return ast_mutex_lock(&conlock);
04589 }

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

References HELPER_MATCHMORE.

Referenced by ast_pbx_run().

01651 {
01652    return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_MATCHMORE);
01653 }

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

02825                                                                                       {
02826    struct ast_context *tmp, *lasttmp = NULL;
02827    tmp = *extcontexts;
02828    ast_mutex_lock(&conlock);
02829    if (registrar) {
02830       __ast_context_destroy(NULL,registrar,0);
02831       while (tmp) {
02832          lasttmp = tmp;
02833          tmp = tmp->next;
02834       }
02835    } else {
02836       while (tmp) {
02837          __ast_context_destroy(tmp,tmp->registrar,0);
02838          lasttmp = tmp;
02839          tmp = tmp->next;
02840       }
02841    }
02842    if (lasttmp) {
02843       lasttmp->next = contexts;
02844       contexts = *extcontexts;
02845       *extcontexts = NULL;
02846    } else 
02847       ast_log(LOG_WARNING, "Requested contexts didn't get merged\n");
02848    ast_mutex_unlock(&conlock);
02849    return;  
02850 }

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
 

Definition at line 3976 of file pbx.c.

03977 {
03978    struct ast_channel *chan;
03979    struct async_stat *as;
03980    struct app_tmp *tmp;
03981    char *var, *vartmp;
03982    int res = -1;
03983    pthread_attr_t attr;
03984    
03985    if (!app || !strlen(app))
03986       return -1;
03987    if (sync) {
03988       chan = ast_request_and_dial(type, format, data, timeout, reason, callerid);
03989       if (chan) {
03990          pbx_builtin_setaccount(chan, account);
03991          if (variable) {
03992             vartmp = ast_strdupa(variable);
03993             for (var = strtok_r(vartmp, "|", &vartmp); var; var = strtok_r(NULL, "|", &vartmp)) {
03994                pbx_builtin_setvar( chan, var );
03995             }
03996          }
03997          if (chan->_state == AST_STATE_UP) {
03998             res = 0;
03999             if (option_verbose > 3)
04000                ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", chan->name);
04001             tmp = malloc(sizeof(struct app_tmp));
04002             if (tmp) {
04003                memset(tmp, 0, sizeof(struct app_tmp));
04004                strncpy(tmp->app, app, sizeof(tmp->app) - 1);
04005                strncpy(tmp->data, appdata, sizeof(tmp->data) - 1);
04006                tmp->chan = chan;
04007                if (sync > 1) {
04008                   ast_pbx_run_app(tmp);
04009                } else {
04010                   pthread_attr_init(&attr);
04011                   pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
04012                   if (pthread_create(&tmp->t, &attr, ast_pbx_run_app, tmp)) {
04013                      ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno));
04014                      free(tmp);
04015                      ast_hangup(chan);
04016                      res = -1;
04017                   }
04018                }
04019             } else {
04020                ast_log(LOG_ERROR, "Out of memory :(\n");
04021                res = -1;
04022             }
04023          } else {
04024             if (option_verbose > 3)
04025                ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", chan->name);
04026             ast_hangup(chan);
04027          }
04028       }
04029    } else {
04030       as = malloc(sizeof(struct async_stat));
04031       if (!as)
04032          return -1;
04033       memset(as, 0, sizeof(struct async_stat));
04034       chan = ast_request_and_dial(type, format, data, timeout, reason, callerid);
04035       if (!chan) {
04036          free(as);
04037          return -1;
04038       }
04039       pbx_builtin_setaccount(chan, account);
04040       as->chan = chan;
04041       strncpy(as->app, app, sizeof(as->app) - 1);
04042       if (appdata)
04043          strncpy(as->appdata,  appdata, sizeof(as->appdata) - 1);
04044       as->timeout = timeout;
04045       if (pthread_create(&as->p, NULL, async_wait, as)) {
04046          ast_log(LOG_WARNING, "Failed to start async wait\n");
04047          free(as);
04048          ast_hangup(chan);
04049          return -1;
04050       }
04051       res = 0;
04052    }
04053    return res;
04054 }

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

Definition at line 3865 of file pbx.c.

References option_verbose.

03866 {
03867    struct ast_channel *chan;
03868    struct async_stat *as;
03869    int res = -1;
03870    char *var, *tmp;
03871    struct outgoing_helper oh;
03872    pthread_attr_t attr;
03873       
03874    if (sync) {
03875       LOAD_OH(oh);
03876       chan = __ast_request_and_dial(type, format, data, timeout, reason, callerid, &oh);
03877       if (chan) {
03878          pbx_builtin_setaccount(chan, account);
03879          if (chan->_state == AST_STATE_UP) {
03880                res = 0;
03881             if (option_verbose > 3)
03882                ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", chan->name);
03883 
03884             if (sync > 1) {
03885                if (ast_pbx_run(chan)) {
03886                   ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name);
03887                   ast_hangup(chan);
03888                   res = -1;
03889                }
03890             } else {
03891                if (ast_pbx_start(chan)) {
03892                   ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name);
03893                   ast_hangup(chan);
03894                   res = -1;
03895                } 
03896             }
03897          } else {
03898             if (option_verbose > 3)
03899                ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", chan->name);
03900             ast_hangup(chan);
03901          }
03902       } else {
03903          /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */
03904          /* check if "failed" exists */
03905          if (ast_exists_extension(chan, context, "failed", 1, NULL)) {
03906             chan = ast_channel_alloc(0);
03907             if (chan) {
03908                strncpy(chan->name, "OutgoingSpoolFailed", sizeof(chan->name) - 1);
03909                if (context && strlen(context))
03910                   strncpy(chan->context, context, sizeof(chan->context) - 1);
03911                strncpy(chan->exten, "failed", sizeof(chan->exten) - 1);
03912                chan->priority = 1;
03913                if (variable) {
03914                   tmp = ast_strdupa(variable);
03915                   for (var = strtok_r(tmp, "|", &tmp); var; var = strtok_r(NULL, "|", &tmp)) {
03916                      pbx_builtin_setvar( chan, var );
03917                   }
03918                }
03919                ast_pbx_run(chan);   
03920             } else
03921                ast_log(LOG_WARNING, "Can't allocate the channel structure, skipping execution of extension 'failed'\n");
03922          }
03923       }
03924    } else {
03925       as = malloc(sizeof(struct async_stat));
03926       if (!as)
03927          return -1;
03928       memset(as, 0, sizeof(struct async_stat));
03929       chan = ast_request_and_dial(type, format, data, timeout, reason, callerid);
03930       if (!chan) {
03931          free(as);
03932          return -1;
03933       }
03934       pbx_builtin_setaccount(chan, account);
03935       as->chan = chan;
03936       strncpy(as->context, context, sizeof(as->context) - 1);
03937       strncpy(as->exten,  exten, sizeof(as->exten) - 1);
03938       as->priority = priority;
03939       as->timeout = timeout;
03940       pthread_attr_init(&attr);
03941       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
03942       if (pthread_create(&as->p, &attr, async_wait, as)) {
03943          ast_log(LOG_WARNING, "Failed to start async wait\n");
03944          free(as);
03945          ast_hangup(chan);
03946          return -1;
03947       }
03948       res = 0;
03949    }
03950    return res;
03951 }

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 1660 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, EVENT_FLAG_CALL, ast_channel::exten, free, LOG_DEBUG, LOG_ERROR, LOG_WARNING, malloc, manager_event(), ast_channel::name, option_debug, option_verbose, ast_channel::pbx, pbx_builtin_setvar_helper(), ast_channel::priority, ast_pbx::rtimeout, ast_channel::uniqueid, VERBOSE_PREFIX_2, VERBOSE_PREFIX_3, and ast_channel::whentohangup.

01661 {
01662    int firstpass = 1;
01663    char digit;
01664    char exten[256];
01665    int pos;
01666    int waittime;
01667    int res=0;
01668 
01669    /* A little initial setup here */
01670    if (c->pbx)
01671       ast_log(LOG_WARNING, "%s already has PBX structure??\n", c->name);
01672    c->pbx = malloc(sizeof(struct ast_pbx));
01673    if (!c->pbx) {
01674       ast_log(LOG_ERROR, "Out of memory\n");
01675       return -1;
01676    }
01677    if (c->amaflags) {
01678       if (c->cdr) {
01679          ast_log(LOG_WARNING, "%s already has a call record??\n", c->name);
01680       } else {
01681          c->cdr = ast_cdr_alloc();
01682          if (!c->cdr) {
01683             ast_log(LOG_WARNING, "Unable to create Call Detail Record\n");
01684             free(c->pbx);
01685             return -1;
01686          }
01687          ast_cdr_init(c->cdr, c);
01688       }
01689    }
01690    memset(c->pbx, 0, sizeof(struct ast_pbx));
01691    /* Set reasonable defaults */
01692    c->pbx->rtimeout = 10;
01693    c->pbx->dtimeout = 5;
01694 
01695    /* Start by trying whatever the channel is set to */
01696    if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) {
01697       /* JK02: If not successfull fall back to 's' */
01698       strncpy(c->exten, "s", sizeof(c->exten)-1);
01699       if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) {
01700          /* JK02: And finally back to default if everything else failed */
01701          strncpy(c->context, "default", sizeof(c->context)-1);
01702       }
01703       c->priority = 1;
01704    }
01705    if (c->cdr)
01706       ast_cdr_start(c->cdr);
01707    for(;;) {
01708       pos = 0;
01709       digit = 0;
01710       while(ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) {
01711          memset(exten, 0, sizeof(exten));
01712          manager_event(EVENT_FLAG_CALL, "Newexten", 
01713             "Channel: %s\r\n"
01714             "Context: %s\r\n"
01715             "Extension: %s\r\n"
01716             "Priority: %d\r\n"
01717             "Uniqueid: %s\r\n",
01718             c->name, c->context, c->exten, c->priority, c->uniqueid);
01719          if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->callerid))) {
01720             /* Something bad happened, or a hangup has been requested. */
01721             if (((res >= '0') && (res <= '9')) || ((res >= 'A') && (res <= 'F')) ||
01722                (res == '*') || (res == '#')) {
01723                ast_log(LOG_DEBUG, "Oooh, got something to jump out with ('%c')!\n", res);
01724                memset(exten, 0, sizeof(exten));
01725                pos = 0;
01726                exten[pos++] = digit = res;
01727                break;
01728             }
01729             switch(res) {
01730             case AST_PBX_KEEPALIVE:
01731                if (option_debug)
01732                   ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
01733                else if (option_verbose > 1)
01734                   ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
01735                goto out;
01736                break;
01737             default:
01738                if (option_debug)
01739                   ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
01740                else if (option_verbose > 1)
01741                   ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
01742                if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
01743                   c->_softhangup =0;
01744                   break;
01745                }
01746                /* atimeout */
01747                if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) {
01748                   break;
01749                }
01750 
01751                if (c->cdr) {
01752                   ast_cdr_update(c);
01753                }
01754                goto out;
01755             }
01756          }
01757          if ((c->_softhangup == AST_SOFTHANGUP_TIMEOUT) && (ast_exists_extension(c,c->context,"T",1,c->callerid))) {
01758             strncpy(c->exten,"T",sizeof(c->exten) - 1);
01759             /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
01760             c->whentohangup = 0;
01761             c->priority = 0;
01762             c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT;
01763          } else if (c->_softhangup) {
01764             ast_log(LOG_DEBUG, "Extension %s, priority %d returned normally even though call was hung up\n",
01765                c->exten, c->priority);
01766             goto out;
01767          }
01768          firstpass = 0;
01769          c->priority++;
01770       }
01771       if (!ast_exists_extension(c, c->context, c->exten, 1, c->callerid)) {
01772          /* It's not a valid extension anymore */
01773          if (ast_exists_extension(c, c->context, "i", 1, c->callerid)) {
01774             if (option_verbose > 2)
01775                ast_verbose(VERBOSE_PREFIX_3 "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, c->name);
01776             pbx_builtin_setvar_helper(c, "INVALID_EXTEN", c->exten);
01777             strncpy(c->exten, "i", sizeof(c->exten)-1);
01778             c->priority = 1;
01779          } else {
01780             ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n",
01781                c->name, c->exten, c->context);
01782             goto out;
01783          }
01784       } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) {
01785          /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */
01786          c->_softhangup = 0;
01787       } else {
01788          /* Done, wait for an extension */
01789          if (digit)
01790             waittime = c->pbx->dtimeout;
01791          else
01792             waittime = c->pbx->rtimeout;
01793          while (ast_matchmore_extension(c, c->context, exten, 1, c->callerid)) {
01794             /* As long as we're willing to wait, and as long as it's not defined, 
01795                keep reading digits until we can't possibly get a right answer anymore.  */
01796             digit = ast_waitfordigit(c, waittime * 1000);
01797             if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
01798                c->_softhangup = 0;
01799             } else {
01800                if (!digit)
01801                   /* No entry */
01802                   break;
01803                if (digit < 0)
01804                   /* Error, maybe a  hangup */
01805                   goto out;
01806                exten[pos++] = digit;
01807                waittime = c->pbx->dtimeout;
01808             }
01809          }
01810          if (ast_exists_extension(c, c->context, exten, 1, c->callerid)) {
01811             /* Prepare the next cycle */
01812             strncpy(c->exten, exten, sizeof(c->exten)-1);
01813             c->priority = 1;
01814          } else {
01815             /* No such extension */
01816             if (strlen(exten)) {
01817                /* An invalid extension */
01818                if (ast_exists_extension(c, c->context, "i", 1, c->callerid)) {
01819                   if (option_verbose > 2)
01820                      ast_verbose( VERBOSE_PREFIX_3 "Invalid extension '%s' in context '%s' on %s\n", exten, c->context, c->name);
01821                   pbx_builtin_setvar_helper(c, "INVALID_EXTEN", exten);
01822                   strncpy(c->exten, "i", sizeof(c->exten)-1);
01823                   c->priority = 1;
01824                } else {
01825                   ast_log(LOG_WARNING, "Invalid extension, but no rule 'i' in context '%s'\n", c->context);
01826                   goto out;
01827                }
01828             } else {
01829                /* A simple timeout */
01830                if (ast_exists_extension(c, c->context, "t", 1, c->callerid)) {
01831                   if (option_verbose > 2)
01832                      ast_verbose( VERBOSE_PREFIX_3 "Timeout on %s\n", c->name);
01833                   strncpy(c->exten, "t", sizeof(c->exten)-1);
01834                   c->priority = 1;
01835                } else {
01836                   ast_log(LOG_WARNING, "Timeout, but no rule 't' in context '%s'\n", c->context);
01837                   goto out;
01838                }
01839             }  
01840          }
01841          if (c->cdr) {
01842              if (option_verbose > 2)
01843             ast_verbose(VERBOSE_PREFIX_2 "CDR updated on %s\n",c->name);   
01844              ast_cdr_update(c);
01845           }
01846       }
01847    }
01848    if (firstpass) 
01849       ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name);
01850 out:
01851    if ((res != AST_PBX_KEEPALIVE) && ast_exists_extension(c, c->context, "h", 1, c->callerid)) {
01852       strcpy(c->exten, "h");
01853       c->priority = 1;
01854       while(ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) {
01855          if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->callerid))) {
01856             /* Something bad happened, or a hangup has been requested. */
01857             if (option_debug)
01858                ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
01859             else if (option_verbose > 1)
01860                ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
01861             break;
01862          }
01863          c->priority++;
01864       }
01865    }
01866 
01867    pbx_destroy(c->pbx);
01868    c->pbx = NULL;
01869    if (res != AST_PBX_KEEPALIVE)
01870       ast_hangup(c);
01871    return 0;
01872 }

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

References ast_log(), and LOG_WARNING.

01888 {
01889    pthread_t t;
01890    pthread_attr_t attr;
01891    if (!c) {
01892       ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
01893       return -1;
01894    }
01895       
01896    /* Start a new thread, and get something handling this channel. */
01897    pthread_attr_init(&attr);
01898    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
01899    if (pthread_create(&t, &attr, pbx_thread, c)) {
01900       ast_log(LOG_WARNING, "Failed to create new channel thread\n");
01901       return -1;
01902    }
01903    return 0;
01904 }

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.

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

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

02196 {
02197    struct ast_app *tmp, *prev, *cur;
02198    char tmps[80];
02199    if (ast_mutex_lock(&applock)) {
02200       ast_log(LOG_ERROR, "Unable to lock application list\n");
02201       return -1;
02202    }
02203    tmp = apps;
02204    while(tmp) {
02205       if (!strcasecmp(app, tmp->name)) {
02206          ast_log(LOG_WARNING, "Already have an application '%s'\n", app);
02207          ast_mutex_unlock(&applock);
02208          return -1;
02209       }
02210       tmp = tmp->next;
02211    }
02212    tmp = malloc(sizeof(struct ast_app));
02213    if (tmp) {
02214       memset(tmp, 0, sizeof(struct ast_app));
02215       strncpy(tmp->name, app, sizeof(tmp->name)-1);
02216       tmp->execute = execute;
02217       tmp->synopsis = synopsis;
02218       tmp->description = description;
02219       /* Store in alphabetical order */
02220       cur = apps;
02221       prev = NULL;
02222       while(cur) {
02223          if (strcasecmp(tmp->name, cur->name) < 0)
02224             break;
02225          prev = cur;
02226          cur = cur->next;
02227       }
02228       if (prev) {
02229          tmp->next = prev->next;
02230          prev->next = tmp;
02231       } else {
02232          tmp->next = apps;
02233          apps = tmp;
02234       }
02235    } else {
02236       ast_log(LOG_ERROR, "Out of memory\n");
02237       ast_mutex_unlock(&applock);
02238       return -1;
02239    }
02240    if (option_verbose > 1)
02241       ast_verbose( VERBOSE_PREFIX_2 "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps)));
02242    ast_mutex_unlock(&applock);
02243    return 0;
02244 }

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

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

02247 {
02248    struct ast_switch *tmp, *prev=NULL;
02249    if (ast_mutex_lock(&switchlock)) {
02250       ast_log(LOG_ERROR, "Unable to lock switch lock\n");
02251       return -1;
02252    }
02253    tmp = switches;
02254    while(tmp) {
02255       if (!strcasecmp(tmp->name, sw->name))
02256          break;
02257       prev = tmp;
02258       tmp = tmp->next;
02259    }
02260    if (tmp) {  
02261       ast_mutex_unlock(&switchlock);
02262       ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name);
02263       return -1;
02264    }
02265    sw->next = NULL;
02266    if (prev) 
02267       prev->next = sw;
02268    else
02269       switches = sw;
02270    ast_mutex_unlock(&switchlock);
02271    return 0;
02272 }

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

References HELPER_SPAWN.

Referenced by ast_pbx_run().

01656 {
01657    return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_SPAWN);
01658 }

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

04605 {
04606    return ast_mutex_unlock(&con->lock);
04607 }

int ast_unlock_contexts void   ) 
 

Unlocks contexts.

Returns 0 on success, -1 on failure

Definition at line 4591 of file pbx.c.

Referenced by ast_context_remove_extension(), ast_context_remove_include(), ast_context_remove_switch(), and ast_ignore_pattern().

04592 {
04593    return ast_mutex_unlock(&conlock);
04594 }

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

02755                                           {
02756    struct ast_app *tmp, *tmpl = NULL;
02757    if (ast_mutex_lock(&applock)) {
02758       ast_log(LOG_ERROR, "Unable to lock application list\n");
02759       return -1;
02760    }
02761    tmp = apps;
02762    while(tmp) {
02763       if (!strcasecmp(app, tmp->name)) {
02764          if (tmpl)
02765             tmpl->next = tmp->next;
02766          else
02767             apps = tmp->next;
02768          if (option_verbose > 1)
02769             ast_verbose( VERBOSE_PREFIX_2 "Unregistered application '%s'\n", tmp->name);
02770          ast_mutex_unlock(&applock);
02771          return 0;
02772       }
02773       tmpl = tmp;
02774       tmp = tmp->next;
02775    }
02776    ast_mutex_unlock(&applock);
02777    return -1;
02778 }

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

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

02275 {
02276    struct ast_switch *tmp, *prev=NULL;
02277    if (ast_mutex_lock(&switchlock)) {
02278       ast_log(LOG_ERROR, "Unable to lock switch lock\n");
02279       return;
02280    }
02281    tmp = switches;
02282    while(tmp) {
02283       if (tmp == sw) {
02284          if (prev)
02285             prev->next = tmp->next;
02286          else
02287             switches = tmp->next;
02288          tmp->next = NULL;
02289          break;         
02290       }
02291       prev = tmp;
02292       tmp = tmp->next;
02293    }
02294    ast_mutex_unlock(&switchlock);
02295 }

struct ast_exten* ast_walk_context_extensions struct ast_context con,
struct ast_exten exten
 

Definition at line 4696 of file pbx.c.

04698 {
04699    if (!exten)
04700       return con ? con->root : NULL;
04701    else
04702       return exten->next;
04703 }

struct ast_ignorepat* ast_walk_context_ignorepats struct ast_context con,
struct ast_ignorepat ip
 

Definition at line 4732 of file pbx.c.

04734 {
04735    if (!ip)
04736       return con ? con->ignorepats : NULL;
04737    else
04738       return ip->next;
04739 }

struct ast_include* ast_walk_context_includes struct ast_context con,
struct ast_include inc
 

Definition at line 4723 of file pbx.c.

04725 {
04726    if (!inc)
04727       return con ? con->includes : NULL;
04728    else
04729       return inc->next;
04730 }

struct ast_sw* ast_walk_context_switches struct ast_context con,
struct ast_sw sw
 

Definition at line 4705 of file pbx.c.

04707 {
04708    if (!sw)
04709       return con ? con->alts : NULL;
04710    else
04711       return sw->next;
04712 }

struct ast_context* ast_walk_contexts struct ast_context con  ) 
 

Definition at line 4688 of file pbx.c.

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

Referenced by ast_context_remove_extension(), ast_context_remove_include(), ast_context_remove_switch(), and ast_ignore_pattern().

04689 {
04690    if (!con)
04691       return contexts;
04692    else
04693       return con->next;
04694 }

struct ast_exten* ast_walk_extension_priorities struct ast_exten exten,
struct ast_exten priority
 

Definition at line 4714 of file pbx.c.

04716 {
04717    if (!priority)
04718       return exten;
04719    else
04720       return priority->peer;
04721 }

int load_pbx void   ) 
 

Definition at line 4560 of file pbx.c.

Referenced by main().

04561 {
04562    int x;
04563    /* Initialize the PBX */
04564    if (option_verbose) {
04565       ast_verbose( "Asterisk PBX Core Initializing\n");
04566       ast_verbose( "Registering builtin applications:\n");
04567    }
04568    ast_cli_register(&show_applications_cli);
04569    ast_cli_register(&show_application_cli);
04570    ast_cli_register(&show_dialplan_cli);
04571    ast_cli_register(&show_switches_cli);
04572    for (x=0;x<sizeof(builtins) / sizeof(struct pbx_builtin); x++) {
04573       if (option_verbose)
04574          ast_verbose( VERBOSE_PREFIX_1 "[%s]\n", builtins[x].name);
04575       if (ast_register_application(builtins[x].name, builtins[x].execute, builtins[x].synopsis, builtins[x].description)) {
04576          ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name);
04577          return -1;
04578       }
04579    }
04580    return 0;
04581 }

void pbx_builtin_clear_globals void   ) 
 

Definition at line 4484 of file pbx.c.

04485 {
04486    struct ast_var_t *vardata;
04487    while (!AST_LIST_EMPTY(&globals)) {
04488       vardata = AST_LIST_FIRST(&globals);
04489       AST_LIST_REMOVE_HEAD(&globals, entries);
04490       ast_var_delete(vardata);
04491    }
04492 }

char * pbx_builtin_getvar_helper struct ast_channel chan,
char *  name
 

Definition at line 4386 of file pbx.c.

References ast_var_name(), and ast_var_value().

04386                                                                       {
04387    struct ast_var_t *variables;
04388    struct varshead *headp;
04389 
04390     if (chan)
04391         headp=&chan->varshead;
04392    else
04393       headp=&globals;
04394 
04395    if (name) {
04396       AST_LIST_TRAVERSE(headp,variables,entries) {
04397          if (!strcmp(name, ast_var_name(variables)))
04398             return ast_var_value(variables);
04399       }
04400       if (headp != &globals) {
04401          /* Check global variables if we haven't already */
04402          headp = &globals;
04403          AST_LIST_TRAVERSE(headp,variables,entries) {
04404             if (!strcmp(name, ast_var_name(variables)))
04405                return ast_var_value(variables);
04406          }
04407       }
04408    }
04409    return NULL;
04410 }

int pbx_builtin_setvar struct ast_channel ,
void * 
 

Definition at line 4437 of file pbx.c.

04438 {
04439    char *name;
04440    char *value;
04441    char *stringp=NULL;
04442                 
04443    if (!data || !strlen(data)) {
04444       ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n");
04445       return 0;
04446    }
04447    
04448    stringp=data;
04449    name=strsep(&stringp,"=");
04450    value=strsep(&stringp,"\0"); 
04451    
04452    pbx_builtin_setvar_helper(chan,name,value);
04453          
04454         return(0);
04455 }

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

Definition at line 4412 of file pbx.c.

References AST_LIST_INSERT_HEAD, ast_var_assign(), ast_verbose(), option_verbose, and VERBOSE_PREFIX_3.

04412                                                                                   {
04413    struct ast_var_t *newvariable;
04414         struct varshead *headp;
04415     if (chan)
04416         headp=&chan->varshead;
04417    else
04418       headp=&globals;
04419                 
04420    AST_LIST_TRAVERSE (headp,newvariable,entries) {
04421       if (strcasecmp(ast_var_name(newvariable),name)==0) {
04422          /* there is already such a variable, delete it */
04423          AST_LIST_REMOVE(headp,newvariable,ast_var_t,entries);
04424          ast_var_delete(newvariable);
04425          break;
04426       }
04427    } 
04428    
04429    if (value) {
04430       if ((option_verbose > 1) && (headp == &globals))
04431          ast_verbose(VERBOSE_PREFIX_3 "Setting global variable '%s' to '%s'\n",name, value);
04432       newvariable=ast_var_assign(name,value);   
04433       AST_LIST_INSERT_HEAD(headp,newvariable,entries);
04434    }
04435 }

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

00366 {
00367    /* This function is special.  It saves the stack so that no matter
00368       how many times it is called, it returns to the same place */
00369    int res;
00370    int stack = c->stack;
00371    int (*execute)(struct ast_channel *chan, void *data) = app->execute; 
00372    if (newstack && stack > AST_CHANNEL_MAX_STACK - 2) {
00373       /* Don't allow us to go over the max number of stacks we
00374          permit saving. */
00375       ast_log(LOG_WARNING, "Stack overflow, cannot create another stack\n");
00376       return -1;
00377    }
00378    if (newstack && (res = setjmp(c->jmp[++c->stack]))) {
00379       /* Okay, here's where it gets weird.  If newstack is non-zero, 
00380          then we increase the stack increment, but setjmp is not going
00381          to return until longjmp is called -- when the application
00382          exec'd is finished running. */
00383       if (res == 1)
00384          res = 0;
00385       if (c->stack != stack + 1) 
00386          ast_log(LOG_WARNING, "Stack returned to an unexpected place!\n");
00387       else if (c->app[c->stack])
00388          ast_log(LOG_WARNING, "Application may have forgotten to free its memory\n");
00389       c->stack = stack;
00390       return res;
00391    } else {
00392       if (c->cdr)
00393          ast_cdr_setapp(c->cdr, app->name, data);
00394       c->appl = app->name;
00395       c->data = data;      
00396       res = execute(c, data);
00397       c->appl = NULL;
00398       c->data = NULL;      
00399       /* Any application that returns, we longjmp back, just in case. */
00400       if (c->stack != stack + 1)
00401          ast_log(LOG_WARNING, "Stack is not at expected value\n");
00402       longjmp(c->jmp[stack+1], res);
00403       /* Never returns */
00404    }
00405 }

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

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

00418 {
00419    struct ast_app *tmp;
00420    if (ast_mutex_lock(&applock)) {
00421       ast_log(LOG_WARNING, "Unable to obtain application lock\n");
00422       return NULL;
00423    }
00424    tmp = apps;
00425    while(tmp) {
00426       if (!strcasecmp(tmp->name, app))
00427          break;
00428       tmp = tmp->next;
00429    }
00430    ast_mutex_unlock(&applock);
00431    return tmp;
00432 }

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

Definition at line 945 of file pbx.c.

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

00946 {
00947    char *cp4;
00948    const char *tmp, *whereweare;
00949    int length;
00950    char workspace[256];
00951    char ltmp[256], var[256];
00952    char *nextvar, *nextexp;
00953    char *vars, *vare;
00954    int pos, brackets, needsub, len;
00955 
00956    /* Substitutes variables into cp2, based on string cp1, and assuming cp2 to be
00957       zero-filled */
00958    whereweare=tmp=cp1;
00959    while(strlen(whereweare) && count) {
00960       /* Assume we're copying the whole remaining string */
00961       pos = strlen(whereweare);
00962 
00963       /* Look for a variable */
00964       nextvar = strstr(whereweare, "${");
00965       
00966       nextexp = strstr(whereweare, "$[");
00967       
00968       if (nextvar && nextexp) {
00969          if (nextvar < nextexp)
00970             nextexp = NULL;
00971          else
00972             nextvar = NULL;
00973       }
00974       
00975       /* If there is one, we only go that far */
00976       if (nextvar)
00977          pos = nextvar - whereweare;
00978       else if (nextexp)
00979          pos = nextexp - whereweare;
00980       
00981       /* Can't copy more than 'count' bytes */
00982       if (pos > count)
00983          pos = count;
00984       
00985       /* Copy that many bytes */
00986       memcpy(cp2, whereweare, pos);
00987       
00988       count -= pos;
00989       cp2 += pos;
00990       whereweare += pos;
00991       
00992       if (nextvar) {
00993          /* We have a variable.  Find the start and end, and determine
00994             if we are going to have to recursively call ourselves on the
00995             contents */
00996          vars = vare = nextvar + 2;
00997          brackets = 1;
00998          needsub = 0;
00999          
01000          /* Find the end of it */
01001          while(brackets && *vare) {
01002             if ((vare[0] == '$') && (vare[1] == '{')) {
01003                needsub++;
01004                brackets++;
01005             } else if (vare[0] == '}') {
01006                brackets--;
01007             } else if ((vare[0] == '$') && (vare[1] == '['))
01008                needsub++;
01009             vare++;
01010          }
01011          if (brackets)
01012             ast_log(LOG_NOTICE, "Error in extension logic (missing '}')\n");
01013          len = vare - vars - 1;
01014          
01015          /* Skip totally over variable name */
01016          whereweare += ( len + 3);
01017          
01018          /* Store variable name (and truncate) */
01019          memset(var, 0, sizeof(var));
01020          strncpy(var, vars, sizeof(var) - 1);
01021          var[len] = '\0';
01022          
01023          /* Substitute if necessary */
01024          if (needsub) {
01025             memset(ltmp, 0, sizeof(ltmp));
01026             pbx_substitute_variables_helper(c, var, ltmp, sizeof(ltmp) - 1);
01027             vars = ltmp;
01028          } else {
01029             vars = var;
01030          }
01031          
01032          /* Retrieve variable value */
01033          strcpy(workspace, "");
01034          pbx_substitute_variables_temp(c,vars,&cp4, workspace, sizeof(workspace));
01035          if (cp4) {
01036             length = strlen(cp4);
01037             if (length > count)
01038                length = count;
01039             memcpy(cp2, cp4, length);
01040             count -= length;
01041             cp2 += length;
01042          }
01043          
01044       } else if (nextexp) {
01045          /* We have an expression.  Find the start and end, and determine
01046             if we are going to have to recursively call ourselves on the
01047             contents */
01048          vars = vare = nextexp + 2;
01049          brackets = 1;
01050          needsub = 0;
01051          
01052          /* Find the end of it */
01053          while(brackets && *vare) {
01054             if ((vare[0] == '$') && (vare[1] == '[')) {
01055                needsub++;
01056                brackets++;
01057             } else if (vare[0] == ']') {
01058                brackets--;
01059             } else if ((vare[0] == '$') && (vare[1] == '{'))
01060                needsub++;
01061             vare++;
01062          }
01063          if (brackets)
01064             ast_log(LOG_NOTICE, "Error in extension logic (missing ']')\n");
01065          len = vare - vars - 1;
01066          
01067          /* Skip totally over variable name */
01068          whereweare += ( len + 3);
01069          
01070          /* Store variable name (and truncate) */
01071          memset(var, 0, sizeof(var));
01072          strncpy(var, vars, sizeof(var) - 1);
01073          var[len] = '\0';
01074          
01075          /* Substitute if necessary */
01076          if (needsub) {
01077             memset(ltmp, 0, sizeof(ltmp));
01078             pbx_substitute_variables_helper(c, var, ltmp, sizeof(ltmp) - 1);
01079             vars = ltmp;
01080          } else {
01081             vars = var;
01082          }
01083 
01084          /* Evaluate expression */        
01085          cp4 = ast_expr(vars);
01086          
01087          ast_log(LOG_DEBUG, "Expression is '%s'\n", cp4);
01088          
01089          if (cp4) {
01090             length = strlen(cp4);
01091             if (length > count)
01092                length = count;
01093             memcpy(cp2, cp4, length);
01094             count -= length;
01095             cp2 += length;
01096             free(cp4);
01097          }
01098          
01099       } else
01100          break;
01101    }
01102 }


Variable Documentation

struct ast_hint* hints = NULL
 

Definition at line 359 of file pbx.c.

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

struct ast_state_cb* statecbs = NULL
 

Definition at line 360 of file pbx.c.

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

struct ast_switch* switches = NULL
 

Definition at line 354 of file pbx.c.

Referenced by ast_register_switch(), and ast_unregister_switch().


Generated on Sun Apr 18 23:34:12 2004 for Asterisk by doxygen 1.3.6-20040222