Wed Mar 12 07:00:01 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                                                 if (!(*cp4)) {
758                                                         int len=strlen(cp3);
759                                                         int len_env=strlen("ENV(");
760                                                         if (len > (len_env+1) && !strncasecmp(cp3,"ENV(",len_env) && !strcmp(cp3+len-1,")")) {
761                                                                 cp3[len-1]='\0';
762                                                                 *cp4=getenv(cp3+len_env);
763                                                         }
764                                                 }
765                                         }
766 }
767
768 static void pbx_substitute_variables_helper(struct ast_channel *c,char *cp1,char **ecp2,int count)
769 {
770         char *cp4,*cp2;
771         char *tmp,*wherearewe,*finish,*ltmp,*lval,*nextvar;
772         int length,variables=0;
773
774         wherearewe=tmp=cp1;
775         cp2=*ecp2;
776         *cp2='\0';
777         do {
778                 char *start,*start2;
779                 if ((tmp=strstr(wherearewe,"${"))) {
780                         variables++;
781                         length=(int)(tmp-wherearewe);
782                         strncat(cp2,wherearewe,length);
783                         wherearewe=tmp;
784                         
785                         ltmp=malloc(sizeof(char)*256);
786                         start=start2=tmp+1;
787                         do {
788                                 if (variables==0) {
789                                         nextvar=strstr(start2,"${");
790                                         if (nextvar) {
791                                                 if ((int)(finish-nextvar)>0) {
792                                                         variables++;
793                                                         start2=nextvar+1;
794                                                 } else break;
795                                         } else break;
796                                 }
797                                 finish=strchr(start,'}');
798                                 if (finish) {
799                                         variables--;
800                                         start=finish+1;
801                                 } else {
802                                         if (variables>0) {
803                                                 ast_log(LOG_NOTICE, "Error in extension logic\n");
804                                                 cp2[0]='\0';
805                                                 return;
806                                         }
807                                         break;
808                                 }
809                         } while (1);
810                         
811                         length=(int)(finish-tmp);
812                         wherearewe+=length+1;
813                         lval=strndup(tmp+2,length-2);
814                         pbx_substitute_variables_helper(c,lval,&ltmp,count+1);
815                         free(lval);
816                         if (ltmp) {
817                                 length=strlen(ltmp);
818                                 strncat(cp2,ltmp,length);
819                         }
820                 } else {
821                         if (wherearewe!=cp1) {
822                                 if (*wherearewe) {
823                                         length=strlen(wherearewe);
824                                         strncat(cp2,wherearewe,length);
825                                 }
826                                 strcat(cp2,"\0");
827                                 
828                                 cp1=cp2;
829                         }
830                         if (count) {                    
831                                 pbx_substitute_variables_temp(c,cp1,&cp4);
832                                 if (cp4) {
833                                         /* reset output variable so we could store the result */
834                                         *cp2='\0';
835                                         length=strlen(cp4);
836                                         strncat(cp2,cp4,length);
837                                 } else
838                                         cp2[0]='\0';
839                         }
840                         break;
841                 }
842         } while(1);
843 }
844
845 static void *pbx_substitute_variables(struct ast_channel *c, struct ast_exten *e) {
846         char *cp1,*cp3,*cp4,*cp5;
847         char *cp2;
848         char c1,c2;
849         int m,mve,origlen,quoted,dolsign,docopy;
850         
851         /* No variables or expressions in e->data, so why scan it? */
852         if (!strstr(e->data,"${") && !strstr(e->data,"$[")) {
853                 return strndup(e->data,strlen(e->data)+1);
854         }
855         
856         cp1=e->data;
857         cp2=malloc(sizeof(char)*256);
858         pbx_substitute_variables_helper(c,cp1,(char **)&cp2,0);
859
860         /* Second stage, expression evaluation */
861         if ((strstr(cp2,"$[")==NULL)) {
862                 /* No expressions in cp2, return it */
863                 return(cp2);
864         }
865         /* else, do expression evaluation */
866         
867         dolsign=0;
868         docopy=1;
869         origlen=strlen(cp2)+1;
870         
871         cp5=malloc(origlen);
872         memset(cp5,0,origlen);
873         cp4=NULL;
874         cp1=cp2;
875         quoted=0;
876         
877         do {
878                 c1=*cp1;
879                 mve=0;
880                 switch (c1) {
881                         case '$' : 
882                                 dolsign=1;
883                                 docopy=0;
884                                 break;
885                         case '[' :
886                                 if (dolsign==0) {
887                                         docopy=1;
888                                         dolsign=0;
889                                         break;
890                                 }
891                                 dolsign=0;
892                                 docopy=0;
893                                 m=0;
894                                 mve=1;
895                                 cp1++;
896                                 
897                                 while (((c2=*(cp1+m))!=']') && (c2!='\0')) {
898                                         m++;
899                                 }
900                                 cp3=malloc(m+2);
901                                 strncpy(cp3,cp1,m);
902                                 cp3[m]='\0';
903                                 cp1+=m;
904                                 /* Now we have the expression to evaluate on cp3 */
905                                 cp4=ast_expr(cp3);
906                                 free(cp3);
907                                 break;
908                         default :
909                                 if (dolsign==1) {
910                                         strncat((char *)cp5,"$",1);
911                                 }
912                                 dolsign=0;
913                                 docopy=1;
914                                 mve=0;
915                                 break;
916                 }
917                 if (cp1!='\0') {
918                         if (mve==0) {
919                                 if (docopy==1) {
920                                         strncat((char *)cp5,&c1,1);
921                                 }
922                         } else {
923                                 if (cp4!=NULL) {
924                                         cp5=realloc(cp5,origlen+strlen(cp4)+1);
925                                         strncat((char *)cp5,cp4,strlen(cp4));
926                                         free(cp4);
927                                 } else {
928                                         ast_log(LOG_WARNING,"mve!=0 and cp4=NULL, something gone astray\n");
929                                 }
930                         }
931                 }
932                         
933         } while (*cp1++!='\0');
934         free(cp2);
935         return(cp5);
936 }
937                                 
938                         
939                                                                 
940
941 static int pbx_extension_helper(struct ast_channel *c, char *context, char *exten, int priority, char *callerid, int action) 
942 {
943         struct ast_exten *e;
944         struct ast_app *app;
945         struct ast_switch *sw;
946         char *data;
947         char *newdata;
948         int newstack = 0;
949         int res;
950         int status = 0;
951         char *incstack[AST_PBX_MAX_STACK];
952         int stacklen = 0;
953         char tmp[80];
954         char tmp2[80];
955         char tmp3[256];
956         if (ast_pthread_mutex_lock(&conlock)) {
957                 ast_log(LOG_WARNING, "Unable to obtain lock\n");
958                 if ((action == HELPER_EXISTS) || (action == HELPER_CANMATCH) || (action == HELPER_MATCHMORE))
959                         return 0;
960                 else
961                         return -1;
962         }
963         e = pbx_find_extension(c, context, exten, priority, callerid, action, incstack, &stacklen, &status, &sw, &data);
964         if (e) {
965                 switch(action) {
966                 case HELPER_CANMATCH:
967                         pthread_mutex_unlock(&conlock);
968                         return -1;
969                 case HELPER_EXISTS:
970                         pthread_mutex_unlock(&conlock);
971                         return -1;
972                 case HELPER_MATCHMORE:
973                         pthread_mutex_unlock(&conlock);
974                         return -1;
975                 case HELPER_SPAWN:
976                         newstack++;
977                         /* Fall through */
978                 case HELPER_EXEC:
979                         app = pbx_findapp(e->app);
980                         pthread_mutex_unlock(&conlock);
981                         if (app) {
982                                 strncpy(c->context, context, sizeof(c->context-1));
983                                 strncpy(c->exten, exten, sizeof(c->exten)-1);
984                                 c->priority = priority;
985                                 newdata=pbx_substitute_variables(c,e);
986                                 if (option_debug)
987                                                 ast_log(LOG_DEBUG, "Launching '%s'\n", app->name);
988                                 else if (option_verbose > 2)
989                                                 ast_verbose( VERBOSE_PREFIX_3 "Executing %s(\"%s\", \"%s\") %s\n", 
990                                                                 term_color(tmp, app->name, COLOR_BRCYAN, 0, sizeof(tmp)),
991                                                                 term_color(tmp2, c->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)),
992                                                                 term_color(tmp3, (newdata ? (char *)newdata : NULL), COLOR_BRMAGENTA, 0, sizeof(tmp3)),
993                                                                 (newstack ? "in new stack" : "in same stack"));
994                                 res = pbx_exec(c, app, newdata, newstack);
995                                 free(newdata);
996                                 return res;
997                         } else {
998                                 ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority);
999                                 return -1;
1000                         }
1001                 default:
1002                         ast_log(LOG_WARNING, "Huh (%d)?\n", action);                    return -1;
1003                 }
1004         } else if (sw) {
1005                 switch(action) {
1006                 case HELPER_CANMATCH:
1007                         pthread_mutex_unlock(&conlock);
1008                         return -1;
1009                 case HELPER_EXISTS:
1010                         pthread_mutex_unlock(&conlock);
1011                         return -1;
1012                 case HELPER_MATCHMORE:
1013                         pthread_mutex_unlock(&conlock);
1014                         return -1;
1015                 case HELPER_SPAWN:
1016                         newstack++;
1017                         /* Fall through */
1018                 case HELPER_EXEC:
1019                         pthread_mutex_unlock(&conlock);
1020                         if (sw->exec)
1021                                 res = sw->exec(c, context, exten, priority, callerid, newstack, data);
1022                         else {
1023                                 ast_log(LOG_WARNING, "No execution engine for switch %s\n", sw->name);
1024                                 res = -1;
1025                         }
1026                         return res;
1027                 default:
1028                         ast_log(LOG_WARNING, "Huh (%d)?\n", action);
1029                         return -1;
1030                 }
1031         } else {
1032                 pthread_mutex_unlock(&conlock);
1033                 switch(status) {
1034                 case STATUS_NO_CONTEXT:
1035                         if ((action != HELPER_EXISTS) && (action != HELPER_MATCHMORE))
1036                                 ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", context);
1037                         break;
1038                 case STATUS_NO_EXTENSION:
1039                         if ((action != HELPER_EXISTS) && (action !=  HELPER_CANMATCH) && (action != HELPER_MATCHMORE))
1040                                 ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, context);
1041                         break;
1042                 case STATUS_NO_PRIORITY:
1043                         if ((action != HELPER_EXISTS) && (action !=  HELPER_CANMATCH) && (action != HELPER_MATCHMORE))
1044                                 ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, context);
1045                         break;
1046                 default:
1047                         ast_log(LOG_DEBUG, "Shouldn't happen!\n");
1048                 }
1049                 if ((action != HELPER_EXISTS) && (action != HELPER_CANMATCH) && (action != HELPER_MATCHMORE))
1050                         return -1;
1051                 else
1052                         return 0;
1053         }
1054
1055 }
1056
1057 int ast_exists_extension(struct ast_channel *c, char *context, char *exten, int priority, char *callerid) 
1058 {
1059         return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_EXISTS);
1060 }
1061
1062 int ast_canmatch_extension(struct ast_channel *c, char *context, char *exten, int priority, char *callerid)
1063 {
1064         return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_CANMATCH);
1065 }
1066
1067 int ast_matchmore_extension(struct ast_channel *c, char *context, char *exten, int priority, char *callerid)
1068 {
1069         return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_MATCHMORE);
1070 }
1071
1072 int ast_spawn_extension(struct ast_channel *c, char *context, char *exten, int priority, char *callerid) 
1073 {
1074         return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_SPAWN);
1075 }
1076
1077 int ast_pbx_run(struct ast_channel *c)
1078 {
1079         int firstpass = 1;
1080         char digit;
1081         char exten[256];
1082         int pos;
1083         int waittime;
1084         int res=0;
1085
1086         /* A little initial setup here */
1087         if (c->pbx)
1088                 ast_log(LOG_WARNING, "%s already has PBX structure??\n", c->name);
1089         c->pbx = malloc(sizeof(struct ast_pbx));
1090         if (!c->pbx) {
1091                 ast_log(LOG_WARNING, "Out of memory\n");
1092                 return -1;
1093         }
1094         if (c->amaflags) {
1095                 if (c->cdr) {
1096                         ast_log(LOG_WARNING, "%s already has a call record??\n", c->name);
1097                 } else {
1098                         c->cdr = ast_cdr_alloc();
1099                         if (!c->cdr) {
1100                                 ast_log(LOG_WARNING, "Unable to create Call Detail Record\n");
1101                                 free(c->pbx);
1102                                 return -1;
1103                         }
1104                         ast_cdr_init(c->cdr, c);
1105                 }
1106         }
1107         memset(c->pbx, 0, sizeof(struct ast_pbx));
1108         /* Set reasonable defaults */
1109         c->pbx->rtimeout = 10;
1110         c->pbx->dtimeout = 5;
1111
1112         /* Start by trying whatever the channel is set to */
1113         if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) {
1114                 /* JK02: If not successfull fall back to 's' */
1115                 strncpy(c->exten, "s", sizeof(c->exten)-1);
1116                 if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) {
1117                         /* JK02: And finally back to default if everything else failed */
1118                         strncpy(c->context, "default", sizeof(c->context)-1);
1119                 }
1120                 c->priority = 1;
1121         }
1122         if (c->cdr)
1123                 ast_cdr_start(c->cdr);
1124         for(;;) {
1125                 pos = 0;
1126                 digit = 0;
1127                 while(ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) {
1128                         memset(exten, 0, sizeof(exten));
1129                         manager_event(EVENT_FLAG_CALL, "Newexten", 
1130                                 "Channel: %s\r\n"
1131                                 "Context: %s\r\n"
1132                                 "Extension: %s\r\n"
1133                                 "Priority: %d\r\n",
1134                                 c->name, c->context, c->exten, c->priority);                    
1135                         if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->callerid))) {
1136                                 /* Something bad happened, or a hangup has been requested. */
1137                                 if (((res >= '0') && (res <= '9')) || ((res >= 'A') && (res <= 'F')) ||
1138                                         (res == '*') || (res == '#')) {
1139                                         ast_log(LOG_DEBUG, "Oooh, got something to jump out with ('%c')!\n", res);
1140                                         exten[pos++] = digit = res;
1141                                         break;
1142                                 }
1143                                 switch(res) {
1144                                 case AST_PBX_KEEPALIVE:
1145                                         if (option_debug)
1146                                                 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
1147                                         else if (option_verbose > 1)
1148                                                 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
1149                                         goto out;
1150                                         break;
1151                                 default:
1152                                         if (option_debug)
1153                                                 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
1154                                         else if (option_verbose > 1)
1155                                                 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
1156                                         if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
1157                                                 c->_softhangup =0;
1158                                                 break;
1159                                         }
1160                                         /* atimeout */
1161                                         if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) {
1162                                                 break;
1163                                         }
1164                                         goto out;
1165                                 }
1166                         }
1167                         if ((c->_softhangup == AST_SOFTHANGUP_TIMEOUT) && (ast_exists_extension(c,c->context,"T",1,c->callerid))) {
1168                                 strncpy(c->exten,"T",sizeof(c->exten) - 1);
1169                                 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
1170                                 c->whentohangup = 0;
1171                         } else if (c->_softhangup) {
1172                                 ast_log(LOG_DEBUG, "Extension %s, priority %d returned normally even though call was hung up\n",
1173                                         c->exten, c->priority);
1174                                 goto out;
1175                         }
1176                         firstpass = 0;
1177                         c->priority++;
1178                 }
1179                 if (!ast_exists_extension(c, c->context, c->exten, 1, c->callerid)) {
1180                         /* It's not a valid extension anymore */
1181                         if (ast_exists_extension(c, c->context, "i", 1, c->callerid)) {
1182                                 if (option_verbose > 2)
1183                                         ast_verbose(VERBOSE_PREFIX_3 "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, c->name);
1184                                 strncpy(c->exten, "i", sizeof(c->exten)-1);
1185                                 c->priority = 1;
1186                         } else {
1187                                 ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n",
1188                                         c->name, c->exten, c->context);
1189                                 goto out;
1190                         }
1191                 } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) {
1192                         /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */
1193                         c->_softhangup = 0;
1194                 } else {
1195                         /* Done, wait for an extension */
1196                         if (digit)
1197                                 waittime = c->pbx->dtimeout;
1198                         else
1199                                 waittime = c->pbx->rtimeout;
1200                         while (ast_matchmore_extension(c, c->context, exten, 1, c->callerid)) {
1201                                 /* As long as we're willing to wait, and as long as it's not defined, 
1202                                    keep reading digits until we can't possibly get a right answer anymore.  */
1203                                 digit = ast_waitfordigit(c, waittime * 1000);
1204                                 if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
1205                                         c->_softhangup = 0;
1206                                 } else {
1207                                         if (!digit)
1208                                                 /* No entry */
1209                                                 break;
1210                                         if (digit < 0)
1211                                                 /* Error, maybe a  hangup */
1212                                                 goto out;
1213                                         exten[pos++] = digit;
1214                                         waittime = c->pbx->dtimeout;
1215                                 }
1216                         }
1217                         if (ast_exists_extension(c, c->context, exten, 1, c->callerid)) {
1218                                 /* Prepare the next cycle */
1219                                 strncpy(c->exten, exten, sizeof(c->exten)-1);
1220                                 c->priority = 1;
1221                         } else {
1222                                 /* No such extension */
1223                                 if (strlen(exten)) {
1224                                         /* An invalid extension */
1225                                         if (ast_exists_extension(c, c->context, "i", 1, c->callerid)) {
1226                                                 if (option_verbose > 2)
1227                                                         ast_verbose( VERBOSE_PREFIX_3 "Invalid extension '%s' in context '%s' on %s\n", exten, c->context, c->name);
1228                                                 strncpy(c->exten, "i", sizeof(c->exten)-1);
1229                                                 c->priority = 1;
1230                                         } else {
1231                                                 ast_log(LOG_WARNING, "Invalid extension, but no rule 'i' in context '%s'\n", c->context);
1232                                                 goto out;
1233                                         }
1234                                 } else {
1235                                         /* A simple timeout */
1236                                         if (ast_exists_extension(c, c->context, "t", 1, c->callerid)) {
1237                                                 if (option_verbose > 2)
1238                                                         ast_verbose( VERBOSE_PREFIX_3 "Timeout on %s\n", c->name);
1239                                                 strncpy(c->exten, "t", sizeof(c->exten)-1);
1240                                                 c->priority = 1;
1241                                         } else {
1242                                                 ast_log(LOG_WARNING, "Timeout, but no rule 't' in context '%s'\n", c->context);
1243                                                 goto out;
1244                                         }
1245                                 }       
1246                         }
1247                 }
1248         }
1249         if (firstpass) 
1250                 ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name);
1251 out:
1252         if (ast_exists_extension(c, c->context, "h", 1, c->callerid)) {
1253                 strcpy(c->exten, "h");
1254                 c->priority = 1;
1255                 while(ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) {
1256                         if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->callerid))) {
1257                                 /* Something bad happened, or a hangup has been requested. */
1258                                 if (option_debug)
1259                                         ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
1260                                 else if (option_verbose > 1)
1261                                         ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
1262                                 break;
1263                         }
1264                         c->priority++;
1265                 }
1266         }
1267
1268         pbx_destroy(c->pbx);
1269         c->pbx = NULL;
1270         if (res != AST_PBX_KEEPALIVE)
1271                 ast_hangup(c);
1272         return 0;
1273 }
1274
1275 static void *pbx_thread(void *data)
1276 {
1277         /* Oh joyeous kernel, we're a new thread, with nothing to do but
1278            answer this channel and get it going.  The setjmp stuff is fairly
1279            confusing, but necessary to get smooth transitions between
1280            the execution of different applications (without the use of
1281            additional threads) */
1282         struct ast_channel *c = data;
1283         ast_pbx_run(c);
1284         pthread_exit(NULL);
1285         return NULL;
1286 }
1287
1288 int ast_pbx_start(struct ast_channel *c)
1289 {
1290         pthread_t t;
1291         pthread_attr_t attr;
1292         if (!c) {
1293                 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
1294                 return -1;
1295         }
1296            
1297         /* Start a new thread, and get something handling this channel. */
1298         pthread_attr_init(&attr);
1299         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1300         if (pthread_create(&t, &attr, pbx_thread, c)) {
1301                 ast_log(LOG_WARNING, "Failed to create new channel thread\n");
1302                 return -1;
1303         }
1304         return 0;
1305 }
1306
1307 /*
1308  * This function locks contexts list by &conlist, search for the rigt context
1309  * structure, leave context list locked and call ast_context_remove_include2
1310  * which removes include, unlock contexts list and return ...
1311  */
1312 int ast_context_remove_include(char *context, char *include, char *registrar)
1313 {
1314         struct ast_context *c;
1315
1316         if (ast_lock_contexts()) return -1;
1317
1318         /* walk contexts and search for the right one ...*/
1319         c = ast_walk_contexts(NULL);
1320         while (c) {
1321                 /* we found one ... */
1322                 if (!strcmp(ast_get_context_name(c), context)) {
1323                         int ret;
1324                         /* remove include from this context ... */      
1325                         ret = ast_context_remove_include2(c, include, registrar);
1326
1327                         ast_unlock_contexts();
1328
1329                         /* ... return results */
1330                         return ret;
1331                 }
1332                 c = ast_walk_contexts(c);
1333         }
1334
1335         /* we can't find the right one context */
1336         ast_unlock_contexts();
1337         return -1;
1338 }
1339
1340 /*
1341  * When we call this function, &conlock lock must be locked, because when
1342  * we giving *con argument, some process can remove/change this context
1343  * and after that there can be segfault.
1344  *
1345  * This function locks given context, removes include, unlock context and
1346  * return.
1347  */
1348 int ast_context_remove_include2(struct ast_context *con, char *include, char *registrar)
1349 {
1350         struct ast_include *i, *pi = NULL;
1351
1352         if (ast_pthread_mutex_lock(&con->lock)) return -1;
1353
1354         /* walk includes */
1355         i = con->includes;
1356         while (i) {
1357                 /* find our include */
1358                 if (!strcmp(i->name, include) && 
1359                         (!strcmp(i->registrar, registrar) || !registrar)) {
1360                         /* remove from list */
1361                         if (pi)
1362                                 pi->next = i->next;
1363                         else
1364                                 con->includes = i->next;
1365                         /* free include and return */
1366                         free(i);
1367                         ast_pthread_mutex_unlock(&con->lock);
1368                         return 0;
1369                 }
1370                 pi = i;
1371                 i = i->next;
1372         }
1373
1374         /* we can't find the right include */
1375         ast_pthread_mutex_unlock(&con->lock);
1376         return -1;
1377 }
1378
1379 /*
1380  * This function locks contexts list by &conlist, search for the rigt context
1381  * structure, leave context list locked and call ast_context_remove_switch2
1382  * which removes switch, unlock contexts list and return ...
1383  */
1384 int ast_context_remove_switch(char *context, char *sw, char *data, char *registrar)
1385 {
1386         struct ast_context *c;
1387
1388         if (ast_lock_contexts()) return -1;
1389
1390         /* walk contexts and search for the right one ...*/
1391         c = ast_walk_contexts(NULL);
1392         while (c) {
1393                 /* we found one ... */
1394                 if (!strcmp(ast_get_context_name(c), context)) {
1395                         int ret;
1396                         /* remove switch from this context ... */       
1397                         ret = ast_context_remove_switch2(c, sw, data, registrar);
1398
1399                         ast_unlock_contexts();
1400
1401                         /* ... return results */
1402                         return ret;
1403                 }
1404                 c = ast_walk_contexts(c);
1405         }
1406
1407         /* we can't find the right one context */
1408         ast_unlock_contexts();
1409         return -1;
1410 }
1411
1412 /*
1413  * When we call this function, &conlock lock must be locked, because when
1414  * we giving *con argument, some process can remove/change this context
1415  * and after that there can be segfault.
1416  *
1417  * This function locks given context, removes switch, unlock context and
1418  * return.
1419  */
1420 int ast_context_remove_switch2(struct ast_context *con, char *sw, char *data, char *registrar)
1421 {
1422         struct ast_sw *i, *pi = NULL;
1423
1424         if (ast_pthread_mutex_lock(&con->lock)) return -1;
1425
1426         /* walk switchs */
1427         i = con->alts;
1428         while (i) {
1429                 /* find our switch */
1430                 if (!strcmp(i->name, sw) && !strcmp(i->data, data) && 
1431                         (!strcmp(i->registrar, registrar) || !registrar)) {
1432                         /* remove from list */
1433                         if (pi)
1434                                 pi->next = i->next;
1435                         else
1436                                 con->alts = i->next;
1437                         /* free switch and return */
1438                         free(i);
1439                         ast_pthread_mutex_unlock(&con->lock);
1440                         return 0;
1441                 }
1442                 pi = i;
1443                 i = i->next;
1444         }
1445
1446         /* we can't find the right switch */
1447         ast_pthread_mutex_unlock(&con->lock);
1448         return -1;
1449 }
1450
1451 /*
1452  * This functions lock contexts list, search for the right context,
1453  * call ast_context_remove_extension2, unlock contexts list and return.
1454  * In this function we are using
1455  */
1456 int ast_context_remove_extension(char *context, char *extension, int priority, char *registrar)
1457 {
1458         struct ast_context *c;
1459
1460         if (ast_lock_contexts()) return -1;
1461
1462         /* walk contexts ... */
1463         c = ast_walk_contexts(NULL);
1464         while (c) {
1465                 /* ... search for the right one ... */
1466                 if (!strcmp(ast_get_context_name(c), context)) {
1467                         /* ... remove extension ... */
1468                         int ret = ast_context_remove_extension2(c, extension, priority,
1469                                 registrar);
1470                         /* ... unlock contexts list and return */
1471                         ast_unlock_contexts();
1472                         return ret;
1473                 }
1474                 c = ast_walk_contexts(c);
1475         }
1476
1477         /* we can't find the right context */
1478         ast_unlock_contexts();
1479         return -1;
1480 }
1481
1482 /*
1483  * When do you want to call this function, make sure that &conlock is locked,
1484  * because some process can handle with your *con context before you lock
1485  * it.
1486  *
1487  * This functionc locks given context, search for the right extension and
1488  * fires out all peer in this extensions with given priority. If priority
1489  * is set to 0, all peers are removed. After that, unlock context and
1490  * return.
1491  */
1492 int ast_context_remove_extension2(struct ast_context *con, char *extension, int priority, char *registrar)
1493 {
1494         struct ast_exten *exten, *prev_exten = NULL;
1495
1496         if (ast_pthread_mutex_lock(&con->lock)) return -1;
1497
1498         /* go through all extensions in context and search the right one ... */
1499         exten = con->root;
1500         while (exten) {
1501
1502                 /* look for right extension */
1503                 if (!strcmp(exten->exten, extension) &&
1504                         (!strcmp(exten->registrar, registrar) || !registrar)) {
1505                         struct ast_exten *peer;
1506
1507                         /* should we free all peers in this extension? (priority == 0)? */
1508                         if (priority == 0) {
1509                                 /* remove this extension from context list */
1510                                 if (prev_exten)
1511                                         prev_exten->next = exten->next;
1512                                 else
1513                                         con->root = exten->next;
1514
1515                                 /* fire out all peers */
1516                                 peer = exten; 
1517                                 while (peer) {
1518                                         exten = peer->peer;
1519
1520                                         peer->datad(peer->data);
1521                                         free(peer);
1522
1523                                         peer = exten;
1524                                 }
1525
1526                                 ast_pthread_mutex_unlock(&con->lock);
1527                                 return 0;
1528                         } else {
1529                                 /* remove only extension with exten->priority == priority */
1530                                 struct ast_exten *previous_peer = NULL;
1531
1532                                 peer = exten;
1533                                 while (peer) {
1534                                         /* is this our extension? */
1535                                         if (peer->priority == priority &&
1536                                                 (!strcmp(peer->registrar, registrar) || !registrar)) {
1537                                                 /* we are first priority extension? */
1538                                                 if (!previous_peer) {
1539                                                         /* exists previous extension here? */
1540                                                         if (prev_exten) {
1541                                                                 /* yes, so we must change next pointer in
1542                                                                  * previous connection to next peer
1543                                                                  */
1544                                                                 if (peer->peer) {
1545                                                                         prev_exten->next = peer->peer;
1546                                                                         peer->peer->next = exten->next;
1547                                                                 } else
1548                                                                         prev_exten->next = exten->next;
1549                                                         } else {
1550                                                                 /* no previous extension, we are first
1551                                                                  * extension, so change con->root ...
1552                                                                  */
1553                                                                 if (peer->peer)
1554                                                                         con->root = peer->peer;
1555                                                                 else
1556                                                                         con->root = exten->next; 
1557                                                         }
1558                                                 } else {
1559                                                         /* we are not first priority in extension */
1560                                                         previous_peer->peer = peer->peer;
1561                                                 }
1562
1563                                                 /* now, free whole priority extension */
1564                                                 peer->datad(peer->data);
1565                                                 free(peer);
1566
1567                                                 ast_pthread_mutex_unlock(&con->lock);
1568                                                 return 0;
1569                                         } else {
1570                                                 /* this is not right extension, skip to next peer */
1571                                                 previous_peer = peer;
1572                                                 peer = peer->peer;
1573                                         }
1574                                 }
1575
1576                                 ast_pthread_mutex_unlock(&con->lock);
1577                                 return -1;
1578                         }
1579                 }
1580
1581                 prev_exten = exten;
1582                 exten = exten->next;
1583         }
1584
1585         /* we can't find right extension */
1586         ast_pthread_mutex_unlock(&con->lock);
1587         return -1;
1588 }
1589
1590
1591 int ast_register_application(char *app, int (*execute)(struct ast_channel *, void *), char *synopsis, char *description)
1592 {
1593         struct ast_app *tmp;
1594         char tmps[80];
1595         if (ast_pthread_mutex_lock(&applock)) {
1596                 ast_log(LOG_ERROR, "Unable to lock application list\n");
1597                 return -1;
1598         }
1599         tmp = apps;
1600         while(tmp) {
1601                 if (!strcasecmp(app, tmp->name)) {
1602                         ast_log(LOG_WARNING, "Already have an application '%s'\n", app);
1603                         ast_pthread_mutex_unlock(&applock);
1604                         return -1;
1605                 }
1606                 tmp = tmp->next;
1607         }
1608         tmp = malloc(sizeof(struct ast_app));
1609         if (tmp) {
1610                 memset(tmp, 0, sizeof(struct ast_app));
1611                 strncpy(tmp->name, app, sizeof(tmp->name)-1);
1612                 tmp->execute = execute;
1613                 tmp->synopsis = synopsis;
1614                 tmp->description = description;
1615                 tmp->next = apps;
1616                 apps = tmp;
1617         } else {
1618                 ast_log(LOG_WARNING, "Out of memory\n");
1619                 ast_pthread_mutex_unlock(&applock);
1620                 return -1;
1621         }
1622         if (option_verbose > 1)
1623                 ast_verbose( VERBOSE_PREFIX_2 "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps)));
1624         ast_pthread_mutex_unlock(&applock);
1625         return 0;
1626 }
1627
1628 int ast_register_switch(struct ast_switch *sw)
1629 {
1630         struct ast_switch *tmp, *prev=NULL;
1631         if (ast_pthread_mutex_lock(&switchlock)) {
1632                 ast_log(LOG_ERROR, "Unable to lock switch lock\n");
1633                 return -1;
1634         }
1635         tmp = switches;
1636         while(tmp) {
1637                 if (!strcasecmp(tmp->name, sw->name))
1638                         break;
1639                 prev = tmp;
1640                 tmp = tmp->next;
1641         }
1642         if (tmp) {      
1643                 ast_pthread_mutex_unlock(&switchlock);
1644                 ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name);
1645                 return -1;
1646         }
1647         sw->next = NULL;
1648         if (prev) 
1649                 prev->next = sw;
1650         else
1651                 switches = sw;
1652         ast_pthread_mutex_unlock(&switchlock);
1653         return 0;
1654 }
1655
1656 void ast_unregister_switch(struct ast_switch *sw)
1657 {
1658         struct ast_switch *tmp, *prev=NULL;
1659         if (ast_pthread_mutex_lock(&switchlock)) {
1660                 ast_log(LOG_ERROR, "Unable to lock switch lock\n");
1661                 return;
1662         }
1663         tmp = switches;
1664         while(tmp) {
1665                 if (tmp == sw) {
1666                         if (prev)
1667                                 prev->next = tmp->next;
1668                         else
1669                                 switches = tmp->next;
1670                         tmp->next = NULL;
1671                         break;                  
1672                 }
1673                 prev = tmp;
1674                 tmp = tmp->next;
1675         }
1676         ast_pthread_mutex_unlock(&switchlock);
1677 }
1678
1679 /*
1680  * Help for CLI commands ...
1681  */
1682 static char show_application_help[] = 
1683 "Usage: show application <application> [<application> [<application> [...]]]\n"
1684 "       Describes a particular application.\n";
1685
1686 static char show_applications_help[] =
1687 "Usage: show applications\n"
1688 "       List applications which are currently available.\n";
1689
1690 static char show_dialplan_help[] =
1691 "Usage: show dialplan [exten@][context]\n"
1692 "       Show dialplan\n";
1693
1694 static char show_switches_help[] = 
1695 "Usage: show switches\n"
1696 "       Show registered switches\n";
1697
1698 /*
1699  * IMPLEMENTATION OF CLI FUNCTIONS IS IN THE SAME ORDER AS COMMANDS HELPS
1700  *
1701  */
1702
1703 /*
1704  * 'show application' CLI command implementation functions ...
1705  */
1706
1707 /*
1708  * There is a possibility to show informations about more than one
1709  * application at one time. You can type 'show application Dial Echo' and
1710  * you will see informations about these two applications ...
1711  */
1712 static char *complete_show_application(char *line, char *word,
1713         int pos, int state)
1714 {
1715         struct ast_app *a;
1716         int which = 0;
1717
1718         /* try to lock applications list ... */
1719         if (ast_pthread_mutex_lock(&applock)) {
1720                 ast_log(LOG_ERROR, "Unable to lock application list\n");
1721                 return NULL;
1722         }
1723
1724         /* ... walk all applications ... */
1725         a = apps; 
1726         while (a) {
1727                 /* ... check if word matches this application ... */
1728                 if (!strncasecmp(word, a->name, strlen(word))) {
1729                         /* ... if this is right app serve it ... */
1730                         if (++which > state) {
1731                                 char *ret = strdup(a->name);
1732                                 ast_pthread_mutex_unlock(&applock);
1733                                 return ret;
1734                         }
1735                 }
1736                 a = a->next; 
1737         }
1738
1739         /* no application match */
1740         ast_pthread_mutex_unlock(&applock);
1741         return NULL; 
1742 }
1743
1744 static int handle_show_application(int fd, int argc, char *argv[])
1745 {
1746         struct ast_app *a;
1747         char buf[2048];
1748         int app, no_registered_app = 1;
1749
1750         if (argc < 3) return RESULT_SHOWUSAGE;
1751
1752         /* try to lock applications list ... */
1753         if (ast_pthread_mutex_lock(&applock)) {
1754                 ast_log(LOG_ERROR, "Unable to lock application list\n");
1755                 return -1;
1756         }
1757
1758         /* ... go through all applications ... */
1759         a = apps; 
1760         while (a) {
1761                 /* ... compare this application name with all arguments given
1762                  * to 'show application' command ... */
1763                 for (app = 2; app < argc; app++) {
1764                         if (!strcasecmp(a->name, argv[app])) {
1765                                 no_registered_app = 0;
1766
1767                                 /* ... one of our applications, show info ...*/
1768                                 snprintf(buf, sizeof(buf),
1769                                         "\n  -= Info about application '%s' =- \n\n"
1770                                         "[Synopsis]:\n  %s\n\n"
1771                                         "[Description]:\n%s\n",
1772                                         a->name,
1773                                         a->synopsis ? a->synopsis : "Not available",
1774                                         a->description ? a-> description : "Not available");
1775                                 ast_cli(fd, buf);
1776                         }
1777                 }
1778                 a = a->next; 
1779         }
1780
1781         ast_pthread_mutex_unlock(&applock);
1782
1783         /* we found at least one app? no? */
1784         if (no_registered_app) {
1785                 ast_cli(fd, "Your application(s) is (are) not registered\n");
1786                 return RESULT_FAILURE;
1787         }
1788
1789         return RESULT_SUCCESS;
1790 }
1791
1792 static int handle_show_switches(int fd, int argc, char *argv[])
1793 {
1794         struct ast_switch *sw;
1795         if (!switches) {
1796                 ast_cli(fd, "There are no registered alternative switches\n");
1797                 return RESULT_SUCCESS;
1798         }
1799         /* ... we have applications ... */
1800         ast_cli(fd, "\n    -= Registered Asterisk Alternative Switches =-\n");
1801         if (ast_pthread_mutex_lock(&switchlock)) {
1802                 ast_log(LOG_ERROR, "Unable to lock switches\n");
1803                 return -1;
1804         }
1805         sw = switches;
1806         while (sw) {
1807                 ast_cli(fd, "%s: %s\n", sw->name, sw->description);
1808                 sw = sw->next;
1809         }
1810         ast_pthread_mutex_unlock(&switchlock);
1811         return RESULT_SUCCESS;
1812 }
1813
1814 /*
1815  * 'show applications' CLI command implementation functions ...
1816  */
1817 static int handle_show_applications(int fd, int argc, char *argv[])
1818 {
1819         struct ast_app *a;
1820
1821         /* try to lock applications list ... */
1822         if (ast_pthread_mutex_lock(&applock)) {
1823                 ast_log(LOG_ERROR, "Unable to lock application list\n");
1824                 return -1;
1825         }
1826
1827         /* ... go to first application ... */
1828         a = apps; 
1829
1830         /* ... have we got at least one application (first)? no? */
1831         if (!a) {
1832                 ast_cli(fd, "There is no registered applications\n");
1833                 ast_pthread_mutex_unlock(&applock);
1834                 return -1;
1835         }
1836
1837         /* ... we have applications ... */
1838         ast_cli(fd, "\n    -= Registered Asterisk Applications =-\n");
1839
1840         /* ... go through all applications ... */
1841         while (a) {
1842                 /* ... show informations about applications ... */
1843                 ast_cli(fd,"  %15s: %s\n",
1844                         a->name,
1845                         a->synopsis ? a->synopsis : "<Synopsis not available>");
1846                 a = a->next; 
1847         }
1848
1849         /* ... unlock and return */
1850         ast_pthread_mutex_unlock(&applock);
1851
1852         return RESULT_SUCCESS;
1853 }
1854
1855 /*
1856  * 'show dialplan' CLI command implementation functions ...
1857  */
1858 static char *complete_show_dialplan_context(char *line, char *word, int pos,
1859         int state)
1860 {
1861         struct ast_context *c;
1862         int which = 0;
1863
1864         /* we are do completion of [exten@]context on second postion only */
1865         if (pos != 2) return NULL;
1866
1867         /* try to lock contexts list ... */
1868         if (ast_lock_contexts()) {
1869                 ast_log(LOG_ERROR, "Unable to lock context list\n");
1870                 return NULL;
1871         }
1872
1873         /* ... walk through all contexts ... */
1874         c = ast_walk_contexts(NULL);
1875         while(c) {
1876                 /* ... word matches context name? yes? ... */
1877                 if (!strncasecmp(word, ast_get_context_name(c), strlen(word))) {
1878                         /* ... for serve? ... */
1879                         if (++which > state) {
1880                                 /* ... yes, serve this context name ... */
1881                                 char *ret = strdup(ast_get_context_name(c));
1882                                 ast_unlock_contexts();
1883                                 return ret;
1884                         }
1885                 }
1886                 c = ast_walk_contexts(c);
1887         }
1888
1889         /* ... unlock and return */
1890         ast_unlock_contexts();
1891         return NULL;
1892 }
1893
1894 static int handle_show_dialplan(int fd, int argc, char *argv[])
1895 {
1896         struct ast_context *c;
1897         char *exten = NULL, *context = NULL;
1898         int context_existence = 0, extension_existence = 0;
1899
1900         if (argc != 3 && argc != 2) return -1;
1901
1902         /* we obtain [exten@]context? if yes, split them ... */
1903         if (argc == 3) {
1904                 char *splitter = argv[2];
1905                 /* is there a '@' character? */
1906                 if (strchr(argv[2], '@')) {
1907                         /* yes, split into exten & context ... */
1908                         exten   = strsep(&splitter, "@");
1909                         context = splitter;
1910
1911                         /* check for length and change to NULL if !strlen() */
1912                         if (!strlen(exten))   exten = NULL;
1913                         if (!strlen(context)) context = NULL;
1914                 } else
1915                 {
1916                         /* no '@' char, only context given */
1917                         context = argv[2];
1918                         if (!strlen(context)) context = NULL;
1919                 }
1920         }
1921
1922         /* try to lock contexts */
1923         if (ast_lock_contexts()) {
1924                 ast_cli(LOG_WARNING, "Failed to lock contexts list\n");
1925                 return RESULT_FAILURE;
1926         }
1927
1928         /* walk all contexts ... */
1929         c = ast_walk_contexts(NULL);
1930         while (c) {
1931                 /* show this context? */
1932                 if (!context ||
1933                         !strcmp(ast_get_context_name(c), context)) {
1934                         context_existence = 1;
1935
1936                         /* try to lock context before walking in ... */
1937                         if (!ast_lock_context(c)) {
1938                                 struct ast_exten *e;
1939                                 struct ast_include *i;
1940                                 struct ast_ignorepat *ip;
1941                                 struct ast_sw *sw;
1942                                 char buf[256], buf2[256];
1943                                 int context_info_printed = 0;
1944
1945                                 /* are we looking for exten too? if yes, we print context
1946                                  * if we our extension only
1947                                  */
1948                                 if (!exten) {
1949                                         ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
1950                                                 ast_get_context_name(c), ast_get_context_registrar(c));
1951                                         context_info_printed = 1;
1952                                 }
1953
1954                                 /* walk extensions ... */
1955                                 e = ast_walk_context_extensions(c, NULL);
1956                                 while (e) {
1957                                         struct ast_exten *p;
1958
1959                                         /* looking for extension? is this our extension? */
1960                                         if (exten &&
1961                                                 strcmp(ast_get_extension_name(e), exten))
1962                                         {
1963                                                 /* we are looking for extension and it's not our
1964                                                  * extension, so skip to next extension */
1965                                                 e = ast_walk_context_extensions(c, e);
1966                                                 continue;
1967                                         }
1968
1969                                         extension_existence = 1;
1970
1971                                         /* may we print context info? */        
1972                                         if (!context_info_printed) {
1973                                                 ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
1974                                                         ast_get_context_name(c),
1975                                                         ast_get_context_registrar(c));
1976                                                 context_info_printed = 1;
1977                                         }
1978
1979                                         /* write extension name and first peer */       
1980                                         bzero(buf, sizeof(buf));                
1981                                         snprintf(buf, sizeof(buf), "'%s' =>",
1982                                                 ast_get_extension_name(e));
1983
1984                                         snprintf(buf2, sizeof(buf2),
1985                                                 "%d. %s(%s)",
1986                                                 ast_get_extension_priority(e),
1987                                                 ast_get_extension_app(e),
1988                                                 (char *)ast_get_extension_app_data(e));
1989
1990                                         ast_cli(fd, "  %-17s %-45s [%s]\n", buf, buf2,
1991                                                 ast_get_extension_registrar(e));
1992
1993                                         /* walk next extension peers */
1994                                         p = ast_walk_extension_priorities(e, e);
1995                                         while (p) {
1996                                                 bzero((void *)buf2, sizeof(buf2));
1997
1998                                                 snprintf(buf2, sizeof(buf2),
1999                                                         "%d. %s(%s)",
2000                                                         ast_get_extension_priority(p),
2001                                                         ast_get_extension_app(p),
2002                                                         (char *)ast_get_extension_app_data(p));
2003
2004                                                 ast_cli(fd,"  %-17s %-45s [%s]\n",
2005                                                         "", buf2,
2006                                                         ast_get_extension_registrar(p));        
2007
2008                                                 p = ast_walk_extension_priorities(e, p);
2009                                         }
2010                                         e = ast_walk_context_extensions(c, e);
2011                                 }
2012
2013                                 /* include & ignorepat we all printing if we are not
2014                                  * looking for exact extension
2015                                  */
2016                                 if (!exten) {
2017                                         if (ast_walk_context_extensions(c, NULL))
2018                                                 ast_cli(fd, "\n");
2019
2020                                         /* walk included and write info ... */
2021                                         i = ast_walk_context_includes(c, NULL);
2022                                         while (i) {
2023                                                 bzero(buf, sizeof(buf));
2024                                                 snprintf(buf, sizeof(buf), "'%s'",
2025                                                         ast_get_include_name(i));
2026                                                 ast_cli(fd, "  Include =>        %-45s [%s]\n",
2027                                                         buf, ast_get_include_registrar(i));
2028                                                 i = ast_walk_context_includes(c, i);
2029                                         }
2030
2031                                         /* walk ignore patterns and write info ... */
2032                                         ip = ast_walk_context_ignorepats(c, NULL);
2033                                         while (ip) {
2034                                                 bzero(buf, sizeof(buf));
2035                                                 snprintf(buf, sizeof(buf), "'%s'",
2036                                                         ast_get_ignorepat_name(ip));
2037                                                 ast_cli(fd, "  Ignore pattern => %-45s [%s]\n",
2038                                                         buf, ast_get_ignorepat_registrar(ip));  
2039                                                 ip = ast_walk_context_ignorepats(c, ip);
2040                                         }
2041                                         sw = ast_walk_context_switches(c, NULL);
2042                                         while(sw) {
2043                                                 bzero(buf, sizeof(buf));
2044                                                 snprintf(buf, sizeof(buf), "'%s/%s'",
2045                                                         ast_get_switch_name(sw),
2046                                                         ast_get_switch_data(sw));
2047                                                 ast_cli(fd, "  Alt. Switch =>    %-45s [%s]\n",
2048                                                         buf, ast_get_switch_registrar(sw));     
2049                                                 sw = ast_walk_context_switches(c, sw);
2050                                         }
2051                                 }
2052         
2053                                 ast_unlock_context(c);
2054
2055                                 /* if we print something in context, make an empty line */
2056                                 if (context_info_printed) ast_cli(fd, "\n");
2057                         }
2058                 }
2059                 c = ast_walk_contexts(c);
2060         }
2061         ast_unlock_contexts();
2062
2063         /* check for input failure and throw some error messages */
2064         if (context && !context_existence) {
2065                 ast_cli(fd, "There is no existence of '%s' context\n",
2066                         context);
2067                 return RESULT_FAILURE;
2068         }
2069
2070         if (exten && !extension_existence) {
2071                 if (context)
2072                         ast_cli(fd, "There is no existence of %s@%s extension\n",
2073                                 exten, context);
2074                 else
2075                         ast_cli(fd,
2076                                 "There is no existence of '%s' extension in all contexts\n",
2077                                 exten);
2078                 return RESULT_FAILURE;
2079         }
2080
2081         /* everything ok */
2082         return RESULT_SUCCESS;
2083 }
2084
2085 /*
2086  * CLI entries for upper commands ...
2087  */
2088 static struct ast_cli_entry show_applications_cli = 
2089         { { "show", "applications", NULL }, 
2090         handle_show_applications, "Shows registered applications",
2091         show_applications_help };
2092
2093 static struct ast_cli_entry show_application_cli =
2094         { { "show", "application", NULL }, 
2095         handle_show_application, "Describe a specific application",
2096         show_application_help, complete_show_application };
2097
2098 static struct ast_cli_entry show_dialplan_cli =
2099         { { "show", "dialplan", NULL },
2100                 handle_show_dialplan, "Show dialplan",
2101                 show_dialplan_help, complete_show_dialplan_context };
2102
2103 static struct ast_cli_entry show_switches_cli =
2104         { { "show", "switches", NULL },
2105                 handle_show_switches, "Show alternative switches",
2106                 show_switches_help, NULL };
2107
2108 int ast_unregister_application(char *app) {
2109         struct ast_app *tmp, *tmpl = NULL;
2110         if (ast_pthread_mutex_lock(&applock)) {
2111                 ast_log(LOG_ERROR, "Unable to lock application list\n");
2112                 return -1;
2113         }
2114         tmp = apps;
2115         while(tmp) {
2116                 if (!strcasecmp(app, tmp->name)) {
2117                         if (tmpl)
2118                                 tmpl->next = tmp->next;
2119                         else
2120                                 apps = tmp->next;
2121                         if (option_verbose > 1)
2122                                 ast_verbose( VERBOSE_PREFIX_2 "Unregistered application '%s'\n", tmp->name);
2123                         ast_pthread_mutex_unlock(&applock);
2124                         return 0;
2125                 }
2126                 tmpl = tmp;
2127                 tmp = tmp->next;
2128         }
2129         ast_pthread_mutex_unlock(&applock);
2130         return -1;
2131 }
2132
2133 struct ast_context *ast_context_create(char *name, char *registrar)
2134 {
2135         struct ast_context *tmp;
2136         
2137         ast_pthread_mutex_lock(&conlock);
2138         tmp = contexts;
2139         while(tmp) {
2140                 if (!strcasecmp(tmp->name, name)) {
2141                         ast_pthread_mutex_unlock(&conlock);
2142                         ast_log(LOG_WARNING, "Tried to register context '%s', already in use\n", name);
2143                         return NULL;
2144                 }
2145                 tmp = tmp->next;
2146         }
2147         tmp = malloc(sizeof(struct ast_context));
2148         if (tmp) {
2149                 memset(tmp, 0, sizeof(struct ast_context));
2150                 ast_pthread_mutex_init(&tmp->lock);
2151                 strncpy(tmp->name, name, sizeof(tmp->name)-1);
2152                 tmp->root = NULL;
2153                 tmp->registrar = registrar;
2154                 tmp->next = contexts;
2155                 tmp->includes = NULL;
2156                 tmp->ignorepats = NULL;
2157                 contexts = tmp;
2158                 if (option_debug)
2159                         ast_log(LOG_DEBUG, "Registered context '%s'\n", tmp->name);
2160                 else if (option_verbose > 2)
2161                         ast_verbose( VERBOSE_PREFIX_3 "Registered extension context '%s'\n", tmp->name);
2162         } else
2163                 ast_log(LOG_WARNING, "Out of memory\n");
2164         
2165         ast_pthread_mutex_unlock(&conlock);
2166         return tmp;
2167 }
2168
2169 /*
2170  * errno values
2171  *  EBUSY  - can't lock
2172  *  ENODATA - no existence of context
2173  */
2174 int ast_context_add_include(char *context, char *include, char *registrar)
2175 {
2176         struct ast_context *c;
2177
2178         if (ast_lock_contexts()) {
2179                 errno = EBUSY;
2180                 return -1;
2181         }
2182
2183         /* walk contexts ... */
2184         c = ast_walk_contexts(NULL);
2185         while (c) {
2186                 /* ... search for the right one ... */
2187                 if (!strcmp(ast_get_context_name(c), context)) {
2188                         int ret = ast_context_add_include2(c, include, registrar);
2189                         /* ... unlock contexts list and return */
2190                         ast_unlock_contexts();
2191                         return ret;
2192                 }
2193                 c = ast_walk_contexts(c);
2194         }
2195
2196         /* we can't find the right context */
2197         ast_unlock_contexts();
2198         errno = ENODATA;
2199         return -1;
2200 }
2201
2202 #define FIND_NEXT \
2203 do { \
2204         c = info; \
2205         while(*c && (*c != '|')) c++; \
2206         if (*c) { *c = '\0'; c++; } else c = NULL; \
2207 } while(0)
2208
2209 static void get_timerange(struct ast_include *i, char *times)
2210 {
2211         char *e;
2212         int x;
2213         int s1, s2;
2214         int e1, e2;
2215         /* Star is all times */
2216         if (!strlen(times) || !strcmp(times, "*")) {
2217                 for (x=0;x<24;x++)
2218                         i->minmask[x] = (1 << 30) - 1;
2219                 return;
2220         }
2221         /* Otherwise expect a range */
2222         e = strchr(times, '-');
2223         if (!e) {
2224                 ast_log(LOG_WARNING, "Time range is not valid. Assuming no time.\n");
2225                 return;
2226         }
2227         *e = '\0';
2228         e++;
2229         while(*e && !isdigit(*e)) e++;
2230         if (!*e) {
2231                 ast_log(LOG_WARNING, "Invalid time range.  Assuming no time.\n");
2232                 return;
2233         }
2234         if (sscanf(times, "%d:%d", &s1, &s2) != 2) {
2235                 ast_log(LOG_WARNING, "%s isn't a time.  Assuming no time.\n", times);
2236                 return;
2237         }
2238         if (sscanf(e, "%d:%d", &e1, &e2) != 2) {
2239                 ast_log(LOG_WARNING, "%s isn't a time.  Assuming no time.\n", e);
2240                 return;
2241         }
2242         s1 = s1 * 30 + s2/2;
2243         if ((s1 < 0) || (s1 >= 24*30)) {
2244                 ast_log(LOG_WARNING, "%s isn't a valid star time. Assuming no time.\n", times);
2245                 return;
2246         }
2247         e1 = e1 * 30 + e2/2;
2248         if ((e1 < 0) || (e2 >= 24*30)) {
2249                 ast_log(LOG_WARNING, "%s isn't a valid start time. Assuming no time.\n", times);
2250                 return;
2251         }
2252         /* Go through the time and enable each appropriate bit */
2253         for (x=s1;x != e1;x = (x + 1) % (24 * 30)) {
2254                 i->minmask[x/30] |= (1 << (x % 30));
2255         }
2256         /* Do the last one */
2257         i->minmask[x/30] |= (1 << (x % 30));
2258         /* All done */
2259 }
2260
2261 static char *days[] =
2262 {
2263         "sun",
2264         "mon",
2265         "tue",
2266         "wed",
2267         "thu",
2268         "fri",
2269         "sat",
2270 };
2271
2272 static unsigned int get_dow(char *dow)
2273 {
2274         char *c;
2275         /* The following line is coincidence, really! */
2276         int s, e, x;
2277         unsigned int mask;
2278         /* Check for all days */
2279         if (!strlen(dow) || !strcmp(dow, "*"))
2280                 return (1 << 7) - 1;
2281         /* Get start and ending days */
2282         c = strchr(dow, '-');
2283         if (c) {
2284                 *c = '\0';
2285                 c++;
2286         } else
2287                 c = NULL;
2288         /* Find the start */
2289         s = 0;
2290         while((s < 7) && strcasecmp(dow, days[s])) s++;
2291         if (s >= 7) {
2292                 ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", dow);
2293                 return 0;
2294         }
2295         if (c) {
2296                 e = 0;
2297                 while((e < 7) && strcasecmp(c, days[e])) e++;
2298                 if (e >= 7) {
2299                         ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", c);
2300                         return 0;
2301                 }
2302         } else
2303                 e = s;
2304         mask = 0;
2305         for (x=s;x!=e;x = (x + 1) % 7) {
2306                 mask |= (1 << x);
2307         }
2308         /* One last one */
2309         mask |= (1 << x);
2310         return mask;
2311 }
2312
2313 static unsigned int get_day(char *day)
2314 {
2315         char *c;
2316         /* The following line is coincidence, really! */
2317         int s, e, x;
2318         unsigned int mask;
2319         /* Check for all days */
2320         if (!strlen(day) || !strcmp(day, "*")) {
2321                 mask = (1 << 30)  + ((1 << 30) - 1);
2322                 return mask;
2323         }
2324         /* Get start and ending days */
2325         c = strchr(day, '-');
2326         if (c) {
2327                 *c = '\0';
2328                 c++;
2329         }
2330         /* Find the start */
2331         if (sscanf(day, "%d", &s) != 1) {
2332                 ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", day);
2333                 return 0;
2334         }
2335         if ((s < 1) || (s > 31)) {
2336                 ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", day);
2337                 return 0;
2338         }
2339         s--;
2340         if (c) {
2341                 if (sscanf(c, "%d", &e) != 1) {
2342                         ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", c);
2343                         return 0;
2344                 }
2345                 if ((e < 1) || (e > 31)) {
2346                         ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", c);
2347                         return 0;
2348                 }
2349                 e--;
2350         } else
2351                 e = s;
2352         mask = 0;
2353         for (x=s;x!=e;x = (x + 1) % 31) {
2354                 mask |= (1 << x);
2355         }
2356         mask |= (1 << x);
2357         return mask;
2358 }
2359
2360 static char *months[] =
2361 {
2362         "jan",
2363         "feb",
2364         "mar",
2365         "apr",
2366         "may",
2367         "jun",
2368         "jul",
2369         "aug",
2370         "sep",
2371         "oct",
2372         "nov",
2373         "dec",
2374 };
2375
2376 static unsigned int get_month(char *mon)
2377 {
2378         char *c;
2379         /* The following line is coincidence, really! */
2380         int s, e, x;
2381         unsigned int mask;
2382         /* Check for all days */
2383         if (!strlen(mon) || !strcmp(mon, "*")) 
2384                 return (1 << 12) - 1;
2385         /* Get start and ending days */
2386         c = strchr(mon, '-');
2387         if (c) {
2388                 *c = '\0';
2389                 c++;
2390         }
2391         /* Find the start */
2392         s = 0;
2393         while((s < 12) && strcasecmp(mon, months[s])) s++;
2394         if (s >= 12) {
2395                 ast_log(LOG_WARNING, "Invalid month '%s', assuming none\n", mon);
2396                 return 0;
2397         }
2398         if (c) {
2399                 e = 0;
2400                 while((e < 12) && strcasecmp(mon, months[e])) e++;
2401                 if (e >= 12) {
2402                         ast_log(LOG_WARNING, "Invalid month '%s', assuming none\n", c);
2403                         return 0;
2404                 }
2405         } else
2406                 e = s;
2407         mask = 0;
2408         for (x=s;x!=e;x = (x + 1) % 12) {
2409                 mask |= (1 << x);
2410         }
2411         /* One last one */
2412         mask |= (1 << x);
2413         return mask;
2414 }
2415
2416 static void build_timing(struct ast_include *i, char *info)
2417 {
2418         char *c;
2419         /* Check for empty just in case */
2420         if (!strlen(info))
2421                 return;
2422         i->hastime = 1;
2423         /* Assume everything except time */
2424         i->monthmask = (1 << 12) - 1;
2425         i->daymask = (1 << 30) - 1 + (1 << 30);
2426         i->dowmask = (1 << 7) - 1;
2427         /* Avoid using str tok */
2428         FIND_NEXT;
2429         /* Info has the time range, start with that */
2430         get_timerange(i, info);
2431         info = c;
2432         if (!info)
2433                 return;
2434         FIND_NEXT;
2435         /* Now check for day of week */
2436         i->dowmask = get_dow(info);
2437
2438         info = c;
2439         if (!info)
2440                 return;
2441         FIND_NEXT;
2442         /* Now check for the day of the month */
2443         i->daymask = get_day(info);
2444         info = c;
2445         if (!info)
2446                 return;
2447         FIND_NEXT;
2448         /* And finally go for the month */
2449         i->monthmask = get_month(info);
2450 }
2451
2452 /*
2453  * errno values
2454  *  ENOMEM - out of memory
2455  *  EBUSY  - can't lock
2456  *  EEXIST - already included
2457  *  EINVAL - there is no existence of context for inclusion
2458  */
2459 int ast_context_add_include2(struct ast_context *con, char *value,
2460         char *registrar)
2461 {
2462         struct ast_include *new_include;
2463         char *c;
2464         struct ast_include *i, *il = NULL; /* include, include_last */
2465
2466         /* allocate new include structure ... */
2467         if (!(new_include = malloc(sizeof(struct ast_include)))) {
2468                 ast_log(LOG_WARNING, "Out of memory\n");
2469                 errno = ENOMEM;
2470                 return -1;
2471         }
2472         
2473         /* ... fill in this structure ... */
2474         memset(new_include, 0, sizeof(struct ast_include));
2475         strncpy(new_include->name, value, sizeof(new_include->name)-1);
2476         strncpy(new_include->rname, value, sizeof(new_include->rname)-1);
2477         c = new_include->rname;
2478         /* Strip off timing info */
2479         while(*c && (*c != '|')) c++; 
2480         /* Process if it's there */
2481         if (*c) {
2482                 build_timing(new_include, c+1);
2483                 *c = '\0';
2484         }
2485         new_include->next      = NULL;
2486         new_include->registrar = registrar;
2487
2488         /* ... try to lock this context ... */
2489         if (ast_pthread_mutex_lock(&con->lock)) {
2490                 free(new_include);
2491                 errno = EBUSY;
2492                 return -1;
2493         }
2494
2495         /* ... go to last include and check if context is already included too... */
2496         i = con->includes;
2497         while (i) {
2498                 if (!strcasecmp(i->name, new_include->name)) {
2499                         free(new_include);
2500                         ast_pthread_mutex_unlock(&con->lock);
2501                         errno = EEXIST;
2502                         return -1;
2503                 }
2504                 il = i;
2505                 i = i->next;
2506         }
2507
2508         /* ... include new context into context list, unlock, return */
2509         if (il)
2510                 il->next = new_include;
2511         else
2512                 con->includes = new_include;
2513         if (option_verbose > 2)
2514                 ast_verbose(VERBOSE_PREFIX_3 "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con)); 
2515         ast_pthread_mutex_unlock(&con->lock);
2516
2517         return 0;
2518 }
2519
2520 /*
2521  * errno values
2522  *  EBUSY  - can't lock
2523  *  ENODATA - no existence of context
2524  */
2525 int ast_context_add_switch(char *context, char *sw, char *data, char *registrar)
2526 {
2527         struct ast_context *c;
2528
2529         if (ast_lock_contexts()) {
2530                 errno = EBUSY;
2531                 return -1;
2532         }
2533
2534         /* walk contexts ... */
2535         c = ast_walk_contexts(NULL);
2536         while (c) {
2537                 /* ... search for the right one ... */
2538                 if (!strcmp(ast_get_context_name(c), context)) {
2539                         int ret = ast_context_add_switch2(c, sw, data, registrar);
2540                         /* ... unlock contexts list and return */
2541                         ast_unlock_contexts();
2542                         return ret;
2543                 }
2544                 c = ast_walk_contexts(c);
2545         }
2546
2547         /* we can't find the right context */
2548         ast_unlock_contexts();
2549         errno = ENODATA;
2550         return -1;
2551 }
2552
2553 /*
2554  * errno values
2555  *  ENOMEM - out of memory
2556  *  EBUSY  - can't lock
2557  *  EEXIST - already included
2558  *  EINVAL - there is no existence of context for inclusion
2559  */
2560 int ast_context_add_switch2(struct ast_context *con, char *value,
2561         char *data, char *registrar)
2562 {
2563         struct ast_sw *new_sw;
2564         struct ast_sw *i, *il = NULL; /* sw, sw_last */
2565
2566         /* allocate new sw structure ... */
2567         if (!(new_sw = malloc(sizeof(struct ast_sw)))) {
2568                 ast_log(LOG_WARNING, "Out of memory\n");
2569                 errno = ENOMEM;
2570                 return -1;
2571         }
2572         
2573         /* ... fill in this structure ... */
2574         memset(new_sw, 0, sizeof(struct ast_sw));
2575         strncpy(new_sw->name, value, sizeof(new_sw->name)-1);
2576         if (data)
2577                 strncpy(new_sw->data, data, sizeof(new_sw->data)-1);
2578         else
2579                 strncpy(new_sw->data, "", sizeof(new_sw->data)-1);
2580         new_sw->next      = NULL;
2581         new_sw->registrar = registrar;
2582
2583         /* ... try to lock this context ... */
2584         if (ast_pthread_mutex_lock(&con->lock)) {
2585                 free(new_sw);
2586                 errno = EBUSY;
2587                 return -1;
2588         }
2589
2590         /* ... go to last sw and check if context is already swd too... */
2591         i = con->alts;
2592         while (i) {
2593                 if (!strcasecmp(i->name, new_sw->name)) {
2594                         free(new_sw);
2595                         ast_pthread_mutex_unlock(&con->lock);
2596                         errno = EEXIST;
2597                         return -1;
2598                 }
2599                 il = i;
2600                 i = i->next;
2601         }
2602
2603         /* ... sw new context into context list, unlock, return */
2604         if (il)
2605                 il->next = new_sw;
2606         else
2607                 con->alts = new_sw;
2608         if (option_verbose > 2)
2609                 ast_verbose(VERBOSE_PREFIX_3 "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con)); 
2610         ast_pthread_mutex_unlock(&con->lock);
2611
2612         return 0;
2613 }
2614
2615 /*
2616  * EBUSY  - can't lock
2617  * ENODATA - there is not context existence
2618  */
2619 int ast_context_remove_ignorepat(char *context, char *ignorepat, char *registrar)
2620 {
2621         struct ast_context *c;
2622
2623         if (ast_lock_contexts()) {
2624                 errno = EBUSY;
2625                 return -1;
2626         }
2627
2628         c = ast_walk_contexts(NULL);
2629         while (c) {
2630                 if (!strcmp(ast_get_context_name(c), context)) {
2631                         int ret = ast_context_remove_ignorepat2(c, ignorepat, registrar);
2632                         ast_unlock_contexts();
2633                         return ret;
2634                 }
2635                 c = ast_walk_contexts(c);
2636         }
2637
2638         ast_unlock_contexts();
2639         errno = ENODATA;
2640         return -1;
2641 }
2642
2643 int ast_context_remove_ignorepat2(struct ast_context *con, char *ignorepat, char *registrar)
2644 {
2645         struct ast_ignorepat *ip, *ipl = NULL;
2646
2647         if (ast_pthread_mutex_lock(&con->lock)) {
2648                 errno = EBUSY;
2649                 return -1;
2650         }
2651
2652         ip = con->ignorepats;
2653         while (ip) {
2654                 if (!strcmp(ip->pattern, ignorepat) &&
2655                         (registrar == ip->registrar || !registrar)) {
2656                         if (ipl) {
2657                                 ipl->next = ip->next;
2658                                 free(ip);
2659                         } else {
2660                                 con->ignorepats = ip->next;
2661                                 free(ip);
2662                         }
2663                         ast_pthread_mutex_unlock(&con->lock);
2664                         return 0;
2665                 }
2666                 ipl = ip; ip = ip->next;
2667         }
2668
2669         ast_pthread_mutex_unlock(&con->lock);
2670         errno = EINVAL;
2671         return -1;
2672 }
2673
2674 /*
2675  * EBUSY - can't lock
2676  * ENODATA - there is no existence of context
2677  */
2678 int ast_context_add_ignorepat(char *con, char *value, char *registrar)
2679 {
2680         struct ast_context *c;
2681
2682         if (ast_lock_contexts()) {
2683                 errno = EBUSY;
2684                 return -1;
2685         }
2686
2687         c = ast_walk_contexts(NULL);
2688         while (c) {
2689                 if (!strcmp(ast_get_context_name(c), con)) {
2690                         int ret = ast_context_add_ignorepat2(c, value, registrar);
2691                         ast_unlock_contexts();
2692                         return ret;
2693                 } 
2694                 c = ast_walk_contexts(c);
2695         }
2696
2697         ast_unlock_contexts();
2698         errno = ENODATA;
2699         return -1;
2700 }
2701
2702 int ast_context_add_ignorepat2(struct ast_context *con, char *value, char *registrar)
2703 {
2704         struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL;
2705         ignorepat = malloc(sizeof(struct ast_ignorepat));
2706         if (!ignorepat) {
2707                 ast_log(LOG_WARNING, "Out of memory\n");
2708                 errno = ENOMEM;
2709                 return -1;
2710         }
2711         memset(ignorepat, 0, sizeof(struct ast_ignorepat));
2712         strncpy(ignorepat->pattern, value, sizeof(ignorepat->pattern)-1);
2713         ignorepat->next = NULL;
2714         ignorepat->registrar = registrar;
2715         ast_pthread_mutex_lock(&con->lock);
2716         ignorepatc = con->ignorepats;
2717         while(ignorepatc) {
2718                 ignorepatl = ignorepatc;
2719                 if (!strcasecmp(ignorepatc->pattern, value)) {
2720                         /* Already there */
2721                         pthread_mutex_unlock(&con->lock);
2722                         errno = EEXIST;
2723                         return -1;
2724                 }
2725                 ignorepatc = ignorepatc->next;
2726         }
2727         if (ignorepatl) 
2728                 ignorepatl->next = ignorepat;
2729         else
2730                 con->ignorepats = ignorepat;
2731         pthread_mutex_unlock(&con->lock);
2732         return 0;
2733         
2734 }
2735
2736 int ast_ignore_pattern(char *context, char *pattern)
2737 {
2738         struct ast_context *con;
2739         struct ast_ignorepat *pat;
2740         con = ast_context_find(context);
2741         if (con) {
2742                 pat = con->ignorepats;
2743                 while (pat) {
2744                         if (ast_extension_match(pat->pattern, pattern))
2745                                 return 1;
2746                         pat = pat->next;
2747                 }
2748         } 
2749         return 0;
2750 }
2751
2752 /*
2753  * EBUSY   - can't lock
2754  * ENODATA  - no existence of context
2755  *
2756  */
2757 int ast_add_extension(char *context, int replace, char *extension, int priority, char *callerid,
2758         char *application, void *data, void (*datad)(void *), char *registrar)
2759 {
2760         struct ast_context *c;
2761
2762         if (ast_lock_contexts()) {
2763                 errno = EBUSY;
2764                 return -1;
2765         }
2766
2767         c = ast_walk_contexts(NULL);
2768         while (c) {
2769                 if (!strcmp(context, ast_get_context_name(c))) {
2770                         int ret = ast_add_extension2(c, replace, extension, priority, callerid,
2771                                 application, data, datad, registrar);
2772                         ast_unlock_contexts();
2773                         return ret;
2774                 }
2775                 c = ast_walk_contexts(c);
2776         }
2777
2778         ast_unlock_contexts();
2779         errno = ENODATA;
2780         return -1;
2781 }
2782
2783 int ast_async_goto(struct ast_channel *chan, char *context, char *exten, int priority, int needlock)
2784 {
2785         int res = 0;
2786         if (needlock)
2787                 ast_pthread_mutex_lock(&chan->lock);
2788         if (chan->pbx) {
2789                 /* This channel is currently in the PBX */
2790                 if (context && strlen(context))
2791                         strncpy(chan->context, context, sizeof(chan->context) - 1);
2792                 if (exten && strlen(exten))
2793                         strncpy(chan->exten, exten, sizeof(chan->context) - 1);
2794                 if (priority)
2795                         chan->priority = priority - 1;
2796                 ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO);
2797                 if (needlock)
2798                         ast_pthread_mutex_unlock(&chan->lock);
2799         } else {
2800                 /* In order to do it when the channel doesn't really exist within
2801                    the PBX, we have to make a new channel, masquerade, and start the PBX
2802                    at the new location */
2803                 struct ast_channel *tmpchan;
2804                 struct ast_frame *f;
2805                 tmpchan = ast_channel_alloc(0);
2806                 if (tmpchan) {
2807                         snprintf(tmpchan->name, sizeof(tmpchan->name), "AsyncGoto/%s", chan->name);
2808                         ast_setstate(tmpchan, chan->_state);
2809                         /* Make formats okay */
2810                         tmpchan->readformat = chan->readformat;
2811                         tmpchan->writeformat = chan->writeformat;
2812                         /* Setup proper location */
2813                         if (context && strlen(context))
2814                                 strncpy(tmpchan->context, context, sizeof(tmpchan->context) - 1);
2815                         else
2816                                 strncpy(tmpchan->context, chan->context, sizeof(tmpchan->context) - 1);
2817                         if (exten && strlen(exten))
2818                                 strncpy(tmpchan->exten, exten, sizeof(tmpchan->exten) - 1);
2819                         else
2820                                 strncpy(tmpchan->exten, chan->exten, sizeof(tmpchan->exten) - 1);
2821                         if (priority)
2822                                 tmpchan->priority = priority;
2823                         else
2824                                 tmpchan->priority = chan->priority;
2825                         if (needlock)
2826                                 ast_pthread_mutex_unlock(&chan->lock);
2827                         
2828                         /* Masquerade into temp channel */
2829                         ast_channel_masquerade(tmpchan, chan);
2830                         
2831                         /* Make the masquerade happen by reading a frame from the tmp channel */
2832                         f = ast_read(tmpchan);
2833                         if (f)
2834                                 ast_frfree(f);
2835                         /* Start the PBX going on our stolen channel */
2836                         if (ast_pbx_start(tmpchan)) {
2837                                 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name);
2838                                 ast_hangup(tmpchan);
2839                                 res = -1;
2840                         }
2841                 } else {
2842                         res = -1;
2843                         if (needlock)
2844                                 ast_pthread_mutex_unlock(&chan->lock);
2845                 }
2846         }
2847         return res;
2848 }
2849
2850 int ast_async_goto_by_name(char *channame, char *context, char *exten, int priority)
2851 {
2852         struct ast_channel *chan;
2853         chan = ast_channel_walk(NULL);
2854         while(chan) {
2855                 if (!strcasecmp(channame, chan->name))
2856                         break;
2857                 chan = ast_channel_walk(chan);
2858         }
2859         if (chan)
2860                 return ast_async_goto(chan, context, exten, priority, 1);
2861         return -1;
2862 }
2863
2864 static void ext_strncpy(char *dst, char *src, int len)
2865 {
2866         int count=0;
2867         while(*src && (count < len - 1)) {
2868                 switch(*src) {
2869                 case ' ':
2870 //otherwise exten => [a-b],1,... doesn't work
2871 //              case '-':
2872                         /* Ignore */
2873                         break;
2874                 default:
2875                         *dst = *src;
2876                         dst++;
2877                 }
2878                 src++;
2879                 count++;
2880         }
2881         *dst = '\0';
2882 }
2883
2884 /*
2885  * EBUSY - can't lock
2886  * EEXIST - extension with the same priority exist and no replace is set
2887  *
2888  */
2889 int ast_add_extension2(struct ast_context *con,
2890                                           int replace, char *extension, int priority, char *callerid,
2891                                           char *application, void *data, void (*datad)(void *),
2892                                           char *registrar)
2893 {
2894
2895 #define LOG do {        if (option_debug) {\
2896                 if (tmp->matchcid) { \
2897                         ast_log(LOG_DEBUG, "Added extension '%s' priority %d (CID match '%s') to %s\n", tmp->exten, tmp->priority, tmp->cidmatch, con->name); \
2898                 } else { \
2899                         ast_log(LOG_DEBUG, "Added extension '%s' priority %d to %s\n", tmp->exten, tmp->priority, con->name); \
2900                 } \
2901         } else if (option_verbose > 2) { \
2902                 if (tmp->matchcid) { \
2903                         ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d (CID match '%s')to %s\n", tmp->exten, tmp->priority, tmp->cidmatch, con->name); \
2904                 } else {  \
2905                         ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d to %s\n", tmp->exten, tmp->priority, con->name); \
2906                 } \
2907         } } while(0)
2908
2909         /*
2910          * This is a fairly complex routine.  Different extensions are kept
2911          * in order by the extension number.  Then, extensions of different
2912          * priorities (same extension) are kept in a list, according to the
2913          * peer pointer.
2914          */
2915         struct ast_exten *tmp, *e, *el = NULL, *ep = NULL;
2916         int res;
2917         /* Be optimistic:  Build the extension structure first */
2918         tmp = malloc(sizeof(struct ast_exten));
2919         if (tmp) {
2920                 memset(tmp, 0, sizeof(struct ast_exten));
2921                 ext_strncpy(tmp->exten, extension, sizeof(tmp->exten));
2922                 tmp->priority = priority;
2923                 if (callerid) {
2924                         ext_strncpy(tmp->cidmatch, callerid, sizeof(tmp->cidmatch));
2925                         tmp->matchcid = 1;
2926                 } else {
2927                         strcpy(tmp->cidmatch, "");
2928                         tmp->matchcid = 0;
2929                 }
2930                 strncpy(tmp->app, application, sizeof(tmp->app)-1);
2931                 tmp->data = data;
2932                 tmp->datad = datad;
2933                 tmp->registrar = registrar;
2934                 tmp->peer = NULL;
2935                 tmp->next =  NULL;
2936         } else {
2937                 ast_log(LOG_WARNING, "Out of memory\n");
2938                 errno = ENOMEM;
2939                 return -1;
2940         }
2941         if (ast_pthread_mutex_lock(&con->lock)) {
2942                 free(tmp);
2943                 /* And properly destroy the data */
2944                 datad(data);
2945                 ast_log(LOG_WARNING, "Failed to lock context '%s'\n", con->name);
2946                 errno = EBUSY;
2947                 return -1;
2948         }
2949         e = con->root;
2950         while(e) {
2951                 res= strcasecmp(e->exten, extension);
2952                 if (!res) {
2953                         if (!e->matchcid && !tmp->matchcid)
2954                                 res = 0;
2955                         else if (tmp->matchcid && !e->matchcid)
2956                                 res = 1;
2957                         else if (e->matchcid && !tmp->matchcid)
2958                                 res = -1;
2959                         else
2960                                 res = strcasecmp(e->cidmatch, tmp->cidmatch);
2961                 }
2962                 if (res == 0) {
2963                         /* We have an exact match, now we find where we are
2964                            and be sure there's no duplicates */
2965                         while(e) {
2966                                 if (e->priority == tmp->priority) {
2967                                         /* Can't have something exactly the same.  Is this a
2968                                            replacement?  If so, replace, otherwise, bonk. */
2969                                         if (replace) {
2970                                                 if (ep) {
2971                                                         /* We're in the peer list, insert ourselves */
2972                                                         ep->peer = tmp;
2973                                                         tmp->peer = e->peer;
2974                                                 } else if (el) {
2975                                                         /* We're the first extension. Take over e's functions */
2976                                                         el->next = tmp;
2977                                                         tmp->next = e->next;
2978                                                         tmp->peer = e->peer;
2979                                                 } else {
2980                                                         /* We're the very first extension.  */
2981                                                         con->root = tmp;
2982                                                         tmp->next = e->next;
2983                                                         tmp->peer = e->peer;
2984                                                 }
2985                                                 /* Destroy the old one */
2986                                                 e->datad(e->data);
2987                                                 free(e);
2988                                                 ast_pthread_mutex_unlock(&con->lock);
2989                                                 /* And immediately return success. */
2990                                                 LOG;
2991                                                 return 0;
2992                                         } else {
2993                                                 ast_log(LOG_WARNING, "Unable to register extension '%s', priority %d in '%s', already in use\n", tmp->exten, tmp->priority, con->name);
2994                                                 tmp->datad(tmp->data);
2995                                                 free(tmp);
2996                                                 ast_pthread_mutex_unlock(&con->lock);
2997                                                 errno = EEXIST;
2998                                                 return -1;
2999                                         }
3000                                 } else if (e->priority > tmp->priority) {
3001                                         /* Slip ourselves in just before e */
3002                                         if (ep) {
3003                                                 /* Easy enough, we're just in the peer list */
3004                                                 ep->peer = tmp;
3005                                                 tmp->peer = e;
3006                                         } else if (el) {
3007                                                 /* We're the first extension in this peer list */
3008                                                 el->next = tmp;
3009                                                 tmp->next = e->next;
3010                                                 e->next = NULL;
3011                                                 tmp->peer = e;
3012                                         } else {
3013                                                 /* We're the very first extension altogether */
3014                                                 tmp->next = con->root;
3015                                                 /* Con->root must always exist or we couldn't get here */
3016                                                 tmp->peer = con->root->peer;
3017                                                 con->root = tmp;
3018                                         }
3019                                         ast_pthread_mutex_unlock(&con->lock);
3020                   &n