Main Page | Alphabetical List | Data Structures | Directories | 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_switch
 Data structure associated with an asterisk switch. More...
struct  ast_pbx

Defines

#define AST_PBX_KEEP   0
#define AST_PBX_REPLACE   1
#define AST_MAX_APP   32
 Max length of an application.
#define AST_PBX_KEEPALIVE   10
 Special return values from applications to the PBX.
#define AST_PBX_NO_HANGUP_PEER   11
#define PRIORITY_HINT   -1
 Special Priority for an hint.
#define AST_EXTENSION_NOT_INUSE   0
#define AST_EXTENSION_INUSE   1
 One or more devices INUSE.
#define AST_EXTENSION_BUSY   2
 All devices BUSY.
#define AST_EXTENSION_UNAVAILABLE   3
 All devices UNAVAILABLE/UNREGISTERED.

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.
void ast_unregister_switch (struct ast_switch *sw)
 Unregister an alternative switch.
ast_apppbx_findapp (char *app)
 Look up an application.
int pbx_exec (struct ast_channel *c, struct ast_app *app, void *data, int newstack)
 executes an application
ast_contextast_context_create (struct ast_context **extcontexts, char *name, char *registrar)
 Register a new context.
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.
void ast_context_destroy (struct ast_context *con, char *registrar)
 Destroy a context (matches the specified context (or ANY context if NULL).
ast_contextast_context_find (char *name)
 Find a context.
int ast_pbx_start (struct ast_channel *c)
 Create a new thread and start the PBX (or whatever).
int ast_pbx_run (struct ast_channel *c)
 Execute the PBX in the current thread.
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.
int ast_register_application (char *app, int(*execute)(struct ast_channel *, void *), char *synopsis, char *description)
 Add an application. The function 'execute' should return non-zero if the line needs to be hung up.
int ast_unregister_application (char *app)
 Remove an application.
int ast_extension_state (struct ast_channel *c, char *context, char *exten)
 Uses hint and devicestate callback to get the state of an extension.
int ast_device_state_changed (const char *fmt,...) __attribute__((format(printf
 Tells Asterisk the State for Device is changed.
int int ast_extension_state_add (char *context, char *exten, ast_state_cb_type callback, void *data)
 Registers a state change callback.
int ast_extension_state_del (int id, ast_state_cb_type callback)
 Deletes a registered state change callback by ID.
int ast_get_hint (char *hint, int maxlen, struct ast_channel *c, char *context, char *exten)
 If an extension exists, return non-zero.
int ast_exists_extension (struct ast_channel *c, char *context, char *exten, int priority, char *callerid)
 If an extension exists, return non-zero.
int ast_canmatch_extension (struct ast_channel *c, char *context, char *exten, int priority, char *callerid)
 Looks for a valid matching extension.
int ast_matchmore_extension (struct ast_channel *c, char *context, char *exten, int priority, char *callerid)
 Looks to see if adding anything to this extension might match something. (exists ^ canmatch).
int ast_extension_match (char *pattern, char *extension)
 Determine if a given extension matches a given pattern (in NXX format).
int ast_spawn_extension (struct ast_channel *c, char *context, char *exten, int priority, char *callerid)
 Launch a new extension (i.e. new stack).
int ast_exec_extension (struct ast_channel *c, char *context, char *exten, int priority, char *callerid)
 Execute an extension.
int ast_context_add_include (char *context, char *include, char *registrar)
 Add an include.
int ast_context_add_include2 (struct ast_context *con, char *include, char *registrar)
 Add an include.
int ast_context_remove_include (char *context, char *include, char *registrar)
 Removes an include.
int ast_context_remove_include2 (struct ast_context *con, char *include, char *registrar)
 Removes an include by an ast_context structure.
int ast_context_verify_includes (struct ast_context *con)
 Verifies includes in an ast_contect structure.
int ast_context_add_switch (char *context, char *sw, char *data, char *registrar)
 Add a switch.
int ast_context_add_switch2 (struct ast_context *con, char *sw, char *data, char *registrar)
 Adds a switch (first param is a ast_context).
int ast_context_remove_switch (char *context, char *sw, char *data, char *registrar)
 Remove a switch.
int ast_context_remove_switch2 (struct ast_context *con, char *sw, char *data, char *registrar)
int ast_context_remove_extension (char *context, char *extension, int priority, char *registrar)
 Simply remove extension from context.
int ast_context_remove_extension2 (struct ast_context *con, char *extension, int priority, char *registrar)
int ast_context_add_ignorepat (char *context, char *ignorepat, char *registrar)
 Add an ignorepat.
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.
int ast_lock_contexts (void)
 Locks the contexts.
int ast_unlock_contexts (void)
 Unlocks contexts.
int ast_lock_context (struct ast_context *con)
 Locks a given context.
int ast_unlock_context (struct ast_context *con)
 Unlocks the given context.
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.


Function Documentation

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

Parameters:
context context to add the extension to
replace 
extension extension to add
priority priority level of extension addition
callerid callerid of extension
application application to run on the extension with that priority level
data data to pass to the application
datad 
registrar who registered the extension Add and extension to an extension context. Callerid is a pattern to match CallerID, or NULL to match any callerid Returns 0 on success, -1 on failure

Definition at line 3666 of file pbx.c.

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

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

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

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

For details about the arguements, check ast_add_extension()

Definition at line 3799 of file pbx.c.

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

Referenced by ast_add_extension().

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

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

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

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

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

Definition at line 3753 of file pbx.c.

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

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

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

References HELPER_CANMATCH.

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

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

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

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

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

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

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

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

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

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

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

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

Referenced by ast_context_add_include().

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

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

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

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

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

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

Referenced by ast_context_add_switch().

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

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

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

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

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

References __ast_context_destroy().

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

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

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

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

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

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

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

Definition at line 2204 of file pbx.c.

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

Referenced by ast_context_remove_extension().

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

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

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

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

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

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

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

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

Removes an include.

See add_include

Definition at line 2024 of file pbx.c.

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

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

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

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

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

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

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

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

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

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

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

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

05083 {
05084    struct ast_include *inc;
05085    int res = 0;
05086 
05087    for (inc = ast_walk_context_includes(con, NULL); inc; inc = ast_walk_context_includes(con, inc))
05088       if (!ast_context_find(inc->rname)) {
05089          res = -1;
05090          ast_log(LOG_WARNING, "Context '%s' tries includes nonexistent context '%s'\n",
05091                ast_get_context_name(con), inc->rname);
05092       }
05093    return res;
05094 }

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

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

References HELPER_EXISTS.

Referenced by ast_pbx_outgoing_exten(), and ast_pbx_run().

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

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

References EXTENSION_MATCH_CORE.

Referenced by ast_ignore_pattern().

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

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

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

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

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

Referenced by init_manager().

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

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

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

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

char* ast_get_context_name struct ast_context con  ) 
 

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

04944 {
04945    return con ? con->name : NULL;
04946 }

char* ast_get_context_registrar struct ast_context c  ) 
 

Definition at line 4971 of file pbx.c.

References ast_context::registrar.

04972 {
04973    return c ? c->registrar : NULL;
04974 }

char* ast_get_extension_app struct ast_exten e  ) 
 

Definition at line 5001 of file pbx.c.

References ast_exten::app.

Referenced by ast_device_state_changed(), and ast_get_hint().

05002 {
05003    return e ? e->app : NULL;
05004 }

void* ast_get_extension_app_data struct ast_exten e  ) 
 

