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

pbx.h File Reference

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

Include dependency graph for pbx.h:

Include dependency graph

This graph shows which files directly or indirectly include this file:

Included by dependency graph

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 /* Destroy the thread, but don't hang up the channel */
 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 /* Destroy the thread, but don't hang up the channel */
 

Special return values from applications to the PBX.

Definition at line 30 of file pbx.h.

Referenced by ast_pbx_run().

#define AST_PBX_NO_HANGUP_PEER   11
 

Definition at line 31 of file pbx.h.

#define AST_PBX_REPLACE   1
 

Definition at line 24 of file pbx.h.

#define PRIORITY_HINT   -1
 

Special Priority for an hint.

Definition at line 34 of file pbx.h.

Referenced by ast_add_extension2(), and ast_context_remove_extension2().


Typedef Documentation

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

Definition at line 52 of file pbx.h.


Function Documentation

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

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

03508 { 03509 struct ast_context *c; 03510 03511 if (ast_lock_contexts()) { 03512 errno = EBUSY; 03513 return -1; 03514 } 03515 03516 c = ast_walk_contexts(NULL); 03517 while (c) { 03518 if (!strcmp(context, ast_get_context_name(c))) { 03519 int ret = ast_add_extension2(c, replace, extension, priority, callerid, 03520 application, data, datad, registrar); 03521 ast_unlock_contexts(); 03522 return ret; 03523 } 03524 c = ast_walk_contexts(c); 03525 } 03526 03527 ast_unlock_contexts(); 03528 errno = ENOENT; 03529 return -1; 03530 }

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

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

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

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

03533 { 03534 int res = 0; 03535 ast_mutex_lock(&chan->lock); 03536 if (chan->pbx) { 03537 /* This channel is currently in the PBX */ 03538 if (context && !ast_strlen_zero(context)) 03539 strncpy(chan->context, context, sizeof(chan->context) - 1); 03540 if (exten && !ast_strlen_zero(exten)) 03541 strncpy(chan->exten, exten, sizeof(chan->context) - 1); 03542 if (priority) 03543 chan->priority = priority - 1; 03544 ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO); 03545 } else { 03546 /* In order to do it when the channel doesn't really exist within 03547 the PBX, we have to make a new channel, masquerade, and start the PBX 03548 at the new location */ 03549 struct ast_channel *tmpchan; 03550 tmpchan = ast_channel_alloc(0); 03551 if (tmpchan) { 03552 snprintf(tmpchan->name, sizeof(tmpchan->name), "AsyncGoto/%s", chan->name); 03553 ast_setstate(tmpchan, chan->_state); 03554 /* Make formats okay */ 03555 tmpchan->readformat = chan->readformat; 03556 tmpchan->writeformat = chan->writeformat; 03557 /* Setup proper location */ 03558 if (context && !ast_strlen_zero(context)) 03559 strncpy(tmpchan->context, context, sizeof(tmpchan->context) - 1); 03560 else 03561 strncpy(tmpchan->context, chan->context, sizeof(tmpchan->context) - 1); 03562 if (exten && !ast_strlen_zero(exten)) 03563 strncpy(tmpchan->exten, exten, sizeof(tmpchan->exten) - 1); 03564 else 03565 strncpy(tmpchan->exten, chan->exten, sizeof(tmpchan->exten) - 1); 03566 if (priority) 03567 tmpchan->priority = priority; 03568 else 03569 tmpchan->priority = chan->priority; 03570 03571 /* Masquerade into temp channel */ 03572 ast_channel_masquerade(tmpchan, chan); 03573 03574 /* Grab the locks and get going */ 03575 ast_mutex_lock(&tmpchan->lock); 03576 ast_do_masquerade(tmpchan); 03577 ast_mutex_unlock(&tmpchan->lock); 03578 /* Start the PBX going on our stolen channel */ 03579 if (ast_pbx_start(tmpchan)) { 03580 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name); 03581 ast_hangup(tmpchan); 03582 res = -1; 03583 } 03584 } else { 03585 res = -1; 03586 } 03587 } 03588 ast_mutex_unlock(&chan->lock); 03589 return res; 03590 }

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

Definition at line 3592 of file pbx.c.

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

03593 { 03594 struct ast_channel *chan; 03595 int res = -1; 03596 03597 chan = ast_channel_walk_locked(NULL); 03598 while(chan) { 03599 if (!strcasecmp(channame, chan->name)) 03600 break; 03601 ast_mutex_unlock(&chan->lock); 03602 chan = ast_channel_walk_locked(chan); 03603 } 03604 03605 if (chan) { 03606 res = ast_async_goto(chan, context, exten, priority); 03607 ast_mutex_unlock(&chan->lock); 03608 } 03609 return res; 03610 }

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

References HELPER_CANMATCH.

01680 { 01681 return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_CANMATCH); 01682 }

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

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

03428 { 03429 struct ast_context *c; 03430 03431 if (ast_lock_contexts()) { 03432 errno = EBUSY; 03433 return -1; 03434 } 03435 03436 c = ast_walk_contexts(NULL); 03437 while (c) { 03438 if (!strcmp(ast_get_context_name(c), con)) { 03439 int ret = ast_context_add_ignorepat2(c, value, registrar); 03440 ast_unlock_contexts(); 03441 return ret; 03442 } 03443 c = ast_walk_contexts(c); 03444 } 03445 03446 ast_unlock_contexts(); 03447 errno = ENOENT; 03448 return -1; 03449 }

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

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

03452 { 03453 struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL; 03454 ignorepat = malloc(sizeof(struct ast_ignorepat)); 03455 if (!ignorepat) { 03456 ast_log(LOG_ERROR, "Out of memory\n"); 03457 errno = ENOMEM; 03458 return -1; 03459 } 03460 memset(ignorepat, 0, sizeof(struct ast_ignorepat)); 03461 strncpy(ignorepat->pattern, value, sizeof(ignorepat->pattern)-1); 03462 ignorepat->next = NULL; 03463 ignorepat->registrar = registrar; 03464 ast_mutex_lock(&con->lock); 03465 ignorepatc = con->ignorepats; 03466 while(ignorepatc) { 03467 ignorepatl = ignorepatc; 03468 if (!strcasecmp(ignorepatc->pattern, value)) { 03469 /* Already there */ 03470 ast_mutex_unlock(&con->lock); 03471 errno = EEXIST; 03472 return -1; 03473 } 03474 ignorepatc = ignorepatc->next; 03475 } 03476 if (ignorepatl) 03477 ignorepatl->next = ignorepat; 03478 else 03479 con->ignorepats = ignorepat; 03480 ast_mutex_unlock(&con->lock); 03481 return 0; 03482 03483 }

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

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

