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

pbx.c File Reference

#include <asterisk/lock.h>
#include <asterisk/cli.h>
#include <asterisk/pbx.h>
#include <asterisk/channel.h>
#include <asterisk/options.h>
#include <asterisk/logger.h>
#include <asterisk/file.h>
#include <asterisk/callerid.h>
#include <asterisk/cdr.h>
#include <asterisk/config.h>
#include <asterisk/term.h>
#include <asterisk/manager.h>
#include <asterisk/ast_expr.h>
#include <asterisk/channel_pvt.h>
#include <asterisk/linkedlists.h>
#include <asterisk/say.h>
#include <asterisk/utils.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <setjmp.h>
#include <ctype.h>
#include <errno.h>
#include <time.h>
#include <sys/time.h>
#include "asterisk.h"

Go to the source code of this file.

Data Structures

struct  ast_exten
struct  ast_include
struct  ast_sw
struct  ast_ignorepat
struct  ast_context
struct  ast_app
struct  ast_state_cb
struct  ast_hint
struct  pbx_builtin
struct  async_stat
struct  app_tmp

Defines

#define EXT_DATA_SIZE   8192
#define AST_PBX_MAX_STACK   64
#define HELPER_EXISTS   0
#define HELPER_SPAWN   1
#define HELPER_EXEC   2
#define HELPER_CANMATCH   3
#define HELPER_MATCHMORE   4
#define EXTENSION_MATCH_CORE(data, pattern, match)
#define STATUS_NO_CONTEXT   1
#define STATUS_NO_EXTENSION   2
#define STATUS_NO_PRIORITY   3
#define STATUS_SUCCESS   4
#define FIND_NEXT
#define LOG

Functions

int pbx_builtin_setvar (struct ast_channel *, void *)
void pbx_builtin_setvar_helper (struct ast_channel *chan, char *name, char *value)
char * pbx_builtin_getvar_helper (struct ast_channel *chan, char *name)
 AST_MUTEX_DEFINE_STATIC (applock)
 AST_MUTEX_DEFINE_STATIC (conlock)
 AST_MUTEX_DEFINE_STATIC (switchlock)
 AST_MUTEX_DEFINE_STATIC (hintlock)
int pbx_exec (struct ast_channel *c, struct ast_app *app, void *data, int newstack)
 executes an application
ast_apppbx_findapp (char *app)
 Look up an application.
int ast_extension_match (char *pattern, char *data)
 Determine if a given extension matches a given pattern (in NXX format).
ast_contextast_context_find (char *name)
 Find a context.
void pbx_substitute_variables_helper (struct ast_channel *c, const char *cp1, char *cp2, int count)
int ast_extension_state (struct ast_channel *c, char *context, char *exten)
 Uses hint and devicestate callback to get the state of an extension.
int ast_device_state_changed (const char *fmt,...)
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 hintsize, struct ast_channel *c, char *context, char *exten)
 If an extension exists, return non-zero.
int ast_exists_extension (struct ast_channel *c, char *context, char *exten, int priority, char *callerid)
 If an extension exists, return non-zero.
int ast_canmatch_extension (struct ast_channel *c, char *context, char *exten, int priority, char *callerid)
 Looks for a valid matching extension.
int ast_matchmore_extension (struct ast_channel *c, char *context, char *exten, int priority, char *callerid)
 Looks to see if adding anything to this extension might match something. (exists ^ canmatch).
int ast_spawn_extension (struct ast_channel *c, char *context, char *exten, int priority, char *callerid)
 Launch a new extension (i.e. new stack).
int ast_pbx_run (struct ast_channel *c)
 Execute the PBX in the current thread.
int ast_pbx_start (struct ast_channel *c)
 Create a new thread and start the PBX (or whatever).
int ast_context_remove_include (char *context, char *include, char *registrar)
 Removes an include.
int ast_context_remove_include2 (struct ast_context *con, char *include, char *registrar)
 Removes an include by an ast_context structure.
int ast_context_remove_switch (char *context, char *sw, char *data, char *registrar)
 Remove a switch.
int ast_context_remove_switch2 (struct ast_context *con, char *sw, char *data, char *registrar)
int ast_context_remove_extension (char *context, char *extension, int priority, char *registrar)
 Simply remove extension from context.
int ast_context_remove_extension2 (struct ast_context *con, char *extension, int priority, char *registrar)
int ast_register_application (char *app, int(*execute)(struct ast_channel *, void *), char *synopsis, char *description)
 Add an application. The function 'execute' should return non-zero if the line needs to be hung up.
int ast_register_switch (struct ast_switch *sw)
 Register an alternative switch.
void ast_unregister_switch (struct ast_switch *sw)
 Unregister an alternative switch.
int ast_unregister_application (char *app)
 Remove an application.
