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  app_tmp
struct  ast_app
struct  ast_context
struct  ast_exten
struct  ast_hint
struct  ast_ignorepat
struct  ast_include
struct  ast_state_cb
struct  ast_sw
struct  async_stat
struct  pbx_builtin

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

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,...)
 Tells Asterisk the State for Device is changed.

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)
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)
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)

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

References ast_log(), ast_mutex_lock, ast_mutex_unlock, free, LOG_WARNING, ast_context::name, ast_exten::next, ast_context::next, and ast_exten::peer.

Referenced by ast_context_destroy(), and ast_merge_contexts_and_delete().

03960 {
03961    struct ast_context *tmp, *tmpl=NULL;
03962    struct ast_include *tmpi, *tmpil= NULL;
03963    struct ast_sw *sw, *swl= NULL;
03964    struct ast_exten *e, *el, *en;
03965    if (lock)
03966       ast_mutex_lock(&conlock);
03967    tmp = contexts;
03968    while(tmp) {
03969       if (((tmp->name && con && con->name && !strcasecmp(tmp->name, con->name)) || !con) &&
03970           (!registrar || !strcasecmp(registrar, tmp->registrar))) {
03971          /* Okay, let's lock the structure to be sure nobody else
03972             is searching through it. */
03973          if (ast_mutex_lock(&tmp->lock)) {
03974             ast_log(LOG_WARNING, "Unable to lock context lock\n");
03975             return;
03976          }
03977          if (tmpl)
03978             tmpl->next = tmp->next;
03979          else
03980             contexts = tmp->next;
03981          /* Okay, now we're safe to let it go -- in a sense, we were
03982             ready to let it go as soon as we locked it. */
03983          ast_mutex_unlock(&tmp->lock);
03984          for (tmpi = tmp->includes; tmpi; ) {
03985             /* Free includes */
03986             tmpil = tmpi;
03987             tmpi = tmpi->next;
03988             free(tmpil);
03989             tmpil = tmpi;
03990          }
03991          for (sw = tmp->alts; sw; ) {
03992             swl = sw;
03993             sw = sw->next;
03994             free(swl);
03995             swl = sw;
03996          }
03997          for (e = tmp->root; e;) {
03998             for (en = e->peer; en;) {
03999                el = en;
04000                en = en->peer;
04001                destroy_exten(el);
04002             }
04003             el = e;
04004             e = e->next;
04005             destroy_exten(el);
04006          }
04007          free(tmp);
04008          if (!con) {
04009             /* Might need to get another one -- restart */
04010             tmp = contexts;
04011             tmpl = NULL;
04012             tmpil = NULL;
04013             continue;
04014          }
04015          if (lock)
04016             ast_mutex_unlock(&conlock);
04017          return;
04018       }
04019       tmpl = tmp;
04020       tmp = tmp->next;
04021    }
04022    if (lock)
04023       ast_mutex_unlock(&conlock);
04024 }

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

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

03392 {
03393    struct ast_context *c;
03394 
03395    if (ast_lock_contexts()) {
03396       errno = EBUSY;
03397       return -1;
03398    }
03399 
03400    c = ast_walk_contexts(NULL);
03401    while (c) {
03402       if (!strcmp(context, ast_get_context_name(c))) {
03403          int ret = ast_add_extension2(c, replace, extension, priority, callerid,
03404             application, data, datad, registrar);
03405          ast_unlock_contexts();
03406          return ret;
03407       }
03408       c = ast_walk_contexts(c);
03409    }
03410 
03411    ast_unlock_contexts();
03412    errno = ENOENT;
03413    return -1;
03414 }

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

References ast_log(), ast_mutex_lock, ast_mutex_unlock, free, ast_context::lock, LOG_WARNING, malloc, ast_context::name, ast_exten::next, ast_exten::peer, PRIORITY_HINT, ast_context::registrar, and ast_context::root.

Referenced by ast_add_extension().

03526 {
03527 
03528 #define LOG do {  if (option_debug) {\
03529       if (tmp->matchcid) { \
03530          ast_log(LOG_DEBUG, "Added extension '%s' priority %d (CID match '%s') to %s\n", tmp->exten, tmp->priority, tmp->cidmatch, con->name); \
03531       } else { \
03532          ast_log(LOG_DEBUG, "Added extension '%s' priority %d to %s\n", tmp->exten, tmp->priority, con->name); \
03533       } \
03534    } else if (option_verbose > 2) { \
03535       if (tmp->matchcid) { \
03536          ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d (CID match '%s')to %s\n", tmp->exten, tmp->priority, tmp->cidmatch, con->name); \
03537       } else {  \
03538          ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d to %s\n", tmp->exten, tmp->priority, con->name); \
03539       } \
03540    } } while(0)
03541 
03542    /*
03543     * This is a fairly complex routine.  Different extensions are kept
03544     * in order by the extension number.  Then, extensions of different
03545     * priorities (same extension) are kept in a list, according to the
03546     * peer pointer.
03547     */
03548    struct ast_exten *tmp, *e, *el = NULL, *ep = NULL;
03549    int res;
03550    /* Be optimistic:  Build the extension structure first */
03551    tmp = malloc(sizeof(struct ast_exten));
03552    if (tmp) {
03553       memset(tmp, 0, sizeof(struct ast_exten));
03554       ext_strncpy(tmp->exten, extension, sizeof(tmp->exten));
03555       tmp->priority = priority;
03556       if (callerid) {
03557          ext_strncpy(tmp->cidmatch, callerid, sizeof(tmp->cidmatch));
03558          tmp->matchcid = 1;
03559       } else {
03560          strcpy(tmp->cidmatch, "");
03561          tmp->matchcid = 0;
03562       }
03563       strncpy(tmp->app, application, sizeof(tmp->app)-1);
03564       tmp->parent = con;
03565       tmp->data = data;
03566       tmp->datad = datad;
03567       tmp->registrar = registrar;
03568       tmp->peer = NULL;
03569       tmp->next =  NULL;
03570    } else {
03571       ast_log(LOG_WARNING, "Out of memory\n");
03572       errno = ENOMEM;
03573       return -1;
03574    }
03575    if (ast_mutex_lock(&con->lock)) {
03576       free(tmp);
03577       /* And properly destroy the data */
03578       datad(data);
03579       ast_log(LOG_WARNING, "Failed to lock context '%s'\n", con->name);
03580       errno = EBUSY;
03581       return -1;
03582    }
03583    e = con->root;
03584    while(e) {
03585       res= strcasecmp(e->exten, extension);
03586       if (!res) {
03587          if (!e->matchcid && !tmp->matchcid)
03588             res = 0;
03589          else if (tmp->matchcid && !e->matchcid)
03590             res = 1;
03591          else if (e->matchcid && !tmp->matchcid)
03592             res = -1;
03593          else
03594             res = strcasecmp(e->cidmatch, tmp->cidmatch);
03595       }
03596       if (res == 0) {
03597          /* We have an exact match, now we find where we are
03598             and be sure there's no duplicates */
03599          while(e) {
03600             if (e->priority == tmp->priority) {
03601                /* Can't have something exactly the same.  Is this a
03602                   replacement?  If so, replace, otherwise, bonk. */
03603                if (replace) {
03604                   if (ep) {
03605                      /* We're in the peer list, insert ourselves */
03606                      ep->peer = tmp;
03607                      tmp->peer = e->peer;
03608                   } else if (el) {
03609                      /* We're the first extension. Take over e's functions */
03610                      el->next = tmp;
03611                      tmp->next = e->next;
03612                      tmp->peer = e->peer;
03613                   } else {
03614                      /* We're the very first extension.  */
03615                      con->root = tmp;
03616                      tmp->next = e->next;
03617                      tmp->peer = e->peer;
03618                   }
03619                   if (tmp->priority == PRIORITY_HINT)
03620                       ast_change_hint(e,tmp);
03621                   /* Destroy the old one */
03622                   e->datad(e->data);
03623                   free(e);
03624                   ast_mutex_unlock(&con->lock);
03625                   if (tmp->priority == PRIORITY_HINT)
03626                       ast_change_hint(e, tmp);
03627                   /* And immediately return success. */
03628                   LOG;
03629                   return 0;
03630                } else {
03631                   ast_log(LOG_WARNING, "Unable to register extension '%s', priority %d in '%s', already in use\n", tmp->exten, tmp->priority, con->name);
03632                   tmp->datad(tmp->data);
03633                   free(tmp);
03634                   ast_mutex_unlock(&con->lock);
03635                   errno = EEXIST;
03636                   return -1;
03637                }
03638             } else if (e->priority > tmp->priority) {
03639                /* Slip ourselves in just before e */
03640                if (ep) {
03641                   /* Easy enough, we're just in the peer list */
03642                   ep->peer = tmp;
03643                   tmp->peer = e;
03644                } else if (el) {
03645                   /* We're the first extension in this peer list */
03646                   el->next = tmp;
03647                   tmp->next = e->next;
03648                   e->next = NULL;
03649                   tmp->peer = e;
03650                } else {
03651                   /* We're the very first extension altogether */
03652                   tmp->next = con->root;
03653                   /* Con->root must always exist or we couldn't get here */
03654                   tmp->peer = con->root->peer;
03655                   con->root = tmp;
03656                }
03657                ast_mutex_unlock(&con->lock);
03658                /* And immediately return success. */
03659                if (tmp->priority == PRIORITY_HINT)
03660                    ast_add_hint(tmp);
03661                
03662                LOG;
03663                return 0;
03664             }
03665             ep = e;
03666             e = e->peer;
03667          }
03668          /* If we make it here, then it's time for us to go at the very end.
03669             ep *must* be defined or we couldn't have gotten here. */
03670          ep->peer = tmp;
03671          ast_mutex_unlock(&con->lock);
03672          if (tmp->priority == PRIORITY_HINT)
03673              ast_add_hint(tmp);
03674          
03675          /* And immediately return success. */
03676          LOG;
03677          return 0;
03678             
03679       } else if (res > 0) {
03680          /* Insert ourselves just before 'e'.  We're the first extension of
03681             this kind */
03682          tmp->next = e;
03683          if (el) {
03684             /* We're in the list somewhere */
03685             el->next = tmp;
03686          } else {
03687             /* We're at the top of the list */
03688             con->root = tmp;
03689          }
03690          ast_mutex_unlock(&con->lock);
03691          if (tmp->priority == PRIORITY_HINT)
03692              ast_add_hint(tmp);
03693 
03694          /* And immediately return success. */
03695          LOG;
03696          return 0;
03697       }        
03698          
03699       el = e;
03700       e = e->next;
03701    }
03702    /* If we fall all the way through to here, then we need to be on the end. */
03703    if (el)
03704       el->next = tmp;
03705    else
03706       con->root = tmp;
03707    ast_mutex_unlock(&con->lock);
03708    if (tmp->priority == PRIORITY_HINT)
03709        ast_add_hint(tmp);
03710    LOG;
03711    return 0;   
03712 }

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