02892 { 02893 struct ast_context *c; 02894 02895 if (ast_lock_contexts()) { 02896 errno = EBUSY; 02897 return -1; 02898 } 02899 02900 /* walk contexts ... */ 02901 c = ast_walk_contexts(NULL); 02902 while (c) { 02903 /* ... search for the right one ... */ 02904 if (!strcmp(ast_get_context_name(c), context)) { 02905 int ret = ast_context_add_include2(c, include, registrar); 02906 /* ... unlock contexts list and return */ 02907 ast_unlock_contexts(); 02908 return ret; 02909 } 02910 c = ast_walk_contexts(c); 02911 } 02912 02913 /* we can't find the right context */ 02914 ast_unlock_contexts(); 02915 errno = ENOENT; 02916 return -1; 02917 }

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

03210 { 03211 struct ast_include *new_include; 03212 char *c; 03213 struct ast_include *i, *il = NULL; /* include, include_last */ 03214 03215 /* allocate new include structure ... */ 03216 if (!(new_include = malloc(sizeof(struct ast_include)))) { 03217 ast_log(LOG_ERROR, "Out of memory\n"); 03218 errno = ENOMEM; 03219 return -1; 03220 } 03221 03222 /* ... fill in this structure ... */ 03223 memset(new_include, 0, sizeof(struct ast_include)); 03224 strncpy(new_include->name, value, sizeof(new_include->name)-1); 03225 strncpy(new_include->rname, value, sizeof(new_include->rname)-1); 03226 c = new_include->rname; 03227 /* Strip off timing info */ 03228 while(*c && (*c != '|')) c++; 03229 /* Process if it's there */ 03230 if (*c) { 03231 build_timing(new_include, c+1); 03232 *c = '\0'; 03233 } 03234 new_include->next = NULL; 03235 new_include->registrar = registrar; 03236 03237 /* ... try to lock this context ... */ 03238 if (ast_mutex_lock(&con->lock)) { 03239 free(new_include); 03240 errno = EBUSY; 03241 return -1; 03242 } 03243 03244 /* ... go to last include and check if context is already included too... */ 03245 i = con->includes; 03246 while (i) { 03247 if (!strcasecmp(i->name, new_include->name)) { 03248 free(new_include); 03249 ast_mutex_unlock(&con->lock); 03250 errno = EEXIST; 03251 return -1; 03252 } 03253 il = i; 03254 i = i->next; 03255 } 03256 03257 /* ... include new context into context list, unlock, return */ 03258 if (il) 03259 il->next = new_include; 03260 else 03261 con->includes = new_include; 03262 if (option_verbose > 2) 03263 ast_verbose(VERBOSE_PREFIX_3 "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con)); 03264 ast_mutex_unlock(&con->lock); 03265 03266 return 0; 03267 }

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

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

03275 { 03276 struct ast_context *c; 03277 03278 if (ast_lock_contexts()) { 03279 errno = EBUSY; 03280 return -1; 03281 } 03282 03283 /* walk contexts ... */ 03284 c = ast_walk_contexts(NULL); 03285 while (c) { 03286 /* ... search for the right one ... */ 03287 if (!strcmp(ast_get_context_name(c), context)) { 03288 int ret = ast_context_add_switch2(c, sw, data, registrar); 03289 /* ... unlock contexts list and return */ 03290 ast_unlock_contexts(); 03291 return ret; 03292 } 03293 c = ast_walk_contexts(c); 03294 } 03295 03296 /* we can't find the right context */ 03297 ast_unlock_contexts(); 03298 errno = ENOENT; 03299 return -1; 03300 }

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

03311 { 03312 struct ast_sw *new_sw; 03313 struct ast_sw *i, *il = NULL; /* sw, sw_last */ 03314 03315 /* allocate new sw structure ... */ 03316 if (!(new_sw = malloc(sizeof(struct ast_sw)))) { 03317 ast_log(LOG_ERROR, "Out of memory\n"); 03318 errno = ENOMEM; 03319 return -1; 03320 } 03321 03322 /* ... fill in this structure ... */ 03323 memset(new_sw, 0, sizeof(struct ast_sw)); 03324 strncpy(new_sw->name, value, sizeof(new_sw->name)-1); 03325 if (data) 03326 strncpy(new_sw->data, data, sizeof(new_sw->data)-1); 03327 else 03328 strncpy(new_sw->data, "", sizeof(new_sw->data)-1); 03329 new_sw->next = NULL; 03330 new_sw->registrar = registrar; 03331 03332 /* ... try to lock this context ... */ 03333 if (ast_mutex_lock(&con->lock)) { 03334 free(new_sw); 03335 errno = EBUSY; 03336 return -1; 03337 } 03338 03339 /* ... go to last sw and check if context is already swd too... */ 03340 i = con->alts; 03341 while (i) { 03342 if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) { 03343 free(new_sw); 03344 ast_mutex_unlock(&con->lock); 03345 errno = EEXIST; 03346 return -1; 03347 } 03348 il = i; 03349 i = i->next; 03350 } 03351 03352 /* ... sw new context into context list, unlock, return */ 03353 if (il) 03354 il->next = new_sw; 03355 else 03356 con->alts = new_sw; 03357 if (option_verbose > 2) 03358 ast_verbose(VERBOSE_PREFIX_3 "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con)); 03359 ast_mutex_unlock(&con->lock); 03360 03361 return 0; 03362 }

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

02815 { 02816 struct ast_context *tmp, **local_contexts; 02817 if (!extcontexts) { 02818 local_contexts = &contexts; 02819 ast_mutex_lock(&conlock); 02820 } else 02821 local_contexts = extcontexts; 02822 02823 tmp = *local_contexts; 02824 while(tmp) { 02825 if (!strcasecmp(tmp->name, name)) { 02826 ast_mutex_unlock(&conlock); 02827 ast_log(LOG_WARNING, "Tried to register context '%s', already in use\n", name); 02828 if (!extcontexts) 02829 ast_mutex_unlock(&conlock); 02830 return NULL; 02831 } 02832 tmp = tmp->next; 02833 } 02834 tmp = malloc(sizeof(struct ast_context)); 02835 if (tmp) { 02836 memset(tmp, 0, sizeof(struct ast_context)); 02837 ast_mutex_init(&tmp->lock); 02838 strncpy(tmp->name, name, sizeof(tmp->name)-1); 02839 tmp->root = NULL; 02840 tmp->registrar = registrar; 02841 tmp->next = *local_contexts; 02842 tmp->includes = NULL; 02843 tmp->ignorepats = NULL; 02844 *local_contexts = tmp; 02845 if (option_debug) 02846 ast_log(LOG_DEBUG, "Registered context '%s'\n", tmp->name); 02847 else if (option_verbose > 2) 02848 ast_verbose( VERBOSE_PREFIX_3 "Registered extension context '%s'\n", tmp->name); 02849 } else 02850 ast_log(LOG_ERROR, "Out of memory\n"); 02851 02852 if (!extcontexts) 02853 ast_mutex_unlock(&conlock); 02854 return tmp; 02855 }

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

References __ast_context_destroy().

04183 { 04184 __ast_context_destroy(con,registrar); 04185 }

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

00628 { 00629 struct ast_context *tmp; 00630 ast_mutex_lock(&conlock); 00631 if (name) { 00632 tmp = contexts; 00633 while(tmp) { 00634 if (!strcasecmp(name, tmp->name)) 00635 break; 00636 tmp = tmp->next; 00637 } 00638 } else 00639 tmp = contexts; 00640 ast_mutex_unlock(&conlock); 00641 return tmp; 00642 }

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

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

02090 { 02091 struct ast_context *c; 02092 02093 if (ast_lock_contexts()) return -1; 02094 02095 /* walk contexts ... */ 02096 c = ast_walk_contexts(NULL); 02097 while (c) { 02098 /* ... search for the right one ... */ 02099 if (!strcmp(ast_get_context_name(c), context)) { 02100 /* ... remove extension ... */ 02101 int ret = ast_context_remove_extension2(c, extension, priority, 02102 registrar); 02103 /* ... unlock contexts list and return */ 02104 ast_unlock_contexts(); 02105 return ret; 02106 } 02107 c = ast_walk_contexts(c); 02108 } 02109 02110 /* we can't find the right context */ 02111 ast_unlock_contexts(); 02112 return -1; 02113 }

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

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

02126 { 02127 struct ast_exten *exten, *prev_exten = NULL; 02128 02129 if (ast_mutex_lock(&con->lock)) return -1; 02130 02131 /* go through all extensions in context and search the right one ... */ 02132 exten = con->root; 02133 while (exten) { 02134 02135 /* look for right extension */ 02136 if (!strcmp(exten->exten, extension) && 02137 (!strcmp(exten->registrar, registrar) || !registrar)) { 02138 struct ast_exten *peer; 02139 02140 /* should we free all peers in this extension? (priority == 0)? */ 02141 if (priority == 0) { 02142 /* remove this extension from context list */ 02143 if (prev_exten) 02144 prev_exten->next = exten->next; 02145 else 02146 con->root = exten->next; 02147 02148 /* fire out all peers */ 02149 peer = exten; 02150 while (peer) { 02151 exten = peer->peer; 02152 02153 if (!peer->priority==PRIORITY_HINT) 02154 ast_remove_hint(peer); 02155 02156 peer->datad(peer->data); 02157 free(peer); 02158 02159 peer = exten; 02160 } 02161 02162 ast_mutex_unlock(&con->lock); 02163 return 0; 02164 } else { 02165 /* remove only extension with exten->priority == priority */ 02166 struct ast_exten *previous_peer = NULL; 02167 02168 peer = exten; 02169 while (peer) { 02170 /* is this our extension? */ 02171 if (peer->priority == priority && 02172 (!strcmp(peer->registrar, registrar) || !registrar)) { 02173 /* we are first priority extension? */ 02174 if (!previous_peer) { 02175 /* exists previous extension here? */ 02176 if (prev_exten) { 02177 /* yes, so we must change next pointer in 02178 * previous connection to next peer 02179 */ 02180 if (peer->peer) { 02181 prev_exten->next = peer->peer; 02182 peer->peer->next = exten->next; 02183 } else 02184 prev_exten->next = exten->next; 02185 } else { 02186 /* no previous extension, we are first 02187 * extension, so change con->root ... 02188 */ 02189 if (peer->peer) 02190 con->root = peer->peer; 02191 else 02192 con->root = exten->next; 02193 } 02194 } else { 02195 /* we are not first priority in extension */ 02196 previous_peer->peer = peer->peer; 02197 } 02198 02199 /* now, free whole priority extension */ 02200 if (peer->priority==PRIORITY_HINT) 02201 ast_remove_hint(peer); 02202 peer->datad(peer->data); 02203 free(peer); 02204 02205 ast_mutex_unlock(&con->lock); 02206 return 0; 02207 } else { 02208 /* this is not right extension, skip to next peer */ 02209 previous_peer = peer; 02210 peer = peer->peer; 02211 } 02212 } 02213 02214 ast_mutex_unlock(&con->lock); 02215 return -1; 02216 } 02217 } 02218 02219 prev_exten = exten; 02220 exten = exten->next; 02221 } 02222 02223 /* we can't find right extension */ 02224 ast_mutex_unlock(&con->lock); 02225 return -1; 02226 }

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

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

03369 { 03370 struct ast_context *c; 03371 03372 if (ast_lock_contexts()) { 03373 errno = EBUSY; 03374 return -1; 03375 } 03376 03377 c = ast_walk_contexts(NULL); 03378 while (c) { 03379 if (!strcmp(ast_get_context_name(c), context)) { 03380 int ret = ast_context_remove_ignorepat2(c, ignorepat, registrar); 03381 ast_unlock_contexts(); 03382 return ret; 03383 } 03384 c = ast_walk_contexts(c); 03385 } 03386 03387 ast_unlock_contexts(); 03388 errno = ENOENT; 03389 return -1; 03390 }

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

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

03393 { 03394 struct ast_ignorepat *ip, *ipl = NULL; 03395 03396 if (ast_mutex_lock(&con->lock)) { 03397 errno = EBUSY; 03398 return -1; 03399 } 03400 03401 ip = con->ignorepats; 03402 while (ip) { 03403 if (!strcmp(ip->pattern, ignorepat) && 03404 (registrar == ip->registrar || !registrar)) { 03405 if (ipl) { 03406 ipl->next = ip->next; 03407 free(ip); 03408 } else { 03409 con->ignorepats = ip->next; 03410 free(ip); 03411 } 03412 ast_mutex_unlock(&con->lock); 03413 return 0; 03414 } 03415 ipl = ip; ip = ip->next; 03416 } 03417 03418 ast_mutex_unlock(&con->lock); 03419 errno = EINVAL; 03420 return -1; 03421 }

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

Removes an include.

See add_include

Definition at line 1945 of file pbx.c.

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

01946 { 01947 struct ast_context *c; 01948 01949 if (ast_lock_contexts()) return -1; 01950 01951 /* walk contexts and search for the right one ...*/ 01952 c = ast_walk_contexts(NULL); 01953 while (c) { 01954 /* we found one ... */ 01955 if (!strcmp(ast_get_context_name(c), context)) { 01956 int ret; 01957 /* remove include from this context ... */ 01958 ret = ast_context_remove_include2(c, include, registrar); 01959 01960 ast_unlock_contexts(); 01961 01962 /* ... return results */ 01963 return ret; 01964 } 01965 c = ast_walk_contexts(c); 01966 } 01967 01968 /* we can't find the right one context */ 01969 ast_unlock_contexts(); 01970 return -1; 01971 }

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

01982 { 01983 struct ast_include *i, *pi = NULL; 01984 01985 if (ast_mutex_lock(&con->lock)) return -1; 01986 01987 /* walk includes */ 01988 i = con->includes; 01989 while (i) { 01990 /* find our include */ 01991 if (!strcmp(i->name, include) && 01992 (!strcmp(i->registrar, registrar) || !registrar)) { 01993 /* remove from list */ 01994 if (pi) 01995 pi->next = i->next; 01996 else 01997 con->includes = i->next; 01998 /* free include and return */ 01999 free(i); 02000 ast_mutex_unlock(&con->lock); 02001 return 0; 02002 } 02003 pi = i; 02004 i = i->next; 02005 } 02006 02007 /* we can't find the right include */ 02008 ast_mutex_unlock(&con->lock); 02009 return -1; 02010 }

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

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

02018 { 02019 struct ast_context *c; 02020 02021 if (ast_lock_contexts()) return -1; 02022 02023 /* walk contexts and search for the right one ...*/ 02024 c = ast_walk_contexts(NULL); 02025 while (c) { 02026 /* we found one ... */ 02027 if (!strcmp(ast_get_context_name(c), context)) { 02028 int ret; 02029 /* remove switch from this context ... */ 02030 ret = ast_context_remove_switch2(c, sw, data, registrar); 02031 02032 ast_unlock_contexts(); 02033 02034 /* ... return results */ 02035 return ret; 02036 } 02037 c = ast_walk_contexts(c); 02038 } 02039 02040 /* we can't find the right one context */ 02041 ast_unlock_contexts(); 02042 return -1; 02043 }

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

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

02054 { 02055 struct ast_sw *i, *pi = NULL; 02056 02057 if (ast_mutex_lock(&con->lock)) return -1; 02058 02059 /* walk switchs */ 02060 i = con->alts; 02061 while (i) { 02062 /* find our switch */ 02063 if (!strcmp(i->name, sw) && !strcmp(i->data, data) && 02064 (!strcmp(i->registrar, registrar) || !registrar)) { 02065 /* remove from list */ 02066 if (pi) 02067 pi->next = i->next; 02068 else 02069 con->alts = i->next; 02070 /* free switch and return */ 02071 free(i); 02072 ast_mutex_unlock(&con->lock); 02073 return 0; 02074 } 02075 pi = i; 02076 i = i->next; 02077 } 02078 02079 /* we can't find the right switch */ 02080 ast_mutex_unlock(&con->lock); 02081 return -1; 02082 }

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

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

04832 { 04833 struct ast_include *inc; 04834 int res = 0; 04835 04836 for (inc = ast_walk_context_includes(con, NULL); inc; inc = ast_walk_context_includes(con, inc)) 04837 if (!ast_context_find(inc->rname)) { 04838 res = -1; 04839 ast_log(LOG_WARNING, "Context '%s' tries includes non-existant context '%s'\n", 04840 ast_get_context_name(con), inc->rname); 04841 } 04842 return res; 04843 }

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

References HELPER_EXISTS.

Referenced by ast_pbx_outgoing_exten(), and ast_pbx_run().

01675 { 01676 return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_EXISTS); 01677 }

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

References EXTENSION_MATCH_CORE.

Referenced by ast_ignore_pattern().

00595 { 00596 int match; 00597 /* If they're the same return */ 00598 if (!strcmp(pattern, data)) 00599 return 1; 00600 EXTENSION_MATCH_CORE(data,pattern,match); 00601 /* Must be at the end of both */ 00602 if (*data || (*pattern && (*pattern != '/'))) 00603 match = 0; 00604 return match; 00605 }

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

01345 { 01346 struct ast_exten *e; 01347 01348 e = ast_hint_extension(c, context, exten); 01349 if (!e) 01350 return -1; 01351 01352 return ast_extension_state2(e); 01353 }

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

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

Referenced by init_manager().

01424 { 01425 struct ast_hint *list; 01426 struct ast_state_cb *cblist; 01427 struct ast_exten *e; 01428 01429 /* No context and extension add callback to statecbs list */ 01430 if (!context && !exten) { 01431 ast_mutex_lock(&hintlock); 01432 01433 cblist = statecbs; 01434 while (cblist) { 01435 if (cblist->callback == callback) { 01436 cblist->data = data; 01437 ast_mutex_unlock(&hintlock); 01438 } 01439 01440 cblist = cblist->next; 01441 } 01442 01443 /* Now inserts the callback */ 01444 cblist = malloc(sizeof(struct ast_state_cb)); 01445 if (!cblist) { 01446 ast_mutex_unlock(&hintlock); 01447 return -1; 01448 } 01449 memset(cblist, 0, sizeof(struct ast_state_cb)); 01450 cblist->id = 0; 01451 cblist->callback = callback; 01452 cblist->data = data; 01453 01454 cblist->next = statecbs; 01455 statecbs = cblist; 01456 01457 ast_mutex_unlock(&hintlock); 01458 return 0; 01459 } 01460 01461 if (!context || !exten) 01462 return -1; 01463 01464 /* This callback type is for only one hint */ 01465 e = ast_hint_extension(NULL, context, exten); 01466 if (!e) { 01467 return -1; 01468 } 01469 01470 ast_mutex_lock(&hintlock); 01471 list = hints; 01472 01473 while (list) { 01474 if (list->exten == e) 01475 break; 01476 list = list->next; 01477 } 01478 01479 if (!list) { 01480 ast_mutex_unlock(&hintlock); 01481 return -1; 01482 } 01483 01484 /* Now inserts the callback */ 01485 cblist = malloc(sizeof(struct ast_state_cb)); 01486 if (!cblist) { 01487 ast_mutex_unlock(&hintlock); 01488 return -1; 01489 } 01490 memset(cblist, 0, sizeof(struct ast_state_cb)); 01491 cblist->id = stateid++; 01492 cblist->callback = callback; 01493 cblist->data = data; 01494 01495 cblist->next = list->callbacks; 01496 list->callbacks = cblist; 01497 01498 ast_mutex_unlock(&hintlock); 01499 return cblist->id; 01500 }

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

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

01503 { 01504 struct ast_hint *list; 01505 struct ast_state_cb *cblist, *cbprev; 01506 01507 if (!id && !callback) 01508 return -1; 01509 01510 ast_mutex_lock(&hintlock); 01511 01512 /* id is zero is a callback without extension */ 01513 if (!id) { 01514 cbprev = NULL; 01515 cblist = statecbs; 01516 while (cblist) { 01517 if (cblist->callback == callback) { 01518 if (!cbprev) 01519 statecbs = cblist->next; 01520 else 01521 cbprev->next = cblist->next; 01522 01523 free(cblist); 01524 01525 ast_mutex_unlock(&hintlock); 01526 return 0; 01527 } 01528 cbprev = cblist; 01529 cblist = cblist->next; 01530 } 01531 01532 ast_mutex_lock(&hintlock); 01533 return -1; 01534 } 01535 01536 /* id greater zero is a callback with extension */ 01537 list = hints; 01538 while (list) { 01539 cblist = list->callbacks; 01540 cbprev = NULL; 01541 while (cblist) { 01542 if (cblist->id==id) { 01543 if (!cbprev) 01544 list->callbacks = cblist->next; 01545 else 01546 cbprev->next = cblist->next; 01547 01548 free(cblist); 01549 01550 ast_mutex_unlock(&hintlock); 01551 return 0; 01552 } 01553 cbprev = cblist; 01554 cblist = cblist->next; 01555 } 01556 list = list->next; 01557 } 01558 01559 ast_mutex_unlock(&hintlock); 01560 return -1; 01561 }

char* ast_get_context_name struct ast_context con  ) 
 

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

04703 { 04704 return con ? con->name : NULL; 04705 }

char* ast_get_context_registrar struct ast_context c  ) 
 