ast_contextast_context_create (struct ast_context **extcontexts, char *name, char *registrar)
 Register a new context.
void __ast_context_destroy (struct ast_context *con, char *registrar)
void ast_merge_contexts_and_delete (struct ast_context **extcontexts, char *registrar)
 Merge the temporary contexts into a global contexts list and delete from the global list the ones that are being added.
int ast_context_add_include (char *context, char *include, char *registrar)
 Add an include.
int ast_context_add_include2 (struct ast_context *con, char *value, char *registrar)
 Add an include.
int ast_context_add_switch (char *context, char *sw, char *data, char *registrar)
 Add a switch.
int ast_context_add_switch2 (struct ast_context *con, char *value, char *data, char *registrar)
 Adds a switch (first param is a ast_context).
int ast_context_remove_ignorepat (char *context, char *ignorepat, char *registrar)
int ast_context_remove_ignorepat2 (struct ast_context *con, char *ignorepat, char *registrar)
int ast_context_add_ignorepat (char *con, char *value, char *registrar)
 Add an ignorepat.
int ast_context_add_ignorepat2 (struct ast_context *con, char *value, char *registrar)
int ast_ignore_pattern (char *context, char *pattern)
 Checks to see if a number should be ignored.
int ast_add_extension (char *context, int replace, char *extension, int priority, char *callerid, char *application, void *data, void(*datad)(void *), char *registrar)
int ast_async_goto (struct ast_channel *chan, char *context, char *exten, int priority)
int ast_async_goto_by_name (char *channame, char *context, char *exten, int priority)
int ast_add_extension2 (struct ast_context *con, int replace, char *extension, int priority, char *callerid, char *application, void *data, void(*datad)(void *), char *registrar)
 Add an extension to an extension context, this time with an ast_context *. CallerID is a pattern to match on callerid, or NULL to not care about callerid.
int ast_pbx_outgoing_exten (char *type, int format, void *data, int timeout, char *context, char *exten, int priority, int *reason, int sync, char *callerid, char *variable, 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)
void ast_context_destroy (struct ast_context *con, char *registrar)
 Destroy a context (matches the specified context (or ANY context if NULL).
void pbx_builtin_clear_globals (void)
int load_pbx (void)
int ast_lock_contexts ()
 Locks the contexts.
int ast_unlock_contexts ()
 Unlocks contexts.
int ast_lock_context (struct ast_context *con)
 Locks a given context.
int ast_unlock_context (struct ast_context *con)
 Unlocks the given context.
char * ast_get_context_name (struct ast_context *con)
char * ast_get_extension_name (struct ast_exten *exten)
char * ast_get_include_name (struct ast_include *inc)
char * ast_get_ignorepat_name (struct ast_ignorepat *ip)
int ast_get_extension_priority (struct ast_exten *exten)
char * ast_get_context_registrar (struct ast_context *c)
char * ast_get_extension_registrar (struct ast_exten *e)
char * ast_get_include_registrar (struct ast_include *i)
char * ast_get_ignorepat_registrar (struct ast_ignorepat *ip)
int ast_get_extension_matchcid (struct ast_exten *e)
char * ast_get_extension_cidmatch (struct ast_exten *e)
char * ast_get_extension_app (struct ast_exten *e)
void * ast_get_extension_app_data (struct ast_exten *e)
char * ast_get_switch_name (struct ast_sw *sw)
char * ast_get_switch_data (struct ast_sw *sw)
char * ast_get_switch_registrar (struct ast_sw *sw)
ast_contextast_walk_contexts (struct ast_context *con)
ast_extenast_walk_context_extensions (struct ast_context *con, struct ast_exten *exten)
ast_swast_walk_context_switches (struct ast_context *con, struct ast_sw *sw)
ast_extenast_walk_extension_priorities (struct ast_exten *exten, struct ast_exten *priority)
ast_includeast_walk_context_includes (struct ast_context *con, struct ast_include *inc)
ast_ignorepatast_walk_context_ignorepats (struct ast_context *con, struct ast_ignorepat *ip)
int ast_context_verify_includes (struct ast_context *con)
 Verifies includes in an ast_contect structure.

Variables

ast_switchswitches = NULL
ast_hinthints = NULL
ast_state_cbstatecbs = NULL


Define Documentation

#define AST_PBX_MAX_STACK   64
 

Definition at line 484 of file pbx.c.

#define EXT_DATA_SIZE   8192
 

Definition at line 55 of file pbx.c.

#define EXTENSION_MATCH_CORE data,
pattern,
match   ) 
 

Definition at line 572 of file pbx.c.

Referenced by ast_extension_match().

#define FIND_NEXT
 

Value:

