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