Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals  

pbx.h File Reference

#include <asterisk/sched.h>
#include <asterisk/channel.h>

Go to the source code of this file.

Data Structures

struct  ast_pbx
struct  ast_switch
 Data structure associated with an asterisk switch. More...


Defines

#define AST_PBX_KEEP   0
#define AST_PBX_REPLACE   1
#define AST_MAX_APP   32
 Max length of an application. More...

#define AST_PBX_KEEPALIVE   10
 Special return values from applications to the PBX. More...

#define AST_PBX_NO_HANGUP_PEER   11
#define PRIORITY_HINT   -1
 Special Priority for an hint. More...

#define AST_EXTENSION_NOT_INUSE   0
 Extension states No device INUSE or BUSY. More...

#define AST_EXTENSION_INUSE   1
 One or more devices INUSE. More...

#define AST_EXTENSION_BUSY   2
 All devices BUSY. More...

#define AST_EXTENSION_UNAVAILABLE   3
 All devices UNAVAILABLE/UNREGISTERED. More...


Typedefs

typedef int(* ast_state_cb_type )(char *context, char *id, int state, void *data)

Functions

int ast_register_switch (struct ast_switch *sw)
 Register an alternative switch. More...

void ast_unregister_switch (struct ast_switch *sw)
 Unregister an alternative switch. More...

ast_apppbx_findapp (char *app)
 Look up an application. More...

int pbx_exec (struct ast_channel *c, struct ast_app *app, void *data, int newstack)
 executes an application. More...

ast_contextast_context_create (struct ast_context **extcontexts, char *name, char *registrar)
 Register a new context. More...

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

void ast_context_destroy (struct ast_context *con, char *registrar)
 Destroy a context (matches the specified context (or ANY context if NULL). More...

ast_contextast_context_find (char *name)
 Find a context. More...

int ast_pbx_start (struct ast_channel *c)
 Create a new thread and start the PBX (or whatever). More...

int ast_pbx_run (struct ast_channel *c)
 Execute the PBX in the current thread. More...

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

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

int ast_unregister_application (char *app)
 Remove an application. More...

int ast_extension_state (struct ast_channel *c, char *context, char *exten)
 Uses hint and devicestate callback to get the state of an extension. More...

int ast_device_state_changed (const char *fmt,...) __attribute__((format(printf
 Tells Asterisk the State for Device is changed. More...

int ast_extension_state_add (char *context, char *exten, ast_state_cb_type callback, void *data)
 Registers a state change callback. More...

int ast_extension_state_del (int id, ast_state_cb_type callback)
 Deletes a registered state change callback by ID. More...

int ast_get_hint (char *hint, int maxlen, struct ast_channel *c, char *context, char *exten)
 If an extension exists, return non-zero. More...

int ast_exists_extension (struct ast_channel *c, char *context, char *exten, int priority, char *callerid)
 If an extension exists, return non-zero. More...

int ast_canmatch_extension (struct ast_channel *c, char *context, char *exten, int priority, char *callerid)
 Looks for a valid matching extension. More...

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

int ast_extension_match (char *pattern, char *extension)
 Determine if a given extension matches a given pattern (in NXX format). More...

int ast_spawn_extension (struct ast_channel *c, char *context, char *exten, int priority, char *callerid)
 Launch a new extension (i.e. new stack). More...

int ast_exec_extension (struct ast_channel *c, char *context, char *exten, int priority, char *callerid)
 Execute an extension. More...

int ast_context_add_include (char *context, char *include, char *registrar)
 Add an include. More...

int ast_context_add_include2 (struct ast_context *con, char *include, char *registrar)
 Add an include. More...

int ast_context_remove_include (char *context, char *include, char *registrar)
 Removes an include. More...

int ast_context_remove_include2 (struct ast_context *con, char *include, char *registrar)
 Removes an include by an ast_context structure. More...

int ast_context_verify_includes (struct ast_context *con)
 Verifies includes in an ast_contect structure. More...

int ast_context_add_switch (char *context, char *sw, char *data, char *registrar)
 Add a switch. More...

int ast_context_add_switch2 (struct ast_context *con, char *sw, char *data, char *registrar)
 Adds a switch (first param is a ast_context). More...

int ast_context_remove_switch (char *context, char *sw, char *data, char *registrar)
 Remove a switch. More...

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

int ast_context_remove_extension2 (struct ast_context *con, char *extension, int priority, char *registrar)
int ast_context_add_ignorepat (char *context, char *ignorepat, char *registrar)
 Add an ignorepat. More...

int ast_context_add_ignorepat2 (struct ast_context *con, char *ignorepat, char *registrar)
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_ignore_pattern (char *context, char *pattern)
 Checks to see if a number should be ignored. More...

int ast_lock_contexts (void)
 Locks the contexts. More...

int ast_unlock_contexts (void)
 Unlocks contexts. More...

int ast_lock_context (struct ast_context *con)
 Locks a given context. More...

int ast_unlock_context (struct ast_context *con)
 Unlocks the given context. More...

int ast_async_goto (struct ast_channel *chan, char *context, char *exten, int priority)
int ast_async_goto_by_name (char *chan, char *context, char *exten, int priority)
int ast_pbx_outgoing_exten (char *type, int format, void *data, int timeout, char *context, char *exten, int priority, int *reason, int sync, char *callerid, char *variable, char *account)
int ast_pbx_outgoing_app (char *type, int format, void *data, int timeout, char *app, char *appdata, int *reason, int sync, char *callerid, char *variable, char *account)
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 *include)
char * ast_get_ignorepat_name (struct ast_ignorepat *ip)
char * ast_get_switch_name (struct ast_sw *sw)
char * ast_get_switch_data (struct ast_sw *sw)
int ast_get_extension_priority (struct ast_exten *exten)
int ast_get_extension_matchcid (struct ast_exten *e)
char * ast_get_extension_cidmatch (struct ast_exten *e)
char * ast_get_extension_app (struct ast_exten *e)
void * ast_get_extension_app_data (struct ast_exten *e)
char * ast_get_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_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 *priority)
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)
ast_swast_walk_context_switches (struct ast_context *con, struct ast_sw *sw)
char * pbx_builtin_getvar_helper (struct ast_channel *chan, char *name)
void pbx_builtin_setvar_helper (struct ast_channel *chan, char *name, char *value)
void pbx_builtin_clear_globals (void)
int pbx_builtin_setvar (struct ast_channel *chan, void *data)
void pbx_substitute_variables_helper (struct ast_channel *c, const char *cp1, char *cp2, int count)
int ast_extension_patmatch (const char *pattern, const char *data)


Define Documentation

#define AST_EXTENSION_BUSY   2
 

All devices BUSY.

Definition at line 42 of file pbx.h.

#define AST_EXTENSION_INUSE   1
 

One or more devices INUSE.

Definition at line 40 of file pbx.h.

#define AST_EXTENSION_NOT_INUSE   0
 

Extension states No device INUSE or BUSY.

Definition at line 38 of file pbx.h.

#define AST_EXTENSION_UNAVAILABLE   3
 

All devices UNAVAILABLE/UNREGISTERED.

Definition at line 44 of file pbx.h.

#define AST_MAX_APP   32
 

Max length of an application.

Definition at line 27 of file pbx.h.

#define AST_PBX_KEEP   0
 

Definition at line 23 of file pbx.h.

#define AST_PBX_KEEPALIVE   10
 

Special return values from applications to the PBX.

Definition at line 30 of file pbx.h.

Referenced by ast_pbx_run().

#define AST_PBX_NO_HANGUP_PEER   11
 

Definition at line 31 of file pbx.h.

#define AST_PBX_REPLACE   1
 

Definition at line 24 of file pbx.h.

#define PRIORITY_HINT   -1
 

Special Priority for an hint.

Definition at line 34 of file pbx.h.

Referenced by ast_add_extension2(), and ast_context_remove_extension2().


Typedef Documentation

typedef int(* ast_state_cb_type)(char *context, char* id, int state, void *data)
 

Definition at line 52 of file pbx.h.

Referenced by ast_extension_state_add(), and ast_extension_state_del().


Function Documentation

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

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

03638 {
03639    struct ast_context *c;
03640 
03641    if (ast_lock_contexts()) {
03642       errno = EBUSY;
03643       return -1;
03644    }
03645 
03646    c = ast_walk_contexts(NULL);
03647    while (c) {
03648       if (!strcmp(context, ast_get_context_name(c))) {
03649          int ret = ast_add_extension2(c, replace, extension, priority, callerid,
03650             application, data, datad, registrar);
03651          ast_unlock_contexts();
03652          return ret;
03653       }
03654       c = ast_walk_contexts(c);
03655    }
03656 
03657    ast_unlock_contexts();
03658    errno = ENOENT;
03659    return -1;
03660 }

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

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

Referenced by ast_add_extension().

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

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

Definition at line 3662 of file pbx.c.

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

Referenced by ast_async_goto_by_name().

03663 {
03664    int res = 0;
03665    ast_mutex_lock(&chan->lock);
03666 
03667    if (chan->pbx) {
03668       /* This channel is currently in the PBX */
03669       if (context && !ast_strlen_zero(context))
03670          strncpy(chan->context, context, sizeof(chan->context) - 1);
03671       if (exten && !ast_strlen_zero(exten))
03672          strncpy(chan->exten, exten, sizeof(chan->context) - 1);
03673       if (priority)
03674          chan->priority = priority - 1;
03675       ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO);
03676    } else {
03677       /* In order to do it when the channel doesn't really exist within
03678          the PBX, we have to make a new channel, masquerade, and start the PBX
03679          at the new location */
03680       struct ast_channel *tmpchan;
03681       tmpchan = ast_channel_alloc(0);
03682       if (tmpchan) {
03683          snprintf(tmpchan->name, sizeof(tmpchan->name), "AsyncGoto/%s", chan->name);
03684          ast_setstate(tmpchan, chan->_state);
03685          /* Make formats okay */
03686          tmpchan->readformat = chan->readformat;
03687          tmpchan->writeformat = chan->writeformat;
03688          /* Setup proper location */
03689          if (context && !ast_strlen_zero(context))
03690             strncpy(tmpchan->context, context, sizeof(tmpchan->context) - 1);
03691          else
03692             strncpy(tmpchan->context, chan->context, sizeof(tmpchan->context) - 1);
03693          if (exten && !ast_strlen_zero(exten))
03694             strncpy(tmpchan->exten, exten, sizeof(tmpchan->exten) - 1);
03695          else
03696             strncpy(tmpchan->exten, chan->exten, sizeof(tmpchan->exten) - 1);
03697          if (priority)
03698             tmpchan->priority = priority;
03699          else
03700             tmpchan->priority = chan->priority;
03701          
03702          /* Masquerade into temp channel */
03703          ast_channel_masquerade(tmpchan, chan);
03704       
03705          /* Grab the locks and get going */
03706          ast_mutex_lock(&tmpchan->lock);
03707          ast_do_masquerade(tmpchan);
03708          ast_mutex_unlock(&tmpchan->lock);
03709          /* Start the PBX going on our stolen channel */
03710          if (ast_pbx_start(tmpchan)) {
03711             ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name);
03712             ast_hangup(tmpchan);
03713             res = -1;
03714          }
03715       } else {
03716          res = -1;
03717       }
03718    }
03719    ast_mutex_unlock(&chan->lock);
03720    return res;
03721 }

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

