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 'fr/demo-\n"
310 "congrats' 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);
865 } else if (c && !strcmp(var, "HANGUPCAUSE")) {
866 snprintf(workspace, workspacelen -1, "%i", c->hangupcause);
870 AST_LIST_TRAVERSE(headp,variables,entries) {
872 ast_log(LOG_WARNING,"Comparing variable '%s' with '%s'\n",var,ast_var_name(variables));
874 if (strcasecmp(ast_var_name(variables),var)==0) {
875 *ret=ast_var_value(variables);
877 strncpy(workspace, *ret, workspacelen - 1);
885 AST_LIST_TRAVERSE(&globals,variables,entries) {
887 ast_log(LOG_WARNING,"Comparing variable '%s' with '%s'\n",var,ast_var_name(variables));
889 if (strcasecmp(ast_var_name(variables),var)==0) {
890 *ret=ast_var_value(variables);
892 strncpy(workspace, *ret, workspacelen - 1);
900 int len_env=strlen("ENV(");
901 if (len > (len_env+1) && !strncasecmp(var,"ENV(",len_env) && !strcmp(var+len-1,")")) {
903 strncpy(cp3, var, sizeof(cp3) - 1);
905 *ret=getenv(cp3+len_env);
907 strncpy(workspace, *ret, workspacelen - 1);
912 if (!(*ret) && !strncasecmp(var,"LEN(",4)) {
915 if (len > (len_len+1) && !strncasecmp(var,"LEN(",len_len) && strchr(var+len_len+2,')')) {
917 strncpy(cp3, var, sizeof(cp3) - 1);
918 cp3[len-len_len-1]='\0';
919 sprintf(workspace,"%d",strlen(cp3));
921 } else ast_log(LOG_NOTICE, "Wrong use of LEN(VARIABLE)\n");
926 void pbx_substitute_variables_helper(struct ast_channel *c,const char *cp1,char *cp2,int count)
929 const char *tmp, *whereweare;
932 char ltmp[256], var[256];
933 char *nextvar, *nextexp;
935 int pos, brackets, needsub, len;
937 /* Substitutes variables into cp2, based on string cp1, and assuming cp2 to be
940 while(strlen(whereweare) && count) {
941 /* Assume we're copying the whole remaining string */
942 pos = strlen(whereweare);
944 /* Look for a variable */
945 nextvar = strstr(whereweare, "${");
947 nextexp = strstr(whereweare, "$[");
949 if (nextvar && nextexp) {
950 if (nextvar < nextexp)
956 /* If there is one, we only go that far */
958 pos = nextvar - whereweare;
960 pos = nextexp - whereweare;
962 /* Can't copy more than 'count' bytes */
966 /* Copy that many bytes */
967 memcpy(cp2, whereweare, pos);
974 /* We have a variable. Find the start and end, and determine
975 if we are going to have to recursively call ourselves on the
977 vars = vare = nextvar + 2;
981 /* Find the end of it */
982 while(brackets && *vare) {
983 if ((vare[0] == '$') && (vare[1] == '{')) {
986 } else if (vare[0] == '}') {
988 } else if ((vare[0] == '$') && (vare[1] == '['))
993 ast_log(LOG_NOTICE, "Error in extension logic (missing '}')\n");
994 len = vare - vars - 1;
996 /* Skip totally over variable name */
997 whereweare += ( len + 3);
999 /* Store variable name (and truncate) */
1000 memset(var, 0, sizeof(var));
1001 strncpy(var, vars, sizeof(var) - 1);
1004 /* Substitute if necessary */
1006 memset(ltmp, 0, sizeof(ltmp));
1007 pbx_substitute_variables_helper(c, var, ltmp, sizeof(ltmp) - 1);
1013 /* Retrieve variable value */
1014 strcpy(workspace, "");
1015 pbx_substitute_variables_temp(c,vars,&cp4, workspace, sizeof(workspace));
1017 length = strlen(cp4);
1020 memcpy(cp2, cp4, length);
1025 } else if (nextexp) {
1026 /* We have an expression. Find the start and end, and determine
1027 if we are going to have to recursively call ourselves on the
1029 vars = vare = nextexp + 2;
1033 /* Find the end of it */
1034 while(brackets && *vare) {
1035 if ((vare[0] == '$') && (vare[1] == '[')) {
1038 } else if (vare[0] == ']') {
1040 } else if ((vare[0] == '$') && (vare[1] == '{'))
1045 ast_log(LOG_NOTICE, "Error in extension logic (missing ']')\n");
1046 len = vare - vars - 1;
1048 /* Skip totally over variable name */
1049 whereweare += ( len + 3);
1051 /* Store variable name (and truncate) */
1052 memset(var, 0, sizeof(var));
1053 strncpy(var, vars, sizeof(var) - 1);
1056 /* Substitute if necessary */
1058 memset(ltmp, 0, sizeof(ltmp));
1059 pbx_substitute_variables_helper(c, var, ltmp, sizeof(ltmp) - 1);
1065 /* Evaluate expression */
1066 cp4 = ast_expr(vars);
1068 ast_log(LOG_DEBUG, "Expression is '%s'\n", cp4);
1071 length = strlen(cp4);
1074 memcpy(cp2, cp4, length);
1085 static void pbx_substitute_variables(char *passdata, int datalen, struct ast_channel *c, struct ast_exten *e) {
1087 memset(passdata, 0, datalen);
1089 /* No variables or expressions in e->data, so why scan it? */
1090 if (!strstr(e->data,"${") && !strstr(e->data,"$[")) {
1091 strncpy(passdata, e->data, datalen - 1);
1092 passdata[datalen-1] = '\0';
1096 pbx_substitute_variables_helper(c,e->data,passdata, datalen - 1);
1099 static int pbx_extension_helper(struct ast_channel *c, char *context, char *exten, int priority, char *callerid, int action)
1101 struct ast_exten *e;
1102 struct ast_app *app;
1103 struct ast_switch *sw;
1108 char *incstack[AST_PBX_MAX_STACK];
1114 if (ast_mutex_lock(&conlock)) {
1115 ast_log(LOG_WARNING, "Unable to obtain lock\n");
1116 if ((action == HELPER_EXISTS) || (action == HELPER_CANMATCH) || (action == HELPER_MATCHMORE))
1121 e = pbx_find_extension(c, context, exten, priority, callerid, action, incstack, &stacklen, &status, &sw, &data);
1124 case HELPER_CANMATCH:
1125 ast_mutex_unlock(&conlock);
1128 ast_mutex_unlock(&conlock);
1130 case HELPER_MATCHMORE:
1131 ast_mutex_unlock(&conlock);
1137 app = pbx_findapp(e->app);
1138 ast_mutex_unlock(&conlock);
1140 if (c->context != context)
1141 strncpy(c->context, context, sizeof(c->context)-1);
1142 if (c->exten != exten)
1143 strncpy(c->exten, exten, sizeof(c->exten)-1);
1144 c->priority = priority;
1145 pbx_substitute_variables(passdata, sizeof(passdata), c, e);
1147 ast_log(LOG_DEBUG, "Launching '%s'\n", app->name);
1148 else if (option_verbose > 2)
1149 ast_verbose( VERBOSE_PREFIX_3 "Executing %s(\"%s\", \"%s\") %s\n",
1150 term_color(tmp, app->name, COLOR_BRCYAN, 0, sizeof(tmp)),
1151 term_color(tmp2, c->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)),
1152 term_color(tmp3, (strlen(passdata) ? (char *)passdata : ""), COLOR_BRMAGENTA, 0, sizeof(tmp3)),
1153 (newstack ? "in new stack" : "in same stack"));
1154 res = pbx_exec(c, app, passdata, newstack);
1157 ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority);
1161 ast_log(LOG_WARNING, "Huh (%d)?\n", action); return -1;
1165 case HELPER_CANMATCH:
1166 ast_mutex_unlock(&conlock);
1169 ast_mutex_unlock(&conlock);
1171 case HELPER_MATCHMORE:
1172 ast_mutex_unlock(&conlock);
1178 ast_mutex_unlock(&conlock);
1180 res = sw->exec(c, context, exten, priority, callerid, newstack, data);
1182 ast_log(LOG_WARNING, "No execution engine for switch %s\n", sw->name);
1187 ast_log(LOG_WARNING, "Huh (%d)?\n", action);
1191 ast_mutex_unlock(&conlock);
1193 case STATUS_NO_CONTEXT:
1194 if ((action != HELPER_EXISTS) && (action != HELPER_MATCHMORE))
1195 ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", context);
1197 case STATUS_NO_EXTENSION:
1198 if ((action != HELPER_EXISTS) && (action != HELPER_CANMATCH) && (action != HELPER_MATCHMORE))
1199 ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, context);
1201 case STATUS_NO_PRIORITY:
1202 if ((action != HELPER_EXISTS) && (action != HELPER_CANMATCH) && (action != HELPER_MATCHMORE))
1203 ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, context);
1206 ast_log(LOG_DEBUG, "Shouldn't happen!\n");
1208 if ((action != HELPER_EXISTS) && (action != HELPER_CANMATCH) && (action != HELPER_MATCHMORE))
1216 static struct ast_exten *ast_hint_extension(struct ast_channel *c, char *context, char *exten)
1218 struct ast_exten *e;
1219 struct ast_switch *sw;
1222 char *incstack[AST_PBX_MAX_STACK];
1225 if (ast_mutex_lock(&conlock)) {
1226 ast_log(LOG_WARNING, "Unable to obtain lock\n");
1229 e = pbx_find_extension(c, context, exten, PRIORITY_HINT, "", HELPER_EXISTS, incstack, &stacklen, &status, &sw, &data);
1230 ast_mutex_unlock(&conlock);
1234 static int ast_extension_state2(struct ast_exten *e)
1236 char hint[AST_MAX_EXTENSION] = "";
1239 int allunavailable = 1, allbusy = 1, allfree = 1;
1242 strncpy(hint, ast_get_extension_app(e), sizeof(hint)-1);
1246 rest = strchr(cur, '&');
1252 res = ast_device_state(cur);
1254 case AST_DEVICE_NOT_INUSE:
1258 case AST_DEVICE_INUSE:
1259 return AST_EXTENSION_INUSE;
1260 case AST_DEVICE_BUSY:
1265 case AST_DEVICE_UNAVAILABLE:
1266 case AST_DEVICE_INVALID:
1279 return AST_EXTENSION_NOT_INUSE;
1281 return AST_EXTENSION_BUSY;
1283 return AST_EXTENSION_UNAVAILABLE;
1285 return AST_EXTENSION_INUSE;
1287 return AST_EXTENSION_NOT_INUSE;
1291 int ast_extension_state(struct ast_channel *c, char *context, char *exten)
1293 struct ast_exten *e;
1295 e = ast_hint_extension(c, context, exten);
1299 return ast_extension_state2(e);
1302 int ast_device_state_changed(const char *fmt, ...)
1304 struct ast_hint *list;
1305 struct ast_state_cb *cblist;
1306 char hint[AST_MAX_EXTENSION];
1307 char device[AST_MAX_EXTENSION];
1314 vsnprintf(device, sizeof(device)-1, fmt, ap);
1317 rest = strchr(device, '-');
1322 ast_mutex_lock(&hintlock);
1328 strcpy(hint, ast_get_extension_app(list->exten));
1331 rest = strchr(cur, '&');
1337 if (!strcmp(cur, device)) {
1338 // Found extension execute callbacks
1339 state = ast_extension_state2(list->exten);
1340 if ((state != -1) && (state != list->laststate)) {
1341 // For general callbacks
1344 cblist->callback(list->exten->parent->name, list->exten->exten, state, cblist->data);
1345 cblist = cblist->next;
1348 // For extension callbacks
1349 cblist = list->callbacks;
1351 cblist->callback(list->exten->parent->name, list->exten->exten, state, cblist->data);
1352 cblist = cblist->next;
1355 list->laststate = state;
1365 ast_mutex_unlock(&hintlock);
1369 int ast_extension_state_add(char *context, char *exten,
1370 ast_state_cb_type callback, void *data)
1372 struct ast_hint *list;
1373 struct ast_state_cb *cblist;
1374 struct ast_exten *e;
1376 /* No context and extension add callback to statecbs list */
1377 if (!context && !exten) {
1378 ast_mutex_lock(&hintlock);
1382 if (cblist->callback == callback) {
1383 cblist->data = data;
1384 ast_mutex_unlock(&hintlock);
1387 cblist = cblist->next;
1390 /* Now inserts the callback */
1391 cblist = malloc(sizeof(struct ast_state_cb));
1393 ast_mutex_unlock(&hintlock);
1396 memset(cblist, 0, sizeof(struct ast_state_cb));
1398 cblist->callback = callback;
1399 cblist->data = data;
1401 cblist->next = statecbs;
1404 ast_mutex_unlock(&hintlock);
1408 if (!context || !exten)
1411 /* This callback type is for only one hint */
1412 e = ast_hint_extension(NULL, context, exten);
1417 ast_mutex_lock(&hintlock);
1421 if (list->exten == e)
1427 ast_mutex_unlock(&hintlock);
1431 /* Now inserts the callback */
1432 cblist = malloc(sizeof(struct ast_state_cb));
1434 ast_mutex_unlock(&hintlock);
1437 memset(cblist, 0, sizeof(struct ast_state_cb));
1438 cblist->id = stateid++;
1439 cblist->callback = callback;
1440 cblist->data = data;
1442 cblist->next = list->callbacks;
1443 list->callbacks = cblist;
1445 ast_mutex_unlock(&hintlock);
1449 int ast_extension_state_del(int id, ast_state_cb_type callback)
1451 struct ast_hint *list;
1452 struct ast_state_cb *cblist, *cbprev;
1454 if (!id && !callback)
1457 ast_mutex_lock(&hintlock);
1459 /* id is zero is a callback without extension */
1464 if (cblist->callback == callback) {
1466 statecbs = cblist->next;
1468 cbprev->next = cblist->next;
1472 ast_mutex_unlock(&hintlock);
1476 cblist = cblist->next;
1479 ast_mutex_lock(&hintlock);
1483 /* id greater zero is a callback with extension */
1486 cblist = list->callbacks;
1489 if (cblist->id==id) {
1491 list->callbacks = cblist->next;
1493 cbprev->next = cblist->next;
1497 ast_mutex_unlock(&hintlock);
1501 cblist = cblist->next;
1506 ast_mutex_unlock(&hintlock);
1510 static int ast_add_hint(struct ast_exten *e)
1512 struct ast_hint *list;
1516 ast_mutex_lock(&hintlock);
1519 /* Search if hint exists, do nothing */
1521 if (list->exten == e) {
1522 ast_mutex_unlock(&hintlock);
1528 list = malloc(sizeof(struct ast_hint));
1530 ast_mutex_unlock(&hintlock);
1533 /* Initialize and insert new item */
1534 memset(list, 0, sizeof(struct ast_hint));
1536 list->laststate = ast_extension_state2(e);
1540 ast_mutex_unlock(&hintlock);
1544 static int ast_change_hint(struct ast_exten *oe, struct ast_exten *ne)
1546 struct ast_hint *list;
1548 ast_mutex_lock(&hintlock);
1553 if (list->exten == oe) {
1555 ast_mutex_unlock(&hintlock);
1560 ast_mutex_unlock(&hintlock);
1565 static int ast_remove_hint(struct ast_exten *e)
1567 /* Cleanup the Notifys if hint is removed */
1568 struct ast_hint *list, *prev = NULL;
1569 struct ast_state_cb *cblist, *cbprev;
1574 ast_mutex_lock(&hintlock);
1578 if (list->exten==e) {
1580 cblist = list->callbacks;
1582 /* Notify with -1 and remove all callbacks */
1584 cblist = cblist->next;
1585 cbprev->callback(list->exten->parent->name, list->exten->exten, -1, cbprev->data);
1588 list->callbacks = NULL;
1593 prev->next = list->next;
1597 ast_mutex_unlock(&hintlock);
1605 ast_mutex_unlock(&hintlock);
1610 int ast_get_hint(char *hint, int maxlen, struct ast_channel *c, char *context, char *exten)
1612 struct ast_exten *e;
1613 e = ast_hint_extension(c, context, exten);
1615 strncpy(hint, ast_get_extension_app(e), maxlen);
1621 int ast_exists_extension(struct ast_channel *c, char *context, char *exten, int priority, char *callerid)
1623 return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_EXISTS);
1626 int ast_canmatch_extension(struct ast_channel *c, char *context, char *exten, int priority, char *callerid)
1628 return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_CANMATCH);
1631 int ast_matchmore_extension(struct ast_channel *c, char *context, char *exten, int priority, char *callerid)
1633 return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_MATCHMORE);
1636 int ast_spawn_extension(struct ast_channel *c, char *context, char *exten, int priority, char *callerid)
1638 return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_SPAWN);
1641 int ast_pbx_run(struct ast_channel *c)
1650 /* A little initial setup here */
1652 ast_log(LOG_WARNING, "%s already has PBX structure??\n", c->name);
1653 c->pbx = malloc(sizeof(struct ast_pbx));
1655 ast_log(LOG_WARNING, "Out of memory\n");
1660 ast_log(LOG_WARNING, "%s already has a call record??\n", c->name);
1662 c->cdr = ast_cdr_alloc();
1664 ast_log(LOG_WARNING, "Unable to create Call Detail Record\n");
1668 ast_cdr_init(c->cdr, c);
1671 memset(c->pbx, 0, sizeof(struct ast_pbx));
1672 /* Set reasonable defaults */
1673 c->pbx->rtimeout = 10;
1674 c->pbx->dtimeout = 5;
1676 /* Start by trying whatever the channel is set to */
1677 if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) {
1678 /* JK02: If not successfull fall back to 's' */
1679 strncpy(c->exten, "s", sizeof(c->exten)-1);
1680 if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) {
1681 /* JK02: And finally back to default if everything else failed */
1682 strncpy(c->context, "default", sizeof(c->context)-1);
1687 ast_cdr_start(c->cdr);
1691 while(ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) {
1692 memset(exten, 0, sizeof(exten));
1693 manager_event(EVENT_FLAG_CALL, "Newexten",
1699 c->name, c->context, c->exten, c->priority, c->uniqueid);
1700 if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->callerid))) {
1701 /* Something bad happened, or a hangup has been requested. */
1702 if (((res >= '0') && (res <= '9')) || ((res >= 'A') && (res <= 'F')) ||
1703 (res == '*') || (res == '#')) {
1704 ast_log(LOG_DEBUG, "Oooh, got something to jump out with ('%c')!\n", res);
1705 memset(exten, 0, sizeof(exten));
1707 exten[pos++] = digit = res;
1711 case AST_PBX_KEEPALIVE:
1713 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
1714 else if (option_verbose > 1)
1715 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
1720 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
1721 else if (option_verbose > 1)
1722 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
1723 if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
1728 if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) {
1734 if ((c->_softhangup == AST_SOFTHANGUP_TIMEOUT) && (ast_exists_extension(c,c->context,"T",1,c->callerid))) {
1735 strncpy(c->exten,"T",sizeof(c->exten) - 1);
1736 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
1737 c->whentohangup = 0;
1739 c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT;
1740 } else if (c->_softhangup) {
1741 ast_log(LOG_DEBUG, "Extension %s, priority %d returned normally even though call was hung up\n",
1742 c->exten, c->priority);
1748 if (!ast_exists_extension(c, c->context, c->exten, 1, c->callerid)) {
1749 /* It's not a valid extension anymore */
1750 if (ast_exists_extension(c, c->context, "i", 1, c->callerid)) {
1751 if (option_verbose > 2)
1752 ast_verbose(VERBOSE_PREFIX_3 "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, c->name);
1753 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", c->exten);
1754 strncpy(c->exten, "i", sizeof(c->exten)-1);
1757 ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n",
1758 c->name, c->exten, c->context);
1761 } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) {
1762 /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */
1765 /* Done, wait for an extension */
1767 waittime = c->pbx->dtimeout;
1769 waittime = c->pbx->rtimeout;
1770 while (ast_matchmore_extension(c, c->context, exten, 1, c->callerid)) {
1771 /* As long as we're willing to wait, and as long as it's not defined,
1772 keep reading digits until we can't possibly get a right answer anymore. */
1773 digit = ast_waitfordigit(c, waittime * 1000);
1774 if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
1781 /* Error, maybe a hangup */
1783 exten[pos++] = digit;
1784 waittime = c->pbx->dtimeout;
1787 if (ast_exists_extension(c, c->context, exten, 1, c->callerid)) {
1788 /* Prepare the next cycle */
1789 strncpy(c->exten, exten, sizeof(c->exten)-1);
1792 /* No such extension */
1793 if (strlen(exten)) {
1794 /* An invalid extension */
1795 if (ast_exists_extension(c, c->context, "i", 1, c->callerid)) {
1796 if (option_verbose > 2)
1797 ast_verbose( VERBOSE_PREFIX_3 "Invalid extension '%s' in context '%s' on %s\n", exten, c->context, c->name);
1798 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", exten);
1799 strncpy(c->exten, "i", sizeof(c->exten)-1);
1802 ast_log(LOG_WARNING, "Invalid extension, but no rule 'i' in context '%s'\n", c->context);
1806 /* A simple timeout */
1807 if (ast_exists_extension(c, c->context, "t", 1, c->callerid)) {
1808 if (option_verbose > 2)
1809 ast_verbose( VERBOSE_PREFIX_3 "Timeout on %s\n", c->name);
1810 strncpy(c->exten, "t", sizeof(c->exten)-1);
1813 ast_log(LOG_WARNING, "Timeout, but no rule 't' in context '%s'\n", c->context);
1819 if (option_verbose > 2)
1820 ast_verbose(VERBOSE_PREFIX_2 "CDR updated on %s\n",c->name);
1826 ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name);
1828 if ((res != AST_PBX_KEEPALIVE) && ast_exists_extension(c, c->context, "h", 1, c->callerid)) {
1829 strcpy(c->exten, "h");
1831 while(ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) {
1832 if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->callerid))) {
1833 /* Something bad happened, or a hangup has been requested. */
1835 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
1836 else if (option_verbose > 1)
1837 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
1844 pbx_destroy(c->pbx);
1846 if (res != AST_PBX_KEEPALIVE)
1851 static void *pbx_thread(void *data)
1853 /* Oh joyeous kernel, we're a new thread, with nothing to do but
1854 answer this channel and get it going. The setjmp stuff is fairly
1855 confusing, but necessary to get smooth transitions between
1856 the execution of different applications (without the use of
1857 additional threads) */
1858 struct ast_channel *c = data;
1864 int ast_pbx_start(struct ast_channel *c)
1867 pthread_attr_t attr;
1869 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
1873 /* Start a new thread, and get something handling this channel. */
1874 pthread_attr_init(&attr);
1875 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1876 if (pthread_create(&t, &attr, pbx_thread, c)) {
1877 ast_log(LOG_WARNING, "Failed to create new channel thread\n");
1884 * This function locks contexts list by &conlist, search for the rigt context
1885 * structure, leave context list locked and call ast_context_remove_include2
1886 * which removes include, unlock contexts list and return ...
1888 int ast_context_remove_include(char *context, char *include, char *registrar)
1890 struct ast_context *c;
1892 if (ast_lock_contexts()) return -1;
1894 /* walk contexts and search for the right one ...*/
1895 c = ast_walk_contexts(NULL);
1897 /* we found one ... */
1898 if (!strcmp(ast_get_context_name(c), context)) {
1900 /* remove include from this context ... */
1901 ret = ast_context_remove_include2(c, include, registrar);
1903 ast_unlock_contexts();
1905 /* ... return results */
1908 c = ast_walk_contexts(c);
1911 /* we can't find the right one context */
1912 ast_unlock_contexts();
1917 * When we call this function, &conlock lock must be locked, because when
1918 * we giving *con argument, some process can remove/change this context
1919 * and after that there can be segfault.
1921 * This function locks given context, removes include, unlock context and
1924 int ast_context_remove_include2(struct ast_context *con, char *include, char *registrar)
1926 struct ast_include *i, *pi = NULL;
1928 if (ast_mutex_lock(&con->lock)) return -1;
1933 /* find our include */
1934 if (!strcmp(i->name, include) &&
1935 (!strcmp(i->registrar, registrar) || !registrar)) {
1936 /* remove from list */
1940 con->includes = i->next;
1941 /* free include and return */
1943 ast_mutex_unlock(&con->lock);
1950 /* we can't find the right include */
1951 ast_mutex_unlock(&con->lock);
1956 * This function locks contexts list by &conlist, search for the rigt context
1957 * structure, leave context list locked and call ast_context_remove_switch2
1958 * which removes switch, unlock contexts list and return ...
1960 int ast_context_remove_switch(char *context, char *sw, char *data, char *registrar)
1962 struct ast_context *c;
1964 if (ast_lock_contexts()) return -1;
1966 /* walk contexts and search for the right one ...*/
1967 c = ast_walk_contexts(NULL);
1969 /* we found one ... */
1970 if (!strcmp(ast_get_context_name(c), context)) {
1972 /* remove switch from this context ... */
1973 ret = ast_context_remove_switch2(c, sw, data, registrar);
1975 ast_unlock_contexts();
1977 /* ... return results */
1980 c = ast_walk_contexts(c);
1983 /* we can't find the right one context */
1984 ast_unlock_contexts();
1989 * When we call this function, &conlock lock must be locked, because when
1990 * we giving *con argument, some process can remove/change this context
1991 * and after that there can be segfault.
1993 * This function locks given context, removes switch, unlock context and
1996 int ast_context_remove_switch2(struct ast_context *con, char *sw, char *data, char *registrar)
1998 struct ast_sw *i, *pi = NULL;
2000 if (ast_mutex_lock(&con->lock)) return -1;
2005 /* find our switch */
2006 if (!strcmp(i->name, sw) && !strcmp(i->data, data) &&
2007 (!strcmp(i->registrar, registrar) || !registrar)) {
2008 /* remove from list */
2012 con->alts = i->next;
2013 /* free switch and return */
2015 ast_mutex_unlock(&con->lock);
2022 /* we can't find the right switch */
2023 ast_mutex_unlock(&con->lock);
2028 * This functions lock contexts list, search for the right context,
2029 * call ast_context_remove_extension2, unlock contexts list and return.
2030 * In this function we are using
2032 int ast_context_remove_extension(char *context, char *extension, int priority, char *registrar)
2034 struct ast_context *c;
2036 if (ast_lock_contexts()) return -1;
2038 /* walk contexts ... */
2039 c = ast_walk_contexts(NULL);
2041 /* ... search for the right one ... */
2042 if (!strcmp(ast_get_context_name(c), context)) {
2043 /* ... remove extension ... */
2044 int ret = ast_context_remove_extension2(c, extension, priority,
2046 /* ... unlock contexts list and return */
2047 ast_unlock_contexts();
2050 c = ast_walk_contexts(c);
2053 /* we can't find the right context */
2054 ast_unlock_contexts();
2059 * When do you want to call this function, make sure that &conlock is locked,
2060 * because some process can handle with your *con context before you lock
2063 * This functionc locks given context, search for the right extension and
2064 * fires out all peer in this extensions with given priority. If priority
2065 * is set to 0, all peers are removed. After that, unlock context and
2068 int ast_context_remove_extension2(struct ast_context *con, char *extension, int priority, char *registrar)
2070 struct ast_exten *exten, *prev_exten = NULL;
2072 if (ast_mutex_lock(&con->lock)) return -1;
2074 /* go through all extensions in context and search the right one ... */
2078 /* look for right extension */
2079 if (!strcmp(exten->exten, extension) &&
2080 (!strcmp(exten->registrar, registrar) || !registrar)) {
2081 struct ast_exten *peer;
2083 /* should we free all peers in this extension? (priority == 0)? */
2084 if (priority == 0) {
2085 /* remove this extension from context list */
2087 prev_exten->next = exten->next;
2089 con->root = exten->next;
2091 /* fire out all peers */
2096 if (!peer->priority==PRIORITY_HINT)
2097 ast_remove_hint(peer);
2099 peer->datad(peer->data);
2105 ast_mutex_unlock(&con->lock);
2108 /* remove only extension with exten->priority == priority */
2109 struct ast_exten *previous_peer = NULL;
2113 /* is this our extension? */
2114 if (peer->priority == priority &&
2115 (!strcmp(peer->registrar, registrar) || !registrar)) {
2116 /* we are first priority extension? */
2117 if (!previous_peer) {
2118 /* exists previous extension here? */
2120 /* yes, so we must change next pointer in
2121 * previous connection to next peer
2124 prev_exten->next = peer->peer;
2125 peer->peer->next = exten->next;
2127 prev_exten->next = exten->next;
2129 /* no previous extension, we are first
2130 * extension, so change con->root ...
2133 con->root = peer->peer;
2135 con->root = exten->next;
2138 /* we are not first priority in extension */
2139 previous_peer->peer = peer->peer;
2142 /* now, free whole priority extension */
2143 if (peer->priority==PRIORITY_HINT)
2144 ast_remove_hint(peer);
2145 peer->datad(peer->data);
2148 ast_mutex_unlock(&con->lock);
2151 /* this is not right extension, skip to next peer */
2152 previous_peer = peer;
2157 ast_mutex_unlock(&con->lock);
2163 exten = exten->next;
2166 /* we can't find right extension */
2167 ast_mutex_unlock(&con->lock);
2172 int ast_register_application(char *app, int (*execute)(struct ast_channel *, void *), char *synopsis, char *description)
2174 struct ast_app *tmp, *prev, *cur;
2176 if (ast_mutex_lock(&applock)) {
2177 ast_log(LOG_ERROR, "Unable to lock application list\n");
2182 if (!strcasecmp(app, tmp->name)) {
2183 ast_log(LOG_WARNING, "Already have an application '%s'\n", app);
2184 ast_mutex_unlock(&applock);
2189 tmp = malloc(sizeof(struct ast_app));
2191 memset(tmp, 0, sizeof(struct ast_app));
2192 strncpy(tmp->name, app, sizeof(tmp->name)-1);
2193 tmp->execute = execute;
2194 tmp->synopsis = synopsis;
2195 tmp->description = description;
2196 /* Store in alphabetical order */
2200 if (strcasecmp(tmp->name, cur->name) < 0)
2206 tmp->next = prev->next;
2213 ast_log(LOG_WARNING, "Out of memory\n");
2214 ast_mutex_unlock(&applock);
2217 if (option_verbose > 1)
2218 ast_verbose( VERBOSE_PREFIX_2 "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps)));
2219 ast_mutex_unlock(&applock);
2223 int ast_register_switch(struct ast_switch *sw)
2225 struct ast_switch *tmp, *prev=NULL;
2226 if (ast_mutex_lock(&switchlock)) {
2227 ast_log(LOG_ERROR, "Unable to lock switch lock\n");
2232 if (!strcasecmp(tmp->name, sw->name))
2238 ast_mutex_unlock(&switchlock);
2239 ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name);
2247 ast_mutex_unlock(&switchlock);
2251 void ast_unregister_switch(struct ast_switch *sw)
2253 struct ast_switch *tmp, *prev=NULL;
2254 if (ast_mutex_lock(&switchlock)) {
2255 ast_log(LOG_ERROR, "Unable to lock switch lock\n");
2262 prev->next = tmp->next;
2264 switches = tmp->next;
2271 ast_mutex_unlock(&switchlock);
2275 * Help for CLI commands ...
2277 static char show_application_help[] =
2278 "Usage: show application <application> [<application> [<application> [...]]]\n"
2279 " Describes a particular application.\n";
2281 static char show_applications_help[] =
2282 "Usage: show applications\n"
2283 " List applications which are currently available.\n";
2285 static char show_dialplan_help[] =
2286 "Usage: show dialplan [exten@][context]\n"
2289 static char show_switches_help[] =
2290 "Usage: show switches\n"
2291 " Show registered switches\n";
2294 * IMPLEMENTATION OF CLI FUNCTIONS IS IN THE SAME ORDER AS COMMANDS HELPS
2299 * 'show application' CLI command implementation functions ...
2303 * There is a possibility to show informations about more than one
2304 * application at one time. You can type 'show application Dial Echo' and
2305 * you will see informations about these two applications ...
2307 static char *complete_show_application(char *line, char *word,
2313 /* try to lock applications list ... */
2314 if (ast_mutex_lock(&applock)) {
2315 ast_log(LOG_ERROR, "Unable to lock application list\n");
2319 /* ... walk all applications ... */
2322 /* ... check if word matches this application ... */
2323 if (!strncasecmp(word, a->name, strlen(word))) {
2324 /* ... if this is right app serve it ... */
2325 if (++which > state) {
2326 char *ret = strdup(a->name);
2327 ast_mutex_unlock(&applock);
2334 /* no application match */
2335 ast_mutex_unlock(&applock);
2339 static int handle_show_application(int fd, int argc, char *argv[])
2342 int n, app, no_registered_app = 1;
2345 if (argc < 3) return RESULT_SHOWUSAGE;
2347 /* try to lock applications list ... */
2348 if (ast_mutex_lock(&applock)) {
2349 ast_log(LOG_ERROR, "Unable to lock application list\n");
2353 /* ... go through all applications ... */
2356 /* ... compare this application name with all arguments given
2357 * to 'show application' command ... */
2358 for (app = 2; app < argc; app++) {
2359 if (!strcasecmp(a->name, argv[app])) {
2360 no_registered_app = 0;
2362 /* ... one of our applications, show info ...*/
2364 "\n -= Info about application '%s' =- \n\n"
2365 "[Synopsis]:\n %s\n\n"
2366 "[Description]:\n%s\n",
2368 a->synopsis ? a->synopsis : "Not available",
2369 a->description ? a-> description : "Not available");
2379 ast_mutex_unlock(&applock);
2381 /* we found at least one app? no? */
2382 if (no_registered_app) {
2383 ast_cli(fd, "Your application(s) is (are) not registered\n");
2384 return RESULT_FAILURE;
2387 return RESULT_SUCCESS;
2390 static int handle_show_switches(int fd, int argc, char *argv[])
2392 struct ast_switch *sw;
2394 ast_cli(fd, "There are no registered alternative switches\n");
2395 return RESULT_SUCCESS;
2397 /* ... we have applications ... */
2398 ast_cli(fd, "\n -= Registered Asterisk Alternative Switches =-\n");
2399 if (ast_mutex_lock(&switchlock)) {
2400 ast_log(LOG_ERROR, "Unable to lock switches\n");
2405 ast_cli(fd, "%s: %s\n", sw->name, sw->description);
2408 ast_mutex_unlock(&switchlock);
2409 return RESULT_SUCCESS;
2413 * 'show applications' CLI command implementation functions ...
2415 static int handle_show_applications(int fd, int argc, char *argv[])
2419 /* try to lock applications list ... */
2420 if (ast_mutex_lock(&applock)) {
2421 ast_log(LOG_ERROR, "Unable to lock application list\n");
2425 /* ... go to first application ... */
2428 /* ... have we got at least one application (first)? no? */
2430 ast_cli(fd, "There is no registered applications\n");
2431 ast_mutex_unlock(&applock);
2435 /* ... we have applications ... */
2436 ast_cli(fd, "\n -= Registered Asterisk Applications =-\n");
2438 /* ... go through all applications ... */
2440 /* ... show informations about applications ... */
2441 ast_cli(fd," %15s: %s\n",
2443 a->synopsis ? a->synopsis : "<Synopsis not available>");
2447 /* ... unlock and return */
2448 ast_mutex_unlock(&applock);
2450 return RESULT_SUCCESS;
2454 * 'show dialplan' CLI command implementation functions ...
2456 static char *complete_show_dialplan_context(char *line, char *word, int pos,
2459 struct ast_context *c;
2462 /* we are do completion of [exten@]context on second position only */
2463 if (pos != 2) return NULL;
2465 /* try to lock contexts list ... */
2466 if (ast_lock_contexts()) {
2467 ast_log(LOG_ERROR, "Unable to lock context list\n");
2471 /* ... walk through all contexts ... */
2472 c = ast_walk_contexts(NULL);
2474 /* ... word matches context name? yes? ... */
2475 if (!strncasecmp(word, ast_get_context_name(c), strlen(word))) {
2476 /* ... for serve? ... */
2477 if (++which > state) {
2478 /* ... yes, serve this context name ... */
2479 char *ret = strdup(ast_get_context_name(c));
2480 ast_unlock_contexts();
2484 c = ast_walk_contexts(c);
2487 /* ... unlock and return */
2488 ast_unlock_contexts();
2492 static int handle_show_dialplan(int fd, int argc, char *argv[])
2494 struct ast_context *c;
2495 char *exten = NULL, *context = NULL;
2496 int context_existence = 0, extension_existence = 0;
2498 if (argc != 3 && argc != 2) return -1;
2500 /* we obtain [exten@]context? if yes, split them ... */
2502 char *splitter = argv[2];
2503 /* is there a '@' character? */
2504 if (strchr(argv[2], '@')) {
2505 /* yes, split into exten & context ... */
2506 exten = strsep(&splitter, "@");
2509 /* check for length and change to NULL if !strlen() */
2510 if (!strlen(exten)) exten = NULL;
2511 if (!strlen(context)) context = NULL;
2514 /* no '@' char, only context given */
2516 if (!strlen(context)) context = NULL;
2520 /* try to lock contexts */
2521 if (ast_lock_contexts()) {
2522 ast_log(LOG_WARNING, "Failed to lock contexts list\n");
2523 return RESULT_FAILURE;
2526 /* walk all contexts ... */
2527 c = ast_walk_contexts(NULL);
2529 /* show this context? */
2531 !strcmp(ast_get_context_name(c), context)) {
2532 context_existence = 1;
2534 /* try to lock context before walking in ... */
2535 if (!ast_lock_context(c)) {
2536 struct ast_exten *e;
2537 struct ast_include *i;
2538 struct ast_ignorepat *ip;
2540 char buf[256], buf2[256];
2541 int context_info_printed = 0;
2543 /* are we looking for exten too? if yes, we print context
2544 * if we our extension only
2547 ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
2548 ast_get_context_name(c), ast_get_context_registrar(c));
2549 context_info_printed = 1;
2552 /* walk extensions ... */
2553 e = ast_walk_context_extensions(c, NULL);
2555 struct ast_exten *p;
2557 /* looking for extension? is this our extension? */
2559 strcmp(ast_get_extension_name(e), exten))
2561 /* we are looking for extension and it's not our
2562 * extension, so skip to next extension */
2563 e = ast_walk_context_extensions(c, e);
2567 extension_existence = 1;
2569 /* may we print context info? */
2570 if (!context_info_printed) {
2571 ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
2572 ast_get_context_name(c),
2573 ast_get_context_registrar(c));
2574 context_info_printed = 1;
2577 /* write extension name and first peer */
2578 bzero(buf, sizeof(buf));
2579 snprintf(buf, sizeof(buf), "'%s' =>",
2580 ast_get_extension_name(e));
2582 snprintf(buf2, sizeof(buf2),
2584 ast_get_extension_priority(e),
2585 ast_get_extension_app(e),
2586 (char *)ast_get_extension_app_data(e));
2588 ast_cli(fd, " %-17s %-45s [%s]\n", buf, buf2,
2589 ast_get_extension_registrar(e));
2591 /* walk next extension peers */
2592 p = ast_walk_extension_priorities(e, e);
2594 bzero((void *)buf2, sizeof(buf2));
2596 snprintf(buf2, sizeof(buf2),
2598 ast_get_extension_priority(p),
2599 ast_get_extension_app(p),
2600 (char *)ast_get_extension_app_data(p));
2602 ast_cli(fd," %-17s %-45s [%s]\n",
2604 ast_get_extension_registrar(p));
2606 p = ast_walk_extension_priorities(e, p);
2608 e = ast_walk_context_extensions(c, e);
2611 /* include & ignorepat we all printing if we are not
2612 * looking for exact extension
2615 if (ast_walk_context_extensions(c, NULL))
2618 /* walk included and write info ... */
2619 i = ast_walk_context_includes(c, NULL);
2621 bzero(buf, sizeof(buf));
2622 snprintf(buf, sizeof(buf), "'%s'",
2623 ast_get_include_name(i));
2624 ast_cli(fd, " Include => %-45s [%s]\n",
2625 buf, ast_get_include_registrar(i));
2626 i = ast_walk_context_includes(c, i);
2629 /* walk ignore patterns and write info ... */
2630 ip = ast_walk_context_ignorepats(c, NULL);
2632 bzero(buf, sizeof(buf));
2633 snprintf(buf, sizeof(buf), "'%s'",
2634 ast_get_ignorepat_name(ip));
2635 ast_cli(fd, " Ignore pattern => %-45s [%s]\n",
2636 buf, ast_get_ignorepat_registrar(ip));
2637 ip = ast_walk_context_ignorepats(c, ip);
2639 sw = ast_walk_context_switches(c, NULL);
2641 bzero(buf, sizeof(buf));
2642 snprintf(buf, sizeof(buf), "'%s/%s'",
2643 ast_get_switch_name(sw),
2644 ast_get_switch_data(sw));
2645 ast_cli(fd, " Alt. Switch => %-45s [%s]\n",
2646 buf, ast_get_switch_registrar(sw));
2647 sw = ast_walk_context_switches(c, sw);
2651 ast_unlock_context(c);
2653 /* if we print something in context, make an empty line */
2654 if (context_info_printed) ast_cli(fd, "\n");
2657 c = ast_walk_contexts(c);
2659 ast_unlock_contexts();
2661 /* check for input failure and throw some error messages */
2662 if (context && !context_existence) {
2663 ast_cli(fd, "There is no existence of '%s' context\n",
2665 return RESULT_FAILURE;
2668 if (exten && !extension_existence) {
2670 ast_cli(fd, "There is no existence of %s@%s extension\n",
2674 "There is no existence of '%s' extension in all contexts\n",
2676 return RESULT_FAILURE;
2680 return RESULT_SUCCESS;
2684 * CLI entries for upper commands ...
2686 static struct ast_cli_entry show_applications_cli =
2687 { { "show", "applications", NULL },
2688 handle_show_applications, "Shows registered applications",
2689 show_applications_help };
2691 static struct ast_cli_entry show_application_cli =
2692 { { "show", "application", NULL },
2693 handle_show_application, "Describe a specific application",
2694 show_application_help, complete_show_application };
2696 static struct ast_cli_entry show_dialplan_cli =
2697 { { "show", "dialplan", NULL },
2698 handle_show_dialplan, "Show dialplan",
2699 show_dialplan_help, complete_show_dialplan_context };
2701 static struct ast_cli_entry show_switches_cli =
2702 { { "show", "switches", NULL },
2703 handle_show_switches, "Show alternative switches",
2704 show_switches_help, NULL };
2706 int ast_unregister_application(char *app) {
2707 struct ast_app *tmp, *tmpl = NULL;
2708 if (ast_mutex_lock(&applock)) {
2709 ast_log(LOG_ERROR, "Unable to lock application list\n");
2714 if (!strcasecmp(app, tmp->name)) {
2716 tmpl->next = tmp->next;
2719 if (option_verbose > 1)
2720 ast_verbose( VERBOSE_PREFIX_2 "Unregistered application '%s'\n", tmp->name);
2721 ast_mutex_unlock(&applock);
2727 ast_mutex_unlock(&applock);
2731 struct ast_context *ast_context_create(struct ast_context **extcontexts, char *name, char *registrar)
2733 struct ast_context *tmp, **local_contexts;
2735 local_contexts = &contexts;
2736 ast_mutex_lock(&conlock);
2738 local_contexts = extcontexts;
2740 tmp = *local_contexts;
2742 if (!strcasecmp(tmp->name, name)) {
2743 ast_mutex_unlock(&conlock);
2744 ast_log(LOG_WARNING, "Tried to register context '%s', already in use\n", name);
2746 ast_mutex_unlock(&conlock);
2751 tmp = malloc(sizeof(struct ast_context));
2753 memset(tmp, 0, sizeof(struct ast_context));
2754 ast_mutex_init(&tmp->lock);
2755 strncpy(tmp->name, name, sizeof(tmp->name)-1);
2757 tmp->registrar = registrar;
2758 tmp->next = *local_contexts;
2759 tmp->includes = NULL;
2760 tmp->ignorepats = NULL;
2761 *local_contexts = tmp;
2763 ast_log(LOG_DEBUG, "Registered context '%s'\n", tmp->name);
2764 else if (option_verbose > 2)
2765 ast_verbose( VERBOSE_PREFIX_3 "Registered extension context '%s'\n", tmp->name);
2767 ast_log(LOG_WARNING, "Out of memory\n");
2770 ast_mutex_unlock(&conlock);
2774 void __ast_context_destroy(struct ast_context *con, char *registrar, int lock);
2776 void ast_merge_contexts_and_delete(struct ast_context **extcontexts, char *registrar) {
2777 struct ast_context *tmp, *lasttmp = NULL;
2779 ast_mutex_lock(&conlock);
2781 __ast_context_destroy(NULL,registrar,0);
2788 __ast_context_destroy(tmp,tmp->registrar,0);
2794 lasttmp->next = contexts;
2795 contexts = *extcontexts;
2796 *extcontexts = NULL;
2798 ast_log(LOG_WARNING, "Requested contexts didn't get merged\n");
2799 ast_mutex_unlock(&conlock);
2805 * EBUSY - can't lock
2806 * ENOENT - no existence of context
2808 int ast_context_add_include(char *context, char *include, char *registrar)
2810 struct ast_context *c;
2812 if (ast_lock_contexts()) {
2817 /* walk contexts ... */
2818 c = ast_walk_contexts(NULL);
2820 /* ... search for the right one ... */
2821 if (!strcmp(ast_get_context_name(c), context)) {
2822 int ret = ast_context_add_include2(c, include, registrar);
2823 /* ... unlock contexts list and return */
2824 ast_unlock_contexts();
2827 c = ast_walk_contexts(c);
2830 /* we can't find the right context */
2831 ast_unlock_contexts();
2839 while(*c && (*c != '|')) c++; \
2840 if (*c) { *c = '\0'; c++; } else c = NULL; \
2843 static void get_timerange(struct ast_include *i, char *times)
2851 //start disabling all times, fill the fields with 0's, as they may contain garbage
2852 memset(i->minmask, 0, sizeof(i->minmask));
2854 /* Star is all times */
2855 if (!strlen(times) || !strcmp(times, "*")) {
2857 i->minmask[x] = (1 << 30) - 1;
2860 /* Otherwise expect a range */
2861 e = strchr(times, '-');
2863 ast_log(LOG_WARNING, "Time range is not valid. Assuming no time.\n");
2868 while(*e && !isdigit(*e)) e++;
2870 ast_log(LOG_WARNING, "Invalid time range. Assuming no time.\n");
2873 if (sscanf(times, "%d:%d", &s1, &s2) != 2) {
2874 ast_log(LOG_WARNING, "%s isn't a time. Assuming no time.\n", times);
2877 if (sscanf(e, "%d:%d", &e1, &e2) != 2) {
2878 ast_log(LOG_WARNING, "%s isn't a time. Assuming no time.\n", e);
2881 s1 = s1 * 30 + s2/2;
2882 if ((s1 < 0) || (s1 >= 24*30)) {
2883 ast_log(LOG_WARNING, "%s isn't a valid star time. Assuming no time.\n", times);
2886 e1 = e1 * 30 + e2/2;
2887 if ((e1 < 0) || (e2 >= 24*30)) {
2888 ast_log(LOG_WARNING, "%s isn't a valid start time. Assuming no time.\n", times);
2891 /* Go through the time and enable each appropriate bit */
2892 for (x=s1;x != e1;x = (x + 1) % (24 * 30)) {
2893 i->minmask[x/30] |= (1 << (x % 30));
2895 /* Do the last one */
2896 i->minmask[x/30] |= (1 << (x % 30));
2901 static char *days[] =
2912 static unsigned int get_dow(char *dow)
2915 /* The following line is coincidence, really! */
2918 /* Check for all days */
2919 if (!strlen(dow) || !strcmp(dow, "*"))
2920 return (1 << 7) - 1;
2921 /* Get start and ending days */
2922 c = strchr(dow, '-');
2928 /* Find the start */
2930 while((s < 7) && strcasecmp(dow, days[s])) s++;
2932 ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", dow);
2937 while((e < 7) && strcasecmp(c, days[e])) e++;
2939 ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", c);
2945 for (x=s;x!=e;x = (x + 1) % 7) {
2953 static unsigned int get_day(char *day)
2956 /* The following line is coincidence, really! */
2959 /* Check for all days */
2960 if (!strlen(day) || !strcmp(day, "*")) {
2961 mask = (1 << 30) + ((1 << 30) - 1);
2964 /* Get start and ending days */
2965 c = strchr(day, '-');
2970 /* Find the start */
2971 if (sscanf(day, "%d", &s) != 1) {
2972 ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", day);
2975 if ((s < 1) || (s > 31)) {
2976 ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", day);
2981 if (sscanf(c, "%d", &e) != 1) {
2982 ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", c);
2985 if ((e < 1) || (e > 31)) {
2986 ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", c);
2993 for (x=s;x!=e;x = (x + 1) % 31) {
3000 static char *months[] =
3016 static unsigned int get_month(char *mon)
3019 /* The following line is coincidence, really! */
3022 /* Check for all days */
3023 if (!strlen(mon) || !strcmp(mon, "*"))
3024 return (1 << 12) - 1;
3025 /* Get start and ending days */
3026 c = strchr(mon, '-');
3031 /* Find the start */
3033 while((s < 12) && strcasecmp(mon, months[s])) s++;
3035 ast_log(LOG_WARNING, "Invalid month '%s', assuming none\n", mon);
3040 while((e < 12) && strcasecmp(mon, months[e])) e++;
3042 ast_log(LOG_WARNING, "Invalid month '%s', assuming none\n", c);
3048 for (x=s;x!=e;x = (x + 1) % 12) {
3056 static void build_timing(struct ast_include *i, char *info)
3059 /* Check for empty just in case */
3063 /* Assume everything except time */
3064 i->monthmask = (1 << 12) - 1;
3065 i->daymask = (1 << 30) - 1 + (1 << 30);
3066 i->dowmask = (1 << 7) - 1;
3067 /* Avoid using str tok */
3069 /* Info has the time range, start with that */
3070 get_timerange(i, info);
3075 /* Now check for day of week */
3076 i->dowmask = get_dow(info);
3082 /* Now check for the day of the month */
3083 i->daymask = get_day(info);
3088 /* And finally go for the month */
3089 i->monthmask = get_month(info);
3094 * ENOMEM - out of memory
3095 * EBUSY - can't lock
3096 * EEXIST - already included
3097 * EINVAL - there is no existence of context for inclusion
3099 int ast_context_add_include2(struct ast_context *con, char *value,
3102 struct ast_include *new_include;
3104 struct ast_include *i, *il = NULL; /* include, include_last */
3106 /* allocate new include structure ... */
3107 if (!(new_include = malloc(sizeof(struct ast_include)))) {
3108 ast_log(LOG_WARNING, "Out of memory\n");
3113 /* ... fill in this structure ... */
3114 memset(new_include, 0, sizeof(struct ast_include));
3115 strncpy(new_include->name, value, sizeof(new_include->name)-1);
3116 strncpy(new_include->rname, value, sizeof(new_include->rname)-1);
3117 c = new_include->rname;
3118 /* Strip off timing info */
3119 while(*c && (*c != '|')) c++;
3120 /* Process if it's there */
3122 build_timing(new_include, c+1);
3125 new_include->next = NULL;
3126 new_include->registrar = registrar;
3128 /* ... try to lock this context ... */
3129 if (ast_mutex_lock(&con->lock)) {
3135 /* ... go to last include and check if context is already included too... */
3138 if (!strcasecmp(i->name, new_include->name)) {
3140 ast_mutex_unlock(&con->lock);
3148 /* ... include new context into context list, unlock, return */
3150 il->next = new_include;
3152 con->includes = new_include;
3153 if (option_verbose > 2)
3154 ast_verbose(VERBOSE_PREFIX_3 "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con));
3155 ast_mutex_unlock(&con->lock);
3162 * EBUSY - can't lock
3163 * ENOENT - no existence of context
3165 int ast_context_add_switch(char *context, char *sw, char *data, char *registrar)
3167 struct ast_context *c;
3169 if (ast_lock_contexts()) {
3174 /* walk contexts ... */
3175 c = ast_walk_contexts(NULL);
3177 /* ... search for the right one ... */
3178 if (!strcmp(ast_get_context_name(c), context)) {
3179 int ret = ast_context_add_switch2(c, sw, data, registrar);
3180 /* ... unlock contexts list and return */
3181 ast_unlock_contexts();
3184 c = ast_walk_contexts(c);
3187 /* we can't find the right context */
3188 ast_unlock_contexts();
3195 * ENOMEM - out of memory
3196 * EBUSY - can't lock
3197 * EEXIST - already included
3198 * EINVAL - there is no existence of context for inclusion
3200 int ast_context_add_switch2(struct ast_context *con, char *value,
3201 char *data, char *registrar)
3203 struct ast_sw *new_sw;
3204 struct ast_sw *i, *il = NULL; /* sw, sw_last */
3206 /* allocate new sw structure ... */
3207 if (!(new_sw = malloc(sizeof(struct ast_sw)))) {
3208 ast_log(LOG_WARNING, "Out of memory\n");
3213 /* ... fill in this structure ... */
3214 memset(new_sw, 0, sizeof(struct ast_sw));
3215 strncpy(new_sw->name, value, sizeof(new_sw->name)-1);
3217 strncpy(new_sw->data, data, sizeof(new_sw->data)-1);
3219 strncpy(new_sw->data, "", sizeof(new_sw->data)-1);
3220 new_sw->next = NULL;
3221 new_sw->registrar = registrar;
3223 /* ... try to lock this context ... */
3224 if (ast_mutex_lock(&con->lock)) {
3230 /* ... go to last sw and check if context is already swd too... */
3233 if (!strcasecmp(i->name, new_sw->name)) {
3235 ast_mutex_unlock(&con->lock);
3243 /* ... sw new context into context list, unlock, return */
3248 if (option_verbose > 2)
3249 ast_verbose(VERBOSE_PREFIX_3 "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con));
3250 ast_mutex_unlock(&con->lock);
3256 * EBUSY - can't lock
3257 * ENOENT - there is not context existence
3259 int ast_context_remove_ignorepat(char *context, char *ignorepat, char *registrar)
3261 struct ast_context *c;
3263 if (ast_lock_contexts()) {
3268 c = ast_walk_contexts(NULL);
3270 if (!strcmp(ast_get_context_name(c), context)) {
3271 int ret = ast_context_remove_ignorepat2(c, ignorepat, registrar);
3272 ast_unlock_contexts();
3275 c = ast_walk_contexts(c);
3278 ast_unlock_contexts();
3283 int ast_context_remove_ignorepat2(struct ast_context *con, char *ignorepat, char *registrar)
3285 struct ast_ignorepat *ip, *ipl = NULL;
3287 if (ast_mutex_lock(&con->lock)) {
3292 ip = con->ignorepats;
3294 if (!strcmp(ip->pattern, ignorepat) &&
3295 (registrar == ip->registrar || !registrar)) {
3297 ipl->next = ip->next;
3300 con->ignorepats = ip->next;
3303 ast_mutex_unlock(&con->lock);
3306 ipl = ip; ip = ip->next;
3309 ast_mutex_unlock(&con->lock);
3315 * EBUSY - can't lock
3316 * ENOENT - there is no existence of context
3318 int ast_context_add_ignorepat(char *con, char *value, char *registrar)
3320 struct ast_context *c;
3322 if (ast_lock_contexts()) {
3327 c = ast_walk_contexts(NULL);
3329 if (!strcmp(ast_get_context_name(c), con)) {
3330 int ret = ast_context_add_ignorepat2(c, value, registrar);
3331 ast_unlock_contexts();
3334 c = ast_walk_contexts(c);
3337 ast_unlock_contexts();
3342 int ast_context_add_ignorepat2(struct ast_context *con, char *value, char *registrar)
3344 struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL;
3345 ignorepat = malloc(sizeof(struct ast_ignorepat));
3347 ast_log(LOG_WARNING, "Out of memory\n");
3351 memset(ignorepat, 0, sizeof(struct ast_ignorepat));
3352 strncpy(ignorepat->pattern, value, sizeof(ignorepat->pattern)-1);
3353 ignorepat->next = NULL;
3354 ignorepat->registrar = registrar;
3355 ast_mutex_lock(&con->lock);
3356 ignorepatc = con->ignorepats;
3358 ignorepatl = ignorepatc;
3359 if (!strcasecmp(ignorepatc->pattern, value)) {
3361 ast_mutex_unlock(&con->lock);
3365 ignorepatc = ignorepatc->next;
3368 ignorepatl->next = ignorepat;
3370 con->ignorepats = ignorepat;
3371 ast_mutex_unlock(&con->lock);
3376 int ast_ignore_pattern(char *context, char *pattern)
3378 struct ast_context *con;
3379 struct ast_ignorepat *pat;
3380 con = ast_context_find(context);
3382 pat = con->ignorepats;
3384 if (ast_extension_match(pat->pattern, pattern))
3393 * EBUSY - can't lock
3394 * ENOENT - no existence of context
3397 int ast_add_extension(char *context, int replace, char *extension, int priority, char *callerid,
3398 char *application, void *data, void (*datad)(void *), char *registrar)
3400 struct ast_context *c;
3402 if (ast_lock_contexts()) {
3407 c = ast_walk_contexts(NULL);
3409 if (!strcmp(context, ast_get_context_name(c))) {
3410 int ret = ast_add_extension2(c, replace, extension, priority, callerid,
3411 application, data, datad, registrar);
3412 ast_unlock_contexts();
3415 c = ast_walk_contexts(c);
3418 ast_unlock_contexts();
3423 int ast_async_goto(struct ast_channel *chan, char *context, char *exten, int priority, int needlock)
3427 ast_mutex_lock(&chan->lock);
3429 /* This channel is currently in the PBX */
3430 if (context && strlen(context))
3431 strncpy(chan->context, context, sizeof(chan->context) - 1);
3432 if (exten && strlen(exten))
3433 strncpy(chan->exten, exten, sizeof(chan->context) - 1);
3435 chan->priority = priority - 1;
3436 ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO);
3438 ast_mutex_unlock(&chan->lock);
3440 /* In order to do it when the channel doesn't really exist within
3441 the PBX, we have to make a new channel, masquerade, and start the PBX
3442 at the new location */
3443 struct ast_channel *tmpchan;
3444 struct ast_frame *f;
3445 tmpchan = ast_channel_alloc(0);
3447 snprintf(tmpchan->name, sizeof(tmpchan->name), "AsyncGoto/%s", chan->name);
3448 ast_setstate(tmpchan, chan->_state);
3449 /* Make formats okay */
3450 tmpchan->readformat = chan->readformat;
3451 tmpchan->writeformat = chan->writeformat;
3452 /* Setup proper location */
3453 if (context && strlen(context))
3454 strncpy(tmpchan->context, context, sizeof(tmpchan->context) - 1);
3456 strncpy(tmpchan->context, chan->context, sizeof(tmpchan->context) - 1);
3457 if (exten && strlen(exten))
3458 strncpy(tmpchan->exten, exten, sizeof(tmpchan->exten) - 1);
3460 strncpy(tmpchan->exten, chan->exten, sizeof(tmpchan->exten) - 1);
3462 tmpchan->priority = priority;
3464 tmpchan->priority = chan->priority;
3466 ast_mutex_unlock(&chan->lock);
3468 /* Masquerade into temp channel */
3469 ast_channel_masquerade(tmpchan, chan);
3471 /* Make the masquerade happen by reading a frame from the tmp channel */
3472 f = ast_read(tmpchan);
3475 /* Start the PBX going on our stolen channel */
3476 if (ast_pbx_start(tmpchan)) {
3477 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name);
3478 ast_hangup(tmpchan);
3484 ast_mutex_unlock(&chan->lock);
3490 int ast_async_goto_by_name(char *channame, char *context, char *exten, int priority)
3492 struct ast_channel *chan;
3493 chan = ast_channel_walk(NULL);
3495 if (!strcasecmp(channame, chan->name))
3497 chan = ast_channel_walk(chan);
3500 return ast_async_goto(chan, context, exten, priority, 1);
3504 static void ext_strncpy(char *dst, char *src, int len)
3507 while(*src && (count < len - 1)) {
3510 //otherwise exten => [a-b],1,... doesn't work
3525 * EBUSY - can't lock
3526 * EEXIST - extension with the same priority exist and no replace is set
3529 int ast_add_extension2(struct ast_context *con,
3530 int replace, char *extension, int priority, char *callerid,
3531 char *application, void *data, void (*datad)(void *),
3535 #define LOG do { if (option_debug) {\
3536 if (tmp->matchcid) { \
3537 ast_log(LOG_DEBUG, "Added extension '%s' priority %d (CID match '%s') to %s\n", tmp->exten, tmp->priority, tmp->cidmatch, con->name); \
3539 ast_log(LOG_DEBUG, "Added extension '%s' priority %d to %s\n", tmp->exten, tmp->priority, con->name); \
3541 } else if (option_verbose > 2) { \
3542 if (tmp->matchcid) { \
3543 ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d (CID match '%s')to %s\n", tmp->exten, tmp->priority, tmp->cidmatch, con->name); \
3545 ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d to %s\n", tmp->exten, tmp->priority, con->name); \
3550 * This is a fairly complex routine. Different extensions are kept
3551 * in order by the extension number. Then, extensions of different
3552 * priorities (same extension) are kept in a list, according to the
3555 struct ast_exten *tmp, *e, *el = NULL, *ep = NULL;
3557 /* Be optimistic: Build the extension structure first */
3558 tmp = malloc(sizeof(struct ast_exten));
3560 memset(tmp, 0, sizeof(struct ast_exten));
3561 ext_strncpy(tmp->exten, extension, sizeof(tmp->exten));
3562 tmp->priority = priority;
3564 ext_strncpy(tmp->cidmatch, callerid, sizeof(tmp->cidmatch));
3567 strcpy(tmp->cidmatch, "");
3570 strncpy(tmp->app, application, sizeof(tmp->app)-1);
3574 tmp->registrar = registrar;
3578 ast_log(LOG_WARNING, "Out of memory\n");
3582 if (ast_mutex_lock(&con->lock)) {
3584 /* And properly destroy the data */
3586 ast_log(LOG_WARNING, "Failed to lock context '%s'\n", con->name);
3592 res= strcasecmp(e->exten, extension);
3594 if (!e->matchcid && !tmp->matchcid)
3596 else if (tmp->matchcid && !e->matchcid)
3598 else if (e->matchcid && !tmp->matchcid)
3601 res = strcasecmp(e->cidmatch, tmp->cidmatch);
3604 /* We have an exact match, now we find where we are
3605 and be sure there's no duplicates */
3607 if (e->priority == tmp->priority) {
3608 /* Can't have something exactly the same. Is this a
3609 replacement? If so, replace, otherwise, bonk. */
3612 /* We're in the peer list, insert ourselves */
3614 tmp->peer = e->peer;
3616 /* We're the first extension. Take over e's functions */
3618 tmp->next = e->next;
3619 tmp->peer = e->peer;