#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.
Defines | |
| #define | EXT_DATA_SIZE 8192 |
| #define | AST_PBX_MAX_STACK 128 |
| #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_app * | pbx_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_context * | ast_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_context * | ast_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, int callingpres, char *callerid, char *variable, char *account, char *uniqueid) |
| void * | ast_pbx_run_app (void *data) |
| int | ast_pbx_outgoing_app (char *type, int format, void *data, int timeout, char *app, char *appdata, int *reason, int sync, char *callerid, char *variable, char *account, char *uniqueid) |
| 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_context * | ast_walk_contexts (struct ast_context *con) |
| ast_exten * | ast_walk_context_extensions (struct ast_context *con, struct ast_exten *exten) |
| ast_sw * | ast_walk_context_switches (struct ast_context *con, struct ast_sw *sw) |
| ast_exten * | ast_walk_extension_priorities (struct ast_exten *exten, struct ast_exten *priority) |
| ast_include * | ast_walk_context_includes (struct ast_context *con, struct ast_include *inc) |
| ast_ignorepat * | ast_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_switch * | switches = NULL |
| ast_hint * | hints = NULL |
| ast_state_cb * | statecbs = NULL |
|
|
|
|
|
|
|
|
Definition at line 573 of file pbx.c. Referenced by ast_extension_match(). |
|
|
Value: do { \ c = info; \ while(*c && (*c != '|')) c++; \ if (*c) { *c = '\0'; c++; } else c = NULL; \ } while(0) |
|
|
Definition at line 490 of file pbx.c. Referenced by ast_canmatch_extension(). |
|
|
|
|
|
Definition at line 487 of file pbx.c. Referenced by ast_exists_extension(). |
|
|
Definition at line 491 of file pbx.c. Referenced by ast_matchmore_extension(). |
|
|
Definition at line 488 of file pbx.c. Referenced by ast_spawn_extension(). |
|
|
Referenced by ast_add_extension2(). |
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||||||||
|
Definition at line 4283 of file pbx.c. References ast_context::alts, ast_log(), ast_mutex_destroy, ast_mutex_lock, ast_mutex_unlock, free, ast_context::ignorepats, ast_context::includes, ast_context::lock, LOG_WARNING, ast_context::name, ast_exten::next, ast_sw::next, ast_ignorepat::next, ast_include::next, ast_context::next, ast_exten::peer, ast_context::registrar, and ast_context::root. Referenced by ast_context_destroy(), and ast_merge_contexts_and_delete(). 04284 {
04285 struct ast_context *tmp, *tmpl=NULL;
04286 struct ast_include *tmpi, *tmpil= NULL;
04287 struct ast_sw *sw, *swl= NULL;
04288 struct ast_exten *e, *el, *en;
04289 struct ast_ignorepat *ipi, *ipl = NULL;
04290
04291 ast_mutex_lock(&conlock);
04292 tmp = contexts;
04293 while(tmp) {
04294 if (((tmp->name && con && con->name && !strcasecmp(tmp->name, con->name)) || !con) &&
04295 (!registrar || !strcasecmp(registrar, tmp->registrar))) {
04296 /* Okay, let's lock the structure to be sure nobody else
04297 is searching through it. */
04298 if (ast_mutex_lock(&tmp->lock)) {
04299 ast_log(LOG_WARNING, "Unable to lock context lock\n");
04300 return;
04301 }
04302 if (tmpl)
04303 tmpl->next = tmp->next;
04304 else
04305 contexts = tmp->next;
04306 /* Okay, now we're safe to let it go -- in a sense, we were
04307 ready to let it go as soon as we locked it. */
04308 ast_mutex_unlock(&tmp->lock);
04309 for (tmpi = tmp->includes; tmpi; ) {
04310 /* Free includes */
04311 tmpil = tmpi;
04312 tmpi = tmpi->next;
04313 free(tmpil);
04314 }
04315 for (ipi = tmp->ignorepats; ipi; ) {
04316 /* Free ignorepats */
04317 ipl = ipi;
04318 ipi = ipi->next;
04319 free(ipl);
04320 }
04321 for (sw = tmp->alts; sw; ) {
04322 /* Free switches */
04323 swl = sw;
04324 sw = sw->next;
04325 free(swl);
04326 swl = sw;
04327 }
04328 for (e = tmp->root; e;) {
04329 for (en = e->peer; en;) {
04330 el = en;
04331 en = en->peer;
04332 destroy_exten(el);
04333 }
04334 el = e;
04335 e = e->next;
04336 destroy_exten(el);
04337 }
04338 ast_mutex_destroy(&tmp->lock);
04339 free(tmp);
04340 if (!con) {
04341 /* Might need to get another one -- restart */
04342 tmp = contexts;
04343 tmpl = NULL;
04344 tmpil = NULL;
04345 continue;
04346 }
04347 ast_mutex_unlock(&conlock);
04348 return;
04349 }
04350 tmpl = tmp;
04351 tmp = tmp->next;
04352 }
04353 ast_mutex_unlock(&conlock);
04354 }
|
|
||||||||||||||||||||||||||||||||||||||||
|
Definition at line 3667 of file pbx.c. References ast_add_extension2(), ast_get_context_name(), ast_lock_contexts(), ast_unlock_contexts(), and ast_walk_contexts(). 03669 {
03670 struct ast_context *c;
03671
03672 if (ast_lock_contexts()) {
03673 errno = EBUSY;
03674 return -1;
03675 }
03676
03677 c = ast_walk_contexts(NULL);
03678 while (c) {
03679 if (!strcmp(context, ast_get_context_name(c))) {
03680 int ret = ast_add_extension2(c, replace, extension, priority, callerid,
03681 application, data, datad, registrar);
03682 ast_unlock_contexts();
03683 return ret;
03684 }
03685 c = ast_walk_contexts(c);
03686 }
03687
03688 ast_unlock_contexts();
03689 errno = ENOENT;
03690 return -1;
03691 }
|
|
||||||||||||||||||||||||||||||||||||||||
|
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 3800 of file pbx.c. References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_exten::cidmatch, ast_exten::data, ast_exten::datad, ast_exten::exten, free, ast_context::lock, LOG, LOG_ERROR, LOG_WARNING, malloc, ast_exten::matchcid, ast_context::name, ast_exten::next, ast_exten::peer, ast_exten::priority, PRIORITY_HINT, ast_context::registrar, and ast_context::root. Referenced by ast_add_extension(). 03804 {
03805
03806 #define LOG do { if (option_debug) {\
03807 if (tmp->matchcid) { \
03808 ast_log(LOG_DEBUG, "Added extension '%s' priority %d (CID match '%s') to %s\n", tmp->exten, tmp->priority, tmp->cidmatch, con->name); \
03809 } else { \
03810 ast_log(LOG_DEBUG, "Added extension '%s' priority %d to %s\n", tmp->exten, tmp->priority, con->name); \
03811 } \
03812 } else if (option_verbose > 2) { \
03813 if (tmp->matchcid) { \
03814 ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d (CID match '%s')to %s\n", tmp->exten, tmp->priority, tmp->cidmatch, con->name); \
03815 } else { \
03816 ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d to %s\n", tmp->exten, tmp->priority, con->name); \
03817 } \
03818 } } while(0)
03819
03820 /*
03821 * This is a fairly complex routine. Different extensions are kept
03822 * in order by the extension number. Then, extensions of different
03823 * priorities (same extension) are kept in a list, according to the
03824 * peer pointer.
03825 */
03826 struct ast_exten *tmp, *e, *el = NULL, *ep = NULL;
03827 int res;
03828
03829 /* Be optimistic: Build the extension structure first */
03830 tmp = malloc(sizeof(struct ast_exten));
03831 if (tmp) {
03832 memset(tmp, 0, sizeof(struct ast_exten));
03833 ext_strncpy(tmp->exten, extension, sizeof(tmp->exten));
03834 tmp->priority = priority;
03835 if (callerid) {
03836 ext_strncpy(tmp->cidmatch, callerid, sizeof(tmp->cidmatch));
03837 tmp->matchcid = 1;
03838 } else {
03839 tmp->cidmatch[0] = '\0';
03840 tmp->matchcid = 0;
03841 }
03842 strncpy(tmp->app, application, sizeof(tmp->app)-1);
03843 tmp->parent = con;
03844 tmp->data = data;
03845 tmp->datad = datad;
03846 tmp->registrar = registrar;
03847 tmp->peer = NULL;
03848 tmp->next = NULL;
03849 } else {
03850 ast_log(LOG_ERROR, "Out of memory\n");
03851 errno = ENOMEM;
03852 return -1;
03853 }
03854 if (ast_mutex_lock(&con->lock)) {
03855 free(tmp);
03856 /* And properly destroy the data */
03857 datad(data);
03858 ast_log(LOG_WARNING, "Failed to lock context '%s'\n", con->name);
03859 errno = EBUSY;
03860 return -1;
03861 }
03862 e = con->root;
03863 while(e) {
03864 /* Make sure patterns are always last! */
03865 if ((e->exten[0] != '_') && (extension[0] == '_'))
03866 res = -1;
03867 else if ((e->exten[0] == '_') && (extension[0] != '_'))
03868 res = 1;
03869 else
03870 res= strcmp(e->exten, extension);
03871 if (!res) {
03872 if (!e->matchcid && !tmp->matchcid)
03873 res = 0;
03874 else if (tmp->matchcid && !e->matchcid)
03875 res = 1;
03876 else if (e->matchcid && !tmp->matchcid)
03877 res = -1;
03878 else
03879 res = strcasecmp(e->cidmatch, tmp->cidmatch);
03880 }
03881 if (res == 0) {
03882 /* We have an exact match, now we find where we are
03883 and be sure there's no duplicates */
03884 while(e) {
03885 if (e->priority == tmp->priority) {
03886 /* Can't have something exactly the same. Is this a
03887 replacement? If so, replace, otherwise, bonk. */
03888 if (replace) {
03889 if (ep) {
03890 /* We're in the peer list, insert ourselves */
03891 ep->peer = tmp;
03892 tmp->peer = e->peer;
03893 } else if (el) {
03894 /* We're the first extension. Take over e's functions */
03895 el->next = tmp;
03896 tmp->next = e->next;
03897 tmp->peer = e->peer;
03898 } else {
03899 /* We're the very first extension. */
03900 con->root = tmp;
03901 tmp->next = e->next;
03902 tmp->peer = e->peer;
03903 }
03904 if (tmp->priority == PRIORITY_HINT)
03905 ast_change_hint(e,tmp);
03906 /* Destroy the old one */
03907 e->datad(e->data);
03908 free(e);
03909 ast_mutex_unlock(&con->lock);
03910 if (tmp->priority == PRIORITY_HINT)
03911 ast_change_hint(e, tmp);
03912 /* And immediately return success. */
03913 LOG;
03914 return 0;
03915 } else {
03916 ast_log(LOG_WARNING, "Unable to register extension '%s', priority %d in '%s', already in use\n", tmp->exten, tmp->priority, con->name);
03917 tmp->datad(tmp->data);
03918 free(tmp);
03919 ast_mutex_unlock(&con->lock);
03920 errno = EEXIST;
03921 return -1;
03922 }
03923 } else if (e->priority > tmp->priority) {
03924 /* Slip ourselves in just before e */
03925 if (ep) {
03926 /* Easy enough, we're just in the peer list */
03927 ep->peer = tmp;
03928 tmp->peer = e;
03929 } else if (el) {
03930 /* We're the first extension in this peer list */
03931 el->next = tmp;
03932 tmp->next = e->next;
03933 e->next = NULL;
03934 tmp->peer = e;
03935 } else {
03936 /* We're the very first extension altogether */
03937 tmp->next = con->root->next;
03938 /* Con->root must always exist or we couldn't get here */
03939 tmp->peer = con->root;
03940 con->root = tmp;
03941 }
03942 ast_mutex_unlock(&con->lock);
03943 /* And immediately return success. */
03944 if (tmp->priority == PRIORITY_HINT)
03945 ast_add_hint(tmp);
03946
03947 LOG;
03948 return 0;
03949 }
03950 ep = e;
03951 e = e->peer;
03952 }
03953 /* If we make it here, then it's time for us to go at the very end.
03954 ep *must* be defined or we couldn't have gotten here. */
03955 ep->peer = tmp;
03956 ast_mutex_unlock(&con->lock);
03957 if (tmp->priority == PRIORITY_HINT)
03958 ast_add_hint(tmp);
03959
03960 /* And immediately return success. */
03961 LOG;
03962 return 0;
03963
03964 } else if (res > 0) {
03965 /* Insert ourselves just before 'e'. We're the first extension of
03966 this kind */
03967 tmp->next = e;
03968 if (el) {
03969 /* We're in the list somewhere */
03970 el->next = tmp;
03971 } else {
03972 /* We're at the top of the list */
03973 con->root = tmp;
03974 }
03975 ast_mutex_unlock(&con->lock);
03976 if (tmp->priority == PRIORITY_HINT)
03977 ast_add_hint(tmp);
03978
03979 /* And immediately return success. */
03980 LOG;
03981 return 0;
03982 }
03983
03984 el = e;
03985 e = e->next;
03986 }
03987 /* If we fall all the way through to here, then we need to be on the end. */
03988 if (el)
03989 el->next = tmp;
03990 else
03991 con->root = tmp;
03992 ast_mutex_unlock(&con->lock);
03993 if (tmp->priority == PRIORITY_HINT)
03994 ast_add_hint(tmp);
03995 LOG;
03996 return 0;
03997 }
|
|
||||||||||||||||||||
|
Definition at line 3693 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(). 03694 {
03695 int res = 0;
03696 ast_mutex_lock(&chan->lock);
03697
03698 if (chan->pbx) {
03699 /* This channel is currently in the PBX */
03700 if (context && !ast_strlen_zero(context))
03701 strncpy(chan->context, context, sizeof(chan->context) - 1);
03702 if (exten && !ast_strlen_zero(exten))
03703 strncpy(chan->exten, exten, sizeof(chan->context) - 1);
03704 if (priority)
03705 chan->priority = priority - 1;
03706 ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO);
03707 } else {
03708 /* In order to do it when the channel doesn't really exist within
03709 the PBX, we have to make a new channel, masquerade, and start the PBX
03710 at the new location */
03711 struct ast_channel *tmpchan;
03712 tmpchan = ast_channel_alloc(0);
03713 if (tmpchan) {
03714 snprintf(tmpchan->name, sizeof(tmpchan->name), "AsyncGoto/%s", chan->name);
03715 ast_setstate(tmpchan, chan->_state);
03716 /* Make formats okay */
03717 tmpchan->readformat = chan->readformat;
03718 tmpchan->writeformat = chan->writeformat;
03719 /* Setup proper location */
03720 if (context && !ast_strlen_zero(context))
03721 strncpy(tmpchan->context, context, sizeof(tmpchan->context) - 1);
03722 else
03723 strncpy(tmpchan->context, chan->context, sizeof(tmpchan->context) - 1);
03724 if (exten && !ast_strlen_zero(exten))
03725 strncpy(tmpchan->exten, exten, sizeof(tmpchan->exten) - 1);
03726 else
03727 strncpy(tmpchan->exten, chan->exten, sizeof(tmpchan->exten) - 1);
03728 if (priority)
03729 tmpchan->priority = priority;
03730 else
03731 tmpchan->priority = chan->priority;
03732
03733 /* Masquerade into temp channel */
03734 ast_channel_masquerade(tmpchan, chan);
03735
03736 /* Grab the locks and get going */
03737 ast_mutex_lock(&tmpchan->lock);
03738 ast_do_masquerade(tmpchan);
03739 ast_mutex_unlock(&tmpchan->lock);
03740 /* Start the PBX going on our stolen channel */
03741 if (ast_pbx_start(tmpchan)) {
03742 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name);
03743 ast_hangup(tmpchan);
03744 res = -1;
03745 }
03746 } else {
03747 res = -1;
03748 }
03749 }
03750 ast_mutex_unlock(&chan->lock);
03751 return res;
03752 }
|
|
||||||||||||||||||||
|
Definition at line 3754 of file pbx.c. References ast_async_goto(), ast_channel_walk_locked(), ast_mutex_unlock, ast_channel::lock, and ast_channel::name. 03755 {
03756 struct ast_channel *chan;
03757 int res = -1;
03758
03759 chan = ast_channel_walk_locked(NULL);
03760 while(chan) {
03761 if (!strcasecmp(channame, chan->name))
03762 break;
03763 ast_mutex_unlock(&chan->lock);
03764 chan = ast_channel_walk_locked(chan);
03765 }
03766
03767 if (chan) {
03768 res = ast_async_goto(chan, context, exten, priority);
03769 ast_mutex_unlock(&chan->lock);
03770 }
03771 return res;
03772 }
|
|
||||||||||||||||||||||||
|
Looks for a valid matching extension.
Definition at line 1761 of file pbx.c. References HELPER_CANMATCH. 01762 {
01763 return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_CANMATCH);
01764 }
|
|
||||||||||||||||
|
Add an ignorepat.
Definition at line 3586 of file pbx.c. References ast_context_add_ignorepat2(), ast_get_context_name(), ast_lock_contexts(), ast_unlock_contexts(), and ast_walk_contexts(). 03587 {
03588 struct ast_context *c;
03589
03590 if (ast_lock_contexts()) {
03591 errno = EBUSY;
03592 return -1;
03593 }
03594
03595 c = ast_walk_contexts(NULL);
03596 while (c) {
03597 if (!strcmp(ast_get_context_name(c), con)) {
03598 int ret = ast_context_add_ignorepat2(c, value, registrar);
03599 ast_unlock_contexts();
03600 return ret;
03601 }
03602 c = ast_walk_contexts(c);
03603 }
03604
03605 ast_unlock_contexts();
03606 errno = ENOENT;
03607 return -1;
03608 }
|
|
||||||||||||||||
|
Definition at line 3610 of file pbx.c. References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_context::ignorepats, ast_context::lock, LOG_ERROR, malloc, ast_ignorepat::next, ast_ignorepat::pattern, and ast_ignorepat::registrar. Referenced by ast_context_add_ignorepat(). 03611 {
03612 struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL;
03613
03614 ignorepat = malloc(sizeof(struct ast_ignorepat));
03615 if (!ignorepat) {
03616 ast_log(LOG_ERROR, "Out of memory\n");
03617 errno = ENOMEM;
03618 return -1;
03619 }
03620 memset(ignorepat, 0, sizeof(struct ast_ignorepat));
03621 strncpy(ignorepat->pattern, value, sizeof(ignorepat->pattern)-1);
03622 ignorepat->next = NULL;
03623 ignorepat->registrar = registrar;
03624 ast_mutex_lock(&con->lock);
03625 ignorepatc = con->ignorepats;
03626 while(ignorepatc) {
03627 ignorepatl = ignorepatc;
03628 if (!strcasecmp(ignorepatc->pattern, value)) {
03629 /* Already there */
03630 ast_mutex_unlock(&con->lock);
03631 errno = EEXIST;
03632 return -1;
03633 }
03634 ignorepatc = ignorepatc->next;
03635 }
03636 if (ignorepatl)
03637 ignorepatl->next = ignorepat;
03638 else
03639 con->ignorepats = ignorepat;
03640 ast_mutex_unlock(&con->lock);
03641 return 0;
03642
03643 }
|
|
||||||||||||||||
|
Add an include.
Definition at line 3047 of file pbx.c. References ast_context_add_include2(), ast_get_context_name(), ast_lock_contexts(), ast_unlock_contexts(), and ast_walk_contexts(). 03048 {
03049 struct ast_context *c;
03050
03051 if (ast_lock_contexts()) {
03052 errno = EBUSY;
03053 return -1;
03054 }
03055
03056 /* walk contexts ... */
03057 c = ast_walk_contexts(NULL);
03058 while (c) {
03059 /* ... search for the right one ... */
03060 if (!strcmp(ast_get_context_name(c), context)) {
03061 int ret = ast_context_add_include2(c, include, registrar);
03062 /* ... unlock contexts list and return */
03063 ast_unlock_contexts();
03064 return ret;
03065 }
03066 c = ast_walk_contexts(c);
03067 }
03068
03069 /* we can't find the right context */
03070 ast_unlock_contexts();
03071 errno = ENOENT;
03072 return -1;
03073 }
|
|
||||||||||||||||
|
Add an include.
Definition at line 3367 of file pbx.c. References ast_get_context_name(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_verbose(), free, ast_context::includes, ast_context::lock, LOG_ERROR, malloc, ast_include::name, ast_include::next, option_verbose, ast_include::registrar, ast_include::rname, and VERBOSE_PREFIX_3. Referenced by ast_context_add_include(). 03369 {
03370 struct ast_include *new_include;
03371 char *c;
03372 struct ast_include *i, *il = NULL; /* include, include_last */
03373
03374 /* allocate new include structure ... */
03375 if (!(new_include = malloc(sizeof(struct ast_include)))) {
03376 ast_log(LOG_ERROR, "Out of memory\n");
03377 errno = ENOMEM;
03378 return -1;
03379 }
03380
03381 /* ... fill in this structure ... */
03382 memset(new_include, 0, sizeof(struct ast_include));
03383 strncpy(new_include->name, value, sizeof(new_include->name)-1);
03384 strncpy(new_include->rname, value, sizeof(new_include->rname)-1);
03385 c = new_include->rname;
03386 /* Strip off timing info */
03387 while(*c && (*c != '|')) c++;
03388 /* Process if it's there */
03389 if (*c) {
03390 build_timing(new_include, c+1);
03391 *c = '\0';
03392 }
03393 new_include->next = NULL;
03394 new_include->registrar = registrar;
03395
03396 /* ... try to lock this context ... */
03397 if (ast_mutex_lock(&con->lock)) {
03398 free(new_include);
03399 errno = EBUSY;
03400 return -1;
03401 }
03402
03403 /* ... go to last include and check if context is already included too... */
03404 i = con->includes;
03405 while (i) {
03406 if (!strcasecmp(i->name, new_include->name)) {
03407 free(new_include);
03408 ast_mutex_unlock(&con->lock);
03409 errno = EEXIST;
03410 return -1;
03411 }
03412 il = i;
03413 i = i->next;
03414 }
03415
03416 /* ... include new context into context list, unlock, return */
03417 if (il)
03418 il->next = new_include;
03419 else
03420 con->includes = new_include;
03421 if (option_verbose > 2)
03422 ast_verbose(VERBOSE_PREFIX_3 "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con));
03423 ast_mutex_unlock(&con->lock);
03424
03425 return 0;
03426 }
|
|
||||||||||||||||||||
|
Add a switch.
Definition at line 3433 of file pbx.c. References ast_context_add_switch2(), ast_get_context_name(), ast_lock_contexts(), ast_unlock_contexts(), and ast_walk_contexts(). 03434 {
03435 struct ast_context *c;
03436
03437 if (ast_lock_contexts()) {
03438 errno = EBUSY;
03439 return -1;
03440 }
03441
03442 /* walk contexts ... */
03443 c = ast_walk_contexts(NULL);
03444 while (c) {
03445 /* ... search for the right one ... */
03446 if (!strcmp(ast_get_context_name(c), context)) {
03447 int ret = ast_context_add_switch2(c, sw, data, registrar);
03448 /* ... unlock contexts list and return */
03449 ast_unlock_contexts();
03450 return ret;
03451 }
03452 c = ast_walk_contexts(c);
03453 }
03454
03455 /* we can't find the right context */
03456 ast_unlock_contexts();
03457 errno = ENOENT;
03458 return -1;
03459 }
|
|
||||||||||||||||||||
|
Adds a switch (first param is a ast_context). Definition at line 3468 of file pbx.c. References ast_context::alts, ast_get_context_name(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_verbose(), ast_sw::data, free, ast_context::lock, LOG_ERROR, malloc, ast_sw::name, ast_sw::next, option_verbose, ast_sw::registrar, and VERBOSE_PREFIX_3. Referenced by ast_context_add_switch(). 03470 {
03471 struct ast_sw *new_sw;
03472 struct ast_sw *i, *il = NULL; /* sw, sw_last */
03473
03474 /* allocate new sw structure ... */
03475 if (!(new_sw = malloc(sizeof(struct ast_sw)))) {
03476 ast_log(LOG_ERROR, "Out of memory\n");
03477 errno = ENOMEM;
03478 return -1;
03479 }
03480
03481 /* ... fill in this structure ... */
03482 memset(new_sw, 0, sizeof(struct ast_sw));
03483 strncpy(new_sw->name, value, sizeof(new_sw->name)-1);
03484 if (data)
03485 strncpy(new_sw->data, data, sizeof(new_sw->data)-1);
03486 else
03487 strncpy(new_sw->data, "", sizeof(new_sw->data)-1);
03488 new_sw->next = NULL;
03489 new_sw->registrar = registrar;
03490
03491 /* ... try to lock this context ... */
03492 if (ast_mutex_lock(&con->lock)) {
03493 free(new_sw);
03494 errno = EBUSY;
03495 return -1;
03496 }
03497
03498 /* ... go to last sw and check if context is already swd too... */
03499 i = con->alts;
03500 while (i) {
03501 if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) {
03502 free(new_sw);
03503 ast_mutex_unlock(&con->lock);
03504 errno = EEXIST;
03505 return -1;
03506 }
03507 il = i;
03508 i = i->next;
03509 }
03510
03511 /* ... sw new context into context list, unlock, return */
03512 if (il)
03513 il->next = new_sw;
03514 else
03515 con->alts = new_sw;
03516 if (option_verbose > 2)
03517 ast_verbose(VERBOSE_PREFIX_3 "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con));
03518 ast_mutex_unlock(&con->lock);
03519
03520 return 0;
03521 }
|
|
||||||||||||||||
|
Register a new context.
Definition at line 2970 of file pbx.c. References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_verbose(), ast_context::includes, LOG_DEBUG, LOG_ERROR, LOG_WARNING, malloc, ast_context::name, ast_context::next, option_debug, option_verbose, and VERBOSE_PREFIX_3. 02971 {
02972 struct ast_context *tmp, **local_contexts;
02973 if (!extcontexts) {
02974 local_contexts = &contexts;
02975 ast_mutex_lock(&conlock);
02976 } else
02977 local_contexts = extcontexts;
02978
02979 tmp = *local_contexts;
02980 while(tmp) {
02981 if (!strcasecmp(tmp->name, name)) {
02982 ast_mutex_unlock(&conlock);
02983 ast_log(LOG_WARNING, "Tried to register context '%s', already in use\n", name);
02984 if (!extcontexts)
02985 ast_mutex_unlock(&conlock);
02986 return NULL;
02987 }
02988 tmp = tmp->next;
02989 }
02990 tmp = malloc(sizeof(struct ast_context));
02991 if (tmp) {
02992 memset(tmp, 0, sizeof(struct ast_context));
02993 ast_mutex_init(&tmp->lock);
02994 strncpy(tmp->name, name, sizeof(tmp->name)-1);
02995 tmp->root = NULL;
02996 tmp->registrar = registrar;
02997 tmp->next = *local_contexts;
02998 tmp->includes = NULL;
02999 tmp->ignorepats = NULL;
03000 *local_contexts = tmp;
03001 if (option_debug)
03002 ast_log(LOG_DEBUG, "Registered context '%s'\n", tmp->name);
03003 else if (option_verbose > 2)
03004 ast_verbose( VERBOSE_PREFIX_3 "Registered extension context '%s'\n", tmp->name);
03005 } else
03006 ast_log(LOG_ERROR, "Out of memory\n");
03007
03008 if (!extcontexts)
03009 ast_mutex_unlock(&conlock);
03010 return tmp;
03011 }
|
|
||||||||||||
|
Destroy a context (matches the specified context (or ANY context if NULL).
Definition at line 4356 of file pbx.c. References __ast_context_destroy(). 04357 {
04358 __ast_context_destroy(con,registrar);
04359 }
|
|
|
Find a context.
Definition at line 677 of file pbx.c. References ast_mutex_lock, ast_mutex_unlock, ast_context::name, and ast_context::next. Referenced by ast_context_verify_includes(), and ast_ignore_pattern(). 00678 {
00679 struct ast_context *tmp;
00680 ast_mutex_lock(&conlock);
00681 if (name) {
00682 tmp = contexts;
00683 while(tmp) {
00684 if (!strcasecmp(name, tmp->name))
00685 break;
00686 tmp = tmp->next;
00687 }
00688 } else
00689 tmp = contexts;
00690 ast_mutex_unlock(&conlock);
00691 return tmp;
00692 }
|
|
||||||||||||||||||||
|
Simply remove extension from context.
Definition at line 2169 of file pbx.c. References ast_context_remove_extension2(), ast_get_context_name(), ast_lock_contexts(), ast_unlock_contexts(), and ast_walk_contexts(). 02170 {
02171 struct ast_context *c;
02172
02173 if (ast_lock_contexts()) return -1;
02174
02175 /* walk contexts ... */
02176 c = ast_walk_contexts(NULL);
02177 while (c) {
02178 /* ... search for the right one ... */
02179 if (!strcmp(ast_get_context_name(c), context)) {
02180 /* ... remove extension ... */
02181 int ret = ast_context_remove_extension2(c, extension, priority,
02182 registrar);
02183 /* ... unlock contexts list and return */
02184 ast_unlock_contexts();
02185 return ret;
02186 }
02187 c = ast_walk_contexts(c);
02188 }
02189
02190 /* we can't find the right context */
02191 ast_unlock_contexts();
02192 return -1;
02193 }
|
|
||||||||||||||||||||
|
Definition at line 2205 of file pbx.c. References ast_mutex_lock, ast_mutex_unlock, ast_exten::exten, free, ast_context::lock, ast_exten::next, ast_exten::peer, ast_exten::priority, PRIORITY_HINT, ast_exten::registrar, and ast_context::root. Referenced by ast_context_remove_extension(). 02206 {
02207 struct ast_exten *exten, *prev_exten = NULL;
02208
02209 if (ast_mutex_lock(&con->lock)) return -1;
02210
02211 /* go through all extensions in context and search the right one ... */
02212 exten = con->root;
02213 while (exten) {
02214
02215 /* look for right extension */
02216 if (!strcmp(exten->exten, extension) &&
02217 (!registrar || !strcmp(exten->registrar, registrar))) {
02218 struct ast_exten *peer;
02219
02220 /* should we free all peers in this extension? (priority == 0)? */
02221 if (priority == 0) {
02222 /* remove this extension from context list */
02223 if (prev_exten)
02224 prev_exten->next = exten->next;
02225 else
02226 con->root = exten->next;
02227
02228 /* fire out all peers */
02229 peer = exten;
02230 while (peer) {
02231 exten = peer->peer;
02232
02233 if (!peer->priority==PRIORITY_HINT)
02234 ast_remove_hint(peer);
02235
02236 peer->datad(peer->data);
02237 free(peer);
02238
02239 peer = exten;
02240 }
02241
02242 ast_mutex_unlock(&con->lock);
02243 return 0;
02244 } else {
02245 /* remove only extension with exten->priority == priority */
02246 struct ast_exten *previous_peer = NULL;
02247
02248 peer = exten;
02249 while (peer) {
02250 /* is this our extension? */
02251 if (peer->priority == priority &&
02252 (!registrar || !strcmp(peer->registrar, registrar) )) {
02253 /* we are first priority extension? */
02254 if (!previous_peer) {
02255 /* exists previous extension here? */
02256 if (prev_exten) {
02257 /* yes, so we must change next pointer in
02258 * previous connection to next peer
02259 */
02260 if (peer->peer) {
02261 prev_exten->next = peer->peer;
02262 peer->peer->next = exten->next;
02263 } else
02264 prev_exten->next = exten->next;
02265 } else {
02266 /* no previous extension, we are first
02267 * extension, so change con->root ...
02268 */
02269 if (peer->peer)
02270 con->root = peer->peer;
02271 else
02272 con->root = exten->next;
02273 }
02274 } else {
02275 /* we are not first priority in extension */
02276 previous_peer->peer = peer->peer;
02277 }
02278
02279 /* now, free whole priority extension */
02280 if (peer->priority==PRIORITY_HINT)
02281 ast_remove_hint(peer);
02282 peer->datad(peer->data);
02283 free(peer);
02284
02285 ast_mutex_unlock(&con->lock);
02286 return 0;
02287 } else {
02288 /* this is not right extension, skip to next peer */
02289 previous_peer = peer;
02290 peer = peer->peer;
02291 }
02292 }
02293
02294 ast_mutex_unlock(&con->lock);
02295 return -1;
02296 }
02297 }
02298
02299 prev_exten = exten;
02300 exten = exten->next;
02301 }
02302
02303 /* we can't find right extension */
02304 ast_mutex_unlock(&con->lock);
02305 return -1;
02306 }
|
|
||||||||||||||||
|
Definition at line 3527 of file pbx.c. References ast_context_remove_ignorepat2(), ast_get_context_name(), ast_lock_contexts(), ast_unlock_contexts(), and ast_walk_contexts(). 03528 {
03529 struct ast_context *c;
03530
03531 if (ast_lock_contexts()) {
03532 errno = EBUSY;
03533 return -1;
03534 }
03535
03536 c = ast_walk_contexts(NULL);
03537 while (c) {
03538 if (!strcmp(ast_get_context_name(c), context)) {
03539 int ret = ast_context_remove_ignorepat2(c, ignorepat, registrar);
03540 ast_unlock_contexts();
03541 return ret;
03542 }
03543 c = ast_walk_contexts(c);
03544 }
03545
03546 ast_unlock_contexts();
03547 errno = ENOENT;
03548 return -1;
03549 }
|
|
||||||||||||||||
|
Definition at line 3551 of file pbx.c. References ast_mutex_lock, ast_mutex_unlock, free, ast_context::ignorepats, ast_context::lock, ast_ignorepat::next, ast_ignorepat::pattern, and ast_ignorepat::registrar. Referenced by ast_context_remove_ignorepat(). 03552 {
03553 struct ast_ignorepat *ip, *ipl = NULL;
03554
03555 if (ast_mutex_lock(&con->lock)) {
03556 errno = EBUSY;
03557 return -1;
03558 }
03559
03560 ip = con->ignorepats;
03561 while (ip) {
03562 if (!strcmp(ip->pattern, ignorepat) &&
03563 (!registrar || (registrar == ip->registrar))) {
03564 if (ipl) {
03565 ipl->next = ip->next;
03566 free(ip);
03567 } else {
03568 con->ignorepats = ip->next;
03569 free(ip);
03570 }
03571 ast_mutex_unlock(&con->lock);
03572 return 0;
03573 }
03574 ipl = ip; ip = ip->next;
03575 }
03576
03577 ast_mutex_unlock(&con->lock);
03578 errno = EINVAL;
03579 return -1;
03580 }
|
|
||||||||||||||||
|
Removes an include. See add_include Definition at line 2025 of file pbx.c. References ast_context_remove_include2(), ast_get_context_name(), ast_lock_contexts(), ast_unlock_contexts(), and ast_walk_contexts(). 02026 {
02027 struct ast_context *c;
02028
02029 if (ast_lock_contexts()) return -1;
02030
02031 /* walk contexts and search for the right one ...*/
02032 c = ast_walk_contexts(NULL);
02033 while (c) {
02034 /* we found one ... */
02035 if (!strcmp(ast_get_context_name(c), context)) {
02036 int ret;
02037 /* remove include from this context ... */
02038 ret = ast_context_remove_include2(c, include, registrar);
02039
02040 ast_unlock_contexts();
02041
02042 /* ... return results */
02043 return ret;
02044 }
02045 c = ast_walk_contexts(c);
02046 }
02047
02048 /* we can't find the right one context */
02049 ast_unlock_contexts();
02050 return -1;
02051 }
|
|
||||||||||||||||
|
Removes an include by an ast_context structure. See add_include2 Definition at line 2061 of file pbx.c. References ast_mutex_lock, ast_mutex_unlock, free, ast_context::includes, ast_context::lock, ast_include::name, ast_include::next, and ast_include::registrar. Referenced by ast_context_remove_include(). 02062 {
02063 struct ast_include *i, *pi = NULL;
02064
02065 if (ast_mutex_lock(&con->lock)) return -1;
02066
02067 /* walk includes */
02068 i = con->includes;
02069 while (i) {
02070 /* find our include */
02071 if (!strcmp(i->name, include) &&
02072 (!registrar || !strcmp(i->registrar, registrar))) {
02073 /* remove from list */
02074 if (pi)
02075 pi->next = i->next;
02076 else
02077 con->includes = i->next;
02078 /* free include and return */
02079 free(i);
02080 ast_mutex_unlock(&con->lock);
02081 return 0;
02082 }
02083 pi = i;
02084 i = i->next;
02085 }
02086
02087 /* we can't find the right include */
02088 ast_mutex_unlock(&con->lock);
02089 return -1;
02090 }
|
|
||||||||||||||||||||
|
Remove a switch. Removes a switch with the given parameters Returns 0 on success, -1 on failure Definition at line 2097 of file pbx.c. References ast_context_remove_switch2(), ast_get_context_name(), ast_lock_contexts(), ast_unlock_contexts(), and ast_walk_contexts(). 02098 {
02099 struct ast_context *c;
02100
02101 if (ast_lock_contexts()) return -1;
02102
02103 /* walk contexts and search for the right one ...*/
02104 c = ast_walk_contexts(NULL);
02105 while (c) {
02106 /* we found one ... */
02107 if (!strcmp(ast_get_context_name(c), context)) {
02108 int ret;
02109 /* remove switch from this context ... */
02110 ret = ast_context_remove_switch2(c, sw, data, registrar);
02111
02112 ast_unlock_contexts();
02113
02114 /* ... return results */
02115 return ret;
02116 }
02117 c = ast_walk_contexts(c);
02118 }
02119
02120 /* we can't find the right one context */
02121 ast_unlock_contexts();
02122 return -1;
02123 }
|
|
||||||||||||||||||||
|
Definition at line 2133 of file pbx.c. References ast_context::alts, ast_mutex_lock, ast_mutex_unlock, ast_sw::data, free, ast_context::lock, ast_sw::name, ast_sw::next, and ast_sw::registrar. Referenced by ast_context_remove_switch(). 02134 {
02135 struct ast_sw *i, *pi = NULL;
02136
02137 if (ast_mutex_lock(&con->lock)) return -1;
02138
02139 /* walk switchs */
02140 i = con->alts;
02141 while (i) {
02142 /* find our switch */
02143 if (!strcmp(i->name, sw) && !strcmp(i->data, data) &&
02144 (!registrar || !strcmp(i->registrar, registrar))) {
02145 /* remove from list */
02146 if (pi)
02147 pi->next = i->next;
02148 else
02149 con->alts = i->next;
02150 /* free switch and return */
02151 free(i);
02152 ast_mutex_unlock(&con->lock);
02153 return 0;
02154 }
02155 pi = i;
02156 i = i->next;
02157 }
02158
02159 /* we can't find the right switch */
02160 ast_mutex_unlock(&con->lock);
02161 return -1;
02162 }
|
|
|
Verifies includes in an ast_contect structure.
Definition at line 5093 of file pbx.c. References ast_context_find(), ast_get_context_name(), ast_log(), ast_walk_context_includes(), LOG_WARNING, and ast_include::rname. 05094 {
05095 struct ast_include *inc;
05096 int res = 0;
05097
05098 for (inc = ast_walk_context_includes(con, NULL); inc; inc = ast_walk_context_includes(con, inc))
05099 if (!ast_context_find(inc->rname)) {
05100 res = -1;
05101 ast_log(LOG_WARNING, "Context '%s' tries includes non-existant context '%s'\n",
05102 ast_get_context_name(con), inc->rname);
05103 }
05104 return res;
05105 }
|
|
||||||||||||
|
Definition at line 1441 of file pbx.c. References ast_get_extension_app(), AST_MAX_EXTENSION, ast_mutex_lock, ast_mutex_unlock, ast_state_cb::callback, ast_hint::callbacks, ast_state_cb::data, ast_exten::exten, ast_hint::exten, ast_hint::laststate, ast_context::name, ast_hint::next, ast_state_cb::next, and ast_exten::parent. Referenced by ast_channel_free(), and ast_setstate(). 01442 {
01443 struct ast_hint *list;
01444 struct ast_state_cb *cblist;
01445 char hint[AST_MAX_EXTENSION] = "";
01446 char device[AST_MAX_EXTENSION];
01447 char *cur, *rest;
01448 int state;
01449
01450 va_list ap;
01451
01452 va_start(ap, fmt);
01453 vsnprintf(device, sizeof(device), fmt, ap);
01454 va_end(ap);
01455
01456 rest = strchr(device, '-');
01457 if (rest) {
01458 *rest = 0;
01459 }
01460
01461 ast_mutex_lock(&hintlock);
01462
01463 list = hints;
01464
01465 while (list) {
01466
01467 strncpy(hint, ast_get_extension_app(list->exten), sizeof(hint) - 1);
01468 cur = hint;
01469 do {
01470 rest = strchr(cur, '&');
01471 if (rest) {
01472 *rest = 0;
01473 rest++;
01474 }
01475
01476 if (!strcmp(cur, device)) {
01477 /* Found extension execute callbacks */
01478 state = ast_extension_state2(list->exten);
01479 if ((state != -1) && (state != list->laststate)) {
01480 /* For general callbacks */
01481 cblist = statecbs;
01482 while (cblist) {
01483 cblist->callback(list->exten->parent->name, list->exten->exten, state, cblist->data);
01484 cblist = cblist->next;
01485 }
01486
01487 /* For extension callbacks */
01488 cblist = list->callbacks;
01489 while (cblist) {
01490 cblist->callback(list->exten->parent->name, list->exten->exten, state, cblist->data);
01491 cblist = cblist->next;
01492 }
01493
01494 list->laststate = state;
01495 }
01496 break;
01497 }
01498 cur = rest;
01499 } while (cur);
01500 list = list->next;
01501 }
01502 ast_mutex_unlock(&hintlock);
01503 return 1;
01504 }
|
|
||||||||||||||||||||||||
|
If an extension exists, return non-zero.
Definition at line 1756 of file pbx.c. References HELPER_EXISTS. Referenced by ast_pbx_outgoing_exten(), and ast_pbx_run(). 01757 {
01758 return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_EXISTS);
01759 }
|
|
||||||||||||
|
Determine if a given extension matches a given pattern (in NXX format).
Definition at line 644 of file pbx.c. References EXTENSION_MATCH_CORE. Referenced by ast_ignore_pattern(). 00645 {
00646 int match;
00647 /* If they're the same return */
00648 if (!strcmp(pattern, data))
00649 return 1;
00650 EXTENSION_MATCH_CORE(data,pattern,match);
00651 /* Must be at the end of both */
00652 if (*data || (*pattern && (*pattern != '/')))
00653 match = 0;
00654 return match;
00655 }
|
|
||||||||||||||||
|
Uses hint and devicestate callback to get the state of an extension.
Definition at line 1430 of file pbx.c. 01431 {
01432 struct ast_exten *e;
01433
01434 e = ast_hint_extension(c, context, exten);
01435 if (!e)
01436 return -1;
01437
01438 return ast_extension_state2(e);
01439 }
|
|
||||||||||||||||||||
|
Registers a state change callback.
Definition at line 1506 of file pbx.c. References ast_mutex_lock, ast_mutex_unlock, ast_state_cb::callback, ast_hint::callbacks, ast_state_cb::data, ast_hint::exten, ast_state_cb::id, malloc, ast_state_cb::next, and ast_hint::next. Referenced by init_manager(). 01508 {
01509 struct ast_hint *list;
01510 struct ast_state_cb *cblist;
01511 struct ast_exten *e;
01512
01513 /* No context and extension add callback to statecbs list */
01514 if (!context && !exten) {
01515 ast_mutex_lock(&hintlock);
01516
01517 cblist = statecbs;
01518 while (cblist) {
01519 if (cblist->callback == callback) {
01520 cblist->data = data;
01521 ast_mutex_unlock(&hintlock);
01522 }
01523 cblist = cblist->next;
01524 }
01525
01526 /* Now inserts the callback */
01527 cblist = malloc(sizeof(struct ast_state_cb));
01528 if (!cblist) {
01529 ast_mutex_unlock(&hintlock);
01530 return -1;
01531 }
01532 memset(cblist, 0, sizeof(struct ast_state_cb));
01533 cblist->id = 0;
01534 cblist->callback = callback;
01535 cblist->data = data;
01536
01537 cblist->next = statecbs;
01538 statecbs = cblist;
01539
01540 ast_mutex_unlock(&hintlock);
01541 return 0;
01542 }
01543
01544 if (!context || !exten)
01545 return -1;
01546
01547 /* This callback type is for only one hint */
01548 e = ast_hint_extension(NULL, context, exten);
01549 if (!e) {
01550 return -1;
01551 }
01552
01553 ast_mutex_lock(&hintlock);
01554 list = hints;
01555
01556 while (list) {
01557 if (list->exten == e)
01558 break;
01559 list = list->next;
01560 }
01561
01562 if (!list) {
01563 ast_mutex_unlock(&hintlock);
01564 return -1;
01565 }
01566
01567 /* Now inserts the callback */
01568 cblist = malloc(sizeof(struct ast_state_cb));
01569 if (!cblist) {
01570 ast_mutex_unlock(&hintlock);
01571 return -1;
01572 }
01573 memset(cblist, 0, sizeof(struct ast_state_cb));
01574 cblist->id = stateid++;
01575 cblist->callback = callback;
01576 cblist->data = data;
01577
01578 cblist->next = list->callbacks;
01579 list->callbacks = cblist;
01580
01581 ast_mutex_unlock(&hintlock);
01582 return cblist->id;
01583 }
|
|
||||||||||||
|
Deletes a registered state change callback by ID.
Definition at line 1585 of file pbx.c. References ast_mutex_lock, ast_mutex_unlock, ast_hint::callbacks, free, ast_state_cb::next, and ast_hint::next. 01586 {
01587 struct ast_hint *list;
01588 struct ast_state_cb *cblist, *cbprev;
01589
01590 if (!id && !callback)
01591 return -1;
01592
01593 ast_mutex_lock(&hintlock);
01594
01595 /* id is zero is a callback without extension */
01596 if (!id) {
01597 cbprev = NULL;
01598 cblist = statecbs;
01599 while (cblist) {
01600 if (cblist->callback == callback) {
01601 if (!cbprev)
01602 statecbs = cblist->next;
01603 else
01604 cbprev->next = cblist->next;
01605
01606 free(cblist);
01607
01608 ast_mutex_unlock(&hintlock);
01609 return 0;
01610 }
01611 cbprev = cblist;
01612 cblist = cblist->next;
01613 }
01614
01615 ast_mutex_lock(&hintlock);
01616 return -1;
01617 }
01618
01619 /* id greater than zero is a callback with extension */
01620 list = hints;
01621 while (list) {
01622 cblist = list->callbacks;
01623 cbprev = NULL;
01624 while (cblist) {
01625 if (cblist->id==id) {
01626 if (!cbprev)
01627 list->callbacks = cblist->next;
01628 else
01629 cbprev->next = cblist->next;
01630
01631 free(cblist);
01632
01633 ast_mutex_unlock(&hintlock);
01634 return 0;
01635 }
01636 cbprev = cblist;
01637 cblist = cblist->next;
01638 }
01639 list = list->next;
01640 }
01641
01642 ast_mutex_unlock(&hintlock);
01643 return -1;
01644 }
|
|
|
Definition at line 4954 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(). 04955 {
04956 return con ? con->name : NULL;
04957 }
|
|
|
Definition at line 4982 of file pbx.c. References ast_context::registrar. 04983 {
04984 return c ? c->registrar : NULL;
04985 }
|
|
|
Definition at line 5012 of file pbx.c. References ast_exten::app. Referenced by ast_device_state_changed(), and ast_get_hint(). 05013 {
05014 return e ? e->app : NULL;
05015 }
|
|
|
Definition at line 5017 of file pbx.c. References ast_exten::data. 05018 {
05019 return e ? e->data : NULL;
05020 }
|
|
|
Definition at line 5007 of file pbx.c. References ast_exten::cidmatch. 05008 {
05009 return e ? e->cidmatch : NULL;
05010 }
|
|
|
Definition at line 5002 of file pbx.c. References ast_exten::matchcid. 05003 {
05004 return e ? e->matchcid : 0;
05005 }
|
|
|
Definition at line 4959 of file pbx.c. References ast_exten::exten. 04960 {
04961 return exten ? exten->exten : NULL;
04962 }
|
|
|
Definition at line 4974 of file pbx.c. References ast_exten::priority. 04975 {
04976 return exten ? exten->priority : -1;
04977 }
|
|
|
Definition at line 4987 of file pbx.c. References ast_exten::registrar. 04988 {
04989 return e ? e->registrar : NULL;
04990 }
|
|
||||||||||||||||||||||||
|
If an extension exists, return non-zero.
Definition at line 1745 of file pbx.c. References ast_get_extension_app(). 01746 {
01747 struct ast_exten *e;
01748 e = ast_hint_extension(c, context, exten);
01749 if (e) {
01750 strncpy(hint, ast_get_extension_app(e), hintsize - 1);
01751 return -1;
01752 }
01753 return 0;
01754 }
|
|
|
Definition at line 4969 of file pbx.c. References ast_ignorepat::pattern. 04970 {
04971 return ip ? ip->pattern : NULL;
04972 }
|
|
|
Definition at line 4997 of file pbx.c. References ast_ignorepat::registrar. 04998 {
04999 return ip ? ip->registrar : NULL;
05000 }
|
|
|
Definition at line 4964 of file pbx.c. References ast_include::name. 04965 {
04966 return inc ? inc->name : NULL;
04967 }
|
|
|
Definition at line 4992 of file pbx.c. References ast_include::registrar. 04993 {
04994 return i ? i->registrar : NULL;
04995 }
|
|
|
Definition at line 5027 of file pbx.c. References ast_sw::data. 05028 {
05029 return sw ? sw->data : NULL;
05030 }
|
|
|
Definition at line 5022 of file pbx.c. References ast_sw::name. 05023 {
05024 return sw ? sw->name : NULL;
05025 }
|
|
|
Definition at line 5032 of file pbx.c. References ast_sw::registrar. 05033 {
05034 return sw ? sw->registrar : NULL;
05035 }
|
|
||||||||||||
|
Checks to see if a number should be ignored.
Definition at line 3645 of file pbx.c. References ast_context_find(), ast_extension_match(), and ast_context::ignorepats. 03646 {
03647 struct ast_context *con;
03648 struct ast_ignorepat *pat;
03649
03650 con = ast_context_find(context);
03651 if (con) {
03652 pat = con->ignorepats;
03653 while (pat) {
03654 if (ast_extension_match(pat->pattern, pattern))
03655 return 1;
03656 pat = pat->next;
03657 }
03658 }
03659 return 0;
03660 }
|
|
|
Locks a given context.
Definition at line 4941 of file pbx.c. References ast_mutex_lock, and ast_context::lock. 04942 {
04943 return ast_mutex_lock(&con->lock);
04944 }
|
|
|
Locks the contexts. Locks the context list Returns 0 on success, -1 on error Definition at line 4928 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(). 04929 {
04930 return ast_mutex_lock(&conlock);
04931 }
|
|
||||||||||||||||||||||||
|
Looks to see if adding anything to this extension might match something. (exists ^ canmatch).
Definition at line 1766 of file pbx.c. References HELPER_MATCHMORE. Referenced by ast_pbx_run(). 01767 {
01768 return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_MATCHMORE);
01769 }
|
|
||||||||||||
|
Merge the temporary contexts into a global contexts list and delete from the global list the ones that are being added.
Definition at line 3015 of file pbx.c. References __ast_context_destroy(), ast_log(), ast_mutex_lock, ast_mutex_unlock, LOG_WARNING, and ast_context::next. 03015 {
03016 struct ast_context *tmp, *lasttmp = NULL;
03017 tmp = *extcontexts;
03018 ast_mutex_lock(&conlock);
03019 if (registrar) {
03020 __ast_context_destroy(NULL,registrar);
03021 while (tmp) {
03022 lasttmp = tmp;
03023 tmp = tmp->next;
03024 }
03025 } else {
03026 while (tmp) {
03027 __ast_context_destroy(tmp,tmp->registrar);
03028 lasttmp = tmp;
03029 tmp = tmp->next;
03030 }
03031 }
03032 if (lasttmp) {
03033 lasttmp->next = contexts;
03034 contexts = *extcontexts;
03035 *extcontexts = NULL;
03036 } else
03037 ast_log(LOG_WARNING, "Requested contexts didn't get merged\n");
03038 ast_mutex_unlock(&conlock);
03039 return;
03040 }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Definition at line 4185 of file pbx.c. References ast_hangup(), ast_log(), ast_pbx_run_app(), ast_pthread_create(), ast_request_and_dial(), AST_STATE_UP, ast_verbose(), free, LOG_ERROR, LOG_WARNING, malloc, option_verbose, pbx_builtin_setvar(), and VERBOSE_PREFIX_4. 04186 {
04187 struct ast_channel *chan;
04188 struct async_stat *as;
04189 struct app_tmp *tmp;
04190 char *var, *vartmp;
04191 int res = -1;
04192 pthread_attr_t attr;
04193
04194 if (!app || ast_strlen_zero(app))
04195 return -1;
04196 if (sync) {
04197 chan = ast_request_and_dial(type, format, data, timeout, reason, 0, callerid, uniqueid);
04198 if (chan) {
04199 pbx_builtin_setaccount(chan, account);
04200 if (variable) {
04201 vartmp = ast_strdupa(variable);
04202 for (var = strtok_r(vartmp, "|", &vartmp); var; var = strtok_r(NULL, "|", &vartmp)) {
04203 pbx_builtin_setvar( chan, var );
04204 }
04205 }
04206 if (chan->_state == AST_STATE_UP) {
04207 res = 0;
04208 if (option_verbose > 3)
04209 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", chan->name);
04210 tmp = malloc(sizeof(struct app_tmp));
04211 if (tmp) {
04212 memset(tmp, 0, sizeof(struct app_tmp));
04213 strncpy(tmp->app, app, sizeof(tmp->app) - 1);
04214 strncpy(tmp->data, appdata, sizeof(tmp->data) - 1);
04215 tmp->chan = chan;
04216 if (sync > 1) {
04217 ast_pbx_run_app(tmp);
04218 } else {
04219 pthread_attr_init(&attr);
04220 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
04221 if (ast_pthread_create(&tmp->t, &attr, ast_pbx_run_app, tmp)) {
04222 ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno));
04223 free(tmp);
04224 ast_hangup(chan);
04225 res = -1;
04226 }
04227 }
04228 } else {
04229 ast_log(LOG_ERROR, "Out of memory :(\n");
04230 res = -1;
04231 }
04232 } else {
04233 if (option_verbose > 3)
04234 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", chan->name);
04235 ast_hangup(chan);
04236 }
04237 }
04238 } else {
04239 as = malloc(sizeof(struct async_stat));
04240 if (!as)
04241 return -1;
04242 memset(as, 0, sizeof(struct async_stat));
04243 chan = ast_request_and_dial(type, format, data, timeout, reason, 0, callerid, uniqueid);
04244 if (!chan) {
04245 free(as);
04246 return -1;
04247 }
04248 pbx_builtin_setaccount(chan, account);
04249 as->chan = chan;
04250 strncpy(as->app, app, sizeof(as->app) - 1);
04251 if (appdata)
04252 strncpy(as->appdata, appdata, sizeof(as->appdata) - 1);
04253 as->timeout = timeout;
04254 if (variable) {
04255 vartmp = ast_strdupa(variable);
04256 for (var = strtok_r(vartmp, "|", &vartmp); var; var = strtok_r(NULL, "|", &vartmp))
04257 pbx_builtin_setvar( chan, var );
04258 }
04259 /* Start a new thread, and get something handling this channel. */
04260 pthread_attr_init(&attr);
04261 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
04262 if (ast_pthread_create(&as->p, &attr, async_wait, as)) {
04263 ast_log(LOG_WARNING, "Failed to start async wait\n");
04264 free(as);
04265 ast_hangup(chan);
04266 return -1;
04267 }
04268 res = 0;
04269 }
04270 return res;
04271 }
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Definition at line 4067 of file pbx.c. References __ast_request_and_dial(), ast_channel_alloc(), ast_exists_extension(), ast_hangup(), ast_log(), ast_pbx_run(), ast_pbx_start(), ast_pthread_create(), ast_request_and_dial(), AST_STATE_UP, ast_verbose(), 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, and VERBOSE_PREFIX_4. 04068 {
04069 struct ast_channel *chan;
04070 struct async_stat *as;
04071 int res = -1;
04072 char *var, *tmp;
04073 struct outgoing_helper oh;
04074 pthread_attr_t attr;
04075
04076 if (sync) {
04077 LOAD_OH(oh);
04078 chan = __ast_request_and_dial(type, format, data, timeout, reason, callingpres, callerid, &oh, uniqueid);
04079 if (chan) {
04080 pbx_builtin_setaccount(chan, account);
04081 if (chan->_state == AST_STATE_UP) {
04082 res = 0;
04083 if (option_verbose > 3)
04084 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", chan->name);
04085
04086 if (sync > 1) {
04087 if (ast_pbx_run(chan)) {
04088 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name);
04089 ast_hangup(chan);
04090 res = -1;
04091 }
04092 } else {
04093 if (ast_pbx_start(chan)) {
04094 ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name);
04095 ast_hangup(chan);
04096 res = -1;
04097 }
04098 }
04099 } else {
04100 if (option_verbose > 3)
04101 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", chan->name);
04102 ast_hangup(chan);
04103 }
04104 }
04105
04106 if(res < 0) { /* the call failed for some reason */
04107 /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */
04108 /* check if "failed" exists */
04109 if (ast_exists_extension(chan, context, "failed", 1, NULL)) {
04110 chan = ast_channel_alloc(0);
04111 if (chan) {
04112 strncpy(chan->name, "OutgoingSpoolFailed", sizeof(chan->name) - 1);
04113 if (context && !ast_strlen_zero(context))
04114 strncpy(chan->context, context, sizeof(chan->context) - 1);
04115 strncpy(chan->exten, "failed", sizeof(chan->exten) - 1);
04116 chan->priority = 1;
04117 if (variable) {
04118 tmp = ast_strdupa(variable);
04119 for (var = strtok_r(tmp, "|", &tmp); var; var = strtok_r(NULL, "|", &tmp)) {
04120 pbx_builtin_setvar( chan, var );
04121 }
04122 }
04123 ast_pbx_run(chan);
04124 } else
04125 ast_log(LOG_WARNING, "Can't allocate the channel structure, skipping execution of extension 'failed'\n");
04126 }
04127 }
04128 } else {
04129 as = malloc(sizeof(struct async_stat));
04130 if (!as)
04131 return -1;
04132 memset(as, 0, sizeof(struct async_stat));
04133 chan = ast_request_and_dial(type, format, data, timeout, reason, callingpres, callerid, uniqueid);
04134 if (!chan) {
04135 free(as);
04136 return -1;
04137 }
04138 pbx_builtin_setaccount(chan, account);
04139 as->chan = chan;
04140 strncpy(as->context, context, sizeof(as->context) - 1);
04141 strncpy(as->exten, exten, sizeof(as->exten) - 1);
04142 as->priority = priority;
04143 as->timeout = timeout;
04144 if (variable) {
04145 tmp = ast_strdupa(variable);
04146 for (var = strtok_r(tmp, "|", &tmp); var; var = strtok_r(NULL, "|", &tmp))
04147 pbx_builtin_setvar( chan, var );
04148 }
04149 pthread_attr_init(&attr);
04150 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
04151 if (ast_pthread_create(&as->p, &attr, async_wait, as)) {
04152 ast_log(LOG_WARNING, "Failed to start async wait\n");
04153 free(as);
04154 ast_hangup(chan);
04155 return -1;
04156 }
04157 res = 0;
04158 }
04159 return res;
04160 }
|
|
|
Execute the PBX in the current thread.
Definition at line 1776 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(). 01777 {
01778 int firstpass = 1;
01779 char digit;
01780 char exten[256];
01781 int pos;
01782 int waittime;
01783 int res=0;
01784
01785 /* A little initial setup here */
01786 if (c->pbx)
01787 ast_log(LOG_WARNING, "%s already has PBX structure??\n", c->name);
01788 c->pbx = malloc(sizeof(struct ast_pbx));
01789 if (!c->pbx) {
01790 ast_log(LOG_ERROR, "Out of memory\n");
01791 return -1;
01792 }
01793 if (c->amaflags) {
01794 if (c->cdr) {
01795 ast_log(LOG_WARNING, "%s already has a call record??\n", c->name);
01796 } else {
01797 c->cdr = ast_cdr_alloc();
01798 if (!c->cdr) {
01799 ast_log(LOG_WARNING, "Unable to create Call Detail Record\n");
01800 free(c->pbx);
01801 return -1;
01802 }
01803 ast_cdr_init(c->cdr, c);
01804 }
01805 }
01806 memset(c->pbx, 0, sizeof(struct ast_pbx));
01807 /* Set reasonable defaults */
01808 c->pbx->rtimeout = 10;
01809 c->pbx->dtimeout = 5;
01810
01811 /* Start by trying whatever the channel is set to */
01812 if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) {
01813 /* JK02: If not successfull fall back to 's' */
01814 if (option_verbose > 1)
01815 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);
01816 strncpy(c->exten, "s", sizeof(c->exten)-1);
01817 if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) {
01818 /* JK02: And finally back to default if everything else failed */
01819 if (option_verbose > 1)
01820 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);
01821 strncpy(c->context, "default", sizeof(c->context)-1);
01822 }
01823 c->priority = 1;
01824 }
01825 if (c->cdr)
01826 ast_cdr_start(c->cdr);
01827 for(;;) {
01828 pos = 0;
01829 digit = 0;
01830 while(ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) {
01831 memset(exten, 0, sizeof(exten));
01832 if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->callerid))) {
01833 /* Something bad happened, or a hangup has been requested. */
01834 if (((res >= '0') && (res <= '9')) || ((res >= 'A') && (res <= 'F')) ||
01835 (res == '*') || (res == '#')) {
01836 ast_log(LOG_DEBUG, "Oooh, got something to jump out with ('%c')!\n", res);
01837 memset(exten, 0, sizeof(exten));
01838 pos = 0;
01839 exten[pos++] = digit = res;
01840 break;
01841 }
01842 switch(res) {
01843 case AST_PBX_KEEPALIVE:
01844 if (option_debug)
01845 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
01846 else if (option_verbose > 1)
01847 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
01848 goto out;
01849 break;
01850 default:
01851 if (option_debug)
01852 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
01853 else if (option_verbose > 1)
01854 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
01855 if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
01856 c->_softhangup =0;
01857 break;
01858 }
01859 /* atimeout */
01860 if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) {
01861 break;
01862 }
01863
01864 if (c->cdr) {
01865 ast_cdr_update(c);
01866 }
01867 goto out;
01868 }
01869 }
01870 if ((c->_softhangup == AST_SOFTHANGUP_TIMEOUT) && (ast_exists_extension(c,c->context,"T",1,c->callerid))) {
01871 strncpy(c->exten,"T",sizeof(c->exten) - 1);
01872 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
01873 c->whentohangup = 0;
01874 c->priority = 0;
01875 c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT;
01876 } else if (c->_softhangup) {
01877 ast_log(LOG_DEBUG, "Extension %s, priority %d returned normally even though call was hung up\n",
01878 c->exten, c->priority);
01879 goto out;
01880 }
01881 firstpass = 0;
01882 c->priority++;
01883 }
01884 if (!ast_exists_extension(c, c->context, c->exten, 1, c->callerid)) {
01885 /* It's not a valid extension anymore */
01886 if (ast_exists_extension(c, c->context, "i", 1, c->callerid)) {
01887 if (option_verbose > 2)
01888 ast_verbose(VERBOSE_PREFIX_3 "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, c->name);
01889 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", c->exten);
01890 strncpy(c->exten, "i", sizeof(c->exten)-1);
01891 c->priority = 1;
01892 } else {
01893 ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n",
01894 c->name, c->exten, c->context);
01895 goto out;
01896 }
01897 } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) {
01898 /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */
01899 c->_softhangup = 0;
01900 } else {
01901 /* Done, wait for an extension */
01902 if (digit)
01903 waittime = c->pbx->dtimeout;
01904 else
01905 waittime = c->pbx->rtimeout;
01906 while (ast_matchmore_extension(c, c->context, exten, 1, c->callerid)) {
01907 /* As long as we're willing to wait, and as long as it's not defined,
01908 keep reading digits until we can't possibly get a right answer anymore. */
01909 digit = ast_waitfordigit(c, waittime * 1000);
01910 if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
01911 c->_softhangup = 0;
01912 } else {
01913 if (!digit)
01914 /* No entry */
01915 break;
01916 if (digit < 0)
01917 /* Error, maybe a hangup */
01918 goto out;
01919 exten[pos++] = digit;
01920 waittime = c->pbx->dtimeout;
01921 }
01922 }
01923 if (ast_exists_extension(c, c->context, exten, 1, c->callerid)) {
01924 /* Prepare the next cycle */
01925 strncpy(c->exten, exten, sizeof(c->exten)-1);
01926 c->priority = 1;
01927 } else {
01928 /* No such extension */
01929 if (!ast_strlen_zero(exten)) {
01930 /* An invalid extension */
01931 if (ast_exists_extension(c, c->context, "i", 1, c->callerid)) {
01932 if (option_verbose > 2)
01933 ast_verbose( VERBOSE_PREFIX_3 "Invalid extension '%s' in context '%s' on %s\n", exten, c->context, c->name);
01934 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", exten);
01935 strncpy(c->exten, "i", sizeof(c->exten)-1);
01936 c->priority = 1;
01937 } else {
01938 ast_log(LOG_WARNING, "Invalid extension '%s', but no rule 'i' in context '%s'\n", exten, c->context);
01939 goto out;
01940 }
01941 } else {
01942 /* A simple timeout */
01943 if (ast_exists_extension(c, c->context, "t", 1, c->callerid)) {
01944 if (option_verbose > 2)
01945 ast_verbose( VERBOSE_PREFIX_3 "Timeout on %s\n", c->name);
01946 strncpy(c->exten, "t", sizeof(c->exten)-1);
01947 c->priority = 1;
01948 } else {
01949 ast_log(LOG_WARNING, "Timeout, but no rule 't' in context '%s'\n", c->context);
01950 goto out;
01951 }
01952 }
01953 }
01954 if (c->cdr) {
01955 if (option_verbose > 2)
01956 ast_verbose(VERBOSE_PREFIX_2 "CDR updated on %s\n",c->name);
01957 ast_cdr_update(c);
01958 }
01959 }
01960 }
01961 if (firstpass)
01962 ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name);
01963 out:
01964 if ((res != AST_PBX_KEEPALIVE) && ast_exists_extension(c, c->context, "h", 1, c->callerid)) {
01965 c->exten[0] = 'h';
01966 c->exten[1] = '\0';
01967 c->priority = 1;
01968 while(ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) {
01969 if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->callerid))) {
01970 /* Something bad happened, or a hangup has been requested. */
01971 if (option_debug)
01972 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
01973 else if (option_verbose > 1)
01974 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
01975 break;
01976 }
01977 c->priority++;
01978 }
01979 }
01980
01981 pbx_destroy(c->pbx);
01982 c->pbx = NULL;
01983 if (res != AST_PBX_KEEPALIVE)
01984 ast_hangup(c);
01985 return 0;
01986 }
|
|
|
Definition at line 4169 of file pbx.c. References app_tmp::app, ast_hangup(), ast_log(), ast_verbose(), app_tmp::chan, app_tmp::data, free, LOG_WARNING, ast_channel::name, option_verbose, pbx_exec(), pbx_findapp(), and VERBOSE_PREFIX_4. Referenced by ast_pbx_outgoing_app(). 04170 {
04171 struct app_tmp *tmp = data;
04172 struct ast_app *app;
04173 app = pbx_findapp(tmp->app);
04174 if (app) {
04175 if (option_verbose > 3)
04176 ast_verbose(VERBOSE_PREFIX_4 "Lauching %s(%s) on %s\n", tmp->app, tmp->data, tmp->chan->name);
04177 pbx_exec(tmp->chan, app, tmp->data, 1);
04178 } else
04179 ast_log(LOG_WARNING, "No such application '%s'\n", tmp->app);
04180 ast_hangup(tmp->chan);
04181 free(tmp);
04182 return NULL;
04183 }
|
|
|
Create a new thread and start the PBX (or whatever).
Definition at line 2001 of file pbx.c. References ast_log(), ast_pthread_create(), and LOG_WARNING. Referenced by ast_async_goto(), and ast_pbx_outgoing_exten(). 02002 {
02003 pthread_t t;
02004 pthread_attr_t attr;
02005 if (!c) {
02006 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
02007 return -1;
02008 }
02009
02010 /* Start a new thread, and get something handling this channel. */
02011 pthread_attr_init(&attr);
02012 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
02013 if (ast_pthread_create(&t, &attr, pbx_thread, c)) {
02014 ast_log(LOG_WARNING, "Failed to create new channel thread\n");
02015 return -1;
02016 }
02017 return 0;
02018 }
|
|
||||||||||||||||||||
|
Add an application. The function 'execute' should return non-zero if the line needs to be hung up.
Definition at line 2309 of file pbx.c. References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_verbose(), COLOR_BRCYAN, LOG_ERROR, LOG_WARNING, malloc, ast_app::name, ast_app::next, option_verbose, term_color(), and VERBOSE_PREFIX_2. Referenced by load_pbx(). 02310 {
02311 struct ast_app *tmp, *prev, *cur;
02312 char tmps[80];
02313 if (ast_mutex_lock(&applock)) {
02314 ast_log(LOG_ERROR, "Unable to lock application list\n");
02315 return -1;
02316 }
02317 tmp = apps;
02318 while(tmp) {
02319 if (!strcasecmp(app, tmp->name)) {
02320 ast_log(LOG_WARNING, "Already have an application '%s'\n", app);
02321 ast_mutex_unlock(&applock);
02322 return -1;
02323 }
02324 tmp = tmp->next;
02325 }
02326 tmp = malloc(sizeof(struct ast_app));
02327 if (tmp) {
02328 memset(tmp, 0, sizeof(struct ast_app));
02329 strncpy(tmp->name, app, sizeof(tmp->name)-1);
02330 tmp->execute = execute;
02331 tmp->synopsis = synopsis;
02332 tmp->description = description;
02333 /* Store in alphabetical order */
02334 cur = apps;
02335 prev = NULL;
02336 while(cur) {
02337 if (strcasecmp(tmp->name, cur->name) < 0)
02338 break;
02339 prev = cur;
02340 cur = cur->next;
02341 }
02342 if (prev) {
02343 tmp->next = prev->next;
02344 prev->next = tmp;
02345 } else {
02346 tmp->next = apps;
02347 apps = tmp;
02348 }
02349 } else {
02350 ast_log(LOG_ERROR, "Out of memory\n");
02351 ast_mutex_unlock(&applock);
02352 return -1;
02353 }
02354 if (option_verbose > 1)
02355 ast_verbose( VERBOSE_PREFIX_2 "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps)));
02356 ast_mutex_unlock(&applock);
02357 return 0;
02358 }
|
|
|
Register an alternative switch.
Definition at line 2360 of file pbx.c. References ast_log(), ast_mutex_lock, ast_mutex_unlock, LOG_ERROR, LOG_WARNING, ast_switch::name, and ast_switch::next. 02361 {
02362 struct ast_switch *tmp, *prev=NULL;
02363 if (ast_mutex_lock(&switchlock)) {
02364 ast_log(LOG_ERROR, "Unable to lock switch lock\n");
02365 return -1;
02366 }
02367 tmp = switches;
02368 while(tmp) {
02369 if (!strcasecmp(tmp->name, sw->name))
02370 break;
02371 prev = tmp;
02372 tmp = tmp->next;
02373 }
02374 if (tmp) {
02375 ast_mutex_unlock(&switchlock);
02376 ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name);
02377 return -1;
02378 }
02379 sw->next = NULL;
02380 if (prev)
02381 prev->next = sw;
02382 else
02383 switches = sw;
02384 ast_mutex_unlock(&switchlock);
02385 return 0;
02386 }
|
|
||||||||||||||||||||||||
|
Launch a new extension (i.e. new stack).
Definition at line 1771 of file pbx.c. References HELPER_SPAWN. Referenced by ast_pbx_run(). 01772 {
01773 return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_SPAWN);
01774 }
|
|
|
Unlocks the given context.
Definition at line 4946 of file pbx.c. References ast_mutex_unlock, and ast_context::lock. 04947 {
04948 return ast_mutex_unlock(&con->lock);
04949 }
|
|
|
Unlocks contexts. Returns 0 on success, -1 on failure Definition at line 4933 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(). 04934 {
04935 return ast_mutex_unlock(&conlock);
04936 }
|
|
|
Remove an application.
Definition at line 2944 of file pbx.c. References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_verbose(), free, LOG_ERROR, ast_app::name, ast_app::next, option_verbose, and VERBOSE_PREFIX_2. 02944 {
02945 struct ast_app *tmp, *tmpl = NULL;
02946 if (ast_mutex_lock(&applock)) {
02947 ast_log(LOG_ERROR, "Unable to lock application list\n");
02948 return -1;
02949 }
02950 tmp = apps;
02951 while(tmp) {
02952 if (!strcasecmp(app, tmp->name)) {
02953 if (tmpl)
02954 tmpl->next = tmp->next;
02955 else
02956 apps = tmp->next;
02957 if (option_verbose > 1)
02958 ast_verbose( VERBOSE_PREFIX_2 "Unregistered application '%s'\n", tmp->name);
02959 free(tmp);
02960 ast_mutex_unlock(&applock);
02961 return 0;
02962 }
02963 tmpl = tmp;
02964 tmp = tmp->next;
02965 }
02966 ast_mutex_unlock(&applock);
02967 return -1;
02968 }
|
|
|
Unregister an alternative switch.
Definition at line 2388 of file pbx.c. References ast_log(), ast_mutex_lock, ast_mutex_unlock, LOG_ERROR, and ast_switch::next. 02389 {
02390 struct ast_switch *tmp, *prev=NULL;
02391 if (ast_mutex_lock(&switchlock)) {
02392 ast_log(LOG_ERROR, "Unable to lock switch lock\n");
02393 return;
02394 }
02395 tmp = switches;
02396 while(tmp) {
02397 if (tmp == sw) {
02398 if (prev)
02399 prev->next = tmp->next;
02400 else
02401 switches = tmp->next;
02402 tmp->next = NULL;
02403 break;
02404 }
02405 prev = tmp;
02406 tmp = tmp->next;
02407 }
02408 ast_mutex_unlock(&switchlock);
02409 }
|
|
||||||||||||
|
Definition at line 5048 of file pbx.c. References ast_exten::next. 05050 {
05051 if (!exten)
05052 return con ? con->root : NULL;
05053 else
05054 return exten->next;
05055 }
|
|
||||||||||||
|
Definition at line 5084 of file pbx.c. References ast_ignorepat::next. 05086 {
05087 if (!ip)
05088 return con ? con->ignorepats : NULL;
05089 else
05090 return ip->next;
05091 }
|
|
||||||||||||
|
Definition at line 5075 of file pbx.c. References ast_include::next. Referenced by ast_context_verify_includes(). 05077 {
05078 if (!inc)
05079 return con ? con->includes : NULL;
05080 else
05081 return inc->next;
05082 }
|
|
||||||||||||
|
Definition at line 5057 of file pbx.c. References ast_sw::next. 05059 {
05060 if (!sw)
05061 return con ? con->alts : NULL;
05062 else
05063 return sw->next;
05064 }
|
|
|
Definition at line 5040 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(). 05041 {
05042 if (!con)
05043 return contexts;
05044 else
05045 return con->next;
05046 }
|
|
||||||||||||
|
Definition at line 5066 of file pbx.c. References ast_exten::peer. 05068 {
05069 if (!priority)
05070 return exten;
05071 else
05072 return priority->peer;
05073 }
|
|
|
Definition at line 4898 of file pbx.c. References ast_cli_register(), AST_LIST_HEAD_INIT, ast_log(), ast_register_application(), ast_verbose(), LOG_ERROR, option_verbose, and VERBOSE_PREFIX_1. Referenced by main(). 04899 {
04900 int x;
04901
04902 /* Initialize the PBX */
04903 if (option_verbose) {
04904 ast_verbose( "Asterisk PBX Core Initializing\n");
04905 ast_verbose( "Registering builtin applications:\n");
04906 }
04907 AST_LIST_HEAD_INIT(&globals);
04908 ast_cli_register(&show_applications_cli);
04909 ast_cli_register(&show_application_cli);
04910 ast_cli_register(&show_dialplan_cli);
04911 ast_cli_register(&show_switches_cli);
04912
04913 /* Register builtin applications */
04914 for (x=0; x<sizeof(builtins) / sizeof(struct pbx_builtin); x++) {
04915 if (option_verbose)
04916 ast_verbose( VERBOSE_PREFIX_1 "[%s]\n", builtins[x].name);
04917 if (ast_register_application(builtins[x].name, builtins[x].execute, builtins[x].synopsis, builtins[x].description)) {
04918 ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name);
04919 return -1;
04920 }
04921 }
04922 return 0;
04923 }
|
|
|
Definition at line 4786 of file pbx.c. References AST_LIST_EMPTY, AST_LIST_FIRST, AST_LIST_REMOVE_HEAD, and ast_var_delete(). 04787 {
04788 struct ast_var_t *vardata;
04789 while (!AST_LIST_EMPTY(&globals)) {
04790 vardata = AST_LIST_FIRST(&globals);
04791 AST_LIST_REMOVE_HEAD(&globals, entries);
04792 ast_var_delete(vardata);
04793 }
04794 }
|
|
||||||||||||
|
Definition at line 4686 of file pbx.c. References AST_LIST_TRAVERSE, ast_var_name(), and ast_var_value(). 04687 {
04688 struct ast_var_t *variables;
04689 struct varshead *headp;
04690
04691 if (chan)
04692 headp=&chan->varshead;
04693 else
04694 headp=&globals;
04695
04696 if (name) {
04697 AST_LIST_TRAVERSE(headp,variables,entries) {
04698 if (!strcmp(name, ast_var_name(variables)))
04699 return ast_var_value(variables);
04700 }
04701 if (headp != &globals) {
04702 /* Check global variables if we haven't already */
04703 headp = &globals;
04704 AST_LIST_TRAVERSE(headp,variables,entries) {
04705 if (!strcmp(name, ast_var_name(variables)))
04706 return ast_var_value(variables);
04707 }
04708 }
04709 }
04710 return NULL;
04711 }
|
|
||||||||||||
|
Definition at line 4739 of file pbx.c. References ast_log(), LOG_WARNING, and pbx_builtin_setvar_helper(). Referenced by __ast_request_and_dial(), ast_pbx_outgoing_app(), and ast_pbx_outgoing_exten(). 04740 {
04741 char *name;
04742 char *value;
04743 char *stringp=NULL;
04744
04745 if (!data || ast_strlen_zero(data)) {
04746 ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n");
04747 return 0;
04748 }
04749
04750 stringp=data;
04751 name=strsep(&stringp,"=");
04752 value=strsep(&stringp,"\0");
04753
04754 pbx_builtin_setvar_helper(chan,name,value);
04755
04756 return(0);
04757 }
|
|
||||||||||||||||
|
Definition at line 4713 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. Referenced by ast_pbx_run(), and pbx_builtin_setvar(). 04714 {
04715 struct ast_var_t *newvariable;
04716 struct varshead *headp;
04717 if (chan)
04718 headp=&chan->varshead;
04719 else
04720 headp=&globals;
04721
04722 AST_LIST_TRAVERSE (headp,newvariable,entries) {
04723 if (strcasecmp(ast_var_name(newvariable),name)==0) {
04724 /* there is already such a variable, delete it */
04725 AST_LIST_REMOVE(headp,newvariable,ast_var_t,entries);
04726 ast_var_delete(newvariable);
04727 break;
04728 }
04729 }
04730
04731 if (value) {
04732 if ((option_verbose > 1) && (headp == &globals))
04733 ast_verbose(VERBOSE_PREFIX_3 "Setting global variable '%s' to '%s'\n",name, value);
04734 newvariable=ast_var_assign(name,value);
04735 AST_LIST_INSERT_HEAD(headp,newvariable,entries);
04736 }
04737 }
|
|
||||||||||||||||||||
|
executes an application
Definition at line 426 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. Referenced by ast_pbx_run_app(). 00430 {
00431 /* This function is special. It saves the stack so that no matter
00432 how many times it is called, it returns to the same place */
00433 int res;
00434
00435 char *saved_c_appl;
00436 char *saved_c_data;
00437
00438 int stack = c->stack;
00439 int (*execute)(struct ast_channel *chan, void *data) = app->execute;
00440
00441 if (newstack && stack > AST_CHANNEL_MAX_STACK - 2) {
00442 /* Don't allow us to go over the max number of stacks we
00443 permit saving. */
00444 ast_log(LOG_WARNING, "Stack overflow, cannot create another stack\n");
00445 return -1;
00446 }
00447 if (newstack && (res = setjmp(c->jmp[++c->stack]))) {
00448 /* Okay, here's where it gets weird. If newstack is non-zero,
00449 then we increase the stack increment, but setjmp is not going
00450 to return until longjmp is called -- when the application
00451 exec'd is finished running. */
00452 if (res == 1)
00453 res = 0;
00454 if (c->stack != stack + 1)
00455 ast_log(LOG_WARNING, "Stack returned to an unexpected place!\n");
00456 else if (c->app[c->stack])
00457 ast_log(LOG_WARNING, "Application may have forgotten to free its memory\n");
00458 c->stack = stack;
00459 return res;
00460 } else {
00461 if (c->cdr)
00462 ast_cdr_setapp(c->cdr, app->name, data);
00463
00464 /* save channel values */
00465 saved_c_appl= c->appl;
00466 saved_c_data= c->data;
00467
00468 c->appl = app->name;
00469 c->data = data;
00470 res = execute(c, data);
00471 /* restore channel values */
00472 c->appl= saved_c_appl;
00473 c->data= saved_c_data;
00474
00475 /* Any application that returns, we longjmp back, just in case. */
00476 if (c->stack != stack + 1)
00477 ast_log(LOG_WARNING, "Stack is not at expected value\n");
00478 longjmp(c->jmp[stack+1], res);
00479 /* Never returns */
00480 }
00481 }
|
|
|
Look up an application.
Definition at line 493 of file pbx.c. References ast_log(), ast_mutex_lock, ast_mutex_unlock, LOG_WARNING, ast_app::name, and ast_app::next. Referenced by ast_pbx_run_app(). 00494 {
00495 struct ast_app *tmp;
00496
00497 if (ast_mutex_lock(&applock)) {
00498 ast_log(LOG_WARNING, "Unable to obtain application lock\n");
00499 return NULL;
00500 }
00501 tmp = apps;
00502 while(tmp) {
00503 if (!strcasecmp(tmp->name, app))
00504 break;
00505 tmp = tmp->next;
00506 }
00507 ast_mutex_unlock(&applock);
00508 return tmp;
00509 }
|
|
||||||||||||||||||||
|
Definition at line 1044 of file pbx.c. References ast_expr(), ast_log(), free, LOG_DEBUG, LOG_NOTICE, and pbx_substitute_variables_helper(). Referenced by pbx_substitute_variables_helper(). 01045 {
01046 char *cp4;
01047 const char *tmp, *whereweare;
01048 int length;
01049 char workspace[4096];
01050 char ltmp[4096], var[4096];
01051 char *nextvar, *nextexp;
01052 char *vars, *vare;
01053 int pos, brackets, needsub, len;
01054
01055 /* Substitutes variables into cp2, based on string cp1, and assuming cp2 to be
01056 zero-filled */
01057 whereweare=tmp=cp1;
01058 while(!ast_strlen_zero(whereweare) && count) {
01059 /* Assume we're copying the whole remaining string */
01060 pos = strlen(whereweare);
01061
01062 /* Look for a variable */
01063 nextvar = strstr(whereweare, "${");
01064
01065 /* Look for an expression */
01066 nextexp = strstr(whereweare, "$[");
01067
01068 /* Pick the first one only */
01069 if (nextvar && nextexp) {
01070 if (nextvar < nextexp)
01071 nextexp = NULL;
01072 else
01073 nextvar = NULL;
01074 }
01075
01076 /* If there is one, we only go that far */
01077 if (nextvar)
01078 pos = nextvar - whereweare;
01079 else if (nextexp)
01080 pos = nextexp - whereweare;
01081
01082 /* Can't copy more than 'count' bytes */
01083 if (pos > count)
01084 pos = count;
01085
01086 /* Copy that many bytes */
01087 memcpy(cp2, whereweare, pos);
01088
01089 count -= pos;
01090 cp2 += pos;
01091 whereweare += pos;
01092
01093 if (nextvar) {
01094 /* We have a variable. Find the start and end, and determine
01095 if we are going to have to recursively call ourselves on the
01096 contents */
01097 vars = vare = nextvar + 2;
01098 brackets = 1;
01099 needsub = 0;
01100
01101 /* Find the end of it */
01102 while(brackets && *vare) {
01103 if ((vare[0] == '$') && (vare[1] == '{')) {
01104 needsub++;
01105 brackets++;
01106 } else if (vare[0] == '}') {
01107 brackets--;
01108 } else if ((vare[0] == '$') && (vare[1] == '['))
01109 needsub++;
01110 vare++;
01111 }
01112 if (brackets)
01113 ast_log(LOG_NOTICE, "Error in extension logic (missing '}')\n");
01114 len = vare - vars - 1;
01115
01116 /* Skip totally over variable name */
01117 whereweare += ( len + 3);
01118
01119 /* Store variable name (and truncate) */
01120 memset(var, 0, sizeof(var));
01121 strncpy(var, vars, sizeof(var) - 1);
01122 var[len] = '\0';
01123
01124 /* Substitute if necessary */
01125 if (needsub) {
01126 memset(ltmp, 0, sizeof(ltmp));
01127 pbx_substitute_variables_helper(c, var, ltmp, sizeof(ltmp) - 1);
01128 vars = ltmp;
01129 } else {
01130 vars = var;
01131 }
01132
01133 /* Retrieve variable value */
01134 workspace[0] = '\0';
01135 pbx_substitute_variables_temp(c,vars,&cp4, workspace, sizeof(workspace));
01136 if (cp4) {
01137 length = strlen(cp4);
01138 if (length > count)
01139 length = count;
01140 memcpy(cp2, cp4, length);
01141 count -= length;
01142 cp2 += length;
01143 }
01144
01145 } else if (nextexp) {
01146 /* We have an expression. Find the start and end, and determine
01147 if we are going to have to recursively call ourselves on the
01148 contents */
01149 vars = vare = nextexp + 2;
01150 brackets = 1;
01151 needsub = 0;
01152
01153 /* Find the end of it */
01154 while(brackets && *vare) {
01155 if ((vare[0] == '$') && (vare[1] == '[')) {
01156 needsub++;
01157 brackets++;
01158 vare++;
01159 } else if (vare[0] == '[') {
01160 brackets++;
01161 } else if (vare[0] == ']') {
01162 brackets--;
01163 } else if ((vare[0] == '$') && (vare[1] == '{')) {
01164 needsub++;
01165 vare++;
01166 }
01167 vare++;
01168 }
01169 if (brackets)
01170 ast_log(LOG_NOTICE, "Error in extension logic (missing ']')\n");
01171 len = vare - vars - 1;
01172
01173 /* Skip totally over variable name */
01174 whereweare += ( len + 3);
01175
01176 /* Store variable name (and truncate) */
01177 memset(var, 0, sizeof(var));
01178 strncpy(var, vars, sizeof(var) - 1);
01179 var[len] = '\0';
01180
01181 /* Substitute if necessary */
01182 if (needsub) {
01183 memset(ltmp, 0, sizeof(ltmp));
01184 pbx_substitute_variables_helper(c, var, ltmp, sizeof(ltmp) - 1);
01185 vars = ltmp;
01186 } else {
01187 vars = var;
01188 }
01189
01190 /* Evaluate expression */
01191 cp4 = ast_expr(vars);
01192
01193 ast_log(LOG_DEBUG, "Expression is '%s'\n", cp4);
01194
01195 if (cp4) {
01196 length = strlen(cp4);
01197 if (length > count)
01198 length = count;
01199 memcpy(cp2, cp4, length);
01200 count -= length;
01201 cp2 += length;
01202 free(cp4);
01203 }
01204
01205 } else
01206 break;
01207 }
01208 }
|
|
|
|
|
|
|
|
|
|
1.4.2