Definition at line 3416 of file pbx.c.

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

Referenced by ast_async_goto_by_name().

03417 {
03418    int res = 0;
03419    if (needlock)
03420       ast_mutex_lock(&chan->lock);
03421    if (chan->pbx) {
03422       /* This channel is currently in the PBX */
03423       if (context && strlen(context))
03424          strncpy(chan->context, context, sizeof(chan->context) - 1);
03425       if (exten && strlen(exten))
03426          strncpy(chan->exten, exten, sizeof(chan->context) - 1);
03427       if (priority)
03428          chan->priority = priority - 1;
03429       ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO);
03430       if (needlock)
03431          ast_mutex_unlock(&chan->lock);
03432    } else {
03433       /* In order to do it when the channel doesn't really exist within
03434          the PBX, we have to make a new channel, masquerade, and start the PBX
03435          at the new location */
03436       struct ast_channel *tmpchan;
03437       struct ast_frame *f;
03438       tmpchan = ast_channel_alloc(0);
03439       if (tmpchan) {
03440          snprintf(tmpchan->name, sizeof(tmpchan->name), "AsyncGoto/%s", chan->name);
03441          ast_setstate(tmpchan, chan->_state);
03442          /* Make formats okay */
03443          tmpchan->readformat = chan->readformat;
03444          tmpchan->writeformat = chan->writeformat;
03445          /* Setup proper location */
03446          if (context && strlen(context))
03447             strncpy(tmpchan->context, context, sizeof(tmpchan->context) - 1);
03448          else
03449             strncpy(tmpchan->context, chan->context, sizeof(tmpchan->context) - 1);
03450          if (exten && strlen(exten))
03451             strncpy(tmpchan->exten, exten, sizeof(tmpchan->exten) - 1);
03452          else
03453             strncpy(tmpchan->exten, chan->exten, sizeof(tmpchan->exten) - 1);
03454          if (priority)
03455             tmpchan->priority = priority;
03456          else
03457             tmpchan->priority = chan->priority;
03458          if (needlock)
03459             ast_mutex_unlock(&chan->lock);
03460          
03461          /* Masquerade into temp channel */
03462          ast_channel_masquerade(tmpchan, chan);
03463          
03464          /* Make the masquerade happen by reading a frame from the tmp channel */
03465          f = ast_read(tmpchan);
03466          if (f)
03467             ast_frfree(f);
03468          /* Start the PBX going on our stolen channel */
03469          if (ast_pbx_start(tmpchan)) {
03470             ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name);
03471             ast_hangup(tmpchan);
03472             res = -1;
03473          }
03474       } else {
03475          res = -1;
03476          if (needlock)
03477             ast_mutex_unlock(&chan->lock);
03478       }
03479    }
03480    return res;
03481 }

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

Definition at line 3483 of file pbx.c.

References ast_async_goto(), ast_channel_walk(), and ast_channel::name.

03484 {
03485    struct ast_channel *chan;
03486    chan = ast_channel_walk(NULL);
03487    while(chan) {
03488       if (!strcasecmp(channame, chan->name))
03489          break;
03490       chan = ast_channel_walk(chan);
03491    }
03492    if (chan)
03493       return ast_async_goto(chan, context, exten, priority, 1);
03494    return -1;
03495 }

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

References HELPER_CANMATCH.

01623 {
01624    return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_CANMATCH);
01625 }

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

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

03312 {
03313    struct ast_context *c;
03314 
03315    if (ast_lock_contexts()) {
03316       errno = EBUSY;
03317       return -1;
03318    }
03319 
03320    c = ast_walk_contexts(NULL);
03321    while (c) {
03322       if (!strcmp(ast_get_context_name(c), con)) {
03323          int ret = ast_context_add_ignorepat2(c, value, registrar);
03324          ast_unlock_contexts();
03325          return ret;
03326       } 
03327       c = ast_walk_contexts(c);
03328    }
03329 
03330    ast_unlock_contexts();
03331    errno = ENOENT;
03332    return -1;
03333 }

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

Definition at line 3335 of file pbx.c.

References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_context::ignorepats, ast_context::lock, LOG_WARNING, and malloc.

Referenced by ast_context_add_ignorepat().

