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