Definition at line 3723 of file pbx.c.

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

03724 {
03725    struct ast_channel *chan;
03726    int res = -1;
03727 
03728    chan = ast_channel_walk_locked(NULL);
03729    while(chan) {
03730       if (!strcasecmp(channame, chan->name))
03731          break;
03732       ast_mutex_unlock(&chan->lock);
03733       chan = ast_channel_walk_locked(chan);
03734    }
03735    
03736    if (chan) {
03737       res = ast_async_goto(chan, context, exten, priority);
03738       ast_mutex_unlock(&chan->lock);
03739    }
03740    return res;
03741 }

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

References HELPER_CANMATCH.

01746 {
01747    return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_CANMATCH);
01748 }

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

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

03556 {
03557    struct ast_context *c;
03558 
03559    if (ast_lock_contexts()) {
03560       errno = EBUSY;
03561       return -1;
03562    }
03563 
03564    c = ast_walk_contexts(NULL);
03565    while (c) {
03566       if (!strcmp(ast_get_context_name(c), con)) {
03567          int ret = ast_context_add_ignorepat2(c, value, registrar);
03568          ast_unlock_contexts();
03569          return ret;
03570       } 
03571       c = ast_walk_contexts(c);
03572    }
03573 
03574    ast_unlock_contexts();
03575    errno = ENOENT;
03576    return -1;
03577 }

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

Definition at line 3579 of file pbx.c.

References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_context::ignorepats, ast_context::lock, LOG_ERROR, malloc, ast_ignorepat::next, ast_ignorepat::pattern, and ast_ignorepat::registrar.

Referenced by ast_context_add_ignorepat().

03580 {
03581    struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL;
03582 
03583    ignorepat = malloc(sizeof(struct ast_ignorepat));
03584    if (!ignorepat) {
03585       ast_log(LOG_ERROR, "Out of memory\n");
03586       errno = ENOMEM;
03587       return -1;
03588    }
03589    memset(ignorepat, 0, sizeof(struct ast_ignorepat));
03590    strncpy(ignorepat->pattern, value, sizeof(ignorepat->pattern)-1);
03591    ignorepat->next = NULL;
03592    ignorepat->registrar = registrar;
03593    ast_mutex_lock(&con->lock);
03594    ignorepatc = con->ignorepats;
03595    while(ignorepatc) {
03596       ignorepatl = ignorepatc;
03597       if (!strcasecmp(ignorepatc->pattern, value)) {
03598          /* Already there */
03599          ast_mutex_unlock(&con->lock);
03600          errno = EEXIST;
03601          return -1;
03602       }
03603       ignorepatc = ignorepatc->next;
03604    }
03605    if (ignorepatl) 
03606       ignorepatl->next = ignorepat;
03607    else
03608       con->ignorepats = ignorepat;
03609    ast_mutex_unlock(&con->lock);
03610    return 0;
03611    
03612 }

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

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

