Merge "show applications" from corydon76 (bug #2291)
[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                 strncpy(c->exten, "s", sizeof(c->exten)-1);
1794                 if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) {
1795                         /* JK02: And finally back to default if everything else failed */
1796                         strncpy(c->context, "default", sizeof(c->context)-1);
1797                 }
1798                 c->priority = 1;
1799         }
1800         if (c->cdr)
1801                 ast_cdr_start(c->cdr);
1802         for(;;) {
1803                 pos = 0;
1804                 digit = 0;
1805                 while(ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) {
1806                         memset(exten, 0, sizeof(exten));
1807                         if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->callerid))) {
1808                                 /* Something bad happened, or a hangup has been requested. */
1809                                 if (((res >= '0') && (res <= '9')) || ((res >= 'A') && (res <= 'F')) ||
1810                                         (res == '*') || (res == '#')) {
1811                                         ast_log(LOG_DEBUG, "Oooh, got something to jump out with ('%c')!\n", res);
1812                                         memset(exten, 0, sizeof(exten));
1813                                         pos = 0;
1814                                         exten[pos++] = digit = res;
1815                                         break;
1816                                 }
1817                                 switch(res) {
1818                                 case AST_PBX_KEEPALIVE:
1819                                         if (option_debug)
1820                                                 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
1821                                         else if (option_verbose > 1)
1822                                                 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
1823                                         goto out;
1824                                         break;
1825                                 default:
1826                                         if (option_debug)
1827                                                 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
1828                                         else if (option_verbose > 1)
1829                                                 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
1830                                         if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
1831                                                 c->_softhangup =0;
1832                                                 break;
1833                                         }
1834                                         /* atimeout */
1835                                         if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) {
1836                                                 break;
1837                                         }
1838
1839                                         if (c->cdr) {
1840                                                 ast_cdr_update(c);
1841                                         }
1842                                         goto out;
1843                                 }
1844                         }
1845                         if ((c->_softhangup == AST_SOFTHANGUP_TIMEOUT) && (ast_exists_extension(c,c->context,"T",1,c->callerid))) {
1846                                 strncpy(c->exten,"T",sizeof(c->exten) - 1);
1847                                 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
1848                                 c->whentohangup = 0;
1849                                 c->priority = 0;
1850                                 c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT;
1851                         } else if (c->_softhangup) {
1852                                 ast_log(LOG_DEBUG, "Extension %s, priority %d returned normally even though call was hung up\n",
1853                                         c->exten, c->priority);
1854                                 goto out;
1855                         }
1856                         firstpass = 0;
1857                         c->priority++;
1858                 }
1859                 if (!ast_exists_extension(c, c->context, c->exten, 1, c->callerid)) {
1860                         /* It's not a valid extension anymore */
1861                         if (ast_exists_extension(c, c->context, "i", 1, c->callerid)) {
1862                                 if (option_verbose > 2)
1863                                         ast_verbose(VERBOSE_PREFIX_3 "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, c->name);
1864                                 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", c->exten);
1865                                 strncpy(c->exten, "i", sizeof(c->exten)-1);
1866                                 c->priority = 1;
1867                         } else {
1868                                 ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n",
1869                                         c->name, c->exten, c->context);
1870                                 goto out;
1871                         }
1872                 } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) {
1873                         /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */
1874                         c->_softhangup = 0;
1875                 } else {
1876                         /* Done, wait for an extension */
1877                         if (digit)
1878                                 waittime = c->pbx->dtimeout;
1879                         else
1880                                 waittime = c->pbx->rtimeout;
1881                         while (ast_matchmore_extension(c, c->context, exten, 1, c->callerid)) {
1882                                 /* As long as we're willing to wait, and as long as it's not defined, 
1883                                    keep reading digits until we can't possibly get a right answer anymore.  */
1884                                 digit = ast_waitfordigit(c, waittime * 1000);
1885                                 if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
1886                                         c->_softhangup = 0;
1887                                 } else {
1888                                         if (!digit)
1889                                                 /* No entry */
1890                                                 break;
1891                                         if (digit < 0)
1892                                                 /* Error, maybe a  hangup */
1893                                                 goto out;
1894                                         exten[pos++] = digit;
1895                                         waittime = c->pbx->dtimeout;
1896                                 }
1897                         }
1898                         if (ast_exists_extension(c, c->context, exten, 1, c->callerid)) {
1899                                 /* Prepare the next cycle */
1900                                 strncpy(c->exten, exten, sizeof(c->exten)-1);
1901                                 c->priority = 1;
1902                         } else {
1903                                 /* No such extension */
1904                                 if (!ast_strlen_zero(exten)) {
1905                                         /* An invalid extension */
1906                                         if (ast_exists_extension(c, c->context, "i", 1, c->callerid)) {
1907                                                 if (option_verbose > 2)
1908                                                         ast_verbose( VERBOSE_PREFIX_3 "Invalid extension '%s' in context '%s' on %s\n", exten, c->context, c->name);
1909                                                 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", exten);
1910                                                 strncpy(c->exten, "i", sizeof(c->exten)-1);
1911                                                 c->priority = 1;
1912                                         } else {
1913                                                 ast_log(LOG_WARNING, "Invalid extension '%s', but no rule 'i' in context '%s'\n", exten, c->context);
1914                                                 goto out;
1915                                         }
1916                                 } else {
1917                                         /* A simple timeout */
1918                                         if (ast_exists_extension(c, c->context, "t", 1, c->callerid)) {
1919                                                 if (option_verbose > 2)
1920                                                         ast_verbose( VERBOSE_PREFIX_3 "Timeout on %s\n", c->name);
1921                                                 strncpy(c->exten, "t", sizeof(c->exten)-1);
1922                                                 c->priority = 1;
1923                                         } else {
1924                                                 ast_log(LOG_WARNING, "Timeout, but no rule 't' in context '%s'\n", c->context);
1925                                                 goto out;
1926                                         }
1927                                 }       
1928                         }
1929                         if (c->cdr) {
1930                                 if (option_verbose > 2)
1931                                         ast_verbose(VERBOSE_PREFIX_2 "CDR updated on %s\n",c->name);    
1932                                 ast_cdr_update(c);
1933                     }
1934                 }
1935         }
1936         if (firstpass) 
1937                 ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name);
1938 out:
1939         if ((res != AST_PBX_KEEPALIVE) && ast_exists_extension(c, c->context, "h", 1, c->callerid)) {
1940                 c->exten[0] = 'h';
1941                 c->exten[1] = '\0';
1942                 c->priority = 1;
1943                 while(ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) {
1944                         if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->callerid))) {
1945                                 /* Something bad happened, or a hangup has been requested. */
1946                                 if (option_debug)
1947                                         ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
1948                                 else if (option_verbose > 1)
1949                                         ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
1950                                 break;
1951                         }
1952                         c->priority++;
1953                 }
1954         }
1955
1956         pbx_destroy(c->pbx);
1957         c->pbx = NULL;
1958         if (res != AST_PBX_KEEPALIVE)
1959                 ast_hangup(c);
1960         return 0;
1961 }
1962
1963 static void *pbx_thread(void *data)
1964 {
1965         /* Oh joyeous kernel, we're a new thread, with nothing to do but
1966            answer this channel and get it going.  The setjmp stuff is fairly
1967            confusing, but necessary to get smooth transitions between
1968            the execution of different applications (without the use of
1969            additional threads) */
1970         struct ast_channel *c = data;
1971         ast_pbx_run(c);
1972         pthread_exit(NULL);
1973         return NULL;
1974 }
1975
1976 int ast_pbx_start(struct ast_channel *c)
1977 {
1978         pthread_t t;
1979         pthread_attr_t attr;
1980         if (!c) {
1981                 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
1982                 return -1;
1983         }
1984            
1985         /* Start a new thread, and get something handling this channel. */
1986         pthread_attr_init(&attr);
1987         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1988         if (ast_pthread_create(&t, &attr, pbx_thread, c)) {
1989                 ast_log(LOG_WARNING, "Failed to create new channel thread\n");
1990                 return -1;
1991         }
1992         return 0;
1993 }
1994
1995 /*
1996  * This function locks contexts list by &conlist, search for the right context
1997  * structure, leave context list locked and call ast_context_remove_include2
1998  * which removes include, unlock contexts list and return ...
1999  */
2000 int ast_context_remove_include(char *context, char *include, char *registrar)
2001 {
2002         struct ast_context *c;
2003
2004         if (ast_lock_contexts()) return -1;
2005
2006         /* walk contexts and search for the right one ...*/
2007         c = ast_walk_contexts(NULL);
2008         while (c) {
2009                 /* we found one ... */
2010                 if (!strcmp(ast_get_context_name(c), context)) {
2011                         int ret;
2012                         /* remove include from this context ... */      
2013                         ret = ast_context_remove_include2(c, include, registrar);
2014
2015                         ast_unlock_contexts();
2016
2017                         /* ... return results */
2018                         return ret;
2019                 }
2020                 c = ast_walk_contexts(c);
2021         }
2022
2023         /* we can't find the right one context */
2024         ast_unlock_contexts();
2025         return -1;
2026 }
2027
2028 /*
2029  * When we call this function, &conlock lock must be locked, because when
2030  * we giving *con argument, some process can remove/change this context
2031  * and after that there can be segfault.
2032  *
2033  * This function locks given context, removes include, unlock context and
2034  * return.
2035  */
2036 int ast_context_remove_include2(struct ast_context *con, char *include, char *registrar)
2037 {
2038         struct ast_include *i, *pi = NULL;
2039
2040         if (ast_mutex_lock(&con->lock)) return -1;
2041
2042         /* walk includes */
2043         i = con->includes;
2044         while (i) {
2045                 /* find our include */
2046                 if (!strcmp(i->name, include) && 
2047                         (!registrar || !strcmp(i->registrar, registrar))) {
2048                         /* remove from list */
2049                         if (pi)
2050                                 pi->next = i->next;
2051                         else
2052                                 con->includes = i->next;
2053                         /* free include and return */
2054                         free(i);
2055                         ast_mutex_unlock(&con->lock);
2056                         return 0;
2057                 }
2058                 pi = i;
2059                 i = i->next;
2060         }
2061
2062         /* we can't find the right include */
2063         ast_mutex_unlock(&con->lock);
2064         return -1;
2065 }
2066
2067 /*
2068  * This function locks contexts list by &conlist, search for the rigt context
2069  * structure, leave context list locked and call ast_context_remove_switch2
2070  * which removes switch, unlock contexts list and return ...
2071  */
2072 int ast_context_remove_switch(char *context, char *sw, char *data, char *registrar)
2073 {
2074         struct ast_context *c;
2075
2076         if (ast_lock_contexts()) return -1;
2077
2078         /* walk contexts and search for the right one ...*/
2079         c = ast_walk_contexts(NULL);
2080         while (c) {
2081                 /* we found one ... */
2082                 if (!strcmp(ast_get_context_name(c), context)) {
2083                         int ret;
2084                         /* remove switch from this context ... */       
2085                         ret = ast_context_remove_switch2(c, sw, data, registrar);
2086
2087                         ast_unlock_contexts();
2088
2089                         /* ... return results */
2090                         return ret;
2091                 }
2092                 c = ast_walk_contexts(c);
2093         }
2094
2095         /* we can't find the right one context */
2096         ast_unlock_contexts();
2097         return -1;
2098 }
2099
2100 /*
2101  * When we call this function, &conlock lock must be locked, because when
2102  * we giving *con argument, some process can remove/change this context
2103  * and after that there can be segfault.
2104  *
2105  * This function locks given context, removes switch, unlock context and
2106  * return.
2107  */
2108 int ast_context_remove_switch2(struct ast_context *con, char *sw, char *data, char *registrar)
2109 {
2110         struct ast_sw *i, *pi = NULL;
2111
2112         if (ast_mutex_lock(&con->lock)) return -1;
2113
2114         /* walk switchs */
2115         i = con->alts;
2116         while (i) {
2117                 /* find our switch */
2118                 if (!strcmp(i->name, sw) && !strcmp(i->data, data) && 
2119                         (!registrar || !strcmp(i->registrar, registrar))) {
2120                         /* remove from list */
2121                         if (pi)
2122                                 pi->next = i->next;
2123                         else
2124                                 con->alts = i->next;
2125                         /* free switch and return */
2126                         free(i);
2127                         ast_mutex_unlock(&con->lock);
2128                         return 0;
2129                 }
2130                 pi = i;
2131                 i = i->next;
2132         }
2133
2134         /* we can't find the right switch */
2135         ast_mutex_unlock(&con->lock);
2136         return -1;
2137 }
2138
2139 /*
2140  * This functions lock contexts list, search for the right context,
2141  * call ast_context_remove_extension2, unlock contexts list and return.
2142  * In this function we are using
2143  */
2144 int ast_context_remove_extension(char *context, char *extension, int priority, char *registrar)
2145 {
2146         struct ast_context *c;
2147
2148         if (ast_lock_contexts()) return -1;
2149
2150         /* walk contexts ... */
2151         c = ast_walk_contexts(NULL);
2152         while (c) {
2153                 /* ... search for the right one ... */
2154                 if (!strcmp(ast_get_context_name(c), context)) {
2155                         /* ... remove extension ... */
2156                         int ret = ast_context_remove_extension2(c, extension, priority,
2157                                 registrar);
2158                         /* ... unlock contexts list and return */
2159                         ast_unlock_contexts();
2160                         return ret;
2161                 }
2162                 c = ast_walk_contexts(c);
2163         }
2164
2165         /* we can't find the right context */
2166         ast_unlock_contexts();
2167         return -1;
2168 }
2169
2170 /*
2171  * When do you want to call this function, make sure that &conlock is locked,
2172  * because some process can handle with your *con context before you lock
2173  * it.
2174  *
2175  * This functionc locks given context, search for the right extension and
2176  * fires out all peer in this extensions with given priority. If priority
2177  * is set to 0, all peers are removed. After that, unlock context and
2178  * return.
2179  */
2180 int ast_context_remove_extension2(struct ast_context *con, char *extension, int priority, char *registrar)
2181 {
2182         struct ast_exten *exten, *prev_exten = NULL;
2183
2184         if (ast_mutex_lock(&con->lock)) return -1;
2185
2186         /* go through all extensions in context and search the right one ... */
2187         exten = con->root;
2188         while (exten) {
2189
2190                 /* look for right extension */
2191                 if (!strcmp(exten->exten, extension) &&
2192                         (!registrar || !strcmp(exten->registrar, registrar))) {
2193                         struct ast_exten *peer;
2194
2195                         /* should we free all peers in this extension? (priority == 0)? */
2196                         if (priority == 0) {
2197                                 /* remove this extension from context list */
2198                                 if (prev_exten)
2199                                         prev_exten->next = exten->next;
2200                                 else
2201                                         con->root = exten->next;
2202
2203                                 /* fire out all peers */
2204                                 peer = exten; 
2205                                 while (peer) {
2206                                         exten = peer->peer;
2207                                         
2208                                         if (!peer->priority==PRIORITY_HINT) 
2209                                             ast_remove_hint(peer);
2210
2211                                         peer->datad(peer->data);
2212                                         free(peer);
2213
2214                                         peer = exten;
2215                                 }
2216
2217                                 ast_mutex_unlock(&con->lock);
2218                                 return 0;
2219                         } else {
2220                                 /* remove only extension with exten->priority == priority */
2221                                 struct ast_exten *previous_peer = NULL;
2222
2223                                 peer = exten;
2224                                 while (peer) {
2225                                         /* is this our extension? */
2226                                         if (peer->priority == priority &&
2227                                                 (!registrar || !strcmp(peer->registrar, registrar) )) {
2228                                                 /* we are first priority extension? */
2229                                                 if (!previous_peer) {
2230                                                         /* exists previous extension here? */
2231                                                         if (prev_exten) {
2232                                                                 /* yes, so we must change next pointer in
2233                                                                  * previous connection to next peer
2234                                                                  */
2235                                                                 if (peer->peer) {
2236                                                                         prev_exten->next = peer->peer;
2237                                                                         peer->peer->next = exten->next;
2238                                                                 } else
2239                                                                         prev_exten->next = exten->next;
2240                                                         } else {
2241                                                                 /* no previous extension, we are first
2242                                                                  * extension, so change con->root ...
2243                                                                  */
2244                                                                 if (peer->peer)
2245                                                                         con->root = peer->peer;
2246                                                                 else
2247                                                                         con->root = exten->next; 
2248                                                         }
2249                                                 } else {
2250                                                         /* we are not first priority in extension */
2251                                                         previous_peer->peer = peer->peer;
2252                                                 }
2253
2254                                                 /* now, free whole priority extension */
2255                                                 if (peer->priority==PRIORITY_HINT)
2256                                                     ast_remove_hint(peer);
2257                                                 peer->datad(peer->data);
2258                                                 free(peer);
2259
2260                                                 ast_mutex_unlock(&con->lock);
2261                                                 return 0;
2262                                         } else {
2263                                                 /* this is not right extension, skip to next peer */
2264                                                 previous_peer = peer;
2265                                                 peer = peer->peer;
2266                                         }
2267                                 }
2268
2269                                 ast_mutex_unlock(&con->lock);
2270                                 return -1;
2271                         }
2272                 }
2273
2274                 prev_exten = exten;
2275                 exten = exten->next;
2276         }
2277
2278         /* we can't find right extension */
2279         ast_mutex_unlock(&con->lock);
2280         return -1;
2281 }
2282
2283
2284 int ast_register_application(char *app, int (*execute)(struct ast_channel *, void *), char *synopsis, char *description)
2285 {
2286         struct ast_app *tmp, *prev, *cur;
2287         char tmps[80];
2288         if (ast_mutex_lock(&applock)) {
2289                 ast_log(LOG_ERROR, "Unable to lock application list\n");
2290                 return -1;
2291         }
2292         tmp = apps;
2293         while(tmp) {
2294                 if (!strcasecmp(app, tmp->name)) {
2295                         ast_log(LOG_WARNING, "Already have an application '%s'\n", app);
2296                         ast_mutex_unlock(&applock);
2297                         return -1;
2298                 }
2299                 tmp = tmp->next;
2300         }
2301         tmp = malloc(sizeof(struct ast_app));
2302         if (tmp) {
2303                 memset(tmp, 0, sizeof(struct ast_app));
2304                 strncpy(tmp->name, app, sizeof(tmp->name)-1);
2305                 tmp->execute = execute;
2306                 tmp->synopsis = synopsis;
2307                 tmp->description = description;
2308                 /* Store in alphabetical order */
2309                 cur = apps;
2310                 prev = NULL;
2311                 while(cur) {
2312                         if (strcasecmp(tmp->name, cur->name) < 0)
2313                                 break;
2314                         prev = cur;
2315                         cur = cur->next;
2316                 }
2317                 if (prev) {
2318                         tmp->next = prev->next;
2319                         prev->next = tmp;
2320                 } else {
2321                         tmp->next = apps;
2322                         apps = tmp;
2323                 }
2324         } else {
2325                 ast_log(LOG_ERROR, "Out of memory\n");
2326                 ast_mutex_unlock(&applock);
2327                 return -1;
2328         }
2329         if (option_verbose > 1)
2330                 ast_verbose( VERBOSE_PREFIX_2 "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps)));
2331         ast_mutex_unlock(&applock);
2332         return 0;
2333 }
2334
2335 int ast_register_switch(struct ast_switch *sw)
2336 {
2337         struct ast_switch *tmp, *prev=NULL;
2338         if (ast_mutex_lock(&switchlock)) {
2339                 ast_log(LOG_ERROR, "Unable to lock switch lock\n");
2340                 return -1;
2341         }
2342         tmp = switches;
2343         while(tmp) {
2344                 if (!strcasecmp(tmp->name, sw->name))
2345                         break;
2346                 prev = tmp;
2347                 tmp = tmp->next;
2348         }
2349         if (tmp) {      
2350                 ast_mutex_unlock(&switchlock);
2351                 ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name);
2352                 return -1;
2353         }
2354         sw->next = NULL;
2355         if (prev) 
2356                 prev->next = sw;
2357         else
2358                 switches = sw;
2359         ast_mutex_unlock(&switchlock);
2360         return 0;
2361 }
2362
2363 void ast_unregister_switch(struct ast_switch *sw)
2364 {
2365         struct ast_switch *tmp, *prev=NULL;
2366         if (ast_mutex_lock(&switchlock)) {
2367                 ast_log(LOG_ERROR, "Unable to lock switch lock\n");
2368                 return;
2369         }
2370         tmp = switches;
2371         while(tmp) {
2372                 if (tmp == sw) {
2373                         if (prev)
2374                                 prev->next = tmp->next;
2375                         else
2376                                 switches = tmp->next;
2377                         tmp->next = NULL;
2378                         break;                  
2379                 }
2380                 prev = tmp;
2381                 tmp = tmp->next;
2382         }
2383         ast_mutex_unlock(&switchlock);
2384 }
2385
2386 /*
2387  * Help for CLI commands ...
2388  */
2389 static char show_application_help[] = 
2390 "Usage: show application <application> [<application> [<application> [...]]]\n"
2391 "       Describes a particular application.\n";
2392
2393 static char show_applications_help[] =
2394 "Usage: show applications [{like|describing} <text>]\n"
2395 "       List applications which are currently available.\n"
2396 "       If 'like', <text> will be a substring of the app name\n"
2397 "       If 'describing', <text> will be a substring of the description\n";
2398
2399 static char show_dialplan_help[] =
2400 "Usage: show dialplan [exten@][context]\n"
2401 "       Show dialplan\n";
2402
2403 static char show_switches_help[] = 
2404 "Usage: show switches\n"
2405 "       Show registered switches\n";
2406
2407 /*
2408  * IMPLEMENTATION OF CLI FUNCTIONS IS IN THE SAME ORDER AS COMMANDS HELPS
2409  *
2410  */
2411
2412 /*
2413  * 'show application' CLI command implementation functions ...
2414  */
2415
2416 /*
2417  * There is a possibility to show informations about more than one
2418  * application at one time. You can type 'show application Dial Echo' and
2419  * you will see informations about these two applications ...
2420  */
2421 static char *complete_show_application(char *line, char *word,
2422         int pos, int state)
2423 {
2424         struct ast_app *a;
2425         int which = 0;
2426
2427         /* try to lock applications list ... */
2428         if (ast_mutex_lock(&applock)) {
2429                 ast_log(LOG_ERROR, "Unable to lock application list\n");
2430                 return NULL;
2431         }
2432
2433         /* ... walk all applications ... */
2434         a = apps; 
2435         while (a) {
2436                 /* ... check if word matches this application ... */
2437                 if (!strncasecmp(word, a->name, strlen(word))) {
2438                         /* ... if this is right app serve it ... */
2439                         if (++which > state) {
2440                                 char *ret = strdup(a->name);
2441                                 ast_mutex_unlock(&applock);
2442                                 return ret;
2443                         }
2444                 }
2445                 a = a->next; 
2446         }
2447
2448         /* no application match */
2449         ast_mutex_unlock(&applock);
2450         return NULL; 
2451 }
2452
2453 static int handle_show_application(int fd, int argc, char *argv[])
2454 {
2455         struct ast_app *a;
2456         int app, no_registered_app = 1;
2457
2458         if (argc < 3) return RESULT_SHOWUSAGE;
2459
2460         /* try to lock applications list ... */
2461         if (ast_mutex_lock(&applock)) {
2462                 ast_log(LOG_ERROR, "Unable to lock application list\n");
2463                 return -1;
2464         }
2465
2466         /* ... go through all applications ... */
2467         a = apps; 
2468         while (a) {
2469                 /* ... compare this application name with all arguments given
2470                  * to 'show application' command ... */
2471                 for (app = 2; app < argc; app++) {
2472                         if (!strcasecmp(a->name, argv[app])) {
2473                                 /* Maximum number of characters added by terminal coloring is 22 */
2474                                 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40];
2475                                 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL;
2476                                 int synopsis_size, description_size;
2477
2478                                 no_registered_app = 0;
2479
2480                                 if (a->synopsis)
2481                                         synopsis_size = strlen(a->synopsis) + 23;
2482                                 else
2483                                         synopsis_size = strlen("Not available") + 23;
2484                                 synopsis = alloca(synopsis_size);
2485
2486                                 if (a->description)
2487                                         description_size = strlen(a->description) + 23;
2488                                 else
2489                                         description_size = strlen("Not available") + 23;
2490                                 description = alloca(description_size);
2491
2492                                 if (synopsis && description) {
2493                                         snprintf(info, 64 + AST_MAX_APP, "\n  -= Info about application '%s' =- \n\n", a->name);
2494                                         term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22);
2495                                         term_color(syntitle, "[Synopsis]:\n", COLOR_MAGENTA, 0, 40);
2496                                         term_color(destitle, "[Description]:\n", COLOR_MAGENTA, 0, 40);
2497                                         term_color(synopsis,
2498                                                                         a->synopsis ? a->synopsis : "Not available",
2499                                                                         COLOR_CYAN, 0, synopsis_size);
2500                                         term_color(description,
2501                                                                         a->description ? a->description : "Not available",
2502                                                                         COLOR_CYAN, 0, description_size);
2503
2504                                         ast_cli(fd,"%s%s%s\n\n%s%s\n", infotitle, syntitle, synopsis, destitle, description);
2505                                 } else {
2506                                         /* ... one of our applications, show info ...*/
2507                                         ast_cli(fd,"\n  -= Info about application '%s' =- \n\n"
2508                                                 "[Synopsis]:\n  %s\n\n"
2509                                                 "[Description]:\n%s\n",
2510                                                 a->name,
2511                                                 a->synopsis ? a->synopsis : "Not available",
2512                                                 a->description ? a->description : "Not available");
2513                                 }
2514                         }
2515                 }
2516                 a = a->next; 
2517         }
2518
2519         ast_mutex_unlock(&applock);
2520
2521         /* we found at least one app? no? */
2522         if (no_registered_app) {
2523                 ast_cli(fd, "Your application(s) is (are) not registered\n");
2524                 return RESULT_FAILURE;
2525         }
2526
2527         return RESULT_SUCCESS;
2528 }
2529
2530 static int handle_show_switches(int fd, int argc, char *argv[])
2531 {
2532         struct ast_switch *sw;
2533         if (!switches) {
2534                 ast_cli(fd, "There are no registered alternative switches\n");
2535                 return RESULT_SUCCESS;
2536         }
2537         /* ... we have applications ... */
2538         ast_cli(fd, "\n    -= Registered Asterisk Alternative Switches =-\n");
2539         if (ast_mutex_lock(&switchlock)) {
2540                 ast_log(LOG_ERROR, "Unable to lock switches\n");
2541                 return -1;
2542         }
2543         sw = switches;
2544         while (sw) {
2545                 ast_cli(fd, "%s: %s\n", sw->name, sw->description);
2546                 sw = sw->next;
2547         }
2548         ast_mutex_unlock(&switchlock);
2549         return RESULT_SUCCESS;
2550 }
2551
2552 /*
2553  * 'show applications' CLI command implementation functions ...
2554  */
2555 static int handle_show_applications(int fd, int argc, char *argv[])
2556 {
2557         struct ast_app *a;
2558         int like=0, describing=0;
2559
2560         /* try to lock applications list ... */
2561         if (ast_mutex_lock(&applock)) {
2562                 ast_log(LOG_ERROR, "Unable to lock application list\n");
2563                 return -1;
2564         }
2565
2566         /* ... have we got at least one application (first)? no? */
2567         if (!apps) {
2568                 ast_cli(fd, "There are no registered applications\n");
2569                 ast_mutex_unlock(&applock);
2570                 return -1;
2571         }
2572
2573         /* show applications like <keyword> */
2574         if ((argc == 4) && (!strcmp(argv[2], "like"))) {
2575                 like = 1;
2576         } else if ((argc > 3) && (!strcmp(argv[2], "describing"))) {
2577                 describing = 1;
2578         }
2579
2580         /* show applications describing <keyword1> [<keyword2>] [...] */
2581         if ((!like) && (!describing)) {
2582                 ast_cli(fd, "    -= Registered Asterisk Applications =-\n");
2583         } else {
2584                 ast_cli(fd, "    -= Matching Asterisk Applications =-\n");
2585         }
2586
2587         /* ... go through all applications ... */
2588         for (a = apps; a; a = a->next) {
2589                 /* ... show informations about applications ... */
2590                 int printapp=0;
2591
2592                 if (like) {
2593                         if (ast_strcasestr(a->name, argv[3])) {
2594                                 printapp = 1;
2595                         }
2596                 } else if (describing) {
2597                         if (a->description) {
2598                                 /* Match all words on command line */
2599                                 int i;
2600                                 printapp = 1;
2601                                 for (i=3;i<argc;i++) {
2602                                         if (! ast_strcasestr(a->description, argv[i])) {
2603                                                 printapp = 0;
2604                                         }
2605                                 }
2606                         }
2607                 } else {
2608                         printapp = 1;
2609                 }
2610
2611                 if (printapp) {
2612                         ast_cli(fd,"  %20s: %s\n", a->name, a->synopsis ? a->synopsis : "<Synopsis not available>");
2613                 }
2614         }
2615
2616         /* ... unlock and return */
2617         ast_mutex_unlock(&applock);
2618
2619         return RESULT_SUCCESS;
2620 }
2621
2622 static char *complete_show_applications(char *line, char *word, int pos, int state)
2623 {
2624         if (pos == 2) {
2625                 if (ast_strlen_zero(word)) {
2626                         switch (state) {
2627                         case 0:
2628                                 return strdup("like");
2629                         case 1:
2630                                 return strdup("describing");
2631                         default:
2632                                 return NULL;
2633                         }
2634                 } else if (! strncasecmp(word, "like", strlen(word))) {
2635                         if (state == 0) {
2636                                 return strdup("like");
2637                         } else {
2638                                 return NULL;
2639                         }
2640                 } else if (! strncasecmp(word, "describing", strlen(word))) {
2641                         if (state == 0) {
2642                                 return strdup("describing");
2643                         } else {
2644                                 return NULL;
2645                         }
2646                 }
2647         }
2648         return NULL;
2649 }
2650
2651 /*
2652  * 'show dialplan' CLI command implementation functions ...
2653  */
2654 static char *complete_show_dialplan_context(char *line, char *word, int pos,
2655         int state)
2656 {
2657         struct ast_context *c;
2658         int which = 0;
2659
2660         /* we are do completion of [exten@]context on second position only */
2661         if (pos != 2) return NULL;
2662
2663         /* try to lock contexts list ... */
2664         if (ast_lock_contexts()) {
2665                 ast_log(LOG_ERROR, "Unable to lock context list\n");
2666                 return NULL;
2667         }
2668
2669         /* ... walk through all contexts ... */
2670         c = ast_walk_contexts(NULL);
2671         while(c) {
2672                 /* ... word matches context name? yes? ... */
2673                 if (!strncasecmp(word, ast_get_context_name(c), strlen(word))) {
2674                         /* ... for serve? ... */
2675                         if (++which > state) {
2676                                 /* ... yes, serve this context name ... */
2677                                 char *ret = strdup(ast_get_context_name(c));
2678                                 ast_unlock_contexts();
2679                                 return ret;
2680                         }
2681                 }
2682                 c = ast_walk_contexts(c);
2683         }
2684
2685         /* ... unlock and return */
2686         ast_unlock_contexts();
2687         return NULL;
2688 }
2689
2690 static int handle_show_dialplan(int fd, int argc, char *argv[])
2691 {
2692         struct ast_context *c;
2693         char *exten = NULL, *context = NULL;
2694         int context_existence = 0, extension_existence = 0;
2695
2696         if (argc != 3 && argc != 2) return -1;
2697
2698         /* we obtain [exten@]context? if yes, split them ... */
2699         if (argc == 3) {
2700                 char *splitter = argv[2];
2701                 /* is there a '@' character? */
2702                 if (strchr(argv[2], '@')) {
2703                         /* yes, split into exten & context ... */
2704                         exten   = strsep(&splitter, "@");
2705                         context = splitter;
2706
2707                         /* check for length and change to NULL if ast_strlen_zero() */
2708                         if (ast_strlen_zero(exten))   exten = NULL;
2709                         if (ast_strlen_zero(context)) context = NULL;
2710                 } else
2711                 {
2712                         /* no '@' char, only context given */
2713                         context = argv[2];
2714                         if (ast_strlen_zero(context)) context = NULL;
2715                 }
2716         }
2717
2718         /* try to lock contexts */
2719         if (ast_lock_contexts()) {
2720                 ast_log(LOG_WARNING, "Failed to lock contexts list\n");
2721                 return RESULT_FAILURE;
2722         }
2723
2724         /* walk all contexts ... */
2725         c = ast_walk_contexts(NULL);
2726         while (c) {
2727                 /* show this context? */
2728                 if (!context ||
2729                         !strcmp(ast_get_context_name(c), context)) {
2730                         context_existence = 1;
2731
2732                         /* try to lock context before walking in ... */
2733                         if (!ast_lock_context(c)) {
2734                                 struct ast_exten *e;
2735                                 struct ast_include *i;
2736                                 struct ast_ignorepat *ip;
2737                                 struct ast_sw *sw;
2738                                 char buf[256], buf2[256];
2739                                 int context_info_printed = 0;
2740
2741                                 /* are we looking for exten too? if yes, we print context
2742                                  * if we our extension only
2743                                  */
2744                                 if (!exten) {
2745                                         ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
2746                                                 ast_get_context_name(c), ast_get_context_registrar(c));
2747                                         context_info_printed = 1;
2748                                 }
2749
2750                                 /* walk extensions ... */
2751                                 e = ast_walk_context_extensions(c, NULL);
2752                                 while (e) {
2753                                         struct ast_exten *p;
2754
2755                                         /* looking for extension? is this our extension? */
2756                                         if (exten &&
2757                                                 strcmp(ast_get_extension_name(e), exten))
2758                                         {
2759                                                 /* we are looking for extension and it's not our
2760                                                  * extension, so skip to next extension */
2761                                                 e = ast_walk_context_extensions(c, e);
2762                                                 continue;
2763                                         }
2764
2765                                         extension_existence = 1;
2766
2767                                         /* may we print context info? */        
2768                                         if (!context_info_printed) {
2769                                                 ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
2770                                                         ast_get_context_name(c),
2771                                                         ast_get_context_registrar(c));
2772                                                 context_info_printed = 1;
2773                                         }
2774
2775                                         /* write extension name and first peer */       
2776                                         bzero(buf, sizeof(buf));                
2777                                         snprintf(buf, sizeof(buf), "'%s' =>",
2778                                                 ast_get_extension_name(e));
2779
2780                                         snprintf(buf2, sizeof(buf2),
2781                                                 "%d. %s(%s)",
2782                                                 ast_get_extension_priority(e),
2783                                                 ast_get_extension_app(e),
2784                                                 (char *)ast_get_extension_app_data(e));
2785
2786                                         ast_cli(fd, "  %-17s %-45s [%s]\n", buf, buf2,
2787                                                 ast_get_extension_registrar(e));
2788
2789                                         /* walk next extension peers */
2790                                         p = ast_walk_extension_priorities(e, e);
2791                                         while (p) {
2792                                                 bzero((void *)buf2, sizeof(buf2));
2793
2794                                                 snprintf(buf2, sizeof(buf2),
2795                                                         "%d. %s(%s)",
2796                                                         ast_get_extension_priority(p),
2797                                                         ast_get_extension_app(p),
2798                                                         (char *)ast_get_extension_app_data(p));
2799
2800                                                 ast_cli(fd,"  %-17s %-45s [%s]\n",
2801                                                         "", buf2,
2802                                                         ast_get_extension_registrar(p));        
2803
2804                                                 p = ast_walk_extension_priorities(e, p);
2805                                         }
2806                                         e = ast_walk_context_extensions(c, e);
2807                                 }
2808
2809                                 /* include & ignorepat we all printing if we are not
2810                                  * looking for exact extension
2811                                  */
2812                                 if (!exten) {
2813                                         if (ast_walk_context_extensions(c, NULL))
2814                                                 ast_cli(fd, "\n");
2815
2816                                         /* walk included and write info ... */
2817                                         i = ast_walk_context_includes(c, NULL);
2818                                         while (i) {
2819                                                 bzero(buf, sizeof(buf));
2820                                                 snprintf(buf, sizeof(buf), "'%s'",
2821                                                         ast_get_include_name(i));
2822                                                 ast_cli(fd, "  Include =>        %-45s [%s]\n",
2823                                                         buf, ast_get_include_registrar(i));
2824                                                 i = ast_walk_context_includes(c, i);
2825                                         }
2826
2827                                         /* walk ignore patterns and write info ... */
2828                                         ip = ast_walk_context_ignorepats(c, NULL);
2829                                         while (ip) {
2830                                                 bzero(buf, sizeof(buf));
2831                                                 snprintf(buf, sizeof(buf), "'%s'",
2832                                                         ast_get_ignorepat_name(ip));
2833                                                 ast_cli(fd, "  Ignore pattern => %-45s [%s]\n",
2834                                                         buf, ast_get_ignorepat_registrar(ip));  
2835                                                 ip = ast_walk_context_ignorepats(c, ip);
2836                                         }
2837                                         sw = ast_walk_context_switches(c, NULL);
2838                                         while(sw) {
2839                                                 bzero(buf, sizeof(buf));
2840                                                 snprintf(buf, sizeof(buf), "'%s/%s'",
2841                                                         ast_get_switch_name(sw),
2842                                                         ast_get_switch_data(sw));
2843                                                 ast_cli(fd, "  Alt. Switch =>    %-45s [%s]\n",
2844                                                         buf, ast_get_switch_registrar(sw));     
2845                                                 sw = ast_walk_context_switches(c, sw);
2846                                         }
2847                                 }
2848         
2849                                 ast_unlock_context(c);
2850
2851                                 /* if we print something in context, make an empty line */
2852                                 if (context_info_printed) ast_cli(fd, "\n");
2853                         }
2854                 }
2855                 c = ast_walk_contexts(c);
2856         }
2857         ast_unlock_contexts();
2858
2859         /* check for input failure and throw some error messages */
2860         if (context && !context_existence) {
2861                 ast_cli(fd, "There is no existence of '%s' context\n",
2862                         context);
2863                 return RESULT_FAILURE;
2864         }
2865
2866         if (exten && !extension_existence) {
2867                 if (context)
2868                         ast_cli(fd, "There is no existence of %s@%s extension\n",
2869                                 exten, context);
2870                 else
2871                         ast_cli(fd,
2872                                 "There is no existence of '%s' extension in all contexts\n",
2873                                 exten);
2874                 return RESULT_FAILURE;
2875         }
2876
2877         /* everything ok */
2878         return RESULT_SUCCESS;
2879 }
2880
2881 /*
2882  * CLI entries for upper commands ...
2883  */
2884 static struct ast_cli_entry show_applications_cli = 
2885         { { "show", "applications", NULL }, 
2886         handle_show_applications, "Shows registered applications",
2887         show_applications_help, complete_show_applications };
2888
2889 static struct ast_cli_entry show_application_cli =
2890         { { "show", "application", NULL }, 
2891         handle_show_application, "Describe a specific application",
2892         show_application_help, complete_show_application };
2893
2894 static struct ast_cli_entry show_dialplan_cli =
2895         { { "show", "dialplan", NULL },
2896                 handle_show_dialplan, "Show dialplan",
2897                 show_dialplan_help, complete_show_dialplan_context };
2898
2899 static struct ast_cli_entry show_switches_cli =
2900         { { "show", "switches", NULL },
2901                 handle_show_switches, "Show alternative switches",
2902                 show_switches_help, NULL };
2903
2904 int ast_unregister_application(char *app) {
2905         struct ast_app *tmp, *tmpl = NULL;
2906         if (ast_mutex_lock(&applock)) {
2907                 ast_log(LOG_ERROR, "Unable to lock application list\n");
2908                 return -1;
2909         }
2910         tmp = apps;
2911         while(tmp) {
2912                 if (!strcasecmp(app, tmp->name)) {
2913                         if (tmpl)
2914                                 tmpl->next = tmp->next;
2915                         else
2916                                 apps = tmp->next;
2917                         if (option_verbose > 1)
2918                                 ast_verbose( VERBOSE_PREFIX_2 "Unregistered application '%s'\n", tmp->name);
2919                         free(tmp);
2920                         ast_mutex_unlock(&applock);
2921                         return 0;
2922                 }
2923                 tmpl = tmp;
2924                 tmp = tmp->next;
2925         }
2926         ast_mutex_unlock(&applock);
2927         return -1;
2928 }
2929
2930 struct ast_context *ast_context_create(struct ast_context **extcontexts, char *name, char *registrar)
2931 {
2932         struct ast_context *tmp, **local_contexts;
2933         if (!extcontexts) {
2934                 local_contexts = &contexts;
2935                 ast_mutex_lock(&conlock);
2936         } else
2937                 local_contexts = extcontexts;
2938
2939         tmp = *local_contexts;
2940         while(tmp) {
2941                 if (!strcasecmp(tmp->name, name)) {
2942                         ast_mutex_unlock(&conlock);
2943                         ast_log(LOG_WARNING, "Tried to register context '%s', already in use\n", name);
2944                         if (!extcontexts)
2945                                 ast_mutex_unlock(&conlock);
2946                         return NULL;
2947                 }
2948                 tmp = tmp->next;
2949         }
2950         tmp = malloc(sizeof(struct ast_context));
2951         if (tmp) {
2952                 memset(tmp, 0, sizeof(struct ast_context));
2953                 ast_mutex_init(&tmp->lock);
2954                 strncpy(tmp->name, name, sizeof(tmp->name)-1);
2955                 tmp->root = NULL;
2956                 tmp->registrar = registrar;
2957                 tmp->next = *local_contexts;
2958                 tmp->includes = NULL;
2959                 tmp->ignorepats = NULL;
2960                 *local_contexts = tmp;
2961                 if (option_debug)
2962                         ast_log(LOG_DEBUG, "Registered context '%s'\n", tmp->name);
2963                 else if (option_verbose > 2)
2964                         ast_verbose( VERBOSE_PREFIX_3 "Registered extension context '%s'\n", tmp->name);
2965         } else
2966                 ast_log(LOG_ERROR, "Out of memory\n");
2967         
2968         if (!extcontexts)
2969                 ast_mutex_unlock(&conlock);
2970         return tmp;
2971 }
2972
2973 void __ast_context_destroy(struct ast_context *con, char *registrar);
2974
2975 void ast_merge_contexts_and_delete(struct ast_context **extcontexts, char *registrar) {
2976         struct ast_context *tmp, *lasttmp = NULL;
2977         tmp = *extcontexts;
2978         ast_mutex_lock(&conlock);
2979         if (registrar) {
2980                 __ast_context_destroy(NULL,registrar);
2981                 while (tmp) {
2982                         lasttmp = tmp;
2983                         tmp = tmp->next;
2984                 }
2985         } else {
2986                 while (tmp) {
2987                         __ast_context_destroy(tmp,tmp->registrar);
2988                         lasttmp = tmp;
2989                         tmp = tmp->next;
2990                 }
2991         }
2992         if (lasttmp) {
2993                 lasttmp->next = contexts;
2994                 contexts = *extcontexts;
2995                 *extcontexts = NULL;
2996         } else 
2997                 ast_log(LOG_WARNING, "Requested contexts didn't get merged\n");
2998         ast_mutex_unlock(&conlock);
2999         return; 
3000 }
3001
3002 /*
3003  * errno values
3004  *  EBUSY  - can't lock