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