03336 {
03337    struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL;
03338    ignorepat = malloc(sizeof(struct ast_ignorepat));
03339    if (!ignorepat) {
03340       ast_log(LOG_WARNING, "Out of memory\n");
03341       errno = ENOMEM;
03342       return -1;
03343    }
03344    memset(ignorepat, 0, sizeof(struct ast_ignorepat));
03345    strncpy(ignorepat->pattern, value, sizeof(ignorepat->pattern)-1);
03346    ignorepat->next = NULL;
03347    ignorepat->registrar = registrar;
03348    ast_mutex_lock(&con->lock);
03349    ignorepatc = con->ignorepats;
03350    while(ignorepatc) {
03351       ignorepatl = ignorepatc;
03352       if (!strcasecmp(ignorepatc->pattern, value)) {
03353          /* Already there */
03354          ast_mutex_unlock(&con->lock);
03355          errno = EEXIST;
03356          return -1;
03357       }
03358       ignorepatc = ignorepatc->next;
03359    }
03360    if (ignorepatl) 
03361       ignorepatl->next = ignorepat;
03362    else
03363       con->ignorepats = ignorepat;
03364    ast_mutex_unlock(&con->lock);
03365    return 0;
03366    
03367 }

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

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

02802 {
02803    struct ast_context *c;
02804 
02805    if (ast_lock_contexts()) {
02806       errno = EBUSY;
02807       return -1;
02808    }
02809 
02810    /* walk contexts ... */
02811    c = ast_walk_contexts(NULL);
02812    while (c) {
02813       /* ... search for the right one ... */
02814       if (!strcmp(ast_get_context_name(c), context)) {
02815          int ret = ast_context_add_include2(c, include, registrar);
02816          /* ... unlock contexts list and return */
02817          ast_unlock_contexts();
02818          return ret;
02819       }
02820       c = ast_walk_contexts(c);
02821    }
02822 
02823    /* we can't find the right context */
02824    ast_unlock_contexts();
02825    errno = ENOENT;
02826    return -1;
02827 }

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

