2 * Asterisk -- A telephony toolkit for Linux.
6 * Copyright (C) 1999, Mark Spencer
8 * Mark Spencer <markster@linux-support.net>
10 * This program is free software, distributed under the terms of
11 * the GNU General Public License
14 #include <asterisk/lock.h>
15 #include <asterisk/cli.h>
16 #include <asterisk/pbx.h>
17 #include <asterisk/channel.h>
18 #include <asterisk/options.h>
19 #include <asterisk/logger.h>
20 #include <asterisk/file.h>
21 #include <asterisk/callerid.h>
22 #include <asterisk/cdr.h>
23 #include <asterisk/config.h>
24 #include <asterisk/term.h>
25 #include <asterisk/manager.h>
26 #include <asterisk/ast_expr.h>
27 #include <asterisk/channel_pvt.h>
28 #include <asterisk/linkedlists.h>
29 #include <asterisk/say.h>
44 * The speed of extension handling will likely be among the most important
45 * aspects of this PBX. The switching scheme as it exists right now isn't
46 * terribly bad (it's O(N+M), where N is the # of extensions and M is the avg #
47 * of priorities, but a constant search time here would be great ;-)
56 char exten[AST_MAX_EXTENSION];
58 char cidmatch[AST_MAX_EXTENSION];
61 struct ast_context *parent;
62 /* Application to execute */
63 char app[AST_MAX_EXTENSION];
67 void (*datad)(void *);
68 /* Next higher priority with our extension */
69 struct ast_exten *peer;
72 /* Extension with a greater ID */
73 struct ast_exten *next;
77 char name[AST_MAX_EXTENSION];
78 char rname[AST_MAX_EXTENSION];
81 unsigned int monthmask;
84 unsigned int minmask[24];
85 struct ast_include *next;
89 char name[AST_MAX_EXTENSION];
91 char data[AST_MAX_EXTENSION];
95 struct ast_ignorepat {
96 char pattern[AST_MAX_EXTENSION];
98 struct ast_ignorepat *next;
101 /* An extension context */
103 /* Name of the context */
104 char name[AST_MAX_EXTENSION];
105 /* A lock to prevent multiple threads from clobbering the context */
107 /* The root of the list of extensions */
108 struct ast_exten *root;
109 /* Link them together */
110 struct ast_context *next;
111 /* Include other contexts */
112 struct ast_include *includes;
113 /* Patterns for which to continue playing dialtone */
114 struct ast_ignorepat *ignorepats;
117 /* Alternative switches */
124 /* Name of the application */
125 char name[AST_MAX_APP];
126 int (*execute)(struct ast_channel *chan, void *data);
129 struct ast_app *next;
132 /* An extension state notify */
133 struct ast_state_cb {
136 ast_state_cb_type callback;
137 struct ast_state_cb *next;
141 struct ast_exten *exten;
143 struct ast_state_cb *callbacks;
144 struct ast_hint *next;
148 static int pbx_builtin_prefix(struct ast_channel *, void *);
149 static int pbx_builtin_suffix(struct ast_channel *, void *);
150 static int pbx_builtin_stripmsd(struct ast_channel *, void *);
151 static int pbx_builtin_answer(struct ast_channel *, void *);
152 static int pbx_builtin_goto(struct ast_channel *, void *);
153 static int pbx_builtin_hangup(struct ast_channel *, void *);
154 static int pbx_builtin_background(struct ast_channel *, void *);
155 static int pbx_builtin_dtimeout(struct ast_channel *, void *);
156 static int pbx_builtin_rtimeout(struct ast_channel *, void *);
157 static int pbx_builtin_atimeout(struct ast_channel *, void *);
158 static int pbx_builtin_wait(struct ast_channel *, void *);
159 static int pbx_builtin_setlanguage(struct ast_channel *, void *);
160 static int pbx_builtin_resetcdr(struct ast_channel *, void *);
161 static int pbx_builtin_setaccount(struct ast_channel *, void *);
162 static int pbx_builtin_ringing(struct ast_channel *, void *);
163 static int pbx_builtin_congestion(struct ast_channel *, void *);
164 static int pbx_builtin_busy(struct ast_channel *, void *);
165 static int pbx_builtin_setglobalvar(struct ast_channel *, void *);
166 static int pbx_builtin_noop(struct ast_channel *, void *);
167 static int pbx_builtin_gotoif(struct ast_channel *, void *);
168 static int pbx_builtin_gotoiftime(struct ast_channel *, void *);
169 static int pbx_builtin_saynumber(struct ast_channel *, void *);
170 static int pbx_builtin_saydigits(struct ast_channel *, void *);
171 int pbx_builtin_setvar(struct ast_channel *, void *);
172 void pbx_builtin_setvar_helper(struct ast_channel *chan, char *name, char *value);
173 char *pbx_builtin_getvar_helper(struct ast_channel *chan, char *name);
175 static struct varshead globals = AST_LIST_HEAD_INITIALIZER(varshead);
177 static struct pbx_builtin {
178 char name[AST_MAX_APP];
179 int (*execute)(struct ast_channel *chan, void *data);
184 /* These applications are built into the PBX core and do not
185 need separate modules
189 { "AbsoluteTimeout", pbx_builtin_atimeout,
190 "Set absolute maximum time of call",
191 " AbsoluteTimeout(seconds): Set the absolute maximum amount of time permitted\n"
192 "for a call. A setting of 0 disables the timeout. Always returns 0.\n" },
194 { "Answer", pbx_builtin_answer,
195 "Answer a channel if ringing",
196 " Answer(): If the channel is ringing, answer it, otherwise do nothing. \n"
197 "Returns 0 unless it tries to answer the channel and fails.\n" },
199 { "BackGround", pbx_builtin_background,
200 "Play a file while awaiting extension",
201 " Background(filename): Plays a given file, while simultaneously waiting for\n"
202 "the user to begin typing an extension. The timeouts do not count until the\n"
203 "last BackGround application as ended. Always returns 0.\n" },
205 { "Busy", pbx_builtin_busy,
206 "Indicate busy condition and stop",
207 " Busy(): Requests that the channel indicate busy condition and then waits\n"
208 "for the user to hang up. Always returns -1." },
210 { "Congestion", pbx_builtin_congestion,
211 "Indicate congestion and stop",
212 " Congestion(): Requests that the channel indicate congestion and then\n"
213 "waits for the user to hang up. Always returns -1." },
215 { "DigitTimeout", pbx_builtin_dtimeout,
216 "Set maximum timeout between digits",
217 " DigitTimeout(seconds): Set the maximum amount of time permitted between\n"
218 "digits when the user is typing in an extension. When this timeout expires,\n"
219 "after the user has started to type in an extension, the extension will be\n"
220 "considered complete, and will be interpreted. Note that if an extension\n"
221 "typed in is valid, it will not have to timeout to be tested, so typically\n"
222 "at the expiry of this timeout, the extension will be considered invalid\n"
223 "(and thus control would be passed to the 'i' extension, or if it doesn't\n"
224 "exist the call would be terminated). Always returns 0.\n" },
226 { "Goto", pbx_builtin_goto,
227 "Goto a particular priority, extension, or context",
228 " Goto([[context|]extension|]priority): Set the priority to the specified\n"
229 "value, optionally setting the extension and optionally the context as well.\n"
230 "The extension BYEXTENSION is special in that it uses the current extension,\n"
231 "thus permitting you to go to a different context, without specifying a\n"
232 "specific extension. Always returns 0, even if the given context, extension,\n"
233 "or priority is invalid.\n" },
235 { "GotoIf", pbx_builtin_gotoif,
237 " GotoIf(Condition?label1:label2): Go to label 1 if condition is\n"
238 "true, to label2 if condition is false. Either label1 or label2 may be\n"
239 "omitted (in that case, we just don't take the particular branch) but not\n"
240 "both. Look for the condition syntax in examples or documentation." },
242 { "GotoIfTime", pbx_builtin_gotoiftime,
243 "Conditional goto on current time",
244 " GotoIfTime(<times>|<weekdays>|<mdays>|<months>?[[context|]extension|]pri):\n"
245 "If the current time matches the specified time, then branch to the specified\n"
246 "extension. Each of the elements may be specified either as '*' (for always)\n"
247 "or as a range. See the include syntax." },
249 { "Hangup", pbx_builtin_hangup,
250 "Unconditional hangup",
251 " Hangup(): Unconditionally hangs up a given channel by returning -1 always.\n" },
253 { "NoOp", pbx_builtin_noop,
255 " NoOp(): No-operation; Does nothing." },
257 { "Prefix", pbx_builtin_prefix,
258 "Prepend leading digits",
259 " Prefix(digits): Prepends the digit string specified by digits to the\n"
260 "channel's associated extension. For example, the number 1212 when prefixed\n"
261 "with '555' will become 5551212. This app always returns 0, and the PBX will\n"
262 "continue processing at the next priority for the *new* extension.\n"
263 " So, for example, if priority 3 of 1212 is Prefix 555, the next step\n"
264 "executed will be priority 4 of 5551212. If you switch into an extension\n"
265 "which has no first step, the PBX will treat it as though the user dialed an\n"
266 "invalid extension.\n" },
268 { "ResetCDR", pbx_builtin_resetcdr,
269 "Resets the Call Data Record",
270 " ResetCDR([options]): Causes the Call Data Record to be reset, optionally\n"
271 "storing the current CDR before zeroing it out (if 'w' option is specifed).\n"
272 "record WILL be stored. Always returns 0.\n" },
274 { "ResponseTimeout", pbx_builtin_rtimeout,
275 "Set maximum timeout awaiting response",
276 " ResponseTimeout(seconds): Set the maximum amount of time permitted after\n"
277 "falling through a series of priorities for a channel in which the user may\n"
278 "begin typing an extension. If the user does not type an extension in this\n"
279 "amount of time, control will pass to the 't' extension if it exists, and\n"
280 "if not the call would be terminated. Always returns 0.\n" },
282 { "Ringing", pbx_builtin_ringing,
283 "Indicate ringing tone",
284 " Ringing(): Request that the channel indicate ringing tone to the user.\n"
285 "Always returns 0.\n" },
287 { "SayNumber", pbx_builtin_saynumber,
289 " SayNumber(digits): Says the passed number\n" },
291 { "SayDigits", pbx_builtin_saydigits,
293 " SayDigits(digits): Says the passed digits\n" },
295 { "SetAccount", pbx_builtin_setaccount,
297 " SetAccount([account]): Set the channel account code for billing\n"
298 "purposes. Always returns 0.\n" },
300 { "SetGlobalVar", pbx_builtin_setglobalvar,
301 "Set variable to value",
302 " Setvar(#n=value): Sets global variable n to value" },
304 { "SetLanguage", pbx_builtin_setlanguage,
305 "Sets user language",
306 " SetLanguage(language): Set the channel language to 'language'. This\n"
307 "information is used for the generation of numbers, and to select a natural\n"
308 "language file when available. For example, if language is set to 'fr' and\n"
309 "the file 'demo-congrats' is requested to be played, if the file 'demo-\n"
310 "congrats-fr' exists, then it will play that file, and if not will play the\n"
311 "normal 'demo-congrats'. Always returns 0.\n" },
313 { "SetVar", pbx_builtin_setvar,
314 "Set variable to value",
315 " Setvar(#n=value): Sets variable n to value" },
317 { "StripMSD", pbx_builtin_stripmsd,
318 "Strip leading digits",
319 " StripMSD(count): Strips the leading 'count' digits from the channel's\n"
320 "associated extension. For example, the number 5551212 when stripped with a\n"
321 "count of 3 would be changed to 1212. This app always returns 0, and the PBX\n"
322 "will continue processing at the next priority for the *new* extension.\n"
323 " So, for example, if priority 3 of 5551212 is StripMSD 3, the next step\n"
324 "executed will be priority 4 of 1212. If you switch into an extension which\n"
325 "has no first step, the PBX will treat it as though the user dialed an\n"
326 "invalid extension.\n" },
328 { "Suffix", pbx_builtin_suffix,
329 "Append trailing digits",
330 " Suffix(digits): Appends the digit string specified by digits to the\n"
331 "channel's associated extension. For example, the number 555 when suffixed\n"
332 "with '1212' will become 5551212. This app always returns 0, and the PBX will\n"
333 "continue processing at the next priority for the *new* extension.\n"
334 " So, for example, if priority 3 of 555 is Suffix 1212, the next step\n"
335 "executed will be priority 4 of 5551212. If you switch into an extension\n"
336 "which has no first step, the PBX will treat it as though the user dialed an\n"
337 "invalid extension.\n" },
339 { "Wait", pbx_builtin_wait,
340 "Waits for some time",
341 " Wait(seconds): Waits for a specified number of seconds, then returns 0.\n" },
345 /* Lock for the application list */
346 static ast_mutex_t applock = AST_MUTEX_INITIALIZER;
347 static struct ast_context *contexts = NULL;
348 /* Lock for the ast_context list */
349 static ast_mutex_t conlock = AST_MUTEX_INITIALIZER;
350 static struct ast_app *apps = NULL;
352 /* Lock for switches */
353 static ast_mutex_t switchlock = AST_MUTEX_INITIALIZER;
354 struct ast_switch *switches = NULL;
356 /* Lock for extension state notifys */
357 static ast_mutex_t hintlock = AST_MUTEX_INITIALIZER;
358 static int stateid = 1;
359 struct ast_hint *hints = NULL;
360 struct ast_state_cb *statecbs = NULL;
362 int pbx_exec(struct ast_channel *c, /* Channel */
364 void *data, /* Data for execution */
365 int newstack) /* Force stack increment */
367 /* This function is special. It saves the stack so that no matter
368 how many times it is called, it returns to the same place */
370 int stack = c->stack;
371 int (*execute)(struct ast_channel *chan, void *data) = app->execute;
372 if (newstack && stack > AST_CHANNEL_MAX_STACK - 2) {
373 /* Don't allow us to go over the max number of stacks we
375 ast_log(LOG_WARNING, "Stack overflow, cannot create another stack\n");
378 if (newstack && (res = setjmp(c->jmp[++c->stack]))) {
379 /* Okay, here's where it gets weird. If newstack is non-zero,
380 then we increase the stack increment, but setjmp is not going
381 to return until longjmp is called -- when the application
382 exec'd is finished running. */
385 if (c->stack != stack + 1)
386 ast_log(LOG_WARNING, "Stack returned to an unexpected place!\n");
387 else if (c->app[c->stack])
388 ast_log(LOG_WARNING, "Application may have forgotten to free its memory\n");
393 ast_cdr_setapp(c->cdr, app->name, data);
396 res = execute(c, data);
399 /* Any application that returns, we longjmp back, just in case. */
400 if (c->stack != stack + 1)
401 ast_log(LOG_WARNING, "Stack is not at expected value\n");
402 longjmp(c->jmp[stack+1], res);
408 /* Go no deeper than this through includes (not counting loops) */
409 #define AST_PBX_MAX_STACK 64
411 #define HELPER_EXISTS 0
412 #define HELPER_SPAWN 1
413 #define HELPER_EXEC 2
414 #define HELPER_CANMATCH 3
415 #define HELPER_MATCHMORE 4
417 struct ast_app *pbx_findapp(char *app)
420 if (ast_mutex_lock(&applock)) {
421 ast_log(LOG_WARNING, "Unable to obtain application lock\n");
426 if (!strcasecmp(tmp->name, app))
430 ast_mutex_unlock(&applock);
434 static struct ast_switch *pbx_findswitch(char *sw)
436 struct ast_switch *asw;
437 if (ast_mutex_lock(&switchlock)) {
438 ast_log(LOG_WARNING, "Unable to obtain application lock\n");
443 if (!strcasecmp(asw->name, sw))
447 ast_mutex_unlock(&switchlock);
451 static inline int include_valid(struct ast_include *i)
460 /* If it's not the right month, return */
461 if (!(i->monthmask & (1 << tm.tm_mon))) {
465 /* If it's not that time of the month.... */
466 /* Warning, tm_mday has range 1..31! */
467 if (!(i->daymask & (1 << (tm.tm_mday-1))))
470 /* If it's not the right day of the week */
471 if (!(i->dowmask & (1 << tm.tm_wday)))
474 /* Sanity check the hour just to be safe */
475 if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) {
476 ast_log(LOG_WARNING, "Insane time...\n");
480 /* Now the tough part, we calculate if it fits
481 in the right time based on min/hour */
482 if (!(i->minmask[tm.tm_hour] & (1 << (tm.tm_min / 2))))
485 /* If we got this far, then we're good */
489 static void pbx_destroy(struct ast_pbx *p)
494 #define EXTENSION_MATCH_CORE(data,pattern,match) {\
495 /* All patterns begin with _ */\
496 if (pattern[0] != '_') \
498 /* Start optimistic */\
501 while(match && *data && *pattern && (*pattern != '/')) {\
502 switch(toupper(*pattern)) {\
509 where=strchr(pattern,']');\
511 border=(int)(where-pattern);\
512 if (!where || border > strlen(pattern)) {\
513 ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n");\
516 for (i=0; i<border; i++) {\
519 if (pattern[i+1]=='-') {\
520 if (*data >= pattern[i] && *data <= pattern[i+2]) {\
527 if (res==1 || *data==pattern[i]) {\
536 if ((*data < '2') || (*data > '9'))\
540 if ((*data < '0') || (*data > '9'))\
544 if ((*data < '1') || (*data > '9'))\
552 /* Ignore these characters */\
556 if (*data != *pattern)\
564 int ast_extension_match(char *pattern, char *data)
567 /* If they're the same return */
568 if (!strcmp(pattern, data))
570 EXTENSION_MATCH_CORE(data,pattern,match);
571 /* Must be at the end of both */
572 if (*data || (*pattern && (*pattern != '/')))
577 static int extension_close(char *pattern, char *data, int needmore)
580 /* If "data" is longer, it can'be a subset of pattern unless
581 pattern is a pattern match */
582 if ((strlen(pattern) < strlen(data)) && (pattern[0] != '_'))
585 if ((!strlen((char *)data) || !strncasecmp(pattern, data, strlen(data))) &&
586 (!needmore || (strlen(pattern) > strlen(data)))) {
589 EXTENSION_MATCH_CORE(data,pattern,match);
590 /* If there's more or we don't care about more, return non-zero, otlherwise it's a miss */
591 if (!needmore || *pattern) {
597 struct ast_context *ast_context_find(char *name)
599 struct ast_context *tmp;
600 ast_mutex_lock(&conlock);
604 if (!strcasecmp(name, tmp->name))
610 ast_mutex_unlock(&conlock);
614 #define STATUS_NO_CONTEXT 1
615 #define STATUS_NO_EXTENSION 2
616 #define STATUS_NO_PRIORITY 3
617 #define STATUS_SUCCESS 4
619 static int matchcid(char *cidpattern, char *callerid)
621 char tmp[AST_MAX_EXTENSION];
625 /* If the Caller*ID pattern is empty, then we're matching NO Caller*ID, so
626 failing to get a number should count as a match, otherwise not */
629 if (strlen(cidpattern))
637 /* Copy original Caller*ID */
638 strncpy(tmp, callerid, sizeof(tmp)-1);
640 if (ast_callerid_parse(tmp, &name, &num))
644 ast_shrink_phone_number(num);
645 return ast_extension_match(cidpattern, num);
648 static struct ast_exten *pbx_find_extension(struct ast_channel *chan, char *context, char *exten, int priority, char *callerid, int action, char *incstack[], int *stacklen, int *status, struct ast_switch **swo, char **data)
651 struct ast_context *tmp;
652 struct ast_exten *e, *eroot;
653 struct ast_include *i;
655 struct ast_switch *asw;
656 /* Initialize status if appropriate */
658 *status = STATUS_NO_CONTEXT;
662 /* Check for stack overflow */
663 if (*stacklen >= AST_PBX_MAX_STACK) {
664 ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n");
667 /* Check first to see if we've already been checked */
668 for (x=0;x<*stacklen;x++) {
669 if (!strcasecmp(incstack[x], context))
675 if (!strcmp(tmp->name, context)) {
676 if (*status < STATUS_NO_EXTENSION)
677 *status = STATUS_NO_EXTENSION;
680 /* Match extension */
681 if ((((action != HELPER_MATCHMORE) && ast_extension_match(eroot->exten, exten)) ||
682 ((action == HELPER_CANMATCH) && (extension_close(eroot->exten, exten, 0))) ||
683 ((action == HELPER_MATCHMORE) && (extension_close(eroot->exten, exten, 1)))) &&
684 (!eroot->matchcid || matchcid(eroot->cidmatch, callerid))) {
686 if (*status < STATUS_NO_PRIORITY)
687 *status = STATUS_NO_PRIORITY;
690 if (e->priority == priority) {
691 *status = STATUS_SUCCESS;
699 /* Check alternative switches */
702 if ((asw = pbx_findswitch(sw->name))) {
703 if (action == HELPER_CANMATCH)
704 res = asw->canmatch ? asw->canmatch(chan, context, exten, priority, callerid, sw->data) : 0;
705 else if (action == HELPER_MATCHMORE)
706 res = asw->matchmore ? asw->matchmore(chan, context, exten, priority, callerid, sw->data) : 0;
708 res = asw->exists ? asw->exists(chan, context, exten, priority, callerid, sw->data) : 0;
716 ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name);
720 /* Setup the stack */
721 incstack[*stacklen] = tmp->name;
723 /* Now try any includes we have in this context */
726 if (include_valid(i)) {
727 if ((e = pbx_find_extension(chan, i->rname, exten, priority, callerid, action, incstack, stacklen, status, swo, data)))
740 static void pbx_substitute_variables_temp(struct ast_channel *c,const char *var,char **ret, char *workspace, int workspacelen)
743 char tmpvar[80] = "";
745 struct tm brokentime;
747 struct ast_var_t *variables;
748 char *name, *num; /* for callerid name + num variables */
749 struct varshead *headp=NULL;
753 /* Now we have the variable name on cp3 */
754 if ((first=strchr(var,':'))) {
755 strncpy(tmpvar, var, sizeof(tmpvar) - 1);
756 first = strchr(tmpvar, ':');
758 first = tmpvar + strlen(tmpvar);
760 pbx_substitute_variables_temp(c,tmpvar,ret,workspace,workspacelen - 1);
762 offset=atoi(first+1);
763 if ((second=strchr(first+1,':'))) {
765 offset2=atoi(second+1);
767 offset2=strlen(*ret)-offset;
768 if (abs(offset)>strlen(*ret)) {
772 offset=-strlen(*ret);
774 if ((offset<0 && offset2>-offset) || (offset>=0 && offset+offset2>strlen(*ret))) {
776 offset2=strlen(*ret)-offset;
778 offset2=strlen(*ret)+offset;
783 *ret+=strlen(*ret)+offset;
784 (*ret)[offset2] = '\0';
785 } else if (c && !strcmp(var, "CALLERIDNUM")) {
787 strncpy(workspace, c->callerid, workspacelen - 1);
788 ast_callerid_parse(workspace, &name, &num);
790 ast_shrink_phone_number(num);
794 } else if (c && !strcmp(var, "CALLERIDNAME")) {
796 strncpy(workspace, c->callerid, workspacelen - 1);
797 ast_callerid_parse(workspace, &name, &num);
802 } else if (c && !strcmp(var, "CALLERID")) {
804 strncpy(workspace, c->callerid, workspacelen - 1);
808 } else if (c && !strcmp(var, "DNID")) {
810 strncpy(workspace, c->dnid, workspacelen - 1);
814 } else if (c && !strcmp(var, "HINT")) {
815 if (!ast_get_hint(workspace, workspacelen - 1, c, c->context, c->exten))
819 } else if (c && !strcmp(var, "EXTEN")) {
820 strncpy(workspace, c->exten, workspacelen - 1);
822 } else if (c && !strncmp(var, "EXTEN-", strlen("EXTEN-")) &&
823 /* XXX Remove me eventually */
824 (sscanf(var + strlen("EXTEN-"), "%d", &offset) == 1)) {
827 if (offset > strlen(c->exten))
828 offset = strlen(c->exten);
829 strncpy(workspace, c->exten + offset, workspacelen - 1);
831 ast_log(LOG_WARNING, "The use of 'EXTEN-foo' has been derprecated in favor of 'EXTEN:foo'\n");
832 } else if (c && !strcmp(var, "RDNIS")) {
834 strncpy(workspace, c->rdnis, workspacelen - 1);
838 } else if (c && !strcmp(var, "CONTEXT")) {
839 strncpy(workspace, c->context, workspacelen - 1);
841 } else if (c && !strcmp(var, "PRIORITY")) {
842 snprintf(workspace, workspacelen, "%d", c->priority);
844 } else if (c && !strcmp(var, "CHANNEL")) {
845 strncpy(workspace, c->name, workspacelen - 1);
847 } else if (c && !strcmp(var, "EPOCH")) {
848 snprintf(workspace, workspacelen -1, "%u",(int)time(NULL));
850 } else if (c && !strcmp(var, "DATETIME")) {
852 localtime_r(&thistime, &brokentime);
853 snprintf(workspace, workspacelen -1, "%02d%02d%04d-%02d:%02d:%02d",
856 brokentime.tm_year+1900,
862 } else if (c && !strcmp(var, "UNIQUEID")) {
863 snprintf(workspace, workspacelen -1, "%s", c->uniqueid);
867 AST_LIST_TRAVERSE(headp,variables,entries) {
869 ast_log(LOG_WARNING,"Comparing variable '%s' with '%s'\n",var,ast_var_name(variables));
871 if (strcasecmp(ast_var_name(variables),var)==0) {
872 *ret=ast_var_value(variables);
874 strncpy(workspace, *ret, workspacelen - 1);
882 AST_LIST_TRAVERSE(&globals,variables,entries) {
884 ast_log(LOG_WARNING,"Comparing variable '%s' with '%s'\n",var,ast_var_name(variables));
886 if (strcasecmp(ast_var_name(variables),var)==0) {
887 *ret=ast_var_value(variables);
889 strncpy(workspace, *ret, workspacelen - 1);
897 int len_env=strlen("ENV(");
898 if (len > (len_env+1) && !strncasecmp(var,"ENV(",len_env) && !strcmp(var+len-1,")")) {
900 strncpy(cp3, var, sizeof(cp3) - 1);
902 *ret=getenv(cp3+len_env);
904 strncpy(workspace, *ret, workspacelen - 1);
909 if (!(*ret) && !strncasecmp(var,"LEN(",4)) {
912 if (len > (len_len+1) && !strncasecmp(var,"LEN(",len_len) && strchr(var+len_len+2,')')) {
914 strncpy(cp3, var, sizeof(cp3) - 1);
915 cp3[len-len_len-1]='\0';
916 sprintf(workspace,"%d",strlen(cp3));
918 } else ast_log(LOG_NOTICE, "Wrong use of LEN(VARIABLE)\n");
923 void pbx_substitute_variables_helper(struct ast_channel *c,const char *cp1,char *cp2,int count)
926 const char *tmp, *whereweare;
929 char ltmp[256], var[256];
930 char *nextvar, *nextexp;
932 int pos, brackets, needsub, len;
934 /* Substitutes variables into cp2, based on string cp1, and assuming cp2 to be
937 while(strlen(whereweare) && count) {
938 /* Assume we're copying the whole remaining string */
939 pos = strlen(whereweare);
941 /* Look for a variable */
942 nextvar = strstr(whereweare, "${");
944 nextexp = strstr(whereweare, "$[");
946 if (nextvar && nextexp) {
947 if (nextvar < nextexp)
953 /* If there is one, we only go that far */
955 pos = nextvar - whereweare;
957 pos = nextexp - whereweare;
959 /* Can't copy more than 'count' bytes */
963 /* Copy that many bytes */
964 memcpy(cp2, whereweare, pos);
971 /* We have a variable. Find the start and end, and determine
972 if we are going to have to recursively call ourselves on the
974 vars = vare = nextvar + 2;
978 /* Find the end of it */
979 while(brackets && *vare) {
980 if ((vare[0] == '$') && (vare[1] == '{')) {
983 } else if (vare[0] == '}') {
985 } else if ((vare[0] == '$') && (vare[1] == '['))
990 ast_log(LOG_NOTICE, "Error in extension logic (missing '}')\n");
991 len = vare - vars - 1;
993 /* Skip totally over variable name */
994 whereweare += ( len + 3);
996 /* Store variable name (and truncate) */
997 memset(var, 0, sizeof(var));
998 strncpy(var, vars, sizeof(var) - 1);
1001 /* Substitute if necessary */
1003 memset(ltmp, 0, sizeof(ltmp));
1004 pbx_substitute_variables_helper(c, var, ltmp, sizeof(ltmp) - 1);
1010 /* Retrieve variable value */
1011 strcpy(workspace, "");
1012 pbx_substitute_variables_temp(c,vars,&cp4, workspace, sizeof(workspace));
1014 length = strlen(cp4);
1017 memcpy(cp2, cp4, length);
1022 } else if (nextexp) {
1023 /* We have an expression. Find the start and end, and determine
1024 if we are going to have to recursively call ourselves on the
1026 vars = vare = nextexp + 2;
1030 /* Find the end of it */
1031 while(brackets && *vare) {
1032 if ((vare[0] == '$') && (vare[1] == '[')) {
1035 } else if (vare[0] == ']') {
1037 } else if ((vare[0] == '$') && (vare[1] == '{'))
1042 ast_log(LOG_NOTICE, "Error in extension logic (missing ']')\n");
1043 len = vare - vars - 1;
1045 /* Skip totally over variable name */
1046 whereweare += ( len + 3);
1048 /* Store variable name (and truncate) */
1049 memset(var, 0, sizeof(var));
1050 strncpy(var, vars, sizeof(var) - 1);
1053 /* Substitute if necessary */
1055 memset(ltmp, 0, sizeof(ltmp));
1056 pbx_substitute_variables_helper(c, var, ltmp, sizeof(ltmp) - 1);
1062 /* Evaluate expression */
1063 cp4 = ast_expr(vars);
1065 ast_log(LOG_DEBUG, "Expression is '%s'\n", cp4);
1068 length = strlen(cp4);
1071 memcpy(cp2, cp4, length);
1082 static void pbx_substitute_variables(char *passdata, int datalen, struct ast_channel *c, struct ast_exten *e) {
1084 memset(passdata, 0, datalen);
1086 /* No variables or expressions in e->data, so why scan it? */
1087 if (!strstr(e->data,"${") && !strstr(e->data,"$[")) {
1088 strncpy(passdata, e->data, datalen - 1);
1089 passdata[datalen-1] = '\0';
1093 pbx_substitute_variables_helper(c,e->data,passdata, datalen - 1);
1096 static int pbx_extension_helper(struct ast_channel *c, char *context, char *exten, int priority, char *callerid, int action)
1098 struct ast_exten *e;
1099 struct ast_app *app;
1100 struct ast_switch *sw;
1105 char *incstack[AST_PBX_MAX_STACK];
1111 if (ast_mutex_lock(&conlock)) {
1112 ast_log(LOG_WARNING, "Unable to obtain lock\n");
1113 if ((action == HELPER_EXISTS) || (action == HELPER_CANMATCH) || (action == HELPER_MATCHMORE))
1118 e = pbx_find_extension(c, context, exten, priority, callerid, action, incstack, &stacklen, &status, &sw, &data);
1121 case HELPER_CANMATCH:
1122 ast_mutex_unlock(&conlock);
1125 ast_mutex_unlock(&conlock);
1127 case HELPER_MATCHMORE:
1128 ast_mutex_unlock(&conlock);
1134 app = pbx_findapp(e->app);
1135 ast_mutex_unlock(&conlock);
1137 if (c->context != context)
1138 strncpy(c->context, context, sizeof(c->context)-1);
1139 if (c->exten != exten)
1140 strncpy(c->exten, exten, sizeof(c->exten)-1);
1141 c->priority = priority;
1142 pbx_substitute_variables(passdata, sizeof(passdata), c, e);
1144 ast_log(LOG_DEBUG, "Launching '%s'\n", app->name);
1145 else if (option_verbose > 2)
1146 ast_verbose( VERBOSE_PREFIX_3 "Executing %s(\"%s\", \"%s\") %s\n",
1147 term_color(tmp, app->name, COLOR_BRCYAN, 0, sizeof(tmp)),
1148 term_color(tmp2, c->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)),
1149 term_color(tmp3, (strlen(passdata) ? (char *)passdata : ""), COLOR_BRMAGENTA, 0, sizeof(tmp3)),
1150 (newstack ? "in new stack" : "in same stack"));
1151 res = pbx_exec(c, app, passdata, newstack);
1154 ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority);
1158 ast_log(LOG_WARNING, "Huh (%d)?\n", action); return -1;
1162 case HELPER_CANMATCH:
1163 ast_mutex_unlock(&conlock);
1166 ast_mutex_unlock(&conlock);
1168 case HELPER_MATCHMORE:
1169 ast_mutex_unlock(&conlock);
1175 ast_mutex_unlock(&conlock);
1177 res = sw->exec(c, context, exten, priority, callerid, newstack, data);
1179 ast_log(LOG_WARNING, "No execution engine for switch %s\n", sw->name);
1184 ast_log(LOG_WARNING, "Huh (%d)?\n", action);
1188 ast_mutex_unlock(&conlock);
1190 case STATUS_NO_CONTEXT:
1191 if ((action != HELPER_EXISTS) && (action != HELPER_MATCHMORE))
1192 ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", context);
1194 case STATUS_NO_EXTENSION:
1195 if ((action != HELPER_EXISTS) && (action != HELPER_CANMATCH) && (action != HELPER_MATCHMORE))
1196 ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, context);
1198 case STATUS_NO_PRIORITY:
1199 if ((action != HELPER_EXISTS) && (action != HELPER_CANMATCH) && (action != HELPER_MATCHMORE))
1200 ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, context);
1203 ast_log(LOG_DEBUG, "Shouldn't happen!\n");
1205 if ((action != HELPER_EXISTS) && (action != HELPER_CANMATCH) && (action != HELPER_MATCHMORE))
1213 static struct ast_exten *ast_hint_extension(struct ast_channel *c, char *context, char *exten)
1215 struct ast_exten *e;
1216 struct ast_switch *sw;
1219 char *incstack[AST_PBX_MAX_STACK];
1222 if (ast_mutex_lock(&conlock)) {
1223 ast_log(LOG_WARNING, "Unable to obtain lock\n");
1226 e = pbx_find_extension(c, context, exten, PRIORITY_HINT, "", HELPER_EXISTS, incstack, &stacklen, &status, &sw, &data);
1227 ast_mutex_unlock(&conlock);
1231 static int ast_extension_state2(struct ast_exten *e)
1233 char hint[AST_MAX_EXTENSION] = "";
1236 int allunavailable = 1, allbusy = 1, allfree = 1;
1239 strncpy(hint, ast_get_extension_app(e), sizeof(hint)-1);
1243 rest = strchr(cur, '&');
1249 res = ast_device_state(cur);
1251 case AST_DEVICE_NOT_INUSE:
1255 case AST_DEVICE_INUSE:
1256 return AST_EXTENSION_INUSE;
1257 case AST_DEVICE_BUSY:
1262 case AST_DEVICE_UNAVAILABLE:
1263 case AST_DEVICE_INVALID:
1276 return AST_EXTENSION_NOT_INUSE;
1278 return AST_EXTENSION_BUSY;
1280 return AST_EXTENSION_UNAVAILABLE;
1282 return AST_EXTENSION_INUSE;
1284 return AST_EXTENSION_NOT_INUSE;
1288 int ast_extension_state(struct ast_channel *c, char *context, char *exten)
1290 struct ast_exten *e;
1292 e = ast_hint_extension(c, context, exten);
1296 return ast_extension_state2(e);
1299 int ast_device_state_changed(const char *fmt, ...)
1301 struct ast_hint *list;
1302 struct ast_state_cb *cblist;
1303 char hint[AST_MAX_EXTENSION];
1304 char device[AST_MAX_EXTENSION];
1311 vsnprintf(device, sizeof(device)-1, fmt, ap);
1314 rest = strchr(device, '-');
1319 ast_mutex_lock(&hintlock);
1325 strcpy(hint, ast_get_extension_app(list->exten));
1328 rest = strchr(cur, '&');
1334 if (!strcmp(cur, device)) {
1335 // Found extension execute callbacks
1336 state = ast_extension_state2(list->exten);
1337 if ((state != -1) && (state != list->laststate)) {
1338 // For general callbacks
1341 cblist->callback(list->exten->parent->name, list->exten->exten, state, cblist->data);
1342 cblist = cblist->next;
1345 // For extension callbacks
1346 cblist = list->callbacks;
1348 cblist->callback(list->exten->parent->name, list->exten->exten, state, cblist->data);
1349 cblist = cblist->next;
1352 list->laststate = state;
1362 ast_mutex_unlock(&hintlock);
1366 int ast_extension_state_add(char *context, char *exten,
1367 ast_state_cb_type callback, void *data)
1369 struct ast_hint *list;
1370 struct ast_state_cb *cblist;
1371 struct ast_exten *e;
1373 /* No context and extension add callback to statecbs list */
1374 if (!context && !exten) {
1375 ast_mutex_lock(&hintlock);
1379 if (cblist->callback == callback) {
1380 cblist->data = data;
1381 ast_mutex_unlock(&hintlock);
1384 cblist = cblist->next;
1387 /* Now inserts the callback */
1388 cblist = malloc(sizeof(struct ast_state_cb));
1390 ast_mutex_unlock(&hintlock);
1393 memset(cblist, 0, sizeof(struct ast_state_cb));
1395 cblist->callback = callback;
1396 cblist->data = data;
1398 cblist->next = statecbs;
1401 ast_mutex_unlock(&hintlock);
1405 if (!context || !exten)
1408 /* This callback type is for only one hint */
1409 e = ast_hint_extension(NULL, context, exten);
1414 ast_mutex_lock(&hintlock);
1418 if (list->exten == e)
1424 ast_mutex_unlock(&hintlock);
1428 /* Now inserts the callback */
1429 cblist = malloc(sizeof(struct ast_state_cb));
1431 ast_mutex_unlock(&hintlock);
1434 memset(cblist, 0, sizeof(struct ast_state_cb));
1435 cblist->id = stateid++;
1436 cblist->callback = callback;
1437 cblist->data = data;
1439 cblist->next = list->callbacks;
1440 list->callbacks = cblist;
1442 ast_mutex_unlock(&hintlock);
1446 int ast_extension_state_del(int id, ast_state_cb_type callback)
1448 struct ast_hint *list;
1449 struct ast_state_cb *cblist, *cbprev;
1451 if (!id && !callback)
1454 ast_mutex_lock(&hintlock);
1456 /* id is zero is a callback without extension */
1461 if (cblist->callback == callback) {
1463 statecbs = cblist->next;
1465 cbprev->next = cblist->next;
1469 ast_mutex_unlock(&hintlock);
1473 cblist = cblist->next;
1476 ast_mutex_lock(&hintlock);
1480 /* id greater zero is a callback with extension */
1483 cblist = list->callbacks;
1486 if (cblist->id==id) {
1488 list->callbacks = cblist->next;
1490 cbprev->next = cblist->next;
1494 ast_mutex_unlock(&hintlock);
1498 cblist = cblist->next;
1503 ast_mutex_unlock(&hintlock);
1507 static int ast_add_hint(struct ast_exten *e)
1509 struct ast_hint *list;
1513 ast_mutex_lock(&hintlock);
1516 /* Search if hint exists, do nothing */
1518 if (list->exten == e) {
1519 ast_mutex_unlock(&hintlock);
1525 list = malloc(sizeof(struct ast_hint));
1527 ast_mutex_unlock(&hintlock);
1530 /* Initialize and insert new item */
1531 memset(list, 0, sizeof(struct ast_hint));
1533 list->laststate = ast_extension_state2(e);
1537 ast_mutex_unlock(&hintlock);
1541 static int ast_change_hint(struct ast_exten *oe, struct ast_exten *ne)
1543 struct ast_hint *list;
1545 ast_mutex_lock(&hintlock);
1550 if (list->exten == oe) {
1552 ast_mutex_unlock(&hintlock);
1557 ast_mutex_unlock(&hintlock);
1562 static int ast_remove_hint(struct ast_exten *e)
1564 /* Cleanup the Notifys if hint is removed */
1565 struct ast_hint *list, *prev = NULL;
1566 struct ast_state_cb *cblist, *cbprev;
1571 ast_mutex_lock(&hintlock);
1575 if (list->exten==e) {
1577 cblist = list->callbacks;
1579 /* Notify with -1 and remove all callbacks */
1581 cblist = cblist->next;
1582 cbprev->callback(list->exten->parent->name, list->exten->exten, -1, cbprev->data);
1585 list->callbacks = NULL;
1590 prev->next = list->next;
1594 ast_mutex_unlock(&hintlock);
1602 ast_mutex_unlock(&hintlock);
1607 int ast_get_hint(char *hint, int maxlen, struct ast_channel *c, char *context, char *exten)
1609 struct ast_exten *e;
1610 e = ast_hint_extension(c, context, exten);
1612 strncpy(hint, ast_get_extension_app(e), maxlen);
1618 int ast_exists_extension(struct ast_channel *c, char *context, char *exten, int priority, char *callerid)
1620 return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_EXISTS);
1623 int ast_canmatch_extension(struct ast_channel *c, char *context, char *exten, int priority, char *callerid)
1625 return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_CANMATCH);
1628 int ast_matchmore_extension(struct ast_channel *c, char *context, char *exten, int priority, char *callerid)
1630 return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_MATCHMORE);
1633 int ast_spawn_extension(struct ast_channel *c, char *context, char *exten, int priority, char *callerid)
1635 return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_SPAWN);
1638 int ast_pbx_run(struct ast_channel *c)
1647 /* A little initial setup here */
1649 ast_log(LOG_WARNING, "%s already has PBX structure??\n", c->name);
1650 c->pbx = malloc(sizeof(struct ast_pbx));
1652 ast_log(LOG_WARNING, "Out of memory\n");
1657 ast_log(LOG_WARNING, "%s already has a call record??\n", c->name);
1659 c->cdr = ast_cdr_alloc();
1661 ast_log(LOG_WARNING, "Unable to create Call Detail Record\n");
1665 ast_cdr_init(c->cdr, c);
1668 memset(c->pbx, 0, sizeof(struct ast_pbx));
1669 /* Set reasonable defaults */
1670 c->pbx->rtimeout = 10;
1671 c->pbx->dtimeout = 5;
1673 /* Start by trying whatever the channel is set to */
1674 if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) {
1675 /* JK02: If not successfull fall back to 's' */
1676 strncpy(c->exten, "s", sizeof(c->exten)-1);
1677 if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) {
1678 /* JK02: And finally back to default if everything else failed */
1679 strncpy(c->context, "default", sizeof(c->context)-1);
1684 ast_cdr_start(c->cdr);
1688 while(ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) {
1689 memset(exten, 0, sizeof(exten));
1690 manager_event(EVENT_FLAG_CALL, "Newexten",
1696 c->name, c->context, c->exten, c->priority, c->uniqueid);
1697 if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->callerid))) {
1698 /* Something bad happened, or a hangup has been requested. */
1699 if (((res >= '0') && (res <= '9')) || ((res >= 'A') && (res <= 'F')) ||
1700 (res == '*') || (res == '#')) {
1701 ast_log(LOG_DEBUG, "Oooh, got something to jump out with ('%c')!\n", res);
1702 memset(exten, 0, sizeof(exten));
1704 exten[pos++] = digit = res;
1708 case AST_PBX_KEEPALIVE:
1710 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
1711 else if (option_verbose > 1)
1712 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
1717 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
1718 else if (option_verbose > 1)
1719 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
1720 if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
1725 if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) {
1731 if ((c->_softhangup == AST_SOFTHANGUP_TIMEOUT) && (ast_exists_extension(c,c->context,"T",1,c->callerid))) {
1732 strncpy(c->exten,"T",sizeof(c->exten) - 1);
1733 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
1734 c->whentohangup = 0;
1736 c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT;
1737 } else if (c->_softhangup) {
1738 ast_log(LOG_DEBUG, "Extension %s, priority %d returned normally even though call was hung up\n",
1739 c->exten, c->priority);
1745 if (!ast_exists_extension(c, c->context, c->exten, 1, c->callerid)) {
1746 /* It's not a valid extension anymore */
1747 if (ast_exists_extension(c, c->context, "i", 1, c->callerid)) {
1748 if (option_verbose > 2)
1749 ast_verbose(VERBOSE_PREFIX_3 "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, c->name);
1750 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", c->exten);
1751 strncpy(c->exten, "i", sizeof(c->exten)-1);
1754 ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n",
1755 c->name, c->exten, c->context);
1758 } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) {
1759 /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */
1762 /* Done, wait for an extension */
1764 waittime = c->pbx->dtimeout;
1766 waittime = c->pbx->rtimeout;
1767 while (ast_matchmore_extension(c, c->context, exten, 1, c->callerid)) {
1768 /* As long as we're willing to wait, and as long as it's not defined,
1769 keep reading digits until we can't possibly get a right answer anymore. */
1770 digit = ast_waitfordigit(c, waittime * 1000);
1771 if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
1778 /* Error, maybe a hangup */
1780 exten[pos++] = digit;
1781 waittime = c->pbx->dtimeout;
1784 if (ast_exists_extension(c, c->context, exten, 1, c->callerid)) {
1785 /* Prepare the next cycle */
1786 strncpy(c->exten, exten, sizeof(c->exten)-1);
1789 /* No such extension */
1790 if (strlen(exten)) {
1791 /* An invalid extension */
1792 if (ast_exists_extension(c, c->context, "i", 1, c->callerid)) {
1793 if (option_verbose > 2)
1794 ast_verbose( VERBOSE_PREFIX_3 "Invalid extension '%s' in context '%s' on %s\n", exten, c->context, c->name);
1795 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", exten);
1796 strncpy(c->exten, "i", sizeof(c->exten)-1);
1799 ast_log(LOG_WARNING, "Invalid extension, but no rule 'i' in context '%s'\n", c->context);
1803 /* A simple timeout */
1804 if (ast_exists_extension(c, c->context, "t", 1, c->callerid)) {
1805 if (option_verbose > 2)
1806 ast_verbose( VERBOSE_PREFIX_3 "Timeout on %s\n", c->name);
1807 strncpy(c->exten, "t", sizeof(c->exten)-1);
1810 ast_log(LOG_WARNING, "Timeout, but no rule 't' in context '%s'\n", c->context);
1816 if (option_verbose > 2)
1817 ast_verbose(VERBOSE_PREFIX_2 "CDR updated on %s\n",c->name);
1823 ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name);
1825 if ((res != AST_PBX_KEEPALIVE) && ast_exists_extension(c, c->context, "h", 1, c->callerid)) {
1826 strcpy(c->exten, "h");
1828 while(ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) {
1829 if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->callerid))) {
1830 /* Something bad happened, or a hangup has been requested. */
1832 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
1833 else if (option_verbose > 1)
1834 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
1841 pbx_destroy(c->pbx);
1843 if (res != AST_PBX_KEEPALIVE)
1848 static void *pbx_thread(void *data)
1850 /* Oh joyeous kernel, we're a new thread, with nothing to do but
1851 answer this channel and get it going. The setjmp stuff is fairly
1852 confusing, but necessary to get smooth transitions between
1853 the execution of different applications (without the use of
1854 additional threads) */
1855 struct ast_channel *c = data;
1861 int ast_pbx_start(struct ast_channel *c)
1864 pthread_attr_t attr;
1866 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
1870 /* Start a new thread, and get something handling this channel. */
1871 pthread_attr_init(&attr);
1872 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1873 if (pthread_create(&t, &attr, pbx_thread, c)) {
1874 ast_log(LOG_WARNING, "Failed to create new channel thread\n");
1881 * This function locks contexts list by &conlist, search for the rigt context
1882 * structure, leave context list locked and call ast_context_remove_include2
1883 * which removes include, unlock contexts list and return ...
1885 int ast_context_remove_include(char *context, char *include, char *registrar)
1887 struct ast_context *c;
1889 if (ast_lock_contexts()) return -1;
1891 /* walk contexts and search for the right one ...*/
1892 c = ast_walk_contexts(NULL);
1894 /* we found one ... */
1895 if (!strcmp(ast_get_context_name(c), context)) {
1897 /* remove include from this context ... */
1898 ret = ast_context_remove_include2(c, include, registrar);
1900 ast_unlock_contexts();
1902 /* ... return results */
1905 c = ast_walk_contexts(c);
1908 /* we can't find the right one context */
1909 ast_unlock_contexts();
1914 * When we call this function, &conlock lock must be locked, because when
1915 * we giving *con argument, some process can remove/change this context
1916 * and after that there can be segfault.
1918 * This function locks given context, removes include, unlock context and
1921 int ast_context_remove_include2(struct ast_context *con, char *include, char *registrar)
1923 struct ast_include *i, *pi = NULL;
1925 if (ast_mutex_lock(&con->lock)) return -1;
1930 /* find our include */
1931 if (!strcmp(i->name, include) &&
1932 (!strcmp(i->registrar, registrar) || !registrar)) {
1933 /* remove from list */
1937 con->includes = i->next;
1938 /* free include and return */
1940 ast_mutex_unlock(&con->lock);
1947 /* we can't find the right include */
1948 ast_mutex_unlock(&con->lock);
1953 * This function locks contexts list by &conlist, search for the rigt context
1954 * structure, leave context list locked and call ast_context_remove_switch2
1955 * which removes switch, unlock contexts list and return ...
1957 int ast_context_remove_switch(char *context, char *sw, char *data, char *registrar)
1959 struct ast_context *c;
1961 if (ast_lock_contexts()) return -1;
1963 /* walk contexts and search for the right one ...*/
1964 c = ast_walk_contexts(NULL);
1966 /* we found one ... */
1967 if (!strcmp(ast_get_context_name(c), context)) {
1969 /* remove switch from this context ... */
1970 ret = ast_context_remove_switch2(c, sw, data, registrar);
1972 ast_unlock_contexts();
1974 /* ... return results */
1977 c = ast_walk_contexts(c);
1980 /* we can't find the right one context */
1981 ast_unlock_contexts();
1986 * When we call this function, &conlock lock must be locked, because when
1987 * we giving *con argument, some process can remove/change this context
1988 * and after that there can be segfault.
1990 * This function locks given context, removes switch, unlock context and
1993 int ast_context_remove_switch2(struct ast_context *con, char *sw, char *data, char *registrar)
1995 struct ast_sw *i, *pi = NULL;
1997 if (ast_mutex_lock(&con->lock)) return -1;
2002 /* find our switch */
2003 if (!strcmp(i->name, sw) && !strcmp(i->data, data) &&
2004 (!strcmp(i->registrar, registrar) || !registrar)) {
2005 /* remove from list */
2009 con->alts = i->next;
2010 /* free switch and return */
2012 ast_mutex_unlock(&con->lock);
2019 /* we can't find the right switch */
2020 ast_mutex_unlock(&con->lock);
2025 * This functions lock contexts list, search for the right context,
2026 * call ast_context_remove_extension2, unlock contexts list and return.
2027 * In this function we are using
2029 int ast_context_remove_extension(char *context, char *extension, int priority, char *registrar)
2031 struct ast_context *c;
2033 if (ast_lock_contexts()) return -1;
2035 /* walk contexts ... */
2036 c = ast_walk_contexts(NULL);
2038 /* ... search for the right one ... */
2039 if (!strcmp(ast_get_context_name(c), context)) {
2040 /* ... remove extension ... */
2041 int ret = ast_context_remove_extension2(c, extension, priority,
2043 /* ... unlock contexts list and return */
2044 ast_unlock_contexts();
2047 c = ast_walk_contexts(c);
2050 /* we can't find the right context */
2051 ast_unlock_contexts();
2056 * When do you want to call this function, make sure that &conlock is locked,
2057 * because some process can handle with your *con context before you lock
2060 * This functionc locks given context, search for the right extension and
2061 * fires out all peer in this extensions with given priority. If priority
2062 * is set to 0, all peers are removed. After that, unlock context and
2065 int ast_context_remove_extension2(struct ast_context *con, char *extension, int priority, char *registrar)
2067 struct ast_exten *exten, *prev_exten = NULL;
2069 if (ast_mutex_lock(&con->lock)) return -1;
2071 /* go through all extensions in context and search the right one ... */
2075 /* look for right extension */
2076 if (!strcmp(exten->exten, extension) &&
2077 (!strcmp(exten->registrar, registrar) || !registrar)) {
2078 struct ast_exten *peer;
2080 /* should we free all peers in this extension? (priority == 0)? */
2081 if (priority == 0) {
2082 /* remove this extension from context list */
2084 prev_exten->next = exten->next;
2086 con->root = exten->next;
2088 /* fire out all peers */
2093 if (!peer->priority==PRIORITY_HINT)
2094 ast_remove_hint(peer);
2096 peer->datad(peer->data);
2102 ast_mutex_unlock(&con->lock);
2105 /* remove only extension with exten->priority == priority */
2106 struct ast_exten *previous_peer = NULL;
2110 /* is this our extension? */
2111 if (peer->priority == priority &&
2112 (!strcmp(peer->registrar, registrar) || !registrar)) {
2113 /* we are first priority extension? */
2114 if (!previous_peer) {
2115 /* exists previous extension here? */
2117 /* yes, so we must change next pointer in
2118 * previous connection to next peer
2121 prev_exten->next = peer->peer;
2122 peer->peer->next = exten->next;
2124 prev_exten->next = exten->next;
2126 /* no previous extension, we are first
2127 * extension, so change con->root ...
2130 con->root = peer->peer;
2132 con->root = exten->next;
2135 /* we are not first priority in extension */
2136 previous_peer->peer = peer->peer;
2139 /* now, free whole priority extension */
2140 if (peer->priority==PRIORITY_HINT)
2141 ast_remove_hint(peer);
2142 peer->datad(peer->data);
2145 ast_mutex_unlock(&con->lock);
2148 /* this is not right extension, skip to next peer */
2149 previous_peer = peer;
2154 ast_mutex_unlock(&con->lock);
2160 exten = exten->next;
2163 /* we can't find right extension */
2164 ast_mutex_unlock(&con->lock);
2169 int ast_register_application(char *app, int (*execute)(struct ast_channel *, void *), char *synopsis, char *description)
2171 struct ast_app *tmp, *prev, *cur;
2173 if (ast_mutex_lock(&applock)) {
2174 ast_log(LOG_ERROR, "Unable to lock application list\n");
2179 if (!strcasecmp(app, tmp->name)) {
2180 ast_log(LOG_WARNING, "Already have an application '%s'\n", app);
2181 ast_mutex_unlock(&applock);
2186 tmp = malloc(sizeof(struct ast_app));
2188 memset(tmp, 0, sizeof(struct ast_app));
2189 strncpy(tmp->name, app, sizeof(tmp->name)-1);
2190 tmp->execute = execute;
2191 tmp->synopsis = synopsis;
2192 tmp->description = description;
2193 /* Store in alphabetical order */
2197 if (strcasecmp(tmp->name, cur->name) < 0)
2203 tmp->next = prev->next;
2210 ast_log(LOG_WARNING, "Out of memory\n");
2211 ast_mutex_unlock(&applock);
2214 if (option_verbose > 1)
2215 ast_verbose( VERBOSE_PREFIX_2 "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps)));
2216 ast_mutex_unlock(&applock);
2220 int ast_register_switch(struct ast_switch *sw)
2222 struct ast_switch *tmp, *prev=NULL;
2223 if (ast_mutex_lock(&switchlock)) {
2224 ast_log(LOG_ERROR, "Unable to lock switch lock\n");
2229 if (!strcasecmp(tmp->name, sw->name))
2235 ast_mutex_unlock(&switchlock);
2236 ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name);
2244 ast_mutex_unlock(&switchlock);
2248 void ast_unregister_switch(struct ast_switch *sw)
2250 struct ast_switch *tmp, *prev=NULL;
2251 if (ast_mutex_lock(&switchlock)) {
2252 ast_log(LOG_ERROR, "Unable to lock switch lock\n");
2259 prev->next = tmp->next;
2261 switches = tmp->next;
2268 ast_mutex_unlock(&switchlock);
2272 * Help for CLI commands ...
2274 static char show_application_help[] =
2275 "Usage: show application <application> [<application> [<application> [...]]]\n"
2276 " Describes a particular application.\n";
2278 static char show_applications_help[] =
2279 "Usage: show applications\n"
2280 " List applications which are currently available.\n";
2282 static char show_dialplan_help[] =
2283 "Usage: show dialplan [exten@][context]\n"
2286 static char show_switches_help[] =
2287 "Usage: show switches\n"
2288 " Show registered switches\n";
2291 * IMPLEMENTATION OF CLI FUNCTIONS IS IN THE SAME ORDER AS COMMANDS HELPS
2296 * 'show application' CLI command implementation functions ...
2300 * There is a possibility to show informations about more than one
2301 * application at one time. You can type 'show application Dial Echo' and
2302 * you will see informations about these two applications ...
2304 static char *complete_show_application(char *line, char *word,
2310 /* try to lock applications list ... */
2311 if (ast_mutex_lock(&applock)) {
2312 ast_log(LOG_ERROR, "Unable to lock application list\n");
2316 /* ... walk all applications ... */
2319 /* ... check if word matches this application ... */
2320 if (!strncasecmp(word, a->name, strlen(word))) {
2321 /* ... if this is right app serve it ... */
2322 if (++which > state) {
2323 char *ret = strdup(a->name);
2324 ast_mutex_unlock(&applock);
2331 /* no application match */
2332 ast_mutex_unlock(&applock);
2336 static int handle_show_application(int fd, int argc, char *argv[])
2339 int n, app, no_registered_app = 1;
2342 if (argc < 3) return RESULT_SHOWUSAGE;
2344 /* try to lock applications list ... */
2345 if (ast_mutex_lock(&applock)) {
2346 ast_log(LOG_ERROR, "Unable to lock application list\n");
2350 /* ... go through all applications ... */
2353 /* ... compare this application name with all arguments given
2354 * to 'show application' command ... */
2355 for (app = 2; app < argc; app++) {
2356 if (!strcasecmp(a->name, argv[app])) {
2357 no_registered_app = 0;
2359 /* ... one of our applications, show info ...*/
2361 "\n -= Info about application '%s' =- \n\n"
2362 "[Synopsis]:\n %s\n\n"
2363 "[Description]:\n%s\n",
2365 a->synopsis ? a->synopsis : "Not available",
2366 a->description ? a-> description : "Not available");
2376 ast_mutex_unlock(&applock);
2378 /* we found at least one app? no? */
2379 if (no_registered_app) {
2380 ast_cli(fd, "Your application(s) is (are) not registered\n");
2381 return RESULT_FAILURE;
2384 return RESULT_SUCCESS;
2387 static int handle_show_switches(int fd, int argc, char *argv[])
2389 struct ast_switch *sw;
2391 ast_cli(fd, "There are no registered alternative switches\n");
2392 return RESULT_SUCCESS;
2394 /* ... we have applications ... */
2395 ast_cli(fd, "\n -= Registered Asterisk Alternative Switches =-\n");
2396 if (ast_mutex_lock(&switchlock)) {
2397 ast_log(LOG_ERROR, "Unable to lock switches\n");
2402 ast_cli(fd, "%s: %s\n", sw->name, sw->description);
2405 ast_mutex_unlock(&switchlock);
2406 return RESULT_SUCCESS;
2410 * 'show applications' CLI command implementation functions ...
2412 static int handle_show_applications(int fd, int argc, char *argv[])
2416 /* try to lock applications list ... */
2417 if (ast_mutex_lock(&applock)) {
2418 ast_log(LOG_ERROR, "Unable to lock application list\n");
2422 /* ... go to first application ... */
2425 /* ... have we got at least one application (first)? no? */
2427 ast_cli(fd, "There is no registered applications\n");
2428 ast_mutex_unlock(&applock);
2432 /* ... we have applications ... */
2433 ast_cli(fd, "\n -= Registered Asterisk Applications =-\n");
2435 /* ... go through all applications ... */
2437 /* ... show informations about applications ... */
2438 ast_cli(fd," %15s: %s\n",
2440 a->synopsis ? a->synopsis : "<Synopsis not available>");
2444 /* ... unlock and return */
2445 ast_mutex_unlock(&applock);
2447 return RESULT_SUCCESS;
2451 * 'show dialplan' CLI command implementation functions ...
2453 static char *complete_show_dialplan_context(char *line, char *word, int pos,
2456 struct ast_context *c;
2459 /* we are do completion of [exten@]context on second position only */
2460 if (pos != 2) return NULL;
2462 /* try to lock contexts list ... */
2463 if (ast_lock_contexts()) {
2464 ast_log(LOG_ERROR, "Unable to lock context list\n");
2468 /* ... walk through all contexts ... */
2469 c = ast_walk_contexts(NULL);
2471 /* ... word matches context name? yes? ... */
2472 if (!strncasecmp(word, ast_get_context_name(c), strlen(word))) {
2473 /* ... for serve? ... */
2474 if (++which > state) {
2475 /* ... yes, serve this context name ... */
2476 char *ret = strdup(ast_get_context_name(c));
2477 ast_unlock_contexts();
2481 c = ast_walk_contexts(c);
2484 /* ... unlock and return */
2485 ast_unlock_contexts();
2489 static int handle_show_dialplan(int fd, int argc, char *argv[])
2491 struct ast_context *c;
2492 char *exten = NULL, *context = NULL;
2493 int context_existence = 0, extension_existence = 0;
2495 if (argc != 3 && argc != 2) return -1;
2497 /* we obtain [exten@]context? if yes, split them ... */
2499 char *splitter = argv[2];
2500 /* is there a '@' character? */
2501 if (strchr(argv[2], '@')) {
2502 /* yes, split into exten & context ... */
2503 exten = strsep(&splitter, "@");
2506 /* check for length and change to NULL if !strlen() */
2507 if (!strlen(exten)) exten = NULL;
2508 if (!strlen(context)) context = NULL;
2511 /* no '@' char, only context given */
2513 if (!strlen(context)) context = NULL;
2517 /* try to lock contexts */
2518 if (ast_lock_contexts()) {
2519 ast_log(LOG_WARNING, "Failed to lock contexts list\n");
2520 return RESULT_FAILURE;
2523 /* walk all contexts ... */
2524 c = ast_walk_contexts(NULL);
2526 /* show this context? */
2528 !strcmp(ast_get_context_name(c), context)) {
2529 context_existence = 1;
2531 /* try to lock context before walking in ... */
2532 if (!ast_lock_context(c)) {
2533 struct ast_exten *e;
2534 struct ast_include *i;
2535 struct ast_ignorepat *ip;
2537 char buf[256], buf2[256];
2538 int context_info_printed = 0;
2540 /* are we looking for exten too? if yes, we print context
2541 * if we our extension only
2544 ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
2545 ast_get_context_name(c), ast_get_context_registrar(c));
2546 context_info_printed = 1;
2549 /* walk extensions ... */
2550 e = ast_walk_context_extensions(c, NULL);
2552 struct ast_exten *p;
2554 /* looking for extension? is this our extension? */
2556 strcmp(ast_get_extension_name(e), exten))
2558 /* we are looking for extension and it's not our
2559 * extension, so skip to next extension */
2560 e = ast_walk_context_extensions(c, e);
2564 extension_existence = 1;
2566 /* may we print context info? */
2567 if (!context_info_printed) {
2568 ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
2569 ast_get_context_name(c),
2570 ast_get_context_registrar(c));
2571 context_info_printed = 1;
2574 /* write extension name and first peer */
2575 bzero(buf, sizeof(buf));
2576 snprintf(buf, sizeof(buf), "'%s' =>",
2577 ast_get_extension_name(e));
2579 snprintf(buf2, sizeof(buf2),
2581 ast_get_extension_priority(e),
2582 ast_get_extension_app(e),
2583 (char *)ast_get_extension_app_data(e));
2585 ast_cli(fd, " %-17s %-45s [%s]\n", buf, buf2,
2586 ast_get_extension_registrar(e));
2588 /* walk next extension peers */
2589 p = ast_walk_extension_priorities(e, e);
2591 bzero((void *)buf2, sizeof(buf2));
2593 snprintf(buf2, sizeof(buf2),
2595 ast_get_extension_priority(p),
2596 ast_get_extension_app(p),
2597 (char *)ast_get_extension_app_data(p));
2599 ast_cli(fd," %-17s %-45s [%s]\n",
2601 ast_get_extension_registrar(p));
2603 p = ast_walk_extension_priorities(e, p);
2605 e = ast_walk_context_extensions(c, e);
2608 /* include & ignorepat we all printing if we are not
2609 * looking for exact extension
2612 if (ast_walk_context_extensions(c, NULL))
2615 /* walk included and write info ... */
2616 i = ast_walk_context_includes(c, NULL);
2618 bzero(buf, sizeof(buf));
2619 snprintf(buf, sizeof(buf), "'%s'",
2620 ast_get_include_name(i));
2621 ast_cli(fd, " Include => %-45s [%s]\n",
2622 buf, ast_get_include_registrar(i));
2623 i = ast_walk_context_includes(c, i);
2626 /* walk ignore patterns and write info ... */
2627 ip = ast_walk_context_ignorepats(c, NULL);
2629 bzero(buf, sizeof(buf));
2630 snprintf(buf, sizeof(buf), "'%s'",
2631 ast_get_ignorepat_name(ip));
2632 ast_cli(fd, " Ignore pattern => %-45s [%s]\n",
2633 buf, ast_get_ignorepat_registrar(ip));
2634 ip = ast_walk_context_ignorepats(c, ip);
2636 sw = ast_walk_context_switches(c, NULL);
2638 bzero(buf, sizeof(buf));
2639 snprintf(buf, sizeof(buf), "'%s/%s'",
2640 ast_get_switch_name(sw),
2641 ast_get_switch_data(sw));
2642 ast_cli(fd, " Alt. Switch => %-45s [%s]\n",
2643 buf, ast_get_switch_registrar(sw));
2644 sw = ast_walk_context_switches(c, sw);
2648 ast_unlock_context(c);
2650 /* if we print something in context, make an empty line */
2651 if (context_info_printed) ast_cli(fd, "\n");
2654 c = ast_walk_contexts(c);
2656 ast_unlock_contexts();
2658 /* check for input failure and throw some error messages */
2659 if (context && !context_existence) {
2660 ast_cli(fd, "There is no existence of '%s' context\n",
2662 return RESULT_FAILURE;
2665 if (exten && !extension_existence) {
2667 ast_cli(fd, "There is no existence of %s@%s extension\n",
2671 "There is no existence of '%s' extension in all contexts\n",
2673 return RESULT_FAILURE;
2677 return RESULT_SUCCESS;
2681 * CLI entries for upper commands ...
2683 static struct ast_cli_entry show_applications_cli =
2684 { { "show", "applications", NULL },
2685 handle_show_applications, "Shows registered applications",
2686 show_applications_help };
2688 static struct ast_cli_entry show_application_cli =
2689 { { "show", "application", NULL },
2690 handle_show_application, "Describe a specific application",
2691 show_application_help, complete_show_application };
2693 static struct ast_cli_entry show_dialplan_cli =
2694 { { "show", "dialplan", NULL },
2695 handle_show_dialplan, "Show dialplan",
2696 show_dialplan_help, complete_show_dialplan_context };
2698 static struct ast_cli_entry show_switches_cli =
2699 { { "show", "switches", NULL },
2700 handle_show_switches, "Show alternative switches",
2701 show_switches_help, NULL };
2703 int ast_unregister_application(char *app) {
2704 struct ast_app *tmp, *tmpl = NULL;
2705 if (ast_mutex_lock(&applock)) {
2706 ast_log(LOG_ERROR, "Unable to lock application list\n");
2711 if (!strcasecmp(app, tmp->name)) {
2713 tmpl->next = tmp->next;
2716 if (option_verbose > 1)
2717 ast_verbose( VERBOSE_PREFIX_2 "Unregistered application '%s'\n", tmp->name);
2718 ast_mutex_unlock(&applock);
2724 ast_mutex_unlock(&applock);
2728 struct ast_context *ast_context_create(struct ast_context **extcontexts, char *name, char *registrar)
2730 struct ast_context *tmp, **local_contexts;
2732 local_contexts = &contexts;
2733 ast_mutex_lock(&conlock);
2735 local_contexts = extcontexts;
2737 tmp = *local_contexts;
2739 if (!strcasecmp(tmp->name, name)) {
2740 ast_mutex_unlock(&conlock);
2741 ast_log(LOG_WARNING, "Tried to register context '%s', already in use\n", name);
2743 ast_mutex_unlock(&conlock);
2748 tmp = malloc(sizeof(struct ast_context));
2750 memset(tmp, 0, sizeof(struct ast_context));
2751 ast_mutex_init(&tmp->lock);
2752 strncpy(tmp->name, name, sizeof(tmp->name)-1);
2754 tmp->registrar = registrar;
2755 tmp->next = *local_contexts;
2756 tmp->includes = NULL;
2757 tmp->ignorepats = NULL;
2758 *local_contexts = tmp;
2760 ast_log(LOG_DEBUG, "Registered context '%s'\n", tmp->name);
2761 else if (option_verbose > 2)
2762 ast_verbose( VERBOSE_PREFIX_3 "Registered extension context '%s'\n", tmp->name);
2764 ast_log(LOG_WARNING, "Out of memory\n");
2767 ast_mutex_unlock(&conlock);
2771 void __ast_context_destroy(struct ast_context *con, char *registrar, int lock);
2773 void ast_merge_contexts_and_delete(struct ast_context **extcontexts, char *registrar) {
2774 struct ast_context *tmp, *lasttmp = NULL;
2776 ast_mutex_lock(&conlock);
2778 __ast_context_destroy(NULL,registrar,0);
2785 __ast_context_destroy(tmp,tmp->registrar,0);
2791 lasttmp->next = contexts;
2792 contexts = *extcontexts;
2793 *extcontexts = NULL;
2795 ast_log(LOG_WARNING, "Requested contexts didn't get merged\n");
2796 ast_mutex_unlock(&conlock);
2802 * EBUSY - can't lock
2803 * ENOENT - no existence of context
2805 int ast_context_add_include(char *context, char *include, char *registrar)
2807 struct ast_context *c;
2809 if (ast_lock_contexts()) {
2814 /* walk contexts ... */
2815 c = ast_walk_contexts(NULL);
2817 /* ... search for the right one ... */
2818 if (!strcmp(ast_get_context_name(c), context)) {
2819 int ret = ast_context_add_include2(c, include, registrar);
2820 /* ... unlock contexts list and return */
2821 ast_unlock_contexts();
2824 c = ast_walk_contexts(c);
2827 /* we can't find the right context */
2828 ast_unlock_contexts();
2836 while(*c && (*c != '|')) c++; \
2837 if (*c) { *c = '\0'; c++; } else c = NULL; \
2840 static void get_timerange(struct ast_include *i, char *times)
2848 //start disabling all times, fill the fields with 0's, as they may contain garbage
2849 memset(i->minmask, 0, sizeof(i->minmask));
2851 /* Star is all times */
2852 if (!strlen(times) || !strcmp(times, "*")) {
2854 i->minmask[x] = (1 << 30) - 1;
2857 /* Otherwise expect a range */
2858 e = strchr(times, '-');
2860 ast_log(LOG_WARNING, "Time range is not valid. Assuming no time.\n");
2865 while(*e && !isdigit(*e)) e++;
2867 ast_log(LOG_WARNING, "Invalid time range. Assuming no time.\n");
2870 if (sscanf(times, "%d:%d", &s1, &s2) != 2) {
2871 ast_log(LOG_WARNING, "%s isn't a time. Assuming no time.\n", times);
2874 if (sscanf(e, "%d:%d", &e1, &e2) != 2) {
2875 ast_log(LOG_WARNING, "%s isn't a time. Assuming no time.\n", e);
2878 s1 = s1 * 30 + s2/2;
2879 if ((s1 < 0) || (s1 >= 24*30)) {
2880 ast_log(LOG_WARNING, "%s isn't a valid star time. Assuming no time.\n", times);
2883 e1 = e1 * 30 + e2/2;
2884 if ((e1 < 0) || (e2 >= 24*30)) {
2885 ast_log(LOG_WARNING, "%s isn't a valid start time. Assuming no time.\n", times);
2888 /* Go through the time and enable each appropriate bit */
2889 for (x=s1;x != e1;x = (x + 1) % (24 * 30)) {
2890 i->minmask[x/30] |= (1 << (x % 30));
2892 /* Do the last one */
2893 i->minmask[x/30] |= (1 << (x % 30));
2898 static char *days[] =
2909 static unsigned int get_dow(char *dow)
2912 /* The following line is coincidence, really! */
2915 /* Check for all days */
2916 if (!strlen(dow) || !strcmp(dow, "*"))
2917 return (1 << 7) - 1;
2918 /* Get start and ending days */
2919 c = strchr(dow, '-');
2925 /* Find the start */
2927 while((s < 7) && strcasecmp(dow, days[s])) s++;
2929 ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", dow);
2934 while((e < 7) && strcasecmp(c, days[e])) e++;
2936 ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", c);
2942 for (x=s;x!=e;x = (x + 1) % 7) {
2950 static unsigned int get_day(char *day)
2953 /* The following line is coincidence, really! */
2956 /* Check for all days */
2957 if (!strlen(day) || !strcmp(day, "*")) {
2958 mask = (1 << 30) + ((1 << 30) - 1);
2961 /* Get start and ending days */
2962 c = strchr(day, '-');
2967 /* Find the start */
2968 if (sscanf(day, "%d", &s) != 1) {
2969 ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", day);
2972 if ((s < 1) || (s > 31)) {
2973 ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", day);
2978 if (sscanf(c, "%d", &e) != 1) {
2979 ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", c);
2982 if ((e < 1) || (e > 31)) {
2983 ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", c);
2990 for (x=s;x!=e;x = (x + 1) % 31) {
2997 static char *months[] =
3013 static unsigned int get_month(char *mon)
3016 /* The following line is coincidence, really! */
3019 /* Check for all days */
3020 if (!strlen(mon) || !strcmp(mon, "*"))
3021 return (1 << 12) - 1;
3022 /* Get start and ending days */
3023 c = strchr(mon, '-');
3028 /* Find the start */
3030 while((s < 12) && strcasecmp(mon, months[s])) s++;
3032 ast_log(LOG_WARNING, "Invalid month '%s', assuming none\n", mon);
3037 while((e < 12) && strcasecmp(mon, months[e])) e++;
3039 ast_log(LOG_WARNING, "Invalid month '%s', assuming none\n", c);
3045 for (x=s;x!=e;x = (x + 1) % 12) {
3053 static void build_timing(struct ast_include *i, char *info)
3056 /* Check for empty just in case */
3060 /* Assume everything except time */
3061 i->monthmask = (1 << 12) - 1;
3062 i->daymask = (1 << 30) - 1 + (1 << 30);
3063 i->dowmask = (1 << 7) - 1;
3064 /* Avoid using str tok */
3066 /* Info has the time range, start with that */
3067 get_timerange(i, info);
3072 /* Now check for day of week */
3073 i->dowmask = get_dow(info);
3079 /* Now check for the day of the month */
3080 i->daymask = get_day(info);
3085 /* And finally go for the month */
3086 i->monthmask = get_month(info);
3091 * ENOMEM - out of memory
3092 * EBUSY - can't lock
3093 * EEXIST - already included
3094 * EINVAL - there is no existence of context for inclusion
3096 int ast_context_add_include2(struct ast_context *con, char *value,
3099 struct ast_include *new_include;
3101 struct ast_include *i, *il = NULL; /* include, include_last */
3103 /* allocate new include structure ... */
3104 if (!(new_include = malloc(sizeof(struct ast_include)))) {
3105 ast_log(LOG_WARNING, "Out of memory\n");
3110 /* ... fill in this structure ... */
3111 memset(new_include, 0, sizeof(struct ast_include));
3112 strncpy(new_include->name, value, sizeof(new_include->name)-1);
3113 strncpy(new_include->rname, value, sizeof(new_include->rname)-1);
3114 c = new_include->rname;
3115 /* Strip off timing info */
3116 while(*c && (*c != '|')) c++;
3117 /* Process if it's there */
3119 build_timing(new_include, c+1);
3122 new_include->next = NULL;
3123 new_include->registrar = registrar;
3125 /* ... try to lock this context ... */
3126 if (ast_mutex_lock(&con->lock)) {
3132 /* ... go to last include and check if context is already included too... */
3135 if (!strcasecmp(i->name, new_include->name)) {
3137 ast_mutex_unlock(&con->lock);
3145 /* ... include new context into context list, unlock, return */
3147 il->next = new_include;
3149 con->includes = new_include;
3150 if (option_verbose > 2)
3151 ast_verbose(VERBOSE_PREFIX_3 "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con));
3152 ast_mutex_unlock(&con->lock);
3159 * EBUSY - can't lock
3160 * ENOENT - no existence of context
3162 int ast_context_add_switch(char *context, char *sw, char *data, char *registrar)
3164 struct ast_context *c;
3166 if (ast_lock_contexts()) {
3171 /* walk contexts ... */
3172 c = ast_walk_contexts(NULL);
3174 /* ... search for the right one ... */
3175 if (!strcmp(ast_get_context_name(c), context)) {
3176 int ret = ast_context_add_switch2(c, sw, data, registrar);
3177 /* ... unlock contexts list and return */
3178 ast_unlock_contexts();
3181 c = ast_walk_contexts(c);
3184 /* we can't find the right context */
3185 ast_unlock_contexts();
3192 * ENOMEM - out of memory
3193 * EBUSY - can't lock
3194 * EEXIST - already included
3195 * EINVAL - there is no existence of context for inclusion
3197 int ast_context_add_switch2(struct ast_context *con, char *value,
3198 char *data, char *registrar)
3200 struct ast_sw *new_sw;
3201 struct ast_sw *i, *il = NULL; /* sw, sw_last */
3203 /* allocate new sw structure ... */
3204 if (!(new_sw = malloc(sizeof(struct ast_sw)))) {
3205 ast_log(LOG_WARNING, "Out of memory\n");
3210 /* ... fill in this structure ... */
3211 memset(new_sw, 0, sizeof(struct ast_sw));
3212 strncpy(new_sw->name, value, sizeof(new_sw->name)-1);
3214 strncpy(new_sw->data, data, sizeof(new_sw->data)-1);
3216 strncpy(new_sw->data, "", sizeof(new_sw->data)-1);
3217 new_sw->next = NULL;
3218 new_sw->registrar = registrar;
3220 /* ... try to lock this context ... */
3221 if (ast_mutex_lock(&con->lock)) {
3227 /* ... go to last sw and check if context is already swd too... */
3230 if (!strcasecmp(i->name, new_sw->name)) {
3232 ast_mutex_unlock(&con->lock);
3240 /* ... sw new context into context list, unlock, return */
3245 if (option_verbose > 2)
3246 ast_verbose(VERBOSE_PREFIX_3 "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con));
3247 ast_mutex_unlock(&con->lock);
3253 * EBUSY - can't lock
3254 * ENOENT - there is not context existence
3256 int ast_context_remove_ignorepat(char *context, char *ignorepat, char *registrar)
3258 struct ast_context *c;
3260 if (ast_lock_contexts()) {
3265 c = ast_walk_contexts(NULL);
3267 if (!strcmp(ast_get_context_name(c), context)) {
3268 int ret = ast_context_remove_ignorepat2(c, ignorepat, registrar);
3269 ast_unlock_contexts();
3272 c = ast_walk_contexts(c);
3275 ast_unlock_contexts();
3280 int ast_context_remove_ignorepat2(struct ast_context *con, char *ignorepat, char *registrar)
3282 struct ast_ignorepat *ip, *ipl = NULL;
3284 if (ast_mutex_lock(&con->lock)) {
3289 ip = con->ignorepats;
3291 if (!strcmp(ip->pattern, ignorepat) &&
3292 (registrar == ip->registrar || !registrar)) {
3294 ipl->next = ip->next;
3297 con->ignorepats = ip->next;
3300 ast_mutex_unlock(&con->lock);
3303 ipl = ip; ip = ip->next;
3306 ast_mutex_unlock(&con->lock);
3312 * EBUSY - can't lock
3313 * ENOENT - there is no existence of context
3315 int ast_context_add_ignorepat(char *con, char *value, char *registrar)
3317 struct ast_context *c;
3319 if (ast_lock_contexts()) {
3324 c = ast_walk_contexts(NULL);
3326 if (!strcmp(ast_get_context_name(c), con)) {
3327 int ret = ast_context_add_ignorepat2(c, value, registrar);
3328 ast_unlock_contexts();
3331 c = ast_walk_contexts(c);
3334 ast_unlock_contexts();
3339 int ast_context_add_ignorepat2(struct ast_context *con, char *value, char *registrar)
3341 struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL;
3342 ignorepat = malloc(sizeof(struct ast_ignorepat));
3344 ast_log(LOG_WARNING, "Out of memory\n");
3348 memset(ignorepat, 0, sizeof(struct ast_ignorepat));
3349 strncpy(ignorepat->pattern, value, sizeof(ignorepat->pattern)-1);
3350 ignorepat->next = NULL;
3351 ignorepat->registrar = registrar;
3352 ast_mutex_lock(&con->lock);
3353 ignorepatc = con->ignorepats;
3355 ignorepatl = ignorepatc;
3356 if (!strcasecmp(ignorepatc->pattern, value)) {
3358 ast_mutex_unlock(&con->lock);
3362 ignorepatc = ignorepatc->next;
3365 ignorepatl->next = ignorepat;
3367 con->ignorepats = ignorepat;
3368 ast_mutex_unlock(&con->lock);
3373 int ast_ignore_pattern(char *context, char *pattern)
3375 struct ast_context *con;
3376 struct ast_ignorepat *pat;
3377 con = ast_context_find(context);
3379 pat = con->ignorepats;
3381 if (ast_extension_match(pat->pattern, pattern))
3390 * EBUSY - can't lock
3391 * ENOENT - no existence of context
3394 int ast_add_extension(char *context, int replace, char *extension, int priority, char *callerid,
3395 char *application, void *data, void (*datad)(void *), char *registrar)
3397 struct ast_context *c;
3399 if (ast_lock_contexts()) {
3404 c = ast_walk_contexts(NULL);
3406 if (!strcmp(context, ast_get_context_name(c))) {
3407 int ret = ast_add_extension2(c, replace, extension, priority, callerid,
3408 application, data, datad, registrar);
3409 ast_unlock_contexts();
3412 c = ast_walk_contexts(c);
3415 ast_unlock_contexts();
3420 int ast_async_goto(struct ast_channel *chan, char *context, char *exten, int priority, int needlock)
3424 ast_mutex_lock(&chan->lock);
3426 /* This channel is currently in the PBX */
3427 if (context && strlen(context))
3428 strncpy(chan->context, context, sizeof(chan->context) - 1);
3429 if (exten && strlen(exten))
3430 strncpy(chan->exten, exten, sizeof(chan->context) - 1);
3432 chan->priority = priority - 1;
3433 ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO);
3435 ast_mutex_unlock(&chan->lock);
3437 /* In order to do it when the channel doesn't really exist within
3438 the PBX, we have to make a new channel, masquerade, and start the PBX
3439 at the new location */
3440 struct ast_channel *tmpchan;
3441 struct ast_frame *f;
3442 tmpchan = ast_channel_alloc(0);
3444 snprintf(tmpchan->name, sizeof(tmpchan->name), "AsyncGoto/%s", chan->name);
3445 ast_setstate(tmpchan, chan->_state);
3446 /* Make formats okay */
3447 tmpchan->readformat = chan->readformat;
3448 tmpchan->writeformat = chan->writeformat;
3449 /* Setup proper location */
3450 if (context && strlen(context))
3451 strncpy(tmpchan->context, context, sizeof(tmpchan->context) - 1);
3453 strncpy(tmpchan->context, chan->context, sizeof(tmpchan->context) - 1);
3454 if (exten && strlen(exten))
3455 strncpy(tmpchan->exten, exten, sizeof(tmpchan->exten) - 1);
3457 strncpy(tmpchan->exten, chan->exten, sizeof(tmpchan->exten) - 1);
3459 tmpchan->priority = priority;
3461 tmpchan->priority = chan->priority;
3463 ast_mutex_unlock(&chan->lock);
3465 /* Masquerade into temp channel */
3466 ast_channel_masquerade(tmpchan, chan);
3468 /* Make the masquerade happen by reading a frame from the tmp channel */
3469 f = ast_read(tmpchan);
3472 /* Start the PBX going on our stolen channel */
3473 if (ast_pbx_start(tmpchan)) {
3474 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name);
3475 ast_hangup(tmpchan);
3481 ast_mutex_unlock(&chan->lock);
3487 int ast_async_goto_by_name(char *channame, char *context, char *exten, int priority)
3489 struct ast_channel *chan;
3490 chan = ast_channel_walk(NULL);
3492 if (!strcasecmp(channame, chan->name))
3494 chan = ast_channel_walk(chan);
3497 return ast_async_goto(chan, context, exten, priority, 1);
3501 static void ext_strncpy(char *dst, char *src, int len)
3504 while(*src && (count < len - 1)) {
3507 //otherwise exten => [a-b],1,... doesn't work
3522 * EBUSY - can't lock
3523 * EEXIST - extension with the same priority exist and no replace is set
3526 int ast_add_extension2(struct ast_context *con,
3527 int replace, char *extension, int priority, char *callerid,
3528 char *application, void *data, void (*datad)(void *),
3532 #define LOG do { if (option_debug) {\
3533 if (tmp->matchcid) { \
3534 ast_log(LOG_DEBUG, "Added extension '%s' priority %d (CID match '%s') to %s\n", tmp->exten, tmp->priority, tmp->cidmatch, con->name); \
3536 ast_log(LOG_DEBUG, "Added extension '%s' priority %d to %s\n", tmp->exten, tmp->priority, con->name); \
3538 } else if (option_verbose > 2) { \
3539 if (tmp->matchcid) { \
3540 ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d (CID match '%s')to %s\n", tmp->exten, tmp->priority, tmp->cidmatch, con->name); \
3542 ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d to %s\n", tmp->exten, tmp->priority, con->name); \
3547 * This is a fairly complex routine. Different extensions are kept
3548 * in order by the extension number. Then, extensions of different
3549 * priorities (same extension) are kept in a list, according to the
3552 struct ast_exten *tmp, *e, *el = NULL, *ep = NULL;
3554 /* Be optimistic: Build the extension structure first */
3555 tmp = malloc(sizeof(struct ast_exten));
3557 memset(tmp, 0, sizeof(struct ast_exten));
3558 ext_strncpy(tmp->exten, extension, sizeof(tmp->exten));
3559 tmp->priority = priority;
3561 ext_strncpy(tmp->cidmatch, callerid, sizeof(tmp->cidmatch));
3564 strcpy(tmp->cidmatch, "");
3567 strncpy(tmp->app, application, sizeof(tmp->app)-1);
3571 tmp->registrar = registrar;
3575 ast_log(LOG_WARNING, "Out of memory\n");
3579 if (ast_mutex_lock(&con->lock)) {
3581 /* And properly destroy the data */
3583 ast_log(LOG_WARNING, "Failed to lock context '%s'\n", con->name);
3589 res= strcasecmp(e->exten, extension);
3591 if (!e->matchcid && !tmp->matchcid)
3593 else if (tmp->matchcid && !e->matchcid)
3595 else if (e->matchcid && !tmp->matchcid)
3598 res = strcasecmp(e->cidmatch, tmp->cidmatch);
3601 /* We have an exact match, now we find where we are
3602 and be sure there's no duplicates */
3604 if (e->priority == tmp->priority) {
3605 /* Can't have something exactly the same. Is this a
3606 replacement? If so, replace, otherwise, bonk. */
3609 /* We're in the peer list, insert ourselves */
3611 tmp->peer = e->peer;
3613 /* We're the first extension. Take over e's functions */
3615 tmp->next = e->next;
3616 tmp->peer = e->peer;
3618 /* We're the very first extension. */