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

pbx.h File Reference

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

Go to the source code of this file.

Data Structures

struct  ast_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 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)
char * ast_get_extension_app (struct ast_exten *e)
void * ast_get_extension_app_data (struct ast_exten *e)
char * ast_get_context_registrar (struct ast_context *c)
char * ast_get_extension_registrar (struct ast_exten *e)
char * ast_get_include_registrar (struct ast_include *i)
char * ast_get_ignorepat_registrar (struct ast_ignorepat *ip)
char * ast_get_switch_registrar (struct ast_sw *sw)
ast_contextast_walk_contexts (struct ast_context *con)
ast_extenast_walk_context_extensions (struct ast_context *con, struct ast_exten *priority)
ast_extenast_walk_extension_priorities (struct ast_exten *exten, struct ast_exten *priority)
ast_includeast_walk_context_includes (struct ast_context *con, struct ast_include *inc)
ast_ignorepatast_walk_context_ignorepats (struct ast_context *con, struct ast_ignorepat *ip)
ast_swast_walk_context_switches (struct ast_context *con, struct ast_sw *sw)
char * pbx_builtin_getvar_helper (struct ast_channel *chan, char *name)
void pbx_builtin_setvar_helper (struct ast_channel *chan, char *name, char *value)
void pbx_builtin_clear_globals (void)
int pbx_builtin_setvar (struct ast_channel *chan, void *data)
void pbx_substitute_variables_helper (struct ast_channel *c, const char *cp1, char *cp2, int count)
int ast_extension_patmatch (const char *pattern, const char *data)


Define Documentation

#define AST_EXTENSION_BUSY   2
 

All devices BUSY.

Definition at line 42 of file pbx.h.

#define AST_EXTENSION_INUSE   1
 

One or more devices INUSE.

Definition at line 40 of file pbx.h.

#define AST_EXTENSION_NOT_INUSE   0
 

Extension states No device INUSE or BUSY Definition at line 38 of file pbx.h.

#define AST_EXTENSION_UNAVAILABLE   3
 

All devices UNAVAILABLE/UNREGISTERED.

Definition at line 44 of file pbx.h.

#define AST_MAX_APP   32
 

Max length of an application.

Definition at line 27 of file pbx.h.

#define AST_PBX_KEEP   0
 

Definition at line 23 of file pbx.h.

#define AST_PBX_KEEPALIVE   10
 

Special return values from applications to the PBX.

Definition at line 30 of file pbx.h.

Referenced by ast_pbx_run().

#define AST_PBX_NO_HANGUP_PEER   11
 

Definition at line 31 of file pbx.h.

#define AST_PBX_REPLACE   1
 

Definition at line 24 of file pbx.h.

#define PRIORITY_HINT   -1
 

Special Priority for an hint.

Definition at line 34 of file pbx.h.

Referenced by ast_add_extension2(), and ast_context_remove_extension2().


Typedef Documentation

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

Definition at line 52 of file pbx.h.

Referenced by ast_extension_state_add(), and ast_extension_state_del().


Function Documentation

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

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

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

03558 { 03559 struct ast_context *c; 03560 03561 if (ast_lock_contexts()) { 03562 errno = EBUSY; 03563 return -1; 03564 } 03565 03566 c = ast_walk_contexts(NULL); 03567 while (c) { 03568 if (!strcmp(context, ast_get_context_name(c))) { 03569 int ret = ast_add_extension2(c, replace, extension, priority, callerid, 03570 application, data, datad, registrar); 03571 ast_unlock_contexts(); 03572 return ret; 03573 } 03574 c = ast_walk_contexts(c); 03575 } 03576 03577 ast_unlock_contexts(); 03578 errno = ENOENT; 03579 return -1; 03580 }

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

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

For details about the arguements, check ast_add_extension() Definition at line 3689 of file pbx.c.

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

Referenced by ast_add_extension().

