Merge hint patch, add new variables, and misc. PBX cleanups
[asterisk/asterisk.git] / pbx.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * Core PBX routines.
5  * 
6  * Copyright (C) 1999, Mark Spencer
7  *
8  * Mark Spencer <markster@linux-support.net>
9  *
10  * This program is free software, distributed under the terms of
11  * the GNU General Public License
12  */
13
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/term.h>
24 #include <asterisk/manager.h>
25 #include <asterisk/ast_expr.h>
26 #include <asterisk/channel_pvt.h>
27 #include <asterisk/linkedlists.h>
28 #include <string.h>
29 #include <unistd.h>
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <setjmp.h>
33 #include <ctype.h>
34 #include <errno.h>
35 #include <time.h>
36 #include <sys/time.h>
37 #include "asterisk.h"
38
39 /*
40  * I M P O R T A N T :
41  *
42  *              The speed of extension handling will likely be among the most important
43  * aspects of this PBX.  The switching scheme as it exists right now isn't
44  * terribly bad (it's O(N+M), where N is the # of extensions and M is the avg #
45  * of priorities, but a constant search time here would be great ;-) 
46  *
47  */
48
49
50 struct ast_context;
51
52 struct ast_pbx {
53         int dtimeout;                                   /* Timeout between digits (seconds) */
54         int rtimeout;                                   /* Timeout for response (seconds) */
55 };
56
57 /* An extension */
58 struct ast_exten {
59         char exten[AST_MAX_EXTENSION];
60         int matchcid;
61         char cidmatch[AST_MAX_EXTENSION];
62         int priority;
63         /* An extension */
64         struct ast_context *parent;
65         /* Application to execute */
66         char app[AST_MAX_EXTENSION];
67         /* Data to use */
68         void *data;
69         /* Data destructor */
70         void (*datad)(void *);
71         /* Next higher priority with our extension */
72         struct ast_exten *peer;
73         /* Registrar */
74         char *registrar;
75         /* Extension with a greater ID */
76         struct ast_exten *next;
77 };
78
79 struct ast_include {
80         char name[AST_MAX_EXTENSION];
81         char rname[AST_MAX_EXTENSION];
82         char *registrar;
83         int hastime;
84         unsigned int monthmask;
85         unsigned int daymask;
86         unsigned int dowmask;
87         unsigned int minmask[24];
88         struct ast_include *next;
89 };
90
91 struct ast_sw {
92         char name[AST_MAX_EXTENSION];
93         char *registrar;
94         char data[AST_MAX_EXTENSION];
95         struct ast_sw *next;
96 };
97
98 struct ast_ignorepat {
99         char pattern[AST_MAX_EXTENSION];
100         char *registrar;
101         struct ast_ignorepat *next;
102 };
103
104 /* An extension context */
105 struct ast_context {
106         /* Name of the context */
107         char name[AST_MAX_EXTENSION];
108         /* A lock to prevent multiple threads from clobbering the context */
109         pthread_mutex_t lock;
110         /* The root of the list of extensions */
111         struct ast_exten *root;
112         /* Link them together */
113         struct ast_context *next;
114         /* Include other contexts */
115         struct ast_include *includes;
116         /* Patterns for which to continue playing dialtone */
117         struct ast_ignorepat *ignorepats;
118         /* Registrar */
119         char *registrar;
120         /* Alternative switches */
121         struct ast_sw *alts;
122 };
123
124
125 /* An application */
126 struct ast_app {
127         /* Name of the application */
128         char name[AST_MAX_APP];
129         int (*execute)(struct ast_channel *chan, void *data);
130         char *synopsis;
131         char *description;
132         struct ast_app *next;
133 };
134
135 /* An extension state notify */
136 struct ast_notify_cb {
137     int id;
138     void *data;
139     ast_notify_cb_type callback;
140     struct ast_notify_cb *next;
141 };
142             
143 struct ast_notify {
144     struct ast_exten *exten;
145     int laststate; 
146     struct ast_notify_cb *callbacks;
147     struct ast_notify *next;
148 };
149
150
151 static int pbx_builtin_prefix(struct ast_channel *, void *);
152 static int pbx_builtin_stripmsd(struct ast_channel *, void *);
153 static int pbx_builtin_answer(struct ast_channel *, void *);
154 static int pbx_builtin_goto(struct ast_channel *, void *);
155 static int pbx_builtin_hangup(struct ast_channel *, void *);
156 static int pbx_builtin_background(struct ast_channel *, void *);
157 static int pbx_builtin_dtimeout(struct ast_channel *, void *);
158 static int pbx_builtin_rtimeout(struct ast_channel *, void *);
159 static int pbx_builtin_atimeout(struct ast_channel *, void *);
160 static int pbx_builtin_wait(struct ast_channel *, void *);
161 static int pbx_builtin_setlanguage(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_setvar(struct ast_channel *, void *);
166 static int pbx_builtin_setglobalvar(struct ast_channel *, void *);
167 static int pbx_builtin_noop(struct ast_channel *, void *);
168 static int pbx_builtin_gotoif(struct ast_channel *, void *);
169 void pbx_builtin_setvar_helper(struct ast_channel *chan, char *name, char *value);
170 char *pbx_builtin_getvar_helper(struct ast_channel *chan, char *name);
171
172 static struct varshead globals = AST_LIST_HEAD_INITIALIZER(varshead);
173
174 static struct pbx_builtin {
175         char name[AST_MAX_APP];
176         int (*execute)(struct ast_channel *chan, void *data);
177         char *synopsis;
178         char *description;
179 } builtins[] = 
180 {
181         /* These applications are built into the PBX core and do not
182            need separate modules */
183         { "Answer", pbx_builtin_answer, 
184 "Answer a channel if ringing", 
185 "  Answer(): If the channel is ringing, answer it, otherwise do nothing. \n"
186 "Returns 0 unless it tries to answer the channel and fails.\n"   },
187
188         { "Goto", pbx_builtin_goto, 
189 "Goto a particular priority, extension, or context",
190 "  Goto([[context|]extension|]priority):  Set the  priority to the specified\n"
191 "value, optionally setting the extension and optionally the context as well.\n"
192 "The extension BYEXTENSION is special in that it uses the current extension,\n"
193 "thus  permitting  you  to go to a different  context, without  specifying a\n"
194 "specific extension. Always returns 0, even if the given context, extension,\n"
195 "or priority is invalid.\n" },
196
197         { "Hangup", pbx_builtin_hangup,
198 "Unconditional hangup",
199 "  Hangup(): Unconditionally hangs up a given channel by returning -1 always.\n" },
200
201         { "DigitTimeout", pbx_builtin_dtimeout,
202 "Set maximum timeout between digits",
203 "  DigitTimeout(seconds): Set the  maximum  amount of time permitted between\n"
204 "digits when the user is typing in an extension.  When this timeout expires,\n"
205 "after the user has started to  type  in an extension, the extension will be\n"
206 "considered  complete, and  will be interpreted.  Note that if an  extension\n"
207 "typed in is valid, it will not have to timeout to be tested,  so  typically\n"
208 "at  the  expiry of  this timeout, the  extension will be considered invalid\n"
209 "(and  thus  control  would be passed to the 'i' extension, or if it doesn't\n"
210 "exist the call would be terminated).  Always returns 0.\n" },
211
212         { "ResponseTimeout", pbx_builtin_rtimeout,
213 "Set maximum timeout awaiting response",
214 "  ResponseTimeout(seconds): Set the maximum amount of time permitted after\n"
215 "falling through a series of priorities for a channel in which the user may\n"
216 "begin typing an extension.  If the user does not type an extension in this\n"
217 "amount of time, control will pass to the 't' extension if  it  exists, and\n"
218 "if not the call would be terminated.  Always returns 0.\n"  },
219
220         { "AbsoluteTimeout", pbx_builtin_atimeout,
221 "Set absolute maximum time of call",
222 "  AbsoluteTimeout(seconds): Set the absolute maximum amount of time permitted\n"
223 "for a call.  A setting of 0 disables the timeout.  Always returns 0.\n" },
224
225         { "BackGround", pbx_builtin_background,
226 "Play a file while awaiting extension",
227 "  Background(filename): Plays a given file, while simultaneously waiting for\n"
228 "the user to begin typing an extension. The  timeouts  do not count until the\n"
229 "last BackGround application as ended. Always returns 0.\n" },
230
231         { "Wait", pbx_builtin_wait, 
232 "Waits for some time", 
233 "  Wait(seconds): Waits for a specified number of seconds, then returns 0.\n" },
234
235         { "StripMSD", pbx_builtin_stripmsd,
236 "Strip leading digits",
237 "  StripMSD(count): Strips the leading  'count'  digits  from  the  channel's\n"
238 "associated extension. For example, the  number  5551212 when stripped with a\n"
239 "count of 3 would be changed to 1212.  This app always returns 0, and the PBX\n"
240 "will continue processing at the next priority for the *new* extension.\n"
241 "  So, for  example, if  priority 3 of 5551212  is  StripMSD 3, the next step\n"
242 "executed will be priority 4 of 1212.  If you switch into an  extension which\n"
243 "has no first step, the PBX will treat it as though the user dialed an\n"
244 "invalid extension.\n" },
245
246         { "Prefix", pbx_builtin_prefix, 
247 "Prepend leading digits",
248 "  Prefix(digits): Prepends the  digit  string  specified  by  digits to the\n"
249 "channel's associated extension. For example, the number 1212 when  prefixed\n"
250 "with '555' will become 5551212. This app always returns 0, and the PBX will\n"
251 "continue processing at the next priority for the *new* extension.\n"
252 "  So, for example, if priority  3  of 1212 is  Prefix  555, the  next  step\n"
253 "executed will be priority 4 of 5551212. If  you  switch  into an  extension\n"
254 "which has no first step, the PBX will treat it as though the user dialed an\n"
255 "invalid extension.\n" },
256
257         { "SetLanguage", pbx_builtin_setlanguage,
258 "Sets user language",
259 "  SetLanguage(language):  Set  the  channel  language to 'language'.  This\n"
260 "information is used for the generation of numbers, and to select a natural\n"
261 "language file when available.  For example, if language is set to 'fr' and\n"
262 "the file 'demo-congrats' is requested  to  be  played,  if the file 'demo-\n"
263 "congrats-fr' exists, then it will play that file, and if not will play the\n"
264 "normal 'demo-congrats'. Always returns 0.\n"  },
265
266         { "Ringing", pbx_builtin_ringing,
267 "Indicate ringing tone",
268 "  Ringing(): Request that the channel indicate ringing tone to the user.\n"
269 "Always returns 0.\n" },
270
271         { "Congestion", pbx_builtin_congestion,
272 "Indicate congestion and stop",
273 "  Congestion(): Requests that the channel indicate congestion and then\n"
274 "waits for the user to hang up.  Always returns -1." },
275
276         { "Busy", pbx_builtin_busy,
277 "Indicate busy condition and stop",
278 "  Busy(): Requests that the channel indicate busy condition and then waits\n"
279 "for the user to hang up.  Always returns -1." },
280
281         { "SetVar", pbx_builtin_setvar,
282 "Set variable to value",
283 "  Setvar(#n=value): Sets variable n to value" },
284
285         { "SetGlobalVar", pbx_builtin_setglobalvar,
286 "Set variable to value",
287 "  Setvar(#n=value): Sets global variable n to value" },
288
289         { "NoOp", pbx_builtin_noop,
290 "No operation",
291 "  NoOp(): No-operation; Does nothing." },
292
293         { "GotoIf", pbx_builtin_gotoif,
294 "Conditional goto",
295 "  GotoIf(Condition?label1:label2): Go to label 1 if condition is\n"
296 "true, to label2 if condition is false. Either label1 or label2 may be\n"
297 "omitted (in that case, we just don't take the particular branch) but not\n"
298 "both.  Look for the condition syntax in examples or documentation." },
299
300 };
301
302 /* Lock for the application list */
303 static pthread_mutex_t applock = AST_MUTEX_INITIALIZER;
304 static struct ast_context *contexts = NULL;
305 /* Lock for the ast_context list */
306 static pthread_mutex_t conlock = AST_MUTEX_INITIALIZER;
307 static struct ast_app *apps = NULL;
308
309 /* Lock for switches */
310 static pthread_mutex_t switchlock = AST_MUTEX_INITIALIZER;
311 struct ast_switch *switches = NULL;
312
313 /* Lock for extension state notifys */
314 static pthread_mutex_t notifylock = AST_MUTEX_INITIALIZER;
315 static int notifycnt = 0;
316 struct ast_notify *notifys = NULL;
317
318 int pbx_exec(struct ast_channel *c, /* Channel */
319                                         struct ast_app *app,
320                                         void *data,                             /* Data for execution */
321                                         int newstack)                   /* Force stack increment */
322 {
323         /* This function is special.  It saves the stack so that no matter
324            how many times it is called, it returns to the same place */
325         int res;
326         int stack = c->stack;
327         int (*execute)(struct ast_channel *chan, void *data) = app->execute; 
328         if (newstack && stack > AST_CHANNEL_MAX_STACK - 2) {
329                 /* Don't allow us to go over the max number of stacks we
330                    permit saving. */
331                 ast_log(LOG_WARNING, "Stack overflow, cannot create another stack\n");
332                 return -1;
333         }
334         if (newstack && (res = setjmp(c->jmp[++c->stack]))) {
335                 /* Okay, here's where it gets weird.  If newstack is non-zero, 
336                    then we increase the stack increment, but setjmp is not going
337                    to return until longjmp is called -- when the application
338                    exec'd is finished running. */
339                 if (res == 1)
340                         res = 0;
341                 if (c->stack != stack + 1) 
342                         ast_log(LOG_WARNING, "Stack returned to an unexpected place!\n");
343                 else if (c->app[c->stack])
344                         ast_log(LOG_WARNING, "Application may have forgotten to free its memory\n");
345                 c->stack = stack;
346                 return res;
347         } else {
348                 if (c->cdr)
349                         ast_cdr_setapp(c->cdr, app->name, data);
350                 c->appl = app->name;
351                 c->data = data;         
352                 res = execute(c, data);
353                 c->appl = NULL;
354                 c->data = NULL;         
355                 /* Any application that returns, we longjmp back, just in case. */
356                 if (c->stack != stack + 1)
357                         ast_log(LOG_WARNING, "Stack is not at expected value\n");
358                 longjmp(c->jmp[stack+1], res);
359                 /* Never returns */
360         }
361 }
362
363
364 /* Go no deeper than this through includes (not counting loops) */
365 #define AST_PBX_MAX_STACK       64
366
367 #define HELPER_EXISTS 0
368 #define HELPER_SPAWN 1
369 #define HELPER_EXEC 2
370 #define HELPER_CANMATCH 3
371 #define HELPER_MATCHMORE 4
372
373 struct ast_app *pbx_findapp(char *app) 
374 {
375         struct ast_app *tmp;
376         if (ast_pthread_mutex_lock(&applock)) {
377                 ast_log(LOG_WARNING, "Unable to obtain application lock\n");
378                 return NULL;
379         }
380         tmp = apps;
381         while(tmp) {
382                 if (!strcasecmp(tmp->name, app))
383                         break;
384                 tmp = tmp->next;
385         }
386         ast_pthread_mutex_unlock(&applock);
387         return tmp;
388 }
389
390 static struct ast_switch *pbx_findswitch(char *sw)
391 {
392         struct ast_switch *asw;
393         if (ast_pthread_mutex_lock(&switchlock)) {
394                 ast_log(LOG_WARNING, "Unable to obtain application lock\n");
395                 return NULL;
396         }
397         asw = switches;
398         while(asw) {
399                 if (!strcasecmp(asw->name, sw))
400                         break;
401                 asw = asw->next;
402         }
403         ast_pthread_mutex_unlock(&switchlock);
404         return asw;
405 }
406
407 static inline int include_valid(struct ast_include *i)
408 {
409         struct tm *tm;
410         time_t t;
411         if (!i->hastime)
412                 return 1;
413         time(&t);
414         tm = localtime(&t);
415         if (!tm) {
416                 ast_log(LOG_WARNING, "Failed to get local time\n");
417                 return 0;
418         }
419
420         /* If it's not the right month, return */
421         if (!(i->monthmask & (1 << tm->tm_mon))) {
422                 return 0;
423         }
424
425         /* If it's not that time of the month.... */
426         /* Warning, tm_mday has range 1..31! */
427         if (!(i->daymask & (1 << (tm->tm_mday-1))))
428                 return 0;
429
430         /* If it's not the right day of the week */
431         if (!(i->dowmask & (1 << tm->tm_wday)))
432                 return 0;
433
434         /* Sanity check the hour just to be safe */
435         if ((tm->tm_hour < 0) || (tm->tm_hour > 23)) {
436                 ast_log(LOG_WARNING, "Insane time...\n");
437                 return 0;
438         }
439
440         /* Now the tough part, we calculate if it fits
441            in the right time based on min/hour */
442         if (!(i->minmask[tm->tm_hour] & (1 << (tm->tm_min / 2))))
443                 return 0;
444
445         /* If we got this far, then we're good */
446         return 1;
447 }
448
449 static void pbx_destroy(struct ast_pbx *p)
450 {
451         free(p);
452 }
453
454 #define EXTENSION_MATCH_CORE(data,pattern,match) {\
455         /* All patterns begin with _ */\
456         if (pattern[0] != '_') \
457                 return 0;\
458         /* Start optimistic */\
459         match=1;\
460         pattern++;\
461         while(match && *data && *pattern && (*pattern != '/')) {\
462                 switch(toupper(*pattern)) {\
463                 case '[': \
464                 {\
465                         int i,border=0;\
466                         char *where;\
467                         match=0;\
468                         pattern++;\
469                         where=strchr(pattern,']');\
470                         if (where)\
471                                 border=(int)(where-pattern);\
472                         if (!where || border > strlen(pattern)) {\
473                                 ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n");\
474                                 return match;\
475                         }\
476                         for (i=0; i<border; i++) {\
477                                 int res=0;\
478                                 if (i+2<border)\
479                                         if (pattern[i+1]=='-') {\
480                                                 if (*data >= pattern[i] && *data <= pattern[i+2]) {\
481                                                         res=1;\
482                                                 } else {\
483                                                         i+=2;\
484                                                         continue;\
485                                                 }\
486                                         }\
487                                 if (res==1 || *data==pattern[i]) {\
488                                         match = 1;\
489                                         break;\
490                                 }\
491                         }\
492                         pattern+=border;\
493                         break;\
494                 }\
495                 case 'N':\
496                         if ((*data < '2') || (*data > '9'))\
497                                 match=0;\
498                         break;\
499                 case 'X':\
500                         if ((*data < '0') || (*data > '9'))\
501                                 match = 0;\
502                         break;\
503                 case 'Z':\
504                         if ((*data < '1') || (*data > '9'))\
505                                 match = 0;\
506                         break;\
507                 case '.':\
508                         /* Must match */\
509                         return 1;\
510                 case ' ':\
511                 case '-':\
512                         /* Ignore these characters */\
513                         data--;\
514                         break;\
515                 default:\
516                         if (*data != *pattern)\
517                                 match =0;\
518                 }\
519                 data++;\
520                 pattern++;\
521         }\
522 }
523
524 int ast_extension_match(char *pattern, char *data)
525 {
526         int match;
527         /* If they're the same return */
528         if (!strcmp(pattern, data))
529                 return 1;
530         EXTENSION_MATCH_CORE(data,pattern,match);
531         /* Must be at the end of both */
532         if (*data || (*pattern && (*pattern != '/')))
533                 match = 0;
534         return match;
535 }
536
537 static int extension_close(char *pattern, char *data, int needmore)
538 {
539         int match;
540         /* If "data" is longer, it can'be a subset of pattern unless
541            pattern is a pattern match */
542         if ((strlen(pattern) < strlen(data)) && (pattern[0] != '_'))
543                 return 0;
544         
545         if ((!strlen((char *)data) || !strncasecmp(pattern, data, strlen(data))) && 
546                 (!needmore || (strlen(pattern) > strlen(data)))) {
547                 return 1;
548         }
549         EXTENSION_MATCH_CORE(data,pattern,match);
550         /* If there's more or we don't care about more, return non-zero, otlherwise it's a miss */
551         if (!needmore || *pattern) {
552                 return match;
553         } else
554                 return 0;
555 }
556
557 struct ast_context *ast_context_find(char *name)
558 {
559         struct ast_context *tmp;
560         ast_pthread_mutex_lock(&conlock);
561         if (name) {
562                 tmp = contexts;
563                 while(tmp) {
564                         if (!strcasecmp(name, tmp->name))
565                                 break;
566                         tmp = tmp->next;
567                 }
568         } else
569                 tmp = contexts;
570         ast_pthread_mutex_unlock(&conlock);
571         return tmp;
572 }
573
574 #define STATUS_NO_CONTEXT   1
575 #define STATUS_NO_EXTENSION 2
576 #define STATUS_NO_PRIORITY  3
577 #define STATUS_SUCCESS      4
578
579 static int matchcid(char *cidpattern, char *callerid)
580 {
581         char tmp[AST_MAX_EXTENSION];
582         int failresult;
583         char *name, *num;
584         
585         /* If the Caller*ID pattern is empty, then we're matching NO Caller*ID, so
586            failing to get a number should count as a match, otherwise not */
587
588
589         if (strlen(cidpattern))
590                 failresult = 0;
591         else
592                 failresult = 1;
593
594         if (!callerid)
595                 return failresult;
596
597         /* Copy original Caller*ID */
598         strncpy(tmp, callerid, sizeof(tmp)-1);
599         /* Parse Number */
600         if (ast_callerid_parse(tmp, &name, &num)) 
601                 return failresult;
602         if (!num)
603                 return failresult;
604         ast_shrink_phone_number(num);
605         return ast_extension_match(cidpattern, num);
606 }
607
608 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)
609 {
610         int x, res;
611         struct ast_context *tmp;
612         struct ast_exten *e, *eroot;
613         struct ast_include *i;
614         struct ast_sw *sw;
615         struct ast_switch *asw;
616         /* Initialize status if appropriate */
617         if (!*stacklen) {
618                 *status = STATUS_NO_CONTEXT;
619                 *swo = NULL;
620                 *data = NULL;
621         }
622         /* Check for stack overflow */
623         if (*stacklen >= AST_PBX_MAX_STACK) {
624                 ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n");
625                 return NULL;
626         }
627         /* Check first to see if we've already been checked */
628         for (x=0;x<*stacklen;x++) {
629                 if (!strcasecmp(incstack[x], context))
630                         return NULL;
631         }
632         tmp = contexts;
633         while(tmp) {
634                 /* Match context */
635                 if (!strcmp(tmp->name, context)) {
636                         if (*status < STATUS_NO_EXTENSION)
637                                 *status = STATUS_NO_EXTENSION;
638                         eroot = tmp->root;
639                         while(eroot) {
640                                 /* Match extension */
641                                 if ((((action != HELPER_MATCHMORE) && ast_extension_match(eroot->exten, exten)) ||
642                                                 ((action == HELPER_CANMATCH) && (extension_close(eroot->exten, exten, 0))) ||
643                                                 ((action == HELPER_MATCHMORE) && (extension_close(eroot->exten, exten, 1)))) &&
644                                                 (!eroot->matchcid || matchcid(eroot->cidmatch, callerid))) {
645                                                 e = eroot;
646                                                 if (*status < STATUS_NO_PRIORITY)
647                                                         *status = STATUS_NO_PRIORITY;
648                                                 while(e) {
649                                                         /* Match priority */
650                                                         if (e->priority == priority) {
651                                                                 *status = STATUS_SUCCESS;
652                                                                 return e;
653                                                         }
654                                                         e = e->peer;
655                                                 }
656                                 }
657                                 eroot = eroot->next;
658                         }
659                         /* Check alternative switches */
660                         sw = tmp->alts;
661                         while(sw) {
662                                 if ((asw = pbx_findswitch(sw->name))) {
663                                         if (action == HELPER_CANMATCH)
664                                                 res = asw->canmatch ? asw->canmatch(chan, context, exten, priority, callerid, sw->data) : 0;
665                                         else if (action == HELPER_MATCHMORE)
666                                                 res = asw->matchmore ? asw->matchmore(chan, context, exten, priority, callerid, sw->data) : 0;
667                                         else
668                                                 res = asw->exists ? asw->exists(chan, context, exten, priority, callerid, sw->data) : 0;
669                                         if (res) {
670                                                 /* Got a match */
671                                                 *swo = asw;
672                                                 *data = sw->data;
673                                                 return NULL;
674                                         }
675                                 } else {
676                                         ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name);
677                                 }
678                                 sw = sw->next;
679                         }
680                         /* Setup the stack */
681                         incstack[*stacklen] = tmp->name;
682                         (*stacklen)++;
683                         /* Now try any includes we have in this context */
684                         i = tmp->includes;
685                         while(i) {
686                                 if (include_valid(i)) {
687                                         if ((e = pbx_find_extension(chan, i->rname, exten, priority, callerid, action, incstack, stacklen, status, swo, data))) 
688                                                 return e;
689                                         if (*swo) 
690                                                 return NULL;
691                                 }
692                                 i = i->next;
693                         }
694                 }
695                 tmp = tmp->next;
696         }
697         return NULL;
698 }
699
700 static void pbx_substitute_variables_temp(struct ast_channel *c,char *cp3,char **cp4, char *workspace, int workspacelen)
701 {
702         char *first,*second;
703         int offset,offset2;
704         struct ast_var_t *variables;
705         char *name, *num; /* for callerid name + num variables */
706         struct varshead *headp;
707         headp=&c->varshead;
708         *cp4=NULL;
709         /* Now we have the variable name on cp3 */
710         if ((first=strchr(cp3,':'))) {
711                 *first='\0';
712                 pbx_substitute_variables_temp(c,cp3,cp4,workspace,workspacelen);
713                 if (!(*cp4)) return;
714                 offset=atoi(first+1);
715                 if ((second=strchr(first+1,':'))) {
716                         *second='\0';
717                         offset2=atoi(second+1);
718                 } else
719                         offset2=strlen(*cp4)-offset;
720                 if (abs(offset)>strlen(*cp4)) {
721                         if (offset>=0) offset=strlen(*cp4);
722                         else offset=-strlen(*cp4);
723                 }
724                 if ((offset<0 && offset2>-offset) || (offset>=0 && offset+offset2>strlen(*cp4))) {
725                         if (offset>=0) offset2=strlen(*cp4)-offset;
726                         else offset2=strlen(*cp4)+offset;
727                 }
728                 if (offset>=0)
729                         *cp4+=offset;
730                 else
731                         *cp4+=strlen(*cp4)+offset;
732                 (*cp4)[offset2] = '\0';
733         } else if (!strcmp(cp3, "CALLERIDNUM")) {
734                 if (c->callerid)
735                         strncpy(workspace, c->callerid, workspacelen - 1);
736                 ast_callerid_parse(workspace, &name, &num);
737                 if (num) {
738                         ast_shrink_phone_number(num);
739                         *cp4 = num;
740                 } else
741                         *cp4 = "";
742         } else if (!strcmp(cp3, "CALLERIDNAME")) {
743                 if (c->callerid)
744                         strncpy(workspace, c->callerid, workspacelen - 1);
745                 ast_callerid_parse(workspace, &name, &num);
746                 if (name)
747                         *cp4 = name;
748                 else
749                         *cp4 = "";
750         } else if (!strcmp(cp3, "CALLERID")) {
751                 *cp4 = c->callerid;
752                 if (!(*cp4))
753                         *cp4 = "";
754         } else if (!strcmp(cp3, "HINT")) {
755                 if (!ast_get_hint(workspace, workspacelen - 1, c, c->context, c->exten))
756                         *cp4 = "";
757                 else
758                         *cp4 = workspace;
759         } else if (!strcmp(cp3, "EXTEN")) {
760                 *cp4 = c->exten;
761         } else if (!strncmp(cp3, "EXTEN-", strlen("EXTEN-")) && 
762                 /* XXX Remove me eventually */
763                 (sscanf(cp3 + strlen("EXTEN-"), "%d", &offset) == 1)) {
764                 if (offset < 0)
765                         offset=0;
766                 if (offset > strlen(c->exten))
767                         offset = strlen(c->exten);
768                 *cp4 = c->exten + offset;
769                 ast_log(LOG_WARNING, "The use of 'EXTEN-foo' has been derprecated in favor of 'EXTEN:foo'\n");
770 #if 0
771         } else if (!strncmp(cp3, "EXTEN:", strlen("EXTEN:")) && 
772                 (sscanf(cp3 + strlen("EXTEN:"), "%d", &offset) == 1)) {
773                 if (offset < 0)
774                         offset=0;
775                 if (offset > strlen(c->exten))
776                         offset = strlen(c->exten);
777                 *cp4 = c->exten + offset;
778 #endif
779         } else if (!strcmp(cp3, "RDNIS")) {
780                 *cp4 = c->rdnis;
781                 if (!(*cp4))
782                         *cp4 = "";
783         } else if (!strcmp(cp3, "CONTEXT")) {
784                 *cp4 = c->context;
785         } else if (!strcmp(cp3, "PRIORITY")) {
786                 snprintf(workspace, workspacelen, "%d", c->priority);
787                 *cp4 = workspace;
788         } else if (!strcmp(cp3, "CHANNEL")) {
789                 *cp4 = c->name;
790         } else {
791                 AST_LIST_TRAVERSE(headp,variables,entries) {
792 #if 0
793                         ast_log(LOG_WARNING,"Comparing variable '%s' with '%s'\n",cp3,ast_var_name(variables));
794 #endif
795                         if (strcasecmp(ast_var_name(variables),cp3)==0)
796                                 *cp4=ast_var_value(variables);
797                 }
798                 if (!(*cp4)) {
799                         /* Try globals */
800                         AST_LIST_TRAVERSE(&globals,variables,entries) {
801 #if 0
802                                 ast_log(LOG_WARNING,"Comparing variable '%s' with '%s'\n",cp3,ast_var_name(variables));
803 #endif
804                                 if (strcasecmp(ast_var_name(variables),cp3)==0)
805                                         *cp4=ast_var_value(variables);
806                         }
807                 }
808                 if (!(*cp4)) {
809                         int len=strlen(cp3);
810                         int len_env=strlen("ENV(");
811                         if (len > (len_env+1) && !strncasecmp(cp3,"ENV(",len_env) && !strcmp(cp3+len-1,")")) {
812                                 cp3[len-1]='\0';
813                                 *cp4=getenv(cp3+len_env);
814                         }
815                 }
816         }
817 }
818
819 static void pbx_substitute_variables_helper(struct ast_channel *c,char *cp1,char **ecp2,int count)
820 {
821         char *cp4,*cp2;
822         char *tmp,*wherearewe,*finish=NULL,*ltmp,*lval,*nextvar;
823         int length,variables=0;
824         char workspace[256];
825
826         wherearewe=tmp=cp1;
827         cp2=*ecp2;
828         *cp2='\0';
829         do {
830                 char *start,*start2;
831                 if ((tmp=strstr(wherearewe,"${"))) {
832                         variables++;
833                         length=(int)(tmp-wherearewe);
834                         strncat(cp2,wherearewe,length);
835                         wherearewe=tmp;
836                         
837                         ltmp=malloc(sizeof(char)*256);
838                         start=start2=tmp+1;
839                         do {
840                                 if (variables==0) {
841                                         nextvar=strstr(start2,"${");
842                                         if (nextvar) {
843                                                 if ((int)(finish-nextvar)>0) {
844                                                         variables++;
845                                                         start2=nextvar+1;
846                                                 } else break;
847                                         } else break;
848                                 }
849                                 finish=strchr(start,'}');
850                                 if (finish) {
851                                         variables--;
852                                         start=finish+1;
853                                 } else {
854                                         if (variables>0) {
855                                                 ast_log(LOG_NOTICE, "Error in extension logic\n");
856                                                 cp2[0]='\0';
857                                                 return;
858                                         }
859                                         break;
860                                 }
861                         } while (1);
862                         
863                         length=(int)(finish-tmp);
864                         wherearewe+=length+1;
865                         lval=strndup(tmp+2,length-2);
866                         pbx_substitute_variables_helper(c,lval,&ltmp,count+1);
867                         free(lval);
868                         if (ltmp) {
869                                 length=strlen(ltmp);
870                                 strncat(cp2,ltmp,length);
871                         }
872                 } else {
873                         if (wherearewe!=cp1) {
874                                 if (*wherearewe) {
875                                         length=strlen(wherearewe);
876                                         strncat(cp2,wherearewe,length);
877                                 }
878                                 strcat(cp2,"\0");
879                                 
880                                 cp1=cp2;
881                         }
882                         if (count) {                    
883                                 pbx_substitute_variables_temp(c,cp1,&cp4, workspace, sizeof(workspace));
884                                 if (cp4) {
885                                         /* reset output variable so we could store the result */
886                                         *cp2='\0';
887                                         length=strlen(cp4);
888                                         strncat(cp2,cp4,length);
889                                 } else
890                                         cp2[0]='\0';
891                         }
892                         break;
893                 }
894         } while(1);
895 }
896
897 static void *pbx_substitute_variables(struct ast_channel *c, struct ast_exten *e) {
898         char *cp1,*cp3,*cp4,*cp5;
899         char *cp2;
900         char c1,c2;
901         int m,mve,origlen,quoted,dolsign,docopy;
902         
903         /* No variables or expressions in e->data, so why scan it? */
904         if (!strstr(e->data,"${") && !strstr(e->data,"$[")) {
905                 return strndup(e->data,strlen(e->data)+1);
906         }
907         
908         cp1=e->data;
909         cp2=malloc(sizeof(char)*256);
910         pbx_substitute_variables_helper(c,cp1,(char **)&cp2,0);
911
912         /* Second stage, expression evaluation */
913         if ((strstr(cp2,"$[")==NULL)) {
914                 /* No expressions in cp2, return it */
915                 return(cp2);
916         }
917         /* else, do expression evaluation */
918         
919         dolsign=0;
920         docopy=1;
921         origlen=strlen(cp2)+1;
922         
923         cp5=malloc(origlen);
924         memset(cp5,0,origlen);
925         cp4=NULL;
926         cp1=cp2;
927         quoted=0;
928         
929         do {
930                 c1=*cp1;
931                 mve=0;
932                 switch (c1) {
933                         case '$' : 
934                                 dolsign=1;
935                                 docopy=0;
936                                 break;
937                         case '[' :
938                                 if (dolsign==0) {
939                                         docopy=1;
940                                         dolsign=0;
941                                         break;
942                                 }
943                                 dolsign=0;
944                                 docopy=0;
945                                 m=0;
946                                 mve=1;
947                                 cp1++;
948                                 
949                                 while (((c2=*(cp1+m))!=']') && (c2!='\0')) {
950                                         m++;
951                                 }
952                                 cp3=malloc(m+2);
953                                 strncpy(cp3,cp1,m);
954                                 cp3[m]='\0';
955                                 cp1+=m;
956                                 /* Now we have the expression to evaluate on cp3 */
957                                 cp4=ast_expr(cp3);
958                                 free(cp3);
959                                 break;
960                         default :
961                                 if (dolsign==1) {
962                                         strncat((char *)cp5,"$",1);
963                                 }
964                                 dolsign=0;
965                                 docopy=1;
966                                 mve=0;
967                                 break;
968                 }
969                 if (cp1!='\0') {
970                         if (mve==0) {
971                                 if (docopy==1) {
972                                         strncat((char *)cp5,&c1,1);
973                                 }
974                         } else {
975                                 if (cp4!=NULL) {
976                                         cp5=realloc(cp5,origlen+strlen(cp4)+1);
977                                         strncat((char *)cp5,cp4,strlen(cp4));
978                                         free(cp4);
979                                 } else {
980                                         ast_log(LOG_WARNING,"mve!=0 and cp4=NULL, something gone astray\n");
981                                 }
982                         }
983                 }
984                         
985         } while (*cp1++!='\0');
986         free(cp2);
987         return(cp5);
988 }
989                                 
990                         
991                                                                 
992
993 static int pbx_extension_helper(struct ast_channel *c, char *context, char *exten, int priority, char *callerid, int action) 
994 {
995         struct ast_exten *e;
996         struct ast_app *app;
997         struct ast_switch *sw;
998         char *data;
999         char *newdata;
1000         int newstack = 0;
1001         int res;
1002         int status = 0;
1003         char *incstack[AST_PBX_MAX_STACK];
1004         int stacklen = 0;
1005         char tmp[80];
1006         char tmp2[80];
1007         char tmp3[256];
1008         if (ast_pthread_mutex_lock(&conlock)) {
1009                 ast_log(LOG_WARNING, "Unable to obtain lock\n");
1010                 if ((action == HELPER_EXISTS) || (action == HELPER_CANMATCH) || (action == HELPER_MATCHMORE))
1011                         return 0;
1012                 else
1013                         return -1;
1014         }
1015         e = pbx_find_extension(c, context, exten, priority, callerid, action, incstack, &stacklen, &status, &sw, &data);
1016         if (e) {
1017                 switch(action) {
1018                 case HELPER_CANMATCH:
1019                         pthread_mutex_unlock(&conlock);
1020                         return -1;
1021                 case HELPER_EXISTS:
1022                         pthread_mutex_unlock(&conlock);
1023                         return -1;
1024                 case HELPER_MATCHMORE:
1025                         pthread_mutex_unlock(&conlock);
1026                         return -1;
1027                 case HELPER_SPAWN:
1028                         newstack++;
1029                         /* Fall through */
1030                 case HELPER_EXEC:
1031                         app = pbx_findapp(e->app);
1032                         pthread_mutex_unlock(&conlock);
1033                         if (app) {
1034                                 strncpy(c->context, context, sizeof(c->context-1));
1035                                 strncpy(c->exten, exten, sizeof(c->exten)-1);
1036                                 c->priority = priority;
1037                                 newdata=pbx_substitute_variables(c,e);
1038                                 if (option_debug)
1039                                                 ast_log(LOG_DEBUG, "Launching '%s'\n", app->name);
1040                                 else if (option_verbose > 2)
1041                                                 ast_verbose( VERBOSE_PREFIX_3 "Executing %s(\"%s\", \"%s\") %s\n", 
1042                                                                 term_color(tmp, app->name, COLOR_BRCYAN, 0, sizeof(tmp)),
1043                                                                 term_color(tmp2, c->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)),
1044                                                                 term_color(tmp3, (newdata ? (char *)newdata : NULL), COLOR_BRMAGENTA, 0, sizeof(tmp3)),
1045                                                                 (newstack ? "in new stack" : "in same stack"));
1046                                 res = pbx_exec(c, app, newdata, newstack);
1047                                 free(newdata);
1048                                 return res;
1049                         } else {
1050                                 ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority);
1051                                 return -1;
1052                         }
1053                 default:
1054                         ast_log(LOG_WARNING, "Huh (%d)?\n", action);                    return -1;
1055                 }
1056         } else if (sw) {
1057                 switch(action) {
1058                 case HELPER_CANMATCH:
1059                         pthread_mutex_unlock(&conlock);
1060                         return -1;
1061                 case HELPER_EXISTS:
1062                         pthread_mutex_unlock(&conlock);
1063                         return -1;
1064                 case HELPER_MATCHMORE:
1065                         pthread_mutex_unlock(&conlock);
1066                         return -1;
1067                 case HELPER_SPAWN:
1068                         newstack++;
1069                         /* Fall through */
1070                 case HELPER_EXEC:
1071                         pthread_mutex_unlock(&conlock);
1072                         if (sw->exec)
1073                                 res = sw->exec(c, context, exten, priority, callerid, newstack, data);
1074                         else {
1075                                 ast_log(LOG_WARNING, "No execution engine for switch %s\n", sw->name);
1076                                 res = -1;
1077                         }
1078                         return res;
1079                 default:
1080                         ast_log(LOG_WARNING, "Huh (%d)?\n", action);
1081                         return -1;
1082                 }
1083         } else {
1084                 pthread_mutex_unlock(&conlock);
1085                 switch(status) {
1086                 case STATUS_NO_CONTEXT:
1087                         if ((action != HELPER_EXISTS) && (action != HELPER_MATCHMORE))
1088                                 ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", context);
1089                         break;
1090                 case STATUS_NO_EXTENSION:
1091                         if ((action != HELPER_EXISTS) && (action !=  HELPER_CANMATCH) && (action != HELPER_MATCHMORE))
1092                                 ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, context);
1093                         break;
1094                 case STATUS_NO_PRIORITY:
1095                         if ((action != HELPER_EXISTS) && (action !=  HELPER_CANMATCH) && (action != HELPER_MATCHMORE))
1096                                 ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, context);
1097                         break;
1098                 default:
1099                         ast_log(LOG_DEBUG, "Shouldn't happen!\n");
1100                 }
1101                 if ((action != HELPER_EXISTS) && (action != HELPER_CANMATCH) && (action != HELPER_MATCHMORE))
1102                         return -1;
1103                 else
1104                         return 0;
1105         }
1106
1107 }
1108
1109 static struct ast_exten *ast_hint_extension(struct ast_channel *c, char *context, char *exten)
1110 {
1111         struct ast_exten *e;
1112         struct ast_switch *sw;
1113         char *data;
1114         int status = 0;
1115         char *incstack[AST_PBX_MAX_STACK];
1116         int stacklen = 0;
1117
1118         if (ast_pthread_mutex_lock(&conlock)) {
1119                 ast_log(LOG_WARNING, "Unable to obtain lock\n");
1120                 return NULL;
1121         }
1122         e = pbx_find_extension(c, context, exten, PRIORITY_HINT, "", HELPER_EXISTS, incstack, &stacklen, &status, &sw, &data);
1123         ast_pthread_mutex_unlock(&conlock);     
1124         return e;
1125 }
1126
1127 static int ast_extension_state2(struct ast_exten *e)
1128 {
1129     char hint[AST_MAX_EXTENSION] = "";    
1130     char *cur, *rest;
1131     int res = -1;
1132     int allunavailable = 1, allbusy = 1, allfree = 1;
1133     int busy = 0;
1134
1135     strncpy(hint, ast_get_extension_app(e), sizeof(hint)-1);
1136     
1137     cur = hint;    
1138     do {
1139         rest = strchr(cur, '&');
1140         if (rest) {
1141             *rest = 0;
1142             rest++;
1143         }
1144         
1145         res = ast_device_state(cur);
1146         switch (res) {
1147             case AST_DEVICE_NOT_INUSE:
1148                 allunavailable = 0;
1149                 allbusy = 0;
1150                 break;
1151             case AST_DEVICE_INUSE:
1152                 return AST_EXTENSION_INUSE;
1153             case AST_DEVICE_BUSY:
1154                 allunavailable = 0;
1155                 allfree = 0;
1156                 busy = 1;
1157                 break;
1158             case AST_DEVICE_UNAVAILABLE:
1159             case AST_DEVICE_INVALID:
1160                 allbusy = 0;
1161                 allfree = 0;
1162                 break;
1163             default:
1164                 allunavailable = 0;
1165                 allbusy = 0;
1166                 allfree = 0;
1167         }
1168         cur = rest;
1169     } while (cur);
1170
1171     if (allfree)
1172         return AST_EXTENSION_NOT_INUSE;
1173     if (allbusy)
1174         return AST_EXTENSION_BUSY;
1175     if (allunavailable)
1176         return AST_EXTENSION_UNAVAILABLE;
1177     if (busy) 
1178         return AST_EXTENSION_INUSE;
1179
1180     return AST_EXTENSION_NOT_INUSE;
1181 }
1182
1183
1184 int ast_extension_state(struct ast_channel *c, char *context, char *exten)
1185 {
1186     struct ast_exten *e;
1187
1188     e = ast_hint_extension(c, context, exten);    
1189     if (!e) 
1190         return -1;
1191
1192     return ast_extension_state2(e);    
1193 }
1194
1195 int ast_device_state_changed(char *device) 
1196 {
1197     struct ast_notify *list;
1198     struct ast_notify_cb *cblist;
1199     char hint[AST_MAX_EXTENSION];
1200     char *cur, *rest;
1201     int state;
1202         
1203     pthread_mutex_lock(&notifylock);
1204
1205     list = notifys;
1206     
1207     while (list) {
1208         
1209         strcpy(hint, ast_get_extension_app(list->exten));
1210         cur = hint;
1211         do {
1212             rest = strchr(cur, '&');
1213             if (rest) {
1214                 *rest = 0;
1215                 rest++;
1216             }
1217             
1218             if (!strncmp(cur, device, strlen(cur))) {
1219             // Found extension execute callbacks 
1220                 state = ast_extension_state2(list->exten);
1221                 if ((state != -1) && (state != list->laststate)) {
1222                     cblist = list->callbacks;
1223                     while (cblist) {
1224                         cblist->callback(list->exten->parent->name, list->exten->exten, state, cblist->data);
1225                         cblist = cblist->next;
1226                     }
1227                     list->laststate = state;
1228                 }
1229                 break;
1230             }
1231             cur = rest;
1232         } while (cur);
1233         
1234         list = list->next;
1235     }
1236
1237     pthread_mutex_unlock(&notifylock);
1238     return 1;
1239 }
1240                         
1241 int ast_extension_state_add(char *context, char *exten, 
1242                             ast_notify_cb_type callback, void *data)
1243 {
1244     struct ast_notify *list;
1245     struct ast_notify_cb *cblist;
1246     struct ast_exten *e;
1247
1248     pthread_mutex_lock(&notifylock);
1249     list = notifys;        
1250     
1251     while (list) {
1252         if (!strcmp(list->exten->parent->name, context) && 
1253             !strcmp(list->exten->exten, exten))
1254             break;          
1255         list = list->next;    
1256     }
1257
1258     if (!list) {
1259         e = ast_hint_extension(NULL, context, exten);    
1260         if (!e) {
1261             pthread_mutex_unlock(&notifylock);
1262             return -1;
1263         }
1264         list = malloc(sizeof(struct ast_notify));
1265         if (!list) {
1266             pthread_mutex_unlock(&notifylock);
1267             return -1;
1268         }
1269         /* Initialize and insert new item */
1270         memset(list, 0, sizeof(struct ast_notify));         
1271         list->exten = e;
1272         list->laststate = -1;
1273         list->next = notifys;
1274         notifys = list;
1275     }
1276     
1277     /* Now inserts the callback */
1278     cblist = malloc(sizeof(struct ast_notify_cb));
1279     if (!cblist) {
1280         pthread_mutex_unlock(&notifylock);
1281         return -1;
1282     }
1283     memset(cblist, 0, sizeof(struct ast_notify_cb));
1284     cblist->id = notifycnt++;
1285     cblist->callback = callback;
1286     cblist->data = data;
1287
1288     cblist->next = list->callbacks;
1289     list->callbacks = cblist;
1290
1291     pthread_mutex_unlock(&notifylock);
1292     return cblist->id;
1293 }
1294
1295 static int ast_extension_state_clean(struct ast_exten *e)
1296 {
1297     /* Cleanup the Notifys if hint is removed */
1298     struct ast_notify *list, *prev = NULL;
1299     struct ast_notify_cb *cblist, *cbprev;
1300
1301     pthread_mutex_lock(&notifylock);
1302
1303     list = notifys;    
1304     while(list) {
1305         if (list->exten==e) {
1306             cbprev = NULL;
1307             cblist = list->callbacks;
1308             while (cblist) {        
1309                 cbprev = cblist;            
1310                 cblist = cblist->next;
1311                 cblist->callback(list->exten->parent->name, list->exten->exten, -1, cblist->data);
1312                 free(cbprev);
1313             }
1314             list->callbacks = NULL;
1315
1316             if (!prev) {
1317                 notifys = list->next;
1318                 free(list);
1319                 list = notifys;
1320             } else {
1321                 prev->next = list->next;
1322                 free(list);
1323                 list = prev->next;
1324             }
1325         } else {
1326             prev = list;
1327             list = list->next;    
1328         }
1329     }
1330
1331     pthread_mutex_unlock(&notifylock);
1332     return 1;
1333 }
1334
1335 int ast_extension_state_del(int id)
1336 {
1337     struct ast_notify *list, *prev = NULL;
1338     struct ast_notify_cb *cblist, *cbprev;
1339             
1340     pthread_mutex_lock(&notifylock);
1341
1342     list = notifys;
1343     while (list) {
1344         cblist = list->callbacks;
1345         cbprev = NULL;
1346         while (cblist) {
1347             if (cblist->id==id) {
1348                 if (!cbprev) {
1349                     list->callbacks = cblist->next;             
1350                     free(cblist);
1351                     cblist = list->callbacks;
1352                 } else {
1353                     cbprev->next = cblist->next;
1354                     free(cblist);
1355                     cblist = cbprev->next;
1356                 }
1357                 
1358                 if (!list->callbacks) {
1359                     if (!prev) {
1360                         notifys = list->next;
1361                         free(list);
1362                         list = notifys;
1363                     } else {
1364                         prev->next = list->next;
1365                         free(list);
1366                         list = prev->next;
1367                     }
1368                 }
1369                 break;
1370             } else {
1371                 cbprev = cblist;                                
1372                 cblist = cblist->next;
1373             }
1374         }
1375
1376         // we can have only one item
1377         if (cblist)
1378             break;          
1379             
1380         prev = list;
1381         list = list->next;
1382     }
1383     
1384     pthread_mutex_unlock(&notifylock);
1385     if (list) 
1386         return 0;
1387     else
1388         return -1;
1389         
1390 }
1391
1392 int ast_get_hint(char *hint, int maxlen, struct ast_channel *c, char *context, char *exten)
1393 {
1394         struct ast_exten *e;
1395         e = ast_hint_extension(c, context, exten);
1396         if (e) {        
1397             strncpy(hint, ast_get_extension_app(e), maxlen);
1398             return -1;
1399         }
1400         return 0;       
1401 }
1402
1403 int ast_exists_extension(struct ast_channel *c, char *context, char *exten, int priority, char *callerid) 
1404 {
1405         return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_EXISTS);
1406 }
1407
1408 int ast_canmatch_extension(struct ast_channel *c, char *context, char *exten, int priority, char *callerid)
1409 {
1410         return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_CANMATCH);
1411 }
1412
1413 int ast_matchmore_extension(struct ast_channel *c, char *context, char *exten, int priority, char *callerid)
1414 {
1415         return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_MATCHMORE);
1416 }
1417
1418 int ast_spawn_extension(struct ast_channel *c, char *context, char *exten, int priority, char *callerid) 
1419 {
1420         return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_SPAWN);
1421 }
1422
1423 int ast_pbx_run(struct ast_channel *c)
1424 {
1425         int firstpass = 1;
1426         char digit;
1427         char exten[256];
1428         int pos;
1429         int waittime;
1430         int res=0;
1431
1432         /* A little initial setup here */
1433         if (c->pbx)
1434                 ast_log(LOG_WARNING, "%s already has PBX structure??\n", c->name);
1435         c->pbx = malloc(sizeof(struct ast_pbx));
1436         if (!c->pbx) {
1437                 ast_log(LOG_WARNING, "Out of memory\n");
1438                 return -1;
1439         }
1440         if (c->amaflags) {
1441                 if (c->cdr) {
1442                         ast_log(LOG_WARNING, "%s already has a call record??\n", c->name);
1443                 } else {
1444                         c->cdr = ast_cdr_alloc();
1445                         if (!c->cdr) {
1446                                 ast_log(LOG_WARNING, "Unable to create Call Detail Record\n");
1447                                 free(c->pbx);
1448                                 return -1;
1449                         }
1450                         ast_cdr_init(c->cdr, c);
1451                 }
1452         }
1453         memset(c->pbx, 0, sizeof(struct ast_pbx));
1454         /* Set reasonable defaults */
1455         c->pbx->rtimeout = 10;
1456         c->pbx->dtimeout = 5;
1457
1458         /* Start by trying whatever the channel is set to */
1459         if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) {
1460                 /* JK02: If not successfull fall back to 's' */
1461                 strncpy(c->exten, "s", sizeof(c->exten)-1);
1462                 if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) {
1463                         /* JK02: And finally back to default if everything else failed */
1464                         strncpy(c->context, "default", sizeof(c->context)-1);
1465                 }
1466                 c->priority = 1;
1467         }
1468         if (c->cdr)
1469                 ast_cdr_start(c->cdr);
1470         for(;;) {
1471                 pos = 0;
1472                 digit = 0;
1473                 while(ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) {
1474                         memset(exten, 0, sizeof(exten));
1475                         manager_event(EVENT_FLAG_CALL, "Newexten", 
1476                                 "Channel: %s\r\n"
1477                                 "Context: %s\r\n"
1478                                 "Extension: %s\r\n"
1479                                 "Priority: %d\r\n",
1480                                 c->name, c->context, c->exten, c->priority);                    
1481                         if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->callerid))) {
1482                                 /* Something bad happened, or a hangup has been requested. */
1483                                 if (((res >= '0') && (res <= '9')) || ((res >= 'A') && (res <= 'F')) ||
1484                                         (res == '*') || (res == '#')) {
1485                                         ast_log(LOG_DEBUG, "Oooh, got something to jump out with ('%c')!\n", res);
1486                                         memset(exten, 0, sizeof(exten));
1487                                         pos = 0;
1488                                         exten[pos++] = digit = res;
1489                                         break;
1490                                 }
1491                                 switch(res) {
1492                                 case AST_PBX_KEEPALIVE:
1493                                         if (option_debug)
1494                                                 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
1495                                         else if (option_verbose > 1)
1496                                                 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
1497                                         goto out;
1498                                         break;
1499                                 default:
1500                                         if (option_debug)
1501                                                 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
1502                                         else if (option_verbose > 1)
1503                                                 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
1504                                         if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
1505                                                 c->_softhangup =0;
1506                                                 break;
1507                                         }
1508                                         /* atimeout */
1509                                         if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) {
1510                                                 break;
1511                                         }
1512                                         goto out;
1513                                 }
1514                         }
1515                         if ((c->_softhangup == AST_SOFTHANGUP_TIMEOUT) && (ast_exists_extension(c,c->context,"T",1,c->callerid))) {
1516                                 strncpy(c->exten,"T",sizeof(c->exten) - 1);
1517                                 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
1518                                 c->whentohangup = 0;
1519                         } else if (c->_softhangup) {
1520                                 ast_log(LOG_DEBUG, "Extension %s, priority %d returned normally even though call was hung up\n",
1521                                         c->exten, c->priority);
1522                                 goto out;
1523                         }
1524                         firstpass = 0;
1525                         c->priority++;
1526                 }
1527                 if (!ast_exists_extension(c, c->context, c->exten, 1, c->callerid)) {
1528                         /* It's not a valid extension anymore */
1529                         if (ast_exists_extension(c, c->context, "i", 1, c->callerid)) {
1530                                 if (option_verbose > 2)
1531                                         ast_verbose(VERBOSE_PREFIX_3 "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, c->name);
1532                                 strncpy(c->exten, "i", sizeof(c->exten)-1);
1533                                 c->priority = 1;
1534                         } else {
1535                                 ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n",
1536                                         c->name, c->exten, c->context);
1537                                 goto out;
1538                         }
1539                 } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) {
1540                         /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */
1541                         c->_softhangup = 0;
1542                 } else {
1543                         /* Done, wait for an extension */
1544                         if (digit)
1545                                 waittime = c->pbx->dtimeout;
1546                         else
1547                                 waittime = c->pbx->rtimeout;
1548                         while (ast_matchmore_extension(c, c->context, exten, 1, c->callerid)) {
1549                                 /* As long as we're willing to wait, and as long as it's not defined, 
1550                                    keep reading digits until we can't possibly get a right answer anymore.  */
1551                                 digit = ast_waitfordigit(c, waittime * 1000);
1552                                 if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
1553                                         c->_softhangup = 0;
1554                                 } else {
1555                                         if (!digit)
1556                                                 /* No entry */
1557                                                 break;
1558                                         if (digit < 0)
1559                                                 /* Error, maybe a  hangup */
1560                                                 goto out;
1561                                         exten[pos++] = digit;
1562                                         waittime = c->pbx->dtimeout;
1563                                 }
1564                         }
1565                         if (ast_exists_extension(c, c->context, exten, 1, c->callerid)) {
1566                                 /* Prepare the next cycle */
1567                                 strncpy(c->exten, exten, sizeof(c->exten)-1);
1568                                 c->priority = 1;
1569                         } else {
1570                                 /* No such extension */
1571                                 if (strlen(exten)) {
1572                                         /* An invalid extension */
1573                                         if (ast_exists_extension(c, c->context, "i", 1, c->callerid)) {
1574                                                 if (option_verbose > 2)
1575                                                         ast_verbose( VERBOSE_PREFIX_3 "Invalid extension '%s' in context '%s' on %s\n", exten, c->context, c->name);
1576                                                 strncpy(c->exten, "i", sizeof(c->exten)-1);
1577                                                 c->priority = 1;
1578                                         } else {
1579                                                 ast_log(LOG_WARNING, "Invalid extension, but no rule 'i' in context '%s'\n", c->context);
1580                                                 goto out;
1581                                         }
1582                                 } else {
1583                                         /* A simple timeout */
1584                                         if (ast_exists_extension(c, c->context, "t", 1, c->callerid)) {
1585                                                 if (option_verbose > 2)
1586                                                         ast_verbose( VERBOSE_PREFIX_3 "Timeout on %s\n", c->name);
1587                                                 strncpy(c->exten, "t", sizeof(c->exten)-1);
1588                                                 c->priority = 1;
1589                                         } else {
1590                                                 ast_log(LOG_WARNING, "Timeout, but no rule 't' in context '%s'\n", c->context);
1591                                                 goto out;
1592                                         }
1593                                 }       
1594                         }
1595                 }
1596         }
1597         if (firstpass) 
1598                 ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name);
1599 out:
1600         if (ast_exists_extension(c, c->context, "h", 1, c->callerid)) {
1601                 strcpy(c->exten, "h");
1602                 c->priority = 1;
1603                 while(ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) {
1604                         if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->callerid))) {
1605                                 /* Something bad happened, or a hangup has been requested. */
1606                                 if (option_debug)
1607                                         ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
1608                                 else if (option_verbose > 1)
1609                                         ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
1610                                 break;
1611                         }
1612                         c->priority++;
1613                 }
1614         }
1615
1616         pbx_destroy(c->pbx);
1617         c->pbx = NULL;
1618         if (res != AST_PBX_KEEPALIVE)
1619                 ast_hangup(c);
1620         return 0;
1621 }
1622
1623 static void *pbx_thread(void *data)
1624 {
1625         /* Oh joyeous kernel, we're a new thread, with nothing to do but
1626            answer this channel and get it going.  The setjmp stuff is fairly
1627            confusing, but necessary to get smooth transitions between
1628            the execution of different applications (without the use of
1629            additional threads) */
1630         struct ast_channel *c = data;
1631         ast_pbx_run(c);
1632         pthread_exit(NULL);
1633         return NULL;
1634 }
1635
1636 int ast_pbx_start(struct ast_channel *c)
1637 {
1638         pthread_t t;
1639         pthread_attr_t attr;
1640         if (!c) {
1641                 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
1642                 return -1;
1643         }
1644            
1645         /* Start a new thread, and get something handling this channel. */
1646         pthread_attr_init(&attr);
1647         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1648         if (pthread_create(&t, &attr, pbx_thread, c)) {
1649                 ast_log(LOG_WARNING, "Failed to create new channel thread\n");
1650                 return -1;
1651         }
1652         return 0;
1653 }
1654
1655 /*
1656  * This function locks contexts list by &conlist, search for the rigt context
1657  * structure, leave context list locked and call ast_context_remove_include2
1658  * which removes include, unlock contexts list and return ...
1659  */
1660 int ast_context_remove_include(char *context, char *include, char *registrar)
1661 {
1662         struct ast_context *c;
1663
1664         if (ast_lock_contexts()) return -1;
1665
1666         /* walk contexts and search for the right one ...*/
1667         c = ast_walk_contexts(NULL);
1668         while (c) {
1669                 /* we found one ... */
1670                 if (!strcmp(ast_get_context_name(c), context)) {
1671                         int ret;
1672                         /* remove include from this context ... */      
1673                         ret = ast_context_remove_include2(c, include, registrar);
1674
1675                         ast_unlock_contexts();
1676
1677                         /* ... return results */
1678                         return ret;
1679                 }
1680                 c = ast_walk_contexts(c);
1681         }
1682
1683         /* we can't find the right one context */
1684         ast_unlock_contexts();
1685         return -1;
1686 }
1687
1688 /*
1689  * When we call this function, &conlock lock must be locked, because when
1690  * we giving *con argument, some process can remove/change this context
1691  * and after that there can be segfault.
1692  *
1693  * This function locks given context, removes include, unlock context and
1694  * return.
1695  */
1696 int ast_context_remove_include2(struct ast_context *con, char *include, char *registrar)
1697 {
1698         struct ast_include *i, *pi = NULL;
1699
1700         if (ast_pthread_mutex_lock(&con->lock)) return -1;
1701
1702         /* walk includes */
1703         i = con->includes;
1704         while (i) {
1705                 /* find our include */
1706                 if (!strcmp(i->name, include) && 
1707                         (!strcmp(i->registrar, registrar) || !registrar)) {
1708                         /* remove from list */
1709                         if (pi)
1710                                 pi->next = i->next;
1711                         else
1712                                 con->includes = i->next;
1713                         /* free include and return */
1714                         free(i);
1715                         ast_pthread_mutex_unlock(&con->lock);
1716                         return 0;
1717                 }
1718                 pi = i;
1719                 i = i->next;
1720         }
1721
1722         /* we can't find the right include */
1723         ast_pthread_mutex_unlock(&con->lock);
1724         return -1;
1725 }
1726
1727 /*
1728  * This function locks contexts list by &conlist, search for the rigt context
1729  * structure, leave context list locked and call ast_context_remove_switch2
1730  * which removes switch, unlock contexts list and return ...
1731  */
1732 int ast_context_remove_switch(char *context, char *sw, char *data, char *registrar)
1733 {
1734         struct ast_context *c;
1735
1736         if (ast_lock_contexts()) return -1;
1737
1738         /* walk contexts and search for the right one ...*/
1739         c = ast_walk_contexts(NULL);
1740         while (c) {
1741                 /* we found one ... */
1742                 if (!strcmp(ast_get_context_name(c), context)) {
1743                         int ret;
1744                         /* remove switch from this context ... */       
1745                         ret = ast_context_remove_switch2(c, sw, data, registrar);
1746
1747                         ast_unlock_contexts();
1748
1749                         /* ... return results */
1750                         return ret;
1751                 }
1752                 c = ast_walk_contexts(c);
1753         }
1754
1755         /* we can't find the right one context */
1756         ast_unlock_contexts();
1757         return -1;
1758 }
1759
1760 /*
1761  * When we call this function, &conlock lock must be locked, because when
1762  * we giving *con argument, some process can remove/change this context
1763  * and after that there can be segfault.
1764  *
1765  * This function locks given context, removes switch, unlock context and
1766  * return.
1767  */
1768 int ast_context_remove_switch2(struct ast_context *con, char *sw, char *data, char *registrar)
1769 {
1770         struct ast_sw *i, *pi = NULL;
1771
1772         if (ast_pthread_mutex_lock(&con->lock)) return -1;
1773
1774         /* walk switchs */
1775         i = con->alts;
1776         while (i) {
1777                 /* find our switch */
1778                 if (!strcmp(i->name, sw) && !strcmp(i->data, data) && 
1779                         (!strcmp(i->registrar, registrar) || !registrar)) {
1780                         /* remove from list */
1781                         if (pi)
1782                                 pi->next = i->next;
1783                         else
1784                                 con->alts = i->next;
1785                         /* free switch and return */
1786                         free(i);
1787                         ast_pthread_mutex_unlock(&con->lock);
1788                         return 0;
1789                 }
1790                 pi = i;
1791                 i = i->next;
1792         }
1793
1794         /* we can't find the right switch */
1795         ast_pthread_mutex_unlock(&con->lock);
1796         return -1;
1797 }
1798
1799 /*
1800  * This functions lock contexts list, search for the right context,
1801  * call ast_context_remove_extension2, unlock contexts list and return.
1802  * In this function we are using
1803  */
1804 int ast_context_remove_extension(char *context, char *extension, int priority, char *registrar)
1805 {
1806         struct ast_context *c;
1807
1808         if (ast_lock_contexts()) return -1;
1809
1810         /* walk contexts ... */
1811         c = ast_walk_contexts(NULL);
1812         while (c) {
1813                 /* ... search for the right one ... */
1814                 if (!strcmp(ast_get_context_name(c), context)) {
1815                         /* ... remove extension ... */
1816                         int ret = ast_context_remove_extension2(c, extension, priority,
1817                                 registrar);
1818                         /* ... unlock contexts list and return */
1819                         ast_unlock_contexts();
1820                         return ret;
1821                 }
1822                 c = ast_walk_contexts(c);
1823         }
1824
1825         /* we can't find the right context */
1826         ast_unlock_contexts();
1827         return -1;
1828 }
1829
1830 /*
1831  * When do you want to call this function, make sure that &conlock is locked,
1832  * because some process can handle with your *con context before you lock
1833  * it.
1834  *
1835  * This functionc locks given context, search for the right extension and
1836  * fires out all peer in this extensions with given priority. If priority
1837  * is set to 0, all peers are removed. After that, unlock context and
1838  * return.
1839  */
1840 int ast_context_remove_extension2(struct ast_context *con, char *extension, int priority, char *registrar)
1841 {
1842         struct ast_exten *exten, *prev_exten = NULL;
1843
1844         if (ast_pthread_mutex_lock(&con->lock)) return -1;
1845
1846         /* go through all extensions in context and search the right one ... */
1847         exten = con->root;
1848         while (exten) {
1849
1850                 /* look for right extension */
1851                 if (!strcmp(exten->exten, extension) &&
1852                         (!strcmp(exten->registrar, registrar) || !registrar)) {
1853                         struct ast_exten *peer;
1854
1855                         /* should we free all peers in this extension? (priority == 0)? */
1856                         if (priority == 0) {
1857                                 /* remove this extension from context list */
1858                                 if (prev_exten)
1859                                         prev_exten->next = exten->next;
1860                                 else
1861                                         con->root = exten->next;
1862
1863                                 /* fire out all peers */
1864                                 peer = exten; 
1865                                 while (peer) {
1866                                         exten = peer->peer;
1867                                         
1868                                         if (!peer->priority==PRIORITY_HINT) 
1869                                             ast_extension_state_clean(peer);
1870
1871                                         peer->datad(peer->data);
1872                                         free(peer);
1873
1874                                         peer = exten;
1875                                 }
1876
1877                                 ast_pthread_mutex_unlock(&con->lock);
1878                                 return 0;
1879                         } else {
1880                                 /* remove only extension with exten->priority == priority */
1881                                 struct ast_exten *previous_peer = NULL;
1882
1883                                 peer = exten;
1884                                 while (peer) {
1885                                         /* is this our extension? */
1886                                         if (peer->priority == priority &&
1887                                                 (!strcmp(peer->registrar, registrar) || !registrar)) {
1888                                                 /* we are first priority extension? */
1889                                                 if (!previous_peer) {
1890                                                         /* exists previous extension here? */
1891                                                         if (prev_exten) {
1892                                                                 /* yes, so we must change next pointer in
1893                                                                  * previous connection to next peer
1894                                                                  */
1895                                                                 if (peer->peer) {
1896                                                                         prev_exten->next = peer->peer;
1897                                                                         peer->peer->next = exten->next;
1898                                                                 } else
1899                                                                         prev_exten->next = exten->next;
1900                                                         } else {
1901                                                                 /* no previous extension, we are first
1902                                                                  * extension, so change con->root ...
1903                                                                  */
1904                                                                 if (peer->peer)
1905                                                                         con->root = peer->peer;
1906                                                                 else
1907                                                                         con->root = exten->next; 
1908                                                         }
1909                                                 } else {
1910                                                         /* we are not first priority in extension */
1911                                                         previous_peer->peer = peer->peer;
1912                                                 }
1913
1914                                                 /* now, free whole priority extension */
1915                                                 if (peer->priority==PRIORITY_HINT)
1916                                                     ast_extension_state_clean(peer);
1917                                                 peer->datad(peer->data);
1918                                                 free(peer);
1919
1920                                                 ast_pthread_mutex_unlock(&con->lock);
1921                                                 return 0;
1922                                         } else {
1923                                                 /* this is not right extension, skip to next peer */
1924                                                 previous_peer = peer;
1925                                                 peer = peer->peer;
1926                                         }
1927                                 }
1928
1929                                 ast_pthread_mutex_unlock(&con->lock);
1930                                 return -1;
1931                         }
1932                 }
1933
1934                 prev_exten = exten;
1935                 exten = exten->next;
1936         }
1937
1938         /* we can't find right extension */
1939         ast_pthread_mutex_unlock(&con->lock);
1940         return -1;
1941 }
1942
1943
1944 int ast_register_application(char *app, int (*execute)(struct ast_channel *, void *), char *synopsis, char *description)
1945 {
1946         struct ast_app *tmp;
1947         char tmps[80];
1948         if (ast_pthread_mutex_lock(&applock)) {
1949                 ast_log(LOG_ERROR, "Unable to lock application list\n");
1950                 return -1;
1951         }
1952         tmp = apps;
1953         while(tmp) {
1954                 if (!strcasecmp(app, tmp->name)) {
1955                         ast_log(LOG_WARNING, "Already have an application '%s'\n", app);
1956                         ast_pthread_mutex_unlock(&applock);
1957                         return -1;
1958                 }
1959                 tmp = tmp->next;
1960         }
1961         tmp = malloc(sizeof(struct ast_app));
1962         if (tmp) {
1963                 memset(tmp, 0, sizeof(struct ast_app));
1964                 strncpy(tmp->name, app, sizeof(tmp->name)-1);
1965                 tmp->execute = execute;
1966                 tmp->synopsis = synopsis;
1967                 tmp->description = description;
1968                 tmp->next = apps;
1969                 apps = tmp;
1970         } else {
1971                 ast_log(LOG_WARNING, "Out of memory\n");
1972                 ast_pthread_mutex_unlock(&applock);
1973                 return -1;
1974         }
1975         if (option_verbose > 1)
1976                 ast_verbose( VERBOSE_PREFIX_2 "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps)));
1977         ast_pthread_mutex_unlock(&applock);
1978         return 0;
1979 }
1980
1981 int ast_register_switch(struct ast_switch *sw)
1982 {
1983         struct ast_switch *tmp, *prev=NULL;
1984         if (ast_pthread_mutex_lock(&switchlock)) {
1985                 ast_log(LOG_ERROR, "Unable to lock switch lock\n");
1986                 return -1;
1987         }
1988         tmp = switches;
1989         while(tmp) {
1990                 if (!strcasecmp(tmp->name, sw->name))
1991                         break;
1992                 prev = tmp;
1993                 tmp = tmp->next;
1994         }
1995         if (tmp) {      
1996                 ast_pthread_mutex_unlock(&switchlock);
1997                 ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name);
1998                 return -1;
1999         }
2000         sw->next = NULL;
2001         if (prev) 
2002                 prev->next = sw;
2003         else
2004                 switches = sw;
2005         ast_pthread_mutex_unlock(&switchlock);
2006         return 0;
2007 }
2008
2009 void ast_unregister_switch(struct ast_switch *sw)
2010 {
2011         struct ast_switch *tmp, *prev=NULL;
2012         if (ast_pthread_mutex_lock(&switchlock)) {
2013                 ast_log(LOG_ERROR, "Unable to lock switch lock\n");
2014                 return;
2015         }
2016         tmp = switches;
2017         while(tmp) {
2018                 if (tmp == sw) {
2019                         if (prev)
2020                                 prev->next = tmp->next;
2021                         else
2022                                 switches = tmp->next;
2023                         tmp->next = NULL;
2024                         break;                  
2025                 }
2026                 prev = tmp;
2027                 tmp = tmp->next;
2028         }
2029         ast_pthread_mutex_unlock(&switchlock);
2030 }
2031
2032 /*
2033  * Help for CLI commands ...
2034  */
2035 static char show_application_help[] = 
2036 "Usage: show application <application> [<application> [<application> [...]]]\n"
2037 "       Describes a particular application.\n";
2038
2039 static char show_applications_help[] =
2040 "Usage: show applications\n"
2041 "       List applications which are currently available.\n";
2042
2043 static char show_dialplan_help[] =
2044 "Usage: show dialplan [exten@][context]\n"
2045 "       Show dialplan\n";
2046
2047 static char show_switches_help[] = 
2048 "Usage: show switches\n"
2049 "       Show registered switches\n";
2050
2051 /*
2052  * IMPLEMENTATION OF CLI FUNCTIONS IS IN THE SAME ORDER AS COMMANDS HELPS
2053  *
2054  */
2055
2056 /*
2057  * 'show application' CLI command implementation functions ...
2058  */
2059
2060 /*
2061  * There is a possibility to show informations about more than one
2062  * application at one time. You can type 'show application Dial Echo' and
2063  * you will see informations about these two applications ...
2064  */
2065 static char *complete_show_application(char *line, char *word,
2066         int pos, int state)
2067 {
2068         struct ast_app *a;
2069         int which = 0;
2070
2071         /* try to lock applications list ... */
2072         if (ast_pthread_mutex_lock(&applock)) {
2073                 ast_log(LOG_ERROR, "Unable to lock application list\n");
2074                 return NULL;
2075         }
2076
2077         /* ... walk all applications ... */
2078         a = apps; 
2079         while (a) {
2080                 /* ... check if word matches this application ... */
2081                 if (!strncasecmp(word, a->name, strlen(word))) {
2082                         /* ... if this is right app serve it ... */
2083                         if (++which > state) {
2084                                 char *ret = strdup(a->name);
2085                                 ast_pthread_mutex_unlock(&applock);
2086                                 return ret;
2087                         }
2088                 }
2089                 a = a->next; 
2090         }
2091
2092         /* no application match */
2093         ast_pthread_mutex_unlock(&applock);
2094         return NULL; 
2095 }
2096
2097 static int handle_show_application(int fd, int argc, char *argv[])
2098 {
2099         struct ast_app *a;
2100         char buf[2048];
2101         int app, no_registered_app = 1;
2102
2103         if (argc < 3) return RESULT_SHOWUSAGE;
2104
2105         /* try to lock applications list ... */
2106         if (ast_pthread_mutex_lock(&applock)) {
2107                 ast_log(LOG_ERROR, "Unable to lock application list\n");
2108                 return -1;
2109         }
2110
2111         /* ... go through all applications ... */
2112         a = apps; 
2113         while (a) {
2114                 /* ... compare this application name with all arguments given
2115                  * to 'show application' command ... */
2116                 for (app = 2; app < argc; app++) {
2117                         if (!strcasecmp(a->name, argv[app])) {
2118                                 no_registered_app = 0;
2119
2120                                 /* ... one of our applications, show info ...*/
2121                                 snprintf(buf, sizeof(buf),
2122                                         "\n  -= Info about application '%s' =- \n\n"
2123                                         "[Synopsis]:\n  %s\n\n"
2124                                         "[Description]:\n%s\n",
2125                                         a->name,
2126                                         a->synopsis ? a->synopsis : "Not available",
2127                                         a->description ? a-> description : "Not available");
2128                                 ast_cli(fd, buf);
2129                         }
2130                 }
2131                 a = a->next; 
2132         }
2133
2134         ast_pthread_mutex_unlock(&applock);
2135
2136         /* we found at least one app? no? */
2137         if (no_registered_app) {
2138                 ast_cli(fd, "Your application(s) is (are) not registered\n");
2139                 return RESULT_FAILURE;
2140         }
2141
2142         return RESULT_SUCCESS;
2143 }
2144
2145 static int handle_show_switches(int fd, int argc, char *argv[])
2146 {
2147         struct ast_switch *sw;
2148         if (!switches) {
2149                 ast_cli(fd, "There are no registered alternative switches\n");
2150                 return RESULT_SUCCESS;
2151         }
2152         /* ... we have applications ... */
2153         ast_cli(fd, "\n    -= Registered Asterisk Alternative Switches =-\n");
2154         if (ast_pthread_mutex_lock(&switchlock)) {
2155                 ast_log(LOG_ERROR, "Unable to lock switches\n");
2156                 return -1;
2157         }
2158         sw = switches;
2159         while (sw) {
2160                 ast_cli(fd, "%s: %s\n", sw->name, sw->description);
2161                 sw = sw->next;
2162         }
2163         ast_pthread_mutex_unlock(&switchlock);
2164         return RESULT_SUCCESS;
2165 }
2166
2167 /*
2168  * 'show applications' CLI command implementation functions ...
2169  */
2170 static int handle_show_applications(int fd, int argc, char *argv[])
2171 {
2172         struct ast_app *a;
2173
2174         /* try to lock applications list ... */
2175         if (ast_pthread_mutex_lock(&applock)) {
2176                 ast_log(LOG_ERROR, "Unable to lock application list\n");
2177                 return -1;
2178         }
2179
2180         /* ... go to first application ... */
2181         a = apps; 
2182
2183         /* ... have we got at least one application (first)? no? */
2184         if (!a) {
2185                 ast_cli(fd, "There is no registered applications\n");
2186                 ast_pthread_mutex_unlock(&applock);
2187                 return -1;
2188         }
2189
2190         /* ... we have applications ... */
2191         ast_cli(fd, "\n    -= Registered Asterisk Applications =-\n");
2192
2193         /* ... go through all applications ... */
2194         while (a) {
2195                 /* ... show informations about applications ... */
2196                 ast_cli(fd,"  %15s: %s\n",
2197                         a->name,
2198                         a->synopsis ? a->synopsis : "<Synopsis not available>");
2199                 a = a->next; 
2200         }
2201
2202         /* ... unlock and return */
2203         ast_pthread_mutex_unlock(&applock);
2204
2205         return RESULT_SUCCESS;
2206 }
2207
2208 /*
2209  * 'show dialplan' CLI command implementation functions ...
2210  */
2211 static char *complete_show_dialplan_context(char *line, char *word, int pos,
2212         int state)
2213 {
2214         struct ast_context *c;
2215         int which = 0;
2216
2217         /* we are do completion of [exten@]context on second postion only */
2218         if (pos != 2) return NULL;
2219
2220         /* try to lock contexts list ... */
2221         if (ast_lock_contexts()) {
2222                 ast_log(LOG_ERROR, "Unable to lock context list\n");
2223                 return NULL;
2224         }
2225
2226         /* ... walk through all contexts ... */
2227         c = ast_walk_contexts(NULL);
2228         while(c) {
2229                 /* ... word matches context name? yes? ... */
2230                 if (!strncasecmp(word, ast_get_context_name(c), strlen(word))) {
2231                         /* ... for serve? ... */
2232                         if (++which > state) {
2233                                 /* ... yes, serve this context name ... */
2234                                 char *ret = strdup(ast_get_context_name(c));
2235                                 ast_unlock_contexts();
2236                                 return ret;
2237                         }
2238                 }
2239                 c = ast_walk_contexts(c);
2240         }
2241
2242         /* ... unlock and return */
2243         ast_unlock_contexts();
2244         return NULL;
2245 }
2246
2247 static int handle_show_dialplan(int fd, int argc, char *argv[])
2248 {
2249         struct ast_context *c;
2250         char *exten = NULL, *context = NULL;
2251         int context_existence = 0, extension_existence = 0;
2252
2253         if (argc != 3 && argc != 2) return -1;
2254
2255         /* we obtain [exten@]context? if yes, split them ... */
2256         if (argc == 3) {
2257                 char *splitter = argv[2];
2258                 /* is there a '@' character? */
2259                 if (strchr(argv[2], '@')) {
2260                         /* yes, split into exten & context ... */
2261                         exten   = strsep(&splitter, "@");
2262                         context = splitter;
2263
2264                         /* check for length and change to NULL if !strlen() */
2265                         if (!strlen(exten))   exten = NULL;
2266                         if (!strlen(context)) context = NULL;
2267                 } else
2268                 {
2269                         /* no '@' char, only context given */
2270                         context = argv[2];
2271                         if (!strlen(context)) context = NULL;
2272                 }
2273         }
2274
2275         /* try to lock contexts */
2276         if (ast_lock_contexts()) {
2277                 ast_cli(LOG_WARNING, "Failed to lock contexts list\n");
2278                 return RESULT_FAILURE;
2279         }
2280
2281         /* walk all contexts ... */
2282         c = ast_walk_contexts(NULL);
2283         while (c) {
2284                 /* show this context? */
2285                 if (!context ||
2286                         !strcmp(ast_get_context_name(c), context)) {
2287                         context_existence = 1;
2288
2289                         /* try to lock context before walking in ... */
2290                         if (!ast_lock_context(c)) {
2291                                 struct ast_exten *e;
2292                                 struct ast_include *i;
2293                                 struct ast_ignorepat *ip;
2294                                 struct ast_sw *sw;
2295                                 char buf[256], buf2[256];
2296                                 int context_info_printed = 0;
2297
2298                                 /* are we looking for exten too? if yes, we print context
2299                                  * if we our extension only
2300                                  */
2301                                 if (!exten) {
2302                                         ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
2303                                                 ast_get_context_name(c), ast_get_context_registrar(c));
2304                                         context_info_printed = 1;
2305                                 }
2306
2307                                 /* walk extensions ... */
2308                                 e = ast_walk_context_extensions(c, NULL);
2309                                 while (e) {
2310                                         struct ast_exten *p;
2311
2312                                         /* looking for extension? is this our extension? */
2313                                         if (exten &&
2314                                                 strcmp(ast_get_extension_name(e), exten))
2315                                         {
2316                                                 /* we are looking for extension and it's not our
2317                                                  * extension, so skip to next extension */
2318                                                 e = ast_walk_context_extensions(c, e);
2319                                                 continue;
2320                                         }
2321
2322                                         extension_existence = 1;
2323
2324                                         /* may we print context info? */        
2325                                         if (!context_info_printed) {
2326                                                 ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
2327                                                         ast_get_context_name(c),
2328                                                         ast_get_context_registrar(c));
2329                                                 context_info_printed = 1;
2330                                         }
2331
2332                                         /* write extension name and first peer */       
2333                                         bzero(buf, sizeof(buf));                
2334                                         snprintf(buf, sizeof(buf), "'%s' =>",
2335                                                 ast_get_extension_name(e));
2336
2337                                         snprintf(buf2, sizeof(buf2),
2338                                                 "%d. %s(%s)",
2339                                                 ast_get_extension_priority(e),
2340                                                 ast_get_extension_app(e),
2341                                                 (char *)ast_get_extension_app_data(e));
2342
2343                                         ast_cli(fd, "  %-17s %-45s [%s]\n", buf, buf2,
2344                                                 ast_get_extension_registrar(e));
2345
2346                                         /* walk next extension peers */
2347                                         p = ast_walk_extension_priorities(e, e);
2348                                         while (p) {
2349                                                 bzero((void *)buf2, sizeof(buf2));
2350
2351                                                 snprintf(buf2, sizeof(buf2),
2352                                                         "%d. %s(%s)",
2353                                                         ast_get_extension_priority(p),
2354                                                         ast_get_extension_app(p),
2355                                                         (char *)ast_get_extension_app_data(p));
2356
2357                                                 ast_cli(fd,"  %-17s %-45s [%s]\n",
2358                                                         "", buf2,
2359                                                         ast_get_extension_registrar(p));        
2360
2361                                                 p = ast_walk_extension_priorities(e, p);
2362                                         }
2363                                         e = ast_walk_context_extensions(c, e);
2364                                 }
2365
2366                                 /* include & ignorepat we all printing if we are not
2367                                  * looking for exact extension
2368                                  */
2369                                 if (!exten) {
2370                                         if (ast_walk_context_extensions(c, NULL))
2371                                                 ast_cli(fd, "\n");
2372
2373                                         /* walk included and write info ... */
2374                                         i = ast_walk_context_includes(c, NULL);
2375                                         while (i) {
2376                                                 bzero(buf, sizeof(buf));
2377                                                 snprintf(buf, sizeof(buf), "'%s'",
2378                                                         ast_get_include_name(i));
2379                                                 ast_cli(fd, "  Include =>        %-45s [%s]\n",
2380                                                         buf, ast_get_include_registrar(i));
2381                                                 i = ast_walk_context_includes(c, i);
2382                                         }
2383
2384                                         /* walk ignore patterns and write info ... */
2385                                         ip = ast_walk_context_ignorepats(c, NULL);
2386                                         while (ip) {
2387                                                 bzero(buf, sizeof(buf));
2388                                                 snprintf(buf, sizeof(buf), "'%s'",
2389                                                         ast_get_ignorepat_name(ip));
2390                                                 ast_cli(fd, "  Ignore pattern => %-45s [%s]\n",
2391                                                         buf, ast_get_ignorepat_registrar(ip));  
2392                                                 ip = ast_walk_context_ignorepats(c, ip);
2393                                         }
2394                                         sw = ast_walk_context_switches(c, NULL);
2395                                         while(sw) {
2396                                                 bzero(buf, sizeof(buf));
2397                                                 snprintf(buf, sizeof(buf), "'%s/%s'",
2398                                                         ast_get_switch_name(sw),
2399                                                         ast_get_switch_data(sw));
2400                                                 ast_cli(fd, "  Alt. Switch =>    %-45s [%s]\n",
2401                                                         buf, ast_get_switch_registrar(sw));     
2402                                                 sw = ast_walk_context_switches(c, sw);
2403                                         }
2404                                 }
2405         
2406                                 ast_unlock_context(c);
2407
2408                                 /* if we print something in context, make an empty line */
2409                                 if (context_info_printed) ast_cli(fd, "\n");
2410                         }
2411                 }
2412                 c = ast_walk_contexts(c);
2413         }
2414         ast_unlock_contexts();
2415
2416         /* check for input failure and throw some error messages */
2417         if (context && !context_existence) {
2418                 ast_cli(fd, "There is no existence of '%s' context\n",
2419                         context);
2420                 return RESULT_FAILURE;
2421         }
2422
2423         if (exten && !extension_existence) {
2424                 if (context)
2425                         ast_cli(fd, "There is no existence of %s@%s extension\n",
2426                                 exten, context);
2427                 else
2428                         ast_cli(fd,
2429                                 "There is no existence of '%s' extension in all contexts\n",
2430                                 exten);
2431                 return RESULT_FAILURE;
2432         }
2433
2434         /* everything ok */
2435         return RESULT_SUCCESS;
2436 }
2437
2438 /*
2439  * CLI entries for upper commands ...
2440  */
2441 static struct ast_cli_entry show_applications_cli = 
2442         { { "show", "applications", NULL }, 
2443         handle_show_applications, "Shows registered applications",
2444         show_applications_help };
2445
2446 static struct ast_cli_entry show_application_cli =
2447         { { "show", "application", NULL }, 
2448         handle_show_application, "Describe a specific application",
2449         show_application_help, complete_show_application };
2450
2451 static struct ast_cli_entry show_dialplan_cli =
2452         { { "show", "dialplan", NULL },
2453                 handle_show_dialplan, "Show dialplan",
2454                 show_dialplan_help, complete_show_dialplan_context };
2455
2456 static struct ast_cli_entry show_switches_cli =
2457         { { "show", "switches", NULL },
2458                 handle_show_switches, "Show alternative switches",
2459                 show_switches_help, NULL };
2460
2461 int ast_unregister_application(char *app) {
2462         struct ast_app *tmp, *tmpl = NULL;
2463         if (ast_pthread_mutex_lock(&applock)) {
2464                 ast_log(LOG_ERROR, "Unable to lock application list\n");
2465                 return -1;
2466         }
2467         tmp = apps;
2468         while(tmp) {
2469                 if (!strcasecmp(app, tmp->name)) {
2470                         if (tmpl)
2471                                 tmpl->next = tmp->next;
2472                         else
2473                                 apps = tmp->next;
2474                         if (option_verbose > 1)
2475                                 ast_verbose( VERBOSE_PREFIX_2 "Unregistered application '%s'\n", tmp->name);
2476                         ast_pthread_mutex_unlock(&applock);
2477                         return 0;
2478                 }
2479                 tmpl = tmp;
2480                 tmp = tmp->next;
2481         }
2482         ast_pthread_mutex_unlock(&applock);
2483         return -1;
2484 }
2485
2486 struct ast_context *ast_context_create(char *name, char *registrar)
2487 {
2488         struct ast_context *tmp;
2489         
2490         ast_pthread_mutex_lock(&conlock);
2491         tmp = contexts;
2492         while(tmp) {
2493                 if (!strcasecmp(tmp->name, name)) {
2494                         ast_pthread_mutex_unlock(&conlock);
2495                         ast_log(LOG_WARNING, "Tried to register context '%s', already in use\n", name);
2496                         return NULL;
2497                 }
2498                 tmp = tmp->next;
2499         }
2500         tmp = malloc(sizeof(struct ast_context));
2501         if (tmp) {
2502                 memset(tmp, 0, sizeof(struct ast_context));
2503                 ast_pthread_mutex_init(&tmp->lock);
2504                 strncpy(tmp->name, name, sizeof(tmp->name)-1);
2505                 tmp->root = NULL;
2506                 tmp->registrar = registrar;
2507                 tmp->next = contexts;
2508                 tmp->includes = NULL;
2509                 tmp->ignorepats = NULL;
2510                 contexts = tmp;
2511                 if (option_debug)
2512                         ast_log(LOG_DEBUG, "Registered context '%s'\n", tmp->name);
2513                 else if (option_verbose > 2)
2514                         ast_verbose( VERBOSE_PREFIX_3 "Registered extension context '%s'\n", tmp->name);
2515         } else
2516                 ast_log(LOG_WARNING, "Out of memory\n");
2517         
2518         ast_pthread_mutex_unlock(&conlock);
2519         return tmp;
2520 }
2521
2522 /*
2523  * errno values
2524  *  EBUSY  - can't lock
2525  *  ENODATA - no existence of context
2526  */
2527 int ast_context_add_include(char *context, char *include, char *registrar)
2528 {
2529         struct ast_context *c;
2530
2531         if (ast_lock_contexts()) {
2532                 errno = EBUSY;
2533                 return -1;
2534         }
2535
2536         /* walk contexts ... */
2537         c = ast_walk_contexts(NULL);
2538         while (c) {
2539                 /* ... search for the right one ... */
2540                 if (!strcmp(ast_get_context_name(c), context)) {
2541                         int ret = ast_context_add_include2(c, include, registrar);
2542                         /* ... unlock contexts list and return */
2543                         ast_unlock_contexts();
2544                         return ret;
2545                 }
2546                 c = ast_walk_contexts(c);
2547         }
2548
2549         /* we can't find the right context */
2550         ast_unlock_contexts();
2551         errno = ENODATA;
2552         return -1;
2553 }
2554
2555 #define FIND_NEXT \
2556 do { \
2557         c = info; \
2558         while(*c && (*c != '|')) c++; \
2559         if (*c) { *c = '\0'; c++; } else c = NULL; \
2560 } while(0)
2561
2562 static void get_timerange(struct ast_include *i, char *times)
2563 {
2564         char *e;
2565         int x;
2566         int s1, s2;
2567         int e1, e2;
2568         /* Star is all times */
2569         if (!strlen(times) || !strcmp(times, "*")) {
2570                 for (x=0;x<24;x++)
2571                         i->minmask[x] = (1 << 30) - 1;
2572                 return;
2573         }
2574         /* Otherwise expect a range */
2575         e = strchr(times, '-');
2576         if (!e) {
2577                 ast_log(LOG_WARNING, "Time range is not valid. Assuming no time.\n");
2578                 return;
2579         }
2580         *e = '\0';
2581         e++;
2582         while(*e && !isdigit(*e)) e++;
2583         if (!*e) {
2584                 ast_log(LOG_WARNING, "Invalid time range.  Assuming no time.\n");
2585                 return;
2586         }
2587         if (sscanf(times, "%d:%d", &s1, &s2) != 2) {
2588                 ast_log(LOG_WARNING, "%s isn't a time.  Assuming no time.\n", times);
2589                 return;
2590         }
2591         if (sscanf(e, "%d:%d", &e1, &e2) != 2) {
2592                 ast_log(LOG_WARNING, "%s isn't a time.  Assuming no time.\n", e);
2593                 return;
2594         }
2595         s1 = s1 * 30 + s2/2;
2596         if ((s1 < 0) || (s1 >= 24*30)) {
2597                 ast_log(LOG_WARNING, "%s isn't a valid star time. Assuming no time.\n", times);
2598                 return;
2599         }
2600         e1 = e1 * 30 + e2/2;
2601         if ((e1 < 0) || (e2 >= 24*30)) {
2602                 ast_log(LOG_WARNING, "%s isn't a valid start time. Assuming no time.\n", times);
2603                 return;
2604         }
2605         /* Go through the time and enable each appropriate bit */
2606         for (x=s1;x != e1;x = (x + 1) % (24 * 30)) {
2607                 i->minmask[x/30] |= (1 << (x % 30));
2608         }
2609         /* Do the last one */
2610         i->minmask[x/30] |= (1 << (x % 30));
2611         /* All done */
2612 }
2613
2614 static char *days[] =
2615 {
2616         "sun",
2617         "mon",
2618         "tue",
2619         "wed",
2620         "thu",
2621         "fri",
2622         "sat",
2623 };
2624
2625 static unsigned int get_dow(char *dow)
2626 {
2627         char *c;
2628         /* The following line is coincidence, really! */
2629         int s, e, x;
2630         unsigned int mask;
2631         /* Check for all days */
2632         if (!strlen(dow) || !strcmp(dow, "*"))
2633                 return (1 << 7) - 1;
2634         /* Get start and ending days */
2635         c = strchr(dow, '-');
2636         if (c) {
2637                 *c = '\0';
2638                 c++;
2639         } else
2640                 c = NULL;
2641         /* Find the start */
2642         s = 0;
2643         while((s < 7) && strcasecmp(dow, days[s])) s++;
2644         if (s >= 7) {
2645                 ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", dow);
2646                 return 0;
2647         }
2648         if (c) {
2649                 e = 0;
2650                 while((e < 7) && strcasecmp(c, days[e])) e++;
2651                 if (e >= 7) {
2652                         ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", c);
2653                         return 0;
2654                 }
2655         } else
2656                 e = s;
2657         mask = 0;
2658         for (x=s;x!=e;x = (x + 1) % 7) {
2659                 mask |= (1 << x);
2660         }
2661         /* One last one */
2662         mask |= (1 << x);
2663         return mask;
2664 }
2665
2666 static unsigned int get_day(char *day)
2667 {
2668         char *c;
2669         /* The following line is coincidence, really! */
2670         int s, e, x;
2671         unsigned int mask;
2672         /* Check for all days */
2673         if (!strlen(day) || !strcmp(day, "*")) {
2674                 mask = (1 << 30)  + ((1 << 30) - 1);
2675                 return mask;
2676         }
2677         /* Get start and ending days */
2678         c = strchr(day, '-');
2679         if (c) {
2680                 *c = '\0';
2681                 c++;
2682         }
2683         /* Find the start */
2684         if (sscanf(day, "%d", &s) != 1) {
2685                 ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", day);
2686                 return 0;
2687         }
2688         if ((s < 1) || (s > 31)) {
2689                 ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", day);
2690                 return 0;
2691         }
2692         s--;
2693         if (c) {
2694                 if (sscanf(c, "%d", &e) != 1) {
2695                         ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", c);
2696                         return 0;
2697                 }
2698                 if ((e < 1) || (e > 31)) {
2699                         ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", c);
2700                         return 0;
2701                 }
2702                 e--;
2703         } else
2704                 e = s;
2705         mask = 0;
2706         for (x=s;x!=e;x = (x + 1) % 31) {
2707                 mask |= (1 << x);
2708         }
2709         mask |= (1 << x);
2710         return mask;
2711 }
2712
2713 static char *months[] =
2714 {
2715         "jan",
2716         "feb",
2717         "mar",
2718         "apr",
2719         "may",
2720         "jun",
2721         "jul",
2722         "aug",
2723         "sep",
2724         "oct",
2725         "nov",
2726         "dec",
2727 };
2728
2729 static unsigned int get_month(char *mon)
2730 {
2731         char *c;
2732         /* The following line is coincidence, really! */
2733         int s, e, x;
2734         unsigned int mask;
2735         /* Check for all days */
2736         if (!strlen(mon) || !strcmp(mon, "*")) 
2737                 return (1 << 12) - 1;
2738         /* Get start and ending days */
2739         c = strchr(mon, '-');
2740         if (c) {
2741                 *c = '\0';
2742                 c++;
2743         }
2744         /* Find the start */
2745         s = 0;
2746         while((s < 12) && strcasecmp(mon, months[s])) s++;
2747         if (s >= 12) {
2748                 ast_log(LOG_WARNING, "Invalid month '%s', assuming none\n", mon);
2749                 return 0;
2750         }
2751         if (c) {
2752                 e = 0;
2753                 while((e < 12) && strcasecmp(mon, months[e])) e++;
2754                 if (e >= 12) {
2755                         ast_log(LOG_WARNING, "Invalid month '%s', assuming none\n", c);
2756                         return 0;
2757                 }
2758         } else
2759                 e = s;
2760         mask = 0;
2761         for (x=s;x!=e;x = (x + 1) % 12) {
2762                 mask |= (1 << x);
2763         }
2764         /* One last one */
2765         mask |= (1 << x);
2766         return mask;
2767 }
2768
2769 static void build_timing(struct ast_include *i, char *info)
2770 {
2771         char *c;
2772         /* Check for empty just in case */
2773         if (!strlen(info))
2774                 return;
2775         i->hastime = 1;
2776         /* Assume everything except time */
2777         i->monthmask = (1 << 12) - 1;
2778         i->daymask = (1 << 30) - 1 + (1 << 30);
2779         i->dowmask = (1 << 7) - 1;
2780         /* Avoid using str tok */
2781         FIND_NEXT;
2782         /* Info has the time range, start with that */
2783         get_timerange(i, info);
2784         info = c;
2785         if (!info)
2786                 return;
2787         FIND_NEXT;
2788         /* Now check for day of week */
2789         i->dowmask = get_dow(info);
2790
2791         info = c;
2792         if (!info)
2793                 return;
2794         FIND_NEXT;
2795         /* Now check for the day of the month */
2796         i->daymask = get_day(info);
2797         info = c;
2798         if (!info)
2799                 return;
2800         FIND_NEXT;
2801         /* And finally go for the month */
2802         i->monthmask = get_month(info);
2803 }
2804
2805 /*
2806  * errno values
2807  *  ENOMEM - out of memory
2808  *  EBUSY  - can't lock
2809  *  EEXIST - already included
2810  *  EINVAL - there is no existence of context for inclusion
2811  */
2812 int ast_context_add_include2(struct ast_context *con, char *value,
2813         char *registrar)
2814 {
2815         struct ast_include *new_include;
2816         char *c;
2817         struct ast_include *i, *il = NULL; /* include, include_last */
2818
2819         /* allocate new include structure ... */
2820         if (!(new_include = malloc(sizeof(struct ast_include)))) {
2821                 ast_log(LOG_WARNING, "Out of memory\n");
2822                 errno = ENOMEM;
2823                 return -1;
2824         }
2825         
2826         /* ... fill in this structure ... */
2827         memset(new_include, 0, sizeof(struct ast_include));
2828         strncpy(new_include->name, value, sizeof(new_include->name)-1);
2829         strncpy(new_include->rname, value, sizeof(new_include->rname)-1);
2830         c = new_include->rname;
2831         /* Strip off timing info */
2832         while(*c && (*c != '|')) c++; 
2833         /* Process if it's there */
2834         if (*c) {
2835                 build_timing(new_include, c+1);
2836                 *c = '\0';
2837         }
2838         new_include->next      = NULL;
2839         new_include->registrar = registrar;
2840
2841         /* ... try to lock this context ... */
2842         if (ast_pthread_mutex_lock(&con->lock)) {
2843                 free(new_include);
2844                 errno = EBUSY;
2845                 return -1;
2846         }
2847
2848         /* ... go to last include and check if context is already included too... */
2849         i = con->includes;
2850         while (i) {
2851                 if (!strcasecmp(i->name, new_include->name)) {
2852                         free(new_include);
2853                         ast_pthread_mutex_unlock(&con->lock);
2854                         errno = EEXIST;
2855                         return -1;
2856                 }
2857                 il = i;
2858                 i = i->next;
2859         }
2860
2861         /* ... include new context into context list, unlock, return */
2862         if (il)
2863                 il->next = new_include;
2864         else
2865                 con->includes = new_include;
2866         if (option_verbose > 2)
2867                 ast_verbose(VERBOSE_PREFIX_3 "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con)); 
2868         ast_pthread_mutex_unlock(&con->lock);
2869
2870         return 0;
2871 }
2872
2873 /*
2874  * errno values
2875  *  EBUSY  - can't lock
2876  *  ENODATA - no existence of context
2877  */
2878 int ast_context_add_switch(char *context, char *sw, char *data, char *registrar)
2879 {
2880         struct ast_context *c;
2881
2882         if (ast_lock_contexts()) {
2883                 errno = EBUSY;
2884                 return -1;
2885         }
2886
2887         /* walk contexts ... */
2888         c = ast_walk_contexts(NULL);
2889         while (c) {
2890                 /* ... search for the right one ... */
2891                 if (!strcmp(ast_get_context_name(c), context)) {
2892                         int ret = ast_context_add_switch2(c, sw, data, registrar);
2893                         /* ... unlock contexts list and return */
2894                         ast_unlock_contexts();
2895                         return ret;
2896                 }
2897                 c = ast_walk_contexts(c);
2898         }
2899
2900         /* we can't find the right context */
2901         ast_unlock_contexts();
2902         errno = ENODATA;
2903         return -1;
2904 }
2905
2906 /*
2907  * errno values
2908  *  ENOMEM - out of memory
2909  *  EBUSY  - can't lock
2910  *  EEXIST - already included
2911  *  EINVAL - there is no existence of context for inclusion
2912  */
2913 int ast_context_add_switch2(struct ast_context *con, char *value,
2914         char *data, char *registrar)
2915 {
2916         struct ast_sw *new_sw;
2917         struct ast_sw *i, *il = NULL; /* sw, sw_last */
2918
2919         /* allocate new sw structure ... */
2920         if (!(new_sw = malloc(sizeof(struct ast_sw)))) {
2921                 ast_log(LOG_WARNING, "Out of memory\n");
2922                 errno = ENOMEM;
2923                 return -1;
2924         }
2925         
2926         /* ... fill in this structure ... */
2927         memset(new_sw, 0, sizeof(struct ast_sw));
2928         strncpy(new_sw->name, value, sizeof(new_sw->name)-1);
2929         if (data)
2930                 strncpy(new_sw->data, data, sizeof(new_sw->data)-1);
2931         else
2932                 strncpy(new_sw->data, "", sizeof(new_sw->data)-1);
2933         new_sw->next      = NULL;
2934         new_sw->registrar = registrar;
2935
2936         /* ... try to lock this context ... */
2937         if (ast_pthread_mutex_lock(&con->lock)) {
2938                 free(new_sw);
2939                 errno = EBUSY;
2940                 return -1;
2941         }
2942
2943         /* ... go to last sw and check if context is already swd too... */
2944         i = con->alts;
2945         while (i) {
2946                 if (!strcasecmp(i->name, new_sw->name)) {
2947                         free(new_sw);
2948                         ast_pthread_mutex_unlock(&con->lock);
2949                         errno = EEXIST;
2950                         return -1;
2951                 }
2952                 il = i;
2953                 i = i->next;
2954         }
2955
2956         /* ... sw new context into context list, unlock, return */
2957         if (il)
2958                 il->next = new_sw;
2959         else
2960                 con->alts = new_sw;
2961         if (option_verbose > 2)
2962                 ast_verbose(VERBOSE_PREFIX_3 "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con)); 
2963         ast_pthread_mutex_unlock(&con->lock);
2964
2965         return 0;
2966 }
2967
2968 /*
2969  * EBUSY  - can't lock
2970  * ENODATA - there is not context existence
2971  */
2972 int ast_context_remove_ignorepat(char *context, char *ignorepat, char *registrar)
2973 {
2974         struct ast_context *c;
2975
2976         if (ast_lock_contexts()) {
2977                 errno = EBUSY;
2978                 return -1;
2979         }
2980
2981         c = ast_walk_contexts(NULL);
2982         while (c) {
2983                 if (!strcmp(ast_get_context_name(c), context)) {
2984                         int ret = ast_context_remove_ignorepat2(c, ignorepat, registrar);
2985                         ast_unlock_contexts();
2986                         return ret;
2987                 }
2988                 c = ast_walk_contexts(c);
2989         }
2990
2991         ast_unlock_contexts();
2992         errno = ENODATA;
2993         return -1;
2994 }
2995
2996 int ast_context_remove_ignorepat2(struct ast_context *con, char *ignorepat, char *registrar)
2997 {
2998         struct ast_ignorepat *ip, *ipl = NULL;
2999
3000         if (ast_pthread_mutex_lock(&con->lock)) {
3001                 errno = EBUSY;
3002                 return -1;
3003         }
3004
3005         ip = con->ignorepats;
3006         while (ip) {
3007                 if (!strcmp(ip->pattern, ignorepat) &&
3008                         (registrar == ip->registrar || !registrar)) {
3009                         if (ipl) {
3010                                 ipl->next = ip->next;
3011                                 free(ip);
3012                         } else {
3013                                 con->ignorepats = ip->next;
3014                                 free(ip);
3015                         }
3016                         ast_pthread_mutex_unlock(&con->lock);
3017                         return 0;
3018                 }
3019                 ipl = ip; ip = ip->next;
3020         }
3021
3022         ast_pthread_mutex_unlock(&con->lock);
3023         errno = EINVAL;
3024         return -1;
3025 }
3026
3027 /*
3028  * EBUSY - can't lock
3029  * ENODATA - there is no existence of context
3030  */
3031 int ast_context_add_ignorepat(char *con, char *value, char *registrar)
3032 {
3033         struct ast_context *c;
3034
3035         if (ast_lock_contexts()) {
3036                 errno = EBUSY;
3037                 return -1;
3038         }
3039
3040         c = ast_walk_contexts(NULL);
3041         while (c) {
3042                 if (!strcmp(ast_get_context_name(c), con)) {
3043                         int ret = ast_context_add_ignorepat2(c, value, registrar);
3044                         ast_unlock_contexts();
3045                         return ret;
3046                 } 
3047                 c = ast_walk_contexts(c);
3048         }
3049
3050         ast_unlock_contexts();
3051         errno = ENODATA;
3052         return -1;
3053 }
3054
3055 int ast_context_add_ignorepat2(struct ast_context *con, char *value, char *registrar)
3056 {
3057         struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL;
3058         ignorepat = malloc(sizeof(struct ast_ignorepat));
3059         if (!ignorepat) {
3060                 ast_log(LOG_WARNING, "Out of memory\n");
3061                 errno = ENOMEM;
3062                 return -1;
3063         }
3064         memset(ignorepat, 0, sizeof(struct ast_ignorepat));
3065         strncpy(ignorepat->pattern, value, sizeof(ignorepat->pattern)-1);
3066         ignorepat->next = NULL;
3067         ignorepat->registrar = registrar;
3068         ast_pthread_mutex_lock(&con->lock);
3069         ignorepatc = con->ignorepats;
3070         while(ignorepatc) {
3071                 ignorepatl = ignorepatc;
3072                 if (!strcasecmp(ignorepatc->pattern, value)) {
3073                         /* Already there */
3074                         pthread_mutex_unlock(&con->lock);
3075                         errno = EEXIST;
3076                         return -1;
3077                 }
3078                 ignorepatc = ignorepatc->next;
3079         }
3080         if (ignorepatl) 
3081                 ignorepatl->next = ignorepat;
3082         else
3083                 con->ignorepats = ignorepat;
3084         pthread_mutex_unlock(&con->lock);
3085         return 0;
3086         
3087 }
3088
3089 int ast_ignore_pattern(char *context, char *pattern)
3090 {
3091         struct ast_context *con;
3092         struct ast_ignorepat *pat;
3093         con = ast_context_find(context);
3094         if (con) {
3095                 pat = con->ignorepats;
3096                 while (pat) {
3097                         if (ast_extension_match(pat->pattern, pattern))
3098                                 return 1;
3099                         pat = pat->next;
3100                 }
3101         } 
3102         return 0;
3103 }
3104
3105 /*
3106  * EBUSY   - can't lock
3107  * ENODATA  - no existence of context
3108  *
3109  */
3110 int ast_add_extension(char *context, int replace, char *extension, int priority, char *callerid,
3111         char *application, void *data, void (*datad)(void *), char *registrar)
3112 {
3113         struct ast_context *c;
3114
3115         if (ast_lock_contexts()) {
3116                 errno = EBUSY;
3117                 return -1;
3118         }
3119
3120         c = ast_walk_contexts(NULL);
3121         while (c) {
3122                 if (!strcmp(context, ast_get_context_name(c))) {
3123                         int ret = ast_add_extension2(c, replace, extension, priority, callerid,
3124                                 application, data, datad, registrar);
3125                         ast_unlock_contexts();
3126                         return ret;
3127                 }
3128                 c = ast_walk_contexts(c);
3129         }
3130
3131         ast_unlock_contexts();
3132         errno = ENODATA;
3133         return -1;
3134 }
3135
3136 int ast_async_goto(struct ast_channel *chan, char *context, char *exten, int priority, int needlock)
3137 {
3138         int res = 0;
3139         if (needlock)
3140                 ast_pthread_mutex_lock(&chan->lock);
3141         if (chan->pbx) {
3142                 /* This channel is currently in the PBX */
3143                 if (context && strlen(context))
3144                         strncpy(chan->context, context, sizeof(chan->context) - 1);