Definition at line 4730 of file pbx.c.

References ast_context::registrar.

04731 { 04732 return c ? c->registrar : NULL; 04733 }

char* ast_get_extension_app struct ast_exten e  ) 
 

Definition at line 4750 of file pbx.c.

References ast_exten::app.

Referenced by ast_device_state_changed(), and ast_get_hint().

04751 { 04752 return e ? e->app : NULL; 04753 }

void* ast_get_extension_app_data struct ast_exten e  ) 
 

Definition at line 4755 of file pbx.c.

References ast_exten::data.

04756 { 04757 return e ? e->data : NULL; 04758 }

char* ast_get_extension_name struct ast_exten exten  ) 
 

Definition at line 4707 of file pbx.c.

References ast_exten::exten.

04708 { 04709 return exten ? exten->exten : NULL; 04710 }

int ast_get_extension_priority struct ast_exten exten  ) 
 

Definition at line 4722 of file pbx.c.

References ast_exten::priority.

04723 { 04724 return exten ? exten->priority : -1; 04725 }

char* ast_get_extension_registrar struct ast_exten e  ) 
 

Definition at line 4735 of file pbx.c.

References ast_exten::registrar.

04736 { 04737 return e ? e->registrar : NULL; 04738 }

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

References ast_get_extension_app().