03693 { 03694 03695 #define LOG do { if (option_debug) {\ 03696 if (tmp->matchcid) { \ 03697 ast_log(LOG_DEBUG, "Added extension '%s' priority %d (CID match '%s') to %s\n", tmp->exten, tmp->priority, tmp->cidmatch, con->name); \ 03698 } else { \ 03699 ast_log(LOG_DEBUG, "Added extension '%s' priority %d to %s\n", tmp->exten, tmp->priority, con->name); \ 03700 } \ 03701 } else if (option_verbose > 2) { \ 03702 if (tmp->matchcid) { \ 03703 ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d (CID match '%s')to %s\n", tmp->exten, tmp->priority, tmp->cidmatch, con->name); \ 03704 } else { \ 03705 ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d to %s\n", tmp->exten, tmp->priority, con->name); \ 03706 } \ 03707 } } while(0) 03708 03709 /* 03710 * This is a fairly complex routine. Different extensions are kept 03711 * in order by the extension number. Then, extensions of different 03712 * priorities (same extension) are kept in a list, according to the 03713 * peer pointer. 03714 */ 03715 struct ast_exten *tmp, *e, *el = NULL, *ep = NULL; 03716 int res; 03717 03718 /* Be optimistic: Build the extension structure first */ 03719 tmp = malloc(sizeof(struct ast_exten)); 03720 if (tmp) { 03721 memset(tmp, 0, sizeof(struct ast_exten)); 03722 ext_strncpy(tmp->exten, extension, sizeof(tmp->exten)); 03723 tmp->priority = priority; 03724 if (callerid) { 03725 ext_strncpy(tmp->cidmatch, callerid, sizeof(tmp->cidmatch)); 03726 tmp->matchcid = 1; 03727 } else { 03728 tmp->cidmatch[0] = '\0'; 03729 tmp->matchcid = 0; 03730 } 03731 strncpy(tmp->app, application, sizeof(tmp->app)-1); 03732 tmp->parent = con; 03733 tmp->data = data; 03734 tmp->datad = datad; 03735 tmp->registrar = registrar; 03736 tmp->peer = NULL; 03737 tmp->next = NULL; 03738 } else { 03739 ast_log(LOG_ERROR, "Out of memory\n"); 03740 errno = ENOMEM; 03741 return -1; 03742 } 03743 if (ast_mutex_lock(&con->lock)) { 03744 free(tmp); 03745 /* And properly destroy the data */ 03746 datad(data); 03747 ast_log(LOG_WARNING, "Failed to lock context '%s'\n", con->name); 03748 errno = EBUSY; 03749 return -1; 03750 } 03751 e = con->root; 03752 while(e) { 03753 res= strcmp(e->exten, extension); 03754 if (!res) { 03755 if (!e->matchcid && !tmp->matchcid) 03756 res = 0; 03757 else if (tmp->matchcid && !e->matchcid) 03758 res = 1; 03759 else if (e->matchcid && !tmp->matchcid) 03760 res = -1; 03761 else 03762 res = strcasecmp(e->cidmatch, tmp->cidmatch); 03763 } 03764 if (res == 0) { 03765 /* We have an exact match, now we find where we are 03766 and be sure there's no duplicates */ 03767 while(e) { 03768 if (e->priority == tmp->priority) { 03769 /* Can't have something exactly the same. Is this a 03770 replacement? If so, replace, otherwise, bonk. */ 03771 if (replace) { 03772 if (ep) { 03773 /* We're in the peer list, insert ourselves */ 03774 ep->peer = tmp; 03775 tmp->peer = e->peer; 03776 } else if (el) { 03777 /* We're the first extension. Take over e's functions */ 03778 el->next = tmp; 03779 tmp->next = e->next; 03780 tmp->peer = e->peer; 03781 } else { 03782 /* We're the very first extension. */ 03783 con->root = tmp; 03784 tmp->next = e->next; 03785 tmp->peer = e->peer; 03786 } 03787 if (tmp->priority == PRIORITY_HINT) 03788 ast_change_hint(e,tmp); 03789 /* Destroy the old one */ 03790 e->datad(e->data); 03791 free(e); 03792 ast_mutex_unlock(&con->lock); 03793 if (tmp->priority == PRIORITY_HINT) 03794 ast_change_hint(e, tmp); 03795 /* And immediately return success. */ 03796 LOG; 03797 return 0; 03798 } else { 03799 ast_log(LOG_WARNING, "Unable to register extension '%s', priority %d in '%s', already in use\n", tmp->exten, tmp->priority, con->name); 03800 tmp->datad(tmp->data); 03801 free(tmp); 03802 ast_mutex_unlock(&con->lock); 03803 errno = EEXIST; 03804 return -1; 03805 } 03806 } else if (e->priority > tmp->priority) { 03807 /* Slip ourselves in just before e */ 03808 if (ep) { 03809 /* Easy enough, we're just in the peer list */ 03810 ep->peer = tmp; 03811 tmp->peer = e; 03812 } else if (el) { 03813 /* We're the first extension in this peer list */ 03814 el->next = tmp; 03815 tmp->next = e->next; 03816 e->next = NULL; 03817 tmp->peer = e; 03818 } else { 03819 /* We're the very first extension altogether */ 03820 tmp->next = con->root->next; 03821 /* Con->root must always exist or we couldn't get here */ 03822 tmp->peer = con->root; 03823 con->root = tmp; 03824 } 03825 ast_mutex_unlock(&con->lock); 03826 /* And immediately return success. */ 03827 if (tmp->priority == PRIORITY_HINT) 03828 ast_add_hint(tmp); 03829 03830 LOG; 03831 return 0; 03832 } 03833 ep = e; 03834 e = e->peer; 03835 } 03836 /* If we make it here, then it's time for us to go at the very end. 03837 ep *must* be defined or we couldn't have gotten here. */ 03838 ep->peer = tmp; 03839 ast_mutex_unlock(&con->lock); 03840 if (tmp->priority == PRIORITY_HINT) 03841 ast_add_hint(tmp); 03842 03843 /* And immediately return success. */ 03844 LOG; 03845 return 0; 03846 03847 } else if (res > 0) { 03848 /* Insert ourselves just before 'e'. We're the first extension of 03849 this kind */ 03850 tmp->next = e; 03851 if (el) { 03852 /* We're in the list somewhere */ 03853 el->next = tmp; 03854 } else { 03855 /* We're at the top of the list */ 03856 con->root = tmp; 03857 } 03858 ast_mutex_unlock(&con->lock); 03859 if (tmp->priority == PRIORITY_HINT) 03860 ast_add_hint(tmp); 03861 03862 /* And immediately return success. */ 03863 LOG; 03864 return 0; 03865 } 03866 03867 el = e; 03868 e = e->next; 03869 } 03870 /* If we fall all the way through to here, then we need to be on the end. */ 03871 if (el) 03872 el->next = tmp; 03873 else 03874 con->root = tmp; 03875 ast_mutex_unlock(&con->lock); 03876 if (tmp->priority == PRIORITY_HINT) 03877 ast_add_hint(tmp); 03878 LOG; 03879 return 0; 03880 }

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

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

03583 { 03584 int res = 0; 03585 ast_mutex_lock(&chan->lock); 03586 03587 if (chan->pbx) { 03588 /* This channel is currently in the PBX */ 03589 if (context && !ast_strlen_zero(context)) 03590 strncpy(chan->context, context, sizeof(chan->context) - 1); 03591 if (exten && !ast_strlen_zero(exten)) 03592 strncpy(chan->exten, exten, sizeof(chan->context) - 1); 03593 if (priority) 03594 chan->priority = priority - 1; 03595 ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO); 03596 } else { 03597 /* In order to do it when the channel doesn't really exist within 03598 the PBX, we have to make a new channel, masquerade, and start the PBX 03599 at the new location */ 03600 struct ast_channel *tmpchan; 03601 tmpchan = ast_channel_alloc(0); 03602 if (tmpchan) { 03603 snprintf(tmpchan->name, sizeof(tmpchan->name), "AsyncGoto/%s", chan->name); 03604 ast_setstate(tmpchan, chan->_state); 03605 /* Make formats okay */ 03606 tmpchan->readformat = chan->readformat; 03607 tmpchan->writeformat = chan->writeformat; 03608 /* Setup proper location */ 03609 if (context && !ast_strlen_zero(context)) 03610 strncpy(tmpchan->context, context, sizeof(tmpchan->context) - 1); 03611 else 03612 strncpy(tmpchan->context, chan->context, sizeof(tmpchan->context) - 1); 03613 if (exten && !ast_strlen_zero(exten)) 03614 strncpy(tmpchan->exten, exten, sizeof(tmpchan->exten) - 1); 03615 else 03616 strncpy(tmpchan->exten, chan->exten, sizeof(tmpchan->exten) - 1); 03617 if (priority) 03618 tmpchan->priority = priority; 03619 else 03620 tmpchan->priority = chan->priority; 03621 03622 /* Masquerade into temp channel */ 03623 ast_channel_masquerade(tmpchan, chan); 03624 03625 /* Grab the locks and get going */ 03626 ast_mutex_lock(&tmpchan->lock); 03627 ast_do_masquerade(tmpchan); 03628 ast_mutex_unlock(&tmpchan->lock); 03629 /* Start the PBX going on our stolen channel */ 03630 if (ast_pbx_start(tmpchan)) { 03631 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name); 03632 ast_hangup(tmpchan); 03633 res = -1; 03634 } 03635 } else { 03636 res = -1; 03637 } 03638 } 03639 ast_mutex_unlock(&chan->lock); 03640 return res; 03641 }

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

Definition at line 3643 of file pbx.c.

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

03644 { 03645 struct ast_channel *chan; 03646 int res = -1; 03647 03648 chan = ast_channel_walk_locked(NULL); 03649 while(chan) { 03650 if (!strcasecmp(channame, chan->name)) 03651 break; 03652 ast_mutex_unlock(&chan->lock); 03653 chan = ast_channel_walk_locked(chan); 03654 } 03655 03656 if (chan) { 03657 res = ast_async_goto(chan, context, exten, priority); 03658 ast_mutex_unlock(&chan->lock); 03659 } 03660 return res; 03661 }

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