03017 {
03018    struct ast_context *c;
03019 
03020    if (ast_lock_contexts()) {
03021       errno = EBUSY;
03022       return -1;
03023    }
03024 
03025    /* walk contexts ... */
03026    c = ast_walk_contexts(NULL);
03027    while (c) {
03028       /* ... search for the right one ... */
03029       if (!strcmp(ast_get_context_name(c), context)) {
03030          int ret = ast_context_add_include2(c, include, registrar);
03031          /* ... unlock contexts list and return */
03032          ast_unlock_contexts();
03033          return ret;
03034       }
03035       c = ast_walk_contexts(c);
03036    }
03037 
03038    /* we can't find the right context */
03039    ast_unlock_contexts();
03040    errno = ENOENT;
03041    return -1;
03042 }

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

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

Referenced by ast_context_add_include().

03338 {
03339    struct ast_include *new_include;
03340    char *c;
03341    struct ast_include *i, *il = NULL; /* include, include_last */
03342 
03343    /* allocate new include structure ... */
03344    if (!(new_include = malloc(sizeof(struct ast_include)))) {
03345       ast_log(LOG_ERROR, "Out of memory\n");
03346       errno = ENOMEM;
03347       return -1;
03348    }
03349    
03350    /* ... fill in this structure ... */
03351    memset(new_include, 0, sizeof(struct ast_include));
03352    strncpy(new_include->name, value, sizeof(new_include->name)-1);
03353    strncpy(new_include->rname, value, sizeof(new_include->rname)-1);
03354    c = new_include->rname;
03355    /* Strip off timing info */
03356    while(*c && (*c != '|')) c++; 
03357    /* Process if it's there */
03358    if (*c) {
03359       build_timing(new_include, c+1);
03360       *c = '\0';
03361    }
03362    new_include->next      = NULL;
03363    new_include->registrar = registrar;
03364 
03365    /* ... try to lock this context ... */
03366    if (ast_mutex_lock(&con->lock)) {
03367       free(new_include);
03368       errno = EBUSY;
03369       return -1;
03370    }
03371 
03372    /* ... go to last include and check if context is already included too... */
03373    i = con->includes;
03374    while (i) {
03375       if (!strcasecmp(i->name, new_include->name)) {
03376          free(new_include);
03377          ast_mutex_unlock(&con->lock);
03378          errno = EEXIST;
03379          return -1;
03380       }
03381       il = i;
03382       i = i->next;
03383    }
03384 
03385    /* ... include new context into context list, unlock, return */
03386    if (il)
03387       il->next = new_include;
03388    else
03389       con->includes = new_include;
03390    if (option_verbose > 2)
03391       ast_verbose(VERBOSE_PREFIX_3 "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con)); 
03392    ast_mutex_unlock(&con->lock);
03393 
03394    return 0;
03395 }

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

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

03403 {
03404    struct ast_context *c;
03405 
03406    if (ast_lock_contexts()) {
03407       errno = EBUSY;
03408       return -1;
03409    }
03410 
03411    /* walk contexts ... */
03412    c = ast_walk_contexts(NULL);
03413    while (c) {
03414       /* ... search for the right one ... */
03415       if (!strcmp(ast_get_context_name(c), context)) {
03416          int ret = ast_context_add_switch2(c, sw, data, registrar);
03417          /* ... unlock contexts list and return */
03418          ast_unlock_contexts();
03419          return ret;
03420       }
03421       c = ast_walk_contexts(c);
03422    }
03423 
03424    /* we can't find the right context */
03425    ast_unlock_contexts();
03426    errno = ENOENT;
03427    return -1;
03428 }

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

References ast_context::alts, ast_get_context_name(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_verbose(), ast_sw::data, free, ast_context::lock, LOG_ERROR, malloc, ast_sw::name, ast_sw::next, ast_sw::registrar, and VERBOSE_PREFIX_3.

Referenced by ast_context_add_switch().

03439 {
03440    struct ast_sw *new_sw;
03441    struct ast_sw *i, *il = NULL; /* sw, sw_last */
03442 
03443    /* allocate new sw structure ... */
03444    if (!(new_sw = malloc(sizeof(struct ast_sw)))) {
03445       ast_log(LOG_ERROR, "Out of memory\n");
03446       errno = ENOMEM;
03447       return -1;
03448    }
03449    
03450    /* ... fill in this structure ... */
03451    memset(new_sw, 0, sizeof(struct ast_sw));
03452    strncpy(new_sw->name, value, sizeof(new_sw->name)-1);
03453    if (data)
03454       strncpy(new_sw->data, data, sizeof(new_sw->data)-1);
03455    else
03456       strncpy(new_sw->data, "", sizeof(new_sw->data)-1);
03457    new_sw->next      = NULL;
03458    new_sw->registrar = registrar;
03459 
03460    /* ... try to lock this context ... */
03461    if (ast_mutex_lock(&con->lock)) {
03462       free(new_sw);
03463       errno = EBUSY;
03464       return -1;
03465    }
03466 
03467    /* ... go to last sw and check if context is already swd too... */
03468    i = con->alts;
03469    while (i) {
03470       if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) {
03471          free(new_sw);
03472          ast_mutex_unlock(&con->lock);
03473          errno = EEXIST;
03474          return -1;
03475       }
03476       il = i;
03477       i = i->next;
03478    }
03479 
03480    /* ... sw new context into context list, unlock, return */
03481    if (il)
03482       il->next = new_sw;
03483    else
03484       con->alts = new_sw;
03485    if (option_verbose > 2)
03486       ast_verbose(VERBOSE_PREFIX_3 "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con)); 
03487    ast_mutex_unlock(&con->lock);
03488 
03489    return 0;
03490 }

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

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

02940 {
02941    struct ast_context *tmp, **local_contexts;
02942    if (!extcontexts) {
02943       local_contexts = &contexts;
02944       ast_mutex_lock(&conlock);
02945    } else
02946       local_contexts = extcontexts;
02947 
02948    tmp = *local_contexts;
02949    while(tmp) {
02950       if (!strcasecmp(tmp->name, name)) {
02951          ast_mutex_unlock(&conlock);
02952          ast_log(LOG_WARNING, "Tried to register context '%s', already in use\n", name);
02953          if (!extcontexts)
02954             ast_mutex_unlock(&conlock);
02955          return NULL;
02956       }
02957       tmp = tmp->next;
02958    }
02959    tmp = malloc(sizeof(struct ast_context));
02960    if (tmp) {
02961       memset(tmp, 0, sizeof(struct ast_context));
02962       ast_mutex_init(&tmp->lock);
02963       strncpy(tmp->name, name, sizeof(tmp->name)-1);
02964       tmp->root = NULL;
02965       tmp->registrar = registrar;
02966       tmp->next = *local_contexts;
02967       tmp->includes = NULL;
02968       tmp->ignorepats = NULL;
02969       *local_contexts = tmp;
02970       if (option_debug)
02971          ast_log(LOG_DEBUG, "Registered context '%s'\n", tmp->name);
02972       else if (option_verbose > 2)
02973          ast_verbose( VERBOSE_PREFIX_3 "Registered extension context '%s'\n", tmp->name);
02974    } else
02975       ast_log(LOG_ERROR, "Out of memory\n");
02976    
02977    if (!extcontexts)
02978       ast_mutex_unlock(&conlock);
02979    return tmp;
02980 }

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

References __ast_context_destroy().

04326 {
04327    __ast_context_destroy(con,registrar);
04328 }

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

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

Referenced by ast_context_verify_includes(), and ast_ignore_pattern().

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

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

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

02154 {
02155    struct ast_context *c;
02156 
02157    if (ast_lock_contexts()) return -1;
02158 
02159    /* walk contexts ... */
02160    c = ast_walk_contexts(NULL);
02161    while (c) {
02162       /* ... search for the right one ... */
02163       if (!strcmp(ast_get_context_name(c), context)) {
02164          /* ... remove extension ... */
02165          int ret = ast_context_remove_extension2(c, extension, priority,
02166             registrar);
02167          /* ... unlock contexts list and return */
02168          ast_unlock_contexts();
02169          return ret;
02170       }
02171       c = ast_walk_contexts(c);
02172    }
02173 
02174    /* we can't find the right context */
02175    ast_unlock_contexts();
02176    return -1;
02177 }

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

Definition at line 2189 of file pbx.c.

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

Referenced by ast_context_remove_extension().

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

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

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

03497 {
03498    struct ast_context *c;
03499 
03500    if (ast_lock_contexts()) {
03501       errno = EBUSY;
03502       return -1;
03503    }
03504 
03505    c = ast_walk_contexts(NULL);
03506    while (c) {
03507       if (!strcmp(ast_get_context_name(c), context)) {
03508          int ret = ast_context_remove_ignorepat2(c, ignorepat, registrar);
03509          ast_unlock_contexts();
03510          return ret;
03511       }
03512       c = ast_walk_contexts(c);
03513    }
03514 
03515    ast_unlock_contexts();
03516    errno = ENOENT;
03517    return -1;
03518 }

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

Definition at line 3520 of file pbx.c.

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

Referenced by ast_context_remove_ignorepat().

03521 {
03522    struct ast_ignorepat *ip, *ipl = NULL;
03523 
03524    if (ast_mutex_lock(&con->lock)) {
03525       errno = EBUSY;
03526       return -1;
03527    }
03528 
03529    ip = con->ignorepats;
03530    while (ip) {
03531       if (!strcmp(ip->pattern, ignorepat) &&
03532          (!registrar || (registrar == ip->registrar))) {
03533          if (ipl) {
03534             ipl->next = ip->next;
03535             free(ip);
03536          } else {
03537             con->ignorepats = ip->next;
03538             free(ip);
03539          }
03540          ast_mutex_unlock(&con->lock);
03541          return 0;
03542       }
03543       ipl = ip; ip = ip->next;
03544    }
03545 
03546    ast_mutex_unlock(&con->lock);
03547    errno = EINVAL;
03548    return -1;
03549 }

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

Removes an include.

See add_include

Definition at line 2009 of file pbx.c.

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

02010 {
02011    struct ast_context *c;
02012 
02013    if (ast_lock_contexts()) return -1;
02014 
02015    /* walk contexts and search for the right one ...*/
02016    c = ast_walk_contexts(NULL);
02017    while (c) {
02018       /* we found one ... */
02019       if (!strcmp(ast_get_context_name(c), context)) {
02020          int ret;
02021          /* remove include from this context ... */   
02022          ret = ast_context_remove_include2(c, include, registrar);
02023 
02024          ast_unlock_contexts();
02025 
02026          /* ... return results */
02027          return ret;
02028       }
02029       c = ast_walk_contexts(c);
02030    }
02031 
02032    /* we can't find the right one context */
02033    ast_unlock_contexts();
02034    return -1;
02035 }

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

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

Referenced by ast_context_remove_include().

02046 {
02047    struct ast_include *i, *pi = NULL;
02048 
02049    if (ast_mutex_lock(&con->lock)) return -1;
02050 
02051    /* walk includes */
02052    i = con->includes;
02053    while (i) {
02054       /* find our include */
02055       if (!strcmp(i->name, include) && 
02056          (!registrar || !strcmp(i->registrar, registrar))) {
02057          /* remove from list */
02058          if (pi)
02059             pi->next = i->next;
02060          else
02061             con->includes = i->next;
02062          /* free include and return */
02063          free(i);
02064          ast_mutex_unlock(&con->lock);
02065          return 0;
02066       }
02067       pi = i;
02068       i = i->next;
02069    }
02070 
02071    /* we can't find the right include */
02072    ast_mutex_unlock(&con->lock);
02073    return -1;
02074 }

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

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

02082 {
02083    struct ast_context *c;
02084 
02085    if (ast_lock_contexts()) return -1;
02086 
02087    /* walk contexts and search for the right one ...*/
02088    c = ast_walk_contexts(NULL);
02089    while (c) {
02090       /* we found one ... */
02091       if (!strcmp(ast_get_context_name(c), context)) {
02092          int ret;
02093          /* remove switch from this context ... */ 
02094          ret = ast_context_remove_switch2(c, sw, data, registrar);
02095 
02096          ast_unlock_contexts();
02097 
02098          /* ... return results */
02099          return ret;
02100       }
02101       c = ast_walk_contexts(c);
02102    }
02103 
02104    /* we can't find the right one context */
02105    ast_unlock_contexts();
02106    return -1;
02107 }

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

Definition at line 2117 of file pbx.c.

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

Referenced by ast_context_remove_switch().

02118 {
02119    struct ast_sw *i, *pi = NULL;
02120 
02121    if (ast_mutex_lock(&con->lock)) return -1;
02122 
02123    /* walk switchs */
02124    i = con->alts;
02125    while (i) {
02126       /* find our switch */
02127       if (!strcmp(i->name, sw) && !strcmp(i->data, data) && 
02128          (!registrar || !strcmp(i->registrar, registrar))) {
02129          /* remove from list */
02130          if (pi)
02131             pi->next = i->next;
02132          else
02133             con->alts = i->next;
02134          /* free switch and return */
02135          free(i);
02136          ast_mutex_unlock(&con->lock);
02137          return 0;
02138       }
02139       pi = i;
02140       i = i->next;
02141    }
02142 
02143    /* we can't find the right switch */
02144    ast_mutex_unlock(&con->lock);
02145    return -1;
02146 }

int ast_context_verify_includes struct ast_context   con
 

Verifies includes in an ast_contect structure.

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

Definition at line 5043 of file pbx.c.

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

05044 {
05045    struct ast_include *inc;
05046    int res = 0;
05047 
05048    for (inc = ast_walk_context_includes(con, NULL); inc; inc = ast_walk_context_includes(con, inc))
05049       if (!ast_context_find(inc->rname)) {
05050          res = -1;
05051          ast_log(LOG_WARNING, "Context '%s' tries includes non-existant context '%s'\n",
05052                ast_get_context_name(con), inc->rname);
05053       }
05054    return res;
05055 }

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

Referenced by ast_channel_free(), and ast_setstate().

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

Execute an extension.

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

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

References HELPER_EXISTS.

Referenced by ast_pbx_outgoing_exten(), and ast_pbx_run().

01741 {
01742    return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_EXISTS);
01743 }

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

References EXTENSION_MATCH_CORE.

Referenced by ast_ignore_pattern().

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

int ast_extension_patmatch const char *    pattern,
const char *    data
 

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

01415 {
01416    struct ast_exten *e;
01417 
01418    e = ast_hint_extension(c, context, exten);    
01419    if (!e) 
01420       return -1;
01421 
01422    return ast_extension_state2(e);    
01423 }

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

References ast_mutex_lock, ast_mutex_unlock, ast_state_cb_type, ast_state_cb::callback, ast_hint::callbacks, ast_state_cb::data, ast_hint::exten, ast_state_cb::id, malloc, ast_hint::next, and ast_state_cb::next.

Referenced by init_manager().

01492 {
01493    struct ast_hint *list;
01494    struct ast_state_cb *cblist;
01495    struct ast_exten *e;
01496 
01497    /* No context and extension add callback to statecbs list */
01498    if (!context && !exten) {
01499       ast_mutex_lock(&hintlock);
01500 
01501       cblist = statecbs;
01502       while (cblist) {
01503          if (cblist->callback == callback) {
01504             cblist->data = data;
01505             ast_mutex_unlock(&hintlock);
01506          }
01507          cblist = cblist->next;
01508       }
01509    
01510       /* Now inserts the callback */
01511       cblist = malloc(sizeof(struct ast_state_cb));
01512       if (!cblist) {
01513          ast_mutex_unlock(&hintlock);
01514          return -1;
01515       }
01516       memset(cblist, 0, sizeof(struct ast_state_cb));
01517       cblist->id = 0;
01518       cblist->callback = callback;
01519       cblist->data = data;
01520    
01521             cblist->next = statecbs;
01522       statecbs = cblist;
01523 
01524       ast_mutex_unlock(&hintlock);
01525       return 0;
01526       }
01527 
01528    if (!context || !exten)
01529       return -1;
01530 
01531    /* This callback type is for only one hint */
01532    e = ast_hint_extension(NULL, context, exten);    
01533    if (!e) {
01534       return -1;
01535    }
01536     
01537    ast_mutex_lock(&hintlock);
01538    list = hints;        
01539     
01540    while (list) {
01541       if (list->exten == e)
01542          break;       
01543       list = list->next;    
01544    }
01545 
01546    if (!list) {
01547       ast_mutex_unlock(&hintlock);
01548       return -1;
01549    }
01550 
01551    /* Now inserts the callback */
01552    cblist = malloc(sizeof(struct ast_state_cb));
01553    if (!cblist) {
01554       ast_mutex_unlock(&hintlock);
01555       return -1;
01556    }
01557    memset(cblist, 0, sizeof(struct ast_state_cb));
01558    cblist->id = stateid++;
01559    cblist->callback = callback;
01560    cblist->data = data;
01561 
01562    cblist->next = list->callbacks;
01563    list->callbacks = cblist;
01564 
01565    ast_mutex_unlock(&hintlock);
01566    return cblist->id;
01567 }

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

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

01570 {
01571    struct ast_hint *list;
01572    struct ast_state_cb *cblist, *cbprev;
01573     
01574    if (!id && !callback)
01575       return -1;
01576             
01577    ast_mutex_lock(&hintlock);
01578 
01579    /* id is zero is a callback without extension */
01580    if (!id) {
01581       cbprev = NULL;
01582       cblist = statecbs;
01583       while (cblist) {
01584          if (cblist->callback == callback) {
01585             if (!cbprev)
01586                   statecbs = cblist->next;
01587             else
01588                   cbprev->next = cblist->next;
01589 
01590             free(cblist);
01591 
01592                ast_mutex_unlock(&hintlock);
01593             return 0;
01594             }
01595             cbprev = cblist;
01596             cblist = cblist->next;
01597       }
01598 
01599          ast_mutex_lock(&hintlock);
01600       return -1;
01601    }
01602 
01603    /* id greater than zero is a callback with extension */
01604    list = hints;
01605    while (list) {
01606       cblist = list->callbacks;
01607       cbprev = NULL;
01608       while (cblist) {
01609             if (cblist->id==id) {
01610             if (!cbprev)
01611                   list->callbacks = cblist->next;     
01612             else
01613                   cbprev->next = cblist->next;
01614       
01615             free(cblist);
01616       
01617             ast_mutex_unlock(&hintlock);
01618             return 0;      
01619             }     
01620                cbprev = cblist;           
01621             cblist = cblist->next;
01622       }
01623       list = list->next;
01624    }
01625     
01626    ast_mutex_unlock(&hintlock);
01627    return -1;
01628 }

char* ast_get_context_name struct ast_context   con
 

Definition at line 4904 of file pbx.c.

References ast_context::name.

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

04905 {
04906    return con ? con->name : NULL;
04907 }

char* ast_get_context_registrar struct ast_context   c
 

Definition at line 4932 of file pbx.c.

References ast_context::registrar.

04933 {
04934    return c ? c->registrar : NULL;
04935 }

char* ast_get_extension_app struct ast_exten   e
 

Definition at line 4962 of file pbx.c.

References ast_exten::app.

Referenced by ast_device_state_changed(), and ast_get_hint().

04963 {
04964    return e ? e->app : NULL;
04965 }

void* ast_get_extension_app_data struct ast_exten   e
 

Definition at line 4967 of file pbx.c.

References ast_exten::data.

04968 {
04969    return e ? e->data : NULL;
04970 }

char* ast_get_extension_cidmatch struct ast_exten   e
 

Definition at line 4957 of file pbx.c.

References ast_exten::cidmatch.

04958 {
04959    return e ? e->cidmatch : NULL;
04960 }

int ast_get_extension_matchcid struct ast_exten   e
 

Definition at line 4952 of file pbx.c.

References ast_exten::matchcid.

04953 {
04954    return e ? e->matchcid : 0;
04955 }

char* ast_get_extension_name struct ast_exten   exten
 

Definition at line 4909 of file pbx.c.

References ast_exten::exten.

04910 {
04911    return exten ? exten->exten : NULL;
04912 }

int ast_get_extension_priority struct ast_exten   exten
 

Definition at line 4924 of file pbx.c.

References ast_exten::priority.

04925 {
04926    return exten ? exten->priority : -1;
04927 }

char* ast_get_extension_registrar struct ast_exten   e
 

Definition at line 4937 of file pbx.c.

References ast_exten::registrar.

04938 {
04939    return e ? e->registrar : NULL;
04940 }

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

References ast_get_extension_app().

01730 {
01731    struct ast_exten *e;
01732    e = ast_hint_extension(c, context, exten);
01733    if (e) { 
01734        strncpy(hint, ast_get_extension_app(e), hintsize - 1);
01735        return -1;
01736    }
01737    return 0;   
01738 }

char* ast_get_ignorepat_name struct ast_ignorepat   ip
 

Definition at line 4919 of file pbx.c.

References ast_ignorepat::pattern.

04920 {
04921    return ip ? ip->pattern : NULL;
04922 }

char* ast_get_ignorepat_registrar struct ast_ignorepat   ip
 

Definition at line 4947 of file pbx.c.

References ast_ignorepat::registrar.

04948 {
04949    return ip ? ip->registrar : NULL;
04950 }

char* ast_get_include_name struct ast_include   include
 

Definition at line 4914 of file pbx.c.

References ast_include::name.

04915 {
04916    return inc ? inc->name : NULL;
04917 }

char* ast_get_include_registrar struct ast_include   i
 

Definition at line 4942 of file pbx.c.

References ast_include::registrar.

04943 {
04944    return i ? i->registrar : NULL;
04945 }

char* ast_get_switch_data struct ast_sw   sw
 

Definition at line 4977 of file pbx.c.

References ast_sw::data.

04978 {
04979    return sw ? sw->data : NULL;
04980 }

char* ast_get_switch_name struct ast_sw   sw
 

Definition at line 4972 of file pbx.c.

References ast_sw::name.

04973 {
04974    return sw ? sw->name : NULL;
04975 }

char* ast_get_switch_registrar struct ast_sw   sw
 

Definition at line 4982 of file pbx.c.

References ast_sw::registrar.

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

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

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

03615 {
03616    struct ast_context *con;
03617    struct ast_ignorepat *pat;
03618 
03619    con = ast_context_find(context);
03620    if (con) {
03621       pat = con->ignorepats;
03622       while (pat) {
03623          if (ast_extension_match(pat->pattern, pattern))
03624             return 1;
03625          pat = pat->next;
03626       }
03627    } 
03628    return 0;
03629 }

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

References ast_mutex_lock, and ast_context::lock.

04892 {
04893    return ast_mutex_lock(&con->lock);
04894 }

int ast_lock_contexts void   
 

Locks the contexts.

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

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

04879 {
04880    return ast_mutex_lock(&conlock);
04881 }

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

References HELPER_MATCHMORE.

Referenced by ast_pbx_run().

01751 {
01752    return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_MATCHMORE);
01753 }

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

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

