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