References HELPER_CANMATCH.

01724 { 01725 return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_CANMATCH); 01726 }

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

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

03476 { 03477 struct ast_context *c; 03478 03479 if (ast_lock_contexts()) { 03480 errno = EBUSY; 03481 return -1; 03482 } 03483 03484 c = ast_walk_contexts(NULL); 03485 while (c) { 03486 if (!strcmp(ast_get_context_name(c), con)) { 03487 int ret = ast_context_add_ignorepat2(c, value, registrar); 03488 ast_unlock_contexts(); 03489 return ret; 03490 } 03491 c = ast_walk_contexts(c); 03492 } 03493 03494 ast_unlock_contexts(); 03495 errno = ENOENT; 03496 return -1; 03497 }

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

Definition at line 3499 of file pbx.c.

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

Referenced by ast_context_add_ignorepat().

03500 { 03501 struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL; 03502 03503 ignorepat = malloc(sizeof(struct ast_ignorepat)); 03504 if (!ignorepat) { 03505 ast_log(LOG_ERROR, "Out of memory\n"); 03506 errno = ENOMEM; 03507 return -1; 03508 } 03509 memset(ignorepat, 0, sizeof(struct ast_ignorepat)); 03510 strncpy(ignorepat->pattern, value, sizeof(ignorepat->pattern)-1); 03511 ignorepat->next = NULL; 03512 ignorepat->registrar = registrar; 03513 ast_mutex_lock(&con->lock); 03514 ignorepatc = con->ignorepats; 03515 while(ignorepatc) { 03516 ignorepatl = ignorepatc; 03517 if (!strcasecmp(ignorepatc->pattern, value)) { 03518 /* Already there */ 03519 ast_mutex_unlock(&con->lock); 03520 errno = EEXIST; 03521 return -1; 03522 } 03523 ignorepatc = ignorepatc->next; 03524 } 03525 if (ignorepatl) 03526 ignorepatl->next = ignorepat; 03527 else 03528 con->ignorepats = ignorepat; 03529 ast_mutex_unlock(&con->lock); 03530 return 0; 03531 03532 }

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

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

02937 { 02938 struct ast_context *c; 02939 02940 if (ast_lock_contexts()) { 02941 errno = EBUSY; 02942 return -1; 02943 } 02944 02945 /* walk contexts ... */ 02946 c = ast_walk_contexts(NULL); 02947 while (c) { 02948 /* ... search for the right one ... */ 02949 if (!strcmp(ast_get_context_name(c), context)) { 02950 int ret = ast_context_add_include2(c, include, registrar); 02951 /* ... unlock contexts list and return */ 02952 ast_unlock_contexts(); 02953 return ret; 02954 } 02955 c = ast_walk_contexts(c); 02956 } 02957 02958 /* we can't find the right context */ 02959 ast_unlock_contexts(); 02960 errno = ENOENT; 02961 return -1; 02962 }

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 3256 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, option_verbose, and VERBOSE_PREFIX_3.

Referenced by ast_context_add_include().