References ast_get_context_name(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_verbose(), free, ast_context::includes, ast_context::lock, LOG_WARNING, malloc, option_verbose, and VERBOSE_PREFIX_3.

Referenced by ast_context_add_include().

03094 {
03095    struct ast_include *new_include;
03096    char *c;
03097    struct ast_include *i, *il = NULL; /* include, include_last */
03098 
03099    /* allocate new include structure ... */
03100    if (!(new_include = malloc(sizeof(struct ast_include)))) {
03101       ast_log(LOG_WARNING, "Out of memory\n");
03102       errno = ENOMEM;
03103       return -1;
03104    }
03105    
03106    /* ... fill in this structure ... */
03107    memset(new_include, 0, sizeof(struct ast_include));
03108    strncpy(new_include->name, value, sizeof(new_include->name)-1);
03109    strncpy(new_include->rname, value, sizeof(new_include->rname)-1);
03110    c = new_include->rname;
03111    /* Strip off timing info */
03112    while(*c && (*c != '|')) c++; 
03113    /* Process if it's there */
03114    if (*c) {
03115       build_timing(new_include, c+1);
03116       *c = '\0';
03117    }
03118    new_include->next      = NULL;
03119    new_include->registrar = registrar;
03120 
03121    /* ... try to lock this context ... */
03122    if (ast_mutex_lock(&con->lock)) {
03123       free(new_include);
03124       errno = EBUSY;
03125       return -1;
03126    }
03127 
03128    /* ... go to last include and check if context is already included too... */
03129    i = con->includes;
03130    while (i) {
03131       if (!strcasecmp(i->name, new_include->name)) {
03132          free(new_include);
03133          ast_mutex_unlock(&con->lock);
03134          errno = EEXIST;
03135          return -1;
03136       }
03137       il = i;
03138       i = i->next;
03139    }
03140 
03141    /* ... include new context into context list, unlock, return */
03142    if (il)
03143       il->next = new_include;
03144    else
03145       con->includes = new_include;
03146    if (option_verbose > 2)
03147       ast_verbose(VERBOSE_PREFIX_3 "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con)); 
03148    ast_mutex_unlock(&con->lock);
03149 
03150    return 0;
03151 }

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

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

03159 {
03160    struct ast_context *c;
03161 
03162    if (ast_lock_contexts()) {
03163       errno = EBUSY;
03164       return -1;
03165    }
03166 
03167    /* walk contexts ... */
03168    c = ast_walk_contexts(NULL);
03169    while (c) {
03170       /* ... search for the right one ... */
03171       if (!strcmp(ast_get_context_name(c), context)) {
03172          int ret = ast_context_add_switch2(c, sw, data, registrar);
03173          /* ... unlock contexts list and return */
03174          ast_unlock_contexts();
03175          return ret;
03176       }
03177       c = ast_walk_contexts(c);
03178    }
03179 
03180    /* we can't find the right context */
03181    ast_unlock_contexts();
03182    errno = ENOENT;
03183    return -1;
03184 }

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

References ast_context::alts, ast_get_context_name(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_verbose(), free, ast_context::lock, LOG_WARNING, malloc, option_verbose, and VERBOSE_PREFIX_3.

Referenced by ast_context_add_switch().

03195 {
03196    struct ast_sw *new_sw;
03197    struct ast_sw *i, *il = NULL; /* sw, sw_last */
03198 
03199    /* allocate new sw structure ... */
03200    if (!(new_sw = malloc(sizeof(struct ast_sw)))) {
03201       ast_log(LOG_WARNING, "Out of memory\n");
03202       errno = ENOMEM;
03203       return -1;
03204    }
03205    
03206    /* ... fill in this structure ... */
03207    memset(new_sw, 0, sizeof(struct ast_sw));
03208    strncpy(new_sw->name, value, sizeof(new_sw->name)-1);
03209    if (data)
03210       strncpy(new_sw->data, data, sizeof(new_sw->data)-1);
03211    else
03212       strncpy(new_sw->data, "", sizeof(new_sw->data)-1);
03213    new_sw->next      = NULL;
03214    new_sw->registrar = registrar;
03215 
03216    /* ... try to lock this context ... */
03217    if (ast_mutex_lock(&con->lock)) {
03218       free(new_sw);
03219       errno = EBUSY;
03220       return -1;
03221    }
03222 
03223    /* ... go to last sw and check if context is already swd too... */
03224    i = con->alts;
03225    while (i) {
03226       if (!strcasecmp(i->name, new_sw->name)) {
03227          free(new_sw);
03228          ast_mutex_unlock(&con->lock);
03229          errno = EEXIST;
03230          return -1;
03231       }
03232       il = i;
03233       i = i->next;
03234    }
03235 
03236    /* ... sw new context into context list, unlock, return */
03237    if (il)
03238       il->next = new_sw;
03239    else
03240       con->alts = new_sw;
03241    if (option_verbose > 2)
03242       ast_verbose(VERBOSE_PREFIX_3 "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con)); 
03243    ast_mutex_unlock(&con->lock);
03244 
03245    return 0;
03246 }

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

References ast_log(), ast_mutex_init, ast_mutex_lock, ast_mutex_unlock, ast_verbose(), LOG_DEBUG, LOG_WARNING, malloc, option_debug, option_verbose, and VERBOSE_PREFIX_3.

02725 {
02726    struct ast_context *tmp, **local_contexts;
02727    if (!extcontexts) {
02728       local_contexts = &contexts;
02729       ast_mutex_lock(&conlock);
02730    } else
02731       local_contexts = extcontexts;
02732 
02733    tmp = *local_contexts;
02734    while(tmp) {
02735       if (!strcasecmp(tmp->name, name)) {
02736          ast_mutex_unlock(&conlock);
02737          ast_log(LOG_WARNING, "Tried to register context '%s', already in use\n", name);
02738          if (!extcontexts)
02739             ast_mutex_unlock(&conlock);
02740          return NULL;
02741       }
02742       tmp = tmp->next;
02743    }
02744    tmp = malloc(sizeof(struct ast_context));
02745    if (tmp) {
02746       memset(tmp, 0, sizeof(struct ast_context));
02747       ast_mutex_init(&tmp->lock);
02748       strncpy(tmp->name, name, sizeof(tmp->name)-1);
02749       tmp->root = NULL;
02750       tmp->registrar = registrar;
02751       tmp->next = *local_contexts;
02752       tmp->includes = NULL;
02753       tmp->ignorepats = NULL;
02754       *local_contexts = tmp;
02755       if (option_debug)
02756          ast_log(LOG_DEBUG, "Registered context '%s'\n", tmp->name);
02757       else if (option_verbose > 2)
02758          ast_verbose( VERBOSE_PREFIX_3 "Registered extension context '%s'\n", tmp->name);
02759    } else
02760       ast_log(LOG_WARNING, "Out of memory\n");
02761    
02762    if (!extcontexts)
02763       ast_mutex_unlock(&conlock);
02764    return tmp;
02765 }

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

References __ast_context_destroy().

04027 {
04028    __ast_context_destroy(con,registrar,1);
04029 }

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.

Referenced by ast_ignore_pattern().

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

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

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

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

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

02065 {
02066    struct ast_exten *exten, *prev_exten = NULL;
02067 
02068    if (ast_mutex_lock(&con->lock)) return -1;
02069 
02070    /* go through all extensions in context and search the right one ... */
02071    exten = con->root;
02072    while (exten) {
02073 
02074       /* look for right extension */
02075       if (!strcmp(exten->exten, extension) &&
02076          (!strcmp(exten->registrar, registrar) || !registrar)) {
02077          struct ast_exten *peer;
02078 
02079          /* should we free all peers in this extension? (priority == 0)? */
02080          if (priority == 0) {
02081             /* remove this extension from context list */
02082             if (prev_exten)
02083                prev_exten->next = exten->next;
02084             else
02085                con->root = exten->next;
02086 
02087             /* fire out all peers */
02088             peer = exten; 
02089             while (peer) {
02090                exten = peer->peer;
02091                
02092                if (!peer->priority==PRIORITY_HINT) 
02093                    ast_remove_hint(peer);
02094 
02095                peer->datad(peer->data);
02096                free(peer);
02097 
02098                peer = exten;
02099             }
02100 
02101             ast_mutex_unlock(&con->lock);
02102             return 0;
02103          } else {
02104             /* remove only extension with exten->priority == priority */
02105             struct ast_exten *previous_peer = NULL;
02106 
02107             peer = exten;
02108             while (peer) {
02109                /* is this our extension? */
02110                if (peer->priority == priority &&
02111                   (!strcmp(peer->registrar, registrar) || !registrar)) {
02112                   /* we are first priority extension? */
02113                   if (!previous_peer) {
02114                      /* exists previous extension here? */
02115                      if (prev_exten) {
02116                         /* yes, so we must change next pointer in
02117                          * previous connection to next peer
02118                          */
02119                         if (peer->peer) {
02120                            prev_exten->next = peer->peer;
02121                            peer->peer->next = exten->next;
02122                         } else
02123                            prev_exten->next = exten->next;
02124                      } else {
02125                         /* no previous extension, we are first
02126                          * extension, so change con->root ...
02127                          */
02128                         if (peer->peer)
02129                            con->root = peer->peer;
02130                         else
02131                            con->root = exten->next; 
02132                      }
02133                   } else {
02134                      /* we are not first priority in extension */
02135                      previous_peer->peer = peer->peer;
02136                   }
02137 
02138                   /* now, free whole priority extension */
02139                   if (peer->priority==PRIORITY_HINT)
02140                       ast_remove_hint(peer);
02141                   peer->datad(peer->data);
02142                   free(peer);
02143 
02144                   ast_mutex_unlock(&con->lock);
02145                   return 0;
02146                } else {
02147                   /* this is not right extension, skip to next peer */
02148                   previous_peer = peer;
02149                   peer = peer->peer;
02150                }
02151             }
02152 
02153             ast_mutex_unlock(&con->lock);
02154             return -1;
02155          }
02156       }
02157 
02158       prev_exten = exten;
02159       exten = exten->next;
02160    }
02161 
02162    /* we can't find right extension */
02163    ast_mutex_unlock(&con->lock);
02164    return -1;
02165 }

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

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

03253 {
03254    struct ast_context *c;
03255 
03256    if (ast_lock_contexts()) {
03257       errno = EBUSY;
03258       return -1;
03259    }
03260 
03261    c = ast_walk_contexts(NULL);
03262    while (c) {
03263       if (!strcmp(ast_get_context_name(c), context)) {
03264          int ret = ast_context_remove_ignorepat2(c, ignorepat, registrar);
03265          ast_unlock_contexts();
03266          return ret;
03267       }
03268       c = ast_walk_contexts(c);
03269    }
03270 
03271    ast_unlock_contexts();
03272    errno = ENOENT;
03273    return -1;
03274 }

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

Definition at line 3276 of file pbx.c.

References ast_mutex_lock, ast_mutex_unlock, free, ast_context::ignorepats, ast_context::lock, and ast_ignorepat::next.

Referenced by ast_context_remove_ignorepat().

03277 {
03278    struct ast_ignorepat *ip, *ipl = NULL;
03279 
03280    if (ast_mutex_lock(&con->lock)) {
03281       errno = EBUSY;
03282       return -1;
03283    }
03284 
03285    ip = con->ignorepats;
03286    while (ip) {
03287       if (!strcmp(ip->pattern, ignorepat) &&
03288          (registrar == ip->registrar || !registrar)) {
03289          if (ipl) {
03290             ipl->next = ip->next;
03291             free(ip);
03292          } else {
03293             con->ignorepats = ip->next;
03294             free(ip);
03295          }
03296          ast_mutex_unlock(&con->lock);
03297          return 0;
03298       }
03299       ipl = ip; ip = ip->next;
03300    }
03301 
03302    ast_mutex_unlock(&con->lock);
03303    errno = EINVAL;
03304    return -1;
03305 }

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

Removes an include.

See add_include

Definition at line 1884 of file pbx.c.

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

01885 {
01886    struct ast_context *c;
01887 
01888    if (ast_lock_contexts()) return -1;
01889 
01890    /* walk contexts and search for the right one ...*/
01891    c = ast_walk_contexts(NULL);
01892    while (c) {
01893       /* we found one ... */
01894       if (!strcmp(ast_get_context_name(c), context)) {
01895          int ret;
01896          /* remove include from this context ... */   
01897          ret = ast_context_remove_include2(c, include, registrar);
01898 
01899          ast_unlock_contexts();
01900 
01901          /* ... return results */
01902          return ret;
01903       }
01904       c = ast_walk_contexts(c);
01905    }
01906 
01907    /* we can't find the right one context */
01908    ast_unlock_contexts();
01909    return -1;
01910 }

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

01921 {
01922    struct ast_include *i, *pi = NULL;
01923 
01924    if (ast_mutex_lock(&con->lock)) return -1;
01925 
01926    /* walk includes */
01927    i = con->includes;
01928    while (i) {
01929       /* find our include */
01930       if (!strcmp(i->name, include) && 
01931          (!strcmp(i->registrar, registrar) || !registrar)) {
01932          /* remove from list */
01933          if (pi)
01934             pi->next = i->next;
01935          else
01936             con->includes = i->next;
01937          /* free include and return */
01938          free(i);
01939          ast_mutex_unlock(&con->lock);
01940          return 0;
01941       }
01942       pi = i;
01943       i = i->next;
01944    }
01945 
01946    /* we can't find the right include */
01947    ast_mutex_unlock(&con->lock);
01948    return -1;
01949 }

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

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

01957 {
01958    struct ast_context *c;
01959 
01960    if (ast_lock_contexts()) return -1;
01961 
01962    /* walk contexts and search for the right one ...*/
01963    c = ast_walk_contexts(NULL);
01964    while (c) {
01965       /* we found one ... */
01966       if (!strcmp(ast_get_context_name(c), context)) {
01967          int ret;
01968          /* remove switch from this context ... */ 
01969          ret = ast_context_remove_switch2(c, sw, data, registrar);
01970 
01971          ast_unlock_contexts();
01972 
01973          /* ... return results */
01974          return ret;
01975       }
01976       c = ast_walk_contexts(c);
01977    }
01978 
01979    /* we can't find the right one context */
01980    ast_unlock_contexts();
01981    return -1;
01982 }

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

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

01993 {
01994    struct ast_sw *i, *pi = NULL;
01995 
01996    if (ast_mutex_lock(&con->lock)) return -1;
01997 
01998    /* walk switchs */
01999    i = con->alts;
02000    while (i) {
02001       /* find our switch */
02002       if (!strcmp(i->name, sw) && !strcmp(i->data, data) && 
02003          (!strcmp(i->registrar, registrar) || !registrar)) {
02004          /* remove from list */
02005          if (pi)
02006             pi->next = i->next;
02007          else
02008             con->alts = i->next;
02009          /* free switch and return */
02010          free(i);
02011          ast_mutex_unlock(&con->lock);
02012          return 0;
02013       }
02014       pi = i;
02015       i = i->next;
02016    }
02017 
02018    /* we can't find the right switch */
02019    ast_mutex_unlock(&con->lock);
02020    return -1;
02021 }

int ast_device_state_changed const char *  fmt,
... 
 

Tells Asterisk the State for Device is changed.

Parameters:
fmt devicename like a dialstring with format parameters Asterisk polls the new extensionstates and calls the registered callbacks for the changed extensions Returns 0 on success, -1 on failure

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

01299 {
01300     struct ast_hint *list;
01301     struct ast_state_cb *cblist;
01302     char hint[AST_MAX_EXTENSION];
01303     char device[AST_MAX_EXTENSION];
01304     char *cur, *rest;
01305     int state;
01306     
01307     va_list ap;
01308 
01309     va_start(ap, fmt);
01310     vsnprintf(device, sizeof(device)-1, fmt, ap);
01311     va_end(ap);
01312 
01313     rest = strchr(device, '-');
01314     if (rest) {
01315    *rest = 0;
01316     }
01317         
01318     ast_mutex_lock(&hintlock);
01319 
01320     list = hints;
01321     
01322     while (list) {
01323    
01324    strcpy(hint, ast_get_extension_app(list->exten));
01325    cur = hint;
01326    do {
01327        rest = strchr(cur, '&');
01328        if (rest) {
01329       *rest = 0;
01330       rest++;
01331        }
01332        
01333        if (!strcmp(cur, device)) {
01334        // Found extension execute callbacks 
01335       state = ast_extension_state2(list->exten);
01336       if ((state != -1) && (state != list->laststate)) {
01337           // For general callbacks
01338           cblist = statecbs;
01339           while (cblist) {
01340          cblist->callback(list->exten->parent->name, list->exten->exten, state, cblist->data);
01341          cblist = cblist->next;
01342           }
01343           
01344           // For extension callbacks
01345              cblist = list->callbacks;
01346           while (cblist) {
01347          cblist->callback(list->exten->parent->name, list->exten->exten, state, cblist->data);
01348          cblist = cblist->next;
01349           }
01350           
01351           list->laststate = state;
01352       }
01353       break;
01354        }
01355        cur = rest;
01356    } while (cur);
01357    
01358    list = list->next;
01359     }
01360 
01361     ast_mutex_unlock(&hintlock);
01362     return 1;
01363 }

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

References HELPER_EXISTS.

Referenced by ast_pbx_run().

01618 {
01619    return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_EXISTS);
01620 }

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.

Referenced by ast_ignore_pattern().

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

01288 {
01289     struct ast_exten *e;
01290 
01291     e = ast_hint_extension(c, context, exten);    
01292     if (!e) 
01293    return -1;
01294 
01295     return ast_extension_state2(e);    
01296 }

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

01367 {
01368     struct ast_hint *list;
01369     struct ast_state_cb *cblist;
01370     struct ast_exten *e;
01371 
01372     /* No context and extension add callback to statecbs list */
01373     if (!context && !exten) {
01374    ast_mutex_lock(&hintlock);
01375 
01376    cblist = statecbs;
01377    while (cblist) {
01378        if (cblist->callback == callback) {
01379       cblist->data = data;
01380       ast_mutex_unlock(&hintlock);
01381        }
01382        
01383        cblist = cblist->next;
01384    }
01385    
01386    /* Now inserts the callback */
01387    cblist = malloc(sizeof(struct ast_state_cb));
01388    if (!cblist) {
01389        ast_mutex_unlock(&hintlock);
01390        return -1;
01391    }
01392    memset(cblist, 0, sizeof(struct ast_state_cb));
01393    cblist->id = 0;
01394    cblist->callback = callback;
01395    cblist->data = data;
01396 
01397         cblist->next = statecbs;
01398    statecbs = cblist;
01399 
01400    ast_mutex_unlock(&hintlock);
01401    return 0;
01402     }
01403 
01404     if (!context || !exten)
01405    return -1;
01406 
01407     /* This callback type is for only one hint */
01408     e = ast_hint_extension(NULL, context, exten);    
01409     if (!e) {
01410         return -1;
01411     }
01412     
01413     ast_mutex_lock(&hintlock);
01414     list = hints;        
01415     
01416     while (list) {
01417    if (list->exten == e)
01418        break;      
01419    list = list->next;    
01420     }
01421 
01422     if (!list) {
01423    ast_mutex_unlock(&hintlock);
01424    return -1;
01425     }
01426 
01427     /* Now inserts the callback */
01428     cblist = malloc(sizeof(struct ast_state_cb));
01429     if (!cblist) {
01430    ast_mutex_unlock(&hintlock);
01431    return -1;
01432     }
01433     memset(cblist, 0, sizeof(struct ast_state_cb));
01434     cblist->id = stateid++;
01435     cblist->callback = callback;
01436     cblist->data = data;
01437 
01438     cblist->next = list->callbacks;
01439     list->callbacks = cblist;
01440 
01441     ast_mutex_unlock(&hintlock);
01442     return cblist->id;
01443 }

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

01446 {
01447     struct ast_hint *list;
01448     struct ast_state_cb *cblist, *cbprev;
01449     
01450     if (!id && !callback)
01451    return -1;
01452             
01453     ast_mutex_lock(&hintlock);
01454 
01455     /* id is zero is a callback without extension */
01456     if (!id) {
01457    cbprev = NULL;
01458    cblist = statecbs;
01459    while (cblist) {
01460        if (cblist->callback == callback) {
01461       if (!cbprev)
01462           statecbs = cblist->next;
01463       else
01464           cbprev->next = cblist->next;
01465 
01466       free(cblist);
01467 
01468            ast_mutex_unlock(&hintlock);
01469       return 0;
01470        }
01471        cbprev = cblist;
01472        cblist = cblist->next;
01473    }
01474 
01475         ast_mutex_lock(&hintlock);
01476    return -1;
01477     }
01478 
01479     /* id greater zero is a callback with extension */
01480     list = hints;
01481     while (list) {
01482    cblist = list->callbacks;
01483    cbprev = NULL;
01484    while (cblist) {
01485        if (cblist->id==id) {
01486       if (!cbprev)
01487           list->callbacks = cblist->next;    
01488       else
01489           cbprev->next = cblist->next;
01490       
01491       free(cblist);
01492       
01493       ast_mutex_unlock(&hintlock);
01494       return 0;      
01495        }    
01496           cbprev = cblist;          
01497        cblist = cblist->next;
01498    }
01499    list = list->next;
01500     }
01501     
01502     ast_mutex_unlock(&hintlock);
01503     return -1;
01504 }

char* ast_get_context_name struct ast_context con  ) 
 

Definition at line 4497 of file pbx.c.

References ast_context::name.

Referenced by ast_add_extension(), ast_context_add_ignorepat(), ast_context_add_include(), ast_context_add_include2(), ast_context_add_switch(), ast_context_add_switch2(), ast_context_remove_extension(), ast_context_remove_ignorepat(), ast_context_remove_include(), and ast_context_remove_switch().

04498 {
04499    return con ? con->name : NULL;
04500 }

char* ast_get_context_registrar struct ast_context c  ) 
 

Definition at line 4525 of file pbx.c.

References ast_context::registrar.

04526 {
04527    return c ? c->registrar : NULL;
04528 }

char* ast_get_extension_app struct ast_exten e  ) 
 