Definition at line 5006 of file pbx.c.

References ast_exten::data.

05007 {
05008    return e ? e->data : NULL;
05009 }

char* ast_get_extension_cidmatch struct ast_exten e  ) 
 

Definition at line 4996 of file pbx.c.

References ast_exten::cidmatch.

04997 {
04998    return e ? e->cidmatch : NULL;
04999 }

int ast_get_extension_matchcid struct ast_exten e  ) 
 

Definition at line 4991 of file pbx.c.

References ast_exten::matchcid.

04992 {
04993    return e ? e->matchcid : 0;
04994 }

char* ast_get_extension_name struct ast_exten exten  ) 
 

Definition at line 4948 of file pbx.c.

References ast_exten::exten.

04949 {
04950    return exten ? exten->exten : NULL;
04951 }

int ast_get_extension_priority struct ast_exten exten  ) 
 

Definition at line 4963 of file pbx.c.

References ast_exten::priority.

04964 {
04965    return exten ? exten->priority : -1;
04966 }

char* ast_get_extension_registrar struct ast_exten e  ) 
 

Definition at line 4976 of file pbx.c.

References ast_exten::registrar.

04977 {
04978    return e ? e->registrar : NULL;
04979 }

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

References ast_get_extension_app().

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

char* ast_get_ignorepat_name struct ast_ignorepat ip  ) 
 

Definition at line 4958 of file pbx.c.

References ast_ignorepat::pattern.

04959 {
04960    return ip ? ip->pattern : NULL;
04961 }

char* ast_get_ignorepat_registrar struct ast_ignorepat ip  ) 
 

Definition at line 4986 of file pbx.c.

References ast_ignorepat::registrar.

04987 {
04988    return ip ? ip->registrar : NULL;
04989 }

char* ast_get_include_name struct ast_include include  ) 
 

Definition at line 4953 of file pbx.c.

References ast_include::name.

04954 {
04955    return inc ? inc->name : NULL;
04956 }

char* ast_get_include_registrar struct ast_include i  ) 
 

Definition at line 4981 of file pbx.c.

References ast_include::registrar.

04982 {
04983    return i ? i->registrar : NULL;
04984 }

char* ast_get_switch_data struct ast_sw sw  ) 
 

Definition at line 5016 of file pbx.c.

References ast_sw::data.

05017 {
05018    return sw ? sw->data : NULL;
05019 }