03258 { 03259 struct ast_include *new_include; 03260 char *c; 03261 struct ast_include *i, *il = NULL; /* include, include_last */ 03262 03263 /* allocate new include structure ... */ 03264 if (!(new_include = malloc(sizeof(struct ast_include)))) { 03265 ast_log(LOG_ERROR, "Out of memory\n"); 03266 errno = ENOMEM; 03267 return -1; 03268 } 03269 03270 /* ... fill in this structure ... */ 03271 memset(new_include, 0, sizeof(struct ast_include)); 03272 strncpy(new_include->name, value, sizeof(new_include->name)-1); 03273 strncpy(new_include->rname, value, sizeof(new_include->rname)-1); 03274 c = new_include->rname; 03275 /* Strip off timing info */ 03276 while(*c && (*c != '|')) c++; 03277 /* Process if it's there */ 03278 if (*c) { 03279 build_timing(new_include, c+1); 03280 *c = '\0'; 03281 } 03282 new_include->next = NULL; 03283 new_include->registrar = registrar; 03284 03285 /* ... try to lock this context ... */ 03286 if (ast_mutex_lock(&con->lock)) { 03287 free(new_include); 03288 errno = EBUSY; 03289 return -1; 03290 } 03291 03292 /* ... go to last include and check if context is already included too... */ 03293 i = con->includes; 03294 while (i) { 03295 if (!strcasecmp(i->name, new_include->name)) { 03296 free(new_include); 03297 ast_mutex_unlock(&con->lock); 03298 errno = EEXIST; 03299 return -1; 03300 } 03301 il = i; 03302 i = i->next; 03303 } 03304 03305 /* ... include new context into context list, unlock, return */ 03306 if (il) 03307 il->next = new_include; 03308 else 03309 con->includes = new_include; 03310 if (option_verbose > 2) 03311 ast_verbose(VERBOSE_PREFIX_3 "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con)); 03312 ast_mutex_unlock(&con->lock); 03313 03314 return 0; 03315 }

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

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

03323 { 03324 struct ast_context *c; 03325 03326 if (ast_lock_contexts()) { 03327 errno = EBUSY; 03328 return -1; 03329 } 03330 03331 /* walk contexts ... */ 03332 c = ast_walk_contexts(NULL); 03333 while (c) { 03334 /* ... search for the right one ... */ 03335 if (!strcmp(ast_get_context_name(c), context)) { 03336 int ret = ast_context_add_switch2(c, sw, data, registrar); 03337 /* ... unlock contexts list and return */ 03338 ast_unlock_contexts(); 03339 return ret; 03340 } 03341 c = ast_walk_contexts(c); 03342 } 03343 03344 /* we can't find the right context */ 03345 ast_unlock_contexts(); 03346 errno = ENOENT; 03347 return -1; 03348 }

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

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

Referenced by ast_context_add_switch().

03359 { 03360 struct ast_sw *new_sw; 03361 struct ast_sw *i, *il = NULL; /* sw, sw_last */ 03362 03363 /* allocate new sw structure ... */ 03364 if (!(new_sw = malloc(sizeof(struct ast_sw)))) { 03365 ast_log(LOG_ERROR, "Out of memory\n"); 03366 errno = ENOMEM; 03367 return -1; 03368 } 03369 03370 /* ... fill in this structure ... */ 03371 memset(new_sw, 0, sizeof(struct ast_sw)); 03372 strncpy(new_sw->name, value, sizeof(new_sw->name)-1); 03373 if (data) 03374 strncpy(new_sw->data, data, sizeof(new_sw->data)-1); 03375 else 03376 strncpy(new_sw->data, "", sizeof(new_sw->data)-1); 03377 new_sw->next = NULL; 03378 new_sw->registrar = registrar; 03379 03380 /* ... try to lock this context ... */ 03381 if (ast_mutex_lock(&con->lock)) { 03382 free(new_sw); 03383 errno = EBUSY; 03384 return -1; 03385 } 03386 03387 /* ... go to last sw and check if context is already swd too... */ 03388 i = con->alts; 03389 while (i) { 03390 if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) { 03391 free(new_sw); 03392 ast_mutex_unlock(&con->lock); 03393 errno = EEXIST; 03394 return -1; 03395 } 03396 il = i; 03397 i = i->next; 03398 } 03399 03400 /* ... sw new context into context list, unlock, return */ 03401 if (il) 03402 il->next = new_sw; 03403 else 03404 con->alts = new_sw; 03405 if (option_verbose > 2) 03406 ast_verbose(VERBOSE_PREFIX_3 "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con)); 03407 ast_mutex_unlock(&con->lock); 03408 03409 return 0; 03410 }

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

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

02860 { 02861 struct ast_context *tmp, **local_contexts; 02862 if (!extcontexts) { 02863 local_contexts = &contexts; 02864 ast_mutex_lock(&conlock); 02865 } else 02866 local_contexts = extcontexts; 02867 02868 tmp = *local_contexts; 02869 while(tmp) { 02870 if (!strcasecmp(tmp->name, name)) { 02871 ast_mutex_unlock(&conlock); 02872 ast_log(LOG_WARNING, "Tried to register context '%s', already in use\n", name); 02873 if (!extcontexts) 02874 ast_mutex_unlock(&conlock); 02875 return NULL; 02876 } 02877 tmp = tmp->next; 02878 } 02879 tmp = malloc(sizeof(struct ast_context)); 02880 if (tmp) { 02881 memset(tmp, 0, sizeof(struct ast_context)); 02882 ast_mutex_init(&tmp->lock); 02883 strncpy(tmp->name, name, sizeof(tmp->name)-1); 02884 tmp->root = NULL; 02885 tmp->registrar = registrar; 02886 tmp->next = *local_contexts; 02887 tmp->includes = NULL; 02888 tmp->ignorepats = NULL; 02889 *local_contexts = tmp; 02890 if (option_debug) 02891 ast_log(LOG_DEBUG, "Registered context '%s'\n", tmp->name); 02892 else if (option_verbose > 2) 02893 ast_verbose( VERBOSE_PREFIX_3 "Registered extension context '%s'\n", tmp->name); 02894 } else 02895 ast_log(LOG_ERROR, "Out of memory\n"); 02896 02897 if (!extcontexts) 02898 ast_mutex_unlock(&conlock); 02899 return tmp; 02900 }

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

References __ast_context_destroy().

04240 { 04241 __ast_context_destroy(con,registrar); 04242 }

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

References ast_mutex_lock, ast_mutex_unlock, and ast_context::next.

Referenced by ast_context_verify_includes(), and ast_ignore_pattern().

00666 { 00667 struct ast_context *tmp; 00668 ast_mutex_lock(&conlock); 00669 if (name) { 00670 tmp = contexts; 00671 while(tmp) { 00672 if (!strcasecmp(name, tmp->name)) 00673 break; 00674 tmp = tmp->next; 00675 } 00676 } else 00677 tmp = contexts; 00678 ast_mutex_unlock(&conlock); 00679 return tmp; 00680 }

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

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

02135 { 02136 struct ast_context *c; 02137 02138 if (ast_lock_contexts()) return -1; 02139 02140 /* walk contexts ... */ 02141 c = ast_walk_contexts(NULL); 02142 while (c) { 02143 /* ... search for the right one ... */ 02144 if (!strcmp(ast_get_context_name(c), context)) { 02145 /* ... remove extension ... */ 02146 int ret = ast_context_remove_extension2(c, extension, priority, 02147 registrar); 02148 /* ... unlock contexts list and return */ 02149 ast_unlock_contexts(); 02150 return ret; 02151 } 02152 c = ast_walk_contexts(c); 02153 } 02154 02155 /* we can't find the right context */ 02156 ast_unlock_contexts(); 02157 return -1; 02158 }

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

Definition at line 2170 of file pbx.c.

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

Referenced by ast_context_remove_extension().

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

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

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

03417 { 03418 struct ast_context *c; 03419 03420 if (ast_lock_contexts()) { 03421 errno = EBUSY; 03422 return -1; 03423 } 03424 03425 c = ast_walk_contexts(NULL); 03426 while (c) { 03427 if (!strcmp(ast_get_context_name(c), context)) { 03428 int ret = ast_context_remove_ignorepat2(c, ignorepat, registrar); 03429 ast_unlock_contexts(); 03430 return ret; 03431 } 03432 c = ast_walk_contexts(c); 03433 } 03434 03435 ast_unlock_contexts(); 03436 errno = ENOENT; 03437 return -1; 03438 }

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

Definition at line 3440 of file pbx.c.

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

Referenced by ast_context_remove_ignorepat().

03441 { 03442 struct ast_ignorepat *ip, *ipl = NULL; 03443 03444 if (ast_mutex_lock(&con->lock)) { 03445 errno = EBUSY; 03446 return -1; 03447 } 03448 03449 ip = con->ignorepats; 03450 while (ip) { 03451 if (!strcmp(ip->pattern, ignorepat) && 03452 (registrar == ip->registrar || !registrar)) { 03453 if (ipl) { 03454 ipl->next = ip->next; 03455 free(ip); 03456 } else { 03457 con->ignorepats = ip->next; 03458 free(ip); 03459 } 03460 ast_mutex_unlock(&con->lock); 03461 return 0; 03462 } 03463 ipl = ip; ip = ip->next; 03464 } 03465 03466 ast_mutex_unlock(&con->lock); 03467 errno = EINVAL; 03468 return -1; 03469 }

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

Removes an include.

See add_include Definition at line 1990 of file pbx.c.

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

01991 { 01992 struct ast_context *c; 01993 01994 if (ast_lock_contexts()) return -1; 01995 01996 /* walk contexts and search for the right one ...*/ 01997 c = ast_walk_contexts(NULL); 01998 while (c) { 01999 /* we found one ... */ 02000 if (!strcmp(ast_get_context_name(c), context)) { 02001 int ret; 02002 /* remove include from this context ... */ 02003 ret = ast_context_remove_include2(c, include, registrar); 02004 02005 ast_unlock_contexts(); 02006 02007 /* ... return results */ 02008 return ret; 02009 } 02010 c = ast_walk_contexts(c); 02011 } 02012 02013 /* we can't find the right one context */ 02014 ast_unlock_contexts(); 02015 return -1; 02016 }

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

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

Referenced by ast_context_remove_include().

02027 { 02028 struct ast_include *i, *pi = NULL; 02029 02030 if (ast_mutex_lock(&con->lock)) return -1; 02031 02032 /* walk includes */ 02033 i = con->includes; 02034 while (i) { 02035 /* find our include */ 02036 if (!strcmp(i->name, include) && 02037 (!strcmp(i->registrar, registrar) || !registrar)) { 02038 /* remove from list */ 02039 if (pi) 02040 pi->next = i->next; 02041 else 02042 con->includes = i->next; 02043 /* free include and return */ 02044 free(i); 02045 ast_mutex_unlock(&con->lock); 02046 return 0; 02047 } 02048 pi = i; 02049 i = i->next; 02050 } 02051 02052 /* we can't find the right include */ 02053 ast_mutex_unlock(&con->lock); 02054 return -1; 02055 }

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

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

02063 { 02064 struct ast_context *c; 02065 02066 if (ast_lock_contexts()) return -1; 02067 02068 /* walk contexts and search for the right one ...*/ 02069 c = ast_walk_contexts(NULL); 02070 while (c) { 02071 /* we found one ... */ 02072 if (!strcmp(ast_get_context_name(c), context)) { 02073 int ret; 02074 /* remove switch from this context ... */ 02075 ret = ast_context_remove_switch2(c, sw, data, registrar); 02076 02077 ast_unlock_contexts(); 02078 02079 /* ... return results */ 02080 return ret; 02081 } 02082 c = ast_walk_contexts(c); 02083 } 02084 02085 /* we can't find the right one context */ 02086 ast_unlock_contexts(); 02087 return -1; 02088 }

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

Definition at line 2098 of file pbx.c.

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

Referenced by ast_context_remove_switch().

02099 { 02100 struct ast_sw *i, *pi = NULL; 02101 02102 if (ast_mutex_lock(&con->lock)) return -1; 02103 02104 /* walk switchs */ 02105 i = con->alts; 02106 while (i) { 02107 /* find our switch */ 02108 if (!strcmp(i->name, sw) && !strcmp(i->data, data) && 02109 (!strcmp(i->registrar, registrar) || !registrar)) { 02110 /* remove from list */ 02111 if (pi) 02112 pi->next = i->next; 02113 else 02114 con->alts = i->next; 02115 /* free switch and return */ 02116 free(i); 02117 ast_mutex_unlock(&con->lock); 02118 return 0; 02119 } 02120 pi = i; 02121 i = i->next; 02122 } 02123 02124 /* we can't find the right switch */ 02125 ast_mutex_unlock(&con->lock); 02126 return -1; 02127 }

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

References ast_context_find(), ast_get_context_name(), ast_log(), ast_walk_context_includes(), and LOG_WARNING.

04907 { 04908 struct ast_include *inc; 04909 int res = 0; 04910 04911 for (inc = ast_walk_context_includes(con, NULL); inc; inc = ast_walk_context_includes(con, inc)) 04912 if (!ast_context_find(inc->rname)) { 04913 res = -1; 04914 ast_log(LOG_WARNING, "Context '%s' tries includes non-existant context '%s'\n", 04915 ast_get_context_name(con), inc->rname); 04916 } 04917 return res; 04918 }

int ast_device_state_changed const char *  fmt,
  ...
 

Tells Asterisk the State for Device is changed.

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

Referenced by ast_channel_free(), and ast_setstate().

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

Execute an extension.

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

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

If an extension exists, return non-zero.

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

References HELPER_EXISTS.

Referenced by ast_pbx_outgoing_exten(), and ast_pbx_run().

01719 { 01720 return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_EXISTS); 01721 }

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

References EXTENSION_MATCH_CORE.

Referenced by ast_ignore_pattern().

00633 { 00634 int match; 00635 /* If they're the same return */ 00636 if (!strcmp(pattern, data)) 00637 return 1; 00638 EXTENSION_MATCH_CORE(data,pattern,match); 00639 /* Must be at the end of both */ 00640 if (*data || (*pattern && (*pattern != '/'))) 00641 match = 0; 00642 return match; 00643 }

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 1392 of file pbx.c.
01393 { 01394 struct ast_exten *e; 01395 01396 e = ast_hint_extension(c, context, exten); 01397 if (!e) 01398 return -1; 01399 01400 return ast_extension_state2(e); 01401 }

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

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

Referenced by init_manager().

01470 { 01471 struct ast_hint *list; 01472 struct ast_state_cb *cblist; 01473 struct ast_exten *e; 01474 01475 /* No context and extension add callback to statecbs list */ 01476 if (!context && !exten) { 01477 ast_mutex_lock(&hintlock); 01478 01479 cblist = statecbs; 01480 while (cblist) { 01481 if (cblist->callback == callback) { 01482 cblist->data = data; 01483 ast_mutex_unlock(&hintlock); 01484 } 01485 cblist = cblist->next; 01486 } 01487 01488 /* Now inserts the callback */ 01489 cblist = malloc(sizeof(struct ast_state_cb)); 01490 if (!cblist) { 01491 ast_mutex_unlock(&hintlock); 01492 return -1; 01493 } 01494 memset(cblist, 0, sizeof(struct ast_state_cb)); 01495 cblist->id = 0; 01496 cblist->callback = callback; 01497 cblist->data = data; 01498 01499 cblist->next = statecbs; 01500 statecbs = cblist; 01501 01502 ast_mutex_unlock(&hintlock); 01503 return 0; 01504 } 01505 01506 if (!context || !exten) 01507 return -1; 01508 01509 /* This callback type is for only one hint */ 01510 e = ast_hint_extension(NULL, context, exten); 01511 if (!e) { 01512 return -1; 01513 } 01514 01515 ast_mutex_lock(&hintlock); 01516 list = hints; 01517 01518 while (list) { 01519 if (list->exten == e) 01520 break; 01521 list = list->next; 01522 } 01523 01524 if (!list) { 01525 ast_mutex_unlock(&hintlock); 01526 return -1; 01527 } 01528 01529 /* Now inserts the callback */ 01530 cblist = malloc(sizeof(struct ast_state_cb)); 01531 if (!cblist) { 01532 ast_mutex_unlock(&hintlock); 01533 return -1; 01534 } 01535 memset(cblist, 0, sizeof(struct ast_state_cb)); 01536 cblist->id = stateid++; 01537 cblist->callback = callback; 01538 cblist->data = data; 01539 01540 cblist->next = list->callbacks; 01541 list->callbacks = cblist; 01542 01543 ast_mutex_unlock(&hintlock); 01544 return cblist->id; 01545 }

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

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

01548 { 01549 struct ast_hint *list; 01550 struct ast_state_cb *cblist, *cbprev; 01551 01552 if (!id && !callback) 01553 return -1; 01554 01555 ast_mutex_lock(&hintlock); 01556 01557 /* id is zero is a callback without extension */ 01558 if (!id) { 01559 cbprev = NULL; 01560 cblist = statecbs; 01561 while (cblist) { 01562 if (cblist->callback == callback) { 01563 if (!cbprev) 01564 statecbs = cblist->next; 01565 else 01566 cbprev->next = cblist->next; 01567 01568 free(cblist); 01569 01570 ast_mutex_unlock(&hintlock); 01571 return 0; 01572 } 01573 cbprev = cblist; 01574 cblist = cblist->next; 01575 } 01576 01577 ast_mutex_lock(&hintlock); 01578 return -1; 01579 } 01580 01581 /* id greater than zero is a callback with extension */ 01582 list = hints; 01583 while (list) { 01584 cblist = list->callbacks; 01585 cbprev = NULL; 01586 while (cblist) { 01587 if (cblist->id==id) { 01588 if (!cbprev) 01589 list->callbacks = cblist->next; 01590 else 01591 cbprev->next = cblist->next; 01592 01593 free(cblist); 01594 01595 ast_mutex_unlock(&hintlock); 01596 return 0; 01597 } 01598 cbprev = cblist; 01599 cblist = cblist->next; 01600 } 01601 list = list->next; 01602 } 01603 01604 ast_mutex_unlock(&hintlock); 01605 return -1; 01606 }

char* ast_get_context_name struct ast_context con  ) 
 

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

04778 { 04779 return con ? con->name : NULL; 04780 }

char* ast_get_context_registrar struct ast_context c  ) 
 