do { \ c = info; \ while(*c && (*c != '|')) c++; \ if (*c) { *c = '\0'; c++; } else c = NULL; \ } while(0)
Definition at line 3044 of file pbx.c.

#define HELPER_CANMATCH   3
 

Definition at line 489 of file pbx.c.

Referenced by ast_canmatch_extension().

#define HELPER_EXEC   2
 

Definition at line 488 of file pbx.c.

#define HELPER_EXISTS   0
 

Definition at line 486 of file pbx.c.

Referenced by ast_exists_extension().

#define HELPER_MATCHMORE   4
 

Definition at line 490 of file pbx.c.

Referenced by ast_matchmore_extension().

#define HELPER_SPAWN   1
 

Definition at line 487 of file pbx.c.

Referenced by ast_spawn_extension().

#define LOG
 

Referenced by ast_add_extension2().

#define STATUS_NO_CONTEXT   1
 

Definition at line 692 of file pbx.c.

#define STATUS_NO_EXTENSION   2
 

Definition at line 693 of file pbx.c.

#define STATUS_NO_PRIORITY   3
 

Definition at line 694 of file pbx.c.

#define STATUS_SUCCESS   4
 

Definition at line 695 of file pbx.c.


Function Documentation

void __ast_context_destroy struct ast_context con,
char *  registrar
 

Definition at line 4252 of file pbx.c.

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

Referenced by ast_context_destroy(), and ast_merge_contexts_and_delete().

04253 { 04254 struct ast_context *tmp, *tmpl=NULL; 04255 struct ast_include *tmpi, *tmpil= NULL; 04256 struct ast_sw *sw, *swl= NULL; 04257 struct ast_exten *e, *el, *en; 04258 struct ast_ignorepat *ipi, *ipl = NULL; 04259 04260 ast_mutex_lock(&conlock); 04261 tmp = contexts; 04262 while(tmp) { 04263 if (((tmp->name && con && con->name && !strcasecmp(tmp->name, con->name)) || !con) && 04264 (!registrar || !strcasecmp(registrar, tmp->registrar))) { 04265 /* Okay, let's lock the structure to be sure nobody else 04266 is searching through it. */ 04267 if (ast_mutex_lock(&tmp->lock)) { 04268 ast_log(LOG_WARNING, "Unable to lock context lock\n"); 04269 return; 04270 } 04271 if (tmpl) 04272 tmpl->next = tmp->next; 04273 else 04274 contexts = tmp->next; 04275 /* Okay, now we're safe to let it go -- in a sense, we were 04276 ready to let it go as soon as we locked it. */ 04277 ast_mutex_unlock(&tmp->lock); 04278 for (tmpi = tmp->includes; tmpi; ) { 04279 /* Free includes */ 04280 tmpil = tmpi; 04281 tmpi = tmpi->next; 04282 free(tmpil); 04283 } 04284 for (ipi = tmp->ignorepats; ipi; ) { 04285 /* Free ignorepats */ 04286 ipl = ipi; 04287 ipi = ipi->next; 04288 free(ipl); 04289 } 04290 for (sw = tmp->alts; sw; ) { 04291 /* Free switches */ 04292 swl = sw; 04293 sw = sw->next; 04294 free(swl); 04295 swl = sw; 04296 } 04297 for (e = tmp->root; e;) { 04298 for (en = e->peer; en;) { 04299 el = en; 04300 en = en->peer; 04301 destroy_exten(el); 04302 } 04303 el = e; 04304 e = e->next; 04305 destroy_exten(el); 04306 } 04307 ast_mutex_destroy(&tmp->lock); 04308 free(tmp); 04309 if (!con) { 04310 /* Might need to get another one -- restart */ 04311 tmp = contexts; 04312 tmpl = NULL; 04313 tmpil = NULL; 04314 continue; 04315 } 04316 ast_mutex_unlock(&conlock); 04317 return; 04318 } 04319 tmpl = tmp; 04320 tmp = tmp->next; 04321 } 04322 ast_mutex_unlock(&conlock); 04323 }

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

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

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

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

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

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

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

References ast_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().

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

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

Definition at line 3662 of file pbx.c.

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

Referenced by ast_async_goto_by_name().

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

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

Definition at line 3723 of file pbx.c.

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

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

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

Looks for a valid matching extension.

Parameters:
c not really important
context context to serach within
exten extension to check
priority priority of extension path
callerid callerid of extension being searched for If "exten" *could be* a valid extension in this context with or without some more digits, return non-zero. Basically, when this returns 0, no matter what you add to exten, it's not going to be a valid extension anymore
Definition at line 1745 of file pbx.c.

References HELPER_CANMATCH.

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

int ast_context_add_ignorepat char *  context,
char *  ignorepat,
char *  registrar
 

Add an ignorepat.