01664 { 01665 struct ast_exten *e; 01666 e = ast_hint_extension(c, context, exten); 01667 if (e) { 01668 strncpy(hint, ast_get_extension_app(e), maxlen); 01669 return -1; 01670 } 01671 return 0; 01672 }

char* ast_get_ignorepat_name struct ast_ignorepat ip  ) 
 

Definition at line 4717 of file pbx.c.

References ast_ignorepat::pattern.

04718 { 04719 return ip ? ip->pattern : NULL; 04720 }

char* ast_get_ignorepat_registrar struct ast_ignorepat ip  ) 
 

Definition at line 4745 of file pbx.c.

References ast_ignorepat::registrar.

04746 { 04747 return ip ? ip->registrar : NULL; 04748 }

char* ast_get_include_name struct ast_include include  ) 
 

Definition at line 4712 of file pbx.c.

References ast_include::name.

04713 { 04714 return inc ? inc->name : NULL; 04715 }

char* ast_get_include_registrar struct ast_include i  ) 
 

Definition at line 4740 of file pbx.c.

References ast_include::registrar.

04741 { 04742 return i ? i->registrar : NULL; 04743 }

char* ast_get_switch_data struct ast_sw sw  ) 
 

Definition at line 4765 of file pbx.c.

References ast_sw::data.