Definition at line 4805 of file pbx.c.

References ast_context::registrar.

04806 { 04807 return c ? c->registrar : NULL; 04808 }

char* ast_get_extension_app struct ast_exten e  ) 
 

Definition at line 4825 of file pbx.c.

References ast_exten::app.

Referenced by ast_device_state_changed(), and ast_get_hint().

04826 { 04827 return e ? e->app : NULL; 04828 }

void* ast_get_extension_app_data struct ast_exten e  ) 
 

Definition at line 4830 of file pbx.c.

References ast_exten::data.

04831 { 04832 return e ? e->data : NULL; 04833 }

char* ast_get_extension_name struct ast_exten exten  ) 
 

Definition at line 4782 of file pbx.c.

References ast_exten::exten.

04783 { 04784 return exten ? exten->exten : NULL; 04785 }

int ast_get_extension_priority struct ast_exten exten  ) 
 

Definition at line 4797 of file pbx.c.

References ast_exten::priority.

04798 { 04799 return exten ? exten->priority : -1; 04800 }

char* ast_get_extension_registrar struct ast_exten e  ) 
 

Definition at line 4810 of file pbx.c.

References ast_exten::registrar.

04811 { 04812 return e ? e->registrar : NULL; 04813 }

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

References ast_get_extension_app().

