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.
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"
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 /*--- pbx_retrieve_variable: Support for Asterisk built-in variables and
912 functions in the dialplan
914 void pbx_retrieve_variable(struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp)
919 struct tm brokentime;
921 struct ast_var_t *variables;
926 if ((first=strchr(var,':'))) { /* : Remove characters counting from end or start of string */
927 ast_copy_string(tmpvar, var, sizeof(tmpvar));
928 first = strchr(tmpvar, ':');
930 first = tmpvar + strlen(tmpvar);
932 pbx_retrieve_variable(c,tmpvar,ret,workspace,workspacelen - 1, headp);
935 offset=atoi(first+1); /* The number of characters,
936 positive: remove # of chars from start
937 negative: keep # of chars from end */
939 if ((second=strchr(first+1,':'))) {
941 offset2 = atoi(second+1); /* Number of chars to copy */
942 } else if (offset >= 0) {
943 offset2 = strlen(*ret)-offset; /* Rest of string */
945 offset2 = abs(offset);
948 if (abs(offset) > strlen(*ret)) { /* Offset beyond string */
950 offset = strlen(*ret);
952 offset =- strlen(*ret);
954 if ((offset < 0 && offset2 > -offset) || (offset >= 0 && offset+offset2 > strlen(*ret))) {
956 offset2 = strlen(*ret)-offset;
958 offset2 = strlen(*ret)+offset;
963 *ret += strlen(*ret)+offset;
964 (*ret)[offset2] = '\0'; /* Cut at offset2 position */
965 } else if (c && !strncmp(var, "CALL", 4)) {
966 if (!strncmp(var + 4, "ER", 2)) {
967 if (!strncmp(var + 6, "ID", 2)) {
968 if (!var[8]) { /* CALLERID */
969 if (c->cid.cid_num) {
970 if (c->cid.cid_name) {
971 snprintf(workspace, workspacelen, "\"%s\" <%s>", c->cid.cid_name, c->cid.cid_num);
973 ast_copy_string(workspace, c->cid.cid_num, workspacelen);
976 } else if (c->cid.cid_name) {
977 ast_copy_string(workspace, c->cid.cid_name, workspacelen);
981 } else if (!strcmp(var + 8, "NUM")) {
983 if (c->cid.cid_num) {
984 ast_copy_string(workspace, c->cid.cid_num, workspacelen);
988 } else if (!strcmp(var + 8, "NAME")) {
990 if (c->cid.cid_name) {
991 ast_copy_string(workspace, c->cid.cid_name, workspacelen);
996 } else if (!strcmp(var + 6, "ANI")) {
998 if (c->cid.cid_ani) {
999 ast_copy_string(workspace, c->cid.cid_ani, workspacelen);
1005 } else if (!strncmp(var + 4, "ING", 3)) {
1006 if (!strcmp(var + 7, "PRES")) {
1008 snprintf(workspace, workspacelen, "%d", c->cid.cid_pres);
1010 } else if (!strcmp(var + 7, "ANI2")) {
1012 snprintf(workspace, workspacelen, "%d", c->cid.cid_ani2);
1014 } else if (!strcmp(var + 7, "TON")) {
1016 snprintf(workspace, workspacelen, "%d", c->cid.cid_ton);
1018 } else if (!strcmp(var + 7, "TNS")) {
1020 snprintf(workspace, workspacelen, "%d", c->cid.cid_tns);
1026 } else if (c && !strcmp(var, "DNID")) {
1027 if (c->cid.cid_dnid) {
1028 ast_copy_string(workspace, c->cid.cid_dnid, workspacelen);
1032 } else if (c && !strcmp(var, "HINT")) {
1033 if (!ast_get_hint(workspace, workspacelen, NULL, 0, c, c->context, c->exten))
1037 } else if (c && !strcmp(var, "HINTNAME")) {
1038 if (!ast_get_hint(NULL, 0, workspace, workspacelen, c, c->context, c->exten))
1042 } else if (c && !strcmp(var, "EXTEN")) {
1043 ast_copy_string(workspace, c->exten, workspacelen);
1045 } else if (c && !strcmp(var, "RDNIS")) {
1046 if (c->cid.cid_rdnis) {
1047 ast_copy_string(workspace, c->cid.cid_rdnis, workspacelen);
1051 } else if (c && !strcmp(var, "CONTEXT")) {
1052 ast_copy_string(workspace, c->context, workspacelen);
1054 } else if (c && !strcmp(var, "PRIORITY")) {
1055 snprintf(workspace, workspacelen, "%d", c->priority);
1057 } else if (c && !strcmp(var, "CHANNEL")) {
1058 ast_copy_string(workspace, c->name, workspacelen);
1060 } else if (!strcmp(var, "EPOCH")) {
1061 snprintf(workspace, workspacelen, "%u",(int)time(NULL));
1063 } else if (!strcmp(var, "DATETIME")) {
1064 thistime=time(NULL);
1065 localtime_r(&thistime, &brokentime);
1066 snprintf(workspace, workspacelen, "%02d%02d%04d-%02d:%02d:%02d",
1068 brokentime.tm_mon+1,
1069 brokentime.tm_year+1900,
1075 } else if (!strcmp(var, "TIMESTAMP")) {
1076 thistime=time(NULL);
1077 localtime_r(&thistime, &brokentime);
1078 /* 20031130-150612 */
1079 snprintf(workspace, workspacelen, "%04d%02d%02d-%02d%02d%02d",
1080 brokentime.tm_year+1900,
1081 brokentime.tm_mon+1,
1088 } else if (c && !strcmp(var, "UNIQUEID")) {
1089 snprintf(workspace, workspacelen, "%s", c->uniqueid);
1091 } else if (c && !strcmp(var, "HANGUPCAUSE")) {
1092 snprintf(workspace, workspacelen, "%d", c->hangupcause);
1094 } else if (c && !strcmp(var, "ACCOUNTCODE")) {
1095 ast_copy_string(workspace, c->accountcode, workspacelen);
1097 } else if (c && !strcmp(var, "LANGUAGE")) {
1098 ast_copy_string(workspace, c->language, workspacelen);
1103 AST_LIST_TRAVERSE(headp,variables,entries) {
1105 ast_log(LOG_WARNING,"Comparing variable '%s' with '%s'\n",var,ast_var_name(variables));
1107 if (strcasecmp(ast_var_name(variables),var)==0) {
1108 *ret=ast_var_value(variables);
1110 ast_copy_string(workspace, *ret, workspacelen);
1119 AST_LIST_TRAVERSE(&globals,variables,entries) {
1121 ast_log(LOG_WARNING,"Comparing variable '%s' with '%s'\n",var,ast_var_name(variables));
1123 if (strcasecmp(ast_var_name(variables),var)==0) {
1124 *ret = ast_var_value(variables);
1126 ast_copy_string(workspace, *ret, workspacelen);
1135 static int handle_show_functions(int fd, int argc, char *argv[])
1137 struct ast_custom_function *acf;
1140 ast_cli(fd, "Installed Custom Functions:\n--------------------------------------------------------------------------------\n");
1141 for (acf = acf_root ; acf; acf = acf->next) {
1142 ast_cli(fd, "%-20.20s %-35.35s %s\n", acf->name, acf->syntax, acf->synopsis);
1145 ast_cli(fd, "%d custom functions installed.\n", count_acf);
1149 static int handle_show_function(int fd, int argc, char *argv[])
1151 struct ast_custom_function *acf;
1152 /* Maximum number of characters added by terminal coloring is 22 */
1153 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40];
1154 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL;
1155 char stxtitle[40], *syntax = NULL;
1156 int synopsis_size, description_size, syntax_size;
1158 if (argc < 3) return RESULT_SHOWUSAGE;
1160 if (!(acf = ast_custom_function_find(argv[2]))) {
1161 ast_cli(fd, "No function by that name registered.\n");
1162 return RESULT_FAILURE;
1167 synopsis_size = strlen(acf->synopsis) + 23;
1169 synopsis_size = strlen("Not available") + 23;
1170 synopsis = alloca(synopsis_size);
1173 description_size = strlen(acf->desc) + 23;
1175 description_size = strlen("Not available") + 23;
1176 description = alloca(description_size);
1179 syntax_size = strlen(acf->syntax) + 23;
1181 syntax_size = strlen("Not available") + 23;
1182 syntax = alloca(syntax_size);
1184 snprintf(info, 64 + AST_MAX_APP, "\n -= Info about function '%s' =- \n\n", acf->name);
1185 term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22);
1186 term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40);
1187 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
1188 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
1190 acf->syntax ? acf->syntax : "Not available",
1191 COLOR_CYAN, 0, syntax_size);
1192 term_color(synopsis,
1193 acf->synopsis ? acf->synopsis : "Not available",
1194 COLOR_CYAN, 0, synopsis_size);
1195 term_color(description,
1196 acf->desc ? acf->desc : "Not available",
1197 COLOR_CYAN, 0, description_size);
1199 ast_cli(fd,"%s%s%s\n\n%s%s\n\n%s%s\n", infotitle, stxtitle, syntax, syntitle, synopsis, destitle, description);
1201 return RESULT_SUCCESS;
1204 static char *complete_show_function(char *line, char *word, int pos, int state)
1206 struct ast_custom_function *acf;
1209 /* try to lock functions list ... */
1210 if (ast_mutex_lock(&acflock)) {
1211 ast_log(LOG_ERROR, "Unable to lock function list\n");
1217 if (!strncasecmp(word, acf->name, strlen(word))) {
1218 if (++which > state) {
1219 char *ret = strdup(acf->name);
1220 ast_mutex_unlock(&acflock);
1227 ast_mutex_unlock(&acflock);
1231 struct ast_custom_function* ast_custom_function_find(char *name)
1233 struct ast_custom_function *acfptr;
1235 /* try to lock functions list ... */
1236 if (ast_mutex_lock(&acflock)) {
1237 ast_log(LOG_ERROR, "Unable to lock function list\n");
1241 for (acfptr = acf_root; acfptr; acfptr = acfptr->next) {
1242 if (!strcmp(name, acfptr->name)) {
1247 ast_mutex_unlock(&acflock);
1252 int ast_custom_function_unregister(struct ast_custom_function *acf)
1254 struct ast_custom_function *acfptr, *lastacf = NULL;
1260 /* try to lock functions list ... */
1261 if (ast_mutex_lock(&acflock)) {
1262 ast_log(LOG_ERROR, "Unable to lock function list\n");
1266 for (acfptr = acf_root; acfptr; acfptr = acfptr->next) {
1267 if (acfptr == acf) {
1269 lastacf->next = acf->next;
1271 acf_root = acf->next;
1279 ast_mutex_unlock(&acflock);
1281 if (!res && (option_verbose > 1))
1282 ast_verbose(VERBOSE_PREFIX_2 "Unregistered custom function %s\n", acf->name);
1287 int ast_custom_function_register(struct ast_custom_function *acf)
1292 /* try to lock functions list ... */
1293 if (ast_mutex_lock(&acflock)) {
1294 ast_log(LOG_ERROR, "Unable to lock function list. Failed registering function %s\n", acf->name);
1298 if (ast_custom_function_find(acf->name)) {
1299 ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name);
1300 ast_mutex_unlock(&acflock);
1304 acf->next = acf_root;
1307 ast_mutex_unlock(&acflock);
1309 if (option_verbose > 1)
1310 ast_verbose(VERBOSE_PREFIX_2 "Registered custom function %s\n", acf->name);
1315 char *ast_func_read(struct ast_channel *chan, const char *in, char *workspace, size_t len)
1317 char *args = NULL, *function, *p;
1319 struct ast_custom_function *acfptr;
1321 function = ast_strdupa(in);
1323 ast_log(LOG_ERROR, "Out of memory\n");
1326 if ((args = strchr(function, '('))) {
1329 if ((p = strrchr(args, ')'))) {
1332 ast_log(LOG_WARNING, "Can't find trailing parenthesis?\n");
1335 ast_log(LOG_WARNING, "Function doesn't contain parentheses. Assuming null argument.\n");
1338 if ((acfptr = ast_custom_function_find(function))) {
1339 /* run the custom function */
1341 return acfptr->read(chan, function, args, workspace, len);
1343 ast_log(LOG_ERROR, "Function %s cannot be read\n", function);
1346 ast_log(LOG_ERROR, "Function %s not registered\n", function);
1351 void ast_func_write(struct ast_channel *chan, const char *in, const char *value)
1353 char *args = NULL, *function, *p;
1354 struct ast_custom_function *acfptr;
1356 function = ast_strdupa(in);
1358 ast_log(LOG_ERROR, "Out of memory\n");
1361 if ((args = strchr(function, '('))) {
1364 if ((p = strrchr(args, ')'))) {
1367 ast_log(LOG_WARNING, "Can't find trailing parenthesis?\n");
1370 ast_log(LOG_WARNING, "Function doesn't contain parentheses. Assuming null argument.\n");
1373 if ((acfptr = ast_custom_function_find(function))) {
1374 /* run the custom function */
1375 if (acfptr->write) {
1376 acfptr->write(chan, function, args, value);
1378 ast_log(LOG_ERROR, "Function %s is read-only, it cannot be written to\n", function);
1381 ast_log(LOG_ERROR, "Function %s not registered\n", function);
1385 static void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count)
1388 const char *tmp, *whereweare;
1390 char *workspace = NULL;
1391 char *ltmp = NULL, *var = NULL;
1392 char *nextvar, *nextexp, *nextthing;
1394 int pos, brackets, needsub, len;
1396 /* Substitutes variables into cp2, based on string cp1, and assuming cp2 to be
1399 while(!ast_strlen_zero(whereweare) && count) {
1400 /* Assume we're copying the whole remaining string */
1401 pos = strlen(whereweare);
1404 nextthing = strchr(whereweare, '$');
1406 switch(nextthing[1]) {
1408 nextvar = nextthing;
1409 pos = nextvar - whereweare;
1412 nextexp = nextthing;
1413 pos = nextexp - whereweare;
1419 /* Can't copy more than 'count' bytes */
1423 /* Copy that many bytes */
1424 memcpy(cp2, whereweare, pos);
1432 /* We have a variable. Find the start and end, and determine
1433 if we are going to have to recursively call ourselves on the
1435 vars = vare = nextvar + 2;
1439 /* Find the end of it */
1440 while(brackets && *vare) {
1441 if ((vare[0] == '$') && (vare[1] == '{')) {
1444 } else if (vare[0] == '}') {
1446 } else if ((vare[0] == '$') && (vare[1] == '['))
1451 ast_log(LOG_NOTICE, "Error in extension logic (missing '}')\n");
1452 len = vare - vars - 1;
1454 /* Skip totally over variable string */
1455 whereweare += (len + 3);
1458 var = alloca(VAR_BUF_SIZE);
1460 /* Store variable name (and truncate) */
1461 ast_copy_string(var, vars, len + 1);
1463 /* Substitute if necessary */
1466 ltmp = alloca(VAR_BUF_SIZE);
1468 memset(ltmp, 0, VAR_BUF_SIZE);
1469 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1);
1476 workspace = alloca(VAR_BUF_SIZE);
1478 workspace[0] = '\0';
1480 if (var[len - 1] == ')') {
1481 /* Evaluate function */
1482 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE);
1484 ast_log(LOG_DEBUG, "Function result is '%s'\n", cp4 ? cp4 : "(null)");
1486 /* Retrieve variable value */
1487 pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp);
1490 length = strlen(cp4);
1493 memcpy(cp2, cp4, length);
1497 } else if (nextexp) {
1498 /* We have an expression. Find the start and end, and determine
1499 if we are going to have to recursively call ourselves on the
1501 vars = vare = nextexp + 2;
1505 /* Find the end of it */
1506 while(brackets && *vare) {
1507 if ((vare[0] == '$') && (vare[1] == '[')) {
1511 } else if (vare[0] == '[') {
1513 } else if (vare[0] == ']') {
1515 } else if ((vare[0] == '$') && (vare[1] == '{')) {
1522 ast_log(LOG_NOTICE, "Error in extension logic (missing ']')\n");
1523 len = vare - vars - 1;
1525 /* Skip totally over expression */
1526 whereweare += (len + 3);
1529 var = alloca(VAR_BUF_SIZE);
1531 /* Store variable name (and truncate) */
1532 ast_copy_string(var, vars, len + 1);
1534 /* Substitute if necessary */
1537 ltmp = alloca(VAR_BUF_SIZE);
1539 memset(ltmp, 0, VAR_BUF_SIZE);
1540 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1);
1546 length = ast_expr(vars, cp2, count);
1549 ast_log(LOG_DEBUG, "Expression result is '%s'\n", cp2);
1558 void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count)
1560 pbx_substitute_variables_helper_full(c, &c->varshead, cp1, cp2, count);
1563 void pbx_substitute_variables_varshead(struct varshead *headp, const char *cp1, char *cp2, int count)
1565 pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count);
1568 static void pbx_substitute_variables(char *passdata, int datalen, struct ast_channel *c, struct ast_exten *e)
1570 memset(passdata, 0, datalen);
1572 /* No variables or expressions in e->data, so why scan it? */
1573 if (!strchr(e->data, '$') && !strstr(e->data,"${") && !strstr(e->data,"$[") && !strstr(e->data,"$(")) {
1574 ast_copy_string(passdata, e->data, datalen);
1578 pbx_substitute_variables_helper(c, e->data, passdata, datalen - 1);
1581 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)
1583 struct ast_exten *e;
1584 struct ast_app *app;
1585 struct ast_switch *sw;
1587 const char *foundcontext=NULL;
1591 char *incstack[AST_PBX_MAX_STACK];
1592 char passdata[EXT_DATA_SIZE];
1596 char tmp3[EXT_DATA_SIZE];
1598 char atmp2[EXT_DATA_SIZE+100];
1600 if (ast_mutex_lock(&conlock)) {
1601 ast_log(LOG_WARNING, "Unable to obtain lock\n");
1602 if ((action == HELPER_EXISTS) || (action == HELPER_CANMATCH) || (action == HELPER_MATCHMORE))
1607 e = pbx_find_extension(c, con, context, exten, priority, label, callerid, action, incstack, &stacklen, &status, &sw, &data, &foundcontext);
1610 case HELPER_CANMATCH:
1611 ast_mutex_unlock(&conlock);
1614 ast_mutex_unlock(&conlock);
1616 case HELPER_FINDLABEL:
1618 ast_mutex_unlock(&conlock);
1620 case HELPER_MATCHMORE:
1621 ast_mutex_unlock(&conlock);
1627 app = pbx_findapp(e->app);
1628 ast_mutex_unlock(&conlock);
1630 if (c->context != context)
1631 ast_copy_string(c->context, context, sizeof(c->context));
1632 if (c->exten != exten)
1633 ast_copy_string(c->exten, exten, sizeof(c->exten));
1634 c->priority = priority;
1635 pbx_substitute_variables(passdata, sizeof(passdata), c, e);
1637 ast_log(LOG_DEBUG, "Launching '%s'\n", app->name);
1638 snprintf(atmp, 80, "STACK-%s-%s-%d", context, exten, priority);
1639 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"));
1640 pbx_builtin_setvar_helper(c, atmp, atmp2);
1642 if (option_verbose > 2)
1643 ast_verbose( VERBOSE_PREFIX_3 "Executing %s(\"%s\", \"%s\") %s\n",
1644 term_color(tmp, app->name, COLOR_BRCYAN, 0, sizeof(tmp)),
1645 term_color(tmp2, c->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)),
1646 term_color(tmp3, (!ast_strlen_zero(passdata) ? (char *)passdata : ""), COLOR_BRMAGENTA, 0, sizeof(tmp3)),
1647 (newstack ? "in new stack" : "in same stack"));
1648 manager_event(EVENT_FLAG_CALL, "Newexten",
1653 "Application: %s\r\n"
1656 c->name, c->context, c->exten, c->priority, app->name, passdata ? passdata : "(NULL)", c->uniqueid);
1657 res = pbx_exec(c, app, passdata, newstack);
1660 ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority);
1664 ast_log(LOG_WARNING, "Huh (%d)?\n", action); return -1;
1668 case HELPER_CANMATCH:
1669 ast_mutex_unlock(&conlock);
1672 ast_mutex_unlock(&conlock);
1674 case HELPER_MATCHMORE:
1675 ast_mutex_unlock(&conlock);
1677 case HELPER_FINDLABEL:
1678 ast_mutex_unlock(&conlock);
1684 ast_mutex_unlock(&conlock);
1686 res = sw->exec(c, foundcontext ? foundcontext : context, exten, priority, callerid, newstack, data);
1688 ast_log(LOG_WARNING, "No execution engine for switch %s\n", sw->name);
1693 ast_log(LOG_WARNING, "Huh (%d)?\n", action);
1697 ast_mutex_unlock(&conlock);
1699 case STATUS_NO_CONTEXT:
1700 if ((action != HELPER_EXISTS) && (action != HELPER_MATCHMORE))
1701 ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", context);
1703 case STATUS_NO_EXTENSION:
1704 if ((action != HELPER_EXISTS) && (action != HELPER_CANMATCH) && (action != HELPER_MATCHMORE))
1705 ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, context);
1707 case STATUS_NO_PRIORITY:
1708 if ((action != HELPER_EXISTS) && (action != HELPER_CANMATCH) && (action != HELPER_MATCHMORE))
1709 ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, context);
1711 case STATUS_NO_LABEL:
1713 ast_log(LOG_NOTICE, "No such label '%s' in extension '%s' in context '%s'\n", label, exten, context);
1716 ast_log(LOG_DEBUG, "Shouldn't happen!\n");
1719 if ((action != HELPER_EXISTS) && (action != HELPER_CANMATCH) && (action != HELPER_MATCHMORE))
1727 /*--- ast_hint_extension: Find hint for given extension in context */
1728 static struct ast_exten *ast_hint_extension(struct ast_channel *c, const char *context, const char *exten)
1730 struct ast_exten *e;
1731 struct ast_switch *sw;
1733 const char *foundcontext = NULL;
1735 char *incstack[AST_PBX_MAX_STACK];
1738 if (ast_mutex_lock(&conlock)) {
1739 ast_log(LOG_WARNING, "Unable to obtain lock\n");
1742 e = pbx_find_extension(c, NULL, context, exten, PRIORITY_HINT, NULL, "", HELPER_EXISTS, incstack, &stacklen, &status, &sw, &data, &foundcontext);
1743 ast_mutex_unlock(&conlock);
1747 /*--- ast_extensions_state2: Check state of extension by using hints */
1748 static int ast_extension_state2(struct ast_exten *e)
1750 char hint[AST_MAX_EXTENSION] = "";
1753 int allunavailable = 1, allbusy = 1, allfree = 1;
1754 int busy = 0, inuse = 0, ring = 0;
1759 ast_copy_string(hint, ast_get_extension_app(e), sizeof(hint));
1761 cur = hint; /* On or more devices separated with a & character */
1763 rest = strchr(cur, '&');
1769 res = ast_device_state(cur);
1771 case AST_DEVICE_NOT_INUSE:
1775 case AST_DEVICE_INUSE:
1780 case AST_DEVICE_RINGING:
1785 case AST_DEVICE_BUSY:
1790 case AST_DEVICE_UNAVAILABLE:
1791 case AST_DEVICE_INVALID:
1804 return AST_EXTENSION_RINGING;
1806 return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING);
1808 return AST_EXTENSION_INUSE;
1810 return AST_EXTENSION_NOT_INUSE;
1812 return AST_EXTENSION_BUSY;
1814 return AST_EXTENSION_UNAVAILABLE;
1816 return AST_EXTENSION_INUSE;
1818 return AST_EXTENSION_NOT_INUSE;
1821 /*--- ast_extension_state2str: Return extension_state as string */
1822 const char *ast_extension_state2str(int extension_state)
1826 for (i = 0; (i < (sizeof(extension_states) / sizeof(extension_states[0]))); i++) {
1827 if (extension_states[i].extension_state == extension_state) {
1828 return extension_states[i].text;
1834 /*--- ast_extension_state: Check extension state for an extension by using hint */
1835 int ast_extension_state(struct ast_channel *c, char *context, char *exten)
1837 struct ast_exten *e;
1839 e = ast_hint_extension(c, context, exten); /* Do we have a hint for this extension ? */
1841 return -1; /* No hint, return -1 */
1843 return ast_extension_state2(e); /* Check all devices in the hint */
1846 void ast_hint_state_changed(const char *device)
1848 struct ast_hint *hint;
1849 struct ast_state_cb *cblist;
1850 char buf[AST_MAX_EXTENSION];
1855 ast_mutex_lock(&hintlock);
1857 for (hint = hints; hint; hint = hint->next) {
1858 ast_copy_string(buf, ast_get_extension_app(hint->exten), sizeof(buf));
1860 for (cur = strsep(&parse, "&"); cur; cur = strsep(&parse, "&")) {
1861 if (strcmp(cur, device))
1864 /* Get device state for this hint */
1865 state = ast_extension_state2(hint->exten);
1867 if ((state == -1) || (state == hint->laststate))
1870 /* Device state changed since last check - notify the watchers */
1872 /* For general callbacks */
1873 for (cblist = statecbs; cblist; cblist = cblist->next)
1874 cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data);
1876 /* For extension callbacks */
1877 for (cblist = hint->callbacks; cblist; cblist = cblist->next)
1878 cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data);
1880 hint->laststate = state;
1885 ast_mutex_unlock(&hintlock);
1888 /*--- ast_extension_state_add: Add watcher for extension states */
1889 int ast_extension_state_add(const char *context, const char *exten,
1890 ast_state_cb_type callback, void *data)
1892 struct ast_hint *list;
1893 struct ast_state_cb *cblist;
1894 struct ast_exten *e;
1896 /* If there's no context and extension: add callback to statecbs list */
1897 if (!context && !exten) {
1898 ast_mutex_lock(&hintlock);
1902 if (cblist->callback == callback) {
1903 cblist->data = data;
1904 ast_mutex_unlock(&hintlock);
1907 cblist = cblist->next;
1910 /* Now insert the callback */
1911 cblist = malloc(sizeof(struct ast_state_cb));
1913 ast_mutex_unlock(&hintlock);
1916 memset(cblist, 0, sizeof(struct ast_state_cb));
1918 cblist->callback = callback;
1919 cblist->data = data;
1921 cblist->next = statecbs;
1924 ast_mutex_unlock(&hintlock);
1928 if (!context || !exten)
1931 /* This callback type is for only one hint, so get the hint */
1932 e = ast_hint_extension(NULL, context, exten);
1937 /* Find the hint in the list of hints */
1938 ast_mutex_lock(&hintlock);
1942 if (list->exten == e)
1948 /* We have no hint, sorry */
1949 ast_mutex_unlock(&hintlock);
1953 /* Now insert the callback in the callback list */
1954 cblist = malloc(sizeof(struct ast_state_cb));
1956 ast_mutex_unlock(&hintlock);
1959 memset(cblist, 0, sizeof(struct ast_state_cb));
1960 cblist->id = stateid++; /* Unique ID for this callback */
1961 cblist->callback = callback; /* Pointer to callback routine */
1962 cblist->data = data; /* Data for the callback */
1964 cblist->next = list->callbacks;
1965 list->callbacks = cblist;
1967 ast_mutex_unlock(&hintlock);
1971 /*--- ast_extension_state_del: Remove a watcher from the callback list */
1972 int ast_extension_state_del(int id, ast_state_cb_type callback)
1974 struct ast_hint *list;
1975 struct ast_state_cb *cblist, *cbprev;
1977 if (!id && !callback)
1980 ast_mutex_lock(&hintlock);
1982 /* id is zero is a callback without extension */
1987 if (cblist->callback == callback) {
1989 statecbs = cblist->next;
1991 cbprev->next = cblist->next;
1995 ast_mutex_unlock(&hintlock);
1999 cblist = cblist->next;
2002 ast_mutex_lock(&hintlock);
2006 /* id greater than zero is a callback with extension */
2007 /* Find the callback based on ID */
2010 cblist = list->callbacks;
2013 if (cblist->id==id) {
2015 list->callbacks = cblist->next;
2017 cbprev->next = cblist->next;
2021 ast_mutex_unlock(&hintlock);
2025 cblist = cblist->next;
2030 ast_mutex_unlock(&hintlock);
2034 /*--- ast_add_hint: Add hint to hint list, check initial extension state */
2035 static int ast_add_hint(struct ast_exten *e)
2037 struct ast_hint *list;
2042 ast_mutex_lock(&hintlock);
2045 /* Search if hint exists, do nothing */
2047 if (list->exten == e) {
2048 ast_mutex_unlock(&hintlock);
2049 if (option_debug > 1)
2050 ast_log(LOG_DEBUG, "HINTS: Not re-adding existing hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e));
2056 if (option_debug > 1)
2057 ast_log(LOG_DEBUG, "HINTS: Adding hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e));
2059 list = malloc(sizeof(struct ast_hint));
2061 ast_mutex_unlock(&hintlock);
2062 if (option_debug > 1)
2063 ast_log(LOG_DEBUG, "HINTS: Out of memory...\n");
2066 /* Initialize and insert new item at the top */
2067 memset(list, 0, sizeof(struct ast_hint));
2069 list->laststate = ast_extension_state2(e);
2073 ast_mutex_unlock(&hintlock);
2077 /*--- ast_change_hint: Change hint for an extension */
2078 static int ast_change_hint(struct ast_exten *oe, struct ast_exten *ne)
2080 struct ast_hint *list;
2082 ast_mutex_lock(&hintlock);
2086 if (list->exten == oe) {
2088 ast_mutex_unlock(&hintlock);
2093 ast_mutex_unlock(&hintlock);
2098 /*--- ast_remove_hint: Remove hint from extension */
2099 static int ast_remove_hint(struct ast_exten *e)
2101 /* Cleanup the Notifys if hint is removed */
2102 struct ast_hint *list, *prev = NULL;
2103 struct ast_state_cb *cblist, *cbprev;
2108 ast_mutex_lock(&hintlock);
2112 if (list->exten==e) {
2114 cblist = list->callbacks;
2116 /* Notify with -1 and remove all callbacks */
2118 cblist = cblist->next;
2119 cbprev->callback(list->exten->parent->name, list->exten->exten, AST_EXTENSION_DEACTIVATED, cbprev->data);
2122 list->callbacks = NULL;
2127 prev->next = list->next;
2130 ast_mutex_unlock(&hintlock);
2138 ast_mutex_unlock(&hintlock);
2143 /*--- ast_get_hint: Get hint for channel */
2144 int ast_get_hint(char *hint, int hintsize, char *name, int namesize, struct ast_channel *c, const char *context, const char *exten)
2146 struct ast_exten *e;
2149 e = ast_hint_extension(c, context, exten);
2152 ast_copy_string(hint, ast_get_extension_app(e), hintsize);
2154 tmp = ast_get_extension_app_data(e);
2156 ast_copy_string(name, (char *) tmp, namesize);
2163 int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
2165 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, HELPER_EXISTS);
2168 int ast_findlabel_extension(struct ast_channel *c, const char *context, const char *exten, const char *label, const char *callerid)
2170 return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, HELPER_FINDLABEL);
2173 int ast_findlabel_extension2(struct ast_channel *c, struct ast_context *con, const char *exten, const char *label, const char *callerid)
2175 return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, HELPER_FINDLABEL);
2178 int ast_canmatch_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
2180 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, HELPER_CANMATCH);
2183 int ast_matchmore_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
2185 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, HELPER_MATCHMORE);
2188 int ast_spawn_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
2190 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, HELPER_SPAWN);
2193 int ast_exec_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
2195 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, HELPER_EXEC);
2198 static int __ast_pbx_run(struct ast_channel *c)
2208 /* A little initial setup here */
2210 ast_log(LOG_WARNING, "%s already has PBX structure??\n", c->name);
2211 c->pbx = malloc(sizeof(struct ast_pbx));
2213 ast_log(LOG_ERROR, "Out of memory\n");
2218 c->cdr = ast_cdr_alloc();
2220 ast_log(LOG_WARNING, "Unable to create Call Detail Record\n");
2224 ast_cdr_init(c->cdr, c);
2227 memset(c->pbx, 0, sizeof(struct ast_pbx));
2228 /* Set reasonable defaults */
2229 c->pbx->rtimeout = 10;
2230 c->pbx->dtimeout = 5;
2232 autoloopflag = ast_test_flag(c, AST_FLAG_IN_AUTOLOOP);
2233 ast_set_flag(c, AST_FLAG_IN_AUTOLOOP);
2235 /* Start by trying whatever the channel is set to */
2236 if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) {
2237 /* If not successful fall back to 's' */
2238 if (option_verbose > 1)
2239 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);
2240 ast_copy_string(c->exten, "s", sizeof(c->exten));
2241 if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) {
2242 /* JK02: And finally back to default if everything else failed */
2243 if (option_verbose > 1)
2244 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);
2245 ast_copy_string(c->context, "default", sizeof(c->context));
2249 if (c->cdr && !c->cdr->start.tv_sec && !c->cdr->start.tv_usec)
2250 ast_cdr_start(c->cdr);
2254 while(ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) {
2255 memset(exten, 0, sizeof(exten));
2256 if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num))) {
2257 /* Something bad happened, or a hangup has been requested. */
2258 if (((res >= '0') && (res <= '9')) || ((res >= 'A') && (res <= 'F')) ||
2259 (res == '*') || (res == '#')) {
2260 ast_log(LOG_DEBUG, "Oooh, got something to jump out with ('%c')!\n", res);
2261 memset(exten, 0, sizeof(exten));
2263 exten[pos++] = digit = res;
2267 case AST_PBX_KEEPALIVE:
2269 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
2270 else if (option_verbose > 1)
2271 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
2276 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
2277 else if (option_verbose > 1)
2278 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
2279 if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
2284 if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) {
2294 if ((c->_softhangup == AST_SOFTHANGUP_TIMEOUT) && (ast_exists_extension(c,c->context,"T",1,c->cid.cid_num))) {
2295 ast_copy_string(c->exten, "T", sizeof(c->exten));
2296 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
2297 c->whentohangup = 0;
2299 c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT;
2300 } else if (c->_softhangup) {
2301 ast_log(LOG_DEBUG, "Extension %s, priority %d returned normally even though call was hung up\n",
2302 c->exten, c->priority);
2308 if (!ast_exists_extension(c, c->context, c->exten, 1, c->cid.cid_num)) {
2309 /* It's not a valid extension anymore */
2310 if (ast_exists_extension(c, c->context, "i", 1, c->cid.cid_num)) {
2311 if (option_verbose > 2)
2312 ast_verbose(VERBOSE_PREFIX_3 "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, c->name);
2313 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", c->exten);
2314 ast_copy_string(c->exten, "i", sizeof(c->exten));
2317 ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n",
2318 c->name, c->exten, c->context);
2321 } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) {
2322 /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */
2325 /* Done, wait for an extension */
2328 waittime = c->pbx->dtimeout;
2329 else if (!autofallthrough)
2330 waittime = c->pbx->rtimeout;
2332 while (ast_matchmore_extension(c, c->context, exten, 1, c->cid.cid_num)) {
2333 /* As long as we're willing to wait, and as long as it's not defined,
2334 keep reading digits until we can't possibly get a right answer anymore. */
2335 digit = ast_waitfordigit(c, waittime * 1000);
2336 if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
2343 /* Error, maybe a hangup */
2345 exten[pos++] = digit;
2346 waittime = c->pbx->dtimeout;
2349 if (ast_exists_extension(c, c->context, exten, 1, c->cid.cid_num)) {
2350 /* Prepare the next cycle */
2351 ast_copy_string(c->exten, exten, sizeof(c->exten));
2354 /* No such extension */
2355 if (!ast_strlen_zero(exten)) {
2356 /* An invalid extension */
2357 if (ast_exists_extension(c, c->context, "i", 1, c->cid.cid_num)) {
2358 if (option_verbose > 2)
2359 ast_verbose( VERBOSE_PREFIX_3 "Invalid extension '%s' in context '%s' on %s\n", exten, c->context, c->name);
2360 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", exten);
2361 ast_copy_string(c->exten, "i", sizeof(c->exten));
2364 ast_log(LOG_WARNING, "Invalid extension '%s', but no rule 'i' in context '%s'\n", exten, c->context);
2368 /* A simple timeout */
2369 if (ast_exists_extension(c, c->context, "t", 1, c->cid.cid_num)) {
2370 if (option_verbose > 2)
2371 ast_verbose( VERBOSE_PREFIX_3 "Timeout on %s\n", c->name);
2372 ast_copy_string(c->exten, "t", sizeof(c->exten));
2375 ast_log(LOG_WARNING, "Timeout, but no rule 't' in context '%s'\n", c->context);
2381 if (option_verbose > 2)
2382 ast_verbose(VERBOSE_PREFIX_2 "CDR updated on %s\n",c->name);
2388 status = pbx_builtin_getvar_helper(c, "DIALSTATUS");
2391 if (option_verbose > 2)
2392 ast_verbose(VERBOSE_PREFIX_2 "Auto fallthrough, channel '%s' status is '%s'\n", c->name, status);
2393 if (!strcasecmp(status, "CONGESTION"))
2394 res = pbx_builtin_congestion(c, "10");
2395 else if (!strcasecmp(status, "CHANUNAVAIL"))
2396 res = pbx_builtin_congestion(c, "10");
2397 else if (!strcasecmp(status, "BUSY"))
2398 res = pbx_builtin_busy(c, "10");
2404 ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name);
2406 if ((res != AST_PBX_KEEPALIVE) && ast_exists_extension(c, c->context, "h", 1, c->cid.cid_num)) {
2410 while(ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) {
2411 if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num))) {
2412 /* Something bad happened, or a hangup has been requested. */
2414 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
2415 else if (option_verbose > 1)
2416 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
2422 ast_set2_flag(c, autoloopflag, AST_FLAG_IN_AUTOLOOP);
2424 pbx_destroy(c->pbx);
2426 if (res != AST_PBX_KEEPALIVE)
2431 /* Returns 0 on success, non-zero if call limit was reached */
2432 static int increase_call_count(const struct ast_channel *c)
2436 ast_mutex_lock(&maxcalllock);
2437 if (option_maxcalls) {
2438 if (countcalls >= option_maxcalls) {
2439 ast_log(LOG_NOTICE, "Maximum call limit of %d calls exceeded by '%s'!\n", option_maxcalls, c->name);
2445 ast_mutex_unlock(&maxcalllock);
2450 static void decrease_call_count(void)
2452 ast_mutex_lock(&maxcalllock);
2455 ast_mutex_unlock(&maxcalllock);
2458 static void *pbx_thread(void *data)
2460 /* Oh joyeous kernel, we're a new thread, with nothing to do but
2461 answer this channel and get it going.
2464 The launcher of this function _MUST_ increment 'countcalls'
2465 before invoking the function; it will be decremented when the
2466 PBX has finished running on the channel
2468 struct ast_channel *c = data;
2471 decrease_call_count();
2478 enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
2481 pthread_attr_t attr;
2484 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
2485 return AST_PBX_FAILED;
2488 if (increase_call_count(c))
2489 return AST_PBX_CALL_LIMIT;
2491 /* Start a new thread, and get something handling this channel. */
2492 pthread_attr_init(&attr);
2493 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
2494 if (ast_pthread_create(&t, &attr, pbx_thread, c)) {
2495 ast_log(LOG_WARNING, "Failed to create new channel thread\n");
2496 return AST_PBX_FAILED;
2499 return AST_PBX_SUCCESS;
2502 enum ast_pbx_result ast_pbx_run(struct ast_channel *c)
2504 enum ast_pbx_result res = AST_PBX_SUCCESS;
2506 if (increase_call_count(c))
2507 return AST_PBX_CALL_LIMIT;
2509 res = __ast_pbx_run(c);
2510 decrease_call_count();
2515 int ast_active_calls(void)
2520 int pbx_set_autofallthrough(int newval)
2523 oldval = autofallthrough;
2524 if (oldval != newval)
2525 autofallthrough = newval;
2530 * This function locks contexts list by &conlist, search for the right context
2531 * structure, leave context list locked and call ast_context_remove_include2
2532 * which removes include, unlock contexts list and return ...
2534 int ast_context_remove_include(const char *context, const char *include, const char *registrar)
2536 struct ast_context *c;
2538 if (ast_lock_contexts()) return -1;
2540 /* walk contexts and search for the right one ...*/
2541 c = ast_walk_contexts(NULL);
2543 /* we found one ... */
2544 if (!strcmp(ast_get_context_name(c), context)) {
2546 /* remove include from this context ... */
2547 ret = ast_context_remove_include2(c, include, registrar);
2549 ast_unlock_contexts();
2551 /* ... return results */
2554 c = ast_walk_contexts(c);
2557 /* we can't find the right one context */
2558 ast_unlock_contexts();
2563 * When we call this function, &conlock lock must be locked, because when
2564 * we giving *con argument, some process can remove/change this context
2565 * and after that there can be segfault.
2567 * This function locks given context, removes include, unlock context and
2570 int ast_context_remove_include2(struct ast_context *con, const char *include, const char *registrar)
2572 struct ast_include *i, *pi = NULL;
2574 if (ast_mutex_lock(&con->lock)) return -1;
2579 /* find our include */
2580 if (!strcmp(i->name, include) &&
2581 (!registrar || !strcmp(i->registrar, registrar))) {
2582 /* remove from list */
2586 con->includes = i->next;
2587 /* free include and return */
2589 ast_mutex_unlock(&con->lock);
2596 /* we can't find the right include */
2597 ast_mutex_unlock(&con->lock);
2602 * This function locks contexts list by &conlist, search for the rigt context
2603 * structure, leave context list locked and call ast_context_remove_switch2
2604 * which removes switch, unlock contexts list and return ...
2606 int ast_context_remove_switch(const char *context, const char *sw, const char *data, const char *registrar)
2608 struct ast_context *c;
2610 if (ast_lock_contexts()) return -1;
2612 /* walk contexts and search for the right one ...*/
2613 c = ast_walk_contexts(NULL);
2615 /* we found one ... */
2616 if (!strcmp(ast_get_context_name(c), context)) {
2618 /* remove switch from this context ... */
2619 ret = ast_context_remove_switch2(c, sw, data, registrar);
2621 ast_unlock_contexts();
2623 /* ... return results */
2626 c = ast_walk_contexts(c);
2629 /* we can't find the right one context */
2630 ast_unlock_contexts();
2635 * When we call this function, &conlock lock must be locked, because when
2636 * we giving *con argument, some process can remove/change this context
2637 * and after that there can be segfault.
2639 * This function locks given context, removes switch, unlock context and
2642 int ast_context_remove_switch2(struct ast_context *con, const char *sw, const char *data, const char *registrar)
2644 struct ast_sw *i, *pi = NULL;
2646 if (ast_mutex_lock(&con->lock)) return -1;
2651 /* find our switch */
2652 if (!strcmp(i->name, sw) && !strcmp(i->data, data) &&
2653 (!registrar || !strcmp(i->registrar, registrar))) {
2654 /* remove from list */
2658 con->alts = i->next;
2659 /* free switch and return */
2661 ast_mutex_unlock(&con->lock);
2668 /* we can't find the right switch */
2669 ast_mutex_unlock(&con->lock);
2674 * This functions lock contexts list, search for the right context,
2675 * call ast_context_remove_extension2, unlock contexts list and return.
2676 * In this function we are using
2678 int ast_context_remove_extension(const char *context, const char *extension, int priority, const char *registrar)
2680 struct ast_context *c;
2682 if (ast_lock_contexts()) return -1;
2684 /* walk contexts ... */
2685 c = ast_walk_contexts(NULL);
2687 /* ... search for the right one ... */
2688 if (!strcmp(ast_get_context_name(c), context)) {
2689 /* ... remove extension ... */
2690 int ret = ast_context_remove_extension2(c, extension, priority,
2692 /* ... unlock contexts list and return */
2693 ast_unlock_contexts();
2696 c = ast_walk_contexts(c);
2699 /* we can't find the right context */
2700 ast_unlock_contexts();
2705 * When do you want to call this function, make sure that &conlock is locked,
2706 * because some process can handle with your *con context before you lock
2709 * This functionc locks given context, search for the right extension and
2710 * fires out all peer in this extensions with given priority. If priority
2711 * is set to 0, all peers are removed. After that, unlock context and
2714 int ast_context_remove_extension2(struct ast_context *con, const char *extension, int priority, const char *registrar)
2716 struct ast_exten *exten, *prev_exten = NULL;
2718 if (ast_mutex_lock(&con->lock)) return -1;
2720 /* go through all extensions in context and search the right one ... */
2724 /* look for right extension */
2725 if (!strcmp(exten->exten, extension) &&
2726 (!registrar || !strcmp(exten->registrar, registrar))) {
2727 struct ast_exten *peer;
2729 /* should we free all peers in this extension? (priority == 0)? */
2730 if (priority == 0) {
2731 /* remove this extension from context list */
2733 prev_exten->next = exten->next;
2735 con->root = exten->next;
2737 /* fire out all peers */
2742 if (!peer->priority==PRIORITY_HINT)
2743 ast_remove_hint(peer);
2745 peer->datad(peer->data);
2751 ast_mutex_unlock(&con->lock);
2754 /* remove only extension with exten->priority == priority */
2755 struct ast_exten *previous_peer = NULL;
2759 /* is this our extension? */
2760 if (peer->priority == priority &&
2761 (!registrar || !strcmp(peer->registrar, registrar) )) {
2762 /* we are first priority extension? */
2763 if (!previous_peer) {
2764 /* exists previous extension here? */
2766 /* yes, so we must change next pointer in
2767 * previous connection to next peer
2770 prev_exten->next = peer->peer;
2771 peer->peer->next = exten->next;
2773 prev_exten->next = exten->next;
2775 /* no previous extension, we are first
2776 * extension, so change con->root ...
2779 con->root = peer->peer;
2781 con->root = exten->next;
2784 /* we are not first priority in extension */
2785 previous_peer->peer = peer->peer;
2788 /* now, free whole priority extension */
2789 if (peer->priority==PRIORITY_HINT)
2790 ast_remove_hint(peer);
2791 peer->datad(peer->data);
2794 ast_mutex_unlock(&con->lock);
2797 /* this is not right extension, skip to next peer */
2798 previous_peer = peer;
2803 ast_mutex_unlock(&con->lock);
2809 exten = exten->next;
2812 /* we can't find right extension */
2813 ast_mutex_unlock(&con->lock);
2818 int ast_register_application(const char *app, int (*execute)(struct ast_channel *, void *), const char *synopsis, const char *description)
2820 struct ast_app *tmp, *prev, *cur;
2823 length = sizeof(struct ast_app);
2824 length += strlen(app) + 1;
2825 if (ast_mutex_lock(&applock)) {
2826 ast_log(LOG_ERROR, "Unable to lock application list\n");
2831 if (!strcasecmp(app, tmp->name)) {
2832 ast_log(LOG_WARNING, "Already have an application '%s'\n", app);
2833 ast_mutex_unlock(&applock);
2838 tmp = malloc(length);
2840 memset(tmp, 0, length);
2841 strcpy(tmp->name, app);
2842 tmp->execute = execute;
2843 tmp->synopsis = synopsis;
2844 tmp->description = description;
2845 /* Store in alphabetical order */
2849 if (strcasecmp(tmp->name, cur->name) < 0)
2855 tmp->next = prev->next;
2862 ast_log(LOG_ERROR, "Out of memory\n");
2863 ast_mutex_unlock(&applock);
2866 if (option_verbose > 1)
2867 ast_verbose( VERBOSE_PREFIX_2 "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps)));
2868 ast_mutex_unlock(&applock);
2872 int ast_register_switch(struct ast_switch *sw)
2874 struct ast_switch *tmp, *prev=NULL;
2875 if (ast_mutex_lock(&switchlock)) {
2876 ast_log(LOG_ERROR, "Unable to lock switch lock\n");
2881 if (!strcasecmp(tmp->name, sw->name))
2887 ast_mutex_unlock(&switchlock);
2888 ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name);
2896 ast_mutex_unlock(&switchlock);
2900 void ast_unregister_switch(struct ast_switch *sw)
2902 struct ast_switch *tmp, *prev=NULL;
2903 if (ast_mutex_lock(&switchlock)) {
2904 ast_log(LOG_ERROR, "Unable to lock switch lock\n");
2911 prev->next = tmp->next;
2913 switches = tmp->next;
2920 ast_mutex_unlock(&switchlock);
2924 * Help for CLI commands ...
2926 static char show_application_help[] =
2927 "Usage: show application <application> [<application> [<application> [...]]]\n"
2928 " Describes a particular application.\n";
2930 static char show_functions_help[] =
2931 "Usage: show functions\n"
2932 " List builtin functions accessable as $(function args)\n";
2934 static char show_function_help[] =
2935 "Usage: show function <function>\n"
2936 " Describe a particular dialplan function.\n";
2938 static char show_applications_help[] =
2939 "Usage: show applications [{like|describing} <text>]\n"
2940 " List applications which are currently available.\n"
2941 " If 'like', <text> will be a substring of the app name\n"
2942 " If 'describing', <text> will be a substring of the description\n";
2944 static char show_dialplan_help[] =
2945 "Usage: show dialplan [exten@][context]\n"
2948 static char show_switches_help[] =
2949 "Usage: show switches\n"
2950 " Show registered switches\n";
2952 static char show_hints_help[] =
2953 "Usage: show hints\n"
2954 " Show registered hints\n";
2958 * IMPLEMENTATION OF CLI FUNCTIONS IS IN THE SAME ORDER AS COMMANDS HELPS
2963 * 'show application' CLI command implementation functions ...
2967 * There is a possibility to show informations about more than one
2968 * application at one time. You can type 'show application Dial Echo' and
2969 * you will see informations about these two applications ...
2971 static char *complete_show_application(char *line, char *word,
2977 /* try to lock applications list ... */
2978 if (ast_mutex_lock(&applock)) {
2979 ast_log(LOG_ERROR, "Unable to lock application list\n");
2983 /* ... walk all applications ... */
2986 /* ... check if word matches this application ... */
2987 if (!strncasecmp(word, a->name, strlen(word))) {
2988 /* ... if this is right app serve it ... */
2989 if (++which > state) {
2990 char *ret = strdup(a->name);
2991 ast_mutex_unlock(&applock);
2998 /* no application match */
2999 ast_mutex_unlock(&applock);
3003 static int handle_show_application(int fd, int argc, char *argv[])
3006 int app, no_registered_app = 1;
3008 if (argc < 3) return RESULT_SHOWUSAGE;
3010 /* try to lock applications list ... */
3011 if (ast_mutex_lock(&applock)) {
3012 ast_log(LOG_ERROR, "Unable to lock application list\n");
3016 /* ... go through all applications ... */
3019 /* ... compare this application name with all arguments given
3020 * to 'show application' command ... */
3021 for (app = 2; app < argc; app++) {
3022 if (!strcasecmp(a->name, argv[app])) {
3023 /* Maximum number of characters added by terminal coloring is 22 */
3024 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40];
3025 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL;
3026 int synopsis_size, description_size;
3028 no_registered_app = 0;
3031 synopsis_size = strlen(a->synopsis) + 23;
3033 synopsis_size = strlen("Not available") + 23;
3034 synopsis = alloca(synopsis_size);
3037 description_size = strlen(a->description) + 23;
3039 description_size = strlen("Not available") + 23;