Definition at line 4545 of file pbx.c.

References ast_exten::app.

Referenced by ast_device_state_changed(), and ast_get_hint().

04546 {
04547    return e ? e->app : NULL;
04548 }

void* ast_get_extension_app_data struct ast_exten e  ) 
 

Definition at line 4550 of file pbx.c.

References ast_exten::data.

04551 {
04552    return e ? e->data : NULL;
04553 }

char* ast_get_extension_name struct ast_exten exten  ) 
 

Definition at line 4502 of file pbx.c.

References ast_exten::exten.

04503 {
04504    return exten ? exten->exten : NULL;
04505 }

int ast_get_extension_priority struct ast_exten exten  ) 
 

Definition at line 4517 of file pbx.c.

References ast_exten::priority.

04518 {
04519    return exten ? exten->priority : -1;
04520 }

char* ast_get_extension_registrar struct ast_exten e  ) 
 

Definition at line 4530 of file pbx.c.

References ast_exten::registrar.

04531 {
04532    return e ? e->registrar : NULL;
04533 }

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

References ast_get_extension_app().

01607 {
01608    struct ast_exten *e;
01609    e = ast_hint_extension(c, context, exten);
01610    if (e) { 
01611        strncpy(hint, ast_get_extension_app(e), maxlen);
01612        return -1;
01613    }
01614    return 0;   
01615 }

