011bd268777af2422da85eaeac3efd9c4c2543f5
[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         localtime_r(&t,&tm);
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     e = ast_hint_extension(NULL, context, exten);    
1249     if (!e) {
1250         return -1;
1251     }
1252     
1253     pthread_mutex_lock(&notifylock);
1254     list = notifys;        
1255     
1256     while (list) {
1257         if (list->exten == e)
1258             break;          
1259         list = list->next;    
1260     }
1261
1262     if (!list) {
1263         if (!e) {
1264             pthread_mutex_unlock(&notifylock);
1265             return -1;
1266         }
1267         list = malloc(sizeof(struct ast_notify));
1268         if (!list) {
1269             pthread_mutex_unlock(&notifylock);
1270             return -1;
1271         }
1272         /* Initialize and insert new item */
1273         memset(list, 0, sizeof(struct ast_notify));
1274         list->exten = e;
1275         list->laststate = ast_extension_state2(e);
1276         list->next = notifys;
1277         notifys = list;
1278     }
1279     
1280     /* Now inserts the callback */
1281     cblist = malloc(sizeof(struct ast_notify_cb));
1282     if (!cblist) {
1283         pthread_mutex_unlock(&notifylock);
1284         return -1;
1285     }
1286     memset(cblist, 0, sizeof(struct ast_notify_cb));
1287     cblist->id = notifycnt++;
1288     cblist->callback = callback;
1289     cblist->data = data;
1290
1291     cblist->next = list->callbacks;
1292     list->callbacks = cblist;
1293
1294     pthread_mutex_unlock(&notifylock);
1295     return cblist->id;
1296 }
1297
1298 static int ast_extension_state_clean(struct ast_exten *e)
1299 {
1300     /* Cleanup the Notifys if hint is removed */
1301     struct ast_notify *list, *prev = NULL;
1302     struct ast_notify_cb *cblist, *cbprev;
1303
1304     pthread_mutex_lock(&notifylock);
1305
1306     list = notifys;    
1307     while(list) {
1308         if (list->exten==e) {
1309             cbprev = NULL;
1310             cblist = list->callbacks;
1311             while (cblist) {        
1312                 cbprev = cblist;            
1313                 cblist = cblist->next;
1314                 cblist->callback(list->exten->parent->name, list->exten->exten, -1, cblist->data);
1315                 free(cbprev);
1316             }
1317             list->callbacks = NULL;
1318
1319             if (!prev) {
1320                 notifys = list->next;
1321                 free(list);
1322                 list = notifys;
1323             } else {
1324                 prev->next = list->next;
1325                 free(list);
1326                 list = prev->next;
1327             }
1328         } else {
1329             prev = list;
1330             list = list->next;    
1331         }
1332     }
1333
1334     pthread_mutex_unlock(&notifylock);
1335     return 1;
1336 }
1337
1338 int ast_extension_state_del(int id)
1339 {
1340     struct ast_notify *list, *prev = NULL;
1341     struct ast_notify_cb *cblist, *cbprev;
1342     int res = -1;
1343             
1344     pthread_mutex_lock(&notifylock);
1345
1346     list = notifys;
1347     while (list) {
1348         cblist = list->callbacks;
1349         cbprev = NULL;
1350         while (cblist) {
1351             if (cblist->id==id) {
1352                 if (!cbprev) {
1353                     list->callbacks = cblist->next;             
1354                     free(cblist);
1355                     cblist = list->callbacks;
1356                 } else {
1357                     cbprev->next = cblist->next;
1358                     free(cblist);
1359                     cblist = cbprev->next;
1360                 }
1361                 
1362                 if (!list->callbacks) {
1363                     if (!prev) {
1364                         notifys = list->next;
1365                         free(list);
1366                         list = notifys;
1367                     } else {
1368                         prev->next = list->next;
1369                         free(list);
1370                         list = prev->next;
1371                     }
1372                 }
1373                 res = 0;
1374                 break;
1375             } else {
1376                 cbprev = cblist;                                
1377                 cblist = cblist->next;
1378             }
1379         }
1380
1381         // we can have only one item
1382         if (cblist || !list)
1383             break;          
1384             
1385         prev = list;
1386         list = list->next;
1387     }
1388     
1389     pthread_mutex_unlock(&notifylock);
1390     return res;
1391 }
1392
1393 int ast_get_hint(char *hint, int maxlen, struct ast_channel *c, char *context, char *exten)
1394 {
1395         struct ast_exten *e;
1396         e = ast_hint_extension(c, context, exten);
1397         if (e) {        
1398             strncpy(hint, ast_get_extension_app(e), maxlen);
1399             return -1;
1400         }
1401         return 0;       
1402 }
1403
1404 int ast_exists_extension(struct ast_channel *c, char *context, char *exten, int priority, char *callerid) 
1405 {
1406         return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_EXISTS);
1407 }
1408
1409 int ast_canmatch_extension(struct ast_channel *c, char *context, char *exten, int priority, char *callerid)
1410 {
1411         return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_CANMATCH);
1412 }
1413
1414 int ast_matchmore_extension(struct ast_channel *c, char *context, char *exten, int priority, char *callerid)
1415 {
1416         return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_MATCHMORE);
1417 }
1418
1419 int ast_spawn_extension(struct ast_channel *c, char *context, char *exten, int priority, char *callerid) 
1420 {
1421         return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_SPAWN);
1422 }
1423
1424 int ast_pbx_run(struct ast_channel *c)
1425 {
1426         int firstpass = 1;
1427         char digit;
1428         char exten[256];
1429         int pos;
1430         int waittime;
1431         int res=0;
1432
1433         /* A little initial setup here */
1434         if (c->pbx)
1435                 ast_log(LOG_WARNING, "%s already has PBX structure??\n", c->name);
1436         c->pbx = malloc(sizeof(struct ast_pbx));
1437         if (!c->pbx) {
1438                 ast_log(LOG_WARNING, "Out of memory\n");
1439                 return -1;
1440         }
1441         if (c->amaflags) {
1442                 if (c->cdr) {
1443                         ast_log(LOG_WARNING, "%s already has a call record??\n", c->name);
1444                 } else {
1445                         c->cdr = ast_cdr_alloc();
1446                         if (!c->cdr) {
1447                                 ast_log(LOG_WARNING, "Unable to create Call Detail Record\n");
1448                                 free(c->pbx);
1449                                 return -1;
1450                         }
1451                         ast_cdr_init(c->cdr, c);
1452                 }
1453         }
1454         memset(c->pbx, 0, sizeof(struct ast_pbx));
1455         /* Set reasonable defaults */
1456         c->pbx->rtimeout = 10;
1457         c->pbx->dtimeout = 5;
1458
1459         /* Start by trying whatever the channel is set to */
1460         if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) {
1461                 /* JK02: If not successfull fall back to 's' */
1462                 strncpy(c->exten, "s", sizeof(c->exten)-1);
1463                 if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) {
1464                         /* JK02: And finally back to default if everything else failed */
1465                         strncpy(c->context, "default", sizeof(c->context)-1);
1466                 }
1467                 c->priority = 1;
1468         }
1469         if (c->cdr)
1470                 ast_cdr_start(c->cdr);
1471         for(;;) {
1472                 pos = 0;
1473                 digit = 0;
1474                 while(ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) {
1475                         memset(exten, 0, sizeof(exten));
1476                         manager_event(EVENT_FLAG_CALL, "Newexten", 
1477                                 "Channel: %s\r\n"
1478                                 "Context: %s\r\n"
1479                                 "Extension: %s\r\n"
1480                                 "Priority: %d\r\n",
1481                                 c->name, c->context, c->exten, c->priority);                    
1482                         if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->callerid))) {
1483                                 /* Something bad happened, or a hangup has been requested. */
1484                                 if (((res >= '0') && (res <= '9')) || ((res >= 'A') && (res <= 'F')) ||
1485                                         (res == '*') || (res == '#')) {
1486                                         ast_log(LOG_DEBUG, "Oooh, got something to jump out with ('%c')!\n", res);
1487                                         memset(exten, 0, sizeof(exten));
1488                                         pos = 0;
1489                                         exten[pos++] = digit = res;
1490                                         break;
1491                                 }
1492                                 switch(res) {
1493                                 case AST_PBX_KEEPALIVE:
1494                                         if (option_debug)
1495                                                 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
1496                                         else if (option_verbose > 1)
1497                                                 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
1498                                         goto out;
1499                                         break;
1500                                 default:
1501                                         if (option_debug)
1502                                                 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
1503                                         else if (option_verbose > 1)
1504                                                 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
1505                                         if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
1506                                                 c->_softhangup =0;
1507                                                 break;
1508                                         }
1509                                         /* atimeout */
1510                                         if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) {
1511                                                 break;
1512                                         }
1513                                         goto out;
1514                                 }
1515                         }
1516                         if ((c->_softhangup == AST_SOFTHANGUP_TIMEOUT) && (ast_exists_extension(c,c->context,"T",1,c->callerid))) {
1517                                 strncpy(c->exten,"T",sizeof(c->exten) - 1);
1518                                 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
1519                                 c->whentohangup = 0;
1520                         } else if (c->_softhangup) {
1521                                 ast_log(LOG_DEBUG, "Extension %s, priority %d returned normally even though call was hung up\n",
1522                                         c->exten, c->priority);
1523                                 goto out;
1524                         }
1525                         firstpass = 0;
1526                         c->priority++;
1527                 }
1528                 if (!ast_exists_extension(c, c->context, c->exten, 1, c->callerid)) {
1529                         /* It's not a valid extension anymore */
1530                         if (ast_exists_extension(c, c->context, "i", 1, c->callerid)) {
1531                                 if (option_verbose > 2)
1532                                         ast_verbose(VERBOSE_PREFIX_3 "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, c->name);
1533                                 strncpy(c->exten, "i", sizeof(c->exten)-1);
1534                                 c->priority = 1;
1535                         } else {
1536                                 ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n",
1537                                         c->name, c->exten, c->context);
1538                                 goto out;
1539                         }
1540                 } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) {
1541                         /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */
1542                         c->_softhangup = 0;
1543                 } else {
1544                         /* Done, wait for an extension */
1545                         if (digit)
1546                                 waittime = c->pbx->dtimeout;
1547                         else
1548                                 waittime = c->pbx->rtimeout;
1549                         while (ast_matchmore_extension(c, c->context, exten, 1, c->callerid)) {
1550                                 /* As long as we're willing to wait, and as long as it's not defined, 
1551                                    keep reading digits until we can't possibly get a right answer anymore.  */
1552                                 digit = ast_waitfordigit(c, waittime * 1000);
1553                                 if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
1554                                         c->_softhangup = 0;
1555                                 } else {
1556                                         if (!digit)
1557                                                 /* No entry */
1558                                                 break;
1559                                         if (digit < 0)
1560                                                 /* Error, maybe a  hangup */
1561                                                 goto out;
1562                                         exten[pos++] = digit;
1563                                         waittime = c->pbx->dtimeout;
1564                                 }
1565                         }
1566                         if (ast_exists_extension(c, c->context, exten, 1, c->callerid)) {
1567                                 /* Prepare the next cycle */
1568                                 strncpy(c->exten, exten, sizeof(c->exten)-1);
1569                                 c->priority = 1;
1570                         } else {
1571                                 /* No such extension */
1572                                 if (strlen(exten)) {
1573                                         /* An invalid extension */
1574                                         if (ast_exists_extension(c, c->context, "i", 1, c->callerid)) {
1575                                                 if (option_verbose > 2)
1576                                                         ast_verbose( VERBOSE_PREFIX_3 "Invalid extension '%s' in context '%s' on %s\n", exten, c->context, c->name);
1577                                                 strncpy(c->exten, "i", sizeof(c->exten)-1);
1578                                                 c->priority = 1;
1579                                         } else {
1580                                                 ast_log(LOG_WARNING, "Invalid extension, but no rule 'i' in context '%s'\n", c->context);
1581                                                 goto out;
1582                                         }
1583                                 } else {
1584                                         /* A simple timeout */
1585                                         if (ast_exists_extension(c, c->context, "t", 1, c->callerid)) {
1586                                                 if (option_verbose > 2)
1587                                                         ast_verbose( VERBOSE_PREFIX_3 "Timeout on %s\n", c->name);
1588                                                 strncpy(c->exten, "t", sizeof(c->exten)-1);
1589                                                 c->priority = 1;
1590                                         } else {
1591                                                 ast_log(LOG_WARNING, "Timeout, but no rule 't' in context '%s'\n", c->context);
1592                                                 goto out;
1593                                         }
1594                                 }       
1595                         }
1596                 }
1597         }
1598         if (firstpass) 
1599                 ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name);
1600 out:
1601         if (ast_exists_extension(c, c->context, "h", 1, c->callerid)) {
1602                 strcpy(c->exten, "h");
1603                 c->priority = 1;
1604                 while(ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) {
1605                         if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->callerid))) {
1606                                 /* Something bad happened, or a hangup has been requested. */
1607                                 if (option_debug)
1608                                         ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
1609                                 else if (option_verbose > 1)
1610                                         ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
1611                                 break;
1612                         }
1613                         c->priority++;
1614                 }
1615         }
1616
1617         pbx_destroy(c->pbx);
1618         c->pbx = NULL;
1619         if (res != AST_PBX_KEEPALIVE)
1620                 ast_hangup(c);
1621         return 0;
1622 }
1623
1624 static void *pbx_thread(void *data)
1625 {
1626         /* Oh joyeous kernel, we're a new thread, with nothing to do but
1627            answer this channel and get it going.  The setjmp stuff is fairly
1628            confusing, but necessary to get smooth transitions between
1629            the execution of different applications (without the use of
1630            additional threads) */
1631         struct ast_channel *c = data;
1632         ast_pbx_run(c);
1633         pthread_exit(NULL);
1634         return NULL;
1635 }
1636
1637 int ast_pbx_start(struct ast_channel *c)
1638 {
1639         pthread_t t;
1640         pthread_attr_t attr;
1641         if (!c) {
1642                 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
1643                 return -1;
1644         }
1645            
1646         /* Start a new thread, and get something handling this channel. */
1647         pthread_attr_init(&attr);
1648         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1649         if (pthread_create(&t, &attr, pbx_thread, c)) {
1650                 ast_log(LOG_WARNING, "Failed to create new channel thread\n");
1651                 return -1;
1652         }
1653         return 0;
1654 }
1655
1656 /*
1657  * This function locks contexts list by &conlist, search for the rigt context
1658  * structure, leave context list locked and call ast_context_remove_include2
1659  * which removes include, unlock contexts list and return ...
1660  */
1661 int ast_context_remove_include(char *context, char *include, char *registrar)
1662 {
1663         struct ast_context *c;
1664
1665         if (ast_lock_contexts()) return -1;
1666
1667         /* walk contexts and search for the right one ...*/
1668         c = ast_walk_contexts(NULL);
1669         while (c) {
1670                 /* we found one ... */
1671                 if (!strcmp(ast_get_context_name(c), context)) {
1672                         int ret;
1673                         /* remove include from this context ... */      
1674                         ret = ast_context_remove_include2(c, include, registrar);
1675
1676                         ast_unlock_contexts();
1677
1678                         /* ... return results */
1679                         return ret;
1680                 }
1681                 c = ast_walk_contexts(c);
1682         }
1683
1684         /* we can't find the right one context */
1685         ast_unlock_contexts();
1686         return -1;
1687 }
1688
1689 /*
1690  * When we call this function, &conlock lock must be locked, because when
1691  * we giving *con argument, some process can remove/change this context
1692  * and after that there can be segfault.
1693  *
1694  * This function locks given context, removes include, unlock context and
1695  * return.
1696  */
1697 int ast_context_remove_include2(struct ast_context *con, char *include, char *registrar)
1698 {
1699         struct ast_include *i, *pi = NULL;
1700
1701         if (ast_pthread_mutex_lock(&con->lock)) return -1;
1702
1703         /* walk includes */
1704         i = con->includes;
1705         while (i) {
1706                 /* find our include */
1707                 if (!strcmp(i->name, include) && 
1708                         (!strcmp(i->registrar, registrar) || !registrar)) {
1709                         /* remove from list */
1710                         if (pi)
1711                                 pi->next = i->next;
1712                         else
1713                                 con->includes = i->next;
1714                         /* free include and return */
1715                         free(i);
1716                         ast_pthread_mutex_unlock(&con->lock);
1717                         return 0;
1718                 }
1719                 pi = i;
1720                 i = i->next;
1721         }
1722
1723         /* we can't find the right include */
1724         ast_pthread_mutex_unlock(&con->lock);
1725         return -1;
1726 }
1727
1728 /*
1729  * This function locks contexts list by &conlist, search for the rigt context
1730  * structure, leave context list locked and call ast_context_remove_switch2
1731  * which removes switch, unlock contexts list and return ...
1732  */
1733 int ast_context_remove_switch(char *context, char *sw, char *data, char *registrar)
1734 {
1735         struct ast_context *c;
1736
1737         if (ast_lock_contexts()) return -1;
1738
1739         /* walk contexts and search for the right one ...*/
1740         c = ast_walk_contexts(NULL);
1741         while (c) {
1742                 /* we found one ... */
1743                 if (!strcmp(ast_get_context_name(c), context)) {
1744                         int ret;
1745                         /* remove switch from this context ... */       
1746                         ret = ast_context_remove_switch2(c, sw, data, registrar);
1747
1748                         ast_unlock_contexts();
1749
1750                         /* ... return results */
1751                         return ret;
1752                 }
1753                 c = ast_walk_contexts(c);
1754         }
1755
1756         /* we can't find the right one context */
1757         ast_unlock_contexts();
1758         return -1;
1759 }
1760
1761 /*
1762  * When we call this function, &conlock lock must be locked, because when
1763  * we giving *con argument, some process can remove/change this context
1764  * and after that there can be segfault.
1765  *
1766  * This function locks given context, removes switch, unlock context and
1767  * return.
1768  */
1769 int ast_context_remove_switch2(struct ast_context *con, char *sw, char *data, char *registrar)
1770 {
1771         struct ast_sw *i, *pi = NULL;
1772
1773         if (ast_pthread_mutex_lock(&con->lock)) return -1;
1774
1775         /* walk switchs */
1776         i = con->alts;
1777         while (i) {
1778                 /* find our switch */
1779                 if (!strcmp(i->name, sw) && !strcmp(i->data, data) && 
1780                         (!strcmp(i->registrar, registrar) || !registrar)) {
1781                         /* remove from list */
1782                         if (pi)
1783                                 pi->next = i->next;
1784                         else
1785                                 con->alts = i->next;
1786                         /* free switch and return */
1787                         free(i);
1788                         ast_pthread_mutex_unlock(&con->lock);
1789                         return 0;
1790                 }
1791                 pi = i;
1792                 i = i->next;
1793         }
1794
1795         /* we can't find the right switch */
1796         ast_pthread_mutex_unlock(&con->lock);
1797         return -1;
1798 }
1799
1800 /*
1801  * This functions lock contexts list, search for the right context,
1802  * call ast_context_remove_extension2, unlock contexts list and return.
1803  * In this function we are using
1804  */
1805 int ast_context_remove_extension(char *context, char *extension, int priority, char *registrar)
1806 {
1807         struct ast_context *c;
1808
1809         if (ast_lock_contexts()) return -1;
1810
1811         /* walk contexts ... */
1812         c = ast_walk_contexts(NULL);
1813         while (c) {
1814                 /* ... search for the right one ... */
1815                 if (!strcmp(ast_get_context_name(c), context)) {
1816                         /* ... remove extension ... */
1817                         int ret = ast_context_remove_extension2(c, extension, priority,
1818                                 registrar);
1819                         /* ... unlock contexts list and return */
1820                         ast_unlock_contexts();
1821                         return ret;
1822                 }
1823                 c = ast_walk_contexts(c);
1824         }
1825
1826         /* we can't find the right context */
1827         ast_unlock_contexts();
1828         return -1;
1829 }
1830
1831 /*
1832  * When do you want to call this function, make sure that &conlock is locked,
1833  * because some process can handle with your *con context before you lock
1834  * it.
1835  *
1836  * This functionc locks given context, search for the right extension and
1837  * fires out all peer in this extensions with given priority. If priority
1838  * is set to 0, all peers are removed. After that, unlock context and
1839  * return.
1840  */
1841 int ast_context_remove_extension2(struct ast_context *con, char *extension, int priority, char *registrar)
1842 {
1843         struct ast_exten *exten, *prev_exten = NULL;
1844
1845         if (ast_pthread_mutex_lock(&con->lock)) return -1;
1846
1847         /* go through all extensions in context and search the right one ... */
1848         exten = con->root;
1849         while (exten) {
1850
1851                 /* look for right extension */
1852                 if (!strcmp(exten->exten, extension) &&
1853                         (!strcmp(exten->registrar, registrar) || !registrar)) {
1854                         struct ast_exten *peer;
1855
1856                         /* should we free all peers in this extension? (priority == 0)? */
1857                         if (priority == 0) {
1858                                 /* remove this extension from context list */
1859                                 if (prev_exten)
1860                                         prev_exten->next = exten->next;
1861                                 else
1862                                         con->root = exten->next;
1863
1864                                 /* fire out all peers */
1865                                 peer = exten; 
1866                                 while (peer) {
1867                                         exten = peer->peer;
1868                                         
1869                                         if (!peer->priority==PRIORITY_HINT) 
1870                                             ast_extension_state_clean(peer);
1871
1872                                         peer->datad(peer->data);
1873                                         free(peer);
1874
1875                                         peer = exten;
1876                                 }
1877
1878                                 ast_pthread_mutex_unlock(&con->lock);
1879                                 return 0;
1880                         } else {
1881                                 /* remove only extension with exten->priority == priority */
1882                                 struct ast_exten *previous_peer = NULL;
1883
1884                                 peer = exten;
1885                                 while (peer) {
1886                                         /* is this our extension? */
1887                                         if (peer->priority == priority &&
1888                                                 (!strcmp(peer->registrar, registrar) || !registrar)) {
1889                                                 /* we are first priority extension? */
1890                                                 if (!previous_peer) {
1891                                                         /* exists previous extension here? */
1892                                                         if (prev_exten) {
1893                                                                 /* yes, so we must change next pointer in
1894                                                                  * previous connection to next peer
1895                                                                  */
1896                                                                 if (peer->peer) {
1897                                                                         prev_exten->next = peer->peer;
1898                                                                         peer->peer->next = exten->next;
1899                                                                 } else
1900                                                                         prev_exten->next = exten->next;
1901                                                         } else {
1902                                                                 /* no previous extension, we are first
1903                                                                  * extension, so change con->root ...
1904                                                                  */
1905                                                                 if (peer->peer)
1906                                                                         con->root = peer->peer;
1907                                                                 else
1908                                                                         con->root = exten->next; 
1909                                                         }
1910                                                 } else {
1911                                                         /* we are not first priority in extension */
1912                                                         previous_peer->peer = peer->peer;
1913                                                 }
1914
1915                                                 /* now, free whole priority extension */
1916                                                 if (peer->priority==PRIORITY_HINT)
1917                                                     ast_extension_state_clean(peer);
1918                                                 peer->datad(peer->data);
1919                                                 free(peer);
1920
1921                                                 ast_pthread_mutex_unlock(&con->lock);
1922                                                 return 0;
1923                                         } else {
1924                                                 /* this is not right extension, skip to next peer */
1925                                                 previous_peer = peer;
1926                                                 peer = peer->peer;
1927                                         }
1928                                 }
1929
1930                                 ast_pthread_mutex_unlock(&con->lock);
1931                                 return -1;
1932                         }
1933                 }
1934
1935                 prev_exten = exten;
1936                 exten = exten->next;
1937         }
1938
1939         /* we can't find right extension */
1940         ast_pthread_mutex_unlock(&con->lock);
1941         return -1;
1942 }
1943
1944
1945 int ast_register_application(char *app, int (*execute)(struct ast_channel *, void *), char *synopsis, char *description)
1946 {
1947         struct ast_app *tmp;
1948         char tmps[80];
1949         if (ast_pthread_mutex_lock(&applock)) {
1950                 ast_log(LOG_ERROR, "Unable to lock application list\n");
1951                 return -1;
1952         }
1953         tmp = apps;
1954         while(tmp) {
1955                 if (!strcasecmp(app, tmp->name)) {
1956                         ast_log(LOG_WARNING, "Already have an application '%s'\n", app);
1957                         ast_pthread_mutex_unlock(&applock);
1958                         return -1;
1959                 }
1960                 tmp = tmp->next;
1961         }
1962         tmp = malloc(sizeof(struct ast_app));
1963         if (tmp) {
1964                 memset(tmp, 0, sizeof(struct ast_app));
1965                 strncpy(tmp->name, app, sizeof(tmp->name)-1);
1966                 tmp->execute = execute;
1967                 tmp->synopsis = synopsis;
1968                 tmp->description = description;
1969                 tmp->next = apps;
1970                 apps = tmp;
1971         } else {
1972                 ast_log(LOG_WARNING, "Out of memory\n");
1973                 ast_pthread_mutex_unlock(&applock);
1974                 return -1;
1975         }
1976         if (option_verbose > 1)
1977                 ast_verbose( VERBOSE_PREFIX_2 "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps)));
1978         ast_pthread_mutex_unlock(&applock);
1979         return 0;
1980 }
1981
1982 int ast_register_switch(struct ast_switch *sw)
1983 {
1984         struct ast_switch *tmp, *prev=NULL;
1985         if (ast_pthread_mutex_lock(&switchlock)) {
1986                 ast_log(LOG_ERROR, "Unable to lock switch lock\n");
1987                 return -1;
1988         }
1989         tmp = switches;
1990         while(tmp) {
1991                 if (!strcasecmp(tmp->name, sw->name))
1992                         break;
1993                 prev = tmp;
1994                 tmp = tmp->next;
1995         }
1996         if (tmp) {      
1997                 ast_pthread_mutex_unlock(&switchlock);
1998                 ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name);
1999                 return -1;
2000         }
2001         sw->next = NULL;
2002         if (prev) 
2003                 prev->next = sw;
2004         else
2005                 switches = sw;
2006         ast_pthread_mutex_unlock(&switchlock);
2007         return 0;
2008 }
2009
2010 void ast_unregister_switch(struct ast_switch *sw)
2011 {
2012         struct ast_switch *tmp, *prev=NULL;
2013         if (ast_pthread_mutex_lock(&switchlock)) {
2014                 ast_log(LOG_ERROR, "Unable to lock switch lock\n");
2015                 return;
2016         }
2017         tmp = switches;
2018         while(tmp) {
2019                 if (tmp == sw) {
2020                         if (prev)
2021                                 prev->next = tmp->next;
2022                         else
2023                                 switches = tmp->next;
2024                         tmp->next = NULL;
2025                         break;                  
2026                 }
2027                 prev = tmp;
2028                 tmp = tmp->next;
2029         }
2030         ast_pthread_mutex_unlock(&switchlock);
2031 }
2032
2033 /*
2034  * Help for CLI commands ...
2035  */
2036 static char show_application_help[] = 
2037 "Usage: show application <application> [<application> [<application> [...]]]\n"
2038 "       Describes a particular application.\n";
2039
2040 static char show_applications_help[] =
2041 "Usage: show applications\n"
2042 "       List applications which are currently available.\n";
2043
2044 static char show_dialplan_help[] =
2045 "Usage: show dialplan [exten@][context]\n"
2046 "       Show dialplan\n";
2047
2048 static char show_switches_help[] = 
2049 "Usage: show switches\n"
2050 "       Show registered switches\n";
2051
2052 /*
2053  * IMPLEMENTATION OF CLI FUNCTIONS IS IN THE SAME ORDER AS COMMANDS HELPS
2054  *
2055  */
2056
2057 /*
2058  * 'show application' CLI command implementation functions ...
2059  */
2060
2061 /*
2062  * There is a possibility to show informations about more than one
2063  * application at one time. You can type 'show application Dial Echo' and
2064  * you will see informations about these two applications ...
2065  */
2066 static char *complete_show_application(char *line, char *word,
2067         int pos, int state)
2068 {
2069         struct ast_app *a;
2070         int which = 0;
2071
2072         /* try to lock applications list ... */
2073         if (ast_pthread_mutex_lock(&applock)) {
2074                 ast_log(LOG_ERROR, "Unable to lock application list\n");
2075                 return NULL;
2076         }
2077
2078         /* ... walk all applications ... */
2079         a = apps; 
2080         while (a) {
2081                 /* ... check if word matches this application ... */
2082                 if (!strncasecmp(word, a->name, strlen(word))) {
2083                         /* ... if this is right app serve it ... */
2084                         if (++which > state) {
2085                                 char *ret = strdup(a->name);
2086                                 ast_pthread_mutex_unlock(&applock);
2087                                 return ret;
2088                         }
2089                 }
2090                 a = a->next; 
2091         }
2092
2093         /* no application match */
2094         ast_pthread_mutex_unlock(&applock);
2095         return NULL; 
2096 }
2097
2098 static int handle_show_application(int fd, int argc, char *argv[])
2099 {
2100         struct ast_app *a;
2101         char buf[2048];
2102         int app, no_registered_app = 1;
2103
2104         if (argc < 3) return RESULT_SHOWUSAGE;
2105
2106         /* try to lock applications list ... */
2107         if (ast_pthread_mutex_lock(&applock)) {
2108                 ast_log(LOG_ERROR, "Unable to lock application list\n");
2109                 return -1;
2110         }
2111
2112         /* ... go through all applications ... */
2113         a = apps; 
2114         while (a) {
2115                 /* ... compare this application name with all arguments given
2116                  * to 'show application' command ... */
2117                 for (app = 2; app < argc; app++) {
2118                         if (!strcasecmp(a->name, argv[app])) {
2119                                 no_registered_app = 0;
2120
2121                                 /* ... one of our applications, show info ...*/
2122                                 snprintf(buf, sizeof(buf),
2123                                         "\n  -= Info about application '%s' =- \n\n"
2124                                         "[Synopsis]:\n  %s\n\n"
2125                                         "[Description]:\n%s\n",
2126                                         a->name,
2127                                         a->synopsis ? a->synopsis : "Not available",
2128                                         a->description ? a-> description : "Not available");
2129                                 ast_cli(fd, buf);
2130                         }
2131                 }
2132                 a = a->next; 
2133         }
2134
2135         ast_pthread_mutex_unlock(&applock);
2136
2137         /* we found at least one app? no? */
2138         if (no_registered_app) {
2139                 ast_cli(fd, "Your application(s) is (are) not registered\n");
2140                 return RESULT_FAILURE;
2141         }
2142
2143         return RESULT_SUCCESS;
2144 }
2145
2146 static int handle_show_switches(int fd, int argc, char *argv[])
2147 {
2148         struct ast_switch *sw;
2149         if (!switches) {
2150                 ast_cli(fd, "There are no registered alternative switches\n");
2151                 return RESULT_SUCCESS;
2152         }
2153         /* ... we have applications ... */
2154         ast_cli(fd, "\n    -= Registered Asterisk Alternative Switches =-\n");
2155         if (ast_pthread_mutex_lock(&switchlock)) {
2156                 ast_log(LOG_ERROR, "Unable to lock switches\n");
2157                 return -1;
2158         }
2159         sw = switches;
2160         while (sw) {
2161                 ast_cli(fd, "%s: %s\n", sw->name, sw->description);
2162                 sw = sw->next;
2163         }
2164         ast_pthread_mutex_unlock(&switchlock);
2165         return RESULT_SUCCESS;
2166 }
2167
2168 /*
2169  * 'show applications' CLI command implementation functions ...
2170  */
2171 static int handle_show_applications(int fd, int argc, char *argv[])
2172 {
2173         struct ast_app *a;
2174
2175         /* try to lock applications list ... */
2176         if (ast_pthread_mutex_lock(&applock)) {
2177                 ast_log(LOG_ERROR, "Unable to lock application list\n");
2178                 return -1;
2179         }
2180
2181         /* ... go to first application ... */
2182         a = apps; 
2183
2184         /* ... have we got at least one application (first)? no? */
2185         if (!a) {
2186                 ast_cli(fd, "There is no registered applications\n");
2187                 ast_pthread_mutex_unlock(&applock);
2188                 return -1;
2189         }
2190
2191         /* ... we have applications ... */
2192         ast_cli(fd, "\n    -= Registered Asterisk Applications =-\n");
2193
2194         /* ... go through all applications ... */
2195         while (a) {
2196                 /* ... show informations about applications ... */
2197                 ast_cli(fd,"  %15s: %s\n",
2198                         a->name,
2199                         a->synopsis ? a->synopsis : "<Synopsis not available>");
2200                 a = a->next; 
2201         }
2202
2203         /* ... unlock and return */
2204         ast_pthread_mutex_unlock(&applock);
2205
2206         return RESULT_SUCCESS;
2207 }
2208
2209 /*
2210  * 'show dialplan' CLI command implementation functions ...
2211  */
2212 static char *complete_show_dialplan_context(char *line, char *word, int pos,
2213         int state)
2214 {
2215         struct ast_context *c;
2216         int which = 0;
2217
2218         /* we are do completion of [exten@]context on second postion only */
2219         if (pos != 2) return NULL;
2220
2221         /* try to lock contexts list ... */
2222         if (ast_lock_contexts()) {
2223                 ast_log(LOG_ERROR, "Unable to lock context list\n");
2224                 return NULL;
2225         }
2226
2227         /* ... walk through all contexts ... */
2228         c = ast_walk_contexts(NULL);
2229         while(c) {
2230                 /* ... word matches context name? yes? ... */
2231                 if (!strncasecmp(word, ast_get_context_name(c), strlen(word))) {
2232                         /* ... for serve? ... */
2233                         if (++which > state) {
2234                                 /* ... yes, serve this context name ... */
2235                                 char *ret = strdup(ast_get_context_name(c));
2236                                 ast_unlock_contexts();
2237                                 return ret;
2238                         }
2239                 }
2240                 c = ast_walk_contexts(c);
2241         }
2242
2243         /* ... unlock and return */
2244         ast_unlock_contexts();
2245         return NULL;
2246 }
2247
2248 static int handle_show_dialplan(int fd, int argc, char *argv[])
2249 {
2250         struct ast_context *c;
2251         char *exten = NULL, *context = NULL;
2252         int context_existence = 0, extension_existence = 0;
2253
2254         if (argc != 3 && argc != 2) return -1;
2255
2256         /* we obtain [exten@]context? if yes, split them ... */
2257         if (argc == 3) {
2258                 char *splitter = argv[2];
2259                 /* is there a '@' character? */
2260                 if (strchr(argv[2], '@')) {
2261                         /* yes, split into exten & context ... */
2262                         exten   = strsep(&splitter, "@");
2263                         context = splitter;
2264
2265                         /* check for length and change to NULL if !strlen() */
2266                         if (!strlen(exten))   exten = NULL;
2267                         if (!strlen(context)) context = NULL;
2268                 } else
2269                 {
2270                         /* no '@' char, only context given */
2271                         context = argv[2];
2272                         if (!strlen(context)) context = NULL;
2273                 }
2274         }
2275
2276         /* try to lock contexts */
2277         if (ast_lock_contexts()) {
2278                 ast_cli(LOG_WARNING, "Failed to lock contexts list\n");
2279                 return RESULT_FAILURE;
2280         }
2281
2282         /* walk all contexts ... */
2283         c = ast_walk_contexts(NULL);
2284         while (c) {
2285                 /* show this context? */
2286                 if (!context ||
2287                         !strcmp(ast_get_context_name(c), context)) {
2288                         context_existence = 1;
2289
2290                         /* try to lock context before walking in ... */
2291                         if (!ast_lock_context(c)) {
2292                                 struct ast_exten *e;
2293                                 struct ast_include *i;
2294                                 struct ast_ignorepat *ip;
2295                                 struct ast_sw *sw;
2296                                 char buf[256], buf2[256];
2297                                 int context_info_printed = 0;
2298
2299                                 /* are we looking for exten too? if yes, we print context
2300                                  * if we our extension only
2301                                  */
2302                                 if (!exten) {
2303                                         ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
2304                                                 ast_get_context_name(c), ast_get_context_registrar(c));
2305                                         context_info_printed = 1;
2306                                 }
2307
2308                                 /* walk extensions ... */
2309                                 e = ast_walk_context_extensions(c, NULL);
2310                                 while (e) {
2311                                         struct ast_exten *p;
2312
2313                                         /* looking for extension? is this our extension? */
2314                                         if (exten &&
2315                                                 strcmp(ast_get_extension_name(e), exten))
2316                                         {
2317                                                 /* we are looking for extension and it's not our
2318                                                  * extension, so skip to next extension */
2319                                                 e = ast_walk_context_extensions(c, e);
2320                                                 continue;
2321                                         }
2322
2323                                         extension_existence = 1;
2324
2325                                         /* may we print context info? */        
2326                                         if (!context_info_printed) {
2327                                                 ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
2328                                                         ast_get_context_name(c),
2329                                                         ast_get_context_registrar(c));
2330                                                 context_info_printed = 1;
2331                                         }
2332
2333                                         /* write extension name and first peer */       
2334                                         bzero(buf, sizeof(buf));                
2335                                         snprintf(buf, sizeof(buf), "'%s' =>",
2336                                                 ast_get_extension_name(e));
2337
2338                                         snprintf(buf2, sizeof(buf2),
2339                                                 "%d. %s(%s)",
2340                                                 ast_get_extension_priority(e),
2341                                                 ast_get_extension_app(e),
2342                                                 (char *)ast_get_extension_app_data(e));
2343
2344                                         ast_cli(fd, "  %-17s %-45s [%s]\n", buf, buf2,
2345                                                 ast_get_extension_registrar(e));
2346
2347                                         /* walk next extension peers */
2348                                         p = ast_walk_extension_priorities(e, e);
2349                                         while (p) {
2350                                                 bzero((void *)buf2, sizeof(buf2));
2351
2352                                                 snprintf(buf2, sizeof(buf2),
2353                                                         "%d. %s(%s)",
2354                                                         ast_get_extension_priority(p),
2355                                                         ast_get_extension_app(p),
2356                                                         (char *)ast_get_extension_app_data(p));
2357
2358                                                 ast_cli(fd,"  %-17s %-45s [%s]\n",
2359                                                         "", buf2,
2360                                                         ast_get_extension_registrar(p));        
2361
2362                                                 p = ast_walk_extension_priorities(e, p);
2363                                         }
2364                                         e = ast_walk_context_extensions(c, e);
2365                                 }
2366
2367                                 /* include & ignorepat we all printing if we are not
2368                                  * looking for exact extension
2369                                  */
2370                                 if (!exten) {
2371                                         if (ast_walk_context_extensions(c, NULL))
2372                                                 ast_cli(fd, "\n");
2373
2374                                         /* walk included and write info ... */
2375                                         i = ast_walk_context_includes(c, NULL);
2376                                         while (i) {
2377                                                 bzero(buf, sizeof(buf));
2378                                                 snprintf(buf, sizeof(buf), "'%s'",
2379                                                         ast_get_include_name(i));
2380                                                 ast_cli(fd, "  Include =>        %-45s [%s]\n",
2381                                                         buf, ast_get_include_registrar(i));
2382                                                 i = ast_walk_context_includes(c, i);
2383                                         }
2384
2385                                         /* walk ignore patterns and write info ... */
2386                                         ip = ast_walk_context_ignorepats(c, NULL);
2387                                         while (ip) {
2388                                                 bzero(buf, sizeof(buf));
2389                                                 snprintf(buf, sizeof(buf), "'%s'",
2390                                                         ast_get_ignorepat_name(ip));
2391                                                 ast_cli(fd, "  Ignore pattern => %-45s [%s]\n",
2392                                                         buf, ast_get_ignorepat_registrar(ip));  
2393                                                 ip = ast_walk_context_ignorepats(c, ip);
2394                                         }
2395                                         sw = ast_walk_context_switches(c, NULL);
2396                                         while(sw) {
2397                                                 bzero(buf, sizeof(buf));
2398                                                 snprintf(buf, sizeof(buf), "'%s/%s'",
2399                                                         ast_get_switch_name(sw),
2400                                                         ast_get_switch_data(sw));
2401                                                 ast_cli(fd, "  Alt. Switch =>    %-45s [%s]\n",
2402                                                         buf, ast_get_switch_registrar(sw));     
2403                                                 sw = ast_walk_context_switches(c, sw);
2404                                         }
2405                                 }
2406         
2407                                 ast_unlock_context(c);
2408
2409                                 /* if we print something in context, make an empty line */
2410                                 if (context_info_printed) ast_cli(fd, "\n");
2411                         }
2412                 }
2413                 c = ast_walk_contexts(c);
2414         }
2415         ast_unlock_contexts();
2416
2417         /* check for input failure and throw some error messages */
2418         if (context && !context_existence) {
2419                 ast_cli(fd, "There is no existence of '%s' context\n",
2420                         context);
2421                 return RESULT_FAILURE;
2422         }
2423
2424         if (exten && !extension_existence) {
2425                 if (context)
2426                         ast_cli(fd, "There is no existence of %s@%s extension\n",
2427                                 exten, context);
2428                 else
2429                         ast_cli(fd,
2430                                 "There is no existence of '%s' extension in all contexts\n",
2431                                 exten);
2432                 return RESULT_FAILURE;
2433         }
2434
2435         /* everything ok */
2436         return RESULT_SUCCESS;
2437 }
2438
2439 /*
2440  * CLI entries for upper commands ...
2441  */
2442 static struct ast_cli_entry show_applications_cli = 
2443         { { "show", "applications", NULL }, 
2444         handle_show_applications, "Shows registered applications",
2445         show_applications_help };
2446
2447 static struct ast_cli_entry show_application_cli =
2448         { { "show", "application", NULL }, 
2449         handle_show_application, "Describe a specific application",
2450         show_application_help, complete_show_application };
2451
2452 static struct ast_cli_entry show_dialplan_cli =
2453         { { "show", "dialplan", NULL },
2454                 handle_show_dialplan, "Show dialplan",
2455                 show_dialplan_help, complete_show_dialplan_context };
2456
2457 static struct ast_cli_entry show_switches_cli =
2458         { { "show", "switches", NULL },
2459                 handle_show_switches, "Show alternative switches",
2460                 show_switches_help, NULL };
2461
2462 int ast_unregister_application(char *app) {
2463         struct ast_app *tmp, *tmpl = NULL;
2464         if (ast_pthread_mutex_lock(&applock)) {
2465                 ast_log(LOG_ERROR, "Unable to lock application list\n");
2466                 return -1;
2467         }
2468         tmp = apps;
2469         while(tmp) {
2470                 if (!strcasecmp(app, tmp->name)) {
2471                         if (tmpl)
2472                                 tmpl->next = tmp->next;
2473                         else
2474                                 apps = tmp->next;
2475                         if (option_verbose > 1)
2476                                 ast_verbose( VERBOSE_PREFIX_2 "Unregistered application '%s'\n", tmp->name);
2477                         ast_pthread_mutex_unlock(&applock);
2478                         return 0;
2479                 }
2480                 tmpl = tmp;
2481                 tmp = tmp->next;
2482         }
2483         ast_pthread_mutex_unlock(&applock);
2484         return -1;
2485 }
2486
2487 struct ast_context *ast_context_create(char *name, char *registrar)
2488 {
2489         struct ast_context *tmp;
2490         
2491         ast_pthread_mutex_lock(&conlock);
2492         tmp = contexts;
2493         while(tmp) {
2494                 if (!strcasecmp(tmp->name, name)) {
2495                         ast_pthread_mutex_unlock(&conlock);
2496                         ast_log(LOG_WARNING, "Tried to register context '%s', already in use\n", name);
2497                         return NULL;
2498                 }
2499                 tmp = tmp->next;
2500         }
2501         tmp = malloc(sizeof(struct ast_context));
2502         if (tmp) {
2503                 memset(tmp, 0, sizeof(struct ast_context));
2504                 ast_pthread_mutex_init(&tmp->lock);
2505                 strncpy(tmp->name, name, sizeof(tmp->name)-1);
2506                 tmp->root = NULL;
2507                 tmp->registrar = registrar;
2508                 tmp->next = contexts;
2509                 tmp->includes = NULL;
2510                 tmp->ignorepats = NULL;
2511                 contexts = tmp;
2512                 if (option_debug)
2513                         ast_log(LOG_DEBUG, "Registered context '%s'\n", tmp->name);
2514                 else if (option_verbose > 2)
2515                         ast_verbose( VERBOSE_PREFIX_3 "Registered extension context '%s'\n", tmp->name);
2516         } else
2517                 ast_log(LOG_WARNING, "Out of memory\n");
2518         
2519         ast_pthread_mutex_unlock(&conlock);
2520         return tmp;
2521 }
2522
2523 /*
2524  * errno values
2525  *  EBUSY  - can't lock
2526  *  ENODATA - no existence of context
2527  */
2528 int ast_context_add_include(char *context, char *include, char *registrar)
2529 {
2530         struct ast_context *c;
2531
2532         if (ast_lock_contexts()) {
2533                 errno = EBUSY;
2534                 return -1;
2535         }
2536
2537         /* walk contexts ... */
2538         c = ast_walk_contexts(NULL);
2539         while (c) {
2540                 /* ... search for the right one ... */
2541                 if (!strcmp(ast_get_context_name(c), context)) {
2542                         int ret = ast_context_add_include2(c, include, registrar);
2543                         /* ... unlock contexts list and return */
2544                         ast_unlock_contexts();
2545                         return ret;
2546                 }
2547                 c = ast_walk_contexts(c);
2548         }
2549
2550         /* we can't find the right context */
2551         ast_unlock_contexts();
2552         errno = ENODATA;
2553         return -1;
2554 }
2555
2556 #define FIND_NEXT \
2557 do { \
2558         c = info; \
2559         while(*c && (*c != '|')) c++; \
2560         if (*c) { *c = '\0'; c++; } else c = NULL; \
2561 } while(0)
2562
2563 static void get_timerange(struct ast_include *i, char *times)
2564 {
2565         char *e;
2566         int x;
2567         int s1, s2;
2568         int e1, e2;
2569         /* Star is all times */
2570         if (!strlen(times) || !strcmp(times, "*")) {
2571                 for (x=0;x<24;x++)
2572                         i->minmask[x] = (1 << 30) - 1;
2573                 return;
2574         }
2575         /* Otherwise expect a range */
2576         e = strchr(times, '-');
2577         if (!e) {
2578                 ast_log(LOG_WARNING, "Time range is not valid. Assuming no time.\n");
2579                 return;
2580         }
2581         *e = '\0';
2582         e++;
2583         while(*e && !isdigit(*e)) e++;
2584         if (!*e) {
2585                 ast_log(LOG_WARNING, "Invalid time range.  Assuming no time.\n");
2586                 return;
2587         }
2588         if (sscanf(times, "%d:%d", &s1, &s2) != 2) {
2589                 ast_log(LOG_WARNING, "%s isn't a time.  Assuming no time.\n", times);
2590                 return;
2591         }
2592         if (sscanf(e, "%d:%d", &e1, &e2) != 2) {
2593                 ast_log(LOG_WARNING, "%s isn't a time.  Assuming no time.\n", e);
2594                 return;
2595         }
2596         s1 = s1 * 30 + s2/2;
2597         if ((s1 < 0) || (s1 >= 24*30)) {
2598                 ast_log(LOG_WARNING, "%s isn't a valid star time. Assuming no time.\n", times);
2599                 return;
2600         }
2601         e1 = e1 * 30 + e2/2;
2602         if ((e1 < 0) || (e2 >= 24*30)) {
2603                 ast_log(LOG_WARNING, "%s isn't a valid start time. Assuming no time.\n", times);
2604                 return;
2605         }
2606         /* Go through the time and enable each appropriate bit */
2607         for (x=s1;x != e1;x = (x + 1) % (24 * 30)) {
2608                 i->minmask[x/30] |= (1 << (x % 30));
2609         }
2610         /* Do the last one */
2611         i->minmask[x/30] |= (1 << (x % 30));
2612         /* All done */
2613 }
2614
2615 static char *days[] =
2616 {
2617         "sun",
2618         "mon",
2619         "tue",
2620         "wed",
2621         "thu",
2622         "fri",
2623         "sat",
2624 };
2625
2626 static unsigned int get_dow(char *dow)
2627 {
2628         char *c;
2629         /* The following line is coincidence, really! */
2630         int s, e, x;
2631         unsigned int mask;
2632         /* Check for all days */
2633         if (!strlen(dow) || !strcmp(dow, "*"))
2634                 return (1 << 7) - 1;
2635         /* Get start and ending days */
2636         c = strchr(dow, '-');
2637         if (c) {
2638                 *c = '\0';
2639                 c++;
2640         } else
2641                 c = NULL;
2642         /* Find the start */
2643         s = 0;
2644         while((s < 7) && strcasecmp(dow, days[s])) s++;
2645         if (s >= 7) {
2646                 ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", dow);
2647                 return 0;
2648         }
2649         if (c) {
2650                 e = 0;
2651                 while((e < 7) && strcasecmp(c, days[e])) e++;
2652                 if (e >= 7) {
2653                         ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", c);
2654                         return 0;
2655                 }
2656         } else
2657                 e = s;
2658         mask = 0;
2659         for (x=s;x!=e;x = (x + 1) % 7) {
2660                 mask |= (1 << x);
2661         }
2662         /* One last one */
2663         mask |= (1 << x);
2664         return mask;
2665 }
2666
2667 static unsigned int get_day(char *day)
2668 {
2669         char *c;
2670         /* The following line is coincidence, really! */
2671         int s, e, x;
2672         unsigned int mask;
2673         /* Check for all days */
2674         if (!strlen(day) || !strcmp(day, "*")) {
2675                 mask = (1 << 30)  + ((1 << 30) - 1);
2676                 return mask;
2677         }
2678         /* Get start and ending days */
2679         c = strchr(day, '-');
2680         if (c) {
2681                 *c = '\0';
2682                 c++;
2683         }
2684         /* Find the start */
2685         if (sscanf(day, "%d", &s) != 1) {
2686                 ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", day);
2687                 return 0;
2688         }
2689         if ((s < 1) || (s > 31)) {
2690                 ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", day);
2691                 return 0;
2692         }
2693         s--;
2694         if (c) {
2695                 if (sscanf(c, "%d", &e) != 1) {
2696                         ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", c);
2697                         return 0;
2698                 }
2699                 if ((e < 1) || (e > 31)) {
2700                         ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", c);
2701                         return 0;
2702                 }
2703                 e--;
2704         } else
2705                 e = s;
2706         mask = 0;
2707         for (x=s;x!=e;x = (x + 1) % 31) {
2708                 mask |= (1 << x);
2709         }
2710         mask |= (1 << x);
2711         return mask;
2712 }
2713
2714 static char *months[] =
2715 {
2716         "jan",
2717         "feb",
2718         "mar",
2719         "apr",
2720         "may",
2721         "jun",
2722         "jul",
2723         "aug",
2724         "sep",
2725         "oct",
2726         "nov",
2727         "dec",
2728 };
2729
2730 static unsigned int get_month(char *mon)
2731 {
2732         char *c;
2733         /* The following line is coincidence, really! */
2734         int s, e, x;
2735         unsigned int mask;
2736         /* Check for all days */
2737         if (!strlen(mon) || !strcmp(mon, "*")) 
2738                 return (1 << 12) - 1;
2739         /* Get start and ending days */
2740         c = strchr(mon, '-');
2741         if (c) {
2742                 *c = '\0';
2743                 c++;
2744         }
2745         /* Find the start */
2746         s = 0;
2747         while((s < 12) && strcasecmp(mon, months[s])) s++;
2748         if (s >= 12) {
2749                 ast_log(LOG_WARNING, "Invalid month '%s', assuming none\n", mon);
2750                 return 0;
2751         }
2752         if (c) {
2753                 e = 0;
2754                 while((e < 12) && strcasecmp(mon, months[e])) e++;
2755                 if (e >= 12) {
2756                         ast_log(LOG_WARNING, "Invalid month '%s', assuming none\n", c);
2757                         return 0;
2758                 }
2759         } else
2760                 e = s;
2761         mask = 0;
2762         for (x=s;x!=e;x = (x + 1) % 12) {
2763                 mask |= (1 << x);
2764         }
2765         /* One last one */
2766         mask |= (1 << x);
2767         return mask;
2768 }
2769
2770 static void build_timing(struct ast_include *i, char *info)
2771 {
2772         char *c;
2773         /* Check for empty just in case */
2774         if (!strlen(info))
2775                 return;
2776         i->hastime = 1;
2777         /* Assume everything except time */
2778         i->monthmask = (1 << 12) - 1;
2779         i->daymask = (1 << 30) - 1 + (1 << 30);
2780         i->dowmask = (1 << 7) - 1;
2781         /* Avoid using str tok */
2782         FIND_NEXT;
2783         /* Info has the time range, start with that */
2784         get_timerange(i, info);
2785         info = c;
2786         if (!info)
2787                 return;
2788         FIND_NEXT;
2789         /* Now check for day of week */
2790         i->dowmask = get_dow(info);
2791
2792         info = c;
2793         if (!info)
2794                 return;
2795         FIND_NEXT;
2796         /* Now check for the day of the month */
2797         i->daymask = get_day(info);
2798         info = c;
2799         if (!info)
2800                 return;
2801         FIND_NEXT;
2802         /* And finally go for the month */
2803         i->monthmask = get_month(info);
2804 }
2805
2806 /*
2807  * errno values
2808  *  ENOMEM - out of memory
2809  *  EBUSY  - can't lock
2810  *  EEXIST - already included
2811  *  EINVAL - there is no existence of context for inclusion
2812  */
2813 int ast_context_add_include2(struct ast_context *con, char *value,
2814         char *registrar)
2815 {
2816         struct ast_include *new_include;
2817         char *c;
2818         struct ast_include *i, *il = NULL; /* include, include_last */
2819
2820         /* allocate new include structure ... */
2821         if (!(new_include = malloc(sizeof(struct ast_include)))) {
2822                 ast_log(LOG_WARNING, "Out of memory\n");
2823                 errno = ENOMEM;
2824                 return -1;
2825         }
2826         
2827         /* ... fill in this structure ... */
2828         memset(new_include, 0, sizeof(struct ast_include));
2829         strncpy(new_include->name, value, sizeof(new_include->name)-1);
2830         strncpy(new_include->rname, value, sizeof(new_include->rname)-1);
2831         c = new_include->rname;
2832         /* Strip off timing info */
2833         while(*c && (*c != '|')) c++; 
2834         /* Process if it's there */
2835         if (*c) {
2836                 build_timing(new_include, c+1);
2837                 *c = '\0';
2838         }
2839         new_include->next      = NULL;
2840         new_include->registrar = registrar;
2841
2842         /* ... try to lock this context ... */
2843         if (ast_pthread_mutex_lock(&con->lock)) {
2844                 free(new_include);
2845                 errno = EBUSY;
2846                 return -1;
2847         }
2848
2849         /* ... go to last include and check if context is already included too... */
2850         i = con->includes;
2851         while (i) {
2852                 if (!strcasecmp(i->name, new_include->name)) {
2853                         free(new_include);
2854                         ast_pthread_mutex_unlock(&con->lock);
2855                         errno = EEXIST;
2856                         return -1;
2857                 }
2858                 il = i;
2859                 i = i->next;
2860         }
2861
2862         /* ... include new context into context list, unlock, return */
2863         if (il)
2864                 il->next = new_include;
2865         else
2866                 con->includes = new_include;
2867         if (option_verbose > 2)
2868                 ast_verbose(VERBOSE_PREFIX_3 "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con)); 
2869         ast_pthread_mutex_unlock(&con->lock);
2870
2871         return 0;
2872 }
2873
2874 /*
2875  * errno values
2876  *  EBUSY  - can't lock
2877  *  ENODATA - no existence of context
2878  */
2879 int ast_context_add_switch(char *context, char *sw, char *data, char *registrar)
2880 {
2881         struct ast_context *c;
2882
2883         if (ast_lock_contexts()) {
2884                 errno = EBUSY;
2885                 return -1;
2886         }
2887
2888         /* walk contexts ... */
2889         c = ast_walk_contexts(NULL);
2890         while (c) {
2891                 /* ... search for the right one ... */
2892                 if (!strcmp(ast_get_context_name(c), context)) {
2893                         int ret = ast_context_add_switch2(c, sw, data, registrar);
2894                         /* ... unlock contexts list and return */
2895                         ast_unlock_contexts();
2896                         return ret;
2897                 }
2898                 c = ast_walk_contexts(c);
2899         }
2900
2901         /* we can't find the right context */
2902         ast_unlock_contexts();
2903         errno = ENODATA;
2904         return -1;
2905 }
2906
2907 /*
2908  * errno values
2909  *  ENOMEM - out of memory
2910  *  EBUSY  - can't lock
2911  *  EEXIST - already included
2912  *  EINVAL - there is no existence of context for inclusion
2913  */
2914 int ast_context_add_switch2(struct ast_context *con, char *value,
2915         char *data, char *registrar)
2916 {
2917         struct ast_sw *new_sw;
2918         struct ast_sw *i, *il = NULL; /* sw, sw_last */
2919
2920         /* allocate new sw structure ... */
2921         if (!(new_sw = malloc(sizeof(struct ast_sw)))) {
2922                 ast_log(LOG_WARNING, "Out of memory\n");
2923                 errno = ENOMEM;
2924                 return -1;
2925         }
2926         
2927         /* ... fill in this structure ... */
2928         memset(new_sw, 0, sizeof(struct ast_sw));
2929         strncpy(new_sw->name, value, sizeof(new_sw->name)-1);
2930         if (data)
2931                 strncpy(new_sw->data, data, sizeof(new_sw->data)-1);
2932         else
2933                 strncpy(new_sw->data, "", sizeof(new_sw->data)-1);
2934         new_sw->next      = NULL;
2935         new_sw->registrar = registrar;
2936
2937         /* ... try to lock this context ... */
2938         if (ast_pthread_mutex_lock(&con->lock)) {
2939                 free(new_sw);
2940                 errno = EBUSY;
2941                 return -1;
2942         }
2943
2944         /* ... go to last sw and check if context is already swd too... */
2945         i = con->alts;
2946         while (i) {
2947                 if (!strcasecmp(i->name, new_sw->name)) {
2948                         free(new_sw);
2949                         ast_pthread_mutex_unlock(&con->lock);
2950                         errno = EEXIST;
2951                         return -1;
2952                 }
2953                 il = i;
2954                 i = i->next;
2955         }
2956
2957         /* ... sw new context into context list, unlock, return */
2958         if (il)
2959                 il->next = new_sw;
2960         else
2961                 con->alts = new_sw;
2962         if (option_verbose > 2)
2963                 ast_verbose(VERBOSE_PREFIX_3 "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con)); 
2964         ast_pthread_mutex_unlock(&con->lock);
2965
2966         return 0;
2967 }
2968
2969 /*
2970  * EBUSY  - can't lock
2971  * ENODATA - there is not context existence
2972  */
2973 int ast_context_remove_ignorepat(char *context, char *ignorepat, char *registrar)
2974 {
2975         struct ast_context *c;
2976
2977         if (ast_lock_contexts()) {
2978                 errno = EBUSY;
2979                 return -1;
2980         }
2981
2982         c = ast_walk_contexts(NULL);
2983         while (c) {
2984                 if (!strcmp(ast_get_context_name(c), context)) {
2985                         int ret = ast_context_remove_ignorepat2(c, ignorepat, registrar);
2986                         ast_unlock_contexts();
2987                         return ret;
2988                 }
2989                 c = ast_walk_contexts(c);
2990         }
2991
2992         ast_unlock_contexts();
2993         errno = ENODATA;
2994         return -1;
2995 }
2996
2997 int ast_context_remove_ignorepat2(struct ast_context *con, char *ignorepat, char *registrar)
2998 {
2999         struct ast_ignorepat *ip, *ipl = NULL;
3000
3001         if (ast_pthread_mutex_lock(&con->lock)) {
3002                 errno = EBUSY;
3003                 return -1;
3004         }
3005
3006         ip = con->ignorepats;
3007         while (ip) {
3008                 if (!strcmp(ip->pattern, ignorepat) &&
3009                         (registrar == ip->registrar || !registrar)) {
3010                         if (ipl) {
3011                                 ipl->next = ip->next;
3012                                 free(ip);
3013                         } else {
3014                                 con->ignorepats = ip->next;
3015                                 free(ip);
3016                         }
3017                         ast_pthread_mutex_unlock(&con->lock);
3018                         return 0;
3019                 }
3020                 ipl = ip; ip = ip->next;
3021         }
3022
3023         ast_pthread_mutex_unlock(&con->lock);
3024         errno = EINVAL;
3025         return -1;
3026 }
3027
3028 /*
3029  * EBUSY - can't lock
3030  * ENODATA - there is no existence of context
3031  */
3032 int ast_context_add_ignorepat(char *con, char *value, char *registrar)
3033 {
3034         struct ast_context *c;
3035
3036         if (ast_lock_contexts()) {
3037                 errno = EBUSY;
3038                 return -1;
3039         }
3040
3041         c = ast_walk_contexts(NULL);
3042         while (c) {
3043                 if (!strcmp(ast_get_context_name(c), con)) {
3044                         int ret = ast_context_add_ignorepat2(c, value, registrar);
3045                         ast_unlock_contexts();
3046                         return ret;
3047                 } 
3048                 c = ast_walk_contexts(c);
3049         }
3050
3051         ast_unlock_contexts();
3052         errno = ENODATA;
3053         return -1;
3054 }
3055
3056 int ast_context_add_ignorepat2(struct ast_context *con, char *value, char *registrar)
3057 {
3058         struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL;
3059         ignorepat = malloc(sizeof(struct ast_ignorepat));
3060         if (!ignorepat) {
3061                 ast_log(LOG_WARNING, "Out of memory\n");
3062                 errno = ENOMEM;
3063                 return -1;
3064         }
3065         memset(ignorepat, 0, sizeof(struct ast_ignorepat));
3066         strncpy(ignorepat->pattern, value, sizeof(ignorepat->pattern)-1);
3067         ignorepat->next = NULL;
3068         ignorepat->registrar = registrar;
3069         ast_pthread_mutex_lock(&con->lock);
3070         ignorepatc = con->ignorepats;
3071         while(ignorepatc) {
3072                 ignorepatl = ignorepatc;
3073                 if (!strcasecmp(ignorepatc->pattern, value)) {
3074                         /* Already there */
3075                         pthread_mutex_unlock(&con->lock);
3076                         errno = EEXIST;
3077                         return -1;
3078                 }
3079                 ignorepatc = ignorepatc->next;
3080         }
3081         if (ignorepatl) 
3082                 ignorepatl->next = ignorepat;
3083         else
3084                 con->ignorepats = ignorepat;
3085         pthread_mutex_unlock(&con->lock);
3086         return 0;
3087         
3088 }
3089
3090 int ast_ignore_pattern(char *context, char *pattern)
3091 {
3092         struct ast_context *con;
3093         struct ast_ignorepat *pat;
3094         con = ast_context_find(context);
3095         if (con) {
3096                 pat = con->ignorepats;
3097                 while (pat) {
3098                         if (ast_extension_match(pat->pattern, pattern))
3099                                 return 1;
3100                         pat = pat->next;
3101                 }
3102         } 
3103         return 0;
3104 }
3105
3106 /*
3107  * EBUSY   - can't lock
3108  * ENODATA  - no existence of context
3109  *
3110  */
3111 int ast_add_extension(char *context, int replace, char *extension, int priority, char *callerid,
3112         char *application, void *data, void (*datad)(void *), char *registrar)
3113 {
3114         struct ast_context *c;
3115
3116         if (ast_lock_contexts()) {
3117                 errno = EBUSY;
3118                 return -1;
3119         }
3120
3121         c = ast_walk_contexts(NULL);
3122         while (c) {
3123                 if (!strcmp(context, ast_get_context_name(c))) {
3124                         int ret = ast_add_extension2(c, replace, extension, priority, callerid,
3125                                 application, data, datad, registrar);
3126                         ast_unlock_contexts();
3127                         return ret;
3128                 }
3129                 c = ast_walk_contexts(c);
3130         }
3131
3132         ast_unlock_contexts();
3133         errno = ENODATA;
3134         return -1;
3135 }
3136
3137 int ast_async_goto(struct ast_channel *chan, char *context, char *exten, int priority, int needlock)
3138 {
3139         int res = 0;
3140         if (needlock)
3141                 ast_pthread_mutex_lock(&chan->lock);
3142         if (chan->pbx) {
3143                 /* This channel is currently in the PBX */
3144                 if (context && strlen(context))
3145                         strncpy(chan->context, context, sizeof(chan->context) - 1);
3146                 if (exten && strlen(exten))
3147                         strncpy(chan->exten, exten, sizeof(chan->context) - 1);
3148                 if (priority)
3149                         chan->priority = priority - 1;
3150                 ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO);
3151                 if (needlock)
3152                         ast_pthread_mutex_unlock(&chan->lock);
3153         } else {
3154                 /* In order to do it when the channel doesn't really exist within
3155                    the PBX, we have to make a new channel, masquerade, and start the PBX
3156                    at the new location */
3157                 struct ast_channel *tmpchan;
3158                 struct ast_frame *f;
3159                 tmpchan = ast_channel_alloc(0);
3160                 if (tmpchan) {
3161                         snprintf(tmpchan->name, sizeof(tmpchan->name), "AsyncGoto/%s", chan->name);
3162                         ast_setstate(tmpchan, chan->_state);
3163                         /* Make formats okay */
3164                         tmpchan->readformat = chan->readformat;
3165                         tmpchan->writeformat = chan->writeformat;
3166                         /* Setup proper location */
3167                         if (context && strlen(context))
3168                                 strncpy(tmpchan->context, context, sizeof(tmpchan->context) - 1);
3169                         else
3170                                 strncpy(tmpchan->context, chan->context, sizeof(tmpchan->context) - 1);
3171                         if (exten && strlen(exten))
3172                                 strncpy(tmpchan->exten, exten, sizeof(tmpchan->exten) - 1);
3173                         else
3174                                 strncpy(tmpchan->exten, chan->exten, sizeof(tmpchan->exten) - 1);
3175                         if (priority)
3176                                 tmpchan->priority = priority;
3177                         else
3178                                 tmpchan->priority = chan->priority;
3179                         if (needlock)
3180                                 ast_pthread_mutex_unlock(&chan->lock);
3181                         
3182                         /* Masquerade into temp channel */
3183                         ast_channel_masquerade(tmpchan, chan);
3184                         
3185                         /* Make the masquerade happen by reading a frame from the tmp channel */
3186                         f = ast_read(tmpchan);
3187                         if (f)
3188                                 ast_frfree(f);
3189                         /* Start the PBX going on our stolen channel */
3190                         if (ast_pbx_start(tmpchan)) {
3191                                 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name);
3192                                 ast_hangup(tmpchan);
3193                                 res = -1;
3194                         }
3195                 } else {
3196                         res = -1;
3197                         if (needlock)
3198                                 ast_pthread_mutex_unlock(&chan->lock);
3199                 }
3200         }
3201         return res;
3202 }
3203
3204 int ast_async_goto_by_name(char *channame, char *context, char *exten, int priority)
3205 {
3206         struct ast_channel *chan;
3207         chan = ast_channel_walk(NULL);
3208         while(chan) {
3209                 if (!strcasecmp(channame, chan->name))
3210                         break;
3211                 chan = ast_channel_walk(chan);
3212         }
3213         if (chan)
3214                 return ast_async_goto(chan, context, exten, priority, 1);
3215         return -1;
3216 }
3217
3218 static void ext_strncpy(char *dst, char *src, int len)
3219 {
3220         int count=0;
3221         while(*src && (count < len - 1)) {
3222                 switch(*src) {
3223                 case ' ':
3224 //otherwise exten => [a-b],1,... doesn't work
3225 //              case '-':
3226                         /* Ignore */
3227                         break;
3228                 default:
3229                         *dst = *src;
3230                         dst++;
3231                 }
3232                 src++;
3233                 count++;
3234         }
3235         *dst = '\0';
3236 }
3237
3238 /*
3239  * EBUSY - can't lock
3240  * EEXIST - extension with the same priority exist and no replace is set
3241  *
3242  */
3243 int ast_add_extension2(struct ast_context *con,
3244                                           int replace, char *extension, int priority, char *callerid,
3245                                           char *application, void *data, void (*datad)(void *),
3246                                           char *registrar)
3247 {
3248
3249 #define LOG do {        if (option_debug) {\
3250                 if (tmp->matchcid) { \
3251                         ast_log(LOG_DEBUG, "Added extension '%s' priority %d (CID match '%s') to %s\n", tmp->exten, tmp->priority, tmp->cidmatch, con->name); \
3252                 } else { \
3253                         ast_log(LOG_DEBUG, "Added extension '%s' priority %d to %s\n", tmp->exten, tmp->priority, con->name); \
3254                 } \
3255         } else if (option_verbose > 2) { \
3256                 if (tmp->matchcid) { \
3257                         ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d (CID match '%s')to %s\n", tmp->exten, tmp->priority, tmp->cidmatch, con->name); \
3258                 } else {  \
3259                         ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d to %s\n", tmp->exten, tmp->priority, con->name); \
3260                 } \
3261         } } while(0)
3262
3263         /*
3264          * This is a fairly complex routine.  Different extensions are kept
3265          * in order by the extension number.  Then, extensions of different
3266          * priorities (same extension) are kept in a list, according to the
3267          * peer pointer.
3268          */
3269         struct ast_exten *tmp, *e, *el = NULL, *ep = NULL;
3270         int res;
3271         /* Be optimistic:  Build the extension structure first */
3272         tmp = malloc(sizeof(struct ast_exten));
3273         if (tmp) {
3274                 memset(tmp, 0, sizeof(struct ast_exten));
3275                 ext_strncpy(tmp->exten, extension, sizeof(tmp->exten));
3276                 tmp->priority = priority;
3277                 if (callerid) {
3278                         ext_strncpy(tmp->cidmatch, callerid, sizeof(tmp->cidmatch));
3279                         tmp->matchcid = 1;
3280                 } else {
3281                         strcpy(tmp->cidmatch, "");
3282                         tmp->matchcid = 0;
3283                 }
3284                 strncpy(tmp->app, application, sizeof(tmp->app)-1);
3285                 tmp->parent = con;
3286                 tmp->data = data;
3287                 tmp->datad = datad;
3288                 tmp->registrar = registrar;
3289                 tmp->peer = NULL;
3290                 tmp->next =  NULL;
3291         } else {
3292                 ast_log(LOG_WARNING, "Out of memory\n");
3293                 errno = ENOMEM;
3294                 return -1;
3295         }
3296         if (ast_pthread_mutex_lock(&con->lock)) {
3297                 free(tmp);
3298                 /* And properly destroy the data */
3299                 datad(data);
3300                 ast_log(LOG_WARNING, "Failed to lock context '%s'\n", con->name);
3301                 errno = EBUSY;
3302                 return -1;
3303         }
3304         e = con->root;
3305         while(e) {
3306                 res= strcasecmp(e->exten, extension);
3307                 if (!res) {
3308                         if (!e->matchcid && !tmp->matchcid)
3309                                 res = 0;
3310                         else if (tmp->matchcid && !e->matchcid)
3311                                 res = 1;
3312                         else if (e->matchcid && !tmp->matchcid)
3313                                 res = -1;
3314                         else
3315                                 res = strcasecmp(e->cidmatch, tmp->cidmatch);
3316                 }
3317                 if (res == 0) {
3318                         /* We have an exact match, now we find where we are
3319                            and be sure there's no duplicates */
3320                         while(e) {
3321                                 if (e->priority == tmp->priority) {
3322                                         /* Can't have something exactly the same.  Is this a
3323                                            replacement?  If so, replace, otherwise, bonk. */
3324                                         if (replace) {
3325                                                 if (ep) {
3326                                                         /* We're in the peer list, insert ourselves */
3327                                                         ep->peer = tmp;
3328                                                         tmp->peer = e->peer;
3329                                                 } else if (el) {
3330                                                         /* We're the first extension. Take over e's functions */
3331                                                         el->next = tmp;
3332                                                         tmp->next = e->next;
3333                                                         tmp->peer = e->peer;
3334                                                 } else {
3335                                                         /* We're the very first extension.  */
3336                                                         con->root = tmp;
3337                                                         tmp->next = e->next;
3338                                                         tmp->peer = e->peer;
3339                                                 }
3340                                                 /* Destroy the old one */
3341                                                 e->datad(e->data);
3342                                                 free(e);
3343                                                 ast_pthread_mutex_unlock(&con->lock);
3344                                                 /* And immediately return success. */
3345                                                 LOG;
3346                                                 return 0;
3347                                         } else {
3348                                                 ast_log(LOG_WARNING, "Unable to register extension '%s', priority %d in '%s', already in use\n", tmp->exten, tmp->priority, con->name);
3349                                                 tmp->datad(tmp->data);
3350                                                 free(tmp);
3351                                                 ast_pthread_mutex_unlock(&con->lock);
3352                                                 errno = EEXIST;
3353                                                 return -1;
3354                                         }
3355                                 } else if (e->priority > tmp->priority) {
3356                                         /* Slip ourselves in just before e */
3357                                         if (ep) {
3358                                                 /* Easy enough, we're just in the peer list */
3359                                                 ep->peer = tmp;
3360                                                 tmp->peer = e;
3361                                         } else if (el) {
3362                                                 /* We're the first extension in this peer list */
3363                                                 el->next = tmp;
3364                                                 tmp->next = e->next;
3365                                                 e->next = NULL;
3366                                                 tmp->peer = e;
3367                                         } else {
3368                                                 /* We're the very first extension altogether */
3369                                                 tmp->next = con->root;
3370                                                 /* Con->root must always exist or we couldn't get here */
3371                                                 tmp->peer = con->root->peer;
3372                                                 con->root = tmp;
3373                                         }
3374                                         ast_pthread_mutex_unlock(&con->lock);
3375                                         /* And immediately return success. */
3376                                         LOG;
3377                                         return 0;
3378                                 }
3379                                 ep = e;
3380                                 e = e->peer;
3381                         }
3382                         /* If we make it here, then it's time for us to go at the very end.
3383                            ep *must* be defined or we couldn't have gotten here. */
3384                         ep->peer = tmp;
3385                         ast_pthread_mutex_unlock(&con->lock);
3386                         /* And immediately return success. */
3387                         LOG;
3388                         return 0;
3389                                 
3390                 } else if (res > 0) {
3391                         /* Insert ourselves just before 'e'.  We're the first extension of
3392                            this kind */
3393                         tmp->next = e;
3394                         if (el) {
3395                                 /* We're in the list somewhere */
3396                                 el->next = tmp;
3397                         } else {
3398                                 /* We're at the top of the list */
3399                                 con->root = tmp;
3400                         }
3401                         ast_pthread_mutex_unlock(&con->lock);
3402                         /* And immediately return success. */
3403                         LOG;
3404                         return 0;
3405                 }                       
3406                         
3407                 el = e;
3408                 e = e->next;
3409         }
3410         /* If we fall all the way through to here, then we need to be on the end. */
3411         if (el)
3412                 el->next = tmp;
3413         else
3414                 con->root = tmp;
3415         ast_pthread_mutex_unlock(&con->lock);
3416         LOG;
3417         return 0;       
3418 }
3419
3420 struct async_stat {
3421         pthread_t p;
3422         struct ast_channel *chan;
3423         char context[AST_MAX_EXTENSION];
3424         char exten[AST_MAX_EXTENSION];
3425         int priority;
3426         int timeout;
3427         char app[AST_MAX_EXTENSION];
3428         char appdata[1024];
3429 };
3430
3431 static void *async_wait(void *data) 
3432 {
3433         struct async_stat *as = data;
3434         struct ast_channel *chan = as->chan;
3435         int timeout = as->timeout;
3436         int res;
3437         struct ast_frame *f;
3438         struct ast_app *app;
3439         
3440         while(timeout && (chan->_state != AST_STATE_UP)) {
3441                 res = ast_waitfor(chan, timeout);
3442                 if (res < 1) 
3443                         break;
3444                 if (timeout > -1)
3445                         timeout = res;
3446                 f = ast_read(chan);
3447                 if (!f)
3448                         break;
3449                 if (f->frametype == AST_FRAME_CONTROL) {
3450                         if ((f->subclass == AST_CONTROL_BUSY)  ||
3451                                 (f->subclass == AST_CONTROL_CONGESTION) )
3452                                         break;
3453                 }
3454                 ast_frfree(f);
3455         }
3456         if (chan->_state == AST_STATE_UP) {
3457                 if (strlen(as->app)) {
3458                         app = pbx_findapp(as->app);
3459                         if (app) {
3460                                 if (option_verbose > 2)
3461                                         ast_verbose(VERBOSE_PREFIX_3 "Lauching %s(%s) on %s\n", as->app, as->appdata, chan->name);
3462                                 pbx_exec(chan, app, as->appdata, 1);
3463                         } else
3464                                 ast_log(LOG_WARNING, "No such application '%s'\n", as->app);
3465                 } else {
3466                         if (strlen(as->context))
3467                                 strncpy(chan->context, as->context, sizeof(chan->context) - 1);
3468                         if (strlen(as->exten))
3469                                 strncpy(chan->exten, as->exten, sizeof(chan->exten) - 1);
3470                         if (as->priority > 0)
3471                                 chan->priority = as->priority;
3472                         /* Run the PBX */
3473                         if (ast_pbx_run(chan)) {
3474                                 ast_log(LOG_WARNING, "Failed to start PBX on %s\n", chan->name);
3475                         } else {
3476                                 /* PBX will have taken care of this */
3477                                 chan = NULL;
3478                         }
3479                 }
3480                         
3481         }
3482         free(as);
3483         if (chan)
3484                 ast_hangup(chan);
3485         return NULL;
3486 }
3487
3488 int ast_pbx_outgoing_exten(char *type, int format, void *data, int timeout, char *context, char *exten, int priority, int *reason, int sync, char *callerid, char *variable )
3489 {
3490         struct ast_channel *chan;
3491         struct async_stat *as;
3492         int res = -1;
3493         char *var, *tmp;
3494         if (sync) {
3495                 chan = ast_request_and_dial(type, format, data, timeout, reason, callerid);
3496                 if (chan) {
3497                         /* JDG chanvar */
3498                         tmp = variable;
3499                         /* FIXME replace this call with strsep  NOT*/
3500                         while( (var = strtok_r(NULL, "|", &tmp)) ) {
3501                                 pbx_builtin_setvar( chan, var );
3502                         } /* /JDG */
3503                         if (chan->_state == AST_STATE_UP) {
3504                                 res = 0;
3505                                 if (option_verbose > 3)
3506                                         ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", chan->name);
3507                                 if (context && strlen(context))
3508                                         strncpy(chan->context, context, sizeof(chan->context) - 1);
3509                                 if (exten && strlen(exten))
3510                                         strncpy(chan->exten, exten, sizeof(chan->exten) - 1);
3511                                 if (callerid && strlen(callerid))
3512                                         strncpy(chan->callerid, callerid, sizeof(chan->callerid) - 1);
3513                                 if (priority > 0)
3514                                         chan->priority = priority;
3515                                 if (sync > 1) {
3516                                         if (ast_pbx_run(chan)) {
3517                                                 ast_log(LOG_WARNING, "Unable to run PBX on %s\n", chan->name);
3518                                                 ast_hangup(chan);
3519                                                 res = -1;
3520                                         }
3521                                 } else {
3522                                         if (ast_pbx_start(chan)) {
3523                                                 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", chan->name);
3524                                                 ast_hangup(chan);
3525                                                 res = -1;
3526                                         } 
3527                                 }
3528                         } else {
3529                                 if (option_verbose > 3)
3530                                         ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", chan->name);
3531                                 ast_hangup(chan);
3532                         }
3533                 }
3534         } else {
3535                 as = malloc(sizeof(struct async_stat));
3536                 if (!as)
3537                         return -1;
3538                 memset(as, 0, sizeof(struct async_stat));
3539                 chan = ast_request_and_dial(type, format, data, 0, reason, callerid);
3540                 if (!chan) {
3541                         free(as);
3542                         return -1;
3543                 }
3544                 as->chan = chan;
3545                 strncpy(as->context, context, sizeof(as->context) - 1);
3546                 strncpy(as->exten,  exten, sizeof(as->exten) - 1);
3547                 as->priority = priority;
3548                 as->timeout = timeout;
3549                 if (pthread_create(&as->p, NULL, async_wait, as)) {
3550                         ast_log(LOG_WARNING, "Failed to start async wait\n");
3551