Parameters:
context which context to add the ignorpattern to
ignorpat ignorepattern to set up for the extension
registrar registrar of the ignore pattern Adds an ignore pattern to a particular context. Returns 0 on success, -1 on failure
Definition at line 3555 of file pbx.c.

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

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

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

Definition at line 3579 of file pbx.c.

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

Referenced by ast_context_add_ignorepat().

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

int ast_context_add_include char *  context,
char *  include,
char *  registrar
 

Add an include.

Parameters:
context context to add include to
include new include to add
registrar who's registering it Adds an include taking a char * string as the context parameter Returns 0 on success, -1 on error
Definition at line 3016 of file pbx.c.

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

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

int ast_context_add_include2 struct ast_context con,
char *  include,
char *  registrar
 

Add an include.

Parameters:
con context to add the include to
include include to add
registrar who registered the context Adds an include taking a struct ast_context as the first parameter Returns 0 on success, -1 on failure
Definition at line 3336 of file pbx.c.

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

Referenced by ast_context_add_include().

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

int ast_context_add_switch char *  context,
char *  sw,
char *  data,
char *  registrar
 

Add a switch.

Parameters:
context context to which to add the switch
sw switch to add
data data to pass to switch
registrar whoever registered the switch This function registers a switch with the asterisk switch architecture It returns 0 on success, -1 on failure
Definition at line 3402 of file pbx.c.

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

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

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

Adds a switch (first param is a ast_context).

See ast_context_add_switch() Definition at line 3437 of file pbx.c.

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

Referenced by ast_context_add_switch().

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

struct ast_context* ast_context_create struct ast_context **  extcontexts,
char *  name,
char *  registrar
 

Register a new context.

Parameters:
extcontexts pointer to the ast_context structure pointer
name name of the new context
registrar registrar of the context This will first search for a context with your name. If it exists already, it will not create a new one. If it does not exist, it will create a new one with the given name and registrar. It returns NULL on failure, and an ast_context structure on success
Definition at line 2939 of file pbx.c.

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

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

void ast_context_destroy struct ast_context con,
char *  registrar
 

Destroy a context (matches the specified context (or ANY context if NULL).

Parameters:
con context to destroy
registrar who registered it You can optionally leave out either parameter. It will find it based on either the ast_context or the registrar name. Returns nothing
Definition at line 4325 of file pbx.c.

References __ast_context_destroy().

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

struct ast_context* ast_context_find char *  name  ) 
 

Find a context.

Parameters:
name name of the context to find Will search for the context with the given name. Returns the ast_context on success, NULL on failure.
Definition at line 675 of file pbx.c.

References ast_mutex_lock, ast_mutex_unlock, and ast_context::next.

Referenced by ast_context_verify_includes(), and ast_ignore_pattern().

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

int ast_context_remove_extension char *  context,
char *  extension,
int  priority,
char *  registrar
 

Simply remove extension from context.

Parameters:
context context to remove extension from
extension which extension to remove
priority priority of extension to remove
registrar registrar of the extension This function removes an extension from a given context. Returns 0 on success, -1 on failure
Definition at line 2153 of file pbx.c.

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

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

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

Definition at line 2189 of file pbx.c.

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

Referenced by ast_context_remove_extension().

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

int ast_context_remove_ignorepat char *  context,
char *  ignorepat,
char *  registrar
 

Parameters:
context context from which to remove the pattern
ignorepat the pattern to remove
registrar the registrar of the ignore pattern This removes the given ignorepattern Returns 0 on success, -1 on failure
Definition at line 3496 of file pbx.c.

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

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

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

Definition at line 3520 of file pbx.c.

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

Referenced by ast_context_remove_ignorepat().

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

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

Removes an include.

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

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

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

int ast_context_remove_include2 struct ast_context con,
char *  include,
char *  registrar
 

Removes an include by an ast_context structure.

See add_include2 Definition at line 2045 of file pbx.c.

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

Referenced by ast_context_remove_include().

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

int ast_context_remove_switch char *  context,
char *  sw,
char *  data,
char *  registrar
 

Remove a switch.

Removes a switch with the given parameters Returns 0 on success, -1 on failure Definition at line 2081 of file pbx.c.

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

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

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

Definition at line 2117 of file pbx.c.

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

Referenced by ast_context_remove_switch().

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

int ast_context_verify_includes struct ast_context con  ) 
 

Verifies includes in an ast_contect structure.

Parameters:
con context in which to verify the includes Returns 0 if no problems found, -1 if there were any missing context
Definition at line 5038 of file pbx.c.

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

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

int ast_device_state_changed const char *  fmt,
  ...
 

Definition at line 1425 of file pbx.c.

References ast_get_extension_app(), AST_MAX_EXTENSION, ast_mutex_lock, ast_mutex_unlock, ast_state_cb::callback, hints, and statecbs.