char* ast_get_ignorepat_name struct ast_ignorepat ip  ) 
 

Definition at line 4512 of file pbx.c.

References ast_ignorepat::pattern.

04513 {
04514    return ip ? ip->pattern : NULL;
04515 }

char* ast_get_ignorepat_registrar struct ast_ignorepat ip  ) 
 

Definition at line 4540 of file pbx.c.

References ast_ignorepat::registrar.

04541 {
04542    return ip ? ip->registrar : NULL;
04543 }

char* ast_get_include_name struct ast_include inc  ) 
 

Definition at line 4507 of file pbx.c.

References ast_include::name.

04508 {
04509    return inc ? inc->name : NULL;
04510 }

char* ast_get_include_registrar struct ast_include i  ) 
 

Definition at line 4535 of file pbx.c.

References ast_include::registrar.

04536 {
04537    return i ? i->registrar : NULL;
04538 }

char* ast_get_switch_data struct ast_sw sw  ) 
 

Definition at line 4560 of file pbx.c.

References ast_sw::data.

04561 {
04562    return sw ? sw->data : NULL;
04563 }

char* ast_get_switch_name struct ast_sw sw  ) 
 

Definition at line 4555 of file pbx.c.

References ast_sw::name.

04556 {
04557    return sw ? sw->name : NULL;
04558 }

char* ast_get_switch_registrar struct ast_sw sw  ) 
 

Definition at line 4565 of file pbx.c.

References ast_sw::registrar.

04566 {
04567    return sw ? sw->registrar : NULL;
04568 }

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

References ast_context_find(), and ast_extension_match().

03370 {
03371    struct ast_context *con;
03372    struct ast_ignorepat *pat;
03373    con = ast_context_find(context);
03374    if (con) {
03375       pat = con->ignorepats;
03376       while (pat) {
03377          if (ast_extension_match(pat->pattern, pattern))
03378             return 1;
03379          pat = pat->next;
03380       }
03381    } 
03382    return 0;
03383 }

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

References ast_mutex_lock, and ast_context::lock.

04485 {
04486    return ast_mutex_lock(&con->lock);
04487 }

int ast_lock_contexts void   ) 
 

Locks the contexts.

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

Definition at line 4471 of file pbx.c.

References ast_mutex_lock.

Referenced by ast_add_extension(), ast_context_add_ignorepat(), ast_context_add_include(), ast_context_add_switch(), ast_context_remove_extension(), ast_context_remove_ignorepat(), ast_context_remove_include(), and ast_context_remove_switch().

04472 {
04473    return ast_mutex_lock(&conlock);
04474 }

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

References HELPER_MATCHMORE.

Referenced by ast_pbx_run().

01628 {
01629    return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_MATCHMORE);
01630 }

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

References __ast_context_destroy(), ast_log(), ast_mutex_lock, ast_mutex_unlock, and LOG_WARNING.

02769                                                                                       {
02770    struct ast_context *tmp, *lasttmp = NULL;
02771    tmp = *extcontexts;
02772    ast_mutex_lock(&conlock);
02773    if (registrar) {
02774       __ast_context_destroy(NULL,registrar,0);
02775       while (tmp) {
02776          lasttmp = tmp;
02777          tmp = tmp->next;
02778       }
02779    } else {
02780       while (tmp) {
02781          __ast_context_destroy(tmp,tmp->registrar,0);
02782          lasttmp = tmp;
02783          tmp = tmp->next;
02784       }
02785    }
02786    if (lasttmp) {
02787       lasttmp->next = contexts;
02788       contexts = *extcontexts;
02789       *extcontexts = NULL;
02790    } else 
02791       ast_log(LOG_WARNING, "Requested contexts didn't get merged\n");
02792    ast_mutex_unlock(&conlock);
02793    return;  
02794 }

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
 

Definition at line 3877 of file pbx.c.

References ast_channel::_state, ast_hangup(), ast_log(), ast_request_and_dial(), AST_STATE_UP, ast_verbose(), free, LOG_WARNING, malloc, ast_channel::name, option_verbose, type, and VERBOSE_PREFIX_4.

