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