04766 { 04767 return sw ? sw->data : NULL; 04768 }

char* ast_get_switch_name struct ast_sw sw  ) 
 

Definition at line 4760 of file pbx.c.

References ast_sw::name.

04761 { 04762 return sw ? sw->name : NULL; 04763 }

char* ast_get_switch_registrar struct ast_sw sw  ) 
 

Definition at line 4770 of file pbx.c.

References ast_sw::registrar.

04771 { 04772 return sw ? sw->registrar : NULL; 04773 }

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

References ast_context_find(), and ast_extension_match().

03486 { 03487 struct ast_context *con; 03488 struct ast_ignorepat *pat; 03489 con = ast_context_find(context); 03490 if (con) { 03491 pat = con->ignorepats; 03492 while (pat) { 03493 if (ast_extension_match(pat->pattern, pattern)) 03494 return 1; 03495 pat = pat->next; 03496 } 03497 } 03498 return 0; 03499 }

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

References ast_mutex_lock, and ast_context::lock.

04690 { 04691 return ast_mutex_lock(&con->lock); 04692 }

int ast_lock_contexts void   ) 
 

Locks the contexts.

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

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

04677 { 04678 return ast_mutex_lock(&conlock); 04679 }

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

References HELPER_MATCHMORE.

Referenced by ast_pbx_run().

01685 { 01686 return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_MATCHMORE); 01687 }

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

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

02859 { 02860 struct ast_context *tmp, *lasttmp = NULL; 02861 tmp = *extcontexts; 02862 ast_mutex_lock(&conlock); 02863 if (registrar) { 02864 __ast_context_destroy(NULL,registrar); 02865 while (tmp) { 02866 lasttmp = tmp; 02867 tmp = tmp->next; 02868 } 02869 } else { 02870 while (tmp) { 02871 __ast_context_destroy(tmp,tmp->registrar); 02872 lasttmp = tmp; 02873 tmp = tmp->next; 02874 } 02875 } 02876 if (lasttmp) { 02877 lasttmp->next = contexts; 02878 contexts = *extcontexts; 02879 *extcontexts = NULL; 02880 } else 02881 ast_log(LOG_WARNING, "Requested contexts didn't get merged\n"); 02882 ast_mutex_unlock(&conlock); 02883 return; 02884 }

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