01708 { 01709 struct ast_exten *e; 01710 e = ast_hint_extension(c, context, exten); 01711 if (e) { 01712 strncpy(hint, ast_get_extension_app(e), hintsize - 1); 01713 return -1; 01714 } 01715 return 0; 01716 }

char* ast_get_ignorepat_name struct ast_ignorepat ip  ) 
 

Definition at line 4792 of file pbx.c.

References ast_ignorepat::pattern.

04793 { 04794 return ip ? ip->pattern : NULL; 04795 }

char* ast_get_ignorepat_registrar struct ast_ignorepat ip  ) 
 

Definition at line 4820 of file pbx.c.

References ast_ignorepat::registrar.

04821 { 04822 return ip ? ip->registrar : NULL; 04823 }

char* ast_get_include_name struct ast_include include  ) 
 

Definition at line 4787 of file pbx.c.

References ast_include::name.

04788 { 04789 return inc ? inc->name : NULL; 04790 }

char* ast_get_include_registrar struct ast_include i  ) 
 

Definition at line 4815 of file pbx.c.

References ast_include::registrar.

04816 { 04817 return i ? i->registrar : NULL; 04818 }

char* ast_get_switch_data struct ast_sw sw  ) 
 

Definition at line 4840 of file pbx.c.

References ast_sw::data.

04841 { 04842 return sw ? sw->data : NULL; 04843 }

char* ast_get_switch_name struct ast_sw sw  ) 
 

Definition at line 4835 of file pbx.c.

References ast_sw::name.

04836 { 04837 return sw ? sw->name : NULL; 04838 }

char* ast_get_switch_registrar struct ast_sw sw  ) 
 

Definition at line 4845 of file pbx.c.

References ast_sw::registrar.

04846 { 04847 return sw ? sw->registrar : NULL; 04848 }

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

References ast_context_find(), and ast_extension_match().

03535 { 03536 struct ast_context *con; 03537 struct ast_ignorepat *pat; 03538 03539 con = ast_context_find(context); 03540 if (con) { 03541 pat = con->ignorepats; 03542 while (pat) { 03543 if (ast_extension_match(pat->pattern, pattern)) 03544 return 1; 03545 pat = pat->next; 03546 } 03547 } 03548 return 0; 03549 }

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

References ast_mutex_lock, and ast_context::lock.

04765 { 04766 return ast_mutex_lock(&con->lock); 04767 }

int ast_lock_contexts void   ) 
 

Locks the contexts.

Locks the context list Returns 0 on success, -1 on error Definition at line 4751 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().

04752 { 04753 return ast_mutex_lock(&conlock); 04754 }

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

References HELPER_MATCHMORE.

Referenced by ast_pbx_run().

01729 { 01730 return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_MATCHMORE); 01731 }

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

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

02904 { 02905 struct ast_context *tmp, *lasttmp = NULL; 02906 tmp = *extcontexts; 02907 ast_mutex_lock(&conlock); 02908 if (registrar) { 02909 __ast_context_destroy(NULL,registrar); 02910 while (tmp) { 02911 lasttmp = tmp; 02912 tmp = tmp->next; 02913 } 02914 } else { 02915 while (tmp) { 02916 __ast_context_destroy(tmp,tmp->registrar); 02917 lasttmp = tmp; 02918 tmp = tmp->next; 02919 } 02920 } 02921 if (lasttmp) { 02922 lasttmp->next = contexts; 02923 contexts = *extcontexts; 02924 *extcontexts = NULL; 02925 } else 02926 ast_log(LOG_WARNING, "Requested contexts didn't get merged\n"); 02927 ast_mutex_unlock(&conlock); 02928 return; 02929 }

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

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