03878 {
03879    struct ast_channel *chan;
03880    struct async_stat *as;
03881    struct app_tmp *tmp;
03882    char *var, *vartmp;
03883    int res = -1;
03884    if (!app || !strlen(app))
03885       return -1;
03886    if (sync) {
03887       chan = ast_request_and_dial(type, format, data, timeout, reason, callerid);
03888       if (chan) {
03889          vartmp = variable;
03890          while( (var = strtok_r(NULL, "|", &vartmp)) ) {
03891             pbx_builtin_setvar( chan, var );
03892          }
03893          if (chan->_state == AST_STATE_UP) {
03894             res = 0;
03895             if (option_verbose > 3)
03896                ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", chan->name);
03897             tmp = malloc(sizeof(struct app_tmp));
03898             if (tmp) {
03899                memset(tmp, 0, sizeof(struct app_tmp));
03900                strncpy(tmp->app, app, sizeof(tmp->app) - 1);
03901                strncpy(tmp->data, appdata, sizeof(tmp->data) - 1);
03902                tmp->chan = chan;
03903                if (sync > 1) {
03904                   ast_pbx_run_app(tmp);
03905                } else {
03906                   if (pthread_create(&tmp->t, NULL, ast_pbx_run_app, tmp)) {
03907                      ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno));
03908                      free(tmp);
03909                      ast_hangup(chan);
03910                      res = -1;
03911                   }
03912                }
03913             } else {
03914                ast_log(LOG_WARNING, "Out of memory :(\n");
03915                res = -1;
03916             }
03917          } else {
03918             if (option_verbose > 3)
03919                ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", chan->name);
03920             ast_hangup(chan);
03921          }
03922       }
03923    } else {
03924       as = malloc(sizeof(struct async_stat));
03925       if (!as)
03926          return -1;
03927       memset(as, 0, sizeof(struct async_stat));
03928       chan = ast_request_and_dial(type, format, data, 0, reason, callerid);
03929       if (!chan) {
03930          free(as);
03931          return -1;
03932       }
03933       as->chan = chan;
03934       strncpy(as->app, app, sizeof(as->app) - 1);
03935       if (appdata)
03936          strncpy(as->appdata,  appdata, sizeof(as->appdata) - 1);
03937       as->timeout = timeout;
03938       if (pthread_create(&as->p, NULL, async_wait, as)) {
03939          ast_log(LOG_WARNING, "Failed to start async wait\n");
03940          free(as);
03941          ast_hangup(chan);
03942          return -1;
03943       }
03944       res = 0;
03945    }
03946    return res;
03947 }

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
 

Definition at line 3782 of file pbx.c.

References ast_channel::_state, ast_hangup(), ast_log(), ast_pbx_run(), ast_pbx_start(), ast_request_and_dial(), AST_STATE_UP, ast_verbose(), ast_channel::callerid, ast_channel::context, ast_channel::exten, free, LOG_WARNING, malloc, ast_channel::name, option_verbose, ast_channel::priority, type, and VERBOSE_PREFIX_4.

03783 {
03784    struct ast_channel *chan;
03785    struct async_stat *as;
03786    int res = -1;
03787    char *var, *tmp;
03788    if (sync) {
03789       chan = ast_request_and_dial(type, format, data, timeout, reason, callerid);
03790       if (chan) {
03791          /* JDG chanvar */
03792          tmp = variable;
03793          /* FIXME replace this call with strsep  NOT*/
03794          while( (var = strtok_r(NULL, "|", &tmp)) ) {
03795             pbx_builtin_setvar( chan, var );
03796          } /* /JDG */
03797          if (chan->_state == AST_STATE_UP) {
03798             res = 0;
03799             if (option_verbose > 3)
03800                ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", chan->name);
03801             if (context && strlen(context))
03802                strncpy(chan->context, context, sizeof(chan->context) - 1);
03803             if (exten && strlen(exten))
03804                strncpy(chan->exten, exten, sizeof(chan->exten) - 1);
03805             if (callerid && strlen(callerid))
03806                strncpy(chan->callerid, callerid, sizeof(chan->callerid) - 1);
03807             if (priority > 0)
03808                chan->priority = priority;
03809             if (sync > 1) {
03810                if (ast_pbx_run(chan)) {
03811                   ast_log(LOG_WARNING, "Unable to run PBX on %s\n", chan->name);
03812                   ast_hangup(chan);
03813                   res = -1;
03814                }
03815             } else {
03816                if (ast_pbx_start(chan)) {
03817                   ast_log(LOG_WARNING, "Unable to start PBX on %s\n", chan->name);
03818                   ast_hangup(chan);
03819                   res = -1;
03820                } 
03821             }
03822          } else {
03823             if (option_verbose > 3)
03824                ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", chan->name);
03825             ast_hangup(chan);
03826          }
03827       }
03828    } else {
03829       as = malloc(sizeof(struct async_stat));
03830       if (!as)
03831          return -1;
03832       memset(as, 0, sizeof(struct async_stat));
03833       chan = ast_request_and_dial(type, format, data, 0, reason, callerid);
03834       if (!chan) {
03835          free(as);
03836          return -1;
03837       }
03838       as->chan = chan;
03839       strncpy(as->context, context, sizeof(as->context) - 1);
03840       strncpy(as->exten,  exten, sizeof(as->exten) - 1);
03841       as->priority = priority;
03842       as->timeout = timeout;
03843       if (pthread_create(&as->p, NULL, async_wait, as)) {
03844          ast_log(LOG_WARNING, "Failed to start async wait\n");
03845          free(as);
03846          ast_hangup(chan);
03847          return -1;
03848       }
03849       res = 0;
03850    }
03851    return res;
03852 }

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 1637 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_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.

Referenced by ast_pbx_outgoing_exten().

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

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

References ast_log(), and LOG_WARNING.

Referenced by ast_async_goto(), and ast_pbx_outgoing_exten().

01861 {
01862    pthread_t t;
01863    pthread_attr_t attr;
01864    if (!c) {
01865       ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
01866       return -1;
01867    }
01868       
01869    /* Start a new thread, and get something handling this channel. */
01870    pthread_attr_init(&attr);
01871    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
01872    if (pthread_create(&t, &attr, pbx_thread, c)) {
01873       ast_log(LOG_WARNING, "Failed to create new channel thread\n");
01874       return -1;
01875    }
01876    return 0;
01877 }

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

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

Referenced by load_pbx().

02169 {
02170    struct ast_app *tmp, *prev, *cur;
02171    char tmps[80];
02172    if (ast_mutex_lock(&applock)) {
02173       ast_log(LOG_ERROR, "Unable to lock application list\n");
02174       return -1;
02175    }
02176    tmp = apps;
02177    while(tmp) {
02178       if (!strcasecmp(app, tmp->name)) {
02179          ast_log(LOG_WARNING, "Already have an application '%s'\n", app);
02180          ast_mutex_unlock(&applock);
02181          return -1;
02182       }
02183       tmp = tmp->next;
02184    }
02185    tmp = malloc(sizeof(struct ast_app));
02186    if (tmp) {
02187       memset(tmp, 0, sizeof(struct ast_app));
02188       strncpy(tmp->name, app, sizeof(tmp->name)-1);
02189       tmp->execute = execute;
02190       tmp->synopsis = synopsis;
02191       tmp->description = description;
02192       /* Store in alphabetical order */
02193       cur = apps;
02194       prev = NULL;
02195       while(cur) {
02196          if (strcasecmp(tmp->name, cur->name) < 0)
02197             break;
02198          prev = cur;
02199          cur = cur->next;
02200       }
02201       if (prev) {
02202          tmp->next = prev->next;
02203          prev->next = tmp;
02204       } else {
02205          tmp->next = apps;
02206          apps = tmp;
02207       }
02208    } else {
02209       ast_log(LOG_WARNING, "Out of memory\n");
02210       ast_mutex_unlock(&applock);
02211       return -1;
02212    }
02213    if (option_verbose > 1)
02214       ast_verbose( VERBOSE_PREFIX_2 "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps)));
02215    ast_mutex_unlock(&applock);
02216    return 0;
02217 }

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

02220 {
02221    struct ast_switch *tmp, *prev=NULL;
02222    if (ast_mutex_lock(&switchlock)) {
02223       ast_log(LOG_ERROR, "Unable to lock switch lock\n");
02224       return -1;
02225    }
02226    tmp = switches;
02227    while(tmp) {
02228       if (!strcasecmp(tmp->name, sw->name))
02229          break;
02230       prev = tmp;
02231       tmp = tmp->next;
02232    }
02233    if (tmp) {  
02234       ast_mutex_unlock(&switchlock);
02235       ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name);
02236       return -1;
02237    }
02238    sw->next = NULL;
02239    if (prev) 
02240       prev->next = sw;
02241    else
02242       switches = sw;
02243    ast_mutex_unlock(&switchlock);
02244    return 0;
02245 }

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