02984                                                                                       {
02985    struct ast_context *tmp, *lasttmp = NULL;
02986    tmp = *extcontexts;
02987    ast_mutex_lock(&conlock);
02988    if (registrar) {
02989       __ast_context_destroy(NULL,registrar);
02990       while (tmp) {
02991          lasttmp = tmp;
02992          tmp = tmp->next;
02993       }
02994    } else {
02995       while (tmp) {
02996          __ast_context_destroy(tmp,tmp->registrar);
02997          lasttmp = tmp;
02998          tmp = tmp->next;
02999       }
03000    }
03001    if (lasttmp) {
03002       lasttmp->next = contexts;
03003       contexts = *extcontexts;
03004       *extcontexts = NULL;
03005    } else 
03006       ast_log(LOG_WARNING, "Requested contexts didn't get merged\n");
03007    ast_mutex_unlock(&conlock);
03008    return;  
03009 }

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

Definition at line 4154 of file pbx.c.

References ast_channel::_state, async_stat::app, app_tmp::app, async_stat::appdata, ast_hangup(), ast_log(), ast_pthread_create(), ast_request_and_dial(), AST_STATE_UP, ast_verbose(), async_stat::chan, app_tmp::chan, app_tmp::data, free, LOG_ERROR, LOG_WARNING, malloc, ast_channel::name, async_stat::p, pbx_builtin_setvar(), app_tmp::t, async_stat::timeout, timeout, type, and VERBOSE_PREFIX_4.

