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