01426 { 01427 struct ast_hint *list; 01428 struct ast_state_cb *cblist; 01429 char hint[AST_MAX_EXTENSION] = ""; 01430 char device[AST_MAX_EXTENSION]; 01431 char *cur, *rest; 01432 int state; 01433 01434 va_list ap; 01435 01436 va_start(ap, fmt); 01437 vsnprintf(device, sizeof(device), fmt, ap); 01438 va_end(ap); 01439 01440 rest = strchr(device, '-'); 01441 if (rest) { 01442 *rest = 0; 01443 } 01444 01445 ast_mutex_lock(&hintlock); 01446 01447 list = hints; 01448 01449 while (list) { 01450 01451 strncpy(hint, ast_get_extension_app(list->exten), sizeof(hint) - 1); 01452 cur = hint; 01453 do { 01454 rest = strchr(cur, '&'); 01455 if (rest) { 01456 *rest = 0; 01457 rest++; 01458 } 01459 01460 if (!strcmp(cur, device)) { 01461 /* Found extension execute callbacks */ 01462 state = ast_extension_state2(list->exten); 01463 if ((state != -1) && (state != list->laststate)) { 01464 /* For general callbacks */ 01465 cblist = statecbs; 01466 while (cblist) { 01467 cblist->callback(list->exten->parent->name, list->exten->exten, state, cblist->data); 01468 cblist = cblist->next; 01469 } 01470 01471 /* For extension callbacks */ 01472 cblist = list->callbacks; 01473 while (cblist) { 01474 cblist->callback(list->exten->parent->name, list->exten->exten, state, cblist->data); 01475 cblist = cblist->next; 01476 } 01477 01478 list->laststate = state; 01479 } 01480 break; 01481 } 01482 cur = rest; 01483 } while (cur); 01484 list = list->next; 01485 } 01486 ast_mutex_unlock(&hintlock); 01487 return 1; 01488 }

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

If an extension exists, return non-zero.

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

References HELPER_EXISTS.

Referenced by ast_pbx_outgoing_exten(), and ast_pbx_run().

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

int ast_extension_match char *  pattern,
char *  extension
 

Determine if a given extension matches a given pattern (in NXX format).

Parameters:
pattern pattern to match
extension extension to check against the pattern. Checks whether or not the given extension matches the given pattern. Returns 1 on match, 0 on failure
Definition at line 642 of file pbx.c.

References EXTENSION_MATCH_CORE.

Referenced by ast_ignore_pattern().

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

int ast_extension_state struct ast_channel c,
char *  context,
char *  exten
 

Uses hint and devicestate callback to get the state of an extension.

Parameters:
c this is not important
context which context to look in
exten which extension to get state Returns extension state !! = AST_EXTENSION_???
Definition at line 1414 of file pbx.c.
01415 { 01416 struct ast_exten *e; 01417 01418 e = ast_hint_extension(c, context, exten); 01419 if (!e) 01420 return -1; 01421 01422 return ast_extension_state2(e); 01423 }

int ast_extension_state_add char *  context,
char *  exten,
ast_state_cb_type  callback,
void *  data
 

Registers a state change callback.

Parameters:
context which context to look in
exten which extension to get state
callback callback to call if state changed
data to pass to callback The callback is called if the state for extension is changed Return -1 on failure, ID on success
Definition at line 1490 of file pbx.c.

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

Referenced by init_manager().

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

int ast_extension_state_del int  id,
ast_state_cb_type  callback
 

Deletes a registered state change callback by ID.

Parameters:
id of the callback to delete Removes the callback from list of callbacks Return 0 on success, -1 on failure
Definition at line 1569 of file pbx.c.

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

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

char* ast_get_context_name struct ast_context con  ) 
 

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

04900 { 04901 return con ? con->name : NULL; 04902 }

char* ast_get_context_registrar struct ast_context c  ) 
 

Definition at line 4927 of file pbx.c.

References ast_context::registrar.

04928 { 04929 return c ? c->registrar : NULL; 04930 }

char* ast_get_extension_app struct ast_exten e  ) 
 

Definition at line 4957 of file pbx.c.

References ast_exten::app.

Referenced by ast_device_state_changed(), and ast_get_hint().

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

void* ast_get_extension_app_data struct ast_exten e  ) 
 

Definition at line 4962 of file pbx.c.

References ast_exten::data.

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

char* ast_get_extension_cidmatch struct ast_exten e  ) 
 

Definition at line 4952 of file pbx.c.

References ast_exten::cidmatch.

04953 { 04954 return e ? e->cidmatch : NULL; 04955 }

int ast_get_extension_matchcid struct ast_exten e  ) 
 

Definition at line 4947 of file pbx.c.

References ast_exten::matchcid.