04155 {
04156    struct ast_channel *chan;
04157    struct async_stat *as;
04158    struct app_tmp *tmp;
04159    char *var, *vartmp;
04160    int res = -1;
04161    pthread_attr_t attr;
04162    
04163    if (!app || ast_strlen_zero(app))
04164       return -1;
04165    if (sync) {
04166       chan = ast_request_and_dial(type, format, data, timeout, reason, callerid);
04167       if (chan) {
04168          pbx_builtin_setaccount(chan, account);
04169          if (variable) {
04170             vartmp = ast_strdupa(variable);
04171             for (var = strtok_r(vartmp, "|", &vartmp); var; var = strtok_r(NULL, "|", &vartmp)) {
04172                pbx_builtin_setvar( chan, var );
04173             }
04174          }
04175          if (chan->_state == AST_STATE_UP) {
04176             res = 0;
04177             if (option_verbose > 3)
04178                ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", chan->name);
04179             tmp = malloc(sizeof(struct app_tmp));
04180             if (tmp) {
04181                memset(tmp, 0, sizeof(struct app_tmp));
04182                strncpy(tmp->app, app, sizeof(tmp->app) - 1);
04183                strncpy(tmp->data, appdata, sizeof(tmp->data) - 1);
04184                tmp->chan = chan;
04185                if (sync > 1) {
04186                   ast_pbx_run_app(tmp);
04187                } else {
04188                   pthread_attr_init(&attr);
04189                   pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
04190                   if (ast_pthread_create(&tmp->t, &attr, ast_pbx_run_app, tmp)) {
04191                      ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno));
04192                      free(tmp);
04193                      ast_hangup(chan);
04194                      res = -1;
04195                   }
04196                }
04197             } else {
04198                ast_log(LOG_ERROR, "Out of memory :(\n");
04199                res = -1;
04200             }
04201          } else {
04202             if (option_verbose > 3)
04203                ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", chan->name);
04204             ast_hangup(chan);
04205          }
04206       }
04207    } else {
04208       as = malloc(sizeof(struct async_stat));
04209       if (!as)
04210          return -1;
04211       memset(as, 0, sizeof(struct async_stat));
04212       chan = ast_request_and_dial(type, format, data, timeout, reason, callerid);
04213       if (!chan) {
04214          free(as);
04215          return -1;
04216       }
04217       pbx_builtin_setaccount(chan, account);
04218       as->chan = chan;
04219       strncpy(as->app, app, sizeof(as->app) - 1);
04220       if (appdata)
04221          strncpy(as->appdata,  appdata, sizeof(as->appdata) - 1);
04222       as->timeout = timeout;
04223       if (variable) {
04224          vartmp = ast_strdupa(variable);
04225          for (var = strtok_r(vartmp, "|", &vartmp); var; var = strtok_r(NULL, "|", &vartmp))
04226             pbx_builtin_setvar( chan, var );
04227       }
04228       /* Start a new thread, and get something handling this channel. */
04229       pthread_attr_init(&attr);
04230       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
04231       if (ast_pthread_create(&as->p, &attr, async_wait, as)) {
04232          ast_log(LOG_WARNING, "Failed to start async wait\n");
04233          free(as);
04234          ast_hangup(chan);
04235          return -1;
04236       }
04237       res = 0;
04238    }
04239    return res;
04240 }

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