04069 { 04070 struct ast_channel *chan; 04071 struct async_stat *as; 04072 struct app_tmp *tmp; 04073 char *var, *vartmp; 04074 int res = -1; 04075 pthread_attr_t attr; 04076 04077 if (!app || ast_strlen_zero(app)) 04078 return -1; 04079 if (sync) { 04080 chan = ast_request_and_dial(type, format, data, timeout, reason, callerid); 04081 if (chan) { 04082 pbx_builtin_setaccount(chan, account); 04083 if (variable) { 04084 vartmp = ast_strdupa(variable); 04085 for (var = strtok_r(vartmp, "|", &vartmp); var; var = strtok_r(NULL, "|", &vartmp)) { 04086 pbx_builtin_setvar( chan, var ); 04087 } 04088 } 04089 if (chan->_state == AST_STATE_UP) { 04090 res = 0; 04091 if (option_verbose > 3) 04092 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", chan->name); 04093 tmp = malloc(sizeof(struct app_tmp)); 04094 if (tmp) { 04095 memset(tmp, 0, sizeof(struct app_tmp)); 04096 strncpy(tmp->app, app, sizeof(tmp->app) - 1); 04097 strncpy(tmp->data, appdata, sizeof(tmp->data) - 1); 04098 tmp->chan = chan; 04099 if (sync > 1) { 04100 ast_pbx_run_app(tmp); 04101 } else { 04102 pthread_attr_init(&attr); 04103 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 04104 if (pthread_create(&tmp->t, &attr, ast_pbx_run_app, tmp)) { 04105 ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno)); 04106 free(tmp); 04107 ast_hangup(chan); 04108 res = -1; 04109 } 04110 } 04111 } else { 04112 ast_log(LOG_ERROR, "Out of memory :(\n"); 04113 res = -1; 04114 } 04115 } else { 04116 if (option_verbose > 3) 04117 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", chan->name); 04118 ast_hangup(chan); 04119 } 04120 } 04121 } else { 04122 as = malloc(sizeof(struct async_stat)); 04123 if (!as) 04124 return -1; 04125 memset(as, 0, sizeof(struct async_stat)); 04126 chan = ast_request_and_dial(type, format, data, timeout, reason, callerid); 04127 if (!chan) { 04128 free(as); 04129 return -1; 04130 } 04131 pbx_builtin_setaccount(chan, account); 04132 as->chan = chan; 04133 strncpy(as->app, app, sizeof(as->app) - 1); 04134 if (appdata) 04135 strncpy(as->appdata, appdata, sizeof(as->appdata) - 1); 04136 as->timeout = timeout; 04137 if (variable) { 04138 vartmp = ast_strdupa(variable); 04139 for (var = strtok_r(vartmp, "|", &vartmp); var; var = strtok_r(NULL, "|", &vartmp)) 04140 pbx_builtin_setvar( chan, var ); 04141 } 04142 /* Start a new thread, and get something handling this channel. */ 04143 pthread_attr_init(&attr); 04144 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 04145 if (pthread_create(&as->p, &attr, async_wait, as)) { 04146 ast_log(LOG_WARNING, "Failed to start async wait\n"); 04147 free(as); 04148 ast_hangup(chan); 04149 return -1; 04150 } 04151 res = 0; 04152 } 04153 return res; 04154 }

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

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

03951 { 03952 struct ast_channel *chan; 03953 struct async_stat *as; 03954 int res = -1; 03955 char *var, *tmp; 03956 struct outgoing_helper oh; 03957 pthread_attr_t attr; 03958 03959 if (sync) { 03960 LOAD_OH(oh); 03961 chan = __ast_request_and_dial(type, format, data, timeout, reason, callerid, &oh); 03962 if (chan) { 03963 pbx_builtin_setaccount(chan, account); 03964 if (chan->_state == AST_STATE_UP) { 03965 res = 0; 03966 if (option_verbose > 3) 03967 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", chan->name); 03968 03969 if (sync > 1) { 03970 if (ast_pbx_run(chan)) { 03971 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 03972 ast_hangup(chan); 03973 res = -1; 03974 } 03975 } else { 03976 if (ast_pbx_start(chan)) { 03977 ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name); 03978 ast_hangup(chan); 03979 res = -1; 03980 } 03981 } 03982 } else { 03983 if (option_verbose > 3) 03984 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", chan->name); 03985 ast_hangup(chan); 03986 } 03987 } 03988 03989 if(res < 0) { /* the call failed for some reason */ 03990 /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */ 03991 /* check if "failed" exists */ 03992 if (ast_exists_extension(chan, context, "failed", 1, NULL)) { 03993 chan = ast_channel_alloc(0); 03994 if (chan) { 03995 strncpy(chan->name, "OutgoingSpoolFailed", sizeof(chan->name) - 1); 03996 if (context && !ast_strlen_zero(context)) 03997 strncpy(chan->context, context, sizeof(chan->context) - 1); 03998 strncpy(chan->exten, "failed", sizeof(chan->exten) - 1); 03999 chan->priority = 1; 04000 if (variable) { 04001 tmp = ast_strdupa(variable); 04002 for (var = strtok_r(tmp, "|", &tmp); var; var = strtok_r(NULL, "|", &tmp)) { 04003 pbx_builtin_setvar( chan, var ); 04004 } 04005 } 04006 ast_pbx_run(chan); 04007 } else 04008 ast_log(LOG_WARNING, "Can't allocate the channel structure, skipping execution of extension 'failed'\n"); 04009 } 04010 } 04011 } else { 04012 as = malloc(sizeof(struct async_stat)); 04013 if (!as) 04014 return -1; 04015 memset(as, 0, sizeof(struct async_stat)); 04016 chan = ast_request_and_dial(type, format, data, timeout, reason, callerid); 04017 if (!chan) { 04018 free(as); 04019 return -1; 04020 } 04021 pbx_builtin_setaccount(chan, account); 04022 as->chan = chan; 04023 strncpy(as->context, context, sizeof(as->context) - 1); 04024 strncpy(as->exten, exten, sizeof(as->exten) - 1); 04025 as->priority = priority; 04026 as->timeout = timeout; 04027 if (variable) { 04028 tmp = ast_strdupa(variable); 04029 for (var = strtok_r(tmp, "|", &tmp); var; var = strtok_r(NULL, "|", &tmp)) 04030 pbx_builtin_setvar( chan, var ); 04031 } 04032 pthread_attr_init(&attr); 04033 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 04034 if (pthread_create(&as->p, &attr, async_wait, as)) { 04035 ast_log(LOG_WARNING, "Failed to start async wait\n"); 04036 free(as); 04037 ast_hangup(chan); 04038 return -1; 04039 } 04040 res = 0; 04041 } 04042 return res; 04043 }

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

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

Referenced by ast_pbx_outgoing_exten().

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

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

References ast_log(), and LOG_WARNING.

Referenced by ast_async_goto(), and ast_pbx_outgoing_exten().