04948 { 04949 return e ? e->matchcid : 0; 04950 }

char* ast_get_extension_name struct ast_exten exten  ) 
 

Definition at line 4904 of file pbx.c.

References ast_exten::exten.

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

int ast_get_extension_priority struct ast_exten exten  ) 
 

Definition at line 4919 of file pbx.c.

References ast_exten::priority.

04920 { 04921 return exten ? exten->priority : -1; 04922 }

char* ast_get_extension_registrar struct ast_exten e  ) 
 

Definition at line 4932 of file pbx.c.

References ast_exten::registrar.

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

int ast_get_hint char *  hint,
int  maxlen,
struct ast_channel c,
char *  context,
char *  exten
 

If an extension exists, return non-zero.

Parameters:
hint buffer for hint
maxlen size of hint buffer
c this is not important
context which context to look in
exten which extension to search for If an extension within the given context with the priority PRIORITY_HINT is found a non zero value will be returned. Otherwise, 0 is returned.
Definition at line 1729 of file pbx.c.

References ast_get_extension_app().

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

char* ast_get_ignorepat_name struct ast_ignorepat ip  ) 
 

Definition at line 4914 of file pbx.c.

References ast_ignorepat::pattern.

04915 { 04916 return ip ? ip->pattern : NULL; 04917 }

char* ast_get_ignorepat_registrar struct ast_ignorepat ip  ) 
 

Definition at line 4942 of file pbx.c.

References ast_ignorepat::registrar.

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

char* ast_get_include_name struct ast_include inc  ) 
 

Definition at line 4909 of file pbx.c.

References ast_include::name.

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

char* ast_get_include_registrar struct ast_include i  ) 
 

Definition at line 4937 of file pbx.c.

References ast_include::registrar.

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

char* ast_get_switch_data struct ast_sw sw  ) 
 

Definition at line 4972 of file pbx.c.

References ast_sw::data.

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

char* ast_get_switch_name struct ast_sw sw  ) 
 

Definition at line 4967 of file pbx.c.

References ast_sw::name.

04968 { 04969 return sw ? sw->name : NULL; 04970 }

char* ast_get_switch_registrar struct ast_sw sw  ) 
 

Definition at line 4977 of file pbx.c.

References ast_sw::registrar.

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

int ast_ignore_pattern char *  context,
char *  pattern
 

Checks to see if a number should be ignored.

Parameters:
context context to search within
extension to check whether it should be ignored or not Check if a number should be ignored with respect to dialtone cancellation. Returns 0 if the pattern should not be ignored, or non-zero if the pattern should be ignored
Definition at line 3614 of file pbx.c.

References ast_context_find(), and ast_extension_match().

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

int ast_lock_context struct ast_context con  ) 
 

Locks a given context.

Parameters:
con context to lock Locks the context. Returns 0 on success, -1 on failure
Definition at line 4886 of file pbx.c.

References ast_mutex_lock, and ast_context::lock.

04887 { 04888 return ast_mutex_lock(&con->lock); 04889 }

int ast_lock_contexts void   ) 
 

Locks the contexts.

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

04874 { 04875 return ast_mutex_lock(&conlock); 04876 }

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

Looks to see if adding anything to this extension might match something. (exists ^ canmatch).

Parameters:
c not really important
context context to serach within
exten extension to check
priority priority of extension path
callerid callerid of extension being searched for If "exten" *could match* a valid extension in this context with some more digits, return non-zero. Does NOT return non-zero if this is an exact-match only. Basically, when this returns 0, no matter what you add to exten, it's not going to be a valid extension anymore
Definition at line 1750 of file pbx.c.

References HELPER_MATCHMORE.

Referenced by ast_pbx_run().

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

void ast_merge_contexts_and_delete struct ast_context **  extcontexts,
char *  registrar
 

Merge the temporary contexts into a global contexts list and delete from the global list the ones that are being added.

Parameters:
extcontexts pointer to the ast_context structure pointer
registar of the context; if it's set the routine will delete all contexts that belong to that registrar; if NULL only the contexts that are specified in extcontexts
Definition at line 2984 of file pbx.c.

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

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

AST_MUTEX_DEFINE_STATIC hintlock   ) 
 

AST_MUTEX_DEFINE_STATIC switchlock   ) 
 

AST_MUTEX_DEFINE_STATIC conlock   ) 
 

AST_MUTEX_DEFINE_STATIC applock   ) 
 

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

Definition at line 4154 of file pbx.c.

References ast_channel::_state, ast_hangup(), ast_log(), ast_pthread_create(), 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.

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

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

Definition at line 4036 of file pbx.c.

