Fri Feb 14 07:00:01 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(struct ast_channel *c, struct ast_exten *e) {
678         char *cp1,*cp3,*cp4,*cp5;
679         void *cp2;
680         char c1,c2;
681         int m,mve,origlen,quoted,dolsign,docopy,offset;
682         struct ast_var_t *variables;
683         struct varshead *headp;
684         char pri[80];
685         char *name, *num; /* for callerid name + num variables */
686         
687         headp=&c->varshead;
688         origlen=strlen(e->data)+1;
689         cp2=malloc(origlen);
690         memset(cp2,0,origlen);
691         
692         if ((strchr(e->data,'$')==NULL) && (strchr(e->data,'[')==NULL)) {
693                 strncpy(cp2,e->data,strlen(e->data));
694                 return(cp2);
695                 /* No variables or expressions in e->data, so why scan it? */
696         }
697         
698         cp4=NULL;
699         cp1=e->data;
700         quoted=0;
701         dolsign=0;
702         docopy=1;
703         
704         /* First stage, variable substitution */
705         
706         do {
707                 c1=*cp1;
708                 mve=0;
709                 switch (c1) {
710                         case '\\' :
711                                 dolsign=0;
712                                 if (quoted==1) {
713                                         quoted=0;
714                                         docopy=1;
715                                 } else {
716                                         quoted=1;
717                                         docopy=0;
718                                 }
719                                 break;
720                         case '$' :
721                                 if (quoted==1) {
722                                         quoted=0;
723                                         docopy=1;
724                                         dolsign=0;
725                                 } else {
726                                         docopy=0;
727                                         dolsign=1;
728                                 }
729                                 break;
730                         case '{' : 
731                                 if (quoted==1) {
732                                         quoted=0;
733                                         dolsign=0;
734                                         docopy=1;
735                                         break;
736                                 }
737                                 if (dolsign==0) {
738                                         docopy=1;
739                                         break;
740                                 }
741                                 docopy=0;
742                                 dolsign=0;
743                                 m=0;
744                                 cp1++;
745                                 while (((c2=*(cp1+m))!='}') && (c2!='\0')) {
746                                         m++;
747                                 }
748                                 mve=1;
749                                 cp3=malloc(m+2);
750                                 strncpy(cp3,cp1,m);
751                                 cp3[m]='\0';
752                                 cp1+=m;
753                                 /* Now we have the variable name on cp3 */
754                                 if (!strcmp(cp3, "CALLERIDNUM")) {
755                                                 char cid[256] = "";
756                                                 if (c->callerid)
757                                                         strncpy(cid, c->callerid, sizeof(cid) - 1);
758                                                 ast_callerid_parse(cid, &name, &num);
759                                                 if (num) {
760                                                         ast_shrink_phone_number(num);
761                                                         cp4 = num;
762                                                 } else
763                                                         cp4 = "";
764                                                 break;
765                                         } else if (!strcmp(cp3, "CALLERIDNAME")) {
766                                                 char cid[256] = "";
767                                                 if (c->callerid)
768                                                         strncpy(cid, c->callerid, sizeof(cid) - 1);
769                                                 ast_callerid_parse(cid, &name, &num);
770                                                 if (name)
771                                                         cp4 = name;
772                                                 else
773                                                         cp4 = "";
774                                                 break;
775                                         } else if (!strcmp(cp3, "CALLERID")) {
776                                                 cp4 = c->callerid;
777                                                 if (!cp4)
778                                                         cp4 = "";
779                                                 break;
780                                         } else if (!strcmp(cp3, "EXTEN")) {
781                                                 cp4 = c->exten;
782                                                 break;
783                                         } else if (!strncmp(cp3, "EXTEN-", strlen("EXTEN-")) && 
784                                                 (sscanf(cp3 + strlen("EXTEN-"), "%d", &offset) == 1)) {
785                                                 if (offset < 0)
786                                                         offset=0;
787                                                 if (offset > strlen(c->exten))
788                                                         offset = strlen(c->exten);
789                                                 cp4 = c->exten + offset;
790                                         } else if (!strcmp(cp3, "RDNIS")) {
791                                                 cp4 = c->rdnis;
792                                                 if (!cp4)
793                                                         cp4 = "";
794                                                 break;
795                                         } else if (!strcmp(cp3, "CONTEXT")) {
796                                                 cp4 = c->context;
797                                                 break;
798                                         } else if (!strcmp(cp3, "PRIORITY")) {
799                                                 snprintf(pri, sizeof(pri), "%d", c->priority);
800                                                 cp4 = pri;
801                                                 break;
802                                         } else {
803                                         AST_LIST_TRAVERSE(headp,variables,entries) {
804 //                                              ast_log(LOG_WARNING,"Comparing variable '%s' with '%s'\n",cp3,ast_var_name(variables));
805                                                         if (strncasecmp(ast_var_name(variables),cp3,m)==0) {
806                                                                 cp4=ast_var_value(variables);
807                                                                 break;
808                                                         }
809                                                 }
810                                                 if (!cp4) {
811                                                         /* Try globals */
812                                                 AST_LIST_TRAVERSE(&globals,variables,entries) {
813         //                                              ast_log(LOG_WARNING,"Comparing variable '%s' with '%s'\n",cp3,ast_var_name(variables));
814                                                                 if (strncasecmp(ast_var_name(variables),cp3,m)==0) {
815                                                                         cp4=ast_var_value(variables);
816                                                                         break;
817                                                                 }
818                                                         }
819                                                 }
820                                         }
821                                 free(cp3);
822                                 break;
823                         default :
824                                 if (dolsign==1) {
825                                         strncat((char *)cp2,"$",1);
826                                 } 
827                                 if (quoted==1) {
828                                         quoted=0;
829                                 }
830                                 mve=0;
831                                 dolsign=0;
832                                 docopy=1;
833                                 break;
834                 }
835                 if (cp1!='\0') {
836                         if (mve==0) {
837                                 if (docopy==1) {
838                                         strncat((char *)cp2,&c1,1);
839                                 }
840                         } else {
841                                 if (cp4!=NULL) {
842                                         cp2=realloc(cp2,origlen+strlen(cp4)+1);
843                                         strncat((char *)cp2,cp4,strlen(cp4));
844                                         origlen += strlen(cp4);
845                                 } else {
846                                         ast_log(LOG_WARNING,"mve!=0 and cp4=NULL, something gone astray\n");
847                                 }
848                         }
849                 }
850                       cp4 = NULL;
851         } while (*cp1++!='\0');
852         
853         /* Second stage, expression evaluation */
854                 
855         if ((strstr(cp2,"$[")==NULL)) {
856                 /* No expressions in cp2, return it */
857                 return(cp2);
858         }
859         /* else, do expression evaluation */
860         
861         dolsign=0;
862         docopy=1;
863         origlen=strlen(cp2)+1;
864         
865         cp5=malloc(origlen);
866         memset(cp5,0,origlen);
867         cp4=NULL;
868         cp1=cp2;
869         quoted=0;
870         
871         do {
872                 c1=*cp1;
873                 mve=0;
874                 switch (c1) {
875                         case '$' : 
876                                 dolsign=1;
877                                 docopy=0;
878                                 break;
879                         case '[' :
880                                 if (dolsign==0) {
881                                         docopy=1;
882                                         dolsign=0;
883                                         break;
884                                 }
885                                 dolsign=0;
886                                 docopy=0;
887                                 m=0;
888                                 mve=1;
889                                 cp1++;
890                                 
891                                 while (((c2=*(cp1+m))!=']') && (c2!='\0')) {
892                                         m++;
893                                 }
894                                 cp3=malloc(m+2);
895                                 strncpy(cp3,cp1,m);
896                                 cp3[m]='\0';
897                                 cp1+=m;
898                                 /* Now we have the expression to evaluate on cp3 */
899                                 cp4=ast_expr(cp3);
900                                 free(cp3);
901                                 break;
902                         default :
903                                 if (dolsign==1) {
904                                         strncat((char *)cp5,"$",1);
905                                 }
906                                 dolsign=0;
907                                 docopy=1;
908                                 mve=0;
909                                 break;
910                 }
911                 if (cp1!='\0') {
912                         if (mve==0) {
913                                 if (docopy==1) {
914                                         strncat((char *)cp5,&c1,1);
915                                 }
916                         } else {
917                                 if (cp4!=NULL) {
918                                         cp5=realloc(cp5,origlen+strlen(cp4)+1);
919                                         strncat((char *)cp5,cp4,strlen(cp4));
920                                         free(cp4);
921                                 } else {
922                                         ast_log(LOG_WARNING,"mve!=0 and cp4=NULL, something gone astray\n");
923                                 }
924                         }
925                 }
926                         
927         } while (*cp1++!='\0');
928         free(cp2);
929         return(cp5);
930 }
931                                 
932                         
933                                                                 
934
935 static int pbx_extension_helper(struct ast_channel *c, char *context, char *exten, int priority, char *callerid, int action) 
936 {
937         struct ast_exten *e;
938         struct ast_app *app;
939         struct ast_switch *sw;
940         char *data;
941         char *newdata;
942         int newstack = 0;
943         int res;
944         int status = 0;
945         char *incstack[AST_PBX_MAX_STACK];
946         int stacklen = 0;
947         char tmp[80];
948         char tmp2[80];
949         char tmp3[256];
950         if (ast_pthread_mutex_lock(&conlock)) {
951                 ast_log(LOG_WARNING, "Unable to obtain lock\n");
952                 if ((action == HELPER_EXISTS) || (action == HELPER_CANMATCH) || (action == HELPER_MATCHMORE))
953                         return 0;
954                 else
955                         return -1;
956         }
957         e = pbx_find_extension(c, context, exten, priority, callerid, action, incstack, &stacklen, &status, &sw, &data);
958         if (e) {
959                 switch(action) {
960                 case HELPER_CANMATCH:
961                         pthread_mutex_unlock(&conlock);
962                         return -1;
963                 case HELPER_EXISTS:
964                         pthread_mutex_unlock(&conlock);
965                         return -1;
966                 case HELPER_MATCHMORE:
967                         pthread_mutex_unlock(&conlock);
968                         return -1;
969                 case HELPER_SPAWN:
970                         newstack++;
971                         /* Fall through */
972                 case HELPER_EXEC:
973                         app = pbx_findapp(e->app);
974                         pthread_mutex_unlock(&conlock);
975                         if (app) {
976                                 strncpy(c->context, context, sizeof(c->context-1));
977                                 strncpy(c->exten, exten, sizeof(c->exten)-1);
978                                 c->priority = priority;
979                                 newdata=pbx_substitute_variables(c,e);
980                                 if (option_debug)
981                                                 ast_log(LOG_DEBUG, "Launching '%s'\n", app->name);
982                                 else if (option_verbose > 2)
983                                                 ast_verbose( VERBOSE_PREFIX_3 "Executing %s(\"%s\", \"%s\") %s\n", 
984                                                                 term_color(tmp, app->name, COLOR_BRCYAN, 0, sizeof(tmp)),
985                                                                 term_color(tmp2, c->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)),
986                                                                 term_color(tmp3, (newdata ? (char *)newdata : NULL), COLOR_BRMAGENTA, 0, sizeof(tmp3)),
987                                                                 (newstack ? "in new stack" : "in same stack"));
988                                 res = pbx_exec(c, app, newdata, newstack);
989                                 free(newdata);
990                                 return res;
991                         } else {
992                                 ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority);
993                                 return -1;
994                         }
995                 default:
996                         ast_log(LOG_WARNING, "Huh (%d)?\n", action);                    return -1;
997                 }
998         } else if (sw) {
999                 switch(action) {
1000                 case HELPER_CANMATCH:
1001                         pthread_mutex_unlock(&conlock);
1002                         return -1;
1003                 case HELPER_EXISTS:
1004                         pthread_mutex_unlock(&conlock);
1005                         return -1;
1006                 case HELPER_MATCHMORE:
1007                         pthread_mutex_unlock(&conlock);
1008                         return -1;
1009                 case HELPER_SPAWN:
1010                         newstack++;
1011                         /* Fall through */
1012                 case HELPER_EXEC:
1013                         pthread_mutex_unlock(&conlock);
1014                         if (sw->exec)
1015                                 res = sw->exec(c, context, exten, priority, callerid, newstack, data);
1016                         else {
1017                                 ast_log(LOG_WARNING, "No execution engine for switch %s\n", sw->name);
1018                                 res = -1;
1019                         }
1020                         return res;
1021                 default:
1022                         ast_log(LOG_WARNING, "Huh (%d)?\n", action);
1023                         return -1;
1024                 }
1025         } else {
1026                 pthread_mutex_unlock(&conlock);
1027                 switch(status) {
1028                 case STATUS_NO_CONTEXT:
1029                         if ((action != HELPER_EXISTS) && (action != HELPER_MATCHMORE))
1030                                 ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", context);
1031                         break;
1032                 case STATUS_NO_EXTENSION:
1033                         if ((action != HELPER_EXISTS) && (action !=  HELPER_CANMATCH) && (action != HELPER_MATCHMORE))
1034                                 ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, context);
1035                         break;
1036                 case STATUS_NO_PRIORITY:
1037                         if ((action != HELPER_EXISTS) && (action !=  HELPER_CANMATCH) && (action != HELPER_MATCHMORE))
1038                                 ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, context);
1039                         break;
1040                 default:
1041                         ast_log(LOG_DEBUG, "Shouldn't happen!\n");
1042                 }
1043                 if ((action != HELPER_EXISTS) && (action != HELPER_CANMATCH) && (action != HELPER_MATCHMORE))
1044                         return -1;
1045                 else
1046                         return 0;
1047         }
1048
1049 }
1050
1051 int ast_exists_extension(struct ast_channel *c, char *context, char *exten, int priority, char *callerid) 
1052 {
1053         return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_EXISTS);
1054 }
1055
1056 int ast_canmatch_extension(struct ast_channel *c, char *context, char *exten, int priority, char *callerid)
1057 {
1058         return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_CANMATCH);
1059 }
1060
1061 int ast_matchmore_extension(struct ast_channel *c, char *context, char *exten, int priority, char *callerid)
1062 {
1063         return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_MATCHMORE);
1064 }
1065
1066 int ast_spawn_extension(struct ast_channel *c, char *context, char *exten, int priority, char *callerid) 
1067 {
1068         return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_SPAWN);
1069 }
1070
1071 int ast_pbx_run(struct ast_channel *c)
1072 {
1073         int firstpass = 1;
1074         char digit;
1075         char exten[256];
1076         int pos;
1077         int waittime;
1078         int res=0;
1079
1080         /* A little initial setup here */
1081         if (c->pbx)
1082                 ast_log(LOG_WARNING, "%s already has PBX structure??\n", c->name);
1083         c->pbx = malloc(sizeof(struct ast_pbx));
1084         if (!c->pbx) {
1085                 ast_log(LOG_WARNING, "Out of memory\n");
1086                 return -1;
1087         }
1088         if (c->amaflags) {
1089                 if (c->cdr) {
1090                         ast_log(LOG_WARNING, "%s already has a call record??\n", c->name);
1091                 } else {
1092                         c->cdr = ast_cdr_alloc();
1093                         if (!c->cdr) {
1094                                 ast_log(LOG_WARNING, "Unable to create Call Detail Record\n");
1095                                 free(c->pbx);
1096                                 return -1;
1097                         }
1098                         ast_cdr_init(c->cdr, c);
1099                 }
1100         }
1101         memset(c->pbx, 0, sizeof(struct ast_pbx));
1102         /* Set reasonable defaults */
1103         c->pbx->rtimeout = 10;
1104         c->pbx->dtimeout = 5;
1105
1106         if (option_debug)
1107                 ast_log(LOG_DEBUG, "PBX_THREAD(%s)\n", c->name);
1108         else if (option_verbose > 1) {
1109                 if (c->callerid)
1110                         ast_verbose( VERBOSE_PREFIX_2 "Accepting call on '%s' (%s)\n", c->name, c->callerid);
1111                 else
1112                         ast_verbose( VERBOSE_PREFIX_2 "Accepting call on '%s'\n", c->name);
1113         }
1114                 
1115         /* Start by trying whatever the channel is set to */
1116         if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) {
1117                 /* JK02: If not successfull fall back to 's' */
1118                 strncpy(c->exten, "s", sizeof(c->exten)-1);
1119                 if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) {
1120                         /* JK02: And finally back to default if everything else failed */
1121                         strncpy(c->context, "default", sizeof(c->context)-1);
1122                 }
1123                 c->priority = 1;
1124         }
1125         if (c->cdr)
1126                 ast_cdr_start(c->cdr);
1127         for(;;) {
1128                 pos = 0;
1129                 digit = 0;
1130                 while(ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) {
1131                         memset(exten, 0, sizeof(exten));
1132                         manager_event(EVENT_FLAG_CALL, "Newexten", 
1133                                 "Channel: %s\r\n"
1134                                 "Context: %s\r\n"
1135                                 "Extension: %s\r\n"
1136                                 "Priority: %d\r\n",
1137                                 c->name, c->context, c->exten, c->priority);                    
1138                         if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->callerid))) {
1139                                 /* Something bad happened, or a hangup has been requested. */
1140                                 if (((res >= '0') && (res <= '9')) || ((res >= 'A') && (res <= 'F'))) {
1141                                         ast_log(LOG_DEBUG, "Oooh, got something to jump out with ('%c')!\n", res);
1142                                         exten[pos++] = digit = res;
1143                                         break;
1144                                 }
1145                                 switch(res) {
1146                                 case AST_PBX_KEEPALIVE:
1147                                         if (option_debug)
1148                                                 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
1149                                         else if (option_verbose > 1)
1150                                                 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
1151                                         goto out;
1152                                         break;
1153                                 default:
1154                                         if (option_debug)
1155                                                 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
1156                                         else if (option_verbose > 1)
1157                                                 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
1158                                         if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
1159                                                 c->_softhangup =0;
1160                                                 break;
1161                                         }
1162                                         goto out;
1163                                 }
1164                         }
1165                         if (c->_softhangup) {
1166                                 ast_log(LOG_DEBUG, "Extension %s, priority %d returned normally even though call was hung up\n",
1167                                         c->exten, c->priority);
1168                                 goto out;
1169                         }
1170                         firstpass = 0;
1171                         c->priority++;
1172                 }
1173                 if (!ast_exists_extension(c, c->context, c->exten, 1, c->callerid)) {
1174                         /* It's not a valid extension anymore */
1175                         if (ast_exists_extension(c, c->context, "i", 1, c->callerid)) {
1176                                 if (option_verbose > 2)
1177                                         ast_verbose(VERBOSE_PREFIX_3 "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, c->name);
1178                                 strncpy(c->exten, "i", sizeof(c->exten)-1);
1179                                 c->priority = 1;
1180                         } else {
1181                                 ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n",
1182                                         c->name, c->exten, c->context);
1183                                 goto out;
1184                         }
1185                 } else {
1186                         /* Done, wait for an extension */
1187                         if (digit)
1188                                 waittime = c->pbx->dtimeout;
1189                         else
1190                                 waittime = c->pbx->rtimeout;
1191                         while (ast_matchmore_extension(c, c->context, exten, 1, c->callerid)) {
1192                                 /* As long as we're willing to wait, and as long as it's not defined, 
1193                                    keep reading digits until we can't possibly get a right answer anymore.  */
1194                                 digit = ast_waitfordigit(c, waittime * 1000);
1195                                 if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
1196                                         c->_softhangup = 0;
1197                                 } else {
1198                                         if (!digit)
1199                                                 /* No entry */
1200                                                 break;
1201                                         if (digit < 0)
1202                                                 /* Error, maybe a  hangup */
1203                                                 goto out;
1204                                         exten[pos++] = digit;
1205                                         waittime = c->pbx->dtimeout;
1206                                 }
1207                         }
1208                         if (ast_exists_extension(c, c->context, exten, 1, c->callerid)) {
1209                                 /* Prepare the next cycle */
1210                                 strncpy(c->exten, exten, sizeof(c->exten)-1);
1211                                 c->priority = 1;
1212                         } else {
1213                                 /* No such extension */
1214                                 if (strlen(exten)) {
1215                                         /* An invalid extension */
1216                                         if (ast_exists_extension(c, c->context, "i", 1, c->callerid)) {
1217                                                 if (option_verbose > 2)
1218                                                         ast_verbose( VERBOSE_PREFIX_3 "Invalid extension '%s' in context '%s' on %s\n", exten, c->context, c->name);
1219                                                 strncpy(c->exten, "i", sizeof(c->exten)-1);
1220                                                 c->priority = 1;
1221                                         } else {
1222                                                 ast_log(LOG_WARNING, "Invalid extension, but no rule 'i' in context '%s'\n", c->context);
1223                                                 goto out;
1224                                         }
1225                                 } else {
1226                                         /* A simple timeout */
1227                                         if (ast_exists_extension(c, c->context, "t", 1, c->callerid)) {
1228                                                 if (option_verbose > 2)
1229                                                         ast_verbose( VERBOSE_PREFIX_3 "Timeout on %s\n", c->name);
1230                                                 strncpy(c->exten, "t", sizeof(c->exten)-1);
1231                                                 c->priority = 1;
1232                                         } else {
1233                                                 ast_log(LOG_WARNING, "Timeout, but no rule 't' in context '%s'\n", c->context);
1234                                                 goto out;
1235                                         }
1236                                 }       
1237                         }
1238                 }
1239         }
1240         if (firstpass) 
1241                 ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name);
1242 out:
1243         if (ast_exists_extension(c, c->context, "h", 1, c->callerid)) {
1244                 strcpy(c->exten, "h");
1245                 c->priority = 1;
1246                 while(ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) {
1247                         if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->callerid))) {
1248                                 /* Something bad happened, or a hangup has been requested. */
1249                                 if (option_debug)
1250                                         ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
1251                                 else if (option_verbose > 1)
1252                                         ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
1253                                 break;
1254                         }
1255                         c->priority++;
1256                 }
1257         }
1258
1259         pbx_destroy(c->pbx);
1260         c->pbx = NULL;
1261         if (res != AST_PBX_KEEPALIVE)
1262                 ast_hangup(c);
1263         return 0;
1264 }
1265
1266 static void *pbx_thread(void *data)
1267 {
1268         /* Oh joyeous kernel, we're a new thread, with nothing to do but
1269            answer this channel and get it going.  The setjmp stuff is fairly
1270            confusing, but necessary to get smooth transitions between
1271            the execution of different applications (without the use of
1272            additional threads) */
1273         struct ast_channel *c = data;
1274         ast_pbx_run(c);
1275         pthread_exit(NULL);
1276         return NULL;
1277 }
1278
1279 int ast_pbx_start(struct ast_channel *c)
1280 {
1281         pthread_t t;
1282         pthread_attr_t attr;
1283         if (!c) {
1284                 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
1285                 return -1;
1286         }
1287            
1288         /* Start a new thread, and get something handling this channel. */
1289         pthread_attr_init(&attr);
1290         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1291         if (pthread_create(&t, &attr, pbx_thread, c)) {
1292                 ast_log(LOG_WARNING, "Failed to create new channel thread\n");
1293                 return -1;
1294         }
1295         return 0;
1296 }
1297
1298 /*
1299  * This function locks contexts list by &conlist, search for the rigt context
1300  * structure, leave context list locked and call ast_context_remove_include2
1301  * which removes include, unlock contexts list and return ...
1302  */
1303 int ast_context_remove_include(char *context, char *include, char *registrar)
1304 {
1305         struct ast_context *c;
1306
1307         if (ast_lock_contexts()) return -1;
1308
1309         /* walk contexts and search for the right one ...*/
1310         c = ast_walk_contexts(NULL);
1311         while (c) {
1312                 /* we found one ... */
1313                 if (!strcmp(ast_get_context_name(c), context)) {
1314                         int ret;
1315                         /* remove include from this context ... */      
1316                         ret = ast_context_remove_include2(c, include, registrar);
1317
1318                         ast_unlock_contexts();
1319
1320                         /* ... return results */
1321                         return ret;
1322                 }
1323                 c = ast_walk_contexts(c);
1324         }
1325
1326         /* we can't find the right one context */
1327         ast_unlock_contexts();
1328         return -1;
1329 }
1330
1331 /*
1332  * When we call this function, &conlock lock must be locked, because when
1333  * we giving *con argument, some process can remove/change this context
1334  * and after that there can be segfault.
1335  *
1336  * This function locks given context, removes include, unlock context and
1337  * return.
1338  */
1339 int ast_context_remove_include2(struct ast_context *con, char *include, char *registrar)
1340 {
1341         struct ast_include *i, *pi = NULL;
1342
1343         if (ast_pthread_mutex_lock(&con->lock)) return -1;
1344
1345         /* walk includes */
1346         i = con->includes;
1347         while (i) {
1348                 /* find our include */
1349                 if (!strcmp(i->name, include) && 
1350                         (!strcmp(i->registrar, registrar) || !registrar)) {
1351                         /* remove from list */
1352                         if (pi)
1353                                 pi->next = i->next;
1354                         else
1355                                 con->includes = i->next;
1356                         /* free include and return */
1357                         free(i);
1358                         ast_pthread_mutex_unlock(&con->lock);
1359                         return 0;
1360                 }
1361                 pi = i;
1362                 i = i->next;
1363         }
1364
1365         /* we can't find the right include */
1366         ast_pthread_mutex_unlock(&con->lock);
1367         return -1;
1368 }
1369
1370 /*
1371  * This function locks contexts list by &conlist, search for the rigt context
1372  * structure, leave context list locked and call ast_context_remove_switch2
1373  * which removes switch, unlock contexts list and return ...
1374  */
1375 int ast_context_remove_switch(char *context, char *sw, char *data, char *registrar)
1376 {
1377         struct ast_context *c;
1378
1379         if (ast_lock_contexts()) return -1;
1380
1381         /* walk contexts and search for the right one ...*/
1382         c = ast_walk_contexts(NULL);
1383         while (c) {
1384                 /* we found one ... */
1385                 if (!strcmp(ast_get_context_name(c), context)) {
1386                         int ret;
1387                         /* remove switch from this context ... */       
1388                         ret = ast_context_remove_switch2(c, sw, data, registrar);
1389
1390                         ast_unlock_contexts();
1391
1392                         /* ... return results */
1393                         return ret;
1394                 }
1395                 c = ast_walk_contexts(c);
1396         }
1397
1398         /* we can't find the right one context */
1399         ast_unlock_contexts();
1400         return -1;
1401 }
1402
1403 /*
1404  * When we call this function, &conlock lock must be locked, because when
1405  * we giving *con argument, some process can remove/change this context
1406  * and after that there can be segfault.
1407  *
1408  * This function locks given context, removes switch, unlock context and
1409  * return.
1410  */
1411 int ast_context_remove_switch2(struct ast_context *con, char *sw, char *data, char *registrar)
1412 {
1413         struct ast_sw *i, *pi = NULL;
1414
1415         if (ast_pthread_mutex_lock(&con->lock)) return -1;
1416
1417         /* walk switchs */
1418         i = con->alts;
1419         while (i) {
1420                 /* find our switch */
1421                 if (!strcmp(i->name, sw) && !strcmp(i->data, data) && 
1422                         (!strcmp(i->registrar, registrar) || !registrar)) {
1423                         /* remove from list */
1424                         if (pi)
1425                                 pi->next = i->next;
1426                         else
1427                                 con->alts = i->next;
1428                         /* free switch and return */
1429                         free(i);
1430                         ast_pthread_mutex_unlock(&con->lock);
1431                         return 0;
1432                 }
1433                 pi = i;
1434                 i = i->next;
1435         }
1436
1437         /* we can't find the right switch */
1438         ast_pthread_mutex_unlock(&con->lock);
1439         return -1;
1440 }
1441
1442 /*
1443  * This functions lock contexts list, search for the right context,
1444  * call ast_context_remove_extension2, unlock contexts list and return.
1445  * In this function we are using
1446  */
1447 int ast_context_remove_extension(char *context, char *extension, int priority, char *registrar)
1448 {
1449         struct ast_context *c;
1450
1451         if (ast_lock_contexts()) return -1;
1452
1453         /* walk contexts ... */
1454         c = ast_walk_contexts(NULL);
1455         while (c) {
1456                 /* ... search for the right one ... */
1457                 if (!strcmp(ast_get_context_name(c), context)) {
1458                         /* ... remove extension ... */
1459                         int ret = ast_context_remove_extension2(c, extension, priority,
1460                                 registrar);
1461                         /* ... unlock contexts list and return */
1462                         ast_unlock_contexts();
1463                         return ret;
1464                 }
1465                 c = ast_walk_contexts(c);
1466         }
1467
1468         /* we can't find the right context */
1469         ast_unlock_contexts();
1470         return -1;
1471 }
1472
1473 /*
1474  * When do you want to call this function, make sure that &conlock is locked,
1475  * because some process can handle with your *con context before you lock
1476  * it.
1477  *
1478  * This functionc locks given context, search for the right extension and
1479  * fires out all peer in this extensions with given priority. If priority
1480  * is set to 0, all peers are removed. After that, unlock context and
1481  * return.
1482  */
1483 int ast_context_remove_extension2(struct ast_context *con, char *extension, int priority, char *registrar)
1484 {
1485         struct ast_exten *exten, *prev_exten = NULL;
1486
1487         if (ast_pthread_mutex_lock(&con->lock)) return -1;
1488
1489         /* go through all extensions in context and search the right one ... */
1490         exten = con->root;
1491         while (exten) {
1492
1493                 /* look for right extension */
1494                 if (!strcmp(exten->exten, extension) &&
1495                         (!strcmp(exten->registrar, registrar) || !registrar)) {
1496                         struct ast_exten *peer;
1497
1498                         /* should we free all peers in this extension? (priority == 0)? */
1499                         if (priority == 0) {
1500                                 /* remove this extension from context list */
1501                                 if (prev_exten)
1502                                         prev_exten->next = exten->next;
1503                                 else
1504                                         con->root = exten->next;
1505
1506                                 /* fire out all peers */
1507                                 peer = exten; 
1508                                 while (peer) {
1509                                         exten = peer->peer;
1510
1511                                         peer->datad(peer->data);
1512                                         free(peer);
1513
1514                                         peer = exten;
1515                                 }
1516
1517                                 ast_pthread_mutex_unlock(&con->lock);
1518                                 return 0;
1519                         } else {
1520                                 /* remove only extension with exten->priority == priority */
1521                                 struct ast_exten *previous_peer = NULL;
1522
1523                                 peer = exten;
1524                                 while (peer) {
1525                                         /* is this our extension? */
1526                                         if (peer->priority == priority &&
1527                                                 (!strcmp(peer->registrar, registrar) || !registrar)) {
1528                                                 /* we are first priority extension? */
1529                                                 if (!previous_peer) {
1530                                                         /* exists previous extension here? */
1531                                                         if (prev_exten) {
1532                                                                 /* yes, so we must change next pointer in
1533                                                                  * previous connection to next peer
1534                                                                  */
1535                                                                 if (peer->peer) {
1536                                                                         prev_exten->next = peer->peer;
1537                                                                         peer->peer->next = exten->next;
1538                                                                 } else
1539                                                                         prev_exten->next = exten->next;
1540                                                         } else {
1541                                                                 /* no previous extension, we are first
1542                                                                  * extension, so change con->root ...
1543                                                                  */
1544                                                                 if (peer->peer)
1545                                                                         con->root = peer->peer;
1546                                                                 else
1547                                                                         con->root = exten->next; 
1548                                                         }
1549                                                 } else {
1550                                                         /* we are not first priority in extension */
1551                                                         previous_peer->peer = peer->peer;
1552                                                 }
1553
1554                                                 /* now, free whole priority extension */
1555                                                 peer->datad(peer->data);
1556                                                 free(peer);
1557
1558                                                 ast_pthread_mutex_unlock(&con->lock);
1559                                                 return 0;
1560                                         } else {
1561                                                 /* this is not right extension, skip to next peer */
1562                                                 previous_peer = peer;
1563                                                 peer = peer->peer;
1564                                         }
1565                                 }
1566
1567                                 ast_pthread_mutex_unlock(&con->lock);
1568                                 return -1;
1569                         }
1570                 }
1571
1572                 prev_exten = exten;
1573                 exten = exten->next;
1574         }
1575
1576         /* we can't find right extension */
1577         ast_pthread_mutex_unlock(&con->lock);
1578         return -1;
1579 }
1580
1581
1582 int ast_register_application(char *app, int (*execute)(struct ast_channel *, void *), char *synopsis, char *description)
1583 {
1584         struct ast_app *tmp;
1585         char tmps[80];
1586         if (ast_pthread_mutex_lock(&applock)) {
1587                 ast_log(LOG_ERROR, "Unable to lock application list\n");
1588                 return -1;
1589         }
1590         tmp = apps;
1591         while(tmp) {
1592                 if (!strcasecmp(app, tmp->name)) {
1593                         ast_log(LOG_WARNING, "Already have an application '%s'\n", app);
1594                         ast_pthread_mutex_unlock(&applock);
1595                         return -1;
1596                 }
1597                 tmp = tmp->next;
1598         }
1599         tmp = malloc(sizeof(struct ast_app));
1600         if (tmp) {
1601                 memset(tmp, 0, sizeof(struct ast_app));
1602                 strncpy(tmp->name, app, sizeof(tmp->name)-1);
1603                 tmp->execute = execute;
1604                 tmp->synopsis = synopsis;
1605                 tmp->description = description;
1606                 tmp->next = apps;
1607                 apps = tmp;
1608         } else {
1609                 ast_log(LOG_WARNING, "Out of memory\n");
1610                 ast_pthread_mutex_unlock(&applock);
1611                 return -1;
1612         }
1613         if (option_verbose > 1)
1614                 ast_verbose( VERBOSE_PREFIX_2 "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps)));
1615         ast_pthread_mutex_unlock(&applock);
1616         return 0;
1617 }
1618
1619 int ast_register_switch(struct ast_switch *sw)
1620 {
1621         struct ast_switch *tmp, *prev=NULL;
1622         if (ast_pthread_mutex_lock(&switchlock)) {
1623                 ast_log(LOG_ERROR, "Unable to lock switch lock\n");
1624                 return -1;
1625         }
1626         tmp = switches;
1627         while(tmp) {
1628                 if (!strcasecmp(tmp->name, sw->name))
1629                         break;
1630                 prev = tmp;
1631                 tmp = tmp->next;
1632         }
1633         if (tmp) {      
1634                 ast_pthread_mutex_unlock(&switchlock);
1635                 ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name);
1636                 return -1;
1637         }
1638         sw->next = NULL;
1639         if (prev) 
1640                 prev->next = sw;
1641         else
1642                 switches = sw;
1643         ast_pthread_mutex_unlock(&switchlock);
1644         return 0;
1645 }
1646
1647 void ast_unregister_switch(struct ast_switch *sw)
1648 {
1649         struct ast_switch *tmp, *prev=NULL;
1650         if (ast_pthread_mutex_lock(&switchlock)) {
1651                 ast_log(LOG_ERROR, "Unable to lock switch lock\n");
1652                 return;
1653         }
1654         tmp = switches;
1655         while(tmp) {
1656                 if (tmp == sw) {
1657                         if (prev)
1658                                 prev->next = tmp->next;
1659                         else
1660                                 switches = tmp->next;
1661                         tmp->next = NULL;
1662                         break;                  
1663                 }
1664                 prev = tmp;
1665                 tmp = tmp->next;
1666         }
1667         ast_pthread_mutex_unlock(&switchlock);
1668 }
1669
1670 /*
1671  * Help for CLI commands ...
1672  */
1673 static char show_application_help[] = 
1674 "Usage: show application <application> [<application> [<application> [...]]]\n"
1675 "       Describes a particular application.\n";
1676
1677 static char show_applications_help[] =
1678 "Usage: show applications\n"
1679 "       List applications which are currently available.\n";
1680
1681 static char show_dialplan_help[] =
1682 "Usage: show dialplan [exten@][context]\n"
1683 "       Show dialplan\n";
1684
1685 static char show_switches_help[] = 
1686 "Usage: show switches\n"
1687 "       Show registered switches\n";
1688
1689 /*
1690  * IMPLEMENTATION OF CLI FUNCTIONS IS IN THE SAME ORDER AS COMMANDS HELPS
1691  *
1692  */
1693
1694 /*
1695  * 'show application' CLI command implementation functions ...
1696  */
1697
1698 /*
1699  * There is a possibility to show informations about more than one
1700  * application at one time. You can type 'show application Dial Echo' and
1701  * you will see informations about these two applications ...
1702  */
1703 static char *complete_show_application(char *line, char *word,
1704         int pos, int state)
1705 {
1706         struct ast_app *a;
1707         int which = 0;
1708
1709         /* try to lock applications list ... */
1710         if (ast_pthread_mutex_lock(&applock)) {
1711                 ast_log(LOG_ERROR, "Unable to lock application list\n");
1712                 return NULL;
1713         }
1714
1715         /* ... walk all applications ... */
1716         a = apps; 
1717         while (a) {
1718                 /* ... check if word matches this application ... */
1719                 if (!strncasecmp(word, a->name, strlen(word))) {
1720                         /* ... if this is right app serve it ... */
1721                         if (++which > state) {
1722                                 char *ret = strdup(a->name);
1723                                 ast_pthread_mutex_unlock(&applock);
1724                                 return ret;
1725                         }
1726                 }
1727                 a = a->next; 
1728         }
1729
1730         /* no application match */
1731         ast_pthread_mutex_unlock(&applock);
1732         return NULL; 
1733 }
1734
1735 static int handle_show_application(int fd, int argc, char *argv[])
1736 {
1737         struct ast_app *a;
1738         char buf[2048];
1739         int app, no_registered_app = 1;
1740
1741         if (argc < 3) return RESULT_SHOWUSAGE;
1742
1743         /* try to lock applications list ... */
1744         if (ast_pthread_mutex_lock(&applock)) {
1745                 ast_log(LOG_ERROR, "Unable to lock application list\n");
1746                 return -1;
1747         }
1748
1749         /* ... go through all applications ... */
1750         a = apps; 
1751         while (a) {
1752                 /* ... compare this application name with all arguments given
1753                  * to 'show application' command ... */
1754                 for (app = 2; app < argc; app++) {
1755                         if (!strcasecmp(a->name, argv[app])) {
1756                                 no_registered_app = 0;
1757
1758                                 /* ... one of our applications, show info ...*/
1759                                 snprintf(buf, sizeof(buf),
1760                                         "\n  -= Info about application '%s' =- \n\n"
1761                                         "[Synopsis]:\n  %s\n\n"
1762                                         "[Description]:\n%s\n",
1763                                         a->name,
1764                                         a->synopsis ? a->synopsis : "Not available",
1765                                         a->description ? a-> description : "Not available");
1766                                 ast_cli(fd, buf);
1767                         }
1768                 }
1769                 a = a->next; 
1770         }
1771
1772         ast_pthread_mutex_unlock(&applock);
1773
1774         /* we found at least one app? no? */
1775         if (no_registered_app) {
1776                 ast_cli(fd, "Your application(s) is (are) not registered\n");
1777                 return RESULT_FAILURE;
1778         }
1779
1780         return RESULT_SUCCESS;
1781 }
1782
1783 static int handle_show_switches(int fd, int argc, char *argv[])
1784 {
1785         struct ast_switch *sw;
1786         if (!switches) {
1787                 ast_cli(fd, "There are no registered alternative switches\n");
1788                 return RESULT_SUCCESS;
1789         }
1790         /* ... we have applications ... */
1791         ast_cli(fd, "\n    -= Registered Asterisk Alternative Switches =-\n");
1792         if (ast_pthread_mutex_lock(&switchlock)) {
1793                 ast_log(LOG_ERROR, "Unable to lock switches\n");
1794                 return -1;
1795         }
1796         sw = switches;
1797         while (sw) {
1798                 ast_cli(fd, "%s: %s\n", sw->name, sw->description);
1799                 sw = sw->next;
1800         }
1801         ast_pthread_mutex_unlock(&switchlock);
1802         return RESULT_SUCCESS;
1803 }
1804
1805 /*
1806  * 'show applications' CLI command implementation functions ...
1807  */
1808 static int handle_show_applications(int fd, int argc, char *argv[])
1809 {
1810         struct ast_app *a;
1811
1812         /* try to lock applications list ... */
1813         if (ast_pthread_mutex_lock(&applock)) {
1814                 ast_log(LOG_ERROR, "Unable to lock application list\n");
1815                 return -1;
1816         }
1817
1818         /* ... go to first application ... */
1819         a = apps; 
1820
1821         /* ... have we got at least one application (first)? no? */
1822         if (!a) {
1823                 ast_cli(fd, "There is no registered applications\n");
1824                 ast_pthread_mutex_unlock(&applock);
1825                 return -1;
1826         }
1827
1828         /* ... we have applications ... */
1829         ast_cli(fd, "\n    -= Registered Asterisk Applications =-\n");
1830
1831         /* ... go through all applications ... */
1832         while (a) {
1833                 /* ... show informations about applications ... */
1834                 ast_cli(fd,"  %15s: %s\n",
1835                         a->name,
1836                         a->synopsis ? a->synopsis : "<Synopsis not available>");
1837                 a = a->next; 
1838         }
1839
1840         /* ... unlock and return */
1841         ast_pthread_mutex_unlock(&applock);
1842
1843         return RESULT_SUCCESS;
1844 }
1845
1846 /*
1847  * 'show dialplan' CLI command implementation functions ...
1848  */
1849 static char *complete_show_dialplan_context(char *line, char *word, int pos,
1850         int state)
1851 {
1852         struct ast_context *c;
1853         int which = 0;
1854
1855         /* we are do completion of [exten@]context on second postion only */
1856         if (pos != 2) return NULL;
1857
1858         /* try to lock contexts list ... */
1859         if (ast_lock_contexts()) {
1860                 ast_log(LOG_ERROR, "Unable to lock context list\n");
1861                 return NULL;
1862         }
1863
1864         /* ... walk through all contexts ... */
1865         c = ast_walk_contexts(NULL);
1866         while(c) {
1867                 /* ... word matches context name? yes? ... */
1868                 if (!strncasecmp(word, ast_get_context_name(c), strlen(word))) {
1869                         /* ... for serve? ... */
1870                         if (++which > state) {
1871                                 /* ... yes, serve this context name ... */
1872                                 char *ret = strdup(ast_get_context_name(c));
1873                                 ast_unlock_contexts();
1874                                 return ret;
1875                         }
1876                 }
1877                 c = ast_walk_contexts(c);
1878         }
1879
1880         /* ... unlock and return */
1881         ast_unlock_contexts();
1882         return NULL;
1883 }
1884
1885 static int handle_show_dialplan(int fd, int argc, char *argv[])
1886 {
1887         struct ast_context *c;
1888         char *exten = NULL, *context = NULL;
1889         int context_existence = 0, extension_existence = 0;
1890
1891         if (argc != 3 && argc != 2) return -1;
1892
1893         /* we obtain [exten@]context? if yes, split them ... */
1894         if (argc == 3) {
1895                 char *splitter = argv[2];
1896                 /* is there a '@' character? */
1897                 if (strchr(argv[2], '@')) {
1898                         /* yes, split into exten & context ... */
1899                         exten   = strsep(&splitter, "@");
1900                         context = splitter;
1901
1902                         /* check for length and change to NULL if !strlen() */
1903                         if (!strlen(exten))   exten = NULL;
1904                         if (!strlen(context)) context = NULL;
1905                 } else
1906                 {
1907                         /* no '@' char, only context given */
1908                         context = argv[2];
1909                         if (!strlen(context)) context = NULL;
1910                 }
1911         }
1912
1913         /* try to lock contexts */
1914         if (ast_lock_contexts()) {
1915                 ast_cli(LOG_WARNING, "Failed to lock contexts list\n");
1916                 return RESULT_FAILURE;
1917         }
1918
1919         /* walk all contexts ... */
1920         c = ast_walk_contexts(NULL);
1921         while (c) {
1922                 /* show this context? */
1923                 if (!context ||
1924                         !strcmp(ast_get_context_name(c), context)) {
1925                         context_existence = 1;
1926
1927                         /* try to lock context before walking in ... */
1928                         if (!ast_lock_context(c)) {
1929                                 struct ast_exten *e;
1930                                 struct ast_include *i;
1931                                 struct ast_ignorepat *ip;
1932                                 struct ast_sw *sw;
1933                                 char buf[256], buf2[256];
1934                                 int context_info_printed = 0;
1935
1936                                 /* are we looking for exten too? if yes, we print context
1937                                  * if we our extension only
1938                                  */
1939                                 if (!exten) {
1940                                         ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
1941                                                 ast_get_context_name(c), ast_get_context_registrar(c));
1942                                         context_info_printed = 1;
1943                                 }
1944
1945                                 /* walk extensions ... */
1946                                 e = ast_walk_context_extensions(c, NULL);
1947                                 while (e) {
1948                                         struct ast_exten *p;
1949
1950                                         /* looking for extension? is this our extension? */
1951                                         if (exten &&
1952                                                 strcmp(ast_get_extension_name(e), exten))
1953                                         {
1954                                                 /* we are looking for extension and it's not our
1955                                                  * extension, so skip to next extension */
1956                                                 e = ast_walk_context_extensions(c, e);
1957                                                 continue;
1958                                         }
1959
1960                                         extension_existence = 1;
1961
1962                                         /* may we print context info? */        
1963                                         if (!context_info_printed) {
1964                                                 ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
1965                                                         ast_get_context_name(c),
1966                                                         ast_get_context_registrar(c));
1967                                                 context_info_printed = 1;
1968                                         }
1969
1970                                         /* write extension name and first peer */       
1971                                         bzero(buf, sizeof(buf));                
1972                                         snprintf(buf, sizeof(buf), "'%s' =>",
1973                                                 ast_get_extension_name(e));
1974
1975                                         snprintf(buf2, sizeof(buf2),
1976                                                 "%d. %s(%s)",
1977                                                 ast_get_extension_priority(e),
1978                                                 ast_get_extension_app(e),
1979                                                 (char *)ast_get_extension_app_data(e));
1980
1981                                         ast_cli(fd, "  %-17s %-45s [%s]\n", buf, buf2,
1982                                                 ast_get_extension_registrar(e));
1983
1984                                         /* walk next extension peers */
1985                                         p = ast_walk_extension_priorities(e, e);
1986                                         while (p) {
1987                                                 bzero((void *)buf2, sizeof(buf2));
1988
1989                                                 snprintf(buf2, sizeof(buf2),
1990                                                         "%d. %s(%s)",
1991                                                         ast_get_extension_priority(p),
1992                                                         ast_get_extension_app(p),
1993                                                         (char *)ast_get_extension_app_data(p));
1994
1995                                                 ast_cli(fd,"  %-17s %-45s [%s]\n",
1996                                                         "", buf2,
1997                                                         ast_get_extension_registrar(p));        
1998
1999                                                 p = ast_walk_extension_priorities(e, p);
2000                                         }
2001                                         e = ast_walk_context_extensions(c, e);
2002                                 }
2003
2004                                 /* include & ignorepat we all printing if we are not
2005                                  * looking for exact extension
2006                                  */
2007                                 if (!exten) {
2008                                         if (ast_walk_context_extensions(c, NULL))
2009                                                 ast_cli(fd, "\n");
2010
2011                                         /* walk included and write info ... */
2012                                         i = ast_walk_context_includes(c, NULL);
2013                                         while (i) {
2014                                                 bzero(buf, sizeof(buf));
2015                                                 snprintf(buf, sizeof(buf), "'%s'",
2016                                                         ast_get_include_name(i));
2017                                                 ast_cli(fd, "  Include =>        %-45s [%s]\n",
2018                                                         buf, ast_get_include_registrar(i));
2019                                                 i = ast_walk_context_includes(c, i);
2020                                         }
2021
2022                                         /* walk ignore patterns and write info ... */
2023                                         ip = ast_walk_context_ignorepats(c, NULL);
2024                                         while (ip) {
2025                                                 bzero(buf, sizeof(buf));
2026                                                 snprintf(buf, sizeof(buf), "'%s'",
2027                                                         ast_get_ignorepat_name(ip));
2028                                                 ast_cli(fd, "  Ignore pattern => %-45s [%s]\n",
2029                                                         buf, ast_get_ignorepat_registrar(ip));  
2030                                                 ip = ast_walk_context_ignorepats(c, ip);
2031                                         }
2032                                         sw = ast_walk_context_switches(c, NULL);
2033                                         while(sw) {
2034                                                 bzero(buf, sizeof(buf));
2035                                                 snprintf(buf, sizeof(buf), "'%s/%s'",
2036                                                         ast_get_switch_name(sw),
2037                                                         ast_get_switch_data(sw));
2038                                                 ast_cli(fd, "  Alt. Switch =>    %-45s [%s]\n",
2039                                                         buf, ast_get_switch_registrar(sw));     
2040                                                 sw = ast_walk_context_switches(c, sw);
2041                                         }
2042                                 }
2043         
2044                                 ast_unlock_context(c);
2045
2046                                 /* if we print something in context, make an empty line */
2047                                 if (context_info_printed) ast_cli(fd, "\n");
2048                         }
2049                 }
2050                 c = ast_walk_contexts(c);
2051         }
2052         ast_unlock_contexts();
2053
2054         /* check for input failure and throw some error messages */
2055         if (context && !context_existence) {
2056                 ast_cli(fd, "There is no existence of '%s' context\n",
2057                         context);
2058                 return RESULT_FAILURE;
2059         }
2060
2061         if (exten && !extension_existence) {
2062                 if (context)
2063                         ast_cli(fd, "There is no existence of %s@%s extension\n",
2064                                 exten, context);
2065                 else
2066                         ast_cli(fd,
2067                                 "There is no existence of '%s' extension in all contexts\n",
2068                                 exten);
2069                 return RESULT_FAILURE;
2070         }
2071
2072         /* everything ok */
2073         return RESULT_SUCCESS;
2074 }
2075
2076 /*
2077  * CLI entries for upper commands ...
2078  */
2079 static struct ast_cli_entry show_applications_cli = 
2080         { { "show", "applications", NULL }, 
2081         handle_show_applications, "Shows registered applications",
2082         show_applications_help };
2083
2084 static struct ast_cli_entry show_application_cli =
2085         { { "show", "application", NULL }, 
2086         handle_show_application, "Describe a specific application",
2087         show_application_help, complete_show_application };
2088
2089 static struct ast_cli_entry show_dialplan_cli =
2090         { { "show", "dialplan", NULL },
2091                 handle_show_dialplan, "Show dialplan",
2092                 show_dialplan_help, complete_show_dialplan_context };
2093
2094 static struct ast_cli_entry show_switches_cli =
2095         { { "show", "switches", NULL },
2096                 handle_show_switches, "Show alternative switches",
2097                 show_switches_help, NULL };
2098
2099 int ast_unregister_application(char *app) {
2100         struct ast_app *tmp, *tmpl = NULL;
2101         if (ast_pthread_mutex_lock(&applock)) {
2102                 ast_log(LOG_ERROR, "Unable to lock application list\n");
2103                 return -1;
2104         }
2105         tmp = apps;
2106         while(tmp) {
2107                 if (!strcasecmp(app, tmp->name)) {
2108                         if (tmpl)
2109                                 tmpl->next = tmp->next;
2110                         else
2111                                 apps = tmp->next;
2112                         if (option_verbose > 1)
2113                                 ast_verbose( VERBOSE_PREFIX_2 "Unregistered application '%s'\n", tmp->name);
2114                         ast_pthread_mutex_unlock(&applock);
2115                         return 0;
2116                 }
2117                 tmpl = tmp;
2118                 tmp = tmp->next;
2119         }
2120         ast_pthread_mutex_unlock(&applock);
2121         return -1;
2122 }
2123
2124 struct ast_context *ast_context_create(char *name, char *registrar)
2125 {
2126         struct ast_context *tmp;
2127         
2128         ast_pthread_mutex_lock(&conlock);
2129         tmp = contexts;
2130         while(tmp) {
2131                 if (!strcasecmp(tmp->name, name)) {
2132                         ast_pthread_mutex_unlock(&conlock);
2133                         ast_log(LOG_WARNING, "Tried to register context '%s', already in use\n", name);
2134                         return NULL;
2135                 }
2136                 tmp = tmp->next;
2137         }
2138         tmp = malloc(sizeof(struct ast_context));
2139         if (tmp) {
2140                 memset(tmp, 0, sizeof(struct ast_context));
2141                 ast_pthread_mutex_init(&tmp->lock);
2142                 strncpy(tmp->name, name, sizeof(tmp->name)-1);
2143                 tmp->root = NULL;
2144                 tmp->registrar = registrar;
2145                 tmp->next = contexts;
2146                 tmp->includes = NULL;
2147                 tmp->ignorepats = NULL;
2148                 contexts = tmp;
2149                 if (option_debug)
2150                         ast_log(LOG_DEBUG, "Registered context '%s'\n", tmp->name);
2151                 else if (option_verbose > 2)
2152                         ast_verbose( VERBOSE_PREFIX_3 "Registered extension context '%s'\n", tmp->name);
2153         } else
2154                 ast_log(LOG_WARNING, "Out of memory\n");
2155         
2156         ast_pthread_mutex_unlock(&conlock);
2157         return tmp;
2158 }
2159
2160 /*
2161  * errno values
2162  *  EBUSY  - can't lock
2163  *  ENODATA - no existence of context
2164  */
2165 int ast_context_add_include(char *context, char *include, char *registrar)
2166 {
2167         struct ast_context *c;
2168
2169         if (ast_lock_contexts()) {
2170                 errno = EBUSY;
2171                 return -1;
2172         }
2173
2174         /* walk contexts ... */
2175         c = ast_walk_contexts(NULL);
2176         while (c) {
2177                 /* ... search for the right one ... */
2178                 if (!strcmp(ast_get_context_name(c), context)) {
2179                         int ret = ast_context_add_include2(c, include, registrar);
2180                         /* ... unlock contexts list and return */
2181                         ast_unlock_contexts();
2182                         return ret;
2183                 }
2184                 c = ast_walk_contexts(c);
2185         }
2186
2187         /* we can't find the right context */
2188         ast_unlock_contexts();
2189         errno = ENODATA;
2190         return -1;
2191 }
2192
2193 #define FIND_NEXT \
2194 do { \
2195         c = info; \
2196         while(*c && (*c != '|')) c++; \
2197         if (*c) { *c = '\0'; c++; } else c = NULL; \
2198 } while(0)
2199
2200 static void get_timerange(struct ast_include *i, char *times)
2201 {
2202         char *e;
2203         int x;
2204         int s1, s2;
2205         int e1, e2;
2206         /* Star is all times */
2207         if (!strlen(times) || !strcmp(times, "*")) {
2208                 for (x=0;x<24;x++)
2209                         i->minmask[x] = (1 << 30) - 1;
2210                 return;
2211         }
2212         /* Otherwise expect a range */
2213         e = strchr(times, '-');
2214         if (!e) {
2215                 ast_log(LOG_WARNING, "Time range is not valid. Assuming no time.\n");
2216                 return;
2217         }
2218         *e = '\0';
2219         e++;
2220         while(*e && !isdigit(*e)) e++;
2221         if (!*e) {
2222                 ast_log(LOG_WARNING, "Invalid time range.  Assuming no time.\n");
2223                 return;
2224         }
2225         if (sscanf(times, "%d:%d", &s1, &s2) != 2) {
2226                 ast_log(LOG_WARNING, "%s isn't a time.  Assuming no time.\n", times);
2227                 return;
2228         }
2229         if (sscanf(e, "%d:%d", &e1, &e2) != 2) {
2230                 ast_log(LOG_WARNING, "%s isn't a time.  Assuming no time.\n", e);
2231                 return;
2232         }
2233         s1 = s1 * 30 + s2/2;
2234         if ((s1 < 0) || (s1 >= 24*30)) {
2235                 ast_log(LOG_WARNING, "%s isn't a valid star time. Assuming no time.\n", times);
2236                 return;
2237         }
2238         e1 = e1 * 30 + e2/2;
2239         if ((e1 < 0) || (e2 >= 24*30)) {
2240                 ast_log(LOG_WARNING, "%s isn't a valid start time. Assuming no time.\n", times);
2241                 return;
2242         }
2243         /* Go through the time and enable each appropriate bit */
2244         for (x=s1;x != e1;x = (x + 1) % (24 * 30)) {
2245                 i->minmask[x/30] |= (1 << (x % 30));
2246         }
2247         /* Do the last one */
2248         i->minmask[x/30] |= (1 << (x % 30));
2249         /* All done */
2250 }
2251
2252 static char *days[] =
2253 {
2254         "sun",
2255         "mon",
2256         "tue",
2257         "wed",
2258         "thu",
2259         "fri",
2260         "sat",
2261 };
2262
2263 static unsigned int get_dow(char *dow)
2264 {
2265         char *c;
2266         /* The following line is coincidence, really! */
2267         int s, e, x;
2268         unsigned int mask;
2269         /* Check for all days */
2270         if (!strlen(dow) || !strcmp(dow, "*"))
2271                 return (1 << 7) - 1;
2272         /* Get start and ending days */
2273         c = strchr(dow, '-');
2274         if (c) {
2275                 *c = '\0';
2276                 c++;
2277         } else
2278                 c = NULL;
2279         /* Find the start */
2280         s = 0;
2281         while((s < 7) && strcasecmp(dow, days[s])) s++;
2282         if (s >= 7) {
2283                 ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", dow);
2284                 return 0;
2285         }
2286         if (c) {
2287                 e = 0;
2288                 while((e < 7) && strcasecmp(c, days[e])) e++;
2289                 if (e >= 7) {
2290                         ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", c);
2291                         return 0;
2292                 }
2293         } else
2294                 e = s;
2295         mask = 0;
2296         for (x=s;x!=e;x = (x + 1) % 7) {
2297                 mask |= (1 << x);
2298         }
2299         /* One last one */
2300         mask |= (1 << x);
2301         return mask;
2302 }
2303
2304 static unsigned int get_day(char *day)
2305 {
2306         char *c;
2307         /* The following line is coincidence, really! */
2308         int s, e, x;
2309         unsigned int mask;
2310         /* Check for all days */
2311         if (!strlen(day) || !strcmp(day, "*")) {
2312                 mask = (1 << 30)  + ((1 << 30) - 1);
2313                 return mask;
2314         }
2315         /* Get start and ending days */
2316         c = strchr(day, '-');
2317         if (c) {
2318                 *c = '\0';
2319                 c++;
2320         }
2321         /* Find the start */
2322         if (sscanf(day, "%d", &s) != 1) {
2323                 ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", day);
2324                 return 0;
2325         }
2326         if ((s < 1) || (s > 31)) {
2327                 ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", day);
2328                 return 0;
2329         }
2330         s--;
2331         if (c) {
2332                 if (sscanf(c, "%d", &e) != 1) {
2333                         ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", c);
2334                         return 0;
2335                 }
2336                 if ((e < 1) || (e > 31)) {
2337                         ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", c);
2338                         return 0;
2339                 }
2340                 e--;
2341         } else
2342                 e = s;
2343         mask = 0;
2344         for (x=s;x!=e;x = (x + 1) % 31) {
2345                 mask |= (1 << x);
2346         }
2347         mask |= (1 << x);
2348         return mask;
2349 }
2350
2351 static char *months[] =
2352 {
2353         "jan",
2354         "feb",
2355         "mar",
2356         "apr",
2357         "may",
2358         "jun",
2359         "jul",
2360         "aug",
2361         "sep",
2362         "oct",
2363         "nov",
2364         "dec",
2365 };
2366
2367 static unsigned int get_month(char *mon)
2368 {
2369         char *c;
2370         /* The following line is coincidence, really! */
2371         int s, e, x;
2372         unsigned int mask;
2373         /* Check for all days */
2374         if (!strlen(mon) || !strcmp(mon, "*")) 
2375                 return (1 << 12) - 1;
2376         /* Get start and ending days */
2377         c = strchr(mon, '-');
2378         if (c) {
2379                 *c = '\0';
2380                 c++;
2381         }
2382         /* Find the start */
2383         s = 0;
2384         while((s < 12) && strcasecmp(mon, months[s])) s++;
2385         if (s >= 12) {
2386                 ast_log(LOG_WARNING, "Invalid month '%s', assuming none\n", mon);
2387                 return 0;
2388         }
2389         if (c) {
2390                 e = 0;
2391                 while((e < 12) && strcasecmp(mon, months[e])) e++;
2392                 if (e >= 12) {
2393                         ast_log(LOG_WARNING, "Invalid month '%s', assuming none\n", c);
2394                         return 0;
2395                 }
2396         } else
2397                 e = s;
2398         mask = 0;
2399         for (x=s;x!=e;x = (x + 1) % 12) {
2400                 mask |= (1 << x);
2401         }
2402         /* One last one */
2403         mask |= (1 << x);
2404         return mask;
2405 }
2406
2407 static void build_timing(struct ast_include *i, char *info)
2408 {
2409         char *c;
2410         /* Check for empty just in case */
2411         if (!strlen(info))
2412                 return;
2413         i->hastime = 1;
2414         /* Assume everything except time */
2415         i->monthmask = (1 << 12) - 1;
2416         i->daymask = (1 << 30) - 1 + (1 << 30);
2417         i->dowmask = (1 << 7) - 1;
2418         /* Avoid using str tok */
2419         FIND_NEXT;
2420         /* Info has the time range, start with that */
2421         get_timerange(i, info);
2422         info = c;
2423         if (!info)
2424                 return;
2425         FIND_NEXT;
2426         /* Now check for day of week */
2427         i->dowmask = get_dow(info);
2428
2429         info = c;
2430         if (!info)
2431                 return;
2432         FIND_NEXT;
2433         /* Now check for the day of the month */
2434         i->daymask = get_day(info);
2435         info = c;
2436         if (!info)
2437                 return;
2438         FIND_NEXT;
2439         /* And finally go for the month */
2440         i->monthmask = get_month(info);
2441 }
2442
2443 /*
2444  * errno values
2445  *  ENOMEM - out of memory
2446  *  EBUSY  - can't lock
2447  *  EEXIST - already included
2448  *  EINVAL - there is no existence of context for inclusion
2449  */
2450 int ast_context_add_include2(struct ast_context *con, char *value,
2451         char *registrar)
2452 {
2453         struct ast_include *new_include;
2454         char *c;
2455         struct ast_include *i, *il = NULL; /* include, include_last */
2456
2457         /* allocate new include structure ... */
2458         if (!(new_include = malloc(sizeof(struct ast_include)))) {
2459                 ast_log(LOG_WARNING, "Out of memory\n");
2460                 errno = ENOMEM;
2461                 return -1;
2462         }
2463         
2464         /* ... fill in this structure ... */
2465         memset(new_include, 0, sizeof(struct ast_include));
2466         strncpy(new_include->name, value, sizeof(new_include->name)-1);
2467         strncpy(new_include->rname, value, sizeof(new_include->rname)-1);
2468         c = new_include->rname;
2469         /* Strip off timing info */
2470         while(*c && (*c != '|')) c++; 
2471         /* Process if it's there */
2472         if (*c) {
2473                 build_timing(new_include, c+1);
2474                 *c = '\0';
2475         }
2476         new_include->next      = NULL;
2477         new_include->registrar = registrar;
2478
2479         /* ... try to lock this context ... */
2480         if (ast_pthread_mutex_lock(&con->lock)) {
2481                 free(new_include);
2482                 errno = EBUSY;
2483                 return -1;
2484         }
2485
2486         /* ... go to last include and check if context is already included too... */
2487         i = con->includes;
2488         while (i) {
2489                 if (!strcasecmp(i->name, new_include->name)) {
2490                         free(new_include);
2491                         ast_pthread_mutex_unlock(&con->lock);
2492                         errno = EEXIST;
2493                         return -1;
2494                 }
2495                 il = i;
2496                 i = i->next;
2497         }
2498
2499         /* ... include new context into context list, unlock, return */
2500         if (il)
2501                 il->next = new_include;
2502         else
2503                 con->includes = new_include;
2504         if (option_verbose > 2)
2505                 ast_verbose(VERBOSE_PREFIX_3 "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con)); 
2506         ast_pthread_mutex_unlock(&con->lock);
2507
2508         return 0;
2509 }
2510
2511 /*
2512  * errno values
2513  *  EBUSY  - can't lock
2514  *  ENODATA - no existence of context
2515  */
2516 int ast_context_add_switch(char *context, char *sw, char *data, char *registrar)
2517 {
2518         struct ast_context *c;
2519
2520         if (ast_lock_contexts()) {
2521                 errno = EBUSY;
2522                 return -1;
2523         }
2524
2525         /* walk contexts ... */
2526         c = ast_walk_contexts(NULL);
2527         while (c) {
2528                 /* ... search for the right one ... */
2529                 if (!strcmp(ast_get_context_name(c), context)) {
2530                         int ret = ast_context_add_switch2(c, sw, data, registrar);
2531                         /* ... unlock contexts list and return */
2532                         ast_unlock_contexts();
2533                         return ret;
2534                 }
2535                 c = ast_walk_contexts(c);
2536         }
2537
2538         /* we can't find the right context */
2539         ast_unlock_contexts();
2540         errno = ENODATA;
2541         return -1;
2542 }
2543
2544 /*
2545  * errno values
2546  *  ENOMEM - out of memory
2547  *  EBUSY  - can't lock
2548  *  EEXIST - already included
2549  *  EINVAL - there is no existence of context for inclusion
2550  */
2551 int ast_context_add_switch2(struct ast_context *con, char *value,
2552         char *data, char *registrar)
2553 {
2554         struct ast_sw *new_sw;
2555         struct ast_sw *i, *il = NULL; /* sw, sw_last */
2556
2557         /* allocate new sw structure ... */
2558         if (!(new_sw = malloc(sizeof(struct ast_sw)))) {
2559                 ast_log(LOG_WARNING, "Out of memory\n");
2560                 errno = ENOMEM;
2561                 return -1;
2562         }
2563         
2564         /* ... fill in this structure ... */
2565         memset(new_sw, 0, sizeof(struct ast_sw));
2566         strncpy(new_sw->name, value, sizeof(new_sw->name)-1);
2567         if (data)
2568                 strncpy(new_sw->data, data, sizeof(new_sw->data)-1);
2569         else
2570                 strncpy(new_sw->data, "", sizeof(new_sw->data)-1);
2571         new_sw->next      = NULL;
2572         new_sw->registrar = registrar;
2573
2574         /* ... try to lock this context ... */
2575         if (ast_pthread_mutex_lock(&con->lock)) {
2576                 free(new_sw);
2577                 errno = EBUSY;
2578                 return -1;
2579         }
2580
2581         /* ... go to last sw and check if context is already swd too... */
2582         i = con->alts;
2583         while (i) {
2584                 if (!strcasecmp(i->name, new_sw->name)) {
2585                         free(new_sw);
2586                         ast_pthread_mutex_unlock(&con->lock);
2587                         errno = EEXIST;
2588                         return -1;
2589                 }
2590                 il = i;
2591                 i = i->next;
2592         }
2593
2594         /* ... sw new context into context list, unlock, return */
2595         if (il)
2596                 il->next = new_sw;
2597         else
2598                 con->alts = new_sw;
2599         if (option_verbose > 2)
2600                 ast_verbose(VERBOSE_PREFIX_3 "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con)); 
2601         ast_pthread_mutex_unlock(&con->lock);
2602
2603         return 0;
2604 }
2605
2606 /*
2607  * EBUSY  - can't lock
2608  * ENODATA - there is not context existence
2609  */
2610 int ast_context_remove_ignorepat(char *context, char *ignorepat, char *registrar)
2611 {
2612         struct ast_context *c;
2613
2614         if (ast_lock_contexts()) {
2615                 errno = EBUSY;
2616                 return -1;
2617         }
2618
2619         c = ast_walk_contexts(NULL);
2620         while (c) {
2621                 if (!strcmp(ast_get_context_name(c), context)) {
2622                         int ret = ast_context_remove_ignorepat2(c, ignorepat, registrar);
2623                         ast_unlock_contexts();
2624                         return ret;
2625                 }
2626                 c = ast_walk_contexts(c);
2627         }
2628
2629         ast_unlock_contexts();
2630         errno = ENODATA;
2631         return -1;
2632 }
2633
2634 int ast_context_remove_ignorepat2(struct ast_context *con, char *ignorepat, char *registrar)
2635 {
2636         struct ast_ignorepat *ip, *ipl = NULL;
2637
2638         if (ast_pthread_mutex_lock(&con->lock)) {
2639                 errno = EBUSY;
2640                 return -1;
2641         }
2642
2643         ip = con->ignorepats;
2644         while (ip) {
2645                 if (!strcmp(ip->pattern, ignorepat) &&
2646                         (registrar == ip->registrar || !registrar)) {
2647                         if (ipl) {
2648                                 ipl->next = ip->next;
2649                                 free(ip);
2650                         } else {
2651                                 con->ignorepats = ip->next;
2652                                 free(ip);
2653                         }
2654                         ast_pthread_mutex_unlock(&con->lock);
2655                         return 0;
2656                 }
2657                 ipl = ip; ip = ip->next;
2658         }
2659
2660         ast_pthread_mutex_unlock(&con->lock);
2661         errno = EINVAL;
2662         return -1;
2663 }
2664
2665 /*
2666  * EBUSY - can't lock
2667  * ENODATA - there is no existence of context
2668  */
2669 int ast_context_add_ignorepat(char *con, char *value, char *registrar)
2670 {
2671         struct ast_context *c;
2672
2673         if (ast_lock_contexts()) {
2674                 errno = EBUSY;
2675                 return -1;
2676         }
2677
2678         c = ast_walk_contexts(NULL);
2679         while (c) {
2680                 if (!strcmp(ast_get_context_name(c), con)) {
2681                         int ret = ast_context_add_ignorepat2(c, value, registrar);
2682                         ast_unlock_contexts();
2683                         return ret;
2684                 } 
2685                 c = ast_walk_contexts(c);
2686         }
2687
2688         ast_unlock_contexts();
2689         errno = ENODATA;
2690         return -1;
2691 }
2692
2693 int ast_context_add_ignorepat2(struct ast_context *con, char *value, char *registrar)
2694 {
2695         struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL;
2696         ignorepat = malloc(sizeof(struct ast_ignorepat));
2697         if (!ignorepat) {
2698                 ast_log(LOG_WARNING, "Out of memory\n");
2699                 errno = ENOMEM;
2700                 return -1;
2701         }
2702         memset(ignorepat, 0, sizeof(struct ast_ignorepat));
2703         strncpy(ignorepat->pattern, value, sizeof(ignorepat->pattern)-1);
2704         ignorepat->next = NULL;
2705         ignorepat->registrar = registrar;
2706         ast_pthread_mutex_lock(&con->lock);
2707         ignorepatc = con->ignorepats;
2708         while(ignorepatc) {
2709                 ignorepatl = ignorepatc;
2710                 if (!strcasecmp(ignorepatc->pattern, value)) {
2711                         /* Already there */
2712                         pthread_mutex_unlock(&con->lock);
2713                         errno = EEXIST;
2714                         return -1;
2715                 }
2716                 ignorepatc = ignorepatc->next;
2717         }
2718         if (ignorepatl) 
2719                 ignorepatl->next = ignorepat;
2720         else
2721                 con->ignorepats = ignorepat;
2722         pthread_mutex_unlock(&con->lock);
2723         return 0;
2724         
2725 }
2726
2727 int ast_ignore_pattern(char *context, char *pattern)
2728 {
2729         struct ast_context *con;
2730         struct ast_ignorepat *pat;
2731         con = ast_context_find(context);
2732         if (con) {
2733                 pat = con->ignorepats;
2734                 while (pat) {
2735                         if (ast_extension_match(pat->pattern, pattern))
2736                                 return 1;
2737                         pat = pat->next;
2738                 }
2739         } 
2740         return 0;
2741 }
2742
2743 /*
2744  * EBUSY   - can't lock
2745  * ENODATA  - no existence of context
2746  *
2747  */
2748 int ast_add_extension(char *context, int replace, char *extension, int priority, char *callerid,
2749         char *application, void *data, void (*datad)(void *), char *registrar)
2750 {
2751         struct ast_context *c;
2752
2753         if (ast_lock_contexts()) {
2754                 errno = EBUSY;
2755                 return -1;
2756         }
2757
2758         c = ast_walk_contexts(NULL);
2759         while (c) {
2760                 if (!strcmp(context, ast_get_context_name(c))) {
2761                         int ret = ast_add_extension2(c, replace, extension, priority, callerid,
2762                                 application, data, datad, registrar);
2763                         ast_unlock_contexts();
2764                         return ret;
2765                 }
2766                 c = ast_walk_contexts(c);
2767         }
2768
2769         ast_unlock_contexts();
2770         errno = ENODATA;
2771         return -1;
2772 }
2773
2774 int ast_async_goto(struct ast_channel *chan, char *context, char *exten, int priority, int needlock)
2775 {
2776         int res = 0;
2777         if (needlock)
2778                 ast_pthread_mutex_lock(&chan->lock);
2779         if (chan->pbx) {
2780                 /* This channel is currently in the PBX */
2781                 if (context && strlen(context))
2782                         strncpy(chan->context, context, sizeof(chan->context) - 1);
2783                 if (exten && strlen(exten))
2784                         strncpy(chan->exten, exten, sizeof(chan->context) - 1);
2785                 if (priority)
2786                         chan->priority = priority - 1;
2787                 ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO);
2788                 if (needlock)
2789                         ast_pthread_mutex_unlock(&chan->lock);
2790         } else {
2791                 /* In order to do it when the channel doesn't really exist within
2792                    the PBX, we have to make a new channel, masquerade, and start the PBX
2793                    at the new location */
2794                 struct ast_channel *tmpchan;
2795                 struct ast_frame *f;
2796                 tmpchan = ast_channel_alloc(0);
2797                 if (tmpchan) {
2798                         ast_setstate(tmpchan, chan->_state);
2799                         snprintf(tmpchan->name, sizeof(tmpchan->name), "AsyncGoto/%s", chan->name);
2800                         /* Make formats okay */
2801                         tmpchan->readformat = chan->readformat;
2802                         tmpchan->writeformat = chan->writeformat;
2803                         /* Setup proper location */
2804                         if (context && strlen(context))
2805                                 strncpy(tmpchan->context, context, sizeof(tmpchan->context) - 1);
2806                         else
2807                                 strncpy(tmpchan->context, chan->context, sizeof(tmpchan->context) - 1);
2808                         if (exten && strlen(exten))
2809                                 strncpy(tmpchan->exten, exten, sizeof(tmpchan->exten) - 1);
2810                         else
2811                                 strncpy(tmpchan->exten, chan->exten, sizeof(tmpchan->exten) - 1);
2812                         if (priority)
2813                                 tmpchan->priority = priority;
2814                         else
2815                                 tmpchan->priority = chan->priority;
2816                         if (needlock)
2817                                 ast_pthread_mutex_unlock(&chan->lock);
2818                         
2819                         /* Masquerade into temp channel */
2820                         ast_channel_masquerade(tmpchan, chan);
2821                         
2822                         /* Make the masquerade happen by reading a frame from the tmp channel */
2823                         f = ast_read(tmpchan);
2824                         if (f)
2825                                 ast_frfree(f);
2826                         /* Start the PBX going on our stolen channel */
2827                         if (ast_pbx_start(tmpchan)) {
2828                                 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name);
2829                                 ast_hangup(tmpchan);
2830                                 res = -1;
2831                         }
2832                 } else {
2833                         res = -1;
2834                         if (needlock)
2835                                 ast_pthread_mutex_unlock(&chan->lock);
2836                 }
2837         }
2838         return res;
2839 }
2840
2841 int ast_async_goto_by_name(char *channame, char *context, char *exten, int priority)
2842 {
2843         struct ast_channel *chan;
2844         chan = ast_channel_walk(NULL);
2845         while(chan) {
2846                 if (!strcasecmp(channame, chan->name))
2847                         break;
2848                 chan = ast_channel_walk(chan);
2849         }
2850         if (chan)
2851                 return ast_async_goto(chan, context, exten, priority, 1);
2852         return -1;
2853 }
2854
2855 static void ext_strncpy(char *dst, char *src, int len)
2856 {
2857         int count=0;
2858         while(*src && (count < len - 1)) {
2859                 switch(*src) {
2860                 case ' ':
2861 //otherwise exten => [a-b],1,... doesn't work
2862 //              case '-':
2863                         /* Ignore */
2864                         break;
2865                 default:
2866                         *dst = *src;
2867                         dst++;
2868                 }
2869                 src++;
2870                 count++;
2871         }
2872         *dst = '\0';
2873 }
2874
2875 /*
2876  * EBUSY - can't lock
2877  * EEXIST - extension with the same priority exist and no replace is set
2878  *
2879  */
2880 int ast_add_extension2(struct ast_context *con,
2881                                           int replace, char *extension, int priority, char *callerid,
2882                                           char *application, void *data, void (*datad)(void *),
2883                                           char *registrar)
2884 {
2885
2886 #define LOG do {        if (option_debug) {\
2887                 if (tmp->matchcid) { \
2888                         ast_log(LOG_DEBUG, "Added extension '%s' priority %d (CID match '%s') to %s\n", tmp->exten, tmp->priority, tmp->cidmatch, con->name); \
2889                 } else { \
2890                         ast_log(LOG_DEBUG, "Added extension '%s' priority %d to %s\n", tmp->exten, tmp->priority, con->name); \
2891                 } \
2892         } else if (option_verbose > 2) { \
2893                 if (tmp->matchcid) { \
2894                         ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d (CID match '%s')to %s\n", tmp->exten, tmp->priority, tmp->cidmatch, con->name); \
2895                 } else {  \
2896                         ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d to %s\n", tmp->exten, tmp->priority, con->name); \
2897                 } \
2898         } } while(0)
2899
2900         /*
2901          * This is a fairly complex routine.  Different extensions are kept
2902          * in order by the extension number.  Then, extensions of different
2903          * priorities (same extension) are kept in a list, according to the
2904          * peer pointer.
2905          */
2906         struct ast_exten *tmp, *e, *el = NULL, *ep = NULL;
2907         int res;
2908         /* Be optimistic:  Build the extension structure first */
2909         tmp = malloc(sizeof(struct ast_exten));
2910         if (tmp) {
2911                 memset(tmp, 0, sizeof(struct ast_exten));
2912                 ext_strncpy(tmp->exten, extension, sizeof(tmp->exten));
2913                 tmp->priority = priority;
2914                 if (callerid) {
2915                         ext_strncpy(tmp->cidmatch, callerid, sizeof(tmp->cidmatch));
2916                         tmp->matchcid = 1;
2917                 } else {
2918                         strcpy(tmp->cidmatch, "");
2919                         tmp->matchcid = 0;
2920                 }
2921                 strncpy(tmp->app, application, sizeof(tmp->app)-1);
2922                 tmp->data = data;
2923                 tmp->datad = datad;
2924                 tmp->registrar = registrar;
2925                 tmp->peer = NULL;
2926                 tmp->next =  NULL;
2927         } else {
2928                 ast_log(LOG_WARNING, "Out of memory\n");
2929                 errno = ENOMEM;
2930                 return -1;
2931         }
2932         if (ast_pthread_mutex_lock(&con->lock)) {
2933                 free(tmp);
2934                 /* And properly destroy the data */
2935                 datad(data);
2936                 ast_log(LOG_WARNING, "Failed to lock context '%s'\n", con->name);
2937                 errno = EBUSY;
2938                 return -1;
2939         }
2940         e = con->root;
2941         while(e) {
2942                 res= strcasecmp(e->exten, extension);
2943                 if (!res) {
2944                         if (!e->matchcid && !tmp->matchcid)
2945                                 res = 0;
2946                         else if (tmp->matchcid && !e->matchcid)
2947                                 res = 1;
2948                         else if (e->matchcid && !tmp->matchcid)
2949                                 res = -1;
2950                         else
2951                                 res = strcasecmp(e->cidmatch, tmp->cidmatch);
2952                 }
2953                 if (res == 0) {
2954                         /* We have an exact match, now we find where we are
2955                            and be sure there's no duplicates */
2956                         while(e) {
2957                                 if (e->priority == tmp->priority) {
2958                                         /* Can't have something exactly the same.  Is this a
2959                                            replacement?  If so, replace, otherwise, bonk. */
2960                                         if (replace) {
2961                                                 if (ep) {
2962                                                         /* We're in the peer list, insert ourselves */
2963                                                         ep->peer = tmp;
2964                                                         tmp->peer = e->peer;
2965                                                 } else if (el) {
2966                                                         /* We're the first extension. Take over e's functions */
2967                                                         el->next = tmp;
2968                                                         tmp->next = e->next;
2969                                                         tmp->peer = e->peer;
2970                                                 } else {
2971                                                         /* We're the very first extension.  */
2972                                                         con->root = tmp;
2973                                                         tmp->next = e->next;
2974                                                         tmp->peer = e->peer;
2975                                                 }
2976                                                 /* Destroy the old one */
2977                                                 e->datad(e->data);
2978                                                 free(e);
2979                                                 ast_pthread_mutex_unlock(&con->lock);
2980                                                 /* And immediately return success. */
2981                                                 LOG;
2982                                                 return 0;
2983                                         } else {
2984                                                 ast_log(LOG_WARNING, "Unable to register extension '%s', priority %d in '%s', already in use\n", tmp->exten, tmp->priority, con->name);
2985                                                 tmp->datad(tmp->data);
2986                                                 free(tmp);
2987                                                 ast_pthread_mutex_unlock(&con->lock);
2988                                                 errno = EEXIST;
2989                                                 return -1;
2990                                         }
2991                                 } else if (e->priority > tmp->priority) {
2992                                         /* Slip ourselves in just before e */
2993                                         if (ep) {
2994                                                 /* Easy enough, we're just in the peer list */
2995                                                 ep->peer = tmp;
2996                                                 tmp->peer = e;
2997                                         } else if (el) {
2998                                                 /* We're the first extension in this peer list */
2999                                                 el->next = tmp;
3000                                                 tmp->next = e->next;
3001                                                 e->next = NULL;
3002                                                 tmp->peer = e;
3003                                         } else {
3004                                                 /* We're the very first extension altogether */
3005                                                 tmp->next = con->root;
3006                                                 /* Con->root must always exist or we couldn't get here */
3007                                                 tmp->peer = con->root->peer;
3008                                                 con->root = tmp;
3009                                         }
3010                                         ast_pthread_mutex_unlock(&con->lock);
3011                                         /* And immediately return success. */
3012                                         LOG;
3013                                         return 0;
3014                                 }
3015                                 ep = e;
3016                                 e = e->peer;
3017                         }
3018                         /* If we make it here, then it's time for us to go at the very end.
3019                            ep *must* be defined or we couldn't have gotten here. */
3020                         ep->peer = tmp;
3021                         ast_pthread_mutex_unlock(&con->lock);