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"
59 #include "asterisk/compat.h"
62 * \note I M P O R T A N T :
64 * The speed of extension handling will likely be among the most important
65 * aspects of this PBX. The switching scheme as it exists right now isn't
66 * terribly bad (it's O(N+M), where N is the # of extensions and M is the avg #
67 * of priorities, but a constant search time here would be great ;-)
72 #define EXT_DATA_SIZE 256
74 #define EXT_DATA_SIZE 8192
77 #define SWITCH_DATA_LENGTH 256
79 #define VAR_BUF_SIZE 4096
82 #define VAR_SOFTTRAN 2
83 #define VAR_HARDTRAN 3
85 #define BACKGROUND_SKIP (1 << 0)
86 #define BACKGROUND_NOANSWER (1 << 1)
87 #define BACKGROUND_MATCHEXTEN (1 << 2)
88 #define BACKGROUND_PLAYBACK (1 << 3)
90 AST_APP_OPTIONS(background_opts, {
91 AST_APP_OPTION('s', BACKGROUND_SKIP),
92 AST_APP_OPTION('n', BACKGROUND_NOANSWER),
93 AST_APP_OPTION('m', BACKGROUND_MATCHEXTEN),
94 AST_APP_OPTION('p', BACKGROUND_PLAYBACK),
97 #define WAITEXTEN_MOH (1 << 0)
99 AST_APP_OPTIONS(waitexten_opts, {
100 AST_APP_OPTION_ARG('m', WAITEXTEN_MOH, 1),
105 /*!\brief ast_exten: An extension
106 The dialplan is saved as a linked list with each context
107 having it's own linked list of extensions - one item per
111 char *exten; /* Extension name */
112 int matchcid; /* Match caller id ? */
113 char *cidmatch; /* Caller id to match for this extension */
114 int priority; /* Priority */
115 char *label; /* Label */
116 struct ast_context *parent; /* The context this extension belongs to */
117 char *app; /* Application to execute */
118 void *data; /* Data to use (arguments) */
119 void (*datad)(void *); /* Data destructor */
120 struct ast_exten *peer; /* Next higher priority with our extension */
121 const char *registrar; /* Registrar */
122 struct ast_exten *next; /* Extension with a greater ID */
126 /*! \brief ast_include: include= support in extensions.conf */
129 char *rname; /* Context to include */
130 const char *registrar; /* Registrar */
131 int hastime; /* If time construct exists */
132 struct ast_timing timing; /* time construct */
133 struct ast_include *next; /* Link them together */
137 /*! \brief ast_sw: Switch statement in extensions.conf */
140 const char *registrar; /* Registrar */
141 char *data; /* Data load */
143 struct ast_sw *next; /* Link them together */
148 /*! \brief ast_ignorepat: Ignore patterns in dial plan */
149 struct ast_ignorepat {
150 const char *registrar;
151 struct ast_ignorepat *next;
155 /*! \brief ast_context: An extension context */
157 ast_mutex_t lock; /*!< A lock to prevent multiple threads from clobbering the context */
158 struct ast_exten *root; /*!< The root of the list of extensions */
159 struct ast_context *next; /*!< Link them together */
160 struct ast_include *includes; /*!< Include other contexts */
161 struct ast_ignorepat *ignorepats; /*!< Patterns for which to continue playing dialtone */
162 const char *registrar; /*!< Registrar */
163 struct ast_sw *alts; /*!< Alternative switches */
164 char name[0]; /*!< Name of the context */
168 /*! \brief ast_app: A registered application */
170 int (*execute)(struct ast_channel *chan, void *data);
171 const char *synopsis; /* Synopsis text for 'show applications' */
172 const char *description; /* Description (help text) for 'show application <name>' */
173 struct ast_app *next; /* Next app in list */
174 char name[0]; /* Name of the application */
177 /*! \brief ast_state_cb: An extension state notify register item */
178 struct ast_state_cb {
181 ast_state_cb_type callback;
182 struct ast_state_cb *next;
185 /*! \brief Structure for dial plan hints
187 Hints are pointers from an extension in the dialplan to one or
188 more devices (tech/name) */
190 struct ast_exten *exten; /*!< Extension */
191 int laststate; /*!< Last known state */
192 struct ast_state_cb *callbacks; /*!< Callback list for this extension */
193 struct ast_hint *next; /*!< Pointer to next hint in list */
196 int ast_pbx_outgoing_cdr_failed(void);
198 static int pbx_builtin_answer(struct ast_channel *, void *);
199 static int pbx_builtin_goto(struct ast_channel *, void *);
200 static int pbx_builtin_hangup(struct ast_channel *, void *);
201 static int pbx_builtin_background(struct ast_channel *, void *);
202 static int pbx_builtin_dtimeout(struct ast_channel *, void *);
203 static int pbx_builtin_rtimeout(struct ast_channel *, void *);
204 static int pbx_builtin_atimeout(struct ast_channel *, void *);
205 static int pbx_builtin_wait(struct ast_channel *, void *);
206 static int pbx_builtin_waitexten(struct ast_channel *, void *);
207 static int pbx_builtin_setlanguage(struct ast_channel *, void *);
208 static int pbx_builtin_resetcdr(struct ast_channel *, void *);
209 static int pbx_builtin_setaccount(struct ast_channel *, void *);
210 static int pbx_builtin_setamaflags(struct ast_channel *, void *);
211 static int pbx_builtin_ringing(struct ast_channel *, void *);
212 static int pbx_builtin_progress(struct ast_channel *, void *);
213 static int pbx_builtin_congestion(struct ast_channel *, void *);
214 static int pbx_builtin_busy(struct ast_channel *, void *);
215 static int pbx_builtin_setglobalvar(struct ast_channel *, void *);
216 static int pbx_builtin_noop(struct ast_channel *, void *);
217 static int pbx_builtin_gotoif(struct ast_channel *, void *);
218 static int pbx_builtin_gotoiftime(struct ast_channel *, void *);
219 static int pbx_builtin_execiftime(struct ast_channel *, void *);
220 static int pbx_builtin_saynumber(struct ast_channel *, void *);
221 static int pbx_builtin_saydigits(struct ast_channel *, void *);
222 static int pbx_builtin_saycharacters(struct ast_channel *, void *);
223 static int pbx_builtin_sayphonetic(struct ast_channel *, void *);
224 static int pbx_builtin_setvar_old(struct ast_channel *, void *);
225 int pbx_builtin_setvar(struct ast_channel *, void *);
226 static int pbx_builtin_importvar(struct ast_channel *, void *);
228 static struct varshead globals;
230 static int autofallthrough = 0;
232 AST_MUTEX_DEFINE_STATIC(maxcalllock);
233 static int countcalls = 0;
235 AST_MUTEX_DEFINE_STATIC(acflock); /*!< Lock for the custom function list */
236 static struct ast_custom_function *acf_root = NULL;
238 /*! \brief Declaration of builtin applications */
239 static struct pbx_builtin {
240 char name[AST_MAX_APP];
241 int (*execute)(struct ast_channel *chan, void *data);
246 /* These applications are built into the PBX core and do not
247 need separate modules */
249 { "AbsoluteTimeout", pbx_builtin_atimeout,
250 "Set absolute maximum time of call",
251 " AbsoluteTimeout(seconds): This application will set the absolute maximum\n"
252 "amount of time permitted for a call. A setting of 0 disables the timeout.\n"
253 " AbsoluteTimeout has been deprecated in favor of Set(TIMEOUT(absolute)=timeout)\n"
256 { "Answer", pbx_builtin_answer,
257 "Answer a channel if ringing",
258 " Answer([delay]): If the call has not been answered, this application will\n"
259 "answer it. Otherwise, it has no effect on the call. If a delay is specified,\n"
260 "Asterisk will wait this number of milliseconds before answering the call.\n"
263 { "BackGround", pbx_builtin_background,
264 "Play a file while awaiting extension",
265 " Background(filename1[&filename2...][|options[|langoverride][|context]]):\n"
266 "This application will play the given list of files while waiting for an\n"
267 "extension to be dialed by the calling channel. To continue waiting for digits\n"
268 "after this application has finished playing files, the WaitExten application\n"
269 "should be used. The 'langoverride' option explicity specifies which language\n"
270 "to attempt to use for the requested sound files. If a 'context' is specified,\n"
271 "this is the dialplan context that this application will use when exiting to a\n"
273 " If one of the requested sound files does not exist, call processing will be\n"
276 " s - causes the playback of the message to be skipped\n"
277 " if the channel is not in the 'up' state (i.e. it\n"
278 " hasn't been answered yet.) If this happens, the\n"
279 " application will return immediately.\n"
280 " n - don't answer the channel before playing the files\n"
281 " m - only break if a digit hit matches a one digit\n"
282 " extension in the destination context\n"
285 { "Busy", pbx_builtin_busy,
286 "Indicate the Busy condition",
287 " Busy([timeout]): This application will indicate the busy condition to\n"
288 "the calling channel. If the optional timeout is specified, the calling channel\n"
289 "will be hung up after the specified number of seconds. Otherwise, this\n"
290 "application will wait until the calling channel hangs up.\n"
293 { "Congestion", pbx_builtin_congestion,
294 "Indicate the Congestion condition",
295 " Congestion([timeout]): This application will indicate the congenstion\n"
296 "condition to the calling channel. If the optional timeout is specified, the\n"
297 "calling channel will be hung up after the specified number of seconds.\n"
298 "Otherwise, this application will wait until the calling channel hangs up.\n"
301 { "DigitTimeout", pbx_builtin_dtimeout,
302 "Set maximum timeout between digits",
303 " DigitTimeout(seconds): Set the maximum amount of time permitted between\n"
304 "digits when the user is typing in an extension. When this timeout expires,\n"
305 "after the user has started to type in an extension, the extension will be\n"
306 "considered complete, and will be interpreted. Note that if an extension\n"
307 "typed in is valid, it will not have to timeout to be tested, so typically\n"
308 "at the expiry of this timeout, the extension will be considered invalid\n"
309 "(and thus control would be passed to the 'i' extension, or if it doesn't\n"
310 "exist the call would be terminated). The default timeout is 5 seconds.\n"
311 " DigitTimeout has been deprecated in favor of Set(TIMEOUT(digit)=timeout)\n"
314 { "Goto", pbx_builtin_goto,
315 "Jump to a particular priority, extension, or context",
316 " Goto([[context|]extension|]priority): This application will cause the\n"
317 "calling channel to continue dialplan execution at the specified priority.\n"
318 "If no specific extension, or extension and context, are specified, then this\n"
319 "application will jump to the specified priority of the current extension.\n"
320 " If the attempt to jump to another location in the dialplan is not successful,\n"
321 "then the channel will continue at the next priority of the current extension.\n"
324 { "GotoIf", pbx_builtin_gotoif,
326 " GotoIf(Condition?[label1]:[label2]): This application will cause the calling\n"
327 "channel to jump to the speicifed location in the dialplan based on the\n"
328 "evaluation of the given condition. The channel will continue at 'label1' if the\n"
329 "condition is true, or 'label2' if the condition is false. The labels are\n"
330 "specified in the same syntax that is used with the Goto application.\n"
333 { "GotoIfTime", pbx_builtin_gotoiftime,
334 "Conditional Goto based on the current time",
335 " GotoIfTime(<times>|<weekdays>|<mdays>|<months>?[[context|]exten|]priority):\n"
336 "This application will have the calling channel jump to the speicified location\n"
337 "int the dialplan if the current time matches the given time specification.\n"
338 "Further information on the time specification can be found in examples\n"
339 "illustrating how to do time-based context includes in the dialplan.\n"
342 { "ExecIfTime", pbx_builtin_execiftime,
343 "Conditional application execution based on the current time",
344 " ExecIfTime(<times>|<weekdays>|<mdays>|<months>?appname[|appargs]):\n"
345 "This application will execute the specified dialplan application, with optional\n"
346 "arguments, if the current time matches the given time specification. Further\n"
347 "information on the time speicification can be found in examples illustrating\n"
348 "how to do time-based context includes in the dialplan.\n"
351 { "Hangup", pbx_builtin_hangup,
352 "Hang up the calling channel",
353 " Hangup(): This application will hang up the calling channel.\n"
356 { "NoOp", pbx_builtin_noop,
358 " NoOp(): This applicatiion does nothing. However, it is useful for debugging\n"
359 "purposes. Any text that is provided as arguments to this application can be\n"
360 "viewed at the Asterisk CLI. This method can be used to see the evaluations of\n"
361 "variables or functions without having any effect."
364 { "Progress", pbx_builtin_progress,
366 " Progress(): This application will request that in-band progress information\n"
367 "be provided to the calling channel.\n"
370 { "ResetCDR", pbx_builtin_resetcdr,
371 "Resets the Call Data Record",
372 " ResetCDR([options]): This application causes the Call Data Record to be\n"
375 " w -- Store the current CDR record before resetting it.\n"
376 " a -- Store any stacked records.\n"
377 " v -- Save CDR variables.\n"
380 { "ResponseTimeout", pbx_builtin_rtimeout,
381 "Set maximum timeout awaiting response",
382 " ResponseTimeout(seconds): This will set the maximum amount of time permitted\n"
383 "to wait for an extension to dialed (see the WaitExten application), before the\n"
384 "timeout occurs. If this timeout is reached, dialplan execution will continue at\n"
385 "the 't' extension, if it exists.\n"
386 " ResponseTimeout has been deprecated in favor of Set(TIMEOUT(response)=timeout)\n"
389 { "Ringing", pbx_builtin_ringing,
390 "Indicate ringing tone",
391 " Ringing(): This application will request that the channel indicate a ringing\n"
392 "tone to the user.\n"
395 { "SayNumber", pbx_builtin_saynumber,
397 " SayNumber(digits[,gender]): This application will play the sounds that\n"
398 "correspond to the given number. Optionally, a gender may be specified.\n"
399 "This will use the language that is currently set for the channel. See the\n"
400 "LANGUAGE function for more information on setting the language for the channel.\n"
403 { "SayDigits", pbx_builtin_saydigits,
405 " SayDigits(digits): This application will play the sounds that correspond\n"
406 "to the digits of the given number. This will use the language that is currently\n"
407 "set for the channel. See the LANGUAGE function for more information on setting\n"
408 "the language for the channel.\n"
411 { "SayAlpha", pbx_builtin_saycharacters,
413 " SayAlpha(string): This application will play the sounds that correspond to\n"
414 "the letters of the given string.\n"
417 { "SayPhonetic", pbx_builtin_sayphonetic,
419 " SayPhonetic(string): This application will play the sounds from the phonetic\n"
420 "alphabet that correspond to the letters in the given string.\n"
423 { "SetAccount", pbx_builtin_setaccount,
424 "Set the CDR Account Code",
425 " SetAccount([account]): This application will set the channel account code for\n"
426 "billing purposes.\n"
427 " SetAccount has been deprecated in favor of the Set(CDR(accountcode)=account).\n"
430 { "SetAMAFlags", pbx_builtin_setamaflags,
432 " SetAMAFlags([flag]): This channel will set the channel's AMA Flags for billing\n"
436 { "SetGlobalVar", pbx_builtin_setglobalvar,
437 "Set a global variable to a given value",
438 " SetGlobalVar(variable=value): This application sets a given global variable to\n"
439 "the specified value.\n"
442 { "SetLanguage", pbx_builtin_setlanguage,
443 "Set the channel's preferred language",
444 " SetLanguage(language): This will set the channel language to the given value.\n"
445 "This information is used for the syntax in generation of numbers, and to choose\n"
446 "a sound file in the given language, when it is available.\n"
447 " For example, if language is set to 'fr' and the file 'demo-congrats' is \n"
448 "requested to be played, if the file 'fr/demo-congrats' exists, then\n"
449 "it will play that file. If not, it will play the normal 'demo-congrats'.\n"
450 "For some language codes, SetLanguage also changes the syntax of some\n"
451 "Asterisk functions, like SayNumber.\n"
452 " SetLanguage has been deprecated in favor of Set(LANGUAGE()=language)\n"
455 { "Set", pbx_builtin_setvar,
456 "Set channel variable(s) or function value(s)",
457 " Set(name1=value1|name2=value2|..[|options])\n"
458 "This function can be used to set the value of channel variables or dialplan\n"
459 "functions. It will accept up to 24 name/value pairs. When setting variables,\n"
460 "if the variable name is prefixed with _, the variable will be inherited into\n"
461 "channels created from the current channel. If the variable name is prefixed\n"
462 "with __, the variable will be inherited into channels created from the current\n"
463 "channel and all children channels.\n"
465 " g - Set variable globally instead of on the channel\n"
466 " (applies only to variables, not functions)\n"
469 { "SetVar", pbx_builtin_setvar_old,
470 "Set channel variable(s)",
471 " SetVar(name1=value1|name2=value2|..[|options]): This application has been\n"
472 "deprecated in favor of using the Set application.\n"
475 { "ImportVar", pbx_builtin_importvar,
476 "Import a variable from a channel into a new variable",
477 " ImportVar(newvar=channelname|variable): This application imports a variable\n"
478 "from the specified channel (as opposed to the current one) and stores it as\n"
479 "a variable in the current channel (the channel that is calling this\n"
480 "application). Variables created by this application have the same inheritance\n"
481 "properties as those created with the Set application. See the documentation for\n"
482 "Set for more information.\n"
485 { "Wait", pbx_builtin_wait,
486 "Waits for some time",
487 " Wait(seconds): This application waits for a specified number of seconds.\n"
488 "Then, dialplan execution will continue at the next priority.\n"
489 " Note that the seconds can be passed with fractions of a second. For example,\n"
490 "'1.5' will ask the application to wait for 1.5 seconds.\n"
493 { "WaitExten", pbx_builtin_waitexten,
494 "Waits for an extension to be entered",
495 " WaitExten([seconds][|options]): This application waits for the user to enter\n"
496 "a new extension for a specified number of seconds.\n"
497 " Note that the seconds can be passed with fractions of a second. For example,\n"
498 "'1.5' will ask the application to wait for 1.5 seconds.\n"
500 " m[(x)] - Provide music on hold to the caller while waiting for an extension.\n"
501 " Optionally, specify the class for music on hold within parenthesis.\n"
506 static struct ast_context *contexts = NULL;
507 AST_MUTEX_DEFINE_STATIC(conlock); /* Lock for the ast_context list */
508 static struct ast_app *apps = NULL;
509 AST_MUTEX_DEFINE_STATIC(applock); /* Lock for the application list */
511 struct ast_switch *switches = NULL;
512 AST_MUTEX_DEFINE_STATIC(switchlock); /* Lock for switches */
514 AST_MUTEX_DEFINE_STATIC(hintlock); /* Lock for extension state notifys */
515 static int stateid = 1;
516 struct ast_hint *hints = NULL;
517 struct ast_state_cb *statecbs = NULL;
520 \note This function is special. It saves the stack so that no matter
521 how many times it is called, it returns to the same place */
522 int pbx_exec(struct ast_channel *c, /*!< Channel */
523 struct ast_app *app, /*!< Application */
524 void *data, /*!< Data for execution */
525 int newstack) /*!< Force stack increment */
532 int (*execute)(struct ast_channel *chan, void *data) = app->execute;
536 ast_cdr_setapp(c->cdr, app->name, data);
538 /* save channel values */
539 saved_c_appl= c->appl;
540 saved_c_data= c->data;
544 res = execute(c, data);
545 /* restore channel values */
546 c->appl= saved_c_appl;
547 c->data= saved_c_data;
550 ast_log(LOG_WARNING, "You really didn't want to call this function with newstack set to 0\n");
555 /*! Go no deeper than this through includes (not counting loops) */
556 #define AST_PBX_MAX_STACK 128
558 #define HELPER_EXISTS 0
559 #define HELPER_SPAWN 1
560 #define HELPER_EXEC 2
561 #define HELPER_CANMATCH 3
562 #define HELPER_MATCHMORE 4
563 #define HELPER_FINDLABEL 5
565 /*! \brief Find application handle in linked list
567 struct ast_app *pbx_findapp(const char *app)
571 if (ast_mutex_lock(&applock)) {
572 ast_log(LOG_WARNING, "Unable to obtain application lock\n");
577 if (!strcasecmp(tmp->name, app))
581 ast_mutex_unlock(&applock);
585 static struct ast_switch *pbx_findswitch(const char *sw)
587 struct ast_switch *asw;
589 if (ast_mutex_lock(&switchlock)) {
590 ast_log(LOG_WARNING, "Unable to obtain application lock\n");
595 if (!strcasecmp(asw->name, sw))
599 ast_mutex_unlock(&switchlock);
603 static inline int include_valid(struct ast_include *i)
608 return ast_check_timing(&(i->timing));
611 static void pbx_destroy(struct ast_pbx *p)
616 #define EXTENSION_MATCH_CORE(data,pattern,match) {\
617 /* All patterns begin with _ */\
618 if (pattern[0] != '_') \
620 /* Start optimistic */\
623 while(match && *data && *pattern && (*pattern != '/')) {\
624 while (*data == '-' && (*(data+1) != '\0')) data++;\
625 switch(toupper(*pattern)) {\
632 where=strchr(pattern,']');\
634 border=(int)(where-pattern);\
635 if (!where || border > strlen(pattern)) {\
636 ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n");\
639 for (i=0; i<border; i++) {\
642 if (pattern[i+1]=='-') {\
643 if (*data >= pattern[i] && *data <= pattern[i+2]) {\
650 if (res==1 || *data==pattern[i]) {\
659 if ((*data < '2') || (*data > '9'))\
663 if ((*data < '0') || (*data > '9'))\
667 if ((*data < '1') || (*data > '9'))\
678 /* Ignore these characters */\
682 if (*data != *pattern)\
688 /* If we ran off the end of the data and the pattern ends in '!', match */\
689 if (match && !*data && (*pattern == '!'))\
693 int ast_extension_match(const char *pattern, const char *data)
696 /* If they're the same return */
697 if (!strcmp(pattern, data))
699 EXTENSION_MATCH_CORE(data,pattern,match);
700 /* Must be at the end of both */
701 if (*data || (*pattern && (*pattern != '/')))
706 int ast_extension_close(const char *pattern, const char *data, int needmore)
709 /* If "data" is longer, it can'be a subset of pattern unless
710 pattern is a pattern match */
711 if ((strlen(pattern) < strlen(data)) && (pattern[0] != '_'))
714 if ((ast_strlen_zero((char *)data) || !strncasecmp(pattern, data, strlen(data))) &&
715 (!needmore || (strlen(pattern) > strlen(data)))) {
718 EXTENSION_MATCH_CORE(data,pattern,match);
719 /* If there's more or we don't care about more, or if it's a possible early match,
720 return non-zero; otherwise it's a miss */
721 if (!needmore || *pattern || match == 2) {
727 struct ast_context *ast_context_find(const char *name)
729 struct ast_context *tmp;
730 ast_mutex_lock(&conlock);
734 if (!strcasecmp(name, tmp->name))
740 ast_mutex_unlock(&conlock);
744 #define STATUS_NO_CONTEXT 1
745 #define STATUS_NO_EXTENSION 2
746 #define STATUS_NO_PRIORITY 3
747 #define STATUS_NO_LABEL 4
748 #define STATUS_SUCCESS 5
750 static int matchcid(const char *cidpattern, const char *callerid)
754 /* If the Caller*ID pattern is empty, then we're matching NO Caller*ID, so
755 failing to get a number should count as a match, otherwise not */
757 if (!ast_strlen_zero(cidpattern))
765 return ast_extension_match(cidpattern, callerid);
768 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)
771 struct ast_context *tmp;
772 struct ast_exten *e, *eroot;
773 struct ast_include *i;
775 struct ast_switch *asw;
777 /* Initialize status if appropriate */
779 *status = STATUS_NO_CONTEXT;
783 /* Check for stack overflow */
784 if (*stacklen >= AST_PBX_MAX_STACK) {
785 ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n");
788 /* Check first to see if we've already been checked */
789 for (x=0; x<*stacklen; x++) {
790 if (!strcasecmp(incstack[x], context))
799 if (bypass || !strcmp(tmp->name, context)) {
800 struct ast_exten *earlymatch = NULL;
802 if (*status < STATUS_NO_EXTENSION)
803 *status = STATUS_NO_EXTENSION;
804 for (eroot = tmp->root; eroot; eroot=eroot->next) {
806 /* Match extension */
807 if ((((action != HELPER_MATCHMORE) && ast_extension_match(eroot->exten, exten)) ||
808 ((action == HELPER_CANMATCH) && (ast_extension_close(eroot->exten, exten, 0))) ||
809 ((action == HELPER_MATCHMORE) && (match = ast_extension_close(eroot->exten, exten, 1)))) &&
810 (!eroot->matchcid || matchcid(eroot->cidmatch, callerid))) {
812 if (action == HELPER_MATCHMORE && match == 2 && !earlymatch) {
813 /* It matched an extension ending in a '!' wildcard
814 So ignore it for now, unless there's a better match */
818 if (*status < STATUS_NO_PRIORITY)
819 *status = STATUS_NO_PRIORITY;
822 if (action == HELPER_FINDLABEL) {
823 if (*status < STATUS_NO_LABEL)
824 *status = STATUS_NO_LABEL;
825 if (label && e->label && !strcmp(label, e->label)) {
826 *status = STATUS_SUCCESS;
827 *foundcontext = context;
830 } else if (e->priority == priority) {
831 *status = STATUS_SUCCESS;
832 *foundcontext = context;
841 /* Bizarre logic for HELPER_MATCHMORE. We return zero to break out
842 of the loop waiting for more digits, and _then_ match (normally)
843 the extension we ended up with. We got an early-matching wildcard
844 pattern, so return NULL to break out of the loop. */
847 /* Check alternative switches */
850 if ((asw = pbx_findswitch(sw->name))) {
851 /* Substitute variables now */
853 pbx_substitute_variables_helper(chan, sw->data, sw->tmpdata, SWITCH_DATA_LENGTH - 1);
854 if (action == HELPER_CANMATCH)
855 res = asw->canmatch ? asw->canmatch(chan, context, exten, priority, callerid, sw->eval ? sw->tmpdata : sw->data) : 0;
856 else if (action == HELPER_MATCHMORE)
857 res = asw->matchmore ? asw->matchmore(chan, context, exten, priority, callerid, sw->eval ? sw->tmpdata : sw->data) : 0;
859 res = asw->exists ? asw->exists(chan, context, exten, priority, callerid, sw->eval ? sw->tmpdata : sw->data) : 0;
863 *data = sw->eval ? sw->tmpdata : sw->data;
864 *foundcontext = context;
868 ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name);
872 /* Setup the stack */
873 incstack[*stacklen] = tmp->name;
875 /* Now try any includes we have in this context */
878 if (include_valid(i)) {
879 if ((e = pbx_find_extension(chan, bypass, i->rname, exten, priority, label, callerid, action, incstack, stacklen, status, swo, data, foundcontext)))
893 /* Note that it's negative -- that's important later. */
894 #define DONT_HAVE_LENGTH 0x80000000
896 static int parse_variable_name(char *var, int *offset, int *length, int *isfunc)
898 char *varchar, *offsetchar = NULL;
902 *length = DONT_HAVE_LENGTH;
904 for (varchar=var; *varchar; varchar++) {
915 offsetchar = varchar + 1;
923 sscanf(offsetchar, "%d:%d", offset, length);
930 static char *substring(char *value, int offset, int length, char *workspace, size_t workspace_len)
932 char *ret = workspace;
934 /* No need to do anything */
935 if (offset == 0 && length==-1) {
939 ast_copy_string(workspace, value, workspace_len);
941 if (abs(offset) > strlen(ret)) { /* Offset beyond string */
943 offset = strlen(ret);
945 offset =- strlen(ret);
948 /* Detect too-long length */
949 if ((offset < 0 && length > -offset) || (offset >= 0 && offset+length > strlen(ret))) {
951 length = strlen(ret)-offset;
953 length = strlen(ret)+offset;
956 /* Bounce up to the right offset */
960 ret += strlen(ret)+offset;
962 /* Chop off at the requisite length */
969 /*! \brief pbx_retrieve_variable: Support for Asterisk built-in variables and
970 functions in the dialplan
972 void pbx_retrieve_variable(struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp)
976 struct tm brokentime;
977 int offset, offset2, isfunc;
978 struct ast_var_t *variables;
983 ast_copy_string(tmpvar, var, sizeof(tmpvar));
984 if (parse_variable_name(tmpvar, &offset, &offset2, &isfunc)) {
985 pbx_retrieve_variable(c, tmpvar, ret, workspace, workspacelen, headp);
988 *ret = substring(*ret, offset, offset2, workspace, workspacelen);
989 } else if (c && !strncmp(var, "CALL", 4)) {
990 if (!strncmp(var + 4, "ER", 2)) {
991 if (!strncmp(var + 6, "ID", 2)) {
992 if (!var[8]) { /* CALLERID */
993 if (c->cid.cid_num) {
994 if (c->cid.cid_name) {
995 snprintf(workspace, workspacelen, "\"%s\" <%s>", c->cid.cid_name, c->cid.cid_num);
997 ast_copy_string(workspace, c->cid.cid_num, workspacelen);
1000 } else if (c->cid.cid_name) {
1001 ast_copy_string(workspace, c->cid.cid_name, workspacelen);
1005 } else if (!strcmp(var + 8, "NUM")) {
1007 if (c->cid.cid_num) {
1008 ast_copy_string(workspace, c->cid.cid_num, workspacelen);
1012 } else if (!strcmp(var + 8, "NAME")) {
1014 if (c->cid.cid_name) {
1015 ast_copy_string(workspace, c->cid.cid_name, workspacelen);
1020 } else if (!strcmp(var + 6, "ANI")) {
1022 if (c->cid.cid_ani) {
1023 ast_copy_string(workspace, c->cid.cid_ani, workspacelen);
1029 } else if (!strncmp(var + 4, "ING", 3)) {
1030 if (!strcmp(var + 7, "PRES")) {
1032 snprintf(workspace, workspacelen, "%d", c->cid.cid_pres);
1034 } else if (!strcmp(var + 7, "ANI2")) {
1036 snprintf(workspace, workspacelen, "%d", c->cid.cid_ani2);
1038 } else if (!strcmp(var + 7, "TON")) {
1040 snprintf(workspace, workspacelen, "%d", c->cid.cid_ton);
1042 } else if (!strcmp(var + 7, "TNS")) {
1044 snprintf(workspace, workspacelen, "%d", c->cid.cid_tns);
1050 } else if (c && !strcmp(var, "DNID")) {
1051 if (c->cid.cid_dnid) {
1052 ast_copy_string(workspace, c->cid.cid_dnid, workspacelen);
1056 } else if (c && !strcmp(var, "HINT")) {
1057 if (!ast_get_hint(workspace, workspacelen, NULL, 0, c, c->context, c->exten))
1061 } else if (c && !strcmp(var, "HINTNAME")) {
1062 if (!ast_get_hint(NULL, 0, workspace, workspacelen, c, c->context, c->exten))
1066 } else if (c && !strcmp(var, "EXTEN")) {
1067 ast_copy_string(workspace, c->exten, workspacelen);
1069 } else if (c && !strcmp(var, "RDNIS")) {
1070 if (c->cid.cid_rdnis) {
1071 ast_copy_string(workspace, c->cid.cid_rdnis, workspacelen);
1075 } else if (c && !strcmp(var, "CONTEXT")) {
1076 ast_copy_string(workspace, c->context, workspacelen);
1078 } else if (c && !strcmp(var, "PRIORITY")) {
1079 snprintf(workspace, workspacelen, "%d", c->priority);
1081 } else if (c && !strcmp(var, "CHANNEL")) {
1082 ast_copy_string(workspace, c->name, workspacelen);
1084 } else if (!strcmp(var, "EPOCH")) {
1085 snprintf(workspace, workspacelen, "%u",(int)time(NULL));
1087 } else if (!strcmp(var, "DATETIME")) {
1088 thistime=time(NULL);
1089 localtime_r(&thistime, &brokentime);
1090 snprintf(workspace, workspacelen, "%02d%02d%04d-%02d:%02d:%02d",
1092 brokentime.tm_mon+1,
1093 brokentime.tm_year+1900,
1099 } else if (!strcmp(var, "TIMESTAMP")) {
1100 thistime=time(NULL);
1101 localtime_r(&thistime, &brokentime);
1102 /* 20031130-150612 */
1103 snprintf(workspace, workspacelen, "%04d%02d%02d-%02d%02d%02d",
1104 brokentime.tm_year+1900,
1105 brokentime.tm_mon+1,
1112 } else if (c && !strcmp(var, "UNIQUEID")) {
1113 snprintf(workspace, workspacelen, "%s", c->uniqueid);
1115 } else if (c && !strcmp(var, "HANGUPCAUSE")) {
1116 snprintf(workspace, workspacelen, "%d", c->hangupcause);
1118 } else if (c && !strcmp(var, "ACCOUNTCODE")) {
1119 ast_copy_string(workspace, c->accountcode, workspacelen);
1121 } else if (c && !strcmp(var, "LANGUAGE")) {
1122 ast_copy_string(workspace, c->language, workspacelen);
1127 AST_LIST_TRAVERSE(headp,variables,entries) {
1129 ast_log(LOG_WARNING,"Comparing variable '%s' with '%s'\n",var,ast_var_name(variables));
1131 if (strcasecmp(ast_var_name(variables),var)==0) {
1132 *ret=ast_var_value(variables);
1134 ast_copy_string(workspace, *ret, workspacelen);
1143 AST_LIST_TRAVERSE(&globals,variables,entries) {
1145 ast_log(LOG_WARNING,"Comparing variable '%s' with '%s'\n",var,ast_var_name(variables));
1147 if (strcasecmp(ast_var_name(variables),var)==0) {
1148 *ret = ast_var_value(variables);
1150 ast_copy_string(workspace, *ret, workspacelen);
1159 /*! \brief CLI function to show installed custom functions
1160 \addtogroup CLI_functions
1162 static int handle_show_functions(int fd, int argc, char *argv[])
1164 struct ast_custom_function *acf;
1167 ast_cli(fd, "Installed Custom Functions:\n--------------------------------------------------------------------------------\n");
1168 for (acf = acf_root ; acf; acf = acf->next) {
1169 ast_cli(fd, "%-20.20s %-35.35s %s\n", acf->name, acf->syntax, acf->synopsis);
1172 ast_cli(fd, "%d custom functions installed.\n", count_acf);
1176 static int handle_show_function(int fd, int argc, char *argv[])
1178 struct ast_custom_function *acf;
1179 /* Maximum number of characters added by terminal coloring is 22 */
1180 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40];
1181 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL;
1182 char stxtitle[40], *syntax = NULL;
1183 int synopsis_size, description_size, syntax_size;
1185 if (argc < 3) return RESULT_SHOWUSAGE;
1187 if (!(acf = ast_custom_function_find(argv[2]))) {
1188 ast_cli(fd, "No function by that name registered.\n");
1189 return RESULT_FAILURE;
1194 synopsis_size = strlen(acf->synopsis) + 23;
1196 synopsis_size = strlen("Not available") + 23;
1197 synopsis = alloca(synopsis_size);
1200 description_size = strlen(acf->desc) + 23;
1202 description_size = strlen("Not available") + 23;
1203 description = alloca(description_size);
1206 syntax_size = strlen(acf->syntax) + 23;
1208 syntax_size = strlen("Not available") + 23;
1209 syntax = alloca(syntax_size);
1211 snprintf(info, 64 + AST_MAX_APP, "\n -= Info about function '%s' =- \n\n", acf->name);
1212 term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22);
1213 term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40);
1214 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
1215 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
1217 acf->syntax ? acf->syntax : "Not available",
1218 COLOR_CYAN, 0, syntax_size);
1219 term_color(synopsis,
1220 acf->synopsis ? acf->synopsis : "Not available",
1221 COLOR_CYAN, 0, synopsis_size);
1222 term_color(description,
1223 acf->desc ? acf->desc : "Not available",
1224 COLOR_CYAN, 0, description_size);
1226 ast_cli(fd,"%s%s%s\n\n%s%s\n\n%s%s\n", infotitle, stxtitle, syntax, syntitle, synopsis, destitle, description);
1228 return RESULT_SUCCESS;
1231 static char *complete_show_function(char *line, char *word, int pos, int state)
1233 struct ast_custom_function *acf;
1236 /* try to lock functions list ... */
1237 if (ast_mutex_lock(&acflock)) {
1238 ast_log(LOG_ERROR, "Unable to lock function list\n");
1244 if (!strncasecmp(word, acf->name, strlen(word))) {
1245 if (++which > state) {
1246 char *ret = strdup(acf->name);
1247 ast_mutex_unlock(&acflock);
1254 ast_mutex_unlock(&acflock);
1258 struct ast_custom_function* ast_custom_function_find(char *name)
1260 struct ast_custom_function *acfptr;
1262 /* try to lock functions list ... */
1263 if (ast_mutex_lock(&acflock)) {
1264 ast_log(LOG_ERROR, "Unable to lock function list\n");
1268 for (acfptr = acf_root; acfptr; acfptr = acfptr->next) {
1269 if (!strcmp(name, acfptr->name)) {
1274 ast_mutex_unlock(&acflock);
1279 int ast_custom_function_unregister(struct ast_custom_function *acf)
1281 struct ast_custom_function *acfptr, *lastacf = NULL;
1287 /* try to lock functions list ... */
1288 if (ast_mutex_lock(&acflock)) {
1289 ast_log(LOG_ERROR, "Unable to lock function list\n");
1293 for (acfptr = acf_root; acfptr; acfptr = acfptr->next) {
1294 if (acfptr == acf) {
1296 lastacf->next = acf->next;
1298 acf_root = acf->next;
1306 ast_mutex_unlock(&acflock);
1308 if (!res && (option_verbose > 1))
1309 ast_verbose(VERBOSE_PREFIX_2 "Unregistered custom function %s\n", acf->name);
1314 int ast_custom_function_register(struct ast_custom_function *acf)
1319 /* try to lock functions list ... */
1320 if (ast_mutex_lock(&acflock)) {
1321 ast_log(LOG_ERROR, "Unable to lock function list. Failed registering function %s\n", acf->name);
1325 if (ast_custom_function_find(acf->name)) {
1326 ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name);
1327 ast_mutex_unlock(&acflock);
1331 acf->next = acf_root;
1334 ast_mutex_unlock(&acflock);
1336 if (option_verbose > 1)
1337 ast_verbose(VERBOSE_PREFIX_2 "Registered custom function %s\n", acf->name);
1342 char *ast_func_read(struct ast_channel *chan, const char *in, char *workspace, size_t len)
1344 char *args = NULL, *function, *p;
1346 struct ast_custom_function *acfptr;
1348 function = ast_strdupa(in);
1350 ast_log(LOG_ERROR, "Out of memory\n");
1353 if ((args = strchr(function, '('))) {
1356 if ((p = strrchr(args, ')'))) {
1359 ast_log(LOG_WARNING, "Can't find trailing parenthesis?\n");
1362 ast_log(LOG_WARNING, "Function doesn't contain parentheses. Assuming null argument.\n");
1365 if ((acfptr = ast_custom_function_find(function))) {
1366 /* run the custom function */
1368 return acfptr->read(chan, function, args, workspace, len);
1370 ast_log(LOG_ERROR, "Function %s cannot be read\n", function);
1373 ast_log(LOG_ERROR, "Function %s not registered\n", function);
1378 void ast_func_write(struct ast_channel *chan, const char *in, const char *value)
1380 char *args = NULL, *function, *p;
1381 struct ast_custom_function *acfptr;
1383 function = ast_strdupa(in);
1385 ast_log(LOG_ERROR, "Out of memory\n");
1388 if ((args = strchr(function, '('))) {
1391 if ((p = strrchr(args, ')'))) {
1394 ast_log(LOG_WARNING, "Can't find trailing parenthesis?\n");
1397 ast_log(LOG_WARNING, "Function doesn't contain parentheses. Assuming null argument.\n");
1400 if ((acfptr = ast_custom_function_find(function))) {
1401 /* run the custom function */
1402 if (acfptr->write) {
1403 acfptr->write(chan, function, args, value);
1405 ast_log(LOG_ERROR, "Function %s is read-only, it cannot be written to\n", function);
1408 ast_log(LOG_ERROR, "Function %s not registered\n", function);
1412 static void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count)
1415 const char *tmp, *whereweare;
1416 int length, offset, offset2, isfunction;
1417 char *workspace = NULL;
1418 char *ltmp = NULL, *var = NULL;
1419 char *nextvar, *nextexp, *nextthing;
1421 int pos, brackets, needsub, len;
1423 /* Substitutes variables into cp2, based on string cp1, and assuming cp2 to be
1426 while(!ast_strlen_zero(whereweare) && count) {
1427 /* Assume we're copying the whole remaining string */
1428 pos = strlen(whereweare);
1431 nextthing = strchr(whereweare, '$');
1433 switch(nextthing[1]) {
1435 nextvar = nextthing;
1436 pos = nextvar - whereweare;
1439 nextexp = nextthing;
1440 pos = nextexp - whereweare;
1446 /* Can't copy more than 'count' bytes */
1450 /* Copy that many bytes */
1451 memcpy(cp2, whereweare, pos);
1459 /* We have a variable. Find the start and end, and determine
1460 if we are going to have to recursively call ourselves on the
1462 vars = vare = nextvar + 2;
1466 /* Find the end of it */
1467 while(brackets && *vare) {
1468 if ((vare[0] == '$') && (vare[1] == '{')) {
1471 } else if (vare[0] == '}') {
1473 } else if ((vare[0] == '$') && (vare[1] == '['))
1478 ast_log(LOG_NOTICE, "Error in extension logic (missing '}')\n");
1479 len = vare - vars - 1;
1481 /* Skip totally over variable string */
1482 whereweare += (len + 3);
1485 var = alloca(VAR_BUF_SIZE);
1487 /* Store variable name (and truncate) */
1488 ast_copy_string(var, vars, len + 1);
1490 /* Substitute if necessary */
1493 ltmp = alloca(VAR_BUF_SIZE);
1495 memset(ltmp, 0, VAR_BUF_SIZE);
1496 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1);
1503 workspace = alloca(VAR_BUF_SIZE);
1505 workspace[0] = '\0';
1507 parse_variable_name(vars, &offset, &offset2, &isfunction);
1509 /* Evaluate function */
1510 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE);
1512 ast_log(LOG_DEBUG, "Function result is '%s'\n", cp4 ? cp4 : "(null)");
1514 /* Retrieve variable value */
1515 pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp);
1518 cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE);
1520 length = strlen(cp4);
1523 memcpy(cp2, cp4, length);
1527 } else if (nextexp) {
1528 /* We have an expression. Find the start and end, and determine
1529 if we are going to have to recursively call ourselves on the
1531 vars = vare = nextexp + 2;
1535 /* Find the end of it */
1536 while(brackets && *vare) {
1537 if ((vare[0] == '$') && (vare[1] == '[')) {
1541 } else if (vare[0] == '[') {
1543 } else if (vare[0] == ']') {
1545 } else if ((vare[0] == '$') && (vare[1] == '{')) {
1552 ast_log(LOG_NOTICE, "Error in extension logic (missing ']')\n");
1553 len = vare - vars - 1;
1555 /* Skip totally over expression */
1556 whereweare += (len + 3);
1559 var = alloca(VAR_BUF_SIZE);
1561 /* Store variable name (and truncate) */
1562 ast_copy_string(var, vars, len + 1);
1564 /* Substitute if necessary */
1567 ltmp = alloca(VAR_BUF_SIZE);
1569 memset(ltmp, 0, VAR_BUF_SIZE);
1570 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1);
1576 length = ast_expr(vars, cp2, count);
1579 ast_log(LOG_DEBUG, "Expression result is '%s'\n", cp2);
1588 void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count)
1590 pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count);
1593 void pbx_substitute_variables_varshead(struct varshead *headp, const char *cp1, char *cp2, int count)
1595 pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count);
1598 static void pbx_substitute_variables(char *passdata, int datalen, struct ast_channel *c, struct ast_exten *e)
1600 memset(passdata, 0, datalen);
1602 /* No variables or expressions in e->data, so why scan it? */
1603 if (!strchr(e->data, '$') && !strstr(e->data,"${") && !strstr(e->data,"$[") && !strstr(e->data,"$(")) {
1604 ast_copy_string(passdata, e->data, datalen);
1608 pbx_substitute_variables_helper(c, e->data, passdata, datalen - 1);
1611 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)
1613 struct ast_exten *e;
1614 struct ast_app *app;
1615 struct ast_switch *sw;
1617 const char *foundcontext=NULL;
1621 char *incstack[AST_PBX_MAX_STACK];
1622 char passdata[EXT_DATA_SIZE];
1626 char tmp3[EXT_DATA_SIZE];
1628 char atmp2[EXT_DATA_SIZE+100];
1630 if (ast_mutex_lock(&conlock)) {
1631 ast_log(LOG_WARNING, "Unable to obtain lock\n");
1632 if ((action == HELPER_EXISTS) || (action == HELPER_CANMATCH) || (action == HELPER_MATCHMORE))
1637 e = pbx_find_extension(c, con, context, exten, priority, label, callerid, action, incstack, &stacklen, &status, &sw, &data, &foundcontext);
1640 case HELPER_CANMATCH:
1641 ast_mutex_unlock(&conlock);
1644 ast_mutex_unlock(&conlock);
1646 case HELPER_FINDLABEL:
1648 ast_mutex_unlock(&conlock);
1650 case HELPER_MATCHMORE:
1651 ast_mutex_unlock(&conlock);
1657 app = pbx_findapp(e->app);
1658 ast_mutex_unlock(&conlock);
1660 if (c->context != context)
1661 ast_copy_string(c->context, context, sizeof(c->context));
1662 if (c->exten != exten)
1663 ast_copy_string(c->exten, exten, sizeof(c->exten));
1664 c->priority = priority;
1665 pbx_substitute_variables(passdata, sizeof(passdata), c, e);
1667 ast_log(LOG_DEBUG, "Launching '%s'\n", app->name);
1668 snprintf(atmp, 80, "STACK-%s-%s-%d", context, exten, priority);
1669 snprintf(atmp2, EXT_DATA_SIZE+100, "%s(\"%s\", \"%s\") %s", app->name, c->name, passdata, (newstack ? "in new stack" : "in same stack"));
1670 pbx_builtin_setvar_helper(c, atmp, atmp2);
1672 if (option_verbose > 2)
1673 ast_verbose( VERBOSE_PREFIX_3 "Executing %s(\"%s\", \"%s\") %s\n",
1674 term_color(tmp, app->name, COLOR_BRCYAN, 0, sizeof(tmp)),
1675 term_color(tmp2, c->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)),
1676 term_color(tmp3, passdata, COLOR_BRMAGENTA, 0, sizeof(tmp3)),
1677 (newstack ? "in new stack" : "in same stack"));
1678 manager_event(EVENT_FLAG_CALL, "Newexten",
1683 "Application: %s\r\n"
1686 c->name, c->context, c->exten, c->priority, app->name, passdata, c->uniqueid);
1687 res = pbx_exec(c, app, passdata, newstack);
1690 ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority);
1694 ast_log(LOG_WARNING, "Huh (%d)?\n", action); return -1;
1698 case HELPER_CANMATCH:
1699 ast_mutex_unlock(&conlock);
1702 ast_mutex_unlock(&conlock);
1704 case HELPER_MATCHMORE:
1705 ast_mutex_unlock(&conlock);
1707 case HELPER_FINDLABEL:
1708 ast_mutex_unlock(&conlock);
1714 ast_mutex_unlock(&conlock);
1716 res = sw->exec(c, foundcontext ? foundcontext : context, exten, priority, callerid, newstack, data);
1718 ast_log(LOG_WARNING, "No execution engine for switch %s\n", sw->name);
1723 ast_log(LOG_WARNING, "Huh (%d)?\n", action);
1727 ast_mutex_unlock(&conlock);
1729 case STATUS_NO_CONTEXT:
1730 if ((action != HELPER_EXISTS) && (action != HELPER_MATCHMORE))
1731 ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", context);
1733 case STATUS_NO_EXTENSION:
1734 if ((action != HELPER_EXISTS) && (action != HELPER_CANMATCH) && (action != HELPER_MATCHMORE))
1735 ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, context);
1737 case STATUS_NO_PRIORITY:
1738 if ((action != HELPER_EXISTS) && (action != HELPER_CANMATCH) && (action != HELPER_MATCHMORE))
1739 ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, context);
1741 case STATUS_NO_LABEL:
1743 ast_log(LOG_NOTICE, "No such label '%s' in extension '%s' in context '%s'\n", label, exten, context);
1746 ast_log(LOG_DEBUG, "Shouldn't happen!\n");
1749 if ((action != HELPER_EXISTS) && (action != HELPER_CANMATCH) && (action != HELPER_MATCHMORE))
1757 /*! \brief ast_hint_extension: Find hint for given extension in context */
1758 static struct ast_exten *ast_hint_extension(struct ast_channel *c, const char *context, const char *exten)
1760 struct ast_exten *e;
1761 struct ast_switch *sw;
1763 const char *foundcontext = NULL;
1765 char *incstack[AST_PBX_MAX_STACK];
1768 if (ast_mutex_lock(&conlock)) {
1769 ast_log(LOG_WARNING, "Unable to obtain lock\n");
1772 e = pbx_find_extension(c, NULL, context, exten, PRIORITY_HINT, NULL, "", HELPER_EXISTS, incstack, &stacklen, &status, &sw, &data, &foundcontext);
1773 ast_mutex_unlock(&conlock);
1777 /*! \brief ast_extensions_state2: Check state of extension by using hints */
1778 static int ast_extension_state2(struct ast_exten *e)
1780 char hint[AST_MAX_EXTENSION] = "";
1783 int allunavailable = 1, allbusy = 1, allfree = 1;
1784 int busy = 0, inuse = 0, ring = 0;
1789 ast_copy_string(hint, ast_get_extension_app(e), sizeof(hint));
1791 cur = hint; /* On or more devices separated with a & character */
1793 rest = strchr(cur, '&');
1799 res = ast_device_state(cur);
1801 case AST_DEVICE_NOT_INUSE:
1805 case AST_DEVICE_INUSE:
1810 case AST_DEVICE_RINGING:
1815 case AST_DEVICE_BUSY:
1820 case AST_DEVICE_UNAVAILABLE:
1821 case AST_DEVICE_INVALID:
1834 return AST_EXTENSION_RINGING;
1836 return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING);
1838 return AST_EXTENSION_INUSE;
1840 return AST_EXTENSION_NOT_INUSE;
1842 return AST_EXTENSION_BUSY;
1844 return AST_EXTENSION_UNAVAILABLE;
1846 return AST_EXTENSION_INUSE;
1848 return AST_EXTENSION_NOT_INUSE;
1851 /*! \brief ast_extension_state2str: Return extension_state as string */
1852 const char *ast_extension_state2str(int extension_state)
1856 for (i = 0; (i < (sizeof(extension_states) / sizeof(extension_states[0]))); i++) {
1857 if (extension_states[i].extension_state == extension_state) {
1858 return extension_states[i].text;
1864 /*! \brief ast_extension_state: Check extension state for an extension by using hint */
1865 int ast_extension_state(struct ast_channel *c, char *context, char *exten)
1867 struct ast_exten *e;
1869 e = ast_hint_extension(c, context, exten); /* Do we have a hint for this extension ? */
1871 return -1; /* No hint, return -1 */
1873 return ast_extension_state2(e); /* Check all devices in the hint */
1876 void ast_hint_state_changed(const char *device)
1878 struct ast_hint *hint;
1879 struct ast_state_cb *cblist;
1880 char buf[AST_MAX_EXTENSION];
1885 ast_mutex_lock(&hintlock);
1887 for (hint = hints; hint; hint = hint->next) {
1888 ast_copy_string(buf, ast_get_extension_app(hint->exten), sizeof(buf));
1890 for (cur = strsep(&parse, "&"); cur; cur = strsep(&parse, "&")) {
1891 if (strcmp(cur, device))
1894 /* Get device state for this hint */
1895 state = ast_extension_state2(hint->exten);
1897 if ((state == -1) || (state == hint->laststate))
1900 /* Device state changed since last check - notify the watchers */
1902 /* For general callbacks */
1903 for (cblist = statecbs; cblist; cblist = cblist->next)
1904 cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data);
1906 /* For extension callbacks */
1907 for (cblist = hint->callbacks; cblist; cblist = cblist->next)
1908 cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data);
1910 hint->laststate = state;
1915 ast_mutex_unlock(&hintlock);
1918 /*! \brief ast_extension_state_add: Add watcher for extension states */
1919 int ast_extension_state_add(const char *context, const char *exten,
1920 ast_state_cb_type callback, void *data)
1922 struct ast_hint *list;
1923 struct ast_state_cb *cblist;
1924 struct ast_exten *e;
1926 /* If there's no context and extension: add callback to statecbs list */
1927 if (!context && !exten) {
1928 ast_mutex_lock(&hintlock);
1932 if (cblist->callback == callback) {
1933 cblist->data = data;
1934 ast_mutex_unlock(&hintlock);
1937 cblist = cblist->next;
1940 /* Now insert the callback */
1941 cblist = malloc(sizeof(struct ast_state_cb));
1943 ast_mutex_unlock(&hintlock);
1946 memset(cblist, 0, sizeof(struct ast_state_cb));
1948 cblist->callback = callback;
1949 cblist->data = data;
1951 cblist->next = statecbs;
1954 ast_mutex_unlock(&hintlock);
1958 if (!context || !exten)
1961 /* This callback type is for only one hint, so get the hint */
1962 e = ast_hint_extension(NULL, context, exten);
1967 /* Find the hint in the list of hints */
1968 ast_mutex_lock(&hintlock);
1972 if (list->exten == e)
1978 /* We have no hint, sorry */
1979 ast_mutex_unlock(&hintlock);
1983 /* Now insert the callback in the callback list */
1984 cblist = malloc(sizeof(struct ast_state_cb));
1986 ast_mutex_unlock(&hintlock);
1989 memset(cblist, 0, sizeof(struct ast_state_cb));
1990 cblist->id = stateid++; /* Unique ID for this callback */
1991 cblist->callback = callback; /* Pointer to callback routine */
1992 cblist->data = data; /* Data for the callback */
1994 cblist->next = list->callbacks;
1995 list->callbacks = cblist;
1997 ast_mutex_unlock(&hintlock);
2001 /*! \brief ast_extension_state_del: Remove a watcher from the callback list */
2002 int ast_extension_state_del(int id, ast_state_cb_type callback)
2004 struct ast_hint *list;
2005 struct ast_state_cb *cblist, *cbprev;
2007 if (!id && !callback)
2010 ast_mutex_lock(&hintlock);
2012 /* id is zero is a callback without extension */
2017 if (cblist->callback == callback) {
2019 statecbs = cblist->next;
2021 cbprev->next = cblist->next;
2025 ast_mutex_unlock(&hintlock);
2029 cblist = cblist->next;
2032 ast_mutex_lock(&hintlock);
2036 /* id greater than zero is a callback with extension */
2037 /* Find the callback based on ID */
2040 cblist = list->callbacks;
2043 if (cblist->id==id) {
2045 list->callbacks = cblist->next;
2047 cbprev->next = cblist->next;
2051 ast_mutex_unlock(&hintlock);
2055 cblist = cblist->next;
2060 ast_mutex_unlock(&hintlock);
2064 /*! \brief ast_add_hint: Add hint to hint list, check initial extension state */
2065 static int ast_add_hint(struct ast_exten *e)
2067 struct ast_hint *list;
2072 ast_mutex_lock(&hintlock);
2075 /* Search if hint exists, do nothing */
2077 if (list->exten == e) {
2078 ast_mutex_unlock(&hintlock);
2079 if (option_debug > 1)
2080 ast_log(LOG_DEBUG, "HINTS: Not re-adding existing hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e));
2086 if (option_debug > 1)
2087 ast_log(LOG_DEBUG, "HINTS: Adding hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e));
2089 list = malloc(sizeof(struct ast_hint));
2091 ast_mutex_unlock(&hintlock);
2092 if (option_debug > 1)
2093 ast_log(LOG_DEBUG, "HINTS: Out of memory...\n");
2096 /* Initialize and insert new item at the top */
2097 memset(list, 0, sizeof(struct ast_hint));
2099 list->laststate = ast_extension_state2(e);
2103 ast_mutex_unlock(&hintlock);
2107 /*! \brief ast_change_hint: Change hint for an extension */
2108 static int ast_change_hint(struct ast_exten *oe, struct ast_exten *ne)
2110 struct ast_hint *list;
2112 ast_mutex_lock(&hintlock);
2116 if (list->exten == oe) {
2118 ast_mutex_unlock(&hintlock);
2123 ast_mutex_unlock(&hintlock);
2128 /*! \brief ast_remove_hint: Remove hint from extension */
2129 static int ast_remove_hint(struct ast_exten *e)
2131 /* Cleanup the Notifys if hint is removed */
2132 struct ast_hint *list, *prev = NULL;
2133 struct ast_state_cb *cblist, *cbprev;
2138 ast_mutex_lock(&hintlock);
2142 if (list->exten==e) {
2144 cblist = list->callbacks;
2146 /* Notify with -1 and remove all callbacks */
2148 cblist = cblist->next;
2149 cbprev->callback(list->exten->parent->name, list->exten->exten, AST_EXTENSION_DEACTIVATED, cbprev->data);
2152 list->callbacks = NULL;
2157 prev->next = list->next;
2160 ast_mutex_unlock(&hintlock);
2168 ast_mutex_unlock(&hintlock);
2173 /*! \brief ast_get_hint: Get hint for channel */
2174 int ast_get_hint(char *hint, int hintsize, char *name, int namesize, struct ast_channel *c, const char *context, const char *exten)
2176 struct ast_exten *e;
2179 e = ast_hint_extension(c, context, exten);
2182 ast_copy_string(hint, ast_get_extension_app(e), hintsize);
2184 tmp = ast_get_extension_app_data(e);
2186 ast_copy_string(name, (char *) tmp, namesize);
2193 int ast_exists_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_EXISTS);
2198 int ast_findlabel_extension(struct ast_channel *c, const char *context, const char *exten, const char *label, const char *callerid)
2200 return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, HELPER_FINDLABEL);
2203 int ast_findlabel_extension2(struct ast_channel *c, struct ast_context *con, const char *exten, const char *label, const char *callerid)
2205 return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, HELPER_FINDLABEL);
2208 int ast_canmatch_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_CANMATCH);
2213 int ast_matchmore_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
2215 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, HELPER_MATCHMORE);
2218 int ast_spawn_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
2220 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, HELPER_SPAWN);
2223 int ast_exec_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_EXEC);
2228 static int __ast_pbx_run(struct ast_channel *c)
2238 /* A little initial setup here */
2240 ast_log(LOG_WARNING, "%s already has PBX structure??\n", c->name);
2241 c->pbx = malloc(sizeof(struct ast_pbx));
2243 ast_log(LOG_ERROR, "Out of memory\n");
2248 c->cdr = ast_cdr_alloc();
2250 ast_log(LOG_WARNING, "Unable to create Call Detail Record\n");
2254 ast_cdr_init(c->cdr, c);
2257 memset(c->pbx, 0, sizeof(struct ast_pbx));
2258 /* Set reasonable defaults */
2259 c->pbx->rtimeout = 10;
2260 c->pbx->dtimeout = 5;
2262 autoloopflag = ast_test_flag(c, AST_FLAG_IN_AUTOLOOP);
2263 ast_set_flag(c, AST_FLAG_IN_AUTOLOOP);
2265 /* Start by trying whatever the channel is set to */
2266 if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) {
2267 /* If not successful fall back to 's' */
2268 if (option_verbose > 1)
2269 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);
2270 ast_copy_string(c->exten, "s", sizeof(c->exten));
2271 if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) {
2272 /* JK02: And finally back to default if everything else failed */
2273 if (option_verbose > 1)
2274 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);
2275 ast_copy_string(c->context, "default", sizeof(c->context));
2279 if (c->cdr && !c->cdr->start.tv_sec && !c->cdr->start.tv_usec)
2280 ast_cdr_start(c->cdr);
2284 while(ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) {
2285 memset(exten, 0, sizeof(exten));
2286 if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num))) {
2287 /* Something bad happened, or a hangup has been requested. */
2288 if (((res >= '0') && (res <= '9')) || ((res >= 'A') && (res <= 'F')) ||
2289 (res == '*') || (res == '#')) {
2290 ast_log(LOG_DEBUG, "Oooh, got something to jump out with ('%c')!\n", res);
2291 memset(exten, 0, sizeof(exten));
2293 exten[pos++] = digit = res;
2297 case AST_PBX_KEEPALIVE:
2299 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
2300 else if (option_verbose > 1)
2301 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
2306 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
2307 else if (option_verbose > 1)
2308 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
2309 if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
2314 if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) {
2324 if ((c->_softhangup == AST_SOFTHANGUP_TIMEOUT) && (ast_exists_extension(c,c->context,"T",1,c->cid.cid_num))) {
2325 ast_copy_string(c->exten, "T", sizeof(c->exten));
2326 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
2327 c->whentohangup = 0;
2329 c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT;
2330 } else if (c->_softhangup) {
2331 ast_log(LOG_DEBUG, "Extension %s, priority %d returned normally even though call was hung up\n",
2332 c->exten, c->priority);
2338 if (!ast_exists_extension(c, c->context, c->exten, 1, c->cid.cid_num)) {
2339 /* It's not a valid extension anymore */
2340 if (ast_exists_extension(c, c->context, "i", 1, c->cid.cid_num)) {
2341 if (option_verbose > 2)
2342 ast_verbose(VERBOSE_PREFIX_3 "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, c->name);
2343 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", c->exten);
2344 ast_copy_string(c->exten, "i", sizeof(c->exten));
2347 ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n",
2348 c->name, c->exten, c->context);
2351 } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) {
2352 /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */
2355 /* Done, wait for an extension */
2358 waittime = c->pbx->dtimeout;
2359 else if (!autofallthrough)
2360 waittime = c->pbx->rtimeout;
2362 while (ast_matchmore_extension(c, c->context, exten, 1, c->cid.cid_num)) {
2363 /* As long as we're willing to wait, and as long as it's not defined,
2364 keep reading digits until we can't possibly get a right answer anymore. */
2365 digit = ast_waitfordigit(c, waittime * 1000);
2366 if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
2373 /* Error, maybe a hangup */
2375 exten[pos++] = digit;
2376 waittime = c->pbx->dtimeout;
2379 if (ast_exists_extension(c, c->context, exten, 1, c->cid.cid_num)) {
2380 /* Prepare the next cycle */
2381 ast_copy_string(c->exten, exten, sizeof(c->exten));
2384 /* No such extension */
2385 if (!ast_strlen_zero(exten)) {
2386 /* An invalid extension */
2387 if (ast_exists_extension(c, c->context, "i", 1, c->cid.cid_num)) {
2388 if (option_verbose > 2)
2389 ast_verbose( VERBOSE_PREFIX_3 "Invalid extension '%s' in context '%s' on %s\n", exten, c->context, c->name);
2390 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", exten);
2391 ast_copy_string(c->exten, "i", sizeof(c->exten));
2394 ast_log(LOG_WARNING, "Invalid extension '%s', but no rule 'i' in context '%s'\n", exten, c->context);
2398 /* A simple timeout */
2399 if (ast_exists_extension(c, c->context, "t", 1, c->cid.cid_num)) {
2400 if (option_verbose > 2)
2401 ast_verbose( VERBOSE_PREFIX_3 "Timeout on %s\n", c->name);
2402 ast_copy_string(c->exten, "t", sizeof(c->exten));
2405 ast_log(LOG_WARNING, "Timeout, but no rule 't' in context '%s'\n", c->context);
2411 if (option_verbose > 2)
2412 ast_verbose(VERBOSE_PREFIX_2 "CDR updated on %s\n",c->name);
2418 status = pbx_builtin_getvar_helper(c, "DIALSTATUS");
2421 if (option_verbose > 2)
2422 ast_verbose(VERBOSE_PREFIX_2 "Auto fallthrough, channel '%s' status is '%s'\n", c->name, status);
2423 if (!strcasecmp(status, "CONGESTION"))
2424 res = pbx_builtin_congestion(c, "10");
2425 else if (!strcasecmp(status, "CHANUNAVAIL"))
2426 res = pbx_builtin_congestion(c, "10");
2427 else if (!strcasecmp(status, "BUSY"))
2428 res = pbx_builtin_busy(c, "10");
2434 ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name);
2436 if ((res != AST_PBX_KEEPALIVE) && ast_exists_extension(c, c->context, "h", 1, c->cid.cid_num)) {
2440 while(ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) {
2441 if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num))) {
2442 /* Something bad happened, or a hangup has been requested. */
2444 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
2445 else if (option_verbose > 1)
2446 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
2452 ast_set2_flag(c, autoloopflag, AST_FLAG_IN_AUTOLOOP);
2454 pbx_destroy(c->pbx);
2456 if (res != AST_PBX_KEEPALIVE)
2461 /* Returns 0 on success, non-zero if call limit was reached */
2462 static int increase_call_count(const struct ast_channel *c)
2466 ast_mutex_lock(&maxcalllock);
2467 if (option_maxcalls) {
2468 if (countcalls >= option_maxcalls) {
2469 ast_log(LOG_NOTICE, "Maximum call limit of %d calls exceeded by '%s'!\n", option_maxcalls, c->name);
2473 if (option_maxload) {
2474 getloadavg(&curloadavg, 1);
2475 if (curloadavg >= option_maxload) {
2476 ast_log(LOG_NOTICE, "Maximum loadavg limit of %f load exceeded by '%s' (currently %f)!\n", option_maxload, c->name, curloadavg);
2482 ast_mutex_unlock(&maxcalllock);
2487 static void decrease_call_count(void)
2489 ast_mutex_lock(&maxcalllock);
2492 ast_mutex_unlock(&maxcalllock);
2495 static void *pbx_thread(void *data)
2497 /* Oh joyeous kernel, we're a new thread, with nothing to do but
2498 answer this channel and get it going.
2501 The launcher of this function _MUST_ increment 'countcalls'
2502 before invoking the function; it will be decremented when the
2503 PBX has finished running on the channel
2505 struct ast_channel *c = data;
2508 decrease_call_count();
2515 enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
2518 pthread_attr_t attr;
2521 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
2522 return AST_PBX_FAILED;
2525 if (increase_call_count(c))
2526 return AST_PBX_CALL_LIMIT;
2528 /* Start a new thread, and get something handling this channel. */
2529 pthread_attr_init(&attr);
2530 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
2531 if (ast_pthread_create(&t, &attr, pbx_thread, c)) {
2532 ast_log(LOG_WARNING, "Failed to create new channel thread\n");
2533 return AST_PBX_FAILED;
2536 return AST_PBX_SUCCESS;
2539 enum ast_pbx_result ast_pbx_run(struct ast_channel *c)
2541 enum ast_pbx_result res = AST_PBX_SUCCESS;
2543 if (increase_call_count(c))
2544 return AST_PBX_CALL_LIMIT;
2546 res = __ast_pbx_run(c);
2547 decrease_call_count();
2552 int ast_active_calls(void)
2557 int pbx_set_autofallthrough(int newval)
2560 oldval = autofallthrough;
2561 if (oldval != newval)
2562 autofallthrough = newval;
2567 * This function locks contexts list by &conlist, search for the right context
2568 * structure, leave context list locked and call ast_context_remove_include2
2569 * which removes include, unlock contexts list and return ...
2571 int ast_context_remove_include(const char *context, const char *include, const char *registrar)
2573 struct ast_context *c;
2575 if (ast_lock_contexts()) return -1;
2577 /* walk contexts and search for the right one ...*/
2578 c = ast_walk_contexts(NULL);
2580 /* we found one ... */
2581 if (!strcmp(ast_get_context_name(c), context)) {
2583 /* remove include from this context ... */
2584 ret = ast_context_remove_include2(c, include, registrar);
2586 ast_unlock_contexts();
2588 /* ... return results */
2591 c = ast_walk_contexts(c);
2594 /* we can't find the right one context */
2595 ast_unlock_contexts();
2600 * When we call this function, &conlock lock must be locked, because when
2601 * we giving *con argument, some process can remove/change this context
2602 * and after that there can be segfault.
2604 * This function locks given context, removes include, unlock context and
2607 int ast_context_remove_include2(struct ast_context *con, const char *include, const char *registrar)
2609 struct ast_include *i, *pi = NULL;
2611 if (ast_mutex_lock(&con->lock)) return -1;
2616 /* find our include */
2617 if (!strcmp(i->name, include) &&
2618 (!registrar || !strcmp(i->registrar, registrar))) {
2619 /* remove from list */
2623 con->includes = i->next;
2624 /* free include and return */
2626 ast_mutex_unlock(&con->lock);
2633 /* we can't find the right include */
2634 ast_mutex_unlock(&con->lock);
2639 * \note This function locks contexts list by &conlist, search for the rigt context
2640 * structure, leave context list locked and call ast_context_remove_switch2
2641 * which removes switch, unlock contexts list and return ...
2643 int ast_context_remove_switch(const char *context, const char *sw, const char *data, const char *registrar)
2645 struct ast_context *c;
2647 if (ast_lock_contexts()) return -1;
2649 /* walk contexts and search for the right one ...*/
2650 c = ast_walk_contexts(NULL);
2652 /* we found one ... */
2653 if (!strcmp(ast_get_context_name(c), context)) {
2655 /* remove switch from this context ... */
2656 ret = ast_context_remove_switch2(c, sw, data, registrar);
2658 ast_unlock_contexts();
2660 /* ... return results */
2663 c = ast_walk_contexts(c);
2666 /* we can't find the right one context */
2667 ast_unlock_contexts();
2672 * \brief This function locks given context, removes switch, unlock context and
2674 * \note When we call this function, &conlock lock must be locked, because when
2675 * we giving *con argument, some process can remove/change this context
2676 * and after that there can be segfault.
2679 int ast_context_remove_switch2(struct ast_context *con, const char *sw, const char *data, const char *registrar)
2681 struct ast_sw *i, *pi = NULL;
2683 if (ast_mutex_lock(&con->lock)) return -1;
2688 /* find our switch */
2689 if (!strcmp(i->name, sw) && !strcmp(i->data, data) &&
2690 (!registrar || !strcmp(i->registrar, registrar))) {
2691 /* remove from list */
2695 con->alts = i->next;
2696 /* free switch and return */
2698 ast_mutex_unlock(&con->lock);
2705 /* we can't find the right switch */
2706 ast_mutex_unlock(&con->lock);
2711 * \note This functions lock contexts list, search for the right context,
2712 * call ast_context_remove_extension2, unlock contexts list and return.
2713 * In this function we are using
2715 int ast_context_remove_extension(const char *context, const char *extension, int priority, const char *registrar)
2717 struct ast_context *c;
2719 if (ast_lock_contexts()) return -1;
2721 /* walk contexts ... */
2722 c = ast_walk_contexts(NULL);
2724 /* ... search for the right one ... */
2725 if (!strcmp(ast_get_context_name(c), context)) {
2726 /* ... remove extension ... */
2727 int ret = ast_context_remove_extension2(c, extension, priority,
2729 /* ... unlock contexts list and return */
2730 ast_unlock_contexts();
2733 c = ast_walk_contexts(c);
2736 /* we can't find the right context */
2737 ast_unlock_contexts();
2742 * \brief This functionc locks given context, search for the right extension and
2743 * fires out all peer in this extensions with given priority. If priority
2744 * is set to 0, all peers are removed. After that, unlock context and
2746 * \note When do you want to call this function, make sure that &conlock is locked,
2747 * because some process can handle with your *con context before you lock
2751 int ast_context_remove_extension2(struct ast_context *con, const char *extension, int priority, const char *registrar)
2753 struct ast_exten *exten, *prev_exten = NULL;
2755 if (ast_mutex_lock(&con->lock)) return -1;
2757 /* go through all extensions in context and search the right one ... */
2761 /* look for right extension */
2762 if (!strcmp(exten->exten, extension) &&
2763 (!registrar || !strcmp(exten->registrar, registrar))) {
2764 struct ast_exten *peer;
2766 /* should we free all peers in this extension? (priority == 0)? */
2767 if (priority == 0) {
2768 /* remove this extension from context list */
2770 prev_exten->next = exten->next;
2772 con->root = exten->next;
2774 /* fire out all peers */
2779 if (!peer->priority==PRIORITY_HINT)
2780 ast_remove_hint(peer);
2782 peer->datad(peer->data);
2788 ast_mutex_unlock(&con->lock);
2791 /* remove only extension with exten->priority == priority */
2792 struct ast_exten *previous_peer = NULL;
2796 /* is this our extension? */
2797 if (peer->priority == priority &&
2798 (!registrar || !strcmp(peer->registrar, registrar) )) {
2799 /* we are first priority extension? */
2800 if (!previous_peer) {
2801 /* exists previous extension here? */
2803 /* yes, so we must change next pointer in
2804 * previous connection to next peer
2807 prev_exten->next = peer->peer;
2808 peer->peer->next = exten->next;
2810 prev_exten->next = exten->next;
2812 /* no previous extension, we are first
2813 * extension, so change con->root ...
2816 con->root = peer->peer;
2818 con->root = exten->next;
2821 /* we are not first priority in extension */
2822 previous_peer->peer = peer->peer;
2825 /* now, free whole priority extension */
2826 if (peer->priority==PRIORITY_HINT)
2827 ast_remove_hint(peer);
2828 peer->datad(peer->data);
2831 ast_mutex_unlock(&con->lock);
2834 /* this is not right extension, skip to next peer */
2835 previous_peer = peer;
2840 ast_mutex_unlock(&con->lock);
2846 exten = exten->next;
2849 /* we can't find right extension */
2850 ast_mutex_unlock(&con->lock);
2855 /*! \brief Dynamically register a new dial plan application */
2856 int ast_register_application(const char *app, int (*execute)(struct ast_channel *, void *), const char *synopsis, const char *description)
2858 struct ast_app *tmp, *prev, *cur;
2861 length = sizeof(struct ast_app);
2862 length += strlen(app) + 1;
2863 if (ast_mutex_lock(&applock)) {
2864 ast_log(LOG_ERROR, "Unable to lock application list\n");
2869 if (!strcasecmp(app, tmp->name)) {
2870 ast_log(LOG_WARNING, "Already have an application '%s'\n", app);
2871 ast_mutex_unlock(&applock);
2876 tmp = malloc(length);
2878 memset(tmp, 0, length);
2879 strcpy(tmp->name, app);
2880 tmp->execute = execute;
2881 tmp->synopsis = synopsis;
2882 tmp->description = description;
2883 /* Store in alphabetical order */
2887 if (strcasecmp(tmp->name, cur->name) < 0)
2893 tmp->next = prev->next;
2900 ast_log(LOG_ERROR, "Out of memory\n");
2901 ast_mutex_unlock(&applock);
2904 if (option_verbose > 1)
2905 ast_verbose( VERBOSE_PREFIX_2 "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps)));
2906 ast_mutex_unlock(&applock);
2910 int ast_register_switch(struct ast_switch *sw)
2912 struct ast_switch *tmp, *prev=NULL;
2913 if (ast_mutex_lock(&switchlock)) {
2914 ast_log(LOG_ERROR, "Unable to lock switch lock\n");
2919 if (!strcasecmp(tmp->name, sw->name))
2925 ast_mutex_unlock(&switchlock);
2926 ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name);
2934 ast_mutex_unlock(&switchlock);
2938 void ast_unregister_switch(struct ast_switch *sw)
2940 struct ast_switch *tmp, *prev=NULL;
2941 if (ast_mutex_lock(&switchlock)) {
2942 ast_log(LOG_ERROR, "Unable to lock switch lock\n");
2949 prev->next = tmp->next;
2951 switches = tmp->next;
2958 ast_mutex_unlock(&switchlock);
2962 * Help for CLI commands ...
2964 static char show_application_help[] =
2965 "Usage: show application <application> [<application> [<application> [...]]]\n"
2966 " Describes a particular application.\n";
2968 static char show_functions_help[] =
2969 "Usage: show functions\n"
2970 " List builtin functions accessable as $(function args)\n";
2972 static char show_function_help[] =
2973 "Usage: show function <function>\n"
2974 " Describe a particular dialplan function.\n";
2976 static char show_applications_help[] =
2977 "Usage: show applications [{like|describing} <text>]\n"
2978 " List applications which are currently available.\n"
2979 " If 'like', <text> will be a substring of the app name\n"
2980 " If 'describing', <text> will be a substring of the description\n";
2982 static char show_dialplan_help[] =
2983 "Usage: show dialplan [exten@][context]\n"
2986 static char show_switches_help[] =
2987 "Usage: show switches\n"
2988 " Show registered switches\n";
2990 static char show_hints_help[] =
2991 "Usage: show hints\n"
2992 " Show registered hints\n";
2996 * IMPLEMENTATION OF CLI FUNCTIONS IS IN THE SAME ORDER AS COMMANDS HELPS
3001 * \brief 'show application' CLI command implementation functions ...
3005 * There is a possibility to show informations about more than one
3006 * application at one time. You can type 'show application Dial Echo' and
3007 * you will see informations about these two applications ...
3009 static char *complete_show_application(char *line, char *word,
3015 /* try to lock applications list ... */
3016 if (ast_mutex_lock(&applock)) {
3017 ast_log(LOG_ERROR, "Unable to lock application list\n");
3021 /* ... walk all applications ... */
3024 /* ... check if word matches this application ... */
3025 if (!strncasecmp(word, a->name, strlen(word))) {
3026 /* ... if this is right app serve it ... */
3027 if (++which > state) {
3028 char *ret = strdup(a->name);
3029 ast_mutex_unlock(&applock);
3036 /* no application match */
3037 ast_mutex_unlock(&applock);
3041 static int handle_show_application(int fd, int argc, char *argv[])
3044 int app, no_registered_app = 1;
3046 if (argc < 3) return RESULT_SHOWUSAGE;
3048 /* try to lock applications list ... */
3049 if (ast_mutex_lock(&applock)) {
3050 ast_log(LOG_ERROR, "Unable to lock application list\n");
3054 /* ... go through all applications ... */
3057 /* ... compare this application name with all arguments given
3058 * to 'show application' command ... */
3059 for (app = 2; app < argc; app++) {
3060 if (!strcasecmp(a->name, argv[app])) {
3061 /* Maximum number of characters added by terminal coloring is 22 */
3062 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40];
3063 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL;
3064 int synopsis_size, description_size;
3066 no_registered_app = 0;
3069 synopsis_size = strlen(a->synopsis) + 23;
3071 synopsis_size = strlen("Not available") + 23;
3072 synopsis = alloca(synopsis_size);
3075 description_size = strlen(a->description) + 23;
3077 description_size = strlen("Not available") + 23;
3078 description = alloca(description_size);
3080 if (synopsis && description) {
3081 snprintf(info, 64 + AST_MAX_APP, "\n -= Info about application '%s' =- \n\n", a->name);
3082 term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22);
3083 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
3084 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
3085 term_color(synopsis,
3086 a->synopsis ? a->synopsis : "Not available",
3087 COLOR_CYAN, 0, synopsis_size);
3088 term_color(description,
3089 a->description ? a->description : "Not available",
3090 COLOR_CYAN, 0, description_size);
3092 ast_cli(fd,"%s%s%s\n\n%s%s\n", infotitle, syntitle, synopsis, destitle, description);
3094 /* ... one of our applications, show info ...*/
3095 ast_cli(fd,"\n -= Info about application '%s' =- \n\n"
3096 "[Synopsis]\n %s\n\n"
3097 "[Description]\n%s\n",
3099 a->synopsis ? a->synopsis : "Not available",
3100 a->description ? a->description : "Not available");
3107 ast_mutex_unlock(&applock);
3109 /* we found at least one app? no? */
3110 if (no_registered_app) {
3111 ast_cli(fd, "Your application(s) is (are) not registered\n");
3112 return RESULT_FAILURE;
3115 return RESULT_SUCCESS;
3118 /*! \brief handle_show_hints: CLI support for listing registred dial plan hints */
3119 static int handle_show_hints(int fd, int argc, char *argv[])
3121 struct ast_hint *hint;
3124 struct ast_state_cb *watcher;
3127 ast_cli(fd, "There are no registered dialplan hints\n");
3128 return RESULT_SUCCESS;
3130 /* ... we have hints ... */
3131 ast_cli(fd, "\n -= Registered Asterisk Dial Plan Hints =-\n");
3132 if (ast_mutex_lock(&hintlock)) {
3133 ast_log(LOG_ERROR, "Unable to lock hints\n");
3139 for (watcher = hint->callbacks; watcher; watcher = watcher->next)
3141 ast_cli(fd, " %-20.20s: %-20.20s State:%-15.15s Watchers %2d\n",
3142 ast_get_extension_name(hint->exten), ast_get_extension_app(hint->exten),
3143 ast_extension_state2str(hint->laststate), watchers);
3147 ast_cli(fd, "----------------\n");
3148 ast_cli(fd, "- %d hints registered\n", num);
3149 ast_mutex_unlock(&hintlock);
3150 return RESULT_SUCCESS;
3153 /*! \brief handle_show_switches: CLI support for listing registred dial plan switches */
3154 static int handle_show_switches(int fd, int argc, char *argv[])
3156 struct ast_switch *sw;
3158 ast_cli(fd, "There are no registered alternative switches\n");
3159 return RESULT_SUCCESS;
3161 /* ... we have applications ... */
3162 ast_cli(fd, "\n -= Registered Asterisk Alternative Switches =-\n");
3163 if (ast_mutex_lock(&switchlock)) {
3164 ast_log(LOG_ERROR, "Unable to lock switches\n");
3169 ast_cli(fd, "%s: %s\n", sw->name, sw->description);
3172 ast_mutex_unlock(&switchlock);
3173 return RESULT_SUCCESS;
3177 * 'show applications' CLI command implementation functions ...
3179 static int handle_show_applications(int fd, int argc, char *argv[])
3182 int like=0, describing=0;
3183 int total_match = 0; /* Number of matches in like clause */
3184 int total_apps = 0; /* Number of apps registered */
3186 /* try to lock applications list ... */
3187 if (ast_mutex_lock(&applock)) {
3188 ast_log(LOG_ERROR, "Unable to lock application list\n");
3192 /* ... have we got at least one application (first)? no? */
3194 ast_cli(fd, "There are no registered applications\n");
3195 ast_mutex_unlock(&applock);
3199 /* show applications like <keyword> */
3200 if ((argc == 4) && (!strcmp(argv[2], "like"))) {
3202 } else if ((argc > 3) && (!strcmp(argv[2], "describing"))) {
3206 /* show applications describing <keyword1> [<keyword2>] [...] */
3207 if ((!like) && (!describing)) {
3208 ast_cli(fd, " -= Registered Asterisk Applications =-\n");
3210 ast_cli(fd, " -= Matching Asterisk Applications =-\n");
3213 /* ... go through all applications ... */
3214 for (a = apps; a; a = a->next) {
3215 /* ... show informations about applications ... */
3219 if (strcasestr(a->name, argv[3])) {
3223 } else if (describing) {
3224 if (a->description) {
3225 /* Match all words on command line */
3228 for (i=3; i<argc; i++) {
3229 if (!strcasestr(a->description, argv[i])) {
3241 ast_cli(fd," %20s: %s\n", a->name, a->synopsis ? a->synopsis : "<Synopsis not available>");
3244 if ((!like) && (!describing)) {
3245 ast_cli(fd, " -= %d Applications Registered =-\n",total_apps);
3247 ast_cli(fd, " -= %d Applications Matching =-\n",total_match);
3250 /* ... unlock and return */
3251 ast_mutex_unlock(&applock);
3253 return RESULT_SUCCESS;
3256 static char *complete_show_applications(char *line, char *word, int pos, int state)
3259 if (ast_strlen_zero(word)) {
3262 return strdup("like");
3264 return strdup("describing");
3268 } else if (! strncasecmp(word, "like", strlen(word))) {
3270 return strdup("like");
3274 } else if (! strncasecmp(word, "describing", strlen(word))) {
3276 return strdup("describing");
3286 * 'show dialplan' CLI command implementation functions ...
3288 static char *complete_show_dialplan_context(char *line, char *word, int pos,
3291 struct ast_context *c;
3294 /* we are do completion of [exten@]context on second position only */
3295 if (pos != 2) return NULL;
3297 /* try to lock contexts list ... */
3298 if (ast_lock_contexts()) {
3299 ast_log(LOG_ERROR, "Unable to lock context list\n");
3303 /* ... walk through all contexts ... */
3304 c = ast_walk_contexts(NULL);
3306 /* ... word matches context name? yes? ... */
3307 if (!strncasecmp(word, ast_get_context_name(c), strlen(word))) {
3308 /* ... for serve? ... */
3309 if (++which > state) {
3310 /* ... yes, serve this context name ... */
3311 char *ret = strdup(ast_get_context_name(c));
3312 ast_unlock_contexts();
3316 c = ast_walk_contexts(c);
3319 /* ... unlock and return */
3320 ast_unlock_contexts();
3324 struct dialplan_counters {
3328 int context_existence;
3329 int extension_existence;
3332 static int show_dialplan_helper(int fd, char *context, char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude, int includecount, char *includes[])
3334 struct ast_context *c;
3335 int res=0, old_total_exten = dpc->total_exten;
3337 /* try to lock contexts */
3338 if (ast_lock_contexts()) {
3339 ast_log(LOG_WARNING, "Failed to lock contexts list\n");
3343 /* walk all contexts ... */
3344 for (c = ast_walk_contexts(NULL); c ; c = ast_walk_contexts(c)) {
3345 /* show this context? */
3347 !strcmp(ast_get_context_name(c), context)) {
3348 dpc->context_existence = 1;
3350 /* try to lock context before walking in ... */
3351 if (!ast_lock_context(c)) {
3352 struct ast_exten *e;
3353 struct ast_include *i;
3354 struct ast_ignorepat *ip;
3356 char buf[256], buf2[256];
3357 int context_info_printed = 0;
3359 /* are we looking for exten too? if yes, we print context
3360 * if we our extension only
3363 dpc->total_context++;
3364 ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
3365 ast_get_context_name(c), ast_get_context_registrar(c));
3366 context_info_printed = 1;
3369 /* walk extensions ... */
3370 for (e = ast_walk_context_extensions(c, NULL); e; e = ast_walk_context_extensions(c, e)) {
3371 struct ast_exten *p;
3374 /* looking for extension? is this our extension? */
3376 !ast_extension_match(ast_get_extension_name(e), exten))
3378 /* we are looking for extension and it's not our
3379 * extension, so skip to next extension */
3383 dpc->extension_existence = 1;
3385 /* may we print context info? */
3386 if (!context_info_printed) {
3387 dpc->total_context++;
3389 /* TODO Print more info about rinclude */
3390 ast_cli(fd, "[ Included context '%s' created by '%s' ]\n",
3391 ast_get_context_name(c),
3392 ast_get_context_registrar(c));
3394 ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
3395 ast_get_context_name(c),
3396 ast_get_context_registrar(c));
3398 context_info_printed = 1;
3402 /* write extension name and first peer */
3403 bzero(buf, sizeof(buf));
3404 snprintf(buf, sizeof(buf), "'%s' =>",
3405 ast_get_extension_name(e));
3407 prio = ast_get_extension_priority(e);
3408 if (prio == PRIORITY_HINT) {
3409 snprintf(buf2, sizeof(buf2),
3411 ast_get_extension_app(e));
3413 snprintf(buf2, sizeof(buf2),
3416 ast_get_extension_app(e),
3417 (char *)ast_get_extension_app_data(e));
3420 ast_cli(fd, " %-17s %-45s [%s]\n", buf, buf2,
3421 ast_get_extension_registrar(e));
3424 /* walk next extension peers */
3425 for (p=ast_walk_extension_priorities(e, e); p; p=ast_walk_extension_priorities(e, p)) {
3427 bzero((void *)buf2, sizeof(buf2));
3428 bzero((void *)buf, sizeof(buf));
3429 if (ast_get_extension_label(p))
3430 snprintf(buf, sizeof(buf), " [%s]", ast_get_extension_label(p));
3431 prio = ast_get_extension_priority(p);
3432 if (prio == PRIORITY_HINT) {
3433 snprintf(buf2, sizeof(buf2),
3435 ast_get_extension_app(p));
3437 snprintf(buf2, sizeof(buf2),
3440 ast_get_extension_app(p),
3441 (char *)ast_get_extension_app_data(p));
3444 ast_cli(fd," %-17s %-45s [%s]\n",
3446 ast_get_extension_registrar(p));