04014 { 04015 struct ast_channel *chan; 04016 struct async_stat *as; 04017 struct app_tmp *tmp; 04018 char *var, *vartmp; 04019 int res = -1; 04020 pthread_attr_t attr; 04021 04022 if (!app || ast_strlen_zero(app)) 04023 return -1; 04024 if (sync) { 04025 chan = ast_request_and_dial(type, format, data, timeout, reason, callerid); 04026 if (chan) { 04027 pbx_builtin_setaccount(chan, account); 04028 if (variable) { 04029 vartmp = ast_strdupa(variable); 04030 for (var = strtok_r(vartmp, "|", &vartmp); var; var = strtok_r(NULL, "|", &vartmp)) { 04031 pbx_builtin_setvar( chan, var ); 04032 } 04033 } 04034 if (chan->_state == AST_STATE_UP) { 04035 res = 0; 04036 if (option_verbose > 3) 04037 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", chan->name); 04038 tmp = malloc(sizeof(struct app_tmp)); 04039 if (tmp) { 04040 memset(tmp, 0, sizeof(struct app_tmp)); 04041 strncpy(tmp->app, app, sizeof(tmp->app) - 1); 04042 strncpy(tmp->data, appdata, sizeof(tmp->data) - 1); 04043 tmp->chan = chan; 04044 if (sync > 1) { 04045 ast_pbx_run_app(tmp); 04046 } else { 04047 pthread_attr_init(&attr); 04048 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 04049 if (pthread_create(&tmp->t, &attr, ast_pbx_run_app, tmp)) { 04050 ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno)); 04051 free(tmp); 04052 ast_hangup(chan); 04053 res = -1; 04054 } 04055 } 04056 } else { 04057 ast_log(LOG_ERROR, "Out of memory :(\n"); 04058 res = -1; 04059 } 04060 } else { 04061 if (option_verbose > 3) 04062 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", chan->name); 04063 ast_hangup(chan); 04064 } 04065 } 04066 } else { 04067 as = malloc(sizeof(struct async_stat)); 04068 if (!as) 04069 return -1; 04070 memset(as, 0, sizeof(struct async_stat)); 04071 chan = ast_request_and_dial(type, format, data, timeout, reason, callerid); 04072 if (!chan) { 04073 free(as); 04074 return -1; 04075 } 04076 pbx_builtin_setaccount(chan, account); 04077 as->chan = chan; 04078 strncpy(as->app, app, sizeof(as->app) - 1); 04079 if (appdata) 04080 strncpy(as->appdata, appdata, sizeof(as->appdata) - 1); 04081 as->timeout = timeout; 04082 if (variable) { 04083 vartmp = ast_strdupa(variable); 04084 for (var = strtok_r(vartmp, "|", &vartmp); var; var = strtok_r(NULL, "|", &vartmp)) 04085 pbx_builtin_setvar( chan, var ); 04086 } 04087 /* Start a new thread, and get something handling this channel. */ 04088 pthread_attr_init(&attr); 04089 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 04090 if (pthread_create(&as->p, &attr, async_wait, as)) { 04091 ast_log(LOG_WARNING, "Failed to start async wait\n"); 04092 free(as); 04093 ast_hangup(chan); 04094 return -1; 04095 } 04096 res = 0; 04097 } 04098 return res; 04099 }

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

03898 { 03899 struct ast_channel *chan; 03900 struct async_stat *as; 03901 int res = -1; 03902 char *var, *tmp; 03903 struct outgoing_helper oh; 03904 pthread_attr_t attr; 03905 03906 if (sync) { 03907 LOAD_OH(oh); 03908 chan = __ast_request_and_dial(type, format, data, timeout, reason, callerid, &oh); 03909 if (chan) { 03910 pbx_builtin_setaccount(chan, account); 03911 if (chan->_state == AST_STATE_UP) { 03912 res = 0; 03913 if (option_verbose > 3) 03914 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", chan->name); 03915 03916 if (sync > 1) { 03917 if (ast_pbx_run(chan)) { 03918 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 03919 ast_hangup(chan); 03920 res = -1; 03921 } 03922 } else { 03923 if (ast_pbx_start(chan)) { 03924 ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name); 03925 ast_hangup(chan); 03926 res = -1; 03927 } 03928 } 03929 } else { 03930 if (option_verbose > 3) 03931 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", chan->name); 03932 ast_hangup(chan); 03933 } 03934 } else { 03935 /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */ 03936 /* check if "failed" exists */ 03937 if (ast_exists_extension(chan, context, "failed", 1, NULL)) { 03938 chan = ast_channel_alloc(0); 03939 if (chan) { 03940 strncpy(chan->name, "OutgoingSpoolFailed", sizeof(chan->name) - 1); 03941 if (context && !ast_strlen_zero(context)) 03942 strncpy(chan->context, context, sizeof(chan->context) - 1); 03943 strncpy(chan->exten, "failed", sizeof(chan->exten) - 1); 03944 chan->priority = 1; 03945 if (variable) { 03946 tmp = ast_strdupa(variable); 03947 for (var = strtok_r(tmp, "|", &tmp); var; var = strtok_r(NULL, "|", &tmp)) { 03948 pbx_builtin_setvar( chan, var ); 03949 } 03950 } 03951 ast_pbx_run(chan); 03952 } else 03953 ast_log(LOG_WARNING, "Can't allocate the channel structure, skipping execution of extension 'failed'\n"); 03954 } 03955 } 03956 } else { 03957 as = malloc(sizeof(struct async_stat)); 03958 if (!as) 03959 return -1; 03960 memset(as, 0, sizeof(struct async_stat)); 03961 chan = ast_request_and_dial(type, format, data, timeout, reason, callerid); 03962 if (!chan) { 03963 free(as); 03964 return -1; 03965 } 03966 pbx_builtin_setaccount(chan, account); 03967 as->chan = chan; 03968 strncpy(as->context, context, sizeof(as->context) - 1); 03969 strncpy(as->exten, exten, sizeof(as->exten) - 1); 03970 as->priority = priority; 03971 as->timeout = timeout; 03972 if (variable) { 03973 tmp = ast_strdupa(variable); 03974 for (var = strtok_r(tmp, "|", &tmp); var; var = strtok_r(NULL, "|", &tmp)) 03975 pbx_builtin_setvar( chan, var ); 03976 } 03977 pthread_attr_init(&attr); 03978 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 03979 if (pthread_create(&as->p, &attr, async_wait, as)) { 03980 ast_log(LOG_WARNING, "Failed to start async wait\n"); 03981 free(as); 03982 ast_hangup(chan); 03983 return -1; 03984 } 03985 res = 0; 03986 } 03987 return res; 03988 }

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

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

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

References ast_log(), and LOG_WARNING.

Referenced by ast_async_goto(), and ast_pbx_outgoing_exten().