References __ast_request_and_dial(), ast_channel::_state, ast_channel_alloc(), ast_exists_extension(), ast_hangup(), ast_log(), ast_pbx_run(), ast_pbx_start(), ast_pthread_create(), ast_request_and_dial(), AST_STATE_UP, ast_verbose(), 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.

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

int ast_pbx_run struct ast_channel c  ) 
 

Execute the PBX in the current thread.

Parameters:
c channel to run the pbx on This executes the PBX on a given channel. It allocates a new PBX structure for the channel, and provides all PBX functionality.
Definition at line 1760 of file pbx.c.

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

Referenced by ast_pbx_outgoing_exten().

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

int ast_pbx_start struct ast_channel c  ) 
 

Create a new thread and start the PBX (or whatever).

Parameters:
c channel to start the pbx on Starts a pbx thread on a given channel It returns -1 on failure, and 0 on success
Definition at line 1985 of file pbx.c.

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

Referenced by ast_async_goto(), and ast_pbx_outgoing_exten().

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

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

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

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

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

Referenced by load_pbx().

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

int ast_register_switch struct ast_switch sw  ) 
 

Register an alternative switch.

Parameters:
sw switch to register This function registers a populated ast_switch structure with the asterisk switching architecture. It returns 0 on success, and other than 0 on failure
Definition at line 2344 of file pbx.c.

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

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

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

Launch a new extension (i.e. new stack).

Parameters:
c not important
context which context to generate the extension within
exten new extension to add
priority priority of new extension
callerid callerid of extension This adds a new extension to the asterisk extension list. It returns 0 on success, -1 on failure.
Definition at line 1755 of file pbx.c.

References HELPER_SPAWN.

Referenced by ast_pbx_run().

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

int ast_unlock_context struct ast_context con  ) 
 

Unlocks the given context.

Parameters:
con context to unlock Unlocks the given context Returns 0 on success, -1 on failure
Definition at line 4891 of file pbx.c.

References ast_mutex_unlock, and ast_context::lock.

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

int ast_unlock_contexts void   ) 
 

Unlocks contexts.

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

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

int ast_unregister_application char *  app  ) 
 

Remove an application.

Parameters:
app name of the application (does not have to be the same string as the one that was registered) This unregisters an application from asterisk's internal registration mechanisms. It returns 0 on success, and -1 on failure.
Definition at line 2913 of file pbx.c.

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

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

void ast_unregister_switch struct ast_switch sw  ) 
 

Unregister an alternative switch.

Parameters:
sw switch to unregister Unregisters a switch from asterisk. Returns nothing
Definition at line 2372 of file pbx.c.

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

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

struct ast_exten* ast_walk_context_extensions struct ast_context con,
struct ast_exten exten
 

Definition at line 4993 of file pbx.c.

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

04995 { 04996 if (!exten) 04997 return con ? con->root : NULL; 04998 else 04999 return exten->next; 05000 }

struct ast_ignorepat* ast_walk_context_ignorepats struct ast_context con,
struct ast_ignorepat ip
 

Definition at line 5029 of file pbx.c.

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

05031 { 05032 if (!ip) 05033 return con ? con->ignorepats : NULL; 05034 else 05035 return ip->next; 05036 }

struct ast_include* ast_walk_context_includes struct ast_context con,
struct ast_include inc
 

Definition at line 5020 of file pbx.c.

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

Referenced by ast_context_verify_includes().

05022 { 05023 if (!inc) 05024 return con ? con->includes : NULL; 05025 else 05026 return inc->next; 05027 }

struct ast_sw* ast_walk_context_switches struct ast_context con,
struct ast_sw sw
 

Definition at line 5002 of file pbx.c.

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

05004 { 05005 if (!sw) 05006 return con ? con->alts : NULL; 05007 else 05008 return sw->next; 05009 }

struct ast_context* ast_walk_contexts struct ast_context con  ) 
 

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

04986 { 04987 if (!con) 04988 return contexts; 04989 else 04990 return con->next; 04991 }

struct ast_exten* ast_walk_extension_priorities struct ast_exten exten,
struct ast_exten priority
 

Definition at line 5011 of file pbx.c.

References ast_exten::peer.

05013 { 05014 if (!priority) 05015 return exten; 05016 else 05017 return priority->peer; 05018 }

int load_pbx void   ) 
 

Definition at line 4843 of file pbx.c.

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

Referenced by main().