Definition at line 4036 of file pbx.c.

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

04037 {
04038    struct ast_channel *chan;
04039    struct async_stat *as;
04040    int res = -1;
04041    char *var, *tmp;
04042    struct outgoing_helper oh;
04043    pthread_attr_t attr;
04044       
04045    if (sync) {
04046       LOAD_OH(oh);
04047       chan = __ast_request_and_dial(type, format, data, timeout, reason, callerid, &oh);
04048       if (chan) {
04049          pbx_builtin_setaccount(chan, account);
04050          if (chan->_state == AST_STATE_UP) {
04051                res = 0;
04052             if (option_verbose > 3)
04053                ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", chan->name);
04054 
04055             if (sync > 1) {
04056                if (ast_pbx_run(chan)) {
04057                   ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name);
04058                   ast_hangup(chan);
04059                   res = -1;
04060                }
04061             } else {
04062                if (ast_pbx_start(chan)) {
04063                   ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name);
04064                   ast_hangup(chan);
04065                   res = -1;
04066                } 
04067             }
04068          } else {
04069             if (option_verbose > 3)
04070                ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", chan->name);
04071             ast_hangup(chan);
04072          }
04073       }
04074 
04075       if(res < 0) { /* the call failed for some reason */
04076          /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */
04077          /* check if "failed" exists */
04078          if (ast_exists_extension(chan, context, "failed", 1, NULL)) {
04079             chan = ast_channel_alloc(0);
04080             if (chan) {
04081                strncpy(chan->name, "OutgoingSpoolFailed", sizeof(chan->name) - 1);
04082                if (context && !ast_strlen_zero(context))
04083                   strncpy(chan->context, context, sizeof(chan->context) - 1);
04084                strncpy(chan->exten, "failed", sizeof(chan->exten) - 1);
04085                chan->priority = 1;
04086                if (variable) {
04087                   tmp = ast_strdupa(variable);
04088                   for (var = strtok_r(tmp, "|", &tmp); var; var = strtok_r(NULL, "|", &tmp)) {
04089                      pbx_builtin_setvar( chan, var );
04090                   }
04091                }
04092                ast_pbx_run(chan);   
04093             } else
04094                ast_log(LOG_WARNING, "Can't allocate the channel structure, skipping execution of extension 'failed'\n");
04095          }
04096       }
04097    } else {
04098       as = malloc(sizeof(struct async_stat));
04099       if (!as)
04100          return -1;
04101       memset(as, 0, sizeof(struct async_stat));
04102       chan = ast_request_and_dial(type, format, data, timeout, reason, callerid);
04103       if (!chan) {
04104          free(as);
04105          return -1;
04106       }
04107       pbx_builtin_setaccount(chan, account);
04108       as->chan = chan;
04109       strncpy(as->context, context, sizeof(as->context) - 1);
04110       strncpy(as->exten,  exten, sizeof(as->exten) - 1);
04111       as->priority = priority;
04112       as->timeout = timeout;
04113       if (variable) {
04114          tmp = ast_strdupa(variable);
04115          for (var = strtok_r(tmp, "|", &tmp); var; var = strtok_r(NULL, "|", &tmp))
04116             pbx_builtin_setvar( chan, var );
04117       }
04118       pthread_attr_init(&attr);
04119       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
04120       if (ast_pthread_create(&as->p, &attr, async_wait, as)) {
04121          ast_log(LOG_WARNING, "Failed to start async wait\n");
04122          free(as);
04123          ast_hangup(chan);
04124          return -1;
04125       }
04126       res = 0;
04127    }
04128    return res;
04129 }

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

