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