01922 { 01923 pthread_t t; 01924 pthread_attr_t attr; 01925 if (!c) { 01926 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n"); 01927 return -1; 01928 } 01929 01930 /* Start a new thread, and get something handling this channel. */ 01931 pthread_attr_init(&attr); 01932 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 01933 if (pthread_create(&t, &attr, pbx_thread, c)) { 01934 ast_log(LOG_WARNING, "Failed to create new channel thread\n"); 01935 return -1; 01936 } 01937 return 0; 01938 }

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

02230 { 02231 struct ast_app *tmp, *prev, *cur; 02232 char tmps[80]; 02233 if (ast_mutex_lock(&applock)) { 02234 ast_log(LOG_ERROR, "Unable to lock application list\n"); 02235 return -1; 02236 } 02237 tmp = apps; 02238 while(tmp) { 02239 if (!strcasecmp(app, tmp->name)) { 02240 ast_log(LOG_WARNING, "Already have an application '%s'\n", app); 02241 ast_mutex_unlock(&applock); 02242 return -1; 02243 } 02244 tmp = tmp->next; 02245 } 02246 tmp = malloc(sizeof(struct ast_app)); 02247 if (tmp) { 02248 memset(tmp, 0, sizeof(struct ast_app)); 02249 strncpy(tmp->name, app, sizeof(tmp->name)-1); 02250 tmp->execute = execute; 02251 tmp->synopsis = synopsis; 02252 tmp->description = description; 02253 /* Store in alphabetical order */ 02254 cur = apps; 02255 prev = NULL; 02256 while(cur) { 02257 if (strcasecmp(tmp->name, cur->name) < 0) 02258 break; 02259 prev = cur; 02260 cur = cur->next; 02261 } 02262 if (prev) { 02263 tmp->next = prev->next; 02264 prev->next = tmp; 02265 } else { 02266 tmp->next = apps; 02267 apps = tmp; 02268 } 02269 } else { 02270 ast_log(LOG_ERROR, "Out of memory\n"); 02271 ast_mutex_unlock(&applock); 02272 return -1; 02273 } 02274 if (option_verbose > 1) 02275 ast_verbose( VERBOSE_PREFIX_2 "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps))); 02276 ast_mutex_unlock(&applock); 02277 return 0; 02278 }

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

02281 { 02282 struct ast_switch *tmp, *prev=NULL; 02283 if (ast_mutex_lock(&switchlock)) { 02284 ast_log(LOG_ERROR, "Unable to lock switch lock\n"); 02285 return -1; 02286 } 02287 tmp = switches; 02288 while(tmp) { 02289 if (!strcasecmp(tmp->name, sw->name)) 02290 break; 02291 prev = tmp; 02292 tmp = tmp->next; 02293 } 02294 if (tmp) { 02295 ast_mutex_unlock(&switchlock); 02296 ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name); 02297 return -1; 02298 } 02299 sw->next = NULL; 02300 if (prev) 02301 prev->next = sw; 02302 else 02303 switches = sw; 02304 ast_mutex_unlock(&switchlock); 02305 return 0; 02306 }

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

References HELPER_SPAWN.

Referenced by ast_pbx_run().

01690 { 01691 return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_SPAWN); 01692 }

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

References ast_mutex_unlock, and ast_context::lock.

04695 { 04696 return ast_mutex_unlock(&con->lock); 04697 }

int ast_unlock_contexts void   ) 
 

Unlocks contexts.

Returns 0 on success, -1 on failure

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

04682 { 04683 return ast_mutex_unlock(&conlock); 04684 }

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

02789 { 02790 struct ast_app *tmp, *tmpl = NULL; 02791 if (ast_mutex_lock(&applock)) { 02792 ast_log(LOG_ERROR, "Unable to lock application list\n"); 02793 return -1; 02794 } 02795 tmp = apps; 02796 while(tmp) { 02797 if (!strcasecmp(app, tmp->name)) { 02798 if (tmpl) 02799 tmpl->next = tmp->next; 02800 else 02801 apps = tmp->next; 02802 if (option_verbose > 1) 02803 ast_verbose( VERBOSE_PREFIX_2 "Unregistered application '%s'\n", tmp->name); 02804 ast_mutex_unlock(&applock); 02805 return 0; 02806 } 02807 tmpl = tmp; 02808 tmp = tmp->next; 02809 } 02810 ast_mutex_unlock(&applock); 02811 return -1; 02812 }

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

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

02309 { 02310 struct ast_switch *tmp, *prev=NULL; 02311 if (ast_mutex_lock(&switchlock)) { 02312 ast_log(LOG_ERROR, "Unable to lock switch lock\n"); 02313 return; 02314 } 02315 tmp = switches; 02316 while(tmp) { 02317 if (tmp == sw) { 02318 if (prev) 02319 prev->next = tmp->next; 02320 else 02321 switches = tmp->next; 02322 tmp->next = NULL; 02323 break; 02324 } 02325 prev = tmp; 02326 tmp = tmp->next; 02327 } 02328 ast_mutex_unlock(&switchlock); 02329 }

struct ast_exten* ast_walk_context_extensions struct ast_context con,
struct ast_exten priority
 

Definition at line 4786 of file pbx.c.

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

04788 { 04789 if (!exten) 04790 return con ? con->root : NULL; 04791 else 04792 return exten->next; 04793 }

struct ast_ignorepat* ast_walk_context_ignorepats struct ast_context con,
struct ast_ignorepat ip
 

Definition at line 4822 of file pbx.c.

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

04824 { 04825 if (!ip) 04826 return con ? con->ignorepats : NULL; 04827 else 04828 return ip->next; 04829 }

struct ast_include* ast_walk_context_includes struct ast_context con,
struct ast_include inc
 

Definition at line 4813 of file pbx.c.

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

Referenced by ast_context_verify_includes().

04815 { 04816 if (!inc) 04817 return con ? con->includes : NULL; 04818 else 04819 return inc->next; 04820 }

struct ast_sw* ast_walk_context_switches struct ast_context con,
struct ast_sw sw
 

Definition at line 4795 of file pbx.c.

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

04797 { 04798 if (!sw) 04799 return con ? con->alts : NULL; 04800 else 04801 return sw->next; 04802 }

struct ast_context* ast_walk_contexts struct ast_context con  ) 
 

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

04779 { 04780 if (!con) 04781 return contexts; 04782 else 04783 return con->next; 04784 }

struct ast_exten* ast_walk_extension_priorities struct ast_exten exten,
struct ast_exten priority
 

Definition at line 4804 of file pbx.c.

References ast_exten::peer.

04806 { 04807 if (!priority) 04808 return exten; 04809 else 04810 return priority->peer; 04811 }

void pbx_builtin_clear_globals void   ) 
 

Definition at line 4538 of file pbx.c.

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

04539 { 04540 struct ast_var_t *vardata; 04541 while (!AST_LIST_EMPTY(&globals)) { 04542 vardata = AST_LIST_FIRST(&globals); 04543 AST_LIST_REMOVE_HEAD(&globals, entries); 04544 ast_var_delete(vardata); 04545 } 04546 }

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

