2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 1999 - 2006, Digium, Inc.
6 * Mark Spencer <markster@digium.com>
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
21 * \brief Core PBX routines.
23 * \author Mark Spencer <markster@digium.com>
26 #include <sys/types.h>
38 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
40 #include "asterisk/lock.h"
41 #include "asterisk/cli.h"
42 #include "asterisk/pbx.h"
43 #include "asterisk/channel.h"
44 #include "asterisk/options.h"
45 #include "asterisk/logger.h"
46 #include "asterisk/file.h"
47 #include "asterisk/callerid.h"
48 #include "asterisk/cdr.h"
49 #include "asterisk/config.h"
50 #include "asterisk/term.h"
51 #include "asterisk/manager.h"
52 #include "asterisk/ast_expr.h"
53 #include "asterisk/linkedlists.h"
54 #define SAY_STUBS /* generate declarations and stubs for say methods */
55 #include "asterisk/say.h"
56 #include "asterisk/utils.h"
57 #include "asterisk/causes.h"
58 #include "asterisk/musiconhold.h"
59 #include "asterisk/app.h"
60 #include "asterisk/devicestate.h"
61 #include "asterisk/compat.h"
62 #include "asterisk/stringfields.h"
65 * \note I M P O R T A N T :
67 * The speed of extension handling will likely be among the most important
68 * aspects of this PBX. The switching scheme as it exists right now isn't
69 * terribly bad (it's O(N+M), where N is the # of extensions and M is the avg #
70 * of priorities, but a constant search time here would be great ;-)
75 #define EXT_DATA_SIZE 256
77 #define EXT_DATA_SIZE 8192
80 #define SWITCH_DATA_LENGTH 256
82 #define VAR_BUF_SIZE 4096
85 #define VAR_SOFTTRAN 2
86 #define VAR_HARDTRAN 3
88 #define BACKGROUND_SKIP (1 << 0)
89 #define BACKGROUND_NOANSWER (1 << 1)
90 #define BACKGROUND_MATCHEXTEN (1 << 2)
91 #define BACKGROUND_PLAYBACK (1 << 3)
93 AST_APP_OPTIONS(background_opts, {
94 AST_APP_OPTION('s', BACKGROUND_SKIP),
95 AST_APP_OPTION('n', BACKGROUND_NOANSWER),
96 AST_APP_OPTION('m', BACKGROUND_MATCHEXTEN),
97 AST_APP_OPTION('p', BACKGROUND_PLAYBACK),
100 #define WAITEXTEN_MOH (1 << 0)
102 AST_APP_OPTIONS(waitexten_opts, {
103 AST_APP_OPTION_ARG('m', WAITEXTEN_MOH, 1),
109 \brief ast_exten: An extension
110 The dialplan is saved as a linked list with each context
111 having it's own linked list of extensions - one item per
115 char *exten; /*!< Extension name */
116 int matchcid; /*!< Match caller id ? */
117 const char *cidmatch; /*!< Caller id to match for this extension */
118 int priority; /*!< Priority */
119 const char *label; /*!< Label */
120 struct ast_context *parent; /*!< The context this extension belongs to */
121 const char *app; /*!< Application to execute */
122 void *data; /*!< Data to use (arguments) */
123 void (*datad)(void *); /*!< Data destructor */
124 struct ast_exten *peer; /*!< Next higher priority with our extension */
125 const char *registrar; /*!< Registrar */
126 struct ast_exten *next; /*!< Extension with a greater ID */
130 /*! \brief ast_include: include= support in extensions.conf */
133 const char *rname; /*!< Context to include */
134 const char *registrar; /*!< Registrar */
135 int hastime; /*!< If time construct exists */
136 struct ast_timing timing; /*!< time construct */
137 struct ast_include *next; /*!< Link them together */
141 /*! \brief ast_sw: Switch statement in extensions.conf */
144 const char *registrar; /*!< Registrar */
145 char *data; /*!< Data load */
147 struct ast_sw *next; /*!< Link them together */
152 /*! \brief ast_ignorepat: Ignore patterns in dial plan */
153 struct ast_ignorepat {
154 const char *registrar;
155 struct ast_ignorepat *next;
156 const char pattern[0];
159 /*! \brief ast_context: An extension context */
161 ast_mutex_t lock; /*!< A lock to prevent multiple threads from clobbering the context */
162 struct ast_exten *root; /*!< The root of the list of extensions */
163 struct ast_context *next; /*!< Link them together */
164 struct ast_include *includes; /*!< Include other contexts */
165 struct ast_ignorepat *ignorepats; /*!< Patterns for which to continue playing dialtone */
166 const char *registrar; /*!< Registrar */
167 struct ast_sw *alts; /*!< Alternative switches */
168 char name[0]; /*!< Name of the context */
172 /*! \brief ast_app: A registered application */
174 int (*execute)(struct ast_channel *chan, void *data);
175 const char *synopsis; /*!< Synopsis text for 'show applications' */
176 const char *description; /*!< Description (help text) for 'show application <name>' */
177 struct ast_app *next; /*!< Next app in list */
178 char name[0]; /*!< Name of the application */
181 /*! \brief ast_state_cb: An extension state notify register item */
182 struct ast_state_cb {
185 ast_state_cb_type callback;
186 struct ast_state_cb *next;
189 /*! \brief Structure for dial plan hints
191 Hints are pointers from an extension in the dialplan to one or
192 more devices (tech/name) */
194 struct ast_exten *exten; /*!< Extension */
195 int laststate; /*!< Last known state */
196 struct ast_state_cb *callbacks; /*!< Callback list for this extension */
197 AST_LIST_ENTRY(ast_hint) list; /*!< Pointer to next hint in list */
200 static const struct cfextension_states {
202 const char * const text;
203 } extension_states[] = {
204 { AST_EXTENSION_NOT_INUSE, "Idle" },
205 { AST_EXTENSION_INUSE, "InUse" },
206 { AST_EXTENSION_BUSY, "Busy" },
207 { AST_EXTENSION_UNAVAILABLE, "Unavailable" },
208 { AST_EXTENSION_RINGING, "Ringing" },
209 { AST_EXTENSION_INUSE | AST_EXTENSION_RINGING, "InUse&Ringing" }
212 int ast_pbx_outgoing_cdr_failed(void);
214 static int pbx_builtin_answer(struct ast_channel *, void *);
215 static int pbx_builtin_goto(struct ast_channel *, void *);
216 static int pbx_builtin_hangup(struct ast_channel *, void *);
217 static int pbx_builtin_background(struct ast_channel *, void *);
218 static int pbx_builtin_wait(struct ast_channel *, void *);
219 static int pbx_builtin_waitexten(struct ast_channel *, void *);
220 static int pbx_builtin_resetcdr(struct ast_channel *, void *);
221 static int pbx_builtin_setamaflags(struct ast_channel *, void *);
222 static int pbx_builtin_ringing(struct ast_channel *, void *);
223 static int pbx_builtin_progress(struct ast_channel *, void *);
224 static int pbx_builtin_congestion(struct ast_channel *, void *);
225 static int pbx_builtin_busy(struct ast_channel *, void *);
226 static int pbx_builtin_setglobalvar(struct ast_channel *, void *);
227 static int pbx_builtin_noop(struct ast_channel *, void *);
228 static int pbx_builtin_gotoif(struct ast_channel *, void *);
229 static int pbx_builtin_gotoiftime(struct ast_channel *, void *);
230 static int pbx_builtin_execiftime(struct ast_channel *, void *);
231 static int pbx_builtin_saynumber(struct ast_channel *, void *);
232 static int pbx_builtin_saydigits(struct ast_channel *, void *);
233 static int pbx_builtin_saycharacters(struct ast_channel *, void *);
234 static int pbx_builtin_sayphonetic(struct ast_channel *, void *);
235 int pbx_builtin_setvar(struct ast_channel *, void *);
236 static int pbx_builtin_importvar(struct ast_channel *, void *);
238 AST_MUTEX_DEFINE_STATIC(globalslock);
239 static struct varshead globals;
241 static int autofallthrough = 0;
243 AST_MUTEX_DEFINE_STATIC(maxcalllock);
244 static int countcalls = 0;
246 AST_MUTEX_DEFINE_STATIC(acflock); /*!< Lock for the custom function list */
247 static struct ast_custom_function *acf_root = NULL;
249 /*! \brief Declaration of builtin applications */
250 static struct pbx_builtin {
251 char name[AST_MAX_APP];
252 int (*execute)(struct ast_channel *chan, void *data);
257 /* These applications are built into the PBX core and do not
258 need separate modules */
260 { "Answer", pbx_builtin_answer,
261 "Answer a channel if ringing",
262 " Answer([delay]): If the call has not been answered, this application will\n"
263 "answer it. Otherwise, it has no effect on the call. If a delay is specified,\n"
264 "Asterisk will wait this number of milliseconds before answering the call.\n"
267 { "BackGround", pbx_builtin_background,
268 "Play a file while awaiting extension",
269 " Background(filename1[&filename2...][|options[|langoverride][|context]]):\n"
270 "This application will play the given list of files while waiting for an\n"
271 "extension to be dialed by the calling channel. To continue waiting for digits\n"
272 "after this application has finished playing files, the WaitExten application\n"
273 "should be used. The 'langoverride' option explicity specifies which language\n"
274 "to attempt to use for the requested sound files. If a 'context' is specified,\n"
275 "this is the dialplan context that this application will use when exiting to a\n"
277 " If one of the requested sound files does not exist, call processing will be\n"
280 " s - causes the playback of the message to be skipped\n"
281 " if the channel is not in the 'up' state (i.e. it\n"
282 " hasn't been answered yet.) If this happens, the\n"
283 " application will return immediately.\n"
284 " n - don't answer the channel before playing the files\n"
285 " m - only break if a digit hit matches a one digit\n"
286 " extension in the destination context\n"
289 { "Busy", pbx_builtin_busy,
290 "Indicate the Busy condition",
291 " Busy([timeout]): This application will indicate the busy condition to\n"
292 "the calling channel. If the optional timeout is specified, the calling channel\n"
293 "will be hung up after the specified number of seconds. Otherwise, this\n"
294 "application will wait until the calling channel hangs up.\n"
297 { "Congestion", pbx_builtin_congestion,
298 "Indicate the Congestion condition",
299 " Congestion([timeout]): This application will indicate the congenstion\n"
300 "condition to the calling channel. If the optional timeout is specified, the\n"
301 "calling channel will be hung up after the specified number of seconds.\n"
302 "Otherwise, this application will wait until the calling channel hangs up.\n"
305 { "Goto", pbx_builtin_goto,
306 "Jump to a particular priority, extension, or context",
307 " Goto([[context|]extension|]priority): This application will cause the\n"
308 "calling channel to continue dialplan execution at the specified priority.\n"
309 "If no specific extension, or extension and context, are specified, then this\n"
310 "application will jump to the specified priority of the current extension.\n"
311 " If the attempt to jump to another location in the dialplan is not successful,\n"
312 "then the channel will continue at the next priority of the current extension.\n"
315 { "GotoIf", pbx_builtin_gotoif,
317 " GotoIf(condition?[labeliftrue]:[labeliffalse]): This application will cause\n"
318 "the calling channel to jump to the specified location in the dialplan based on\n"
319 "the evaluation of the given condition. The channel will continue at\n"
320 "'labeliftrue' if the condition is true, or 'labeliffalse' if the condition is\n"
321 "false. The labels are specified with the same syntax as used within the Goto\n"
322 "application. If the label chosen by the condition is omitted, no jump is\n"
323 "performed, but execution continues with the next priority in the dialplan.\n"
326 { "GotoIfTime", pbx_builtin_gotoiftime,
327 "Conditional Goto based on the current time",
328 " GotoIfTime(<times>|<weekdays>|<mdays>|<months>?[[context|]exten|]priority):\n"
329 "This application will have the calling channel jump to the speicified location\n"
330 "int the dialplan if the current time matches the given time specification.\n"
331 "Further information on the time specification can be found in examples\n"
332 "illustrating how to do time-based context includes in the dialplan.\n"
335 { "ExecIfTime", pbx_builtin_execiftime,
336 "Conditional application execution based on the current time",
337 " ExecIfTime(<times>|<weekdays>|<mdays>|<months>?appname[|appargs]):\n"
338 "This application will execute the specified dialplan application, with optional\n"
339 "arguments, if the current time matches the given time specification. Further\n"
340 "information on the time speicification can be found in examples illustrating\n"
341 "how to do time-based context includes in the dialplan.\n"
344 { "Hangup", pbx_builtin_hangup,
345 "Hang up the calling channel",
346 " Hangup(): This application will hang up the calling channel.\n"
349 { "NoOp", pbx_builtin_noop,
351 " NoOp(): This applicatiion does nothing. However, it is useful for debugging\n"
352 "purposes. Any text that is provided as arguments to this application can be\n"
353 "viewed at the Asterisk CLI. This method can be used to see the evaluations of\n"
354 "variables or functions without having any effect."
357 { "Progress", pbx_builtin_progress,
359 " Progress(): This application will request that in-band progress information\n"
360 "be provided to the calling channel.\n"
363 { "ResetCDR", pbx_builtin_resetcdr,
364 "Resets the Call Data Record",
365 " ResetCDR([options]): This application causes the Call Data Record to be\n"
368 " w -- Store the current CDR record before resetting it.\n"
369 " a -- Store any stacked records.\n"
370 " v -- Save CDR variables.\n"
373 { "Ringing", pbx_builtin_ringing,
374 "Indicate ringing tone",
375 " Ringing(): This application will request that the channel indicate a ringing\n"
376 "tone to the user.\n"
379 { "SayNumber", pbx_builtin_saynumber,
381 " SayNumber(digits[,gender]): This application will play the sounds that\n"
382 "correspond to the given number. Optionally, a gender may be specified.\n"
383 "This will use the language that is currently set for the channel. See the\n"
384 "LANGUAGE function for more information on setting the language for the channel.\n"
387 { "SayDigits", pbx_builtin_saydigits,
389 " SayDigits(digits): This application will play the sounds that correspond\n"
390 "to the digits of the given number. This will use the language that is currently\n"
391 "set for the channel. See the LANGUAGE function for more information on setting\n"
392 "the language for the channel.\n"
395 { "SayAlpha", pbx_builtin_saycharacters,
397 " SayAlpha(string): This application will play the sounds that correspond to\n"
398 "the letters of the given string.\n"
401 { "SayPhonetic", pbx_builtin_sayphonetic,
403 " SayPhonetic(string): This application will play the sounds from the phonetic\n"
404 "alphabet that correspond to the letters in the given string.\n"
407 { "SetAMAFlags", pbx_builtin_setamaflags,
409 " SetAMAFlags([flag]): This channel will set the channel's AMA Flags for billing\n"
413 { "SetGlobalVar", pbx_builtin_setglobalvar,
414 "Set a global variable to a given value",
415 " SetGlobalVar(variable=value): This application sets a given global variable to\n"
416 "the specified value.\n"
419 { "Set", pbx_builtin_setvar,
420 "Set channel variable(s) or function value(s)",
421 " Set(name1=value1|name2=value2|..[|options])\n"
422 "This function can be used to set the value of channel variables or dialplan\n"
423 "functions. It will accept up to 24 name/value pairs. When setting variables,\n"
424 "if the variable name is prefixed with _, the variable will be inherited into\n"
425 "channels created from the current channel. If the variable name is prefixed\n"
426 "with __, the variable will be inherited into channels created from the current\n"
427 "channel and all children channels.\n"
429 " g - Set variable globally instead of on the channel\n"
430 " (applies only to variables, not functions)\n"
433 { "ImportVar", pbx_builtin_importvar,
434 "Import a variable from a channel into a new variable",
435 " ImportVar(newvar=channelname|variable): This application imports a variable\n"
436 "from the specified channel (as opposed to the current one) and stores it as\n"
437 "a variable in the current channel (the channel that is calling this\n"
438 "application). Variables created by this application have the same inheritance\n"
439 "properties as those created with the Set application. See the documentation for\n"
440 "Set for more information.\n"
443 { "Wait", pbx_builtin_wait,
444 "Waits for some time",
445 " Wait(seconds): This application waits for a specified number of seconds.\n"
446 "Then, dialplan execution will continue at the next priority.\n"
447 " Note that the seconds can be passed with fractions of a second. For example,\n"
448 "'1.5' will ask the application to wait for 1.5 seconds.\n"
451 { "WaitExten", pbx_builtin_waitexten,
452 "Waits for an extension to be entered",
453 " WaitExten([seconds][|options]): This application waits for the user to enter\n"
454 "a new extension for a specified number of seconds.\n"
455 " Note that the seconds can be passed with fractions of a second. For example,\n"
456 "'1.5' will ask the application to wait for 1.5 seconds.\n"
458 " m[(x)] - Provide music on hold to the caller while waiting for an extension.\n"
459 " Optionally, specify the class for music on hold within parenthesis.\n"
464 static struct ast_context *contexts = NULL;
465 AST_MUTEX_DEFINE_STATIC(conlock); /*!< Lock for the ast_context list */
466 static struct ast_app *apps = NULL;
467 AST_MUTEX_DEFINE_STATIC(applock); /*!< Lock for the application list */
469 struct ast_switch *switches = NULL;
470 AST_MUTEX_DEFINE_STATIC(switchlock); /*!< Lock for switches */
472 static int stateid = 1;
473 static AST_LIST_HEAD_STATIC(hints, ast_hint);
474 struct ast_state_cb *statecbs = NULL;
477 \note This function is special. It saves the stack so that no matter
478 how many times it is called, it returns to the same place */
479 int pbx_exec(struct ast_channel *c, /*!< Channel */
480 struct ast_app *app, /*!< Application */
481 void *data, /*!< Data for execution */
482 int newstack) /*!< Force stack increment */
489 int (*execute)(struct ast_channel *chan, void *data) = app->execute;
493 ast_cdr_setapp(c->cdr, app->name, data);
495 /* save channel values */
496 saved_c_appl= c->appl;
497 saved_c_data= c->data;
501 res = execute(c, data);
502 /* restore channel values */
503 c->appl= saved_c_appl;
504 c->data= saved_c_data;
507 ast_log(LOG_WARNING, "You really didn't want to call this function with newstack set to 0\n");
512 /*! Go no deeper than this through includes (not counting loops) */
513 #define AST_PBX_MAX_STACK 128
515 #define HELPER_EXISTS 0
516 #define HELPER_SPAWN 1
517 #define HELPER_EXEC 2
518 #define HELPER_CANMATCH 3
519 #define HELPER_MATCHMORE 4
520 #define HELPER_FINDLABEL 5
522 /*! \brief Find application handle in linked list
524 struct ast_app *pbx_findapp(const char *app)
528 if (ast_mutex_lock(&applock)) {
529 ast_log(LOG_WARNING, "Unable to obtain application lock\n");
532 for (tmp = apps; tmp; tmp = tmp->next) {
533 if (!strcasecmp(tmp->name, app))
536 ast_mutex_unlock(&applock);
540 static struct ast_switch *pbx_findswitch(const char *sw)
542 struct ast_switch *asw;
544 if (ast_mutex_lock(&switchlock)) {
545 ast_log(LOG_WARNING, "Unable to obtain application lock\n");
548 for (asw = switches; asw; asw = asw->next) {
549 if (!strcasecmp(asw->name, sw))
552 ast_mutex_unlock(&switchlock);
556 static inline int include_valid(struct ast_include *i)
561 return ast_check_timing(&(i->timing));
564 static void pbx_destroy(struct ast_pbx *p)
569 #define EXTENSION_MATCH_CORE(data,pattern,match) {\
570 /* All patterns begin with _ */\
571 if (pattern[0] != '_') \
573 /* Start optimistic */\
576 while(match && *data && *pattern && (*pattern != '/')) {\
577 while (*data == '-' && (*(data+1) != '\0')) data++;\
578 switch(toupper(*pattern)) {\
585 where=strchr(pattern,']');\
587 border=(int)(where-pattern);\
588 if (!where || border > strlen(pattern)) {\
589 ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n");\
592 for (i=0; i<border; i++) {\
595 if (pattern[i+1]=='-') {\
596 if (*data >= pattern[i] && *data <= pattern[i+2]) {\
603 if (res==1 || *data==pattern[i]) {\
612 if ((*data < '2') || (*data > '9'))\
616 if ((*data < '0') || (*data > '9'))\
620 if ((*data < '1') || (*data > '9'))\
631 /* Ignore these characters */\
635 if (*data != *pattern)\
641 /* If we ran off the end of the data and the pattern ends in '!', match */\
642 if (match && !*data && (*pattern == '!'))\
646 int ast_extension_match(const char *pattern, const char *data)
649 /* If they're the same return */
650 if (!strcmp(pattern, data))
652 EXTENSION_MATCH_CORE(data,pattern,match);
653 /* Must be at the end of both */
654 if (*data || (*pattern && (*pattern != '/')))
659 int ast_extension_close(const char *pattern, const char *data, int needmore)
662 /* If "data" is longer, it can'be a subset of pattern unless
663 pattern is a pattern match */
664 if ((strlen(pattern) < strlen(data)) && (pattern[0] != '_'))
667 if ((ast_strlen_zero((char *)data) || !strncasecmp(pattern, data, strlen(data))) &&
668 (!needmore || (strlen(pattern) > strlen(data)))) {
671 EXTENSION_MATCH_CORE(data,pattern,match);
672 /* If there's more or we don't care about more, or if it's a possible early match,
673 return non-zero; otherwise it's a miss */
674 if (!needmore || *pattern || match == 2) {
680 struct ast_context *ast_context_find(const char *name)
682 struct ast_context *tmp;
683 ast_mutex_lock(&conlock);
685 for (tmp = contexts; tmp; tmp = tmp->next) {
686 if (!strcasecmp(name, tmp->name))
691 ast_mutex_unlock(&conlock);
695 #define STATUS_NO_CONTEXT 1
696 #define STATUS_NO_EXTENSION 2
697 #define STATUS_NO_PRIORITY 3
698 #define STATUS_NO_LABEL 4
699 #define STATUS_SUCCESS 5
701 static int matchcid(const char *cidpattern, const char *callerid)
705 /* If the Caller*ID pattern is empty, then we're matching NO Caller*ID, so
706 failing to get a number should count as a match, otherwise not */
708 if (!ast_strlen_zero(cidpattern))
716 return ast_extension_match(cidpattern, callerid);
719 static struct ast_exten *pbx_find_extension(struct ast_channel *chan, struct ast_context *bypass, const char *context, const char *exten, int priority, const char *label, const char *callerid, int action, char *incstack[], int *stacklen, int *status, struct ast_switch **swo, char **data, const char **foundcontext)
722 struct ast_context *tmp;
723 struct ast_exten *e, *eroot;
724 struct ast_include *i;
726 struct ast_switch *asw;
728 /* Initialize status if appropriate */
730 *status = STATUS_NO_CONTEXT;
734 /* Check for stack overflow */
735 if (*stacklen >= AST_PBX_MAX_STACK) {
736 ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n");
739 /* Check first to see if we've already been checked */
740 for (x = 0; x < *stacklen; x++) {
741 if (!strcasecmp(incstack[x], context))
748 for (; tmp; tmp = tmp->next) {
750 if (bypass || !strcmp(tmp->name, context)) {
751 struct ast_exten *earlymatch = NULL;
753 if (*status < STATUS_NO_EXTENSION)
754 *status = STATUS_NO_EXTENSION;
755 for (eroot = tmp->root; eroot; eroot = eroot->next) {
757 /* Match extension */
758 if ((((action != HELPER_MATCHMORE) && ast_extension_match(eroot->exten, exten)) ||
759 ((action == HELPER_CANMATCH) && (ast_extension_close(eroot->exten, exten, 0))) ||
760 ((action == HELPER_MATCHMORE) && (match = ast_extension_close(eroot->exten, exten, 1)))) &&
761 (!eroot->matchcid || matchcid(eroot->cidmatch, callerid))) {
763 if (action == HELPER_MATCHMORE && match == 2 && !earlymatch) {
764 /* It matched an extension ending in a '!' wildcard
765 So ignore it for now, unless there's a better match */
768 if (*status < STATUS_NO_PRIORITY)
769 *status = STATUS_NO_PRIORITY;
770 for (e = eroot; e; e = e->peer) {
772 if (action == HELPER_FINDLABEL) {
773 if (*status < STATUS_NO_LABEL)
774 *status = STATUS_NO_LABEL;
775 if (label && e->label && !strcmp(label, e->label)) {
776 *status = STATUS_SUCCESS;
777 *foundcontext = context;
780 } else if (e->priority == priority) {
781 *status = STATUS_SUCCESS;
782 *foundcontext = context;
790 /* Bizarre logic for HELPER_MATCHMORE. We return zero to break out
791 of the loop waiting for more digits, and _then_ match (normally)
792 the extension we ended up with. We got an early-matching wildcard
793 pattern, so return NULL to break out of the loop. */
796 /* Check alternative switches */
797 for (sw = tmp->alts; sw; sw = sw->next) {
798 if ((asw = pbx_findswitch(sw->name))) {
799 /* Substitute variables now */
801 pbx_substitute_variables_helper(chan, sw->data, sw->tmpdata, SWITCH_DATA_LENGTH - 1);
802 if (action == HELPER_CANMATCH)
803 res = asw->canmatch ? asw->canmatch(chan, context, exten, priority, callerid, sw->eval ? sw->tmpdata : sw->data) : 0;
804 else if (action == HELPER_MATCHMORE)
805 res = asw->matchmore ? asw->matchmore(chan, context, exten, priority, callerid, sw->eval ? sw->tmpdata : sw->data) : 0;
807 res = asw->exists ? asw->exists(chan, context, exten, priority, callerid, sw->eval ? sw->tmpdata : sw->data) : 0;
811 *data = sw->eval ? sw->tmpdata : sw->data;
812 *foundcontext = context;
816 ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name);
819 /* Setup the stack */
820 incstack[*stacklen] = tmp->name;
822 /* Now try any includes we have in this context */
823 for (i = tmp->includes; i; i = i->next) {
824 if (include_valid(i)) {
825 if ((e = pbx_find_extension(chan, bypass, i->rname, exten, priority, label, callerid, action, incstack, stacklen, status, swo, data, foundcontext)))
837 /* Note that it's negative -- that's important later. */
838 #define DONT_HAVE_LENGTH 0x80000000
840 /*! \brief extract offset:length from variable name.
841 * Returns 1 if there is a offset:length part, which is
842 * trimmed off (values go into variables)
844 static int parse_variable_name(char *var, int *offset, int *length, int *isfunc)
849 *length = DONT_HAVE_LENGTH;
851 for (; *var; var++) {
855 } else if (*var == ')') {
857 } else if (*var == ':' && parens == 0) {
859 sscanf(var, "%d:%d", offset, length);
860 return 1; /* offset:length valid */
866 /*! \brief takes a substring. It is ok to call with value == workspace.
868 * offset < 0 means start from the end of the string and set the beginning
869 * to be that many characters back.
870 * length is the length of the substring, -1 means unlimited
871 * (we take any negative value).
872 * Always return a copy in workspace.
874 static char *substring(const char *value, int offset, int length, char *workspace, size_t workspace_len)
876 char *ret = workspace;
877 int lr; /* length of the input string after the copy */
879 ast_copy_string(workspace, value, workspace_len); /* always make a copy */
881 if (offset == 0 && length < 0) /* take the whole string */
884 lr = strlen(ret); /* compute length after copy, so we never go out of the workspace */
886 if (offset < 0) { /* translate negative offset into positive ones */
887 offset = lr + offset;
888 if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */
892 /* too large offset result in empty string so we know what to return */
894 return ret + lr; /* the final '\0' */
896 ret += offset; /* move to the start position */
897 if (length >= 0 && length < lr - offset) /* truncate if necessary */
903 /*! \brief pbx_retrieve_variable: Support for Asterisk built-in variables and
904 functions in the dialplan
906 void pbx_retrieve_variable(struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp)
908 const char not_found = '\0';
910 const char *s; /* the result */
912 int i, need_substring;
913 struct varshead *places[2] = { headp, &globals }; /* list of places where we may look */
916 places[0] = &c->varshead;
919 * Make a copy of var because parse_variable_name() modifies the string.
920 * Then if called directly, we might need to run substring() on the result;
921 * remember this for later in 'need_substring', 'offset' and 'length'
923 tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */
924 need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */);
927 * Look first into predefined variables, then into variable lists.
928 * Variable 's' points to the result, according to the following rules:
929 * s == ¬_found (set at the beginning) means that we did not find a
930 * matching variable and need to look into more places.
931 * If s != ¬_found, s is a valid result string as follows:
932 * s = NULL if the variable does not have a value;
933 * you typically do this when looking for an unset predefined variable.
934 * s = workspace if the result has been assembled there;
935 * typically done when the result is built e.g. with an snprintf(),
936 * so we don't need to do an additional copy.
937 * s != workspace in case we have a string, that needs to be copied
938 * (the ast_copy_string is done once for all at the end).
939 * Typically done when the result is already available in some string.
941 s = ¬_found; /* default value */
942 if (c) { /* This group requires a valid channel */
943 /* Names with common parts are looked up a piece at a time using strncmp. */
944 if (!strncmp(var, "CALL", 4)) {
945 if (!strncmp(var + 4, "ING", 3)) {
946 if (!strcmp(var + 7, "PRES")) { /* CALLINGPRES */
947 snprintf(workspace, workspacelen, "%d", c->cid.cid_pres);
949 } else if (!strcmp(var + 7, "ANI2")) { /* CALLINGANI2 */
950 snprintf(workspace, workspacelen, "%d", c->cid.cid_ani2);
952 } else if (!strcmp(var + 7, "TON")) { /* CALLINGTON */
953 snprintf(workspace, workspacelen, "%d", c->cid.cid_ton);
955 } else if (!strcmp(var + 7, "TNS")) { /* CALLINGTNS */
956 snprintf(workspace, workspacelen, "%d", c->cid.cid_tns);
960 } else if (!strcmp(var, "HINT")) {
961 s = ast_get_hint(workspace, workspacelen, NULL, 0, c, c->context, c->exten) ? workspace : NULL;
962 } else if (!strcmp(var, "HINTNAME")) {
963 s = ast_get_hint(NULL, 0, workspace, workspacelen, c, c->context, c->exten) ? workspace : NULL;
964 } else if (!strcmp(var, "EXTEN")) {
966 } else if (!strcmp(var, "CONTEXT")) {
968 } else if (!strcmp(var, "PRIORITY")) {
969 snprintf(workspace, workspacelen, "%d", c->priority);
971 } else if (!strcmp(var, "CHANNEL")) {
973 } else if (!strcmp(var, "UNIQUEID")) {
975 } else if (!strcmp(var, "HANGUPCAUSE")) {
976 snprintf(workspace, workspacelen, "%d", c->hangupcause);
980 if (s == ¬_found) { /* look for more */
981 if (!strcmp(var, "EPOCH")) {
982 snprintf(workspace, workspacelen, "%u",(int)time(NULL));
984 } else if (!strcmp(var, "SYSTEMNAME")) {
985 s = ast_config_AST_SYSTEM_NAME;
988 /* if not found, look into chanvars or global vars */
989 for (i = 0; s == ¬_found && i < (sizeof(places) / sizeof(places[0])); i++) {
990 struct ast_var_t *variables;
993 if (places[i] == &globals)
994 ast_mutex_lock(&globalslock);
995 AST_LIST_TRAVERSE(places[i], variables, entries) {
996 if (strcasecmp(ast_var_name(variables), var)==0) {
997 s = ast_var_value(variables);
1001 if (places[i] == &globals)
1002 ast_mutex_unlock(&globalslock);
1004 if (s == ¬_found || s == NULL)
1008 ast_copy_string(workspace, s, workspacelen);
1011 *ret = substring(*ret, offset, length, workspace, workspacelen);
1015 /*! \brief CLI function to show installed custom functions
1016 \addtogroup CLI_functions
1018 static int handle_show_functions(int fd, int argc, char *argv[])
1020 struct ast_custom_function *acf;
1025 if (argc == 4 && (!strcmp(argv[2], "like")) ) {
1027 } else if (argc != 2) {
1028 return RESULT_SHOWUSAGE;
1031 ast_cli(fd, "%s Custom Functions:\n--------------------------------------------------------------------------------\n", like ? "Matching" : "Installed");
1033 for (acf = acf_root ; acf; acf = acf->next) {
1036 if (strstr(acf->name, argv[3])) {
1046 ast_cli(fd, "%-20.20s %-35.35s %s\n", acf->name, acf->syntax, acf->synopsis);
1050 ast_cli(fd, "%d %scustom functions installed.\n", count_acf, like ? "matching " : "");
1055 static int handle_show_function(int fd, int argc, char *argv[])
1057 struct ast_custom_function *acf;
1058 /* Maximum number of characters added by terminal coloring is 22 */
1059 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40];
1060 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL;
1061 char stxtitle[40], *syntax = NULL;
1062 int synopsis_size, description_size, syntax_size;
1064 if (argc < 3) return RESULT_SHOWUSAGE;
1066 if (!(acf = ast_custom_function_find(argv[2]))) {
1067 ast_cli(fd, "No function by that name registered.\n");
1068 return RESULT_FAILURE;
1073 synopsis_size = strlen(acf->synopsis) + 23;
1075 synopsis_size = strlen("Not available") + 23;
1076 synopsis = alloca(synopsis_size);
1079 description_size = strlen(acf->desc) + 23;
1081 description_size = strlen("Not available") + 23;
1082 description = alloca(description_size);
1085 syntax_size = strlen(acf->syntax) + 23;
1087 syntax_size = strlen("Not available") + 23;
1088 syntax = alloca(syntax_size);
1090 snprintf(info, 64 + AST_MAX_APP, "\n -= Info about function '%s' =- \n\n", acf->name);
1091 term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22);
1092 term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40);
1093 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
1094 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
1096 acf->syntax ? acf->syntax : "Not available",
1097 COLOR_CYAN, 0, syntax_size);
1098 term_color(synopsis,
1099 acf->synopsis ? acf->synopsis : "Not available",
1100 COLOR_CYAN, 0, synopsis_size);
1101 term_color(description,
1102 acf->desc ? acf->desc : "Not available",
1103 COLOR_CYAN, 0, description_size);
1105 ast_cli(fd,"%s%s%s\n\n%s%s\n\n%s%s\n", infotitle, stxtitle, syntax, syntitle, synopsis, destitle, description);
1107 return RESULT_SUCCESS;
1110 static char *complete_show_function(const char *line, const char *word, int pos, int state)
1112 struct ast_custom_function *acf;
1115 int wordlen = strlen(word);
1117 /* try to lock functions list ... */
1118 if (ast_mutex_lock(&acflock)) {
1119 ast_log(LOG_ERROR, "Unable to lock function list\n");
1123 /* case-insensitive for convenience in this 'complete' function */
1124 for (acf = acf_root; acf && !ret; acf = acf->next) {
1125 if (!strncasecmp(word, acf->name, wordlen) && ++which > state)
1126 ret = strdup(acf->name);
1129 ast_mutex_unlock(&acflock);
1134 struct ast_custom_function* ast_custom_function_find(const char *name)
1136 struct ast_custom_function *acfptr;
1138 /* try to lock functions list ... */
1139 if (ast_mutex_lock(&acflock)) {
1140 ast_log(LOG_ERROR, "Unable to lock function list\n");
1144 for (acfptr = acf_root; acfptr; acfptr = acfptr->next) {
1145 if (!strcmp(name, acfptr->name))
1149 ast_mutex_unlock(&acflock);
1154 int ast_custom_function_unregister(struct ast_custom_function *acf)
1156 struct ast_custom_function *acfptr, *lastacf = NULL;
1162 /* try to lock functions list ... */
1163 if (ast_mutex_lock(&acflock)) {
1164 ast_log(LOG_ERROR, "Unable to lock function list\n");
1168 for (acfptr = acf_root; acfptr; acfptr = acfptr->next) {
1169 if (acfptr == acf) {
1171 lastacf->next = acf->next;
1173 acf_root = acf->next;
1181 ast_mutex_unlock(&acflock);
1183 if (!res && (option_verbose > 1))
1184 ast_verbose(VERBOSE_PREFIX_2 "Unregistered custom function %s\n", acf->name);
1189 int ast_custom_function_register(struct ast_custom_function *acf)
1191 struct ast_custom_function *cur, *last = NULL;
1197 /* try to lock functions list ... */
1198 if (ast_mutex_lock(&acflock)) {
1199 ast_log(LOG_ERROR, "Unable to lock function list. Failed registering function %s\n", acf->name);
1203 if (ast_custom_function_find(acf->name)) {
1204 ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name);
1205 ast_mutex_unlock(&acflock);
1209 for (cur = acf_root; cur; cur = cur->next) {
1210 if (strcmp(acf->name, cur->name) < 0) {
1216 acf->next = acf_root;
1224 /* Wasn't before anything else, put it at the end */
1233 ast_mutex_unlock(&acflock);
1235 if (option_verbose > 1)
1236 ast_verbose(VERBOSE_PREFIX_2 "Registered custom function %s\n", acf->name);
1241 int ast_func_read(struct ast_channel *chan, char *function, char *workspace, size_t len)
1243 char *args = NULL, *p;
1244 struct ast_custom_function *acfptr;
1246 if ((args = strchr(function, '('))) {
1248 if ((p = strrchr(args, ')')))
1251 ast_log(LOG_WARNING, "Can't find trailing parenthesis?\n");
1253 ast_log(LOG_WARNING, "Function doesn't contain parentheses. Assuming null argument.\n");
1256 if ((acfptr = ast_custom_function_find(function))) {
1257 /* run the custom function */
1259 return acfptr->read(chan, function, args, workspace, len);
1261 ast_log(LOG_ERROR, "Function %s cannot be read\n", function);
1263 ast_log(LOG_ERROR, "Function %s not registered\n", function);
1269 int ast_func_write(struct ast_channel *chan, char *function, const char *value)
1271 char *args = NULL, *p;
1272 struct ast_custom_function *acfptr;
1274 if ((args = strchr(function, '('))) {
1276 if ((p = strrchr(args, ')')))
1279 ast_log(LOG_WARNING, "Can't find trailing parenthesis?\n");
1281 ast_log(LOG_WARNING, "Function doesn't contain parentheses. Assuming null argument.\n");
1284 if ((acfptr = ast_custom_function_find(function))) {
1285 /* run the custom function */
1287 return acfptr->write(chan, function, args, value);
1289 ast_log(LOG_ERROR, "Function %s is read-only, it cannot be written to\n", function);
1291 ast_log(LOG_ERROR, "Function %s not registered\n", function);
1297 static void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count)
1300 const char *tmp, *whereweare;
1301 int length, offset, offset2, isfunction;
1302 char *workspace = NULL;
1303 char *ltmp = NULL, *var = NULL;
1304 char *nextvar, *nextexp, *nextthing;
1306 int pos, brackets, needsub, len;
1308 /* Substitutes variables into cp2, based on string cp1, and assuming cp2 to be
1311 while(!ast_strlen_zero(whereweare) && count) {
1312 /* Assume we're copying the whole remaining string */
1313 pos = strlen(whereweare);
1316 nextthing = strchr(whereweare, '$');
1318 switch(nextthing[1]) {
1320 nextvar = nextthing;
1321 pos = nextvar - whereweare;
1324 nextexp = nextthing;
1325 pos = nextexp - whereweare;
1331 /* Can't copy more than 'count' bytes */
1335 /* Copy that many bytes */
1336 memcpy(cp2, whereweare, pos);
1344 /* We have a variable. Find the start and end, and determine
1345 if we are going to have to recursively call ourselves on the
1347 vars = vare = nextvar + 2;
1351 /* Find the end of it */
1352 while(brackets && *vare) {
1353 if ((vare[0] == '$') && (vare[1] == '{')) {
1356 } else if (vare[0] == '}') {
1358 } else if ((vare[0] == '$') && (vare[1] == '['))
1363 ast_log(LOG_NOTICE, "Error in extension logic (missing '}')\n");
1364 len = vare - vars - 1;
1366 /* Skip totally over variable string */
1367 whereweare += (len + 3);
1370 var = alloca(VAR_BUF_SIZE);
1372 /* Store variable name (and truncate) */
1373 ast_copy_string(var, vars, len + 1);
1375 /* Substitute if necessary */
1378 ltmp = alloca(VAR_BUF_SIZE);
1380 memset(ltmp, 0, VAR_BUF_SIZE);
1381 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1);
1388 workspace = alloca(VAR_BUF_SIZE);
1390 workspace[0] = '\0';
1392 parse_variable_name(vars, &offset, &offset2, &isfunction);
1394 /* Evaluate function */
1395 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
1397 ast_log(LOG_DEBUG, "Function result is '%s'\n", cp4 ? cp4 : "(null)");
1399 /* Retrieve variable value */
1400 pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp);
1403 cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE);
1405 length = strlen(cp4);
1408 memcpy(cp2, cp4, length);
1412 } else if (nextexp) {
1413 /* We have an expression. Find the start and end, and determine
1414 if we are going to have to recursively call ourselves on the
1416 vars = vare = nextexp + 2;
1420 /* Find the end of it */
1421 while(brackets && *vare) {
1422 if ((vare[0] == '$') && (vare[1] == '[')) {
1426 } else if (vare[0] == '[') {
1428 } else if (vare[0] == ']') {
1430 } else if ((vare[0] == '$') && (vare[1] == '{')) {
1437 ast_log(LOG_NOTICE, "Error in extension logic (missing ']')\n");
1438 len = vare - vars - 1;
1440 /* Skip totally over expression */
1441 whereweare += (len + 3);
1444 var = alloca(VAR_BUF_SIZE);
1446 /* Store variable name (and truncate) */
1447 ast_copy_string(var, vars, len + 1);
1449 /* Substitute if necessary */
1452 ltmp = alloca(VAR_BUF_SIZE);
1454 memset(ltmp, 0, VAR_BUF_SIZE);
1455 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1);
1461 length = ast_expr(vars, cp2, count);
1464 ast_log(LOG_DEBUG, "Expression result is '%s'\n", cp2);
1473 void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count)
1475 pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count);
1478 void pbx_substitute_variables_varshead(struct varshead *headp, const char *cp1, char *cp2, int count)
1480 pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count);
1483 static void pbx_substitute_variables(char *passdata, int datalen, struct ast_channel *c, struct ast_exten *e)
1485 memset(passdata, 0, datalen);
1487 /* No variables or expressions in e->data, so why scan it? */
1488 if (!strchr(e->data, '$') && !strstr(e->data,"${") && !strstr(e->data,"$[") && !strstr(e->data,"$(")) {
1489 ast_copy_string(passdata, e->data, datalen);
1493 pbx_substitute_variables_helper(c, e->data, passdata, datalen - 1);
1496 static int pbx_extension_helper(struct ast_channel *c, struct ast_context *con, const char *context, const char *exten, int priority, const char *label, const char *callerid, int action)
1498 struct ast_exten *e;
1499 struct ast_app *app;
1500 struct ast_switch *sw;
1502 const char *foundcontext=NULL;
1506 char *incstack[AST_PBX_MAX_STACK];
1507 char passdata[EXT_DATA_SIZE];
1511 char tmp3[EXT_DATA_SIZE];
1513 char atmp2[EXT_DATA_SIZE+100];
1515 if (ast_mutex_lock(&conlock)) {
1516 ast_log(LOG_WARNING, "Unable to obtain lock\n");
1517 if ((action == HELPER_EXISTS) || (action == HELPER_CANMATCH) || (action == HELPER_MATCHMORE))
1522 e = pbx_find_extension(c, con, context, exten, priority, label, callerid, action, incstack, &stacklen, &status, &sw, &data, &foundcontext);
1525 case HELPER_CANMATCH:
1526 ast_mutex_unlock(&conlock);
1529 ast_mutex_unlock(&conlock);
1531 case HELPER_FINDLABEL:
1533 ast_mutex_unlock(&conlock);
1535 case HELPER_MATCHMORE:
1536 ast_mutex_unlock(&conlock);
1542 app = pbx_findapp(e->app);
1543 ast_mutex_unlock(&conlock);
1545 if (c->context != context)
1546 ast_copy_string(c->context, context, sizeof(c->context));
1547 if (c->exten != exten)
1548 ast_copy_string(c->exten, exten, sizeof(c->exten));
1549 c->priority = priority;
1550 pbx_substitute_variables(passdata, sizeof(passdata), c, e);
1552 ast_log(LOG_DEBUG, "Launching '%s'\n", app->name);
1553 snprintf(atmp, 80, "STACK-%s-%s-%d", context, exten, priority);
1554 snprintf(atmp2, EXT_DATA_SIZE+100, "%s(\"%s\", \"%s\") %s", app->name, c->name, passdata, (newstack ? "in new stack" : "in same stack"));
1555 pbx_builtin_setvar_helper(c, atmp, atmp2);
1557 if (option_verbose > 2)
1558 ast_verbose( VERBOSE_PREFIX_3 "Executing %s(\"%s\", \"%s\") %s\n",
1559 term_color(tmp, app->name, COLOR_BRCYAN, 0, sizeof(tmp)),
1560 term_color(tmp2, c->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)),
1561 term_color(tmp3, passdata, COLOR_BRMAGENTA, 0, sizeof(tmp3)),
1562 (newstack ? "in new stack" : "in same stack"));
1563 manager_event(EVENT_FLAG_CALL, "Newexten",
1568 "Application: %s\r\n"
1571 c->name, c->context, c->exten, c->priority, app->name, passdata, c->uniqueid);
1572 res = pbx_exec(c, app, passdata, newstack);
1575 ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority);
1579 ast_log(LOG_WARNING, "Huh (%d)?\n", action);
1584 case HELPER_CANMATCH:
1585 ast_mutex_unlock(&conlock);
1588 ast_mutex_unlock(&conlock);
1590 case HELPER_MATCHMORE:
1591 ast_mutex_unlock(&conlock);
1593 case HELPER_FINDLABEL:
1594 ast_mutex_unlock(&conlock);
1600 ast_mutex_unlock(&conlock);
1602 res = sw->exec(c, foundcontext ? foundcontext : context, exten, priority, callerid, newstack, data);
1604 ast_log(LOG_WARNING, "No execution engine for switch %s\n", sw->name);
1609 ast_log(LOG_WARNING, "Huh (%d)?\n", action);
1613 ast_mutex_unlock(&conlock);
1615 case STATUS_NO_CONTEXT:
1616 if ((action != HELPER_EXISTS) && (action != HELPER_MATCHMORE))
1617 ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", context);
1619 case STATUS_NO_EXTENSION:
1620 if ((action != HELPER_EXISTS) && (action != HELPER_CANMATCH) && (action != HELPER_MATCHMORE))
1621 ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, context);
1623 case STATUS_NO_PRIORITY:
1624 if ((action != HELPER_EXISTS) && (action != HELPER_CANMATCH) && (action != HELPER_MATCHMORE))
1625 ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, context);
1627 case STATUS_NO_LABEL:
1629 ast_log(LOG_NOTICE, "No such label '%s' in extension '%s' in context '%s'\n", label, exten, context);
1632 ast_log(LOG_DEBUG, "Shouldn't happen!\n");
1635 if ((action != HELPER_EXISTS) && (action != HELPER_CANMATCH) && (action != HELPER_MATCHMORE))
1643 /*! \brief ast_hint_extension: Find hint for given extension in context */
1644 static struct ast_exten *ast_hint_extension(struct ast_channel *c, const char *context, const char *exten)
1646 struct ast_exten *e;
1647 struct ast_switch *sw;
1649 const char *foundcontext = NULL;
1651 char *incstack[AST_PBX_MAX_STACK];
1654 if (ast_mutex_lock(&conlock)) {
1655 ast_log(LOG_WARNING, "Unable to obtain lock\n");
1658 e = pbx_find_extension(c, NULL, context, exten, PRIORITY_HINT, NULL, "", HELPER_EXISTS, incstack, &stacklen, &status, &sw, &data, &foundcontext);
1659 ast_mutex_unlock(&conlock);
1663 /*! \brief ast_extensions_state2: Check state of extension by using hints */
1664 static int ast_extension_state2(struct ast_exten *e)
1666 char hint[AST_MAX_EXTENSION] = "";
1669 int allunavailable = 1, allbusy = 1, allfree = 1;
1670 int busy = 0, inuse = 0, ring = 0;
1675 ast_copy_string(hint, ast_get_extension_app(e), sizeof(hint));
1677 cur = hint; /* On or more devices separated with a & character */
1679 rest = strchr(cur, '&');
1685 res = ast_device_state(cur);
1687 case AST_DEVICE_NOT_INUSE:
1691 case AST_DEVICE_INUSE:
1696 case AST_DEVICE_RINGING:
1701 case AST_DEVICE_BUSY:
1706 case AST_DEVICE_UNAVAILABLE:
1707 case AST_DEVICE_INVALID:
1720 return AST_EXTENSION_RINGING;
1722 return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING);
1724 return AST_EXTENSION_INUSE;
1726 return AST_EXTENSION_NOT_INUSE;
1728 return AST_EXTENSION_BUSY;
1730 return AST_EXTENSION_UNAVAILABLE;
1732 return AST_EXTENSION_INUSE;
1734 return AST_EXTENSION_NOT_INUSE;
1737 /*! \brief ast_extension_state2str: Return extension_state as string */
1738 const char *ast_extension_state2str(int extension_state)
1742 for (i = 0; (i < (sizeof(extension_states) / sizeof(extension_states[0]))); i++) {
1743 if (extension_states[i].extension_state == extension_state) {
1744 return extension_states[i].text;
1750 /*! \brief ast_extension_state: Check extension state for an extension by using hint */
1751 int ast_extension_state(struct ast_channel *c, const char *context, const char *exten)
1753 struct ast_exten *e;
1755 e = ast_hint_extension(c, context, exten); /* Do we have a hint for this extension ? */
1757 return -1; /* No hint, return -1 */
1759 return ast_extension_state2(e); /* Check all devices in the hint */
1762 void ast_hint_state_changed(const char *device)
1764 struct ast_hint *hint;
1765 struct ast_state_cb *cblist;
1766 char buf[AST_MAX_EXTENSION];
1771 AST_LIST_LOCK(&hints);
1773 AST_LIST_TRAVERSE(&hints, hint, list) {
1774 ast_copy_string(buf, ast_get_extension_app(hint->exten), sizeof(buf));
1776 for (cur = strsep(&parse, "&"); cur; cur = strsep(&parse, "&")) {
1777 if (strcasecmp(cur, device))
1780 /* Get device state for this hint */
1781 state = ast_extension_state2(hint->exten);
1783 if ((state == -1) || (state == hint->laststate))
1786 /* Device state changed since last check - notify the watchers */
1788 /* For general callbacks */
1789 for (cblist = statecbs; cblist; cblist = cblist->next)
1790 cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data);
1792 /* For extension callbacks */
1793 for (cblist = hint->callbacks; cblist; cblist = cblist->next)
1794 cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data);
1796 hint->laststate = state;
1801 AST_LIST_UNLOCK(&hints);
1804 /*! \brief ast_extension_state_add: Add watcher for extension states */
1805 int ast_extension_state_add(const char *context, const char *exten,
1806 ast_state_cb_type callback, void *data)
1808 struct ast_hint *hint;
1809 struct ast_state_cb *cblist;
1810 struct ast_exten *e;
1812 /* If there's no context and extension: add callback to statecbs list */
1813 if (!context && !exten) {
1814 AST_LIST_LOCK(&hints);
1816 for (cblist = statecbs; cblist; cblist = cblist->next) {
1817 if (cblist->callback == callback) {
1818 cblist->data = data;
1819 AST_LIST_UNLOCK(&hints);
1824 /* Now insert the callback */
1825 cblist = calloc(1, sizeof(struct ast_state_cb));
1827 AST_LIST_UNLOCK(&hints);
1831 cblist->callback = callback;
1832 cblist->data = data;
1834 cblist->next = statecbs;
1837 AST_LIST_UNLOCK(&hints);
1841 if (!context || !exten)
1844 /* This callback type is for only one hint, so get the hint */
1845 e = ast_hint_extension(NULL, context, exten);
1850 /* Find the hint in the list of hints */
1851 AST_LIST_LOCK(&hints);
1853 AST_LIST_TRAVERSE(&hints, hint, list) {
1854 if (hint->exten == e)
1859 /* We have no hint, sorry */
1860 AST_LIST_UNLOCK(&hints);
1864 /* Now insert the callback in the callback list */
1865 cblist = calloc(1, sizeof(struct ast_state_cb));
1867 AST_LIST_UNLOCK(&hints);
1870 cblist->id = stateid++; /* Unique ID for this callback */
1871 cblist->callback = callback; /* Pointer to callback routine */
1872 cblist->data = data; /* Data for the callback */
1874 cblist->next = hint->callbacks;
1875 hint->callbacks = cblist;
1877 AST_LIST_UNLOCK(&hints);
1881 /*! \brief ast_extension_state_del: Remove a watcher from the callback list */
1882 int ast_extension_state_del(int id, ast_state_cb_type callback)
1884 struct ast_hint *hint;
1885 struct ast_state_cb *cblist, *cbprev;
1887 if (!id && !callback)
1890 AST_LIST_LOCK(&hints);
1892 /* id is zero is a callback without extension */
1895 for (cblist = statecbs; cblist; cblist = cblist->next) {
1896 if (cblist->callback == callback) {
1898 statecbs = cblist->next;
1900 cbprev->next = cblist->next;
1904 AST_LIST_UNLOCK(&hints);
1910 AST_LIST_UNLOCK(&hints);
1914 /* id greater than zero is a callback with extension */
1915 /* Find the callback based on ID */
1916 AST_LIST_TRAVERSE(&hints, hint, list) {
1918 for (cblist = hint->callbacks; cblist; cblist = cblist->next) {
1919 if (cblist->id==id) {
1921 hint->callbacks = cblist->next;
1923 cbprev->next = cblist->next;
1927 AST_LIST_UNLOCK(&hints);
1934 AST_LIST_UNLOCK(&hints);
1938 /*! \brief ast_add_hint: Add hint to hint list, check initial extension state */
1939 static int ast_add_hint(struct ast_exten *e)
1941 struct ast_hint *hint;
1946 AST_LIST_LOCK(&hints);
1948 /* Search if hint exists, do nothing */
1949 AST_LIST_TRAVERSE(&hints, hint, list) {
1950 if (hint->exten == e) {
1951 AST_LIST_UNLOCK(&hints);
1952 if (option_debug > 1)
1953 ast_log(LOG_DEBUG, "HINTS: Not re-adding existing hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e));
1958 if (option_debug > 1)
1959 ast_log(LOG_DEBUG, "HINTS: Adding hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e));
1961 hint = calloc(1, sizeof(struct ast_hint));
1963 AST_LIST_UNLOCK(&hints);
1964 if (option_debug > 1)
1965 ast_log(LOG_DEBUG, "HINTS: Out of memory...\n");
1968 /* Initialize and insert new item at the top */
1970 hint->laststate = ast_extension_state2(e);
1971 AST_LIST_INSERT_HEAD(&hints, hint, list);
1973 AST_LIST_UNLOCK(&hints);
1977 /*! \brief ast_change_hint: Change hint for an extension */
1978 static int ast_change_hint(struct ast_exten *oe, struct ast_exten *ne)
1980 struct ast_hint *hint;
1983 AST_LIST_LOCK(&hints);
1984 AST_LIST_TRAVERSE(&hints, hint, list) {
1985 if (hint->exten == oe) {
1991 AST_LIST_UNLOCK(&hints);
1996 /*! \brief ast_remove_hint: Remove hint from extension */
1997 static int ast_remove_hint(struct ast_exten *e)
1999 /* Cleanup the Notifys if hint is removed */
2000 struct ast_hint *hint;
2001 struct ast_state_cb *cblist, *cbprev;
2007 AST_LIST_LOCK(&hints);
2008 AST_LIST_TRAVERSE_SAFE_BEGIN(&hints, hint, list) {
2009 if (hint->exten == e) {
2011 cblist = hint->callbacks;
2013 /* Notify with -1 and remove all callbacks */
2015 cblist = cblist->next;
2016 cbprev->callback(hint->exten->parent->name, hint->exten->exten, AST_EXTENSION_DEACTIVATED, cbprev->data);
2019 hint->callbacks = NULL;
2020 AST_LIST_REMOVE_CURRENT(&hints, list);
2026 AST_LIST_TRAVERSE_SAFE_END
2027 AST_LIST_UNLOCK(&hints);
2033 /*! \brief ast_get_hint: Get hint for channel */
2034 int ast_get_hint(char *hint, int hintsize, char *name, int namesize, struct ast_channel *c, const char *context, const char *exten)
2036 struct ast_exten *e;
2039 e = ast_hint_extension(c, context, exten);
2042 ast_copy_string(hint, ast_get_extension_app(e), hintsize);
2044 tmp = ast_get_extension_app_data(e);
2046 ast_copy_string(name, (char *) tmp, namesize);
2053 int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
2055 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, HELPER_EXISTS);
2058 int ast_findlabel_extension(struct ast_channel *c, const char *context, const char *exten, const char *label, const char *callerid)
2060 return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, HELPER_FINDLABEL);
2063 int ast_findlabel_extension2(struct ast_channel *c, struct ast_context *con, const char *exten, const char *label, const char *callerid)
2065 return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, HELPER_FINDLABEL);
2068 int ast_canmatch_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
2070 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, HELPER_CANMATCH);
2073 int ast_matchmore_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
2075 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, HELPER_MATCHMORE);
2078 int ast_spawn_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
2080 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, HELPER_SPAWN);
2083 int ast_exec_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
2085 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, HELPER_EXEC);
2088 static int __ast_pbx_run(struct ast_channel *c)
2098 /* A little initial setup here */
2100 ast_log(LOG_WARNING, "%s already has PBX structure??\n", c->name);
2101 c->pbx = calloc(1, sizeof(struct ast_pbx));
2103 ast_log(LOG_ERROR, "Out of memory\n");
2108 c->cdr = ast_cdr_alloc();
2110 ast_log(LOG_WARNING, "Unable to create Call Detail Record\n");
2114 ast_cdr_init(c->cdr, c);
2117 /* Set reasonable defaults */
2118 c->pbx->rtimeout = 10;
2119 c->pbx->dtimeout = 5;
2121 autoloopflag = ast_test_flag(c, AST_FLAG_IN_AUTOLOOP);
2122 ast_set_flag(c, AST_FLAG_IN_AUTOLOOP);
2124 /* Start by trying whatever the channel is set to */
2125 if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) {
2126 /* If not successful fall back to 's' */
2127 if (option_verbose > 1)
2128 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);
2129 ast_copy_string(c->exten, "s", sizeof(c->exten));
2130 if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) {
2131 /* JK02: And finally back to default if everything else failed */
2132 if (option_verbose > 1)
2133 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);
2134 ast_copy_string(c->context, "default", sizeof(c->context));
2138 if (c->cdr && !c->cdr->start.tv_sec && !c->cdr->start.tv_usec)
2139 ast_cdr_start(c->cdr);
2143 while (ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) {
2144 memset(exten, 0, sizeof(exten));
2145 if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num))) {
2146 /* Something bad happened, or a hangup has been requested. */
2147 if (((res >= '0') && (res <= '9')) || ((res >= 'A') && (res <= 'F')) ||
2148 (res == '*') || (res == '#')) {
2149 ast_log(LOG_DEBUG, "Oooh, got something to jump out with ('%c')!\n", res);
2150 memset(exten, 0, sizeof(exten));
2152 exten[pos++] = digit = res;
2156 case AST_PBX_KEEPALIVE:
2158 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
2159 else if (option_verbose > 1)
2160 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
2165 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
2166 else if (option_verbose > 1)
2167 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
2168 if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
2173 if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) {
2183 if ((c->_softhangup == AST_SOFTHANGUP_TIMEOUT) && (ast_exists_extension(c,c->context,"T",1,c->cid.cid_num))) {
2184 ast_copy_string(c->exten, "T", sizeof(c->exten));
2185 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
2186 c->whentohangup = 0;
2188 c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT;
2189 } else if (c->_softhangup) {
2190 ast_log(LOG_DEBUG, "Extension %s, priority %d returned normally even though call was hung up\n",
2191 c->exten, c->priority);
2197 if (!ast_exists_extension(c, c->context, c->exten, 1, c->cid.cid_num)) {
2198 /* It's not a valid extension anymore */
2199 if (ast_exists_extension(c, c->context, "i", 1, c->cid.cid_num)) {
2200 if (option_verbose > 2)
2201 ast_verbose(VERBOSE_PREFIX_3 "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, c->name);
2202 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", c->exten);
2203 ast_copy_string(c->exten, "i", sizeof(c->exten));
2206 ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n",
2207 c->name, c->exten, c->context);
2210 } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) {
2211 /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */
2214 /* Done, wait for an extension */
2217 waittime = c->pbx->dtimeout;
2218 else if (!autofallthrough)
2219 waittime = c->pbx->rtimeout;
2221 while (ast_matchmore_extension(c, c->context, exten, 1, c->cid.cid_num)) {
2222 /* As long as we're willing to wait, and as long as it's not defined,
2223 keep reading digits until we can't possibly get a right answer anymore. */
2224 digit = ast_waitfordigit(c, waittime * 1000);
2225 if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
2232 /* Error, maybe a hangup */
2234 exten[pos++] = digit;
2235 waittime = c->pbx->dtimeout;
2238 if (ast_exists_extension(c, c->context, exten, 1, c->cid.cid_num)) {
2239 /* Prepare the next cycle */
2240 ast_copy_string(c->exten, exten, sizeof(c->exten));
2243 /* No such extension */
2244 if (!ast_strlen_zero(exten)) {
2245 /* An invalid extension */
2246 if (ast_exists_extension(c, c->context, "i", 1, c->cid.cid_num)) {
2247 if (option_verbose > 2)
2248 ast_verbose( VERBOSE_PREFIX_3 "Invalid extension '%s' in context '%s' on %s\n", exten, c->context, c->name);
2249 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", exten);
2250 ast_copy_string(c->exten, "i", sizeof(c->exten));
2253 ast_log(LOG_WARNING, "Invalid extension '%s', but no rule 'i' in context '%s'\n", exten, c->context);
2257 /* A simple timeout */
2258 if (ast_exists_extension(c, c->context, "t", 1, c->cid.cid_num)) {
2259 if (option_verbose > 2)
2260 ast_verbose( VERBOSE_PREFIX_3 "Timeout on %s\n", c->name);
2261 ast_copy_string(c->exten, "t", sizeof(c->exten));
2264 ast_log(LOG_WARNING, "Timeout, but no rule 't' in context '%s'\n", c->context);
2270 if (option_verbose > 2)
2271 ast_verbose(VERBOSE_PREFIX_2 "CDR updated on %s\n",c->name);
2277 status = pbx_builtin_getvar_helper(c, "DIALSTATUS");
2280 if (option_verbose > 2)
2281 ast_verbose(VERBOSE_PREFIX_2 "Auto fallthrough, channel '%s' status is '%s'\n", c->name, status);
2282 if (!strcasecmp(status, "CONGESTION"))
2283 res = pbx_builtin_congestion(c, "10");
2284 else if (!strcasecmp(status, "CHANUNAVAIL"))
2285 res = pbx_builtin_congestion(c, "10");
2286 else if (!strcasecmp(status, "BUSY"))
2287 res = pbx_builtin_busy(c, "10");
2293 ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name);
2295 if ((res != AST_PBX_KEEPALIVE) && ast_exists_extension(c, c->context, "h", 1, c->cid.cid_num)) {
2296 if (c->cdr && ast_opt_end_cdr_before_h_exten)
2297 ast_cdr_end(c->cdr);
2301 while(ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) {
2302 if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num))) {
2303 /* Something bad happened, or a hangup has been requested. */
2305 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
2306 else if (option_verbose > 1)
2307 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
2313 ast_set2_flag(c, autoloopflag, AST_FLAG_IN_AUTOLOOP);
2315 pbx_destroy(c->pbx);
2317 if (res != AST_PBX_KEEPALIVE)
2322 /* Returns 0 on success, non-zero if call limit was reached */
2323 static int increase_call_count(const struct ast_channel *c)
2327 ast_mutex_lock(&maxcalllock);
2328 if (option_maxcalls) {
2329 if (countcalls >= option_maxcalls) {
2330 ast_log(LOG_NOTICE, "Maximum call limit of %d calls exceeded by '%s'!\n", option_maxcalls, c->name);
2334 if (option_maxload) {
2335 getloadavg(&curloadavg, 1);
2336 if (curloadavg >= option_maxload) {
2337 ast_log(LOG_NOTICE, "Maximum loadavg limit of %f load exceeded by '%s' (currently %f)!\n", option_maxload, c->name, curloadavg);
2343 ast_mutex_unlock(&maxcalllock);
2348 static void decrease_call_count(void)
2350 ast_mutex_lock(&maxcalllock);
2353 ast_mutex_unlock(&maxcalllock);
2356 static void *pbx_thread(void *data)
2358 /* Oh joyeous kernel, we're a new thread, with nothing to do but
2359 answer this channel and get it going.
2362 The launcher of this function _MUST_ increment 'countcalls'
2363 before invoking the function; it will be decremented when the
2364 PBX has finished running on the channel
2366 struct ast_channel *c = data;
2369 decrease_call_count();
2376 enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
2379 pthread_attr_t attr;
2382 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
2383 return AST_PBX_FAILED;
2386 if (increase_call_count(c))
2387 return AST_PBX_CALL_LIMIT;
2389 /* Start a new thread, and get something handling this channel. */
2390 pthread_attr_init(&attr);
2391 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
2392 if (ast_pthread_create(&t, &attr, pbx_thread, c)) {
2393 ast_log(LOG_WARNING, "Failed to create new channel thread\n");
2394 return AST_PBX_FAILED;
2397 return AST_PBX_SUCCESS;
2400 enum ast_pbx_result ast_pbx_run(struct ast_channel *c)
2402 enum ast_pbx_result res = AST_PBX_SUCCESS;
2404 if (increase_call_count(c))
2405 return AST_PBX_CALL_LIMIT;
2407 res = __ast_pbx_run(c);
2408 decrease_call_count();
2413 int ast_active_calls(void)
2418 int pbx_set_autofallthrough(int newval)
2421 oldval = autofallthrough;
2422 if (oldval != newval)
2423 autofallthrough = newval;
2428 * This function locks contexts list by &conlist, search for the right context
2429 * structure, leave context list locked and call ast_context_remove_include2
2430 * which removes include, unlock contexts list and return ...
2432 int ast_context_remove_include(const char *context, const char *include, const char *registrar)
2434 struct ast_context *c = NULL;
2436 if (ast_lock_contexts())
2439 /* walk contexts and search for the right one ...*/
2440 while ( (c = ast_walk_contexts(c)) ) {
2441 /* we found one ... */
2442 if (!strcmp(ast_get_context_name(c), context)) {
2444 /* remove include from this context ... */
2445 ret = ast_context_remove_include2(c, include, registrar);
2447 ast_unlock_contexts();
2449 /* ... return results */
2454 /* we can't find the right one context */
2455 ast_unlock_contexts();
2460 * When we call this function, &conlock lock must be locked, because when
2461 * we giving *con argument, some process can remove/change this context
2462 * and after that there can be segfault.
2464 * This function locks given context, removes include, unlock context and
2467 int ast_context_remove_include2(struct ast_context *con, const char *include, const char *registrar)
2469 struct ast_include *i, *pi = NULL;
2471 if (ast_mutex_lock(&con->lock)) return -1;
2474 for (i = con->includes; i; i = i->next) {
2475 /* find our include */
2476 if (!strcmp(i->name, include) &&
2477 (!registrar || !strcmp(i->registrar, registrar))) {
2478 /* remove from list */
2482 con->includes = i->next;
2483 /* free include and return */
2485 ast_mutex_unlock(&con->lock);
2491 /* we can't find the right include */
2492 ast_mutex_unlock(&con->lock);
2497 * \note This function locks contexts list by &conlist, search for the rigt context
2498 * structure, leave context list locked and call ast_context_remove_switch2
2499 * which removes switch, unlock contexts list and return ...
2501 int ast_context_remove_switch(const char *context, const char *sw, const char *data, const char *registrar)
2503 struct ast_context *c = NULL;
2504 int ret = -1; /* default error return */
2506 if (ast_lock_contexts())
2509 /* walk contexts and search for the right one ...*/
2510 while ( (c = ast_walk_contexts(c)) ) {
2511 /* we found one ... */
2512 if (!strcmp(ast_get_context_name(c), context)) {
2513 /* remove switch from this context ... */
2514 ret = ast_context_remove_switch2(c, sw, data, registrar);
2519 /* found or error */
2520 ast_unlock_contexts();
2525 * \brief This function locks given context, removes switch, unlock context and
2527 * \note When we call this function, &conlock lock must be locked, because when
2528 * we giving *con argument, some process can remove/change this context
2529 * and after that there can be segfault.
2532 int ast_context_remove_switch2(struct ast_context *con, const char *sw, const char *data, const char *registrar)
2534 struct ast_sw *i, *pi = NULL;
2536 if (ast_mutex_lock(&con->lock)) return -1;
2539 for (i = con->alts; i; i = i->next) {
2540 /* find our switch */
2541 if (!strcmp(i->name, sw) && !strcmp(i->data, data) &&
2542 (!registrar || !strcmp(i->registrar, registrar))) {
2543 /* remove from list */
2547 con->alts = i->next;
2548 /* free switch and return */
2550 ast_mutex_unlock(&con->lock);
2556 /* we can't find the right switch */
2557 ast_mutex_unlock(&con->lock);
2562 * \note This functions lock contexts list, search for the right context,
2563 * call ast_context_remove_extension2, unlock contexts list and return.
2564 * In this function we are using
2566 int ast_context_remove_extension(const char *context, const char *extension, int priority, const char *registrar)
2568 struct ast_context *c = NULL;
2569 int ret = -1; /* default error return */
2571 if (ast_lock_contexts())
2574 /* walk contexts ... */
2575 while ( (c = ast_walk_contexts(c)) ) {
2576 /* ... search for the right one ... */
2577 if (!strcmp(ast_get_context_name(c), context)) {
2578 /* ... remove extension ... */
2579 ret = ast_context_remove_extension2(c, extension, priority,
2584 /* found or error */
2585 ast_unlock_contexts();
2590 * \brief This functionc locks given context, search for the right extension and
2591 * fires out all peer in this extensions with given priority. If priority
2592 * is set to 0, all peers are removed. After that, unlock context and
2594 * \note When do you want to call this function, make sure that &conlock is locked,
2595 * because some process can handle with your *con context before you lock
2599 int ast_context_remove_extension2(struct ast_context *con, const char *extension, int priority, const char *registrar)
2601 struct ast_exten *exten, *prev_exten = NULL;
2603 if (ast_mutex_lock(&con->lock)) return -1;
2605 /* go through all extensions in context and search the right one ... */
2609 /* look for right extension */
2610 if (!strcmp(exten->exten, extension) &&
2611 (!registrar || !strcmp(exten->registrar, registrar))) {
2612 struct ast_exten *peer;
2614 /* should we free all peers in this extension? (priority == 0)? */
2615 if (priority == 0) {
2616 /* remove this extension from context list */
2618 prev_exten->next = exten->next;
2620 con->root = exten->next;
2622 /* fire out all peers */
2627 if (!peer->priority==PRIORITY_HINT)
2628 ast_remove_hint(peer);
2630 peer->datad(peer->data);
2636 ast_mutex_unlock(&con->lock);
2639 /* remove only extension with exten->priority == priority */
2640 struct ast_exten *previous_peer = NULL;
2644 /* is this our extension? */
2645 if (peer->priority == priority &&
2646 (!registrar || !strcmp(peer->registrar, registrar) )) {
2647 /* we are first priority extension? */
2648 if (!previous_peer) {
2649 /* exists previous extension here? */
2651 /* yes, so we must change next pointer in
2652 * previous connection to next peer
2655 prev_exten->next = peer->peer;
2656 peer->peer->next = exten->next;
2658 prev_exten->next = exten->next;
2660 /* no previous extension, we are first
2661 * extension, so change con->root ...
2664 con->root = peer->peer;
2666 con->root = exten->next;
2669 /* we are not first priority in extension */
2670 previous_peer->peer = peer->peer;
2673 /* now, free whole priority extension */
2674 if (peer->priority==PRIORITY_HINT)
2675 ast_remove_hint(peer);
2676 peer->datad(peer->data);
2679 ast_mutex_unlock(&con->lock);
2682 /* this is not right extension, skip to next peer */
2683 previous_peer = peer;
2688 ast_mutex_unlock(&con->lock);
2694 exten = exten->next;
2697 /* we can't find right extension */
2698 ast_mutex_unlock(&con->lock);
2703 /*! \brief Dynamically register a new dial plan application */
2704 int ast_register_application(const char *app, int (*execute)(struct ast_channel *, void *), const char *synopsis, const char *description)
2706 struct ast_app *tmp, *prev, *cur;
2709 length = sizeof(struct ast_app);
2710 length += strlen(app) + 1;
2711 if (ast_mutex_lock(&applock)) {
2712 ast_log(LOG_ERROR, "Unable to lock application list\n");
2715 for (tmp = apps; tmp; tmp = tmp->next) {
2716 if (!strcasecmp(app, tmp->name)) {
2717 ast_log(LOG_WARNING, "Already have an application '%s'\n", app);
2718 ast_mutex_unlock(&applock);
2723 tmp = calloc(1, length);
2725 ast_log(LOG_ERROR, "Out of memory\n");
2726 ast_mutex_unlock(&applock);
2730 strcpy(tmp->name, app);
2731 tmp->execute = execute;
2732 tmp->synopsis = synopsis;
2733 tmp->description = description;
2734 /* Store in alphabetical order */
2736 for (cur = apps; cur; cur = cur->next) {
2737 if (strcasecmp(tmp->name, cur->name) < 0)
2742 tmp->next = prev->next;
2749 if (option_verbose > 1)
2750 ast_verbose( VERBOSE_PREFIX_2 "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps)));
2751 ast_mutex_unlock(&applock);
2755 int ast_register_switch(struct ast_switch *sw)
2757 struct ast_switch *tmp, *prev=NULL;
2758 if (ast_mutex_lock(&switchlock)) {
2759 ast_log(LOG_ERROR, "Unable to lock switch lock\n");
2762 for (tmp = switches; tmp; tmp = tmp->next) {
2763 if (!strcasecmp(tmp->name, sw->name))
2768 ast_mutex_unlock(&switchlock);
2769 ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name);
2777 ast_mutex_unlock(&switchlock);
2781 void ast_unregister_switch(struct ast_switch *sw)
2783 struct ast_switch *tmp, *prev=NULL;
2784 if (ast_mutex_lock(&switchlock)) {
2785 ast_log(LOG_ERROR, "Unable to lock switch lock\n");
2788 for (tmp = switches; tmp; tmp = tmp->next) {
2791 prev->next = tmp->next;
2793 switches = tmp->next;
2799 ast_mutex_unlock(&switchlock);
2803 * Help for CLI commands ...
2805 static char show_application_help[] =
2806 "Usage: show application <application> [<application> [<application> [...]]]\n"
2807 " Describes a particular application.\n";
2809 static char show_functions_help[] =
2810 "Usage: show functions [like <text>]\n"
2811 " List builtin functions, optionally only those matching a given string\n";
2813 static char show_function_help[] =
2814 "Usage: show function <function>\n"
2815 " Describe a particular dialplan function.\n";
2817 static char show_applications_help[] =
2818 "Usage: show applications [{like|describing} <text>]\n"
2819 " List applications which are currently available.\n"
2820 " If 'like', <text> will be a substring of the app name\n"
2821 " If 'describing', <text> will be a substring of the description\n";
2823 static char show_dialplan_help[] =
2824 "Usage: show dialplan [exten@][context]\n"
2827 static char show_switches_help[] =
2828 "Usage: show switches\n"
2829 " Show registered switches\n";
2831 static char show_hints_help[] =
2832 "Usage: show hints\n"
2833 " Show registered hints\n";
2835 static char show_globals_help[] =
2836 "Usage: show globals\n"
2837 " Show current global dialplan variables and their values\n";
2839 static char set_global_help[] =
2840 "Usage: set global <name> <value>\n"
2841 " Set global dialplan variable <name> to <value>\n";
2845 * IMPLEMENTATION OF CLI FUNCTIONS IS IN THE SAME ORDER AS COMMANDS HELPS
2850 * \brief 'show application' CLI command implementation functions ...
2854 * There is a possibility to show informations about more than one
2855 * application at one time. You can type 'show application Dial Echo' and
2856 * you will see informations about these two applications ...
2858 static char *complete_show_application(const char *line, const char *word, int pos, int state)
2863 int wordlen = strlen(word);
2865 /* try to lock applications list ... */
2866 if (ast_mutex_lock(&applock)) {
2867 ast_log(LOG_ERROR, "Unable to lock application list\n");
2871 /* return the n-th [partial] matching entry */
2872 for (a = apps; a && !ret; a = a->next) {
2873 if (!strncasecmp(word, a->name, wordlen) && ++which > state)
2874 ret = strdup(a->name);
2877 ast_mutex_unlock(&applock);
2882 static int handle_show_application(int fd, int argc, char *argv[])
2885 int app, no_registered_app = 1;
2887 if (argc < 3) return RESULT_SHOWUSAGE;
2889 /* try to lock applications list ... */
2890 if (ast_mutex_lock(&applock)) {
2891 ast_log(LOG_ERROR, "Unable to lock application list\n");
2895 /* ... go through all applications ... */
2896 for (a = apps; a; a = a->next) {
2897 /* ... compare this application name with all arguments given
2898 * to 'show application' command ... */
2899 for (app = 2; app < argc; app++) {
2900 if (!strcasecmp(a->name, argv[app])) {
2901 /* Maximum number of characters added by terminal coloring is 22 */
2902 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40];
2903 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL;
2904 int synopsis_size, description_size;
2906 no_registered_app = 0;
2909 synopsis_size = strlen(a->synopsis) + 23;
2911 synopsis_size = strlen("Not available") + 23;
2912 synopsis = alloca(synopsis_size);
2915 description_size = strlen(a->description) + 23;
2917 description_size = strlen("Not available") + 23;
2918 description = alloca(description_size);
2920 if (synopsis && description) {
2921 snprintf(info, 64 + AST_MAX_APP, "\n -= Info about application '%s' =- \n\n", a->name);
2922 term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22);
2923 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
2924 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
2925 term_color(synopsis,
2926 a->synopsis ? a->synopsis : "Not available",
2927 COLOR_CYAN, 0, synopsis_size);
2928 term_color(description,
2929 a->description ? a->description : "Not available",
2930 COLOR_CYAN, 0, description_size);
2932 ast_cli(fd,"%s%s%s\n\n%s%s\n", infotitle, syntitle, synopsis, destitle, description);
2934 /* ... one of our applications, show info ...*/
2935 ast_cli(fd,"\n -= Info about application '%s' =- \n\n"
2936 "[Synopsis]\n %s\n\n"
2937 "[Description]\n%s\n",
2939 a->synopsis ? a->synopsis : "Not available",
2940 a->description ? a->description : "Not available");
2946 ast_mutex_unlock(&applock);
2948 /* we found at least one app? no? */
2949 if (no_registered_app) {
2950 ast_cli(fd, "Your application(s) is (are) not registered\n");
2951 return RESULT_FAILURE;
2954 return RESULT_SUCCESS;
2957 /*! \brief handle_show_hints: CLI support for listing registred dial plan hints */
2958 static int handle_show_hints(int fd, int argc, char *argv[])
2960 struct ast_hint *hint;
2963 struct ast_state_cb *watcher;
2965 if (AST_LIST_EMPTY(&hints)) {
2966 ast_cli(fd, "There are no registered dialplan hints\n");
2967 return RESULT_SUCCESS;
2969 /* ... we have hints ... */
2970 ast_cli(fd, "\n -= Registered Asterisk Dial Plan Hints =-\n");
2971 if (AST_LIST_LOCK(&hints)) {
2972 ast_log(LOG_ERROR, "Unable to lock hints\n");
2975 AST_LIST_TRAVERSE(&hints, hint, list) {
2977 for (watcher = hint->callbacks; watcher; watcher = watcher->next)
2979 ast_cli(fd, " %20s@%-20.20s: %-20.20s State:%-15.15s Watchers %2d\n",
2980 ast_get_extension_name(hint->exten),
2981 ast_get_context_name(ast_get_extension_context(hint->exten)),
2982 ast_get_extension_app(hint->exten),
2983 ast_extension_state2str(hint->laststate), watchers);
2986 ast_cli(fd, "----------------\n");
2987 ast_cli(fd, "- %d hints registered\n", num);
2988 AST_LIST_UNLOCK(&hints);
2989 return RESULT_SUCCESS;
2992 /*! \brief handle_show_switches: CLI support for listing registred dial plan switches */
2993 static int handle_show_switches(int fd, int argc, char *argv[])
2995 struct ast_switch *sw;
2997 ast_cli(fd, "There are no registered alternative switches\n");
2998 return RESULT_SUCCESS;
3000 /* ... we have applications ... */
3001 ast_cli(fd, "\n -= Registered Asterisk Alternative Switches =-\n");
3002 if (ast_mutex_lock(&switchlock)) {
3003 ast_log(LOG_ERROR, "Unable to lock switches\n");
3006 for (sw = switches; sw; sw = sw->next) {
3007 ast_cli(fd, "%s: %s\n", sw->name, sw->description);
3009 ast_mutex_unlock(&switchlock);
3010 return RESULT_SUCCESS;
3014 * 'show applications' CLI command implementation functions ...
3016 static int handle_show_applications(int fd, int argc, char *argv[])
3019 int like = 0, describing = 0;
3020 int total_match = 0; /* Number of matches in like clause */
3021 int total_apps = 0; /* Number of apps registered */
3023 /* try to lock applications list ... */
3024 if (ast_mutex_lock(&applock)) {
3025 ast_log(LOG_ERROR, "Unable to lock application list\n");
3029 /* ... have we got at least one application (first)? no? */
3031 ast_cli(fd, "There are no registered applications\n");
3032 ast_mutex_unlock(&applock);
3036 /* show applications like <keyword> */
3037 if ((argc == 4) && (!strcmp(argv[2], "like"))) {
3039 } else if ((argc > 3) && (!strcmp(argv[2], "describing"))) {
3043 /* show applications describing <keyword1> [<keyword2>] [...] */
3044 if ((!like) && (!describing)) {
3045 ast_cli(fd, " -= Registered Asterisk Applications =-\n");
3047 ast_cli(fd, " -= Matching Asterisk Applications =-\n");
3050 /* ... go through all applications ... */
3051 for (a = apps; a; a = a->next) {
3052 /* ... show informations about applications ... */
3056 if (strcasestr(a->name, argv[3])) {
3060 } else if (describing) {
3061 if (a->description) {
3062 /* Match all words on command line */
3065 for (i = 3; i < argc; i++) {
3066 if (!strcasestr(a->description, argv[i])) {