char* ast_get_switch_name struct ast_sw sw  ) 
 

Definition at line 5011 of file pbx.c.

References ast_sw::name.

05012 {
05013    return sw ? sw->name : NULL;
05014 }

char* ast_get_switch_registrar struct ast_sw sw  ) 
 

Definition at line 5021 of file pbx.c.

References ast_sw::registrar.

05022 {
05023    return sw ? sw->registrar : NULL;
05024 }

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

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

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

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

References ast_mutex_lock, and ast_context::lock.

04931 {
04932    return ast_mutex_lock(&con->lock);
04933 }

int ast_lock_contexts void   ) 
 

Locks the contexts.

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

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

04918 {
04919    return ast_mutex_lock(&conlock);
04920 }

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

References HELPER_MATCHMORE.

Referenced by ast_pbx_run().

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

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

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

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

References async_stat::app, async_stat::appdata, ast_hangup(), ast_log(), ast_pthread_create(), ast_request_and_dial(), AST_STATE_UP, ast_verbose(), async_stat::chan, free, LOG_ERROR, LOG_WARNING, malloc, option_verbose, async_stat::p, pbx_builtin_setvar(), async_stat::timeout, and VERBOSE_PREFIX_4.

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

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

References __ast_request_and_dial(), ast_channel_alloc(), ast_exists_extension(), ast_hangup(), ast_log(), ast_pbx_run(), ast_pbx_start(), ast_pthread_create(), ast_request_and_dial(), AST_STATE_UP, ast_verbose(), 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, option_verbose, async_stat::p, pbx_builtin_setvar(), async_stat::priority, ast_channel::priority, async_stat::timeout, and VERBOSE_PREFIX_4.

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

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

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

Referenced by ast_pbx_outgoing_exten().

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

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

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

Referenced by ast_async_goto(), and ast_pbx_outgoing_exten().

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

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

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

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

Definition at line 2308 of file pbx.c.

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

Referenced by load_pbx().

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

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

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

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

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

References HELPER_SPAWN.

Referenced by ast_pbx_run().

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

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

References ast_mutex_unlock, and ast_context::lock.

04936 {
04937    return ast_mutex_unlock(&con->lock);
04938 }

int ast_unlock_contexts void   ) 
 

Unlocks contexts.

Returns 0 on success, -1 on failure

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

04923 {
04924    return ast_mutex_unlock(&conlock);
04925 }

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

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

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

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

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

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

struct ast_exten* ast_walk_context_extensions struct ast_context con,
struct ast_exten priority
 

Definition at line 5037 of file pbx.c.

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

05039 {
05040    if (!exten)
05041       return con ? con->root : NULL;
05042    else
05043       return exten->next;
05044 }

struct ast_ignorepat* ast_walk_context_ignorepats struct ast_context con,
struct ast_ignorepat ip
 

Definition at line 5073 of file pbx.c.

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

05075 {
05076    if (!ip)
05077       return con ? con->ignorepats : NULL;
05078    else
05079       return ip->next;
05080 }

struct ast_include* ast_walk_context_includes struct ast_context con,
struct ast_include inc
 

Definition at line 5064 of file pbx.c.

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

Referenced by ast_context_verify_includes().

05066 {
05067    if (!inc)
05068       return con ? con->includes : NULL;
05069    else
05070       return inc->next;
05071 }

struct ast_sw* ast_walk_context_switches struct ast_context con,
struct ast_sw sw
 

Definition at line 5046 of file pbx.c.

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

05048 {
05049    if (!sw)
05050       return con ? con->alts : NULL;
05051    else
05052       return sw->next;
05053 }

struct ast_context* ast_walk_contexts struct ast_context con  ) 
 

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

05030 {
05031    if (!con)
05032       return contexts;
05033    else
05034       return con->next;
05035 }

struct ast_exten* ast_walk_extension_priorities struct ast_exten exten,
struct ast_exten priority
 

Definition at line 5055 of file pbx.c.

References ast_exten::peer.

05057 {
05058    if (!priority)
05059       return exten;
05060    else
05061       return priority->peer;
05062 }

void pbx_builtin_clear_globals void   ) 
 

Definition at line 4790 of file pbx.c.

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

04791 {
04792    struct ast_var_t *vardata;
04793    while (!AST_LIST_EMPTY(&globals)) {
04794       vardata = AST_LIST_FIRST(&globals);
04795       AST_LIST_REMOVE_HEAD(&globals, entries);
04796       ast_var_delete(vardata);
04797    }
04798 }

char* pbx_builtin_getvar_helper struct ast_channel chan,
char *  name
 

int pbx_builtin_setvar struct ast_channel chan,
void *  data
 

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

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

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

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

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

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

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

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

Definition at line 1045 of file pbx.c.

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

Referenced by pbx_substitute_variables_helper().

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


Generated on Wed Aug 10 11:36:34 2005 for Asterisk by  doxygen 1.4.4