References ast_channel::_softhangup, ast_channel::amaflags, ast_cdr_alloc(), ast_cdr_init(), ast_cdr_start(), ast_cdr_update(), ast_exists_extension(), ast_hangup(), ast_log(), ast_matchmore_extension(), AST_PBX_KEEPALIVE, AST_SOFTHANGUP_ASYNCGOTO, AST_SOFTHANGUP_TIMEOUT, ast_spawn_extension(), ast_verbose(), ast_waitfordigit(), ast_channel::callerid, ast_channel::cdr, ast_channel::context, ast_pbx::dtimeout, ast_channel::exten, free, LOG_DEBUG, LOG_ERROR, LOG_WARNING, malloc, ast_channel::name, ast_channel::pbx, pbx_builtin_setvar_helper(), ast_channel::priority, ast_pbx::rtimeout, VERBOSE_PREFIX_2, VERBOSE_PREFIX_3, and ast_channel::whentohangup.

Referenced by ast_pbx_outgoing_exten().

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

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

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

Referenced by ast_async_goto(), and ast_pbx_outgoing_exten().

01986 {
01987    pthread_t t;
01988    pthread_attr_t attr;
01989    if (!c) {
01990       ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
01991       return -1;
01992    }
01993       
01994    /* Start a new thread, and get something handling this channel. */
01995    pthread_attr_init(&attr);
01996    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
01997    if (ast_pthread_create(&t, &attr, pbx_thread, c)) {
01998       ast_log(LOG_WARNING, "Failed to create new channel thread\n");
01999       return -1;
02000    }
02001    return 0;
02002 }

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

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

Referenced by load_pbx().