04844 { 04845 int x; 04846 04847 /* Initialize the PBX */ 04848 if (option_verbose) { 04849 ast_verbose( "Asterisk PBX Core Initializing\n"); 04850 ast_verbose( "Registering builtin applications:\n"); 04851 } 04852 AST_LIST_HEAD_INIT(&globals); 04853 ast_cli_register(&show_applications_cli); 04854 ast_cli_register(&show_application_cli); 04855 ast_cli_register(&show_dialplan_cli); 04856 ast_cli_register(&show_switches_cli); 04857 04858 /* Register builtin applications */ 04859 for (x=0; x<sizeof(builtins) / sizeof(struct pbx_builtin); x++) { 04860 if (option_verbose) 04861 ast_verbose( VERBOSE_PREFIX_1 "[%s]\n", builtins[x].name); 04862 if (ast_register_application(builtins[x].name, builtins[x].execute, builtins[x].synopsis, builtins[x].description)) { 04863 ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name); 04864 return -1; 04865 } 04866 } 04867 return 0; 04868 }

void pbx_builtin_clear_globals void   ) 
 

Definition at line 4746 of file pbx.c.

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

04747 { 04748 struct ast_var_t *vardata; 04749 while (!AST_LIST_EMPTY(&globals)) { 04750 vardata = AST_LIST_FIRST(&globals); 04751 AST_LIST_REMOVE_HEAD(&globals, entries); 04752 ast_var_delete(vardata); 04753 } 04754 }

char * pbx_builtin_getvar_helper struct ast_channel chan,
char *  name
 

Definition at line 4646 of file pbx.c.

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

04647 { 04648 struct ast_var_t *variables; 04649 struct varshead *headp; 04650 04651 if (chan) 04652 headp=&chan->varshead; 04653 else 04654 headp=&globals; 04655 04656 if (name) { 04657 AST_LIST_TRAVERSE(headp,variables,entries) { 04658 if (!strcmp(name, ast_var_name(variables))) 04659 return ast_var_value(variables); 04660 } 04661 if (headp != &globals) { 04662 /* Check global variables if we haven't already */ 04663 headp = &globals; 04664 AST_LIST_TRAVERSE(headp,variables,entries) { 04665 if (!strcmp(name, ast_var_name(variables))) 04666 return ast_var_value(variables); 04667 } 04668 } 04669 } 04670 return NULL; 04671 }

int pbx_builtin_setvar struct ast_channel ,
void * 
 

Definition at line 4699 of file pbx.c.

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

04700 { 04701 char *name; 04702 char *value; 04703 char *stringp=NULL; 04704 04705 if (!data || ast_strlen_zero(data)) { 04706 ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n"); 04707 return 0; 04708 } 04709 04710 stringp=data; 04711 name=strsep(&stringp,"="); 04712 value=strsep(&stringp,"\0"); 04713 04714 pbx_builtin_setvar_helper(chan,name,value); 04715 04716 return(0); 04717 }

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

Definition at line 4673 of file pbx.c.

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

04674 { 04675 struct ast_var_t *newvariable; 04676 struct varshead *headp; 04677 if (chan) 04678 headp=&chan->varshead; 04679 else 04680 headp=&globals; 04681 04682 AST_LIST_TRAVERSE (headp,newvariable,entries) { 04683 if (strcasecmp(ast_var_name(newvariable),name)==0) { 04684 /* there is already such a variable, delete it */ 04685 AST_LIST_REMOVE(headp,newvariable,ast_var_t,entries); 04686 ast_var_delete(newvariable); 04687 break; 04688 } 04689 } 04690 04691 if (value) { 04692 if ((option_verbose > 1) && (headp == &globals)) 04693 ast_verbose(VERBOSE_PREFIX_3 "Setting global variable '%s' to '%s'\n",name, value); 04694 newvariable=ast_var_assign(name,value); 04695 AST_LIST_INSERT_HEAD(headp,newvariable,entries); 04696 } 04697 }

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

executes an application

Parameters:
c channel to execute on
app which app to execute
data the data passed into the app
newstack stack pointer This application executes an application on a given channel. It saves the stack and executes the given appliation passing in the given data. It returns 0 on success, and -1 on failure
Definition at line 425 of file pbx.c.

References ast_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.

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

struct ast_app* pbx_findapp char *  app  ) 
 

Look up an application.

Parameters:
app name of the app This function searches for the ast_app structure within the apps that are registered for the one with the name you passed in. Returns the ast_app structure that matches on success, or NULL on failure
Definition at line 492 of file pbx.c.

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

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

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

Definition at line 1031 of file pbx.c.

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

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


Variable Documentation

struct ast_hint* hints = NULL
 

Definition at line 422 of file pbx.c.

Referenced by ast_device_state_changed(), ast_extension_state_add(), and ast_extension_state_del().

struct ast_state_cb* statecbs = NULL
 

Definition at line 423 of file pbx.c.

Referenced by ast_device_state_changed(), ast_extension_state_add(), and ast_extension_state_del().

struct ast_switch* switches = NULL
 

Definition at line 418 of file pbx.c.

Referenced by ast_register_switch(), and ast_unregister_switch().


Generated on Fri Sep 24 21:03:53 2004 for Asterisk by doxygen 1.3.8