00385 { 00386 /* This function is special. It saves the stack so that no matter 00387 how many times it is called, it returns to the same place */ 00388 int res; 00389 00390 char *saved_c_appl; 00391 char *saved_c_data; 00392 00393 int stack = c->stack; 00394 int (*execute)(struct ast_channel *chan, void *data) = app->execute; 00395 if (newstack && stack > AST_CHANNEL_MAX_STACK - 2) { 00396 /* Don't allow us to go over the max number of stacks we 00397 permit saving. */ 00398 ast_log(LOG_WARNING, "Stack overflow, cannot create another stack\n"); 00399 return -1; 00400 } 00401 if (newstack && (res = setjmp(c->jmp[++c->stack]))) { 00402 /* Okay, here's where it gets weird. If newstack is non-zero, 00403 then we increase the stack increment, but setjmp is not going 00404 to return until longjmp is called -- when the application 00405 exec'd is finished running. */ 00406 if (res == 1) 00407 res = 0; 00408 if (c->stack != stack + 1) 00409 ast_log(LOG_WARNING, "Stack returned to an unexpected place!\n"); 00410 else if (c->app[c->stack]) 00411 ast_log(LOG_WARNING, "Application may have forgotten to free its memory\n"); 00412 c->stack = stack; 00413 return res; 00414 } else { 00415 if (c->cdr) 00416 ast_cdr_setapp(c->cdr, app->name, data); 00417 00418 // save channel values 00419 saved_c_appl= c->appl; 00420 saved_c_data= c->data; 00421 00422 c->appl = app->name; 00423 c->data = data; 00424 res = execute(c, data); 00425 // restore channel values 00426 c->appl= saved_c_appl; 00427 c->data= saved_c_data; 00428 00429 /* Any application that returns, we longjmp back, just in case. */ 00430 if (c->stack != stack + 1) 00431 ast_log(LOG_WARNING, "Stack is not at expected value\n"); 00432 longjmp(c->jmp[stack+1], res); 00433 /* Never returns */ 00434 } 00435 }

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

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

00448 { 00449 struct ast_app *tmp; 00450 if (ast_mutex_lock(&applock)) { 00451 ast_log(LOG_WARNING, "Unable to obtain application lock\n"); 00452 return NULL; 00453 } 00454 tmp = apps; 00455 while(tmp) { 00456 if (!strcasecmp(tmp->name, app)) 00457 break; 00458 tmp = tmp->next; 00459 } 00460 ast_mutex_unlock(&applock); 00461 return tmp; 00462 }

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

Definition at line 979 of file pbx.c.

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

00980 { 00981 char *cp4; 00982 const char *tmp, *whereweare; 00983 int length; 00984 char workspace[256]; 00985 char ltmp[256], var[256]; 00986 char *nextvar, *nextexp; 00987 char *vars, *vare; 00988 int pos, brackets, needsub, len; 00989 00990 /* Substitutes variables into cp2, based on string cp1, and assuming cp2 to be 00991 zero-filled */ 00992 whereweare=tmp=cp1; 00993 while(!ast_strlen_zero(whereweare) && count) { 00994 /* Assume we're copying the whole remaining string */ 00995 pos = strlen(whereweare); 00996 00997 /* Look for a variable */ 00998 nextvar = strstr(whereweare, "${"); 00999 01000 nextexp = strstr(whereweare, "$["); 01001 01002 if (nextvar && nextexp) { 01003 if (nextvar < nextexp) 01004 nextexp = NULL; 01005 else 01006 nextvar = NULL; 01007 } 01008 01009 /* If there is one, we only go that far */ 01010 if (nextvar) 01011 pos = nextvar - whereweare; 01012 else if (nextexp) 01013 pos = nextexp - whereweare; 01014 01015 /* Can't copy more than 'count' bytes */ 01016 if (pos > count) 01017 pos = count; 01018 01019 /* Copy that many bytes */ 01020 memcpy(cp2, whereweare, pos); 01021 01022 count -= pos; 01023 cp2 += pos; 01024 whereweare += pos; 01025 01026 if (nextvar) { 01027 /* We have a variable. Find the start and end, and determine 01028 if we are going to have to recursively call ourselves on the 01029 contents */ 01030 vars = vare = nextvar + 2; 01031 brackets = 1; 01032 needsub = 0; 01033 01034 /* Find the end of it */ 01035 while(brackets && *vare) { 01036 if ((vare[0] == '$') && (vare[1] == '{')) { 01037 needsub++; 01038 brackets++; 01039 } else if (vare[0] == '}') { 01040 brackets--; 01041 } else if ((vare[0] == '$') && (vare[1] == '[')) 01042 needsub++; 01043 vare++; 01044 } 01045 if (brackets) 01046 ast_log(LOG_NOTICE, "Error in extension logic (missing '}')\n"); 01047 len = vare - vars - 1; 01048 01049 /* Skip totally over variable name */ 01050 whereweare += ( len + 3); 01051 01052 /* Store variable name (and truncate) */ 01053 memset(var, 0, sizeof(var)); 01054 strncpy(var, vars, sizeof(var) - 1); 01055 var[len] = '\0'; 01056 01057 /* Substitute if necessary */ 01058 if (needsub) { 01059 memset(ltmp, 0, sizeof(ltmp)); 01060 pbx_substitute_variables_helper(c, var, ltmp, sizeof(ltmp) - 1); 01061 vars = ltmp; 01062 } else { 01063 vars = var; 01064 } 01065 01066 /* Retrieve variable value */ 01067 strcpy(workspace, ""); 01068 pbx_substitute_variables_temp(c,vars,&cp4, workspace, sizeof(workspace)); 01069 if (cp4) { 01070 length = strlen(cp4); 01071 if (length > count) 01072 length = count; 01073 memcpy(cp2, cp4, length); 01074 count -= length; 01075 cp2 += length; 01076 } 01077 01078 } else if (nextexp) { 01079 /* We have an expression. Find the start and end, and determine 01080 if we are going to have to recursively call ourselves on the 01081 contents */ 01082 vars = vare = nextexp + 2; 01083 brackets = 1; 01084 needsub = 0; 01085 01086 /* Find the end of it */ 01087 while(brackets && *vare) { 01088 if ((vare[0] == '$') && (vare[1] == '[')) { 01089 needsub++; 01090 brackets++; 01091 } else if (vare[0] == ']') { 01092 brackets--; 01093 } else if ((vare[0] == '$') && (vare[1] == '{')) 01094 needsub++; 01095 vare++; 01096 } 01097 if (brackets) 01098 ast_log(LOG_NOTICE, "Error in extension logic (missing ']')\n"); 01099 len = vare - vars - 1; 01100 01101 /* Skip totally over variable name */ 01102 whereweare += ( len + 3); 01103 01104 /* Store variable name (and truncate) */ 01105 memset(var, 0, sizeof(var)); 01106 strncpy(var, vars, sizeof(var) - 1); 01107 var[len] = '\0'; 01108 01109 /* Substitute if necessary */ 01110 if (needsub) { 01111 memset(ltmp, 0, sizeof(ltmp)); 01112 pbx_substitute_variables_helper(c, var, ltmp, sizeof(ltmp) - 1); 01113 vars = ltmp; 01114 } else { 01115 vars = var; 01116 } 01117 01118 /* Evaluate expression */ 01119 cp4 = ast_expr(vars); 01120 01121 ast_log(LOG_DEBUG, "Expression is '%s'\n", cp4); 01122 01123 if (cp4) { 01124 length = strlen(cp4); 01125 if (length > count) 01126 length = count; 01127 memcpy(cp2, cp4, length); 01128 count -= length; 01129 cp2 += length; 01130 free(cp4); 01131 } 01132 01133 } else 01134 break; 01135 } 01136 }


Generated on Sat Jun 12 16:41:44 2004 for Asterisk by doxygen 1.3.7