02294 {
02295    struct ast_app *tmp, *prev, *cur;
02296    char tmps[80];
02297    if (ast_mutex_lock(&applock)) {
02298       ast_log(LOG_ERROR, "Unable to lock application list\n");
02299       return -1;
02300    }
02301    tmp = apps;
02302    while(tmp) {
02303       if (!strcasecmp(app, tmp->name)) {
02304          ast_log(LOG_WARNING, "Already have an application '%s'\n", app);
02305          ast_mutex_unlock(&applock);
02306          return -1;
02307       }
02308       tmp = tmp->next;
02309    }
02310    tmp = malloc(sizeof(struct ast_app));
02311    if (tmp) {
02312       memset(tmp, 0, sizeof(struct ast_app));
02313       strncpy(tmp->name, app, sizeof(tmp->name)-1);
02314       tmp->execute = execute;
02315       tmp->synopsis = synopsis;
02316       tmp->description = description;
02317       /* Store in alphabetical order */
02318       cur = apps;
02319       prev = NULL;
02320       while(cur) {
02321          if (strcasecmp(tmp->name, cur->name) < 0)
02322             break;
02323          prev = cur;
02324          cur = cur->next;
02325       }
02326       if (prev) {
02327          tmp->next = prev->next;
02328          prev->next = tmp;
02329       } else {
02330          tmp->next = apps;
02331          apps = tmp;
02332       }
02333    } else {
02334       ast_log(LOG_ERROR, "Out of memory\n");
02335       ast_mutex_unlock(&applock);
02336       return -1;
02337    }
02338    if (option_verbose > 1)
02339       ast_verbose( VERBOSE_PREFIX_2 "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps)));
02340    ast_mutex_unlock(&applock);
02341    return 0;
02342 }

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

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

02345 {
02346    struct ast_switch *tmp, *prev=NULL;
02347    if (ast_mutex_lock(&switchlock)) {
02348       ast_log(LOG_ERROR, "Unable to lock switch lock\n");
02349       return -1;
02350    }
02351    tmp = switches;
02352    while(tmp) {
02353       if (!strcasecmp(tmp->name, sw->name))
02354          break;
02355       prev = tmp;
02356       tmp = tmp->next;
02357    }
02358    if (tmp) {  
02359       ast_mutex_unlock(&switchlock);
02360       ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name);
02361       return -1;
02362    }
02363    sw->next = NULL;
02364    if (prev) 
02365       prev->next = sw;
02366    else
02367       switches = sw;
02368    ast_mutex_unlock(&switchlock);
02369    return 0;
02370 }

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

References HELPER_SPAWN.

Referenced by ast_pbx_run().

01756 {
01757    return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_SPAWN);
01758 }

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

References ast_mutex_unlock, and ast_context::lock.

04897 {
04898    return ast_mutex_unlock(&con->lock);
04899 }

int ast_unlock_contexts void   
 

Unlocks contexts.

Returns 0 on success, -1 on failure

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

04884 {
04885    return ast_mutex_unlock(&conlock);
04886 }

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

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

02913                                           {
02914    struct ast_app *tmp, *tmpl = NULL;
02915    if (ast_mutex_lock(&applock)) {
02916       ast_log(LOG_ERROR, "Unable to lock application list\n");
02917       return -1;
02918    }
02919    tmp = apps;
02920    while(tmp) {
02921       if (!strcasecmp(app, tmp->name)) {
02922          if (tmpl)
02923             tmpl->next = tmp->next;
02924          else
02925             apps = tmp->next;
02926          if (option_verbose > 1)
02927             ast_verbose( VERBOSE_PREFIX_2 "Unregistered application '%s'\n", tmp->name);
02928          free(tmp);
02929          ast_mutex_unlock(&applock);
02930          return 0;
02931       }
02932       tmpl = tmp;
02933       tmp = tmp->next;
02934    }
02935    ast_mutex_unlock(&applock);
02936    return -1;
02937 }

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

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

02373 {
02374    struct ast_switch *tmp, *prev=NULL;
02375    if (ast_mutex_lock(&switchlock)) {
02376       ast_log(LOG_ERROR, "Unable to lock switch lock\n");
02377       return;
02378    }
02379    tmp = switches;
02380    while(tmp) {
02381       if (tmp == sw) {
02382          if (prev)
02383             prev->next = tmp->next;
02384          else
02385             switches = tmp->next;
02386          tmp->next = NULL;
02387          break;         
02388       }
02389       prev = tmp;
02390       tmp = tmp->next;
02391    }
02392    ast_mutex_unlock(&switchlock);
02393 }

struct ast_exten* ast_walk_context_extensions struct ast_context   con,
struct ast_exten   priority
 

Definition at line 4998 of file pbx.c.

References ast_exten::next.

05000 {
05001    if (!exten)
05002       return con ? con->root : NULL;
05003    else
05004       return exten->next;
05005 }

struct ast_ignorepat* ast_walk_context_ignorepats struct ast_context   con,
struct ast_ignorepat   ip
 

Definition at line 5034 of file pbx.c.

References ast_ignorepat::next.

05036 {
05037    if (!ip)
05038       return con ? con->ignorepats : NULL;
05039    else
05040       return ip->next;
05041 }

struct ast_include* ast_walk_context_includes struct ast_context   con,
struct ast_include   inc
 

Definition at line 5025 of file pbx.c.

References ast_include::next.

Referenced by ast_context_verify_includes().

05027 {
05028    if (!inc)
05029       return con ? con->includes : NULL;
05030    else
05031       return inc->next;
05032 }

struct ast_sw* ast_walk_context_switches struct ast_context   con,
struct ast_sw   sw
 

Definition at line 5007 of file pbx.c.

References ast_sw::next.

05009 {
05010    if (!sw)
05011       return con ? con->alts : NULL;
05012    else
05013       return sw->next;
05014 }

struct ast_context* ast_walk_contexts struct ast_context   con
 

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

04991 {
04992    if (!con)
04993       return contexts;
04994    else
04995       return con->next;
04996 }

struct ast_exten* ast_walk_extension_priorities struct ast_exten   exten,
struct ast_exten   priority
 

Definition at line 5016 of file pbx.c.

References ast_exten::peer.

05018 {
05019    if (!priority)
05020       return exten;
05021    else
05022       return priority->peer;
05023 }

void pbx_builtin_clear_globals void   
 

Definition at line 4751 of file pbx.c.

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

04752 {
04753    struct ast_var_t *vardata;
04754    while (!AST_LIST_EMPTY(&globals)) {
04755       vardata = AST_LIST_FIRST(&globals);
04756       AST_LIST_REMOVE_HEAD(&globals, entries);
04757       ast_var_delete(vardata);
04758    }
04759 }

char* pbx_builtin_getvar_helper struct ast_channel   chan,
char *    name
 

int pbx_builtin_setvar struct ast_channel   chan,
void *    data
 

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

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

Referenced by ast_pbx_run(), and pbx_builtin_setvar().

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

References ast_cdr_setapp(), AST_CHANNEL_MAX_STACK, ast_log(), and LOG_WARNING.

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

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

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

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

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

Definition at line 1031 of file pbx.c.

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

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


Generated on Thu Oct 28 11:33:06 2004 for Asterisk by doxygen1.2.15