2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 1999 - 2005, 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.
25 #include <sys/types.h>
37 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
39 #include "asterisk/lock.h"
40 #include "asterisk/cli.h"
41 #include "asterisk/pbx.h"
42 #include "asterisk/channel.h"
43 #include "asterisk/options.h"
44 #include "asterisk/logger.h"
45 #include "asterisk/file.h"
46 #include "asterisk/callerid.h"
47 #include "asterisk/cdr.h"
48 #include "asterisk/config.h"
49 #include "asterisk/term.h"
50 #include "asterisk/manager.h"
51 #include "asterisk/ast_expr.h"
52 #include "asterisk/linkedlists.h"
53 #include "asterisk/say.h"
54 #include "asterisk/utils.h"
55 #include "asterisk/causes.h"
56 #include "asterisk/musiconhold.h"
57 #include "asterisk/app.h"
58 #include "asterisk/devicestate.h"
61 * \note I M P O R T A N T :
63 * The speed of extension handling will likely be among the most important
64 * aspects of this PBX. The switching scheme as it exists right now isn't
65 * terribly bad (it's O(N+M), where N is the # of extensions and M is the avg #
66 * of priorities, but a constant search time here would be great ;-)
71 #define EXT_DATA_SIZE 256
73 #define EXT_DATA_SIZE 8192
76 #define SWITCH_DATA_LENGTH 256
78 #define VAR_BUF_SIZE 4096
81 #define VAR_SOFTTRAN 2
82 #define VAR_HARDTRAN 3
84 #define BACKGROUND_SKIP (1 << 0)
85 #define BACKGROUND_NOANSWER (1 << 1)
86 #define BACKGROUND_MATCHEXTEN (1 << 2)
87 #define BACKGROUND_PLAYBACK (1 << 3)
89 AST_DECLARE_OPTIONS(background_opts,{
90 ['s'] = { BACKGROUND_SKIP },
91 ['n'] = { BACKGROUND_NOANSWER },
92 ['m'] = { BACKGROUND_MATCHEXTEN },
93 ['p'] = { BACKGROUND_PLAYBACK },
96 #define WAITEXTEN_MOH (1 << 0)
98 AST_DECLARE_OPTIONS(waitexten_opts,{
99 ['m'] = { WAITEXTEN_MOH, 1 },
104 /* ast_exten: An extension */
106 char *exten; /* Extension name */
107 int matchcid; /* Match caller id ? */
108 char *cidmatch; /* Caller id to match for this extension */
109 int priority; /* Priority */
110 char *label; /* Label */
111 struct ast_context *parent; /* The context this extension belongs to */
112 char *app; /* Application to execute */
113 void *data; /* Data to use (arguments) */
114 void (*datad)(void *); /* Data destructor */
115 struct ast_exten *peer; /* Next higher priority with our extension */
116 const char *registrar; /* Registrar */
117 struct ast_exten *next; /* Extension with a greater ID */
121 /* ast_include: include= support in extensions.conf */
124 char *rname; /* Context to include */
125 const char *registrar; /* Registrar */
126 int hastime; /* If time construct exists */
127 struct ast_timing timing; /* time construct */
128 struct ast_include *next; /* Link them together */
132 /* ast_sw: Switch statement in extensions.conf */
135 const char *registrar; /* Registrar */
136 char *data; /* Data load */
138 struct ast_sw *next; /* Link them together */
143 struct ast_ignorepat {
144 const char *registrar;
145 struct ast_ignorepat *next;
149 /* ast_context: An extension context */
151 ast_mutex_t lock; /* A lock to prevent multiple threads from clobbering the context */
152 struct ast_exten *root; /* The root of the list of extensions */
153 struct ast_context *next; /* Link them together */
154 struct ast_include *includes; /* Include other contexts */
155 struct ast_ignorepat *ignorepats; /* Patterns for which to continue playing dialtone */
156 const char *registrar; /* Registrar */
157 struct ast_sw *alts; /* Alternative switches */
158 char name[0]; /* Name of the context */
162 /* ast_app: An application */
164 int (*execute)(struct ast_channel *chan, void *data);
165 const char *synopsis; /* Synopsis text for 'show applications' */
166 const char *description; /* Description (help text) for 'show application <name>' */
167 struct ast_app *next; /* Next app in list */
168 char name[0]; /* Name of the application */
171 /* ast_state_cb: An extension state notify */
172 struct ast_state_cb {
175 ast_state_cb_type callback;
176 struct ast_state_cb *next;
179 /* Hints are pointers from an extension in the dialplan to one or more devices (tech/name) */
181 struct ast_exten *exten; /* Extension */
182 int laststate; /* Last known state */
183 struct ast_state_cb *callbacks; /* Callback list for this extension */
184 struct ast_hint *next; /* Pointer to next hint in list */
187 int ast_pbx_outgoing_cdr_failed(void);
189 static int pbx_builtin_prefix(struct ast_channel *, void *);
190 static int pbx_builtin_suffix(struct ast_channel *, void *);
191 static int pbx_builtin_stripmsd(struct ast_channel *, void *);
192 static int pbx_builtin_answer(struct ast_channel *, void *);
193 static int pbx_builtin_goto(struct ast_channel *, void *);
194 static int pbx_builtin_hangup(struct ast_channel *, void *);
195 static int pbx_builtin_background(struct ast_channel *, void *);
196 static int pbx_builtin_dtimeout(struct ast_channel *, void *);
197 static int pbx_builtin_rtimeout(struct ast_channel *, void *);
198 static int pbx_builtin_atimeout(struct ast_channel *, void *);
199 static int pbx_builtin_wait(struct ast_channel *, void *);
200 static int pbx_builtin_waitexten(struct ast_channel *, void *);
201 static int pbx_builtin_setlanguage(struct ast_channel *, void *);
202 static int pbx_builtin_resetcdr(struct ast_channel *, void *);
203 static int pbx_builtin_setaccount(struct ast_channel *, void *);
204 static int pbx_builtin_setamaflags(struct ast_channel *, void *);
205 static int pbx_builtin_ringing(struct ast_channel *, void *);
206 static int pbx_builtin_progress(struct ast_channel *, void *);
207 static int pbx_builtin_congestion(struct ast_channel *, void *);
208 static int pbx_builtin_busy(struct ast_channel *, void *);
209 static int pbx_builtin_setglobalvar(struct ast_channel *, void *);
210 static int pbx_builtin_noop(struct ast_channel *, void *);
211 static int pbx_builtin_gotoif(struct ast_channel *, void *);
212 static int pbx_builtin_gotoiftime(struct ast_channel *, void *);
213 static int pbx_builtin_execiftime(struct ast_channel *, void *);
214 static int pbx_builtin_saynumber(struct ast_channel *, void *);
215 static int pbx_builtin_saydigits(struct ast_channel *, void *);
216 static int pbx_builtin_saycharacters(struct ast_channel *, void *);
217 static int pbx_builtin_sayphonetic(struct ast_channel *, void *);
218 static int pbx_builtin_setvar_old(struct ast_channel *, void *);
219 int pbx_builtin_setvar(struct ast_channel *, void *);
220 static int pbx_builtin_importvar(struct ast_channel *, void *);
222 static struct varshead globals;
224 static int autofallthrough = 0;
226 AST_MUTEX_DEFINE_STATIC(maxcalllock);
227 static int countcalls = 0;
229 AST_MUTEX_DEFINE_STATIC(acflock); /* Lock for the custom function list */
230 static struct ast_custom_function *acf_root = NULL;
232 static struct pbx_builtin {
233 char name[AST_MAX_APP];
234 int (*execute)(struct ast_channel *chan, void *data);
239 /* These applications are built into the PBX core and do not
240 need separate modules */
242 { "AbsoluteTimeout", pbx_builtin_atimeout,
243 "Set absolute maximum time of call",
244 " AbsoluteTimeout(seconds): Set the absolute maximum amount of time permitted\n"
245 "for a call. A setting of 0 disables the timeout. Always returns 0.\n"
246 "AbsoluteTimeout has been deprecated in favor of Set(TIMEOUT(absolute)=timeout)\n"
249 { "Answer", pbx_builtin_answer,
250 "Answer a channel if ringing",
251 " Answer([delay]): If the channel is ringing, answer it, otherwise do nothing. \n"
252 "If delay is specified, asterisk will pause execution for the specified amount\n"
253 "of milliseconds if an answer is required, in order to give audio a chance to\n"
254 "become ready. Returns 0 unless it tries to answer the channel and fails.\n"
257 { "BackGround", pbx_builtin_background,
258 "Play a file while awaiting extension",
259 " Background(filename1[&filename2...][|options[|langoverride][|context]]):\n"
260 "Plays given files, while simultaneously waiting for the user to begin typing\n"
261 "an extension. The timeouts do not count until the last BackGround\n"
262 "application has ended. Options may also be included following a pipe \n"
263 "symbol. The 'langoverride' may be a language to use for playing the prompt\n"
264 "which differs from the current language of the channel. The optional\n"
265 "'context' can be used to specify an optional context to exit into.\n"
266 "Returns -1 if thhe channel was hung up, or if the file does not exist./n"
267 "Returns 0 otherwise.\n\n"
269 " 's' - causes the playback of the message to be skipped\n"
270 " if the channel is not in the 'up' state (i.e. it\n"
271 " hasn't been answered yet.) If this happens, the\n"
272 " application will return immediately.\n"
273 " 'n' - don't answer the channel before playing the files\n"
274 " 'm' - only break if a digit hit matches a one digit\n"
275 " extension in the destination context\n"
278 { "Busy", pbx_builtin_busy,
279 "Indicate busy condition and stop",
280 " Busy([timeout]): Requests that the channel indicate busy condition and\n"
281 "then waits for the user to hang up or the optional timeout to expire.\n"
285 { "Congestion", pbx_builtin_congestion,
286 "Indicate congestion and stop",
287 " Congestion([timeout]): Requests that the channel indicate congestion\n"
288 "and then waits for the user to hang up or for the optional timeout to\n"
289 "expire. Always returns -1."
292 { "DigitTimeout", pbx_builtin_dtimeout,
293 "Set maximum timeout between digits",
294 " DigitTimeout(seconds): Set the maximum amount of time permitted between\n"
295 "digits when the user is typing in an extension. When this timeout expires,\n"
296 "after the user has started to type in an extension, the extension will be\n"
297 "considered complete, and will be interpreted. Note that if an extension\n"
298 "typed in is valid, it will not have to timeout to be tested, so typically\n"
299 "at the expiry of this timeout, the extension will be considered invalid\n"
300 "(and thus control would be passed to the 'i' extension, or if it doesn't\n"
301 "exist the call would be terminated). The default timeout is 5 seconds.\n"
302 "Always returns 0.\n"
303 "DigitTimeout has been deprecated in favor of Set(TIMEOUT(digit)=timeout)\n"
306 { "Goto", pbx_builtin_goto,
307 "Goto a particular priority, extension, or context",
308 " Goto([[context|]extension|]priority): Set the priority to the specified\n"
309 "value, optionally setting the extension and optionally the context as well.\n"
310 "The extension BYEXTENSION is special in that it uses the current extension,\n"
311 "thus permitting you to go to a different context, without specifying a\n"
312 "specific extension. Always returns 0, even if the given context, extension,\n"
313 "or priority is invalid.\n"
316 { "GotoIf", pbx_builtin_gotoif,
318 " GotoIf(Condition?label1:label2): Go to label 1 if condition is\n"
319 "true, to label2 if condition is false. Either label1 or label2 may be\n"
320 "omitted (in that case, we just don't take the particular branch) but not\n"
321 "both. Look for the condition syntax in examples or documentation."
324 { "GotoIfTime", pbx_builtin_gotoiftime,
325 "Conditional goto on current time",
326 " GotoIfTime(<times>|<weekdays>|<mdays>|<months>?[[context|]extension|]pri):\n"
327 "If the current time matches the specified time, then branch to the specified\n"
328 "extension. Each of the elements may be specified either as '*' (for always)\n"
329 "or as a range. See the 'include' syntax for details."
332 { "ExecIfTime", pbx_builtin_execiftime,
333 "Conditional application execution on current time",
334 " ExecIfTime(<times>|<weekdays>|<mdays>|<months>?<appname>[|<appdata>]):\n"
335 "If the current time matches the specified time, then execute the specified\n"
336 "application. Each of the elements may be specified either as '*' (for always)\n"
337 "or as a range. See the 'include' syntax for details. It will return whatever\n"
338 "<appname> returns, or a non-zero value if the application is not found.\n"
341 { "Hangup", pbx_builtin_hangup,
342 "Unconditional hangup",
343 " Hangup(): Unconditionally hangs up a given channel by returning -1 always.\n"
346 { "NoOp", pbx_builtin_noop,
348 " NoOp(): No-operation; Does nothing."
351 { "Prefix", pbx_builtin_prefix,
352 "Prepend leading digits",
353 " Prefix(digits): Prepends the digit string specified by digits to the\n"
354 "channel's associated extension. For example, the number 1212 when prefixed\n"
355 "with '555' will become 5551212. This app always returns 0, and the PBX will\n"
356 "continue processing at the next priority for the *new* extension.\n"
357 " So, for example, if priority 3 of 1212 is Prefix 555, the next step\n"
358 "executed will be priority 4 of 5551212. If you switch into an extension\n"
359 "which has no first step, the PBX will treat it as though the user dialed an\n"
360 "invalid extension.\n"
363 { "Progress", pbx_builtin_progress,
365 " Progress(): Request that the channel indicate in-band progress is \n"
366 "available to the user.\nAlways returns 0.\n"
369 { "ResetCDR", pbx_builtin_resetcdr,
370 "Resets the Call Data Record",
371 " ResetCDR([options]): Causes the Call Data Record to be reset, optionally\n"
372 "storing the current CDR before zeroing it out\b"
373 " - if 'w' option is specified record will be stored.\n"
374 " - if 'a' option is specified any stacked records will be stored.\n"
375 " - if 'v' option is specified any variables will be saved.\n"
376 "Always returns 0.\n"
379 { "ResponseTimeout", pbx_builtin_rtimeout,
380 "Set maximum timeout awaiting response",
381 " ResponseTimeout(seconds): Set the maximum amount of time permitted after\n"
382 "falling through a series of priorities for a channel in which the user may\n"
383 "begin typing an extension. If the user does not type an extension in this\n"
384 "amount of time, control will pass to the 't' extension if it exists, and\n"
385 "if not the call would be terminated. The default timeout is 10 seconds.\n"
386 "Always returns 0.\n"
387 "ResponseTimeout has been deprecated in favor of Set(TIMEOUT(response)=timeout)\n"
390 { "Ringing", pbx_builtin_ringing,
391 "Indicate ringing tone",
392 " Ringing(): Request that the channel indicate ringing tone to the user.\n"
393 "Always returns 0.\n"
396 { "SayNumber", pbx_builtin_saynumber,
398 " SayNumber(digits[,gender]): Says the passed number. SayNumber is using\n"
399 "the current language setting for the channel. (See app SetLanguage).\n"
402 { "SayDigits", pbx_builtin_saydigits,
404 " SayDigits(digits): Says the passed digits. SayDigits is using the\n"
405 "current language setting for the channel. (See app setLanguage)\n"
408 { "SayAlpha", pbx_builtin_saycharacters,
410 " SayAlpha(string): Spells the passed string\n"
413 { "SayPhonetic", pbx_builtin_sayphonetic,
415 " SayPhonetic(string): Spells the passed string with phonetic alphabet\n"
418 { "SetAccount", pbx_builtin_setaccount,
420 " SetAccount([account]): Set the channel account code for billing\n"
421 "purposes. Always returns 0.\n"
424 { "SetAMAFlags", pbx_builtin_setamaflags,
426 " SetAMAFlags([flag]): Set the channel AMA Flags for billing\n"
427 "purposes. Always returns 0.\n"
430 { "SetGlobalVar", pbx_builtin_setglobalvar,
431 "Set global variable to value",
432 " SetGlobalVar(#n=value): Sets global variable n to value. Global\n"
433 "variable are available across channels.\n"
436 { "SetLanguage", pbx_builtin_setlanguage,
437 "Sets channel language",
438 " SetLanguage(language): Set the channel language to 'language'. This\n"
439 "information is used for the syntax in generation of numbers, and to choose\n"
440 "a natural language file when available.\n"
441 " For example, if language is set to 'fr' and the file 'demo-congrats' is \n"
442 "requested to be played, if the file 'fr/demo-congrats' exists, then\n"
443 "it will play that file, and if not will play the normal 'demo-congrats'.\n"
444 "For some language codes, SetLanguage also changes the syntax of some\n"
445 "Asterisk functions, like SayNumber.\n"
446 "Always returns 0.\n"
447 "SetLanguage has been deprecated in favor of Set(LANGUAGE()=language)\n"
450 { "Set", pbx_builtin_setvar,
451 "Set channel variable(s) or function value(s)",
452 " Set(name1=value1|name2=value2|..[|options])\n"
453 "This function can be used to set the value of channel variables\n"
454 "or dialplan functions. It will accept up to 24 name/value pairs.\n"
455 "When setting variables, if the variable name is prefixed with _,\n"
456 "the variable will be inherited into channels created from the\n"
457 "current channel. If the variable name is prefixed with __,\n"
458 "the variable will be inherited into channels created from the\n"
459 "current channel and all child channels.\n"
460 "The last argument, if it does not contain '=', is interpreted\n"
461 "as a string of options. The valid options are:\n"
462 " g - Set variable globally instead of on the channel\n"
463 " (applies only to variables, not functions)\n"
466 { "SetVar", pbx_builtin_setvar_old,
467 "Set channel variable(s)",
468 " SetVar(name1=value1|name2=value2|..[|options])\n"
469 "SetVar has been deprecated in favor of Set.\n"
472 { "ImportVar", pbx_builtin_importvar,
473 "Import a variable from a channel into a new variable",
474 " ImportVar(newvar=channelname|variable): This application imports a\n"
475 "variable from the specified channel (as opposed to the current one)\n"
476 "and stores it as a variable in the current channel (the channel that\n"
477 "is calling this application). If the new variable name is prefixed by\n"
478 "a single underscore \"_\", then it will be inherited into any channels\n"
479 "created from this one. If it is prefixed with two underscores,then\n"
480 "the variable will have infinite inheritance, meaning that it will be\n"
481 "present in any descendent channel of this one.\n"
484 { "StripMSD", pbx_builtin_stripmsd,
485 "Strip leading digits",
486 " StripMSD(count): Strips the leading 'count' digits from the channel's\n"
487 "associated extension. For example, the number 5551212 when stripped with a\n"
488 "count of 3 would be changed to 1212. This app always returns 0, and the PBX\n"
489 "will continue processing at the next priority for the *new* extension.\n"
490 " So, for example, if priority 3 of 5551212 is StripMSD 3, the next step\n"
491 "executed will be priority 4 of 1212. If you switch into an extension which\n"
492 "has no first step, the PBX will treat it as though the user dialed an\n"
493 "invalid extension.\n"
496 { "Suffix", pbx_builtin_suffix,
497 "Append trailing digits",
498 " Suffix(digits): Appends the digit string specified by digits to the\n"
499 "channel's associated extension. For example, the number 555 when suffixed\n"
500 "with '1212' will become 5551212. This app always returns 0, and the PBX will\n"
501 "continue processing at the next priority for the *new* extension.\n"
502 " So, for example, if priority 3 of 555 is Suffix 1212, the next step\n"
503 "executed will be priority 4 of 5551212. If you switch into an extension\n"
504 "which has no first step, the PBX will treat it as though the user dialed an\n"
505 "invalid extension.\n"
508 { "Wait", pbx_builtin_wait,
509 "Waits for some time",
510 " Wait(seconds): Waits for a specified number of seconds, then returns 0.\n"
511 "seconds can be passed with fractions of a second. (eg: 1.5 = 1.5 seconds)\n"
514 { "WaitExten", pbx_builtin_waitexten,
515 "Waits for an extension to be entered",
516 " WaitExten([seconds][|options]): Waits for the user to enter a new extension for the \n"
517 "specified number of seconds, then returns 0. Seconds can be passed with\n"
518 "fractions of a seconds (eg: 1.5 = 1.5 seconds) or if unspecified the\n"
519 "default extension timeout will be used.\n"
521 " 'm[(x)]' - Provide music on hold to the caller while waiting for an extension.\n"
522 " Optionally, specify the class for music on hold within parenthesis.\n"
527 static struct ast_context *contexts = NULL;
528 AST_MUTEX_DEFINE_STATIC(conlock); /* Lock for the ast_context list */
529 static struct ast_app *apps = NULL;
530 AST_MUTEX_DEFINE_STATIC(applock); /* Lock for the application list */
532 struct ast_switch *switches = NULL;
533 AST_MUTEX_DEFINE_STATIC(switchlock); /* Lock for switches */
535 AST_MUTEX_DEFINE_STATIC(hintlock); /* Lock for extension state notifys */
536 static int stateid = 1;
537 struct ast_hint *hints = NULL;
538 struct ast_state_cb *statecbs = NULL;
540 int pbx_exec(struct ast_channel *c, /* Channel */
541 struct ast_app *app, /* Application */
542 void *data, /* Data for execution */
543 int newstack) /* Force stack increment */
545 /* This function is special. It saves the stack so that no matter
546 how many times it is called, it returns to the same place */
552 int (*execute)(struct ast_channel *chan, void *data) = app->execute;
556 ast_cdr_setapp(c->cdr, app->name, data);
558 /* save channel values */
559 saved_c_appl= c->appl;
560 saved_c_data= c->data;
564 res = execute(c, data);
565 /* restore channel values */
566 c->appl= saved_c_appl;
567 c->data= saved_c_data;
570 ast_log(LOG_WARNING, "You really didn't want to call this function with newstack set to 0\n");
575 /* Go no deeper than this through includes (not counting loops) */
576 #define AST_PBX_MAX_STACK 128
578 #define HELPER_EXISTS 0
579 #define HELPER_SPAWN 1
580 #define HELPER_EXEC 2
581 #define HELPER_CANMATCH 3
582 #define HELPER_MATCHMORE 4
583 #define HELPER_FINDLABEL 5
585 struct ast_app *pbx_findapp(const char *app)
589 if (ast_mutex_lock(&applock)) {
590 ast_log(LOG_WARNING, "Unable to obtain application lock\n");
595 if (!strcasecmp(tmp->name, app))
599 ast_mutex_unlock(&applock);
603 static struct ast_switch *pbx_findswitch(const char *sw)
605 struct ast_switch *asw;
607 if (ast_mutex_lock(&switchlock)) {
608 ast_log(LOG_WARNING, "Unable to obtain application lock\n");
613 if (!strcasecmp(asw->name, sw))
617 ast_mutex_unlock(&switchlock);
621 static inline int include_valid(struct ast_include *i)
626 return ast_check_timing(&(i->timing));
629 static void pbx_destroy(struct ast_pbx *p)
634 #define EXTENSION_MATCH_CORE(data,pattern,match) {\
635 /* All patterns begin with _ */\
636 if (pattern[0] != '_') \
638 /* Start optimistic */\
641 while(match && *data && *pattern && (*pattern != '/')) {\
642 while (*data == '-' && (*(data+1) != '\0')) data++;\
643 switch(toupper(*pattern)) {\
650 where=strchr(pattern,']');\
652 border=(int)(where-pattern);\
653 if (!where || border > strlen(pattern)) {\
654 ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n");\
657 for (i=0; i<border; i++) {\
660 if (pattern[i+1]=='-') {\
661 if (*data >= pattern[i] && *data <= pattern[i+2]) {\
668 if (res==1 || *data==pattern[i]) {\
677 if ((*data < '2') || (*data > '9'))\
681 if ((*data < '0') || (*data > '9'))\
685 if ((*data < '1') || (*data > '9'))\
696 /* Ignore these characters */\
700 if (*data != *pattern)\
706 /* If we ran off the end of the data and the pattern ends in '!', match */\
707 if (match && !*data && (*pattern == '!'))\
711 int ast_extension_match(const char *pattern, const char *data)
714 /* If they're the same return */
715 if (!strcmp(pattern, data))
717 EXTENSION_MATCH_CORE(data,pattern,match);
718 /* Must be at the end of both */
719 if (*data || (*pattern && (*pattern != '/')))
724 int ast_extension_close(const char *pattern, const char *data, int needmore)
727 /* If "data" is longer, it can'be a subset of pattern unless
728 pattern is a pattern match */
729 if ((strlen(pattern) < strlen(data)) && (pattern[0] != '_'))
732 if ((ast_strlen_zero((char *)data) || !strncasecmp(pattern, data, strlen(data))) &&
733 (!needmore || (strlen(pattern) > strlen(data)))) {
736 EXTENSION_MATCH_CORE(data,pattern,match);
737 /* If there's more or we don't care about more, or if it's a possible early match,
738 return non-zero; otherwise it's a miss */
739 if (!needmore || *pattern || match == 2) {
745 struct ast_context *ast_context_find(const char *name)
747 struct ast_context *tmp;
748 ast_mutex_lock(&conlock);
752 if (!strcasecmp(name, tmp->name))
758 ast_mutex_unlock(&conlock);
762 #define STATUS_NO_CONTEXT 1
763 #define STATUS_NO_EXTENSION 2
764 #define STATUS_NO_PRIORITY 3
765 #define STATUS_NO_LABEL 4
766 #define STATUS_SUCCESS 5
768 static int matchcid(const char *cidpattern, const char *callerid)
772 /* If the Caller*ID pattern is empty, then we're matching NO Caller*ID, so
773 failing to get a number should count as a match, otherwise not */
775 if (!ast_strlen_zero(cidpattern))
783 return ast_extension_match(cidpattern, callerid);
786 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)
789 struct ast_context *tmp;
790 struct ast_exten *e, *eroot;
791 struct ast_include *i;
793 struct ast_switch *asw;
795 /* Initialize status if appropriate */
797 *status = STATUS_NO_CONTEXT;
801 /* Check for stack overflow */
802 if (*stacklen >= AST_PBX_MAX_STACK) {
803 ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n");
806 /* Check first to see if we've already been checked */
807 for (x=0; x<*stacklen; x++) {
808 if (!strcasecmp(incstack[x], context))
817 if (bypass || !strcmp(tmp->name, context)) {
818 struct ast_exten *earlymatch = NULL;
820 if (*status < STATUS_NO_EXTENSION)
821 *status = STATUS_NO_EXTENSION;
822 for (eroot = tmp->root; eroot; eroot=eroot->next) {
824 /* Match extension */
825 if ((((action != HELPER_MATCHMORE) && ast_extension_match(eroot->exten, exten)) ||
826 ((action == HELPER_CANMATCH) && (ast_extension_close(eroot->exten, exten, 0))) ||
827 ((action == HELPER_MATCHMORE) && (match = ast_extension_close(eroot->exten, exten, 1)))) &&
828 (!eroot->matchcid || matchcid(eroot->cidmatch, callerid))) {
830 if (action == HELPER_MATCHMORE && match == 2 && !earlymatch) {
831 /* It matched an extension ending in a '!' wildcard
832 So ignore it for now, unless there's a better match */
836 if (*status < STATUS_NO_PRIORITY)
837 *status = STATUS_NO_PRIORITY;
840 if (action == HELPER_FINDLABEL) {
841 if (*status < STATUS_NO_LABEL)
842 *status = STATUS_NO_LABEL;
843 if (label && e->label && !strcmp(label, e->label)) {
844 *status = STATUS_SUCCESS;
845 *foundcontext = context;
848 } else if (e->priority == priority) {
849 *status = STATUS_SUCCESS;
850 *foundcontext = context;
859 /* Bizarre logic for HELPER_MATCHMORE. We return zero to break out
860 of the loop waiting for more digits, and _then_ match (normally)
861 the extension we ended up with. We got an early-matching wildcard
862 pattern, so return NULL to break out of the loop. */
865 /* Check alternative switches */
868 if ((asw = pbx_findswitch(sw->name))) {
869 /* Substitute variables now */
871 pbx_substitute_variables_helper(chan, sw->data, sw->tmpdata, SWITCH_DATA_LENGTH - 1);
872 if (action == HELPER_CANMATCH)
873 res = asw->canmatch ? asw->canmatch(chan, context, exten, priority, callerid, sw->eval ? sw->tmpdata : sw->data) : 0;
874 else if (action == HELPER_MATCHMORE)
875 res = asw->matchmore ? asw->matchmore(chan, context, exten, priority, callerid, sw->eval ? sw->tmpdata : sw->data) : 0;
877 res = asw->exists ? asw->exists(chan, context, exten, priority, callerid, sw->eval ? sw->tmpdata : sw->data) : 0;
881 *data = sw->eval ? sw->tmpdata : sw->data;
882 *foundcontext = context;
886 ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name);
890 /* Setup the stack */
891 incstack[*stacklen] = tmp->name;
893 /* Now try any includes we have in this context */
896 if (include_valid(i)) {
897 if ((e = pbx_find_extension(chan, bypass, i->rname, exten, priority, label, callerid, action, incstack, stacklen, status, swo, data, foundcontext)))
911 /* Note that it's negative -- that's important later. */
912 #define DONT_HAVE_LENGTH 0x80000000
914 static int parse_variable_name(char *var, int *offset, int *length, int *isfunc)
916 char *varchar, *offsetchar = NULL;
920 *length = DONT_HAVE_LENGTH;
922 for (varchar=var; *varchar; varchar++) {
933 offsetchar = varchar + 1;
941 sscanf(offsetchar, "%d:%d", offset, length);
948 static char *substring(char *value, int offset, int length, char *workspace, size_t workspace_len)
950 char *ret = workspace;
952 /* No need to do anything */
953 if (offset == 0 && length==-1) {
957 ast_copy_string(workspace, value, workspace_len);
959 if (abs(offset) > strlen(ret)) { /* Offset beyond string */
961 offset = strlen(ret);
963 offset =- strlen(ret);
966 /* Detect too-long length */
967 if ((offset < 0 && length > -offset) || (offset >= 0 && offset+length > strlen(ret))) {
969 length = strlen(ret)-offset;
971 length = strlen(ret)+offset;
974 /* Bounce up to the right offset */
978 ret += strlen(ret)+offset;
980 /* Chop off at the requisite length */
987 /*! \brief pbx_retrieve_variable: Support for Asterisk built-in variables and
988 functions in the dialplan
990 void pbx_retrieve_variable(struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp)
994 struct tm brokentime;
995 int offset, offset2, isfunc;
996 struct ast_var_t *variables;
1001 ast_copy_string(tmpvar, var, sizeof(tmpvar));
1002 if (parse_variable_name(tmpvar, &offset, &offset2, &isfunc)) {
1003 pbx_retrieve_variable(c, tmpvar, ret, workspace, workspacelen, headp);
1006 *ret = substring(*ret, offset, offset2, workspace, workspacelen);
1007 } else if (c && !strncmp(var, "CALL", 4)) {
1008 if (!strncmp(var + 4, "ER", 2)) {
1009 if (!strncmp(var + 6, "ID", 2)) {
1010 if (!var[8]) { /* CALLERID */
1011 if (c->cid.cid_num) {
1012 if (c->cid.cid_name) {
1013 snprintf(workspace, workspacelen, "\"%s\" <%s>", c->cid.cid_name, c->cid.cid_num);
1015 ast_copy_string(workspace, c->cid.cid_num, workspacelen);
1018 } else if (c->cid.cid_name) {
1019 ast_copy_string(workspace, c->cid.cid_name, workspacelen);
1023 } else if (!strcmp(var + 8, "NUM")) {
1025 if (c->cid.cid_num) {
1026 ast_copy_string(workspace, c->cid.cid_num, workspacelen);
1030 } else if (!strcmp(var + 8, "NAME")) {
1032 if (c->cid.cid_name) {
1033 ast_copy_string(workspace, c->cid.cid_name, workspacelen);
1038 } else if (!strcmp(var + 6, "ANI")) {
1040 if (c->cid.cid_ani) {
1041 ast_copy_string(workspace, c->cid.cid_ani, workspacelen);
1047 } else if (!strncmp(var + 4, "ING", 3)) {
1048 if (!strcmp(var + 7, "PRES")) {
1050 snprintf(workspace, workspacelen, "%d", c->cid.cid_pres);
1052 } else if (!strcmp(var + 7, "ANI2")) {
1054 snprintf(workspace, workspacelen, "%d", c->cid.cid_ani2);
1056 } else if (!strcmp(var + 7, "TON")) {
1058 snprintf(workspace, workspacelen, "%d", c->cid.cid_ton);
1060 } else if (!strcmp(var + 7, "TNS")) {
1062 snprintf(workspace, workspacelen, "%d", c->cid.cid_tns);
1068 } else if (c && !strcmp(var, "DNID")) {
1069 if (c->cid.cid_dnid) {
1070 ast_copy_string(workspace, c->cid.cid_dnid, workspacelen);
1074 } else if (c && !strcmp(var, "HINT")) {
1075 if (!ast_get_hint(workspace, workspacelen, NULL, 0, c, c->context, c->exten))
1079 } else if (c && !strcmp(var, "HINTNAME")) {
1080 if (!ast_get_hint(NULL, 0, workspace, workspacelen, c, c->context, c->exten))
1084 } else if (c && !strcmp(var, "EXTEN")) {
1085 ast_copy_string(workspace, c->exten, workspacelen);
1087 } else if (c && !strcmp(var, "RDNIS")) {
1088 if (c->cid.cid_rdnis) {
1089 ast_copy_string(workspace, c->cid.cid_rdnis, workspacelen);
1093 } else if (c && !strcmp(var, "CONTEXT")) {
1094 ast_copy_string(workspace, c->context, workspacelen);
1096 } else if (c && !strcmp(var, "PRIORITY")) {
1097 snprintf(workspace, workspacelen, "%d", c->priority);
1099 } else if (c && !strcmp(var, "CHANNEL")) {
1100 ast_copy_string(workspace, c->name, workspacelen);
1102 } else if (!strcmp(var, "EPOCH")) {
1103 snprintf(workspace, workspacelen, "%u",(int)time(NULL));
1105 } else if (!strcmp(var, "DATETIME")) {
1106 thistime=time(NULL);
1107 localtime_r(&thistime, &brokentime);
1108 snprintf(workspace, workspacelen, "%02d%02d%04d-%02d:%02d:%02d",
1110 brokentime.tm_mon+1,
1111 brokentime.tm_year+1900,
1117 } else if (!strcmp(var, "TIMESTAMP")) {
1118 thistime=time(NULL);
1119 localtime_r(&thistime, &brokentime);
1120 /* 20031130-150612 */
1121 snprintf(workspace, workspacelen, "%04d%02d%02d-%02d%02d%02d",
1122 brokentime.tm_year+1900,
1123 brokentime.tm_mon+1,
1130 } else if (c && !strcmp(var, "UNIQUEID")) {
1131 snprintf(workspace, workspacelen, "%s", c->uniqueid);
1133 } else if (c && !strcmp(var, "HANGUPCAUSE")) {
1134 snprintf(workspace, workspacelen, "%d", c->hangupcause);
1136 } else if (c && !strcmp(var, "ACCOUNTCODE")) {
1137 ast_copy_string(workspace, c->accountcode, workspacelen);
1139 } else if (c && !strcmp(var, "LANGUAGE")) {
1140 ast_copy_string(workspace, c->language, workspacelen);
1145 AST_LIST_TRAVERSE(headp,variables,entries) {
1147 ast_log(LOG_WARNING,"Comparing variable '%s' with '%s'\n",var,ast_var_name(variables));
1149 if (strcasecmp(ast_var_name(variables),var)==0) {
1150 *ret=ast_var_value(variables);
1152 ast_copy_string(workspace, *ret, workspacelen);
1161 AST_LIST_TRAVERSE(&globals,variables,entries) {
1163 ast_log(LOG_WARNING,"Comparing variable '%s' with '%s'\n",var,ast_var_name(variables));
1165 if (strcasecmp(ast_var_name(variables),var)==0) {
1166 *ret = ast_var_value(variables);
1168 ast_copy_string(workspace, *ret, workspacelen);
1177 static int handle_show_functions(int fd, int argc, char *argv[])
1179 struct ast_custom_function *acf;
1182 ast_cli(fd, "Installed Custom Functions:\n--------------------------------------------------------------------------------\n");
1183 for (acf = acf_root ; acf; acf = acf->next) {
1184 ast_cli(fd, "%-20.20s %-35.35s %s\n", acf->name, acf->syntax, acf->synopsis);
1187 ast_cli(fd, "%d custom functions installed.\n", count_acf);
1191 static int handle_show_function(int fd, int argc, char *argv[])
1193 struct ast_custom_function *acf;
1194 /* Maximum number of characters added by terminal coloring is 22 */
1195 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40];
1196 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL;
1197 char stxtitle[40], *syntax = NULL;
1198 int synopsis_size, description_size, syntax_size;
1200 if (argc < 3) return RESULT_SHOWUSAGE;
1202 if (!(acf = ast_custom_function_find(argv[2]))) {
1203 ast_cli(fd, "No function by that name registered.\n");
1204 return RESULT_FAILURE;
1209 synopsis_size = strlen(acf->synopsis) + 23;
1211 synopsis_size = strlen("Not available") + 23;
1212 synopsis = alloca(synopsis_size);
1215 description_size = strlen(acf->desc) + 23;
1217 description_size = strlen("Not available") + 23;
1218 description = alloca(description_size);
1221 syntax_size = strlen(acf->syntax) + 23;
1223 syntax_size = strlen("Not available") + 23;
1224 syntax = alloca(syntax_size);
1226 snprintf(info, 64 + AST_MAX_APP, "\n -= Info about function '%s' =- \n\n", acf->name);
1227 term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22);
1228 term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40);
1229 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
1230 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
1232 acf->syntax ? acf->syntax : "Not available",
1233 COLOR_CYAN, 0, syntax_size);
1234 term_color(synopsis,
1235 acf->synopsis ? acf->synopsis : "Not available",
1236 COLOR_CYAN, 0, synopsis_size);
1237 term_color(description,
1238 acf->desc ? acf->desc : "Not available",
1239 COLOR_CYAN, 0, description_size);
1241 ast_cli(fd,"%s%s%s\n\n%s%s\n\n%s%s\n", infotitle, stxtitle, syntax, syntitle, synopsis, destitle, description);
1243 return RESULT_SUCCESS;
1246 static char *complete_show_function(char *line, char *word, int pos, int state)
1248 struct ast_custom_function *acf;
1251 /* try to lock functions list ... */
1252 if (ast_mutex_lock(&acflock)) {
1253 ast_log(LOG_ERROR, "Unable to lock function list\n");
1259 if (!strncasecmp(word, acf->name, strlen(word))) {
1260 if (++which > state) {
1261 char *ret = strdup(acf->name);
1262 ast_mutex_unlock(&acflock);
1269 ast_mutex_unlock(&acflock);
1273 struct ast_custom_function* ast_custom_function_find(char *name)
1275 struct ast_custom_function *acfptr;
1277 /* try to lock functions list ... */
1278 if (ast_mutex_lock(&acflock)) {
1279 ast_log(LOG_ERROR, "Unable to lock function list\n");
1283 for (acfptr = acf_root; acfptr; acfptr = acfptr->next) {
1284 if (!strcmp(name, acfptr->name)) {
1289 ast_mutex_unlock(&acflock);
1294 int ast_custom_function_unregister(struct ast_custom_function *acf)
1296 struct ast_custom_function *acfptr, *lastacf = NULL;
1302 /* try to lock functions list ... */
1303 if (ast_mutex_lock(&acflock)) {
1304 ast_log(LOG_ERROR, "Unable to lock function list\n");
1308 for (acfptr = acf_root; acfptr; acfptr = acfptr->next) {
1309 if (acfptr == acf) {
1311 lastacf->next = acf->next;
1313 acf_root = acf->next;
1321 ast_mutex_unlock(&acflock);
1323 if (!res && (option_verbose > 1))
1324 ast_verbose(VERBOSE_PREFIX_2 "Unregistered custom function %s\n", acf->name);
1329 int ast_custom_function_register(struct ast_custom_function *acf)
1334 /* try to lock functions list ... */
1335 if (ast_mutex_lock(&acflock)) {
1336 ast_log(LOG_ERROR, "Unable to lock function list. Failed registering function %s\n", acf->name);
1340 if (ast_custom_function_find(acf->name)) {
1341 ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name);
1342 ast_mutex_unlock(&acflock);
1346 acf->next = acf_root;
1349 ast_mutex_unlock(&acflock);
1351 if (option_verbose > 1)
1352 ast_verbose(VERBOSE_PREFIX_2 "Registered custom function %s\n", acf->name);
1357 char *ast_func_read(struct ast_channel *chan, const char *in, char *workspace, size_t len)
1359 char *args = NULL, *function, *p;
1361 struct ast_custom_function *acfptr;
1363 function = ast_strdupa(in);
1365 ast_log(LOG_ERROR, "Out of memory\n");
1368 if ((args = strchr(function, '('))) {
1371 if ((p = strrchr(args, ')'))) {
1374 ast_log(LOG_WARNING, "Can't find trailing parenthesis?\n");
1377 ast_log(LOG_WARNING, "Function doesn't contain parentheses. Assuming null argument.\n");
1380 if ((acfptr = ast_custom_function_find(function))) {
1381 /* run the custom function */
1383 return acfptr->read(chan, function, args, workspace, len);
1385 ast_log(LOG_ERROR, "Function %s cannot be read\n", function);
1388 ast_log(LOG_ERROR, "Function %s not registered\n", function);
1393 void ast_func_write(struct ast_channel *chan, const char *in, const char *value)
1395 char *args = NULL, *function, *p;
1396 struct ast_custom_function *acfptr;
1398 function = ast_strdupa(in);
1400 ast_log(LOG_ERROR, "Out of memory\n");
1403 if ((args = strchr(function, '('))) {
1406 if ((p = strrchr(args, ')'))) {
1409 ast_log(LOG_WARNING, "Can't find trailing parenthesis?\n");
1412 ast_log(LOG_WARNING, "Function doesn't contain parentheses. Assuming null argument.\n");
1415 if ((acfptr = ast_custom_function_find(function))) {
1416 /* run the custom function */
1417 if (acfptr->write) {
1418 acfptr->write(chan, function, args, value);
1420 ast_log(LOG_ERROR, "Function %s is read-only, it cannot be written to\n", function);
1423 ast_log(LOG_ERROR, "Function %s not registered\n", function);
1427 static void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count)
1430 const char *tmp, *whereweare;
1431 int length, offset, offset2, isfunction;
1432 char *workspace = NULL;
1433 char *ltmp = NULL, *var = NULL;
1434 char *nextvar, *nextexp, *nextthing;
1436 int pos, brackets, needsub, len;
1438 /* Substitutes variables into cp2, based on string cp1, and assuming cp2 to be
1441 while(!ast_strlen_zero(whereweare) && count) {
1442 /* Assume we're copying the whole remaining string */
1443 pos = strlen(whereweare);
1446 nextthing = strchr(whereweare, '$');
1448 switch(nextthing[1]) {
1450 nextvar = nextthing;
1451 pos = nextvar - whereweare;
1454 nextexp = nextthing;
1455 pos = nextexp - whereweare;
1461 /* Can't copy more than 'count' bytes */
1465 /* Copy that many bytes */
1466 memcpy(cp2, whereweare, pos);
1474 /* We have a variable. Find the start and end, and determine
1475 if we are going to have to recursively call ourselves on the
1477 vars = vare = nextvar + 2;
1481 /* Find the end of it */
1482 while(brackets && *vare) {
1483 if ((vare[0] == '$') && (vare[1] == '{')) {
1486 } else if (vare[0] == '}') {
1488 } else if ((vare[0] == '$') && (vare[1] == '['))
1493 ast_log(LOG_NOTICE, "Error in extension logic (missing '}')\n");
1494 len = vare - vars - 1;
1496 /* Skip totally over variable string */
1497 whereweare += (len + 3);
1500 var = alloca(VAR_BUF_SIZE);
1502 /* Store variable name (and truncate) */
1503 ast_copy_string(var, vars, len + 1);
1505 /* Substitute if necessary */
1508 ltmp = alloca(VAR_BUF_SIZE);
1510 memset(ltmp, 0, VAR_BUF_SIZE);
1511 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1);
1518 workspace = alloca(VAR_BUF_SIZE);
1520 workspace[0] = '\0';
1522 parse_variable_name(var, &offset, &offset2, &isfunction);
1524 /* Evaluate function */
1525 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE);
1527 ast_log(LOG_DEBUG, "Function result is '%s'\n", cp4 ? cp4 : "(null)");
1529 /* Retrieve variable value */
1530 pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp);
1533 cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE);
1535 length = strlen(cp4);
1538 memcpy(cp2, cp4, length);
1542 } else if (nextexp) {
1543 /* We have an expression. Find the start and end, and determine
1544 if we are going to have to recursively call ourselves on the
1546 vars = vare = nextexp + 2;
1550 /* Find the end of it */
1551 while(brackets && *vare) {
1552 if ((vare[0] == '$') && (vare[1] == '[')) {
1556 } else if (vare[0] == '[') {
1558 } else if (vare[0] == ']') {
1560 } else if ((vare[0] == '$') && (vare[1] == '{')) {
1567 ast_log(LOG_NOTICE, "Error in extension logic (missing ']')\n");
1568 len = vare - vars - 1;
1570 /* Skip totally over expression */
1571 whereweare += (len + 3);
1574 var = alloca(VAR_BUF_SIZE);
1576 /* Store variable name (and truncate) */
1577 ast_copy_string(var, vars, len + 1);
1579 /* Substitute if necessary */
1582 ltmp = alloca(VAR_BUF_SIZE);
1584 memset(ltmp, 0, VAR_BUF_SIZE);
1585 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1);
1591 length = ast_expr(vars, cp2, count);
1594 ast_log(LOG_DEBUG, "Expression result is '%s'\n", cp2);
1603 void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count)
1605 pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count);
1608 void pbx_substitute_variables_varshead(struct varshead *headp, const char *cp1, char *cp2, int count)
1610 pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count);
1613 static void pbx_substitute_variables(char *passdata, int datalen, struct ast_channel *c, struct ast_exten *e)
1615 memset(passdata, 0, datalen);
1617 /* No variables or expressions in e->data, so why scan it? */
1618 if (!strchr(e->data, '$') && !strstr(e->data,"${") && !strstr(e->data,"$[") && !strstr(e->data,"$(")) {
1619 ast_copy_string(passdata, e->data, datalen);
1623 pbx_substitute_variables_helper(c, e->data, passdata, datalen - 1);
1626 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)
1628 struct ast_exten *e;
1629 struct ast_app *app;
1630 struct ast_switch *sw;
1632 const char *foundcontext=NULL;
1636 char *incstack[AST_PBX_MAX_STACK];
1637 char passdata[EXT_DATA_SIZE];
1641 char tmp3[EXT_DATA_SIZE];
1643 char atmp2[EXT_DATA_SIZE+100];
1645 if (ast_mutex_lock(&conlock)) {
1646 ast_log(LOG_WARNING, "Unable to obtain lock\n");
1647 if ((action == HELPER_EXISTS) || (action == HELPER_CANMATCH) || (action == HELPER_MATCHMORE))
1652 e = pbx_find_extension(c, con, context, exten, priority, label, callerid, action, incstack, &stacklen, &status, &sw, &data, &foundcontext);
1655 case HELPER_CANMATCH:
1656 ast_mutex_unlock(&conlock);
1659 ast_mutex_unlock(&conlock);
1661 case HELPER_FINDLABEL:
1663 ast_mutex_unlock(&conlock);
1665 case HELPER_MATCHMORE:
1666 ast_mutex_unlock(&conlock);
1672 app = pbx_findapp(e->app);
1673 ast_mutex_unlock(&conlock);
1675 if (c->context != context)
1676 ast_copy_string(c->context, context, sizeof(c->context));
1677 if (c->exten != exten)
1678 ast_copy_string(c->exten, exten, sizeof(c->exten));
1679 c->priority = priority;
1680 pbx_substitute_variables(passdata, sizeof(passdata), c, e);
1682 ast_log(LOG_DEBUG, "Launching '%s'\n", app->name);
1683 snprintf(atmp, 80, "STACK-%s-%s-%d", context, exten, priority);
1684 snprintf(atmp2, EXT_DATA_SIZE+100, "%s(\"%s\", \"%s\") %s", app->name, c->name, (!ast_strlen_zero(passdata) ? (char *)passdata : ""), (newstack ? "in new stack" : "in same stack"));
1685 pbx_builtin_setvar_helper(c, atmp, atmp2);
1687 if (option_verbose > 2)
1688 ast_verbose( VERBOSE_PREFIX_3 "Executing %s(\"%s\", \"%s\") %s\n",
1689 term_color(tmp, app->name, COLOR_BRCYAN, 0, sizeof(tmp)),
1690 term_color(tmp2, c->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)),
1691 term_color(tmp3, (!ast_strlen_zero(passdata) ? (char *)passdata : ""), COLOR_BRMAGENTA, 0, sizeof(tmp3)),
1692 (newstack ? "in new stack" : "in same stack"));
1693 manager_event(EVENT_FLAG_CALL, "Newexten",
1698 "Application: %s\r\n"
1701 c->name, c->context, c->exten, c->priority, app->name, passdata ? passdata : "(NULL)", c->uniqueid);
1702 res = pbx_exec(c, app, passdata, newstack);
1705 ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority);
1709 ast_log(LOG_WARNING, "Huh (%d)?\n", action); return -1;
1713 case HELPER_CANMATCH:
1714 ast_mutex_unlock(&conlock);
1717 ast_mutex_unlock(&conlock);
1719 case HELPER_MATCHMORE:
1720 ast_mutex_unlock(&conlock);
1722 case HELPER_FINDLABEL:
1723 ast_mutex_unlock(&conlock);
1729 ast_mutex_unlock(&conlock);
1731 res = sw->exec(c, foundcontext ? foundcontext : context, exten, priority, callerid, newstack, data);
1733 ast_log(LOG_WARNING, "No execution engine for switch %s\n", sw->name);
1738 ast_log(LOG_WARNING, "Huh (%d)?\n", action);
1742 ast_mutex_unlock(&conlock);
1744 case STATUS_NO_CONTEXT:
1745 if ((action != HELPER_EXISTS) && (action != HELPER_MATCHMORE))
1746 ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", context);
1748 case STATUS_NO_EXTENSION:
1749 if ((action != HELPER_EXISTS) && (action != HELPER_CANMATCH) && (action != HELPER_MATCHMORE))
1750 ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, context);
1752 case STATUS_NO_PRIORITY:
1753 if ((action != HELPER_EXISTS) && (action != HELPER_CANMATCH) && (action != HELPER_MATCHMORE))
1754 ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, context);
1756 case STATUS_NO_LABEL:
1758 ast_log(LOG_NOTICE, "No such label '%s' in extension '%s' in context '%s'\n", label, exten, context);
1761 ast_log(LOG_DEBUG, "Shouldn't happen!\n");
1764 if ((action != HELPER_EXISTS) && (action != HELPER_CANMATCH) && (action != HELPER_MATCHMORE))
1772 /*! \brief ast_hint_extension: Find hint for given extension in context */
1773 static struct ast_exten *ast_hint_extension(struct ast_channel *c, const char *context, const char *exten)
1775 struct ast_exten *e;
1776 struct ast_switch *sw;
1778 const char *foundcontext = NULL;
1780 char *incstack[AST_PBX_MAX_STACK];
1783 if (ast_mutex_lock(&conlock)) {
1784 ast_log(LOG_WARNING, "Unable to obtain lock\n");
1787 e = pbx_find_extension(c, NULL, context, exten, PRIORITY_HINT, NULL, "", HELPER_EXISTS, incstack, &stacklen, &status, &sw, &data, &foundcontext);
1788 ast_mutex_unlock(&conlock);
1792 /*! \brief ast_extensions_state2: Check state of extension by using hints */
1793 static int ast_extension_state2(struct ast_exten *e)
1795 char hint[AST_MAX_EXTENSION] = "";
1798 int allunavailable = 1, allbusy = 1, allfree = 1;
1799 int busy = 0, inuse = 0, ring = 0;
1804 ast_copy_string(hint, ast_get_extension_app(e), sizeof(hint));
1806 cur = hint; /* On or more devices separated with a & character */
1808 rest = strchr(cur, '&');
1814 res = ast_device_state(cur);
1816 case AST_DEVICE_NOT_INUSE:
1820 case AST_DEVICE_INUSE:
1825 case AST_DEVICE_RINGING:
1830 case AST_DEVICE_BUSY:
1835 case AST_DEVICE_UNAVAILABLE:
1836 case AST_DEVICE_INVALID:
1849 return AST_EXTENSION_RINGING;
1851 return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING);
1853 return AST_EXTENSION_INUSE;
1855 return AST_EXTENSION_NOT_INUSE;
1857 return AST_EXTENSION_BUSY;
1859 return AST_EXTENSION_UNAVAILABLE;
1861 return AST_EXTENSION_INUSE;
1863 return AST_EXTENSION_NOT_INUSE;
1866 /*! \brief ast_extension_state2str: Return extension_state as string */
1867 const char *ast_extension_state2str(int extension_state)
1871 for (i = 0; (i < (sizeof(extension_states) / sizeof(extension_states[0]))); i++) {
1872 if (extension_states[i].extension_state == extension_state) {
1873 return extension_states[i].text;
1879 /*! \brief ast_extension_state: Check extension state for an extension by using hint */
1880 int ast_extension_state(struct ast_channel *c, char *context, char *exten)
1882 struct ast_exten *e;
1884 e = ast_hint_extension(c, context, exten); /* Do we have a hint for this extension ? */
1886 return -1; /* No hint, return -1 */
1888 return ast_extension_state2(e); /* Check all devices in the hint */
1891 void ast_hint_state_changed(const char *device)
1893 struct ast_hint *hint;
1894 struct ast_state_cb *cblist;
1895 char buf[AST_MAX_EXTENSION];
1900 ast_mutex_lock(&hintlock);
1902 for (hint = hints; hint; hint = hint->next) {
1903 ast_copy_string(buf, ast_get_extension_app(hint->exten), sizeof(buf));
1905 for (cur = strsep(&parse, "&"); cur; cur = strsep(&parse, "&")) {
1906 if (strcmp(cur, device))
1909 /* Get device state for this hint */
1910 state = ast_extension_state2(hint->exten);
1912 if ((state == -1) || (state == hint->laststate))
1915 /* Device state changed since last check - notify the watchers */
1917 /* For general callbacks */
1918 for (cblist = statecbs; cblist; cblist = cblist->next)
1919 cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data);
1921 /* For extension callbacks */
1922 for (cblist = hint->callbacks; cblist; cblist = cblist->next)
1923 cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data);
1925 hint->laststate = state;
1930 ast_mutex_unlock(&hintlock);
1933 /*! \brief ast_extension_state_add: Add watcher for extension states */
1934 int ast_extension_state_add(const char *context, const char *exten,
1935 ast_state_cb_type callback, void *data)
1937 struct ast_hint *list;
1938 struct ast_state_cb *cblist;
1939 struct ast_exten *e;
1941 /* If there's no context and extension: add callback to statecbs list */
1942 if (!context && !exten) {
1943 ast_mutex_lock(&hintlock);
1947 if (cblist->callback == callback) {
1948 cblist->data = data;
1949 ast_mutex_unlock(&hintlock);
1952 cblist = cblist->next;
1955 /* Now insert the callback */
1956 cblist = malloc(sizeof(struct ast_state_cb));
1958 ast_mutex_unlock(&hintlock);
1961 memset(cblist, 0, sizeof(struct ast_state_cb));
1963 cblist->callback = callback;
1964 cblist->data = data;
1966 cblist->next = statecbs;
1969 ast_mutex_unlock(&hintlock);
1973 if (!context || !exten)
1976 /* This callback type is for only one hint, so get the hint */
1977 e = ast_hint_extension(NULL, context, exten);
1982 /* Find the hint in the list of hints */
1983 ast_mutex_lock(&hintlock);
1987 if (list->exten == e)
1993 /* We have no hint, sorry */
1994 ast_mutex_unlock(&hintlock);
1998 /* Now insert the callback in the callback list */
1999 cblist = malloc(sizeof(struct ast_state_cb));
2001 ast_mutex_unlock(&hintlock);
2004 memset(cblist, 0, sizeof(struct ast_state_cb));
2005 cblist->id = stateid++; /* Unique ID for this callback */
2006 cblist->callback = callback; /* Pointer to callback routine */
2007 cblist->data = data; /* Data for the callback */
2009 cblist->next = list->callbacks;
2010 list->callbacks = cblist;
2012 ast_mutex_unlock(&hintlock);
2016 /*! \brief ast_extension_state_del: Remove a watcher from the callback list */
2017 int ast_extension_state_del(int id, ast_state_cb_type callback)
2019 struct ast_hint *list;
2020 struct ast_state_cb *cblist, *cbprev;
2022 if (!id && !callback)
2025 ast_mutex_lock(&hintlock);
2027 /* id is zero is a callback without extension */
2032 if (cblist->callback == callback) {
2034 statecbs = cblist->next;
2036 cbprev->next = cblist->next;
2040 ast_mutex_unlock(&hintlock);
2044 cblist = cblist->next;
2047 ast_mutex_lock(&hintlock);
2051 /* id greater than zero is a callback with extension */
2052 /* Find the callback based on ID */
2055 cblist = list->callbacks;
2058 if (cblist->id==id) {
2060 list->callbacks = cblist->next;
2062 cbprev->next = cblist->next;
2066 ast_mutex_unlock(&hintlock);
2070 cblist = cblist->next;
2075 ast_mutex_unlock(&hintlock);
2079 /*! \brief ast_add_hint: Add hint to hint list, check initial extension state */
2080 static int ast_add_hint(struct ast_exten *e)
2082 struct ast_hint *list;
2087 ast_mutex_lock(&hintlock);
2090 /* Search if hint exists, do nothing */
2092 if (list->exten == e) {
2093 ast_mutex_unlock(&hintlock);
2094 if (option_debug > 1)
2095 ast_log(LOG_DEBUG, "HINTS: Not re-adding existing hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e));
2101 if (option_debug > 1)
2102 ast_log(LOG_DEBUG, "HINTS: Adding hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e));
2104 list = malloc(sizeof(struct ast_hint));
2106 ast_mutex_unlock(&hintlock);
2107 if (option_debug > 1)
2108 ast_log(LOG_DEBUG, "HINTS: Out of memory...\n");
2111 /* Initialize and insert new item at the top */
2112 memset(list, 0, sizeof(struct ast_hint));
2114 list->laststate = ast_extension_state2(e);
2118 ast_mutex_unlock(&hintlock);
2122 /*! \brief ast_change_hint: Change hint for an extension */
2123 static int ast_change_hint(struct ast_exten *oe, struct ast_exten *ne)
2125 struct ast_hint *list;
2127 ast_mutex_lock(&hintlock);
2131 if (list->exten == oe) {
2133 ast_mutex_unlock(&hintlock);
2138 ast_mutex_unlock(&hintlock);
2143 /*! \brief ast_remove_hint: Remove hint from extension */
2144 static int ast_remove_hint(struct ast_exten *e)
2146 /* Cleanup the Notifys if hint is removed */
2147 struct ast_hint *list, *prev = NULL;
2148 struct ast_state_cb *cblist, *cbprev;
2153 ast_mutex_lock(&hintlock);
2157 if (list->exten==e) {
2159 cblist = list->callbacks;
2161 /* Notify with -1 and remove all callbacks */
2163 cblist = cblist->next;
2164 cbprev->callback(list->exten->parent->name, list->exten->exten, AST_EXTENSION_DEACTIVATED, cbprev->data);
2167 list->callbacks = NULL;
2172 prev->next = list->next;
2175 ast_mutex_unlock(&hintlock);
2183 ast_mutex_unlock(&hintlock);
2188 /*! \brief ast_get_hint: Get hint for channel */
2189 int ast_get_hint(char *hint, int hintsize, char *name, int namesize, struct ast_channel *c, const char *context, const char *exten)
2191 struct ast_exten *e;
2194 e = ast_hint_extension(c, context, exten);
2197 ast_copy_string(hint, ast_get_extension_app(e), hintsize);
2199 tmp = ast_get_extension_app_data(e);
2201 ast_copy_string(name, (char *) tmp, namesize);
2208 int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
2210 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, HELPER_EXISTS);
2213 int ast_findlabel_extension(struct ast_channel *c, const char *context, const char *exten, const char *label, const char *callerid)
2215 return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, HELPER_FINDLABEL);
2218 int ast_findlabel_extension2(struct ast_channel *c, struct ast_context *con, const char *exten, const char *label, const char *callerid)
2220 return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, HELPER_FINDLABEL);
2223 int ast_canmatch_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
2225 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, HELPER_CANMATCH);
2228 int ast_matchmore_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
2230 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, HELPER_MATCHMORE);
2233 int ast_spawn_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
2235 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, HELPER_SPAWN);
2238 int ast_exec_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
2240 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, HELPER_EXEC);
2243 static int __ast_pbx_run(struct ast_channel *c)
2253 /* A little initial setup here */
2255 ast_log(LOG_WARNING, "%s already has PBX structure??\n", c->name);
2256 c->pbx = malloc(sizeof(struct ast_pbx));
2258 ast_log(LOG_ERROR, "Out of memory\n");
2263 c->cdr = ast_cdr_alloc();
2265 ast_log(LOG_WARNING, "Unable to create Call Detail Record\n");
2269 ast_cdr_init(c->cdr, c);
2272 memset(c->pbx, 0, sizeof(struct ast_pbx));
2273 /* Set reasonable defaults */
2274 c->pbx->rtimeout = 10;
2275 c->pbx->dtimeout = 5;
2277 autoloopflag = ast_test_flag(c, AST_FLAG_IN_AUTOLOOP);
2278 ast_set_flag(c, AST_FLAG_IN_AUTOLOOP);
2280 /* Start by trying whatever the channel is set to */
2281 if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) {
2282 /* If not successful fall back to 's' */
2283 if (option_verbose > 1)
2284 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);
2285 ast_copy_string(c->exten, "s", sizeof(c->exten));
2286 if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) {
2287 /* JK02: And finally back to default if everything else failed */
2288 if (option_verbose > 1)
2289 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);
2290 ast_copy_string(c->context, "default", sizeof(c->context));
2294 if (c->cdr && !c->cdr->start.tv_sec && !c->cdr->start.tv_usec)
2295 ast_cdr_start(c->cdr);
2299 while(ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) {
2300 memset(exten, 0, sizeof(exten));
2301 if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num))) {
2302 /* Something bad happened, or a hangup has been requested. */
2303 if (((res >= '0') && (res <= '9')) || ((res >= 'A') && (res <= 'F')) ||
2304 (res == '*') || (res == '#')) {
2305 ast_log(LOG_DEBUG, "Oooh, got something to jump out with ('%c')!\n", res);
2306 memset(exten, 0, sizeof(exten));
2308 exten[pos++] = digit = res;
2312 case AST_PBX_KEEPALIVE:
2314 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
2315 else if (option_verbose > 1)
2316 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
2321 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
2322 else if (option_verbose > 1)
2323 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
2324 if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
2329 if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) {
2339 if ((c->_softhangup == AST_SOFTHANGUP_TIMEOUT) && (ast_exists_extension(c,c->context,"T",1,c->cid.cid_num))) {
2340 ast_copy_string(c->exten, "T", sizeof(c->exten));
2341 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
2342 c->whentohangup = 0;
2344 c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT;
2345 } else if (c->_softhangup) {
2346 ast_log(LOG_DEBUG, "Extension %s, priority %d returned normally even though call was hung up\n",
2347 c->exten, c->priority);
2353 if (!ast_exists_extension(c, c->context, c->exten, 1, c->cid.cid_num)) {
2354 /* It's not a valid extension anymore */
2355 if (ast_exists_extension(c, c->context, "i", 1, c->cid.cid_num)) {
2356 if (option_verbose > 2)
2357 ast_verbose(VERBOSE_PREFIX_3 "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, c->name);
2358 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", c->exten);
2359 ast_copy_string(c->exten, "i", sizeof(c->exten));
2362 ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n",
2363 c->name, c->exten, c->context);
2366 } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) {
2367 /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */
2370 /* Done, wait for an extension */
2373 waittime = c->pbx->dtimeout;
2374 else if (!autofallthrough)
2375 waittime = c->pbx->rtimeout;
2377 while (ast_matchmore_extension(c, c->context, exten, 1, c->cid.cid_num)) {
2378 /* As long as we're willing to wait, and as long as it's not defined,
2379 keep reading digits until we can't possibly get a right answer anymore. */
2380 digit = ast_waitfordigit(c, waittime * 1000);
2381 if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
2388 /* Error, maybe a hangup */
2390 exten[pos++] = digit;
2391 waittime = c->pbx->dtimeout;
2394 if (ast_exists_extension(c, c->context, exten, 1, c->cid.cid_num)) {
2395 /* Prepare the next cycle */
2396 ast_copy_string(c->exten, exten, sizeof(c->exten));
2399 /* No such extension */
2400 if (!ast_strlen_zero(exten)) {
2401 /* An invalid extension */
2402 if (ast_exists_extension(c, c->context, "i", 1, c->cid.cid_num)) {
2403 if (option_verbose > 2)
2404 ast_verbose( VERBOSE_PREFIX_3 "Invalid extension '%s' in context '%s' on %s\n", exten, c->context, c->name);
2405 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", exten);
2406 ast_copy_string(c->exten, "i", sizeof(c->exten));
2409 ast_log(LOG_WARNING, "Invalid extension '%s', but no rule 'i' in context '%s'\n", exten, c->context);
2413 /* A simple timeout */
2414 if (ast_exists_extension(c, c->context, "t", 1, c->cid.cid_num)) {
2415 if (option_verbose > 2)
2416 ast_verbose( VERBOSE_PREFIX_3 "Timeout on %s\n", c->name);
2417 ast_copy_string(c->exten, "t", sizeof(c->exten));
2420 ast_log(LOG_WARNING, "Timeout, but no rule 't' in context '%s'\n", c->context);
2426 if (option_verbose > 2)
2427 ast_verbose(VERBOSE_PREFIX_2 "CDR updated on %s\n",c->name);
2433 status = pbx_builtin_getvar_helper(c, "DIALSTATUS");
2436 if (option_verbose > 2)
2437 ast_verbose(VERBOSE_PREFIX_2 "Auto fallthrough, channel '%s' status is '%s'\n", c->name, status);
2438 if (!strcasecmp(status, "CONGESTION"))
2439 res = pbx_builtin_congestion(c, "10");
2440 else if (!strcasecmp(status, "CHANUNAVAIL"))
2441 res = pbx_builtin_congestion(c, "10");
2442 else if (!strcasecmp(status, "BUSY"))
2443 res = pbx_builtin_busy(c, "10");
2449 ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name);
2451 if ((res != AST_PBX_KEEPALIVE) && ast_exists_extension(c, c->context, "h", 1, c->cid.cid_num)) {
2455 while(ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) {
2456 if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num))) {
2457 /* Something bad happened, or a hangup has been requested. */
2459 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
2460 else if (option_verbose > 1)
2461 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
2467 ast_set2_flag(c, autoloopflag, AST_FLAG_IN_AUTOLOOP);
2469 pbx_destroy(c->pbx);
2471 if (res != AST_PBX_KEEPALIVE)
2476 /* Returns 0 on success, non-zero if call limit was reached */
2477 static int increase_call_count(const struct ast_channel *c)
2481 ast_mutex_lock(&maxcalllock);
2482 if (option_maxcalls) {
2483 if (countcalls >= option_maxcalls) {
2484 ast_log(LOG_NOTICE, "Maximum call limit of %d calls exceeded by '%s'!\n", option_maxcalls, c->name);
2488 if (option_maxload) {
2489 getloadavg(&curloadavg, 1);
2490 if (curloadavg >= option_maxload) {
2491 ast_log(LOG_NOTICE, "Maximum loadavg limit of %lf load exceeded by '%s' (currently %f)!\n", option_maxload, c->name, curloadavg);
2497 ast_mutex_unlock(&maxcalllock);
2502 static void decrease_call_count(void)
2504 ast_mutex_lock(&maxcalllock);
2507 ast_mutex_unlock(&maxcalllock);
2510 static void *pbx_thread(void *data)
2512 /* Oh joyeous kernel, we're a new thread, with nothing to do but
2513 answer this channel and get it going.
2516 The launcher of this function _MUST_ increment 'countcalls'
2517 before invoking the function; it will be decremented when the
2518 PBX has finished running on the channel
2520 struct ast_channel *c = data;
2523 decrease_call_count();
2530 enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
2533 pthread_attr_t attr;
2536 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
2537 return AST_PBX_FAILED;
2540 if (increase_call_count(c))
2541 return AST_PBX_CALL_LIMIT;
2543 /* Start a new thread, and get something handling this channel. */
2544 pthread_attr_init(&attr);
2545 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
2546 if (ast_pthread_create(&t, &attr, pbx_thread, c)) {
2547 ast_log(LOG_WARNING, "Failed to create new channel thread\n");
2548 return AST_PBX_FAILED;
2551 return AST_PBX_SUCCESS;
2554 enum ast_pbx_result ast_pbx_run(struct ast_channel *c)
2556 enum ast_pbx_result res = AST_PBX_SUCCESS;
2558 if (increase_call_count(c))
2559 return AST_PBX_CALL_LIMIT;
2561 res = __ast_pbx_run(c);
2562 decrease_call_count();
2567 int ast_active_calls(void)
2572 int pbx_set_autofallthrough(int newval)
2575 oldval = autofallthrough;
2576 if (oldval != newval)
2577 autofallthrough = newval;
2582 * This function locks contexts list by &conlist, search for the right context
2583 * structure, leave context list locked and call ast_context_remove_include2
2584 * which removes include, unlock contexts list and return ...
2586 int ast_context_remove_include(const char *context, const char *include, const char *registrar)
2588 struct ast_context *c;
2590 if (ast_lock_contexts()) return -1;
2592 /* walk contexts and search for the right one ...*/
2593 c = ast_walk_contexts(NULL);
2595 /* we found one ... */
2596 if (!strcmp(ast_get_context_name(c), context)) {
2598 /* remove include from this context ... */
2599 ret = ast_context_remove_include2(c, include, registrar);
2601 ast_unlock_contexts();
2603 /* ... return results */
2606 c = ast_walk_contexts(c);
2609 /* we can't find the right one context */
2610 ast_unlock_contexts();
2615 * When we call this function, &conlock lock must be locked, because when
2616 * we giving *con argument, some process can remove/change this context
2617 * and after that there can be segfault.
2619 * This function locks given context, removes include, unlock context and
2622 int ast_context_remove_include2(struct ast_context *con, const char *include, const char *registrar)
2624 struct ast_include *i, *pi = NULL;
2626 if (ast_mutex_lock(&con->lock)) return -1;
2631 /* find our include */
2632 if (!strcmp(i->name, include) &&
2633 (!registrar || !strcmp(i->registrar, registrar))) {
2634 /* remove from list */
2638 con->includes = i->next;
2639 /* free include and return */
2641 ast_mutex_unlock(&con->lock);
2648 /* we can't find the right include */
2649 ast_mutex_unlock(&con->lock);
2654 * This function locks contexts list by &conlist, search for the rigt context
2655 * structure, leave context list locked and call ast_context_remove_switch2
2656 * which removes switch, unlock contexts list and return ...
2658 int ast_context_remove_switch(const char *context, const char *sw, const char *data, const char *registrar)
2660 struct ast_context *c;
2662 if (ast_lock_contexts()) return -1;
2664 /* walk contexts and search for the right one ...*/
2665 c = ast_walk_contexts(NULL);
2667 /* we found one ... */
2668 if (!strcmp(ast_get_context_name(c), context)) {
2670 /* remove switch from this context ... */
2671 ret = ast_context_remove_switch2(c, sw, data, registrar);
2673 ast_unlock_contexts();
2675 /* ... return results */
2678 c = ast_walk_contexts(c);
2681 /* we can't find the right one context */
2682 ast_unlock_contexts();
2687 * When we call this function, &conlock lock must be locked, because when
2688 * we giving *con argument, some process can remove/change this context
2689 * and after that there can be segfault.
2691 * This function locks given context, removes switch, unlock context and
2694 int ast_context_remove_switch2(struct ast_context *con, const char *sw, const char *data, const char *registrar)
2696 struct ast_sw *i, *pi = NULL;
2698 if (ast_mutex_lock(&con->lock)) return -1;
2703 /* find our switch */
2704 if (!strcmp(i->name, sw) && !strcmp(i->data, data) &&
2705 (!registrar || !strcmp(i->registrar, registrar))) {
2706 /* remove from list */
2710 con->alts = i->next;
2711 /* free switch and return */
2713 ast_mutex_unlock(&con->lock);
2720 /* we can't find the right switch */
2721 ast_mutex_unlock(&con->lock);
2726 * This functions lock contexts list, search for the right context,
2727 * call ast_context_remove_extension2, unlock contexts list and return.
2728 * In this function we are using
2730 int ast_context_remove_extension(const char *context, const char *extension, int priority, const char *registrar)
2732 struct ast_context *c;
2734 if (ast_lock_contexts()) return -1;
2736 /* walk contexts ... */
2737 c = ast_walk_contexts(NULL);
2739 /* ... search for the right one ... */
2740 if (!strcmp(ast_get_context_name(c), context)) {
2741 /* ... remove extension ... */
2742 int ret = ast_context_remove_extension2(c, extension, priority,
2744 /* ... unlock contexts list and return */
2745 ast_unlock_contexts();
2748 c = ast_walk_contexts(c);
2751 /* we can't find the right context */
2752 ast_unlock_contexts();
2757 * When do you want to call this function, make sure that &conlock is locked,
2758 * because some process can handle with your *con context before you lock
2761 * This functionc locks given context, search for the right extension and
2762 * fires out all peer in this extensions with given priority. If priority
2763 * is set to 0, all peers are removed. After that, unlock context and
2766 int ast_context_remove_extension2(struct ast_context *con, const char *extension, int priority, const char *registrar)
2768 struct ast_exten *exten, *prev_exten = NULL;
2770 if (ast_mutex_lock(&con->lock)) return -1;
2772 /* go through all extensions in context and search the right one ... */
2776 /* look for right extension */
2777 if (!strcmp(exten->exten, extension) &&
2778 (!registrar || !strcmp(exten->registrar, registrar))) {
2779 struct ast_exten *peer;
2781 /* should we free all peers in this extension? (priority == 0)? */
2782 if (priority == 0) {
2783 /* remove this extension from context list */
2785 prev_exten->next = exten->next;
2787 con->root = exten->next;
2789 /* fire out all peers */
2794 if (!peer->priority==PRIORITY_HINT)
2795 ast_remove_hint(peer);
2797 peer->datad(peer->data);
2803 ast_mutex_unlock(&con->lock);
2806 /* remove only extension with exten->priority == priority */
2807 struct ast_exten *previous_peer = NULL;
2811 /* is this our extension? */
2812 if (peer->priority == priority &&
2813 (!registrar || !strcmp(peer->registrar, registrar) )) {
2814 /* we are first priority extension? */
2815 if (!previous_peer) {
2816 /* exists previous extension here? */
2818 /* yes, so we must change next pointer in
2819 * previous connection to next peer
2822 prev_exten->next = peer->peer;
2823 peer->peer->next = exten->next;
2825 prev_exten->next = exten->next;
2827 /* no previous extension, we are first
2828 * extension, so change con->root ...
2831 con->root = peer->peer;
2833 con->root = exten->next;
2836 /* we are not first priority in extension */
2837 previous_peer->peer = peer->peer;
2840 /* now, free whole priority extension */
2841 if (peer->priority==PRIORITY_HINT)
2842 ast_remove_hint(peer);
2843 peer->datad(peer->data);
2846 ast_mutex_unlock(&con->lock);
2849 /* this is not right extension, skip to next peer */
2850 previous_peer = peer;
2855 ast_mutex_unlock(&con->lock);
2861 exten = exten->next;
2864 /* we can't find right extension */
2865 ast_mutex_unlock(&con->lock);
2870 int ast_register_application(const char *app, int (*execute)(struct ast_channel *, void *), const char *synopsis, const char *description)
2872 struct ast_app *tmp, *prev, *cur;
2875 length = sizeof(struct ast_app);
2876 length += strlen(app) + 1;
2877 if (ast_mutex_lock(&applock)) {
2878 ast_log(LOG_ERROR, "Unable to lock application list\n");
2883 if (!strcasecmp(app, tmp->name)) {
2884 ast_log(LOG_WARNING, "Already have an application '%s'\n", app);
2885 ast_mutex_unlock(&applock);
2890 tmp = malloc(length);
2892 memset(tmp, 0, length);
2893 strcpy(tmp->name, app);
2894 tmp->execute = execute;
2895 tmp->synopsis = synopsis;
2896 tmp->description = description;
2897 /* Store in alphabetical order */
2901 if (strcasecmp(tmp->name, cur->name) < 0)
2907 tmp->next = prev->next;
2914 ast_log(LOG_ERROR, "Out of memory\n");
2915 ast_mutex_unlock(&applock);
2918 if (option_verbose > 1)
2919 ast_verbose( VERBOSE_PREFIX_2 "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps)));
2920 ast_mutex_unlock(&applock);
2924 int ast_register_switch(struct ast_switch *sw)
2926 struct ast_switch *tmp, *prev=NULL;
2927 if (ast_mutex_lock(&switchlock)) {
2928 ast_log(LOG_ERROR, "Unable to lock switch lock\n");
2933 if (!strcasecmp(tmp->name, sw->name))
2939 ast_mutex_unlock(&switchlock);
2940 ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name);
2948 ast_mutex_unlock(&switchlock);
2952 void ast_unregister_switch(struct ast_switch *sw)
2954 struct ast_switch *tmp, *prev=NULL;
2955 if (ast_mutex_lock(&switchlock)) {
2956 ast_log(LOG_ERROR, "Unable to lock switch lock\n");
2963 prev->next = tmp->next;
2965 switches = tmp->next;
2972 ast_mutex_unlock(&switchlock);
2976 * Help for CLI commands ...
2978 static char show_application_help[] =
2979 "Usage: show application <application> [<application> [<application> [...]]]\n"
2980 " Describes a particular application.\n";
2982 static char show_functions_help[] =
2983 "Usage: show functions\n"
2984 " List builtin functions accessable as $(function args)\n";
2986 static char show_function_help[] =
2987 "Usage: show function <function>\n"
2988 " Describe a particular dialplan function.\n";
2990 static char show_applications_help[] =
2991 "Usage: show applications [{like|describing} <text>]\n"
2992 " List applications which are currently available.\n"
2993 " If 'like', <text> will be a substring of the app name\n"
2994 " If 'describing', <text> will be a substring of the description\n";
2996 static char show_dialplan_help[] =
2997 "Usage: show dialplan [exten@][context]\n"
3000 static char show_switches_help[] =
3001 "Usage: show switches\n"
3002 " Show registered switches\n";
3004 static char show_hints_help[] =
3005 "Usage: show hints\n"
3006 " Show registered hints\n";
3010 * IMPLEMENTATION OF CLI FUNCTIONS IS IN THE SAME ORDER AS COMMANDS HELPS
3015 * 'show application' CLI command implementation functions ...
3019 * There is a possibility to show informations about more than one
3020 * application at one time. You can type 'show application Dial Echo' and
3021 * you will see informations about these two applications ...
3023 static char *complete_show_application(char *line, char *word,
3029 /* try to lock applications list ... */
3030 if (ast_mutex_lock(&applock)) {
3031 ast_log(LOG_ERROR, "Unable to lock application list\n");
3035 /* ... walk all applications ... */
3038 /* ... check if word matches this application ... */
3039 if (!strncasecmp(word, a->name, strlen(word))) {
3040 /* ... if this is right app serve it ... */
3041 if (++which > state) {
3042 char *ret = strdup(a->name);
3043 ast_mutex_unlock(&applock);
3050 /* no application match */
3051 ast_mutex_unlock(&applock);