References HELPER_SPAWN.

Referenced by ast_pbx_run().

01633 {
01634    return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_SPAWN);
01635 }

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

References ast_mutex_unlock, and ast_context::lock.

04490 {
04491    return ast_mutex_unlock(&con->lock);
04492 }

int ast_unlock_contexts void   ) 
 

Unlocks contexts.

Returns 0 on success, -1 on failure

Definition at line 4476 of file pbx.c.

References ast_mutex_unlock.

Referenced by ast_add_extension(), ast_context_add_ignorepat(), ast_context_add_include(), ast_context_add_switch(), ast_context_remove_extension(), ast_context_remove_ignorepat(), ast_context_remove_include(), and ast_context_remove_switch().

04477 {
04478    return ast_mutex_unlock(&conlock);
04479 }

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

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

02699                                           {
02700    struct ast_app *tmp, *tmpl = NULL;
02701    if (ast_mutex_lock(&applock)) {
02702       ast_log(LOG_ERROR, "Unable to lock application list\n");
02703       return -1;
02704    }
02705    tmp = apps;
02706    while(tmp) {
02707       if (!strcasecmp(app, tmp->name)) {
02708          if (tmpl)
02709             tmpl->next = tmp->next;
02710          else
02711             apps = tmp->next;
02712          if (option_verbose > 1)
02713             ast_verbose( VERBOSE_PREFIX_2 "Unregistered application '%s'\n", tmp->name);
02714          ast_mutex_unlock(&applock);
02715          return 0;
02716       }
02717       tmpl = tmp;
02718       tmp = tmp->next;
02719    }
02720    ast_mutex_unlock(&applock);
02721    return -1;
02722 }

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

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

02248 {
02249    struct ast_switch *tmp, *prev=NULL;
02250    if (ast_mutex_lock(&switchlock)) {
02251       ast_log(LOG_ERROR, "Unable to lock switch lock\n");
02252       return;
02253    }
02254    tmp = switches;
02255    while(tmp) {
02256       if (tmp == sw) {
02257          if (prev)
02258             prev->next = tmp->next;
02259          else
02260             switches = tmp->next;
02261          tmp->next = NULL;
02262          break;         
02263       }
02264       prev = tmp;
02265       tmp = tmp->next;
02266    }
02267    ast_mutex_unlock(&switchlock);
02268 }

struct ast_exten* ast_walk_context_extensions struct ast_context con,
struct ast_exten exten
 

Definition at line 4581 of file pbx.c.

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

04583 {
04584    if (!exten)
04585       return con ? con->root : NULL;
04586    else
04587       return exten->next;
04588 }

struct ast_ignorepat* ast_walk_context_ignorepats struct ast_context con,
struct ast_ignorepat ip
 

Definition at line 4617 of file pbx.c.

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

04619 {
04620    if (!ip)
04621       return con ? con->ignorepats : NULL;
04622    else
04623       return ip->next;
04624 }

struct ast_include* ast_walk_context_includes struct ast_context con,
struct ast_include inc
 

Definition at line 4608 of file pbx.c.

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

04610 {
04611    if (!inc)
04612       return con ? con->includes : NULL;
04613    else
04614       return inc->next;
04615 }

struct ast_sw* ast_walk_context_switches struct ast_context con,
struct ast_sw sw
 

Definition at line 4590 of file pbx.c.

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

04592 {
04593    if (!sw)
04594       return con ? con->alts : NULL;
04595    else
04596       return sw->next;
04597 }

struct ast_context* ast_walk_contexts struct ast_context con  ) 
 

Definition at line 4573 of file pbx.c.

References ast_context::next.

Referenced by ast_add_extension(), ast_context_add_ignorepat(), ast_context_add_include(), ast_context_add_switch(), ast_context_remove_extension(), ast_context_remove_ignorepat(), ast_context_remove_include(), and ast_context_remove_switch().

04574 {
04575    if (!con)
04576       return contexts;
04577    else
04578       return con->next;
04579 }

struct ast_exten* ast_walk_extension_priorities struct ast_exten exten,
struct ast_exten priority
 

Definition at line 4599 of file pbx.c.

References ast_exten::peer.

04601 {
04602    if (!priority)
04603       return exten;
04604    else
04605       return priority->peer;
04606 }

int load_pbx void   ) 
 

Definition at line 4445 of file pbx.c.

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

Referenced by main().

04446 {
04447    int x;
04448    /* Initialize the PBX */
04449    if (option_verbose) {
04450       ast_verbose( "Asterisk PBX Core Initializing\n");
04451       ast_verbose( "Registering builtin applications:\n");
04452    }
04453    ast_cli_register(&show_applications_cli);
04454    ast_cli_register(&show_application_cli);
04455    ast_cli_register(&show_dialplan_cli);
04456    ast_cli_register(&show_switches_cli);
04457    for (x=0;x<sizeof(builtins) / sizeof(struct pbx_builtin); x++) {
04458       if (option_verbose)
04459          ast_verbose( VERBOSE_PREFIX_1 "[%s]\n", builtins[x].name);
04460       if (ast_register_application(builtins[x].name, builtins[x].execute, builtins[x].synopsis, builtins[x].description)) {
04461          ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name);
04462          return -1;
04463       }
04464    }
04465    return 0;
04466 }

void pbx_builtin_clear_globals void   ) 
 

Definition at line 4369 of file pbx.c.

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

04370 {
04371    struct ast_var_t *vardata;
04372    while (!AST_LIST_EMPTY(&globals)) {
04373       vardata = AST_LIST_FIRST(&globals);
04374       AST_LIST_REMOVE_HEAD(&globals, entries);
04375       ast_var_delete(vardata);
04376    }
04377 }

char * pbx_builtin_getvar_helper struct ast_channel chan,
char *  name
 

Definition at line 4271 of file pbx.c.

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

04271                                                                       {
04272    struct ast_var_t *variables;
04273    struct varshead *headp;
04274 
04275     if (chan)
04276         headp=&chan->varshead;
04277    else
04278       headp=&globals;
04279 
04280    if (name) {
04281       AST_LIST_TRAVERSE(headp,variables,entries) {
04282          if (!strcmp(name, ast_var_name(variables)))
04283             return ast_var_value(variables);
04284       }
04285       if (headp != &globals) {
04286          /* Check global variables if we haven't already */
04287          headp = &globals;
04288          AST_LIST_TRAVERSE(headp,variables,entries) {
04289             if (!strcmp(name, ast_var_name(variables)))
04290                return ast_var_value(variables);
04291          }
04292       }
04293    }
04294    return NULL;
04295 }

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

Definition at line 4297 of file pbx.c.

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

04297                                                                                   {
04298    struct ast_var_t *newvariable;
04299         struct varshead *headp;
04300     if (chan)
04301         headp=&chan->varshead;
04302    else
04303       headp=&globals;
04304                 
04305    AST_LIST_TRAVERSE (headp,newvariable,entries) {
04306       if (strcasecmp(ast_var_name(newvariable),name)==0) {
04307          /* there is already such a variable, delete it */
04308          AST_LIST_REMOVE(headp,newvariable,ast_var_t,entries);
04309          ast_var_delete(newvariable);
04310          break;
04311       }
04312    } 
04313    
04314    if (value) {
04315       if ((option_verbose > 1) && (headp == &globals))
04316          ast_verbose(VERBOSE_PREFIX_3 "Setting global variable '%s' to '%s'\n",name, value);
04317       newvariable=ast_var_assign(name,value);   
04318       AST_LIST_INSERT_HEAD(headp,newvariable,entries);
04319    }
04320 }

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

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

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


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 Fri Oct 31 07:05:15 2003 for Asterisk by doxygen 1.3.4