01967 { 01968 pthread_t t; 01969 pthread_attr_t attr; 01970 if (!c) { 01971 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n"); 01972 return -1; 01973 } 01974 01975 /* Start a new thread, and get something handling this channel. */ 01976 pthread_attr_init(&attr); 01977 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 01978 if (pthread_create(&t, &attr, pbx_thread, c)) { 01979 ast_log(LOG_WARNING, "Failed to create new channel thread\n"); 01980 return -1; 01981 } 01982 return 0; 01983 }

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

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

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

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

Referenced by load_pbx().

02275 { 02276 struct ast_app *tmp, *prev, *cur; 02277 char tmps[80]; 02278 if (ast_mutex_lock(&applock)) { 02279 ast_log(LOG_ERROR, "Unable to lock application list\n"); 02280 return -1; 02281 } 02282 tmp = apps; 02283 while(tmp) { 02284 if (!strcasecmp(app, tmp->name)) { 02285 ast_log(LOG_WARNING, "Already have an application '%s'\n", app); 02286 ast_mutex_unlock(&applock); 02287 return -1; 02288 } 02289 tmp = tmp->next; 02290 } 02291 tmp = malloc(sizeof(struct ast_app)); 02292 if (tmp) { 02293 memset(tmp, 0, sizeof(struct ast_app)); 02294 strncpy(tmp->name, app, sizeof(tmp->name)-1); 02295 tmp->execute = execute; 02296 tmp->synopsis = synopsis; 02297 tmp->description = description; 02298 /* Store in alphabetical order */ 02299 cur = apps; 02300 prev = NULL; 02301 while(cur) { 02302 if (strcasecmp(tmp->name, cur->name) < 0) 02303 break; 02304 prev = cur; 02305 cur = cur->next; 02306 } 02307 if (prev) { 02308 tmp->next = prev->next; 02309 prev->next = tmp; 02310 } else { 02311 tmp->next = apps; 02312 apps = tmp; 02313 } 02314 } else { 02315 ast_log(LOG_ERROR, "Out of memory\n"); 02316 ast_mutex_unlock(&applock); 02317 return -1; 02318 } 02319 if (option_verbose > 1) 02320 ast_verbose( VERBOSE_PREFIX_2 "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps))); 02321 ast_mutex_unlock(&applock); 02322 return 0; 02323 }

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

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

02326 { 02327 struct ast_switch *tmp, *prev=NULL; 02328 if (ast_mutex_lock(&switchlock)) { 02329 ast_log(LOG_ERROR, "Unable to lock switch lock\n"); 02330 return -1; 02331 } 02332 tmp = switches; 02333 while(tmp) { 02334 if (!strcasecmp(tmp->name, sw->name)) 02335 break; 02336 prev = tmp; 02337 tmp = tmp->next; 02338 } 02339 if (tmp) { 02340 ast_mutex_unlock(&switchlock); 02341 ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name); 02342 return -1; 02343 } 02344 sw->next = NULL; 02345 if (prev) 02346 prev->next = sw; 02347 else 02348 switches = sw; 02349 ast_mutex_unlock(&switchlock); 02350 return 0; 02351 }

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

References HELPER_SPAWN.

Referenced by ast_pbx_run().

01734 { 01735 return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_SPAWN); 01736 }

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

References ast_mutex_unlock, and ast_context::lock.

04770 { 04771 return ast_mutex_unlock(&con->lock); 04772 }

int ast_unlock_contexts void   ) 
 

Unlocks contexts.

Returns 0 on success, -1 on failure Definition at line 4756 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().

04757 { 04758 return ast_mutex_unlock(&conlock); 04759 }

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

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

02834 { 02835 struct ast_app *tmp, *tmpl = NULL; 02836 if (ast_mutex_lock(&applock)) { 02837 ast_log(LOG_ERROR, "Unable to lock application list\n"); 02838 return -1; 02839 } 02840 tmp = apps; 02841 while(tmp) { 02842 if (!strcasecmp(app, tmp->name)) { 02843 if (tmpl) 02844 tmpl->next = tmp->next; 02845 else 02846 apps = tmp->next; 02847 if (option_verbose > 1) 02848 ast_verbose( VERBOSE_PREFIX_2 "Unregistered application '%s'\n", tmp->name); 02849 ast_mutex_unlock(&applock); 02850 return 0; 02851 } 02852 tmpl = tmp; 02853 tmp = tmp->next; 02854 } 02855 ast_mutex_unlock(&applock); 02856 return -1; 02857 }

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

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

02354 { 02355 struct ast_switch *tmp, *prev=NULL; 02356 if (ast_mutex_lock(&switchlock)) { 02357 ast_log(LOG_ERROR, "Unable to lock switch lock\n"); 02358 return; 02359 } 02360 tmp = switches; 02361 while(tmp) { 02362 if (tmp == sw) { 02363 if (prev) 02364 prev->next = tmp->next; 02365 else 02366 switches = tmp->next; 02367 tmp->next = NULL; 02368 break; 02369 } 02370 prev = tmp; 02371 tmp = tmp->next; 02372 } 02373 ast_mutex_unlock(&switchlock); 02374 }

struct ast_exten* ast_walk_context_extensions struct ast_context con,
struct ast_exten priority
 

Definition at line 4861 of file pbx.c.

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

04863 { 04864 if (!exten) 04865 return con ? con->root : NULL; 04866 else 04867 return exten->next; 04868 }

struct ast_ignorepat* ast_walk_context_ignorepats struct ast_context con,
struct ast_ignorepat ip
 

Definition at line 4897 of file pbx.c.

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

04899 { 04900 if (!ip) 04901 return con ? con->ignorepats : NULL; 04902 else 04903 return ip->next; 04904 }

struct ast_include* ast_walk_context_includes struct ast_context con,
struct ast_include inc
 

Definition at line 4888 of file pbx.c.

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

Referenced by ast_context_verify_includes().

04890 { 04891 if (!inc) 04892 return con ? con->includes : NULL; 04893 else 04894 return inc->next; 04895 }

struct ast_sw* ast_walk_context_switches struct ast_context con,
struct ast_sw sw
 

Definition at line 4870 of file pbx.c.

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

04872 { 04873 if (!sw) 04874 return con ? con->alts : NULL; 04875 else 04876 return sw->next; 04877 }

struct ast_context* ast_walk_contexts struct ast_context con  ) 
 

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

04854 { 04855 if (!con) 04856 return contexts; 04857 else 04858 return con->next; 04859 }

struct ast_exten* ast_walk_extension_priorities struct ast_exten exten,
struct ast_exten priority
 

Definition at line 4879 of file pbx.c.

References ast_exten::peer.

04881 { 04882 if (!priority) 04883 return exten; 04884 else 04885 return priority->peer; 04886 }

void pbx_builtin_clear_globals void   ) 
 

Definition at line 4624 of file pbx.c.

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

04625 { 04626 struct ast_var_t *vardata; 04627 while (!AST_LIST_EMPTY(&globals)) { 04628 vardata = AST_LIST_FIRST(&globals); 04629 AST_LIST_REMOVE_HEAD(&globals, entries); 04630 ast_var_delete(vardata); 04631 } 04632 }

char* pbx_builtin_getvar_helper struct ast_channel chan,
char *  name
 

int pbx_builtin_setvar struct ast_channel chan,
void *  data
 

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

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

Referenced by ast_pbx_run(), and pbx_builtin_setvar().

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

executes an application

Parameters:
c channel to execute on
app which app to execute
data the data passed into the app
newstack stack pointer This application executes an application on a given channel. It saves the stack and executes the given appliation passing in the given data. It returns 0 on success, and -1 on failure
Definition at line 415 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.

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

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

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

00483 { 00484 struct ast_app *tmp; 00485 00486 if (ast_mutex_lock(&applock)) { 00487 ast_log(LOG_WARNING, "Unable to obtain application lock\n"); 00488 return NULL; 00489 } 00490 tmp = apps; 00491 while(tmp) { 00492 if (!strcasecmp(tmp->name, app)) 00493 break; 00494 tmp = tmp->next; 00495 } 00496 ast_mutex_unlock(&applock); 00497 return tmp; 00498 }

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

Definition at line 1018 of file pbx.c.

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

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


Generated on Tue Aug 17 16:13:56 2004 for Asterisk by doxygen 1.3.8