Version 0.1.8 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 <pthread.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 <string.h>
22 #include <unistd.h>
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <setjmp.h>
26 #include <ctype.h>
27 #include "asterisk.h"
28
29 /*
30  * I M P O R T A N T :
31  *
32  *              The speed of extension handling will likely be among the most important
33  * aspects of this PBX.  The switching scheme as it exists right now isn't
34  * terribly bad (it's O(N+M), where N is the # of extensions and M is the avg #
35  * of priorities, but a constant search time here would be great ;-) 
36  *
37  */
38
39
40 struct ast_context;
41
42 struct ast_pbx {
43         int dtimeout;                                   /* Timeout between digits (seconds) */
44         int rtimeout;                                   /* Timeout for response (seconds) */
45 };
46
47 /* An extension */
48 struct ast_exten {
49         char exten[AST_MAX_EXTENSION];
50         int priority;
51         /* An extension */
52         struct ast_context *parent;
53         /* Application to execute */
54         char app[AST_MAX_EXTENSION];
55         /* Data to use */
56         void *data;
57         /* Data destructor */
58         void (*datad)(void *);
59         /* Next higher priority with our extension */
60         struct ast_exten *peer;
61         /* Registrar */
62         char *registrar;
63         /* Extension with a greater ID */
64         struct ast_exten *next;
65 };
66
67 struct ast_include {
68         char name[AST_MAX_EXTENSION];
69         char *registrar;
70         struct ast_include *next;
71 };
72
73 /* An extension context */
74 struct ast_context {
75         /* Name of the context */
76         char name[AST_MAX_EXTENSION];
77         /* A lock to prevent multiple threads from clobbering the context */
78         pthread_mutex_t lock;
79         /* The root of the list of extensions */
80         struct ast_exten *root;
81         /* Link them together */
82         struct ast_context *next;
83         /* Include other contexts */
84         struct ast_include *includes;
85         /* Registrar */
86         char *registrar;
87 };
88
89
90 /* An application */
91 struct ast_app {
92         /* Name of the application */
93         char name[AST_MAX_APP];
94         int (*execute)(struct ast_channel *chan, void *data);
95         char *synopsis;
96         char *description;
97         struct ast_app *next;
98 };
99
100 static int pbx_builtin_prefix(struct ast_channel *, void *);
101 static int pbx_builtin_stripmsd(struct ast_channel *, void *);
102 static int pbx_builtin_answer(struct ast_channel *, void *);
103 static int pbx_builtin_goto(struct ast_channel *, void *);
104 static int pbx_builtin_hangup(struct ast_channel *, void *);
105 static int pbx_builtin_background(struct ast_channel *, void *);
106 static int pbx_builtin_dtimeout(struct ast_channel *, void *);
107 static int pbx_builtin_rtimeout(struct ast_channel *, void *);
108 static int pbx_builtin_wait(struct ast_channel *, void *);
109 static int pbx_builtin_setlanguage(struct ast_channel *, void *);
110 static int pbx_builtin_ringing(struct ast_channel *, void *);
111 static int pbx_builtin_congestion(struct ast_channel *, void *);
112 static int pbx_builtin_busy(struct ast_channel *, void *);
113
114 static struct pbx_builtin {
115         char name[AST_MAX_APP];
116         int (*execute)(struct ast_channel *chan, void *data);
117         char *synopsis;
118         char *description;
119 } builtins[] = 
120 {
121         /* These applications are built into the PBX core and do not
122            need separate modules */
123         { "Answer", pbx_builtin_answer, 
124                         "Answer a channel if ringing", 
125                         "  Answer(): If the channel is ringing, answer it, otherwise do nothing.  Returns 0 unless it\n"
126                         "  tries to answer the channel and fails.\n"   },
127         { "Goto", pbx_builtin_goto, 
128                         "Goto a particular priority, extension, or context",
129                         "  Goto([[context|]extension|]priority): Set the priority to the specified value, optionally setting\n"
130                         "  the extension and optionally the context as well.  The extension BYEXTENSION is special in that it\n"
131                         "  uses the current extension, thus permitting you to go to a different context, without specifying a\n"
132                         "  specific extension.  Always returns 0, even if the given context, extension, or priority is invalid.\n" },
133         { "Hangup", pbx_builtin_hangup,
134                         "Unconditional hangup",
135                         "  Hangup(): Unconditionally hangs up a given channel by returning -1 always.\n" },
136         { "DigitTimeout", pbx_builtin_dtimeout,
137                         "Set maximum timeout between digits",
138                         "  DigitTimeout(seconds): Set the maximum amount of time permitted between digits when the user is\n" 
139                         "  typing in an extension.  When this timeout expires, after the user has started to type in an\n"
140                         "  extension, the extension will be considered complete, and will be interpreted.  Note that if an\n"
141                         "  extension typed in is valid, it will not have to timeout to be tested, so typically at the expiry\n"
142                         "  of this timeout, the extension will be considered invalid (and thus control would be passed to the\n"
143                         "  'i' extension, or if it doesn't exist the call would be terminated).  Always returns 0.\n" },
144         { "ResponseTimeout", pbx_builtin_rtimeout,
145                         "Set maximum timeout awaiting response",
146                         "  ResponseTimeout(seconds): Set the maximum amount of time permitted after falling through a series\n"
147                         "  of priorities for a channel in which the user may begin typing an extension.  If the user does not\n"
148                         "  type an extension in this amount of time, control will pass to the 't' extension if it exists, and\n"
149                         "  if not the call would be terminated.  Always returns 0.\n"  },
150         { "BackGround", pbx_builtin_background,
151                         "Play a file while awaiting extension",
152                         "  Background(filename): Plays a given file, while simultaneously waiting for the user to begin typing\n"
153                         "  an extension.  The timeouts do not count until the last BackGround application as ended.  Always\n"
154                         "  returns 0.\n" },
155         { "Wait", pbx_builtin_wait, 
156                         "Waits for some time", 
157                         "  Wait(seconds): Waits for a specified number of seconds, then returns 0.\n" },
158         { "StripMSD", pbx_builtin_stripmsd, "Strip leading digits",
159                         "  StripMSD(count): Strips the leading 'count' digits from the channel's associated extension.  For\n"
160                         "  example, the number 5551212 when stripped with a count of 3 would be changed to 1212.  This app\n"
161                         "  always returns 0, and the PBX will continue processing at the next priority for the *new* extension.\n"
162                         "  So, for example, if priority 3 of 5551212 is StripMSD 3, the next step executed will be priority 4 of\n"
163                         "  1212.  If you switch into an extension which has no first step, the PBX will treat it as though\n"
164                         "  the user dialed an invalid extension.\n" },
165         { "Prefix", pbx_builtin_prefix, "Prepend leading digits",
166                         "  Prefix(digits): Prepends the digit string specified by digits to the channel's associated\n"
167                         "  extension.  For example, the number 1212 when prefixed with '555' will become 5551212.  This app\n"
168                         "  always returns 0, and the PBX will continue processing at the next priority for the *new* extension.\n"
169                         "  So, for example, if priority 3 of 1212 is Prefix 555, the next step executed will be priority 4 of\n"
170                         "  5551212.  If you switch into an extension which has no first step, the PBX will treat it as though\n"
171                         "  the user dialed an invalid extension.\n" },
172         { "SetLanguage", pbx_builtin_setlanguage, "Sets user language",
173                         "  SetLanguage(language): Set the channel language to 'language'.  This information is used for the\n"
174                         "  generation of numbers, and to select a natural language file when available.  For example, if\n"
175                         "  language is set to 'fr' and the file 'demo-congrats' is requested to be played, if the file \n"
176                         "  'demo-congrats-fr' exists, then it will play that file, and if not will play the normal \n"
177                         "  'demo-congrats'.  Always returns 0.\n"  },
178         { "Ringing", pbx_builtin_ringing, "Indicate ringing tone",
179                         "  Ringing(): Request that the channel indicate ringing tone to the user.  Always returns 0.\n" },
180         { "Congestion", pbx_builtin_congestion, "Indicate congestion and stop",
181                         "  Congestion(): Requests that the channel indicate congestion and then waits for the user to\n"
182                         "  hang up.  Always returns -1." },
183         { "Busy", pbx_builtin_busy, "Indicate busy condition and stop",
184                         "  Busy(): Requests that the channel indicate busy condition and then waits for the user to\n"
185                         "  hang up.  Always returns -1." },
186 };
187
188 /* Lock for the application list */
189 static pthread_mutex_t applock = PTHREAD_MUTEX_INITIALIZER;
190 static struct ast_context *contexts = NULL;
191 /* Lock for the ast_context list */
192 static pthread_mutex_t conlock = PTHREAD_MUTEX_INITIALIZER;
193 static struct ast_app *apps = NULL;
194
195 static int pbx_exec(struct ast_channel *c, /* Channel */
196                                         int (*execute)(struct ast_channel *chan, void *data), 
197                                         void *data,                             /* Data for execution */
198                                         int newstack)                   /* Force stack increment */
199 {
200         /* This function is special.  It saves the stack so that no matter
201            how many times it is called, it returns to the same place */
202         int res;
203         int stack = c->stack;
204         if (newstack && stack > AST_CHANNEL_MAX_STACK - 2) {
205                 /* Don't allow us to go over the max number of stacks we
206                    permit saving. */
207                 ast_log(LOG_WARNING, "Stack overflow, cannot create another stack\n");
208                 return -1;
209         }
210         if (newstack && (res = setjmp(c->jmp[++c->stack]))) {
211                 /* Okay, here's where it gets weird.  If newstack is non-zero, 
212                    then we increase the stack increment, but setjmp is not going
213                    to return until longjmp is called -- when the application
214                    exec'd is finished running. */
215                 if (res == 1)
216                         res = 0;
217                 if (c->stack != stack + 1) 
218                         ast_log(LOG_WARNING, "Stack returned to an unexpected place!\n");
219                 else if (c->app[c->stack])
220                         ast_log(LOG_WARNING, "Application may have forgotten to free its memory\n");
221                 c->stack = stack;
222                 return res;
223         } else {
224                 res = execute(c, data);
225                 /* Any application that returns, we longjmp back, just in case. */
226                 if (c->stack != stack + 1)
227                         ast_log(LOG_WARNING, "Stack is not at expected value\n");
228                 longjmp(c->jmp[stack+1], res);
229                 /* Never returns */
230         }
231 }
232
233
234 /* Go no deeper than this through includes (not counting loops) */
235 #define AST_PBX_MAX_STACK       64
236
237 #define HELPER_EXISTS 0
238 #define HELPER_SPAWN 1
239 #define HELPER_EXEC 2
240 #define HELPER_CANMATCH 3
241
242 static struct ast_app *pbx_findapp(char *app) 
243 {
244         struct ast_app *tmp;
245         if (ast_pthread_mutex_lock(&applock)) {
246                 ast_log(LOG_WARNING, "Unable to obtain application lock\n");
247                 return NULL;
248         }
249         tmp = apps;
250         while(tmp) {
251                 if (!strcasecmp(tmp->name, app))
252                         break;
253                 tmp = tmp->next;
254         }
255         ast_pthread_mutex_unlock(&applock);
256         return tmp;
257 }
258
259 static void pbx_destroy(struct ast_pbx *p)
260 {
261         free(p);
262 }
263
264 int ast_extension_match(char *pattern, char *data)
265 {
266         int match;
267         /* If they're the same return */
268         if (!strcasecmp(pattern, data))
269                 return 1;
270         /* All patterns begin with _ */
271         if (pattern[0] != '_') 
272                 return 0;
273         /* Obviously must be the same length */
274         if (strlen(pattern) != strlen(data) + 1)
275                 return 0;
276         /* Start optimistic */
277         match=1;
278         pattern++;
279         while(match && *data && *pattern) {
280                 switch(toupper(*pattern)) {
281                 case 'N':
282                         if ((*data < '2') || (*data > '9'))
283                                 match=0;
284                         break;
285                 case 'X':
286                         if ((*data < '0') || (*data > '9'))
287                                 match = 0;
288                         break;
289                 default:
290                         if (*data != *pattern)
291                                 match =0;
292                 }
293                 data++;
294                 pattern++;
295         }
296         return match;
297 }
298
299 static int extension_close(char *pattern, char *data)
300 {
301         int match;
302         /* If "data" is longer, it can'be a subset of pattern */
303         if (strlen(pattern) < strlen(data)) 
304                 return 0;
305         
306         
307         if (!strlen((char *)data) || !strncasecmp(pattern, data, strlen(data))) {
308                 return 1;
309         }
310         /* All patterns begin with _ */
311         if (pattern[0] != '_') 
312                 return 0;
313         /* Start optimistic */
314         match=1;
315         pattern++;
316         while(match && *data && *pattern) {
317                 switch(toupper(*pattern)) {
318                 case 'N':
319                         if ((*data < '2') || (*data > '9'))
320                                 match=0;
321                         break;
322                 case 'X':
323                         if ((*data < '0') || (*data > '9'))
324                                 match = 0;
325                         break;
326                 default:
327                         if (*data != *pattern)
328                                 match =0;
329                 }
330                 data++;
331                 pattern++;
332         }
333         return match;
334 }
335
336 struct ast_context *ast_context_find(char *name)
337 {
338         struct ast_context *tmp;
339         ast_pthread_mutex_lock(&conlock);
340         if (name) {
341                 tmp = contexts;
342                 while(tmp) {
343                         if (!strcasecmp(name, tmp->name))
344                                 break;
345                         tmp = tmp->next;
346                 }
347         } else
348                 tmp = contexts;
349         ast_pthread_mutex_unlock(&conlock);
350         return tmp;
351 }
352
353 #define STATUS_NO_CONTEXT   1
354 #define STATUS_NO_EXTENSION 2
355 #define STATUS_NO_PRIORITY  3
356 #define STATUS_SUCCESS      4
357
358 static struct ast_exten *pbx_find_extension(char *context, char *exten, int priority, int action, char *incstack[], int *stacklen, int *status)
359 {
360         int x;
361         struct ast_context *tmp;
362         struct ast_exten *e, *eroot;
363         struct ast_include *i;
364         /* Initialize status if appropriate */
365         if (!*stacklen)
366                 *status = STATUS_NO_CONTEXT;
367         /* Check for stack overflow */
368         if (*stacklen >= AST_PBX_MAX_STACK) {
369                 ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n");
370                 return NULL;
371         }
372         /* Check first to see if we've already been checked */
373         for (x=0;x<*stacklen;x++) {
374                 if (!strcasecmp(incstack[x], context))
375                         return NULL;
376         }
377         tmp = contexts;
378         while(tmp) {
379                 /* Match context */
380                 if (!strcasecmp(tmp->name, context)) {
381                         if (*status < STATUS_NO_EXTENSION)
382                                 *status = STATUS_NO_EXTENSION;
383                         eroot = tmp->root;
384                         while(eroot) {
385                                 /* Match extension */
386                                 if (ast_extension_match(eroot->exten, exten) ||
387                                                 ((action == HELPER_CANMATCH) && (extension_close(eroot->exten, exten)))) {
388                                                 e = eroot;
389                                                 if (*status < STATUS_NO_PRIORITY)
390                                                         *status = STATUS_NO_PRIORITY;
391                                                 while(e) {
392                                                         /* Match priority */
393                                                         if (e->priority == priority) {
394                                                                 *status = STATUS_SUCCESS;
395                                                                 return e;
396                                                         }
397                                                         e = e->peer;
398                                                 }
399                                 }
400                                 eroot = eroot->next;
401                         }
402                         /* Setup the stack */
403                         incstack[*stacklen] = tmp->name;
404                         (*stacklen)++;
405                         /* Now try any includes we have in this context */
406                         i = tmp->includes;
407                         while(i) {
408                                 if ((e = pbx_find_extension(i->name, exten, priority, action, incstack, stacklen, status))) 
409                                         return e;
410                                 i = i->next;
411                         }
412                 }
413                 tmp = tmp->next;
414         }
415         return NULL;
416 }
417
418 static int pbx_extension_helper(struct ast_channel *c, char *context, char *exten, int priority, int action) 
419 {
420         struct ast_exten *e;
421         struct ast_app *app;
422         int newstack = 0;
423         int res;
424         int status = 0;
425         char *incstack[AST_PBX_MAX_STACK];
426         int stacklen = 0;
427         if (ast_pthread_mutex_lock(&conlock)) {
428                 ast_log(LOG_WARNING, "Unable to obtain lock\n");
429                 if ((action == HELPER_EXISTS) || (action == HELPER_CANMATCH))
430                         return 0;
431                 else
432                         return -1;
433         }
434         e = pbx_find_extension(context, exten, priority, action, incstack, &stacklen, &status);
435         if (e) {
436                 switch(action) {
437                 case HELPER_CANMATCH:
438                         pthread_mutex_unlock(&conlock);
439                         return -1;
440                 case HELPER_EXISTS:
441                         pthread_mutex_unlock(&conlock);
442                         return -1;
443                 case HELPER_SPAWN:
444                         newstack++;
445                         /* Fall through */
446                 case HELPER_EXEC:
447                         app = pbx_findapp(e->app);
448                         pthread_mutex_unlock(&conlock);
449                         if (app) {
450                                 strncpy(c->context, context, sizeof(c->context));
451                                 strncpy(c->exten, exten, sizeof(c->exten));
452                                 c->priority = priority;
453                                 if (option_debug)
454                                                 ast_log(LOG_DEBUG, "Launching '%s'\n", app->name);
455                                 else if (option_verbose > 2)
456                                                 ast_verbose( VERBOSE_PREFIX_3 "Executing %s(\"%s\", \"%s\") %s\n", 
457                                                                 app->name, c->name, (e->data ? (char *)e->data : NULL), (newstack ? "in new stack" : "in same stack"));
458                                 c->appl = app->name;
459                                 c->data = e->data;              
460                                 res = pbx_exec(c, app->execute, e->data, newstack);
461                                 c->appl = NULL;
462                                 c->data = NULL;
463                                 pthread_mutex_unlock(&conlock);
464                                 return res;
465                         } else {
466                                 ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority);
467                                 return -1;
468                         }
469                 default:
470                         ast_log(LOG_WARNING, "Huh (%d)?\n", action);
471                         return -1;
472                 }
473         } else {
474                 pthread_mutex_unlock(&conlock);
475                 switch(status) {
476                 case STATUS_NO_CONTEXT:
477                         if (action != HELPER_EXISTS)
478                                 ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", context);
479                         break;
480                 case STATUS_NO_EXTENSION:
481                         if ((action != HELPER_EXISTS) && (action !=  HELPER_CANMATCH))
482                                 ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, context);
483                         break;
484                 case STATUS_NO_PRIORITY:
485                         if ((action != HELPER_EXISTS) && (action !=  HELPER_CANMATCH))
486                                 ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, context);
487                         break;
488                 default:
489                         ast_log(LOG_DEBUG, "Shouldn't happen!\n");
490                 }
491                 if ((action != HELPER_EXISTS) && (action != HELPER_CANMATCH))
492                         return -1;
493                 else
494                         return 0;
495         }
496
497 #if 0           
498         tmp = contexts;
499         while(tmp) {
500                 if (!strcasecmp(tmp->name, context)) {
501 #if 0
502                         /* By locking tmp, not only can the state of its entries not
503                            change, but it cannot be destroyed either. */
504                         ast_pthread_mutex_lock(&tmp->lock);
505 #endif
506                         e = tmp->root;
507                         while(e) {
508                                 if (extension_match(e->exten, exten) || 
509                                         ((action == HELPER_CANMATCH) && extension_close(e->exten, exten))) {
510                                         reale = e;
511                                         while(e) {
512                                                 if (e->priority == priority) {
513                                                         /* We have a winner! Maybe there are some races
514                                                            in here though. XXX */
515                                                         switch(action) {
516                                                         case HELPER_CANMATCH:
517                                                                 ast_pthread_mutex_unlock(&conlock);
518                                                                 return -1;
519                                                         case HELPER_EXISTS:
520                                                                 ast_pthread_mutex_unlock(&conlock);
521                                                                 return -1;
522                                                         case HELPER_SPAWN:
523                                                                 newstack++;
524                                                                 /* Fall through */
525                                                         case HELPER_EXEC:
526                                                                 app = pbx_findapp(e->app);
527                                                                 ast_pthread_mutex_unlock(&conlock);
528                                                                 if (app) {
529                                                                         strncpy(c->context, context, sizeof(c->context));
530                                                                         strncpy(c->exten, exten, sizeof(c->exten));
531                                                                         c->priority = priority;
532                                                                         if (option_debug)
533                                                                                 ast_log(LOG_DEBUG, "Launching '%s'\n", app->name);
534                                                                         else if (option_verbose > 2)
535                                                                                 ast_verbose( VERBOSE_PREFIX_3 "Executing %s(\"%s\", \"%s\") %s\n", 
536                                                                                                 app->name, c->name, (e->data ? (char *)e->data : NULL), (newstack ? "in new stack" : "in same stack"));
537                                                                         c->appl = app->name;
538                                                                         c->data = e->data;              
539                                                                         res = pbx_exec(c, app->execute, e->data, newstack);
540                                                                         c->appl = NULL;
541                                                                         c->data = NULL;
542                                                                         ast_pthread_mutex_unlock(&conlock);
543                                                                         return res;
544                                                                 } else {
545                                                                         ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority);
546                                                                         return -1;
547                                                                 }
548                                                         default:
549                                                                 ast_log(LOG_WARNING, "Huh (%d)?\n", action);
550                                                         }
551                                                 }
552                                                 e = e->peer;
553                                         }
554                                         ast_pthread_mutex_unlock(&tmp->lock);
555                                         if ((action != HELPER_EXISTS) && (action != HELPER_CANMATCH)) {
556                                                 ast_log(LOG_WARNING, "No such priority '%d' in '%s' in '%s'\n", priority, exten, context);
557                                                 ast_pthread_mutex_unlock(&conlock);
558                                                 return -1;
559                                         } else if (action != HELPER_CANMATCH) {
560                                                 ast_pthread_mutex_unlock(&conlock);
561                                                 return 0;
562                                         } else e = reale; /* Keep going */
563                                 }
564                                 e = e->next;
565                         }
566                         if ((action != HELPER_EXISTS) && (action != HELPER_CANMATCH)) {
567                                 ast_pthread_mutex_unlock(&conlock);
568                                 ast_log(LOG_WARNING, "No such extension '%s' in '%s'\n", exten, context);
569                                 return -1;
570                         } else {
571                                 ast_pthread_mutex_unlock(&conlock);
572                                 return 0;
573                         }
574                 }
575                 tmp = tmp->next;
576         }
577         ast_pthread_mutex_unlock(&conlock);
578         if (action != HELPER_EXISTS) {
579                 ast_log(LOG_WARNING, "No such context '%s'\n", context);
580                 return -1;
581         } else
582                 return 0;
583 #endif
584 }
585
586 int ast_pbx_longest_extension(char *context) 
587 {
588         /* XXX Not include-aware XXX */
589         struct ast_context *tmp;
590         struct ast_exten *e;
591         int len = 0;
592         if (ast_pthread_mutex_lock(&conlock)) {
593                 ast_log(LOG_WARNING, "Unable to obtain lock\n");
594                 return -1;
595         }
596         tmp = contexts;
597         while(tmp) {
598                 if (!strcasecmp(tmp->name, context)) {
599                         /* By locking tmp, not only can the state of its entries not
600                            change, but it cannot be destroyed either. */
601                         ast_pthread_mutex_lock(&tmp->lock);
602                         /* But we can relieve the conlock, as tmp will not change */
603                         ast_pthread_mutex_unlock(&conlock);
604                         e = tmp->root;
605                         while(e) {
606                                 if (strlen(e->exten) > len)
607                                         len = strlen(e->exten);
608                                 e = e->next;
609                         }
610                         ast_pthread_mutex_unlock(&tmp->lock);
611                         return len;
612                 }
613                 tmp = tmp->next;
614         }
615         ast_log(LOG_WARNING, "No such context '%s'\n", context);
616         return -1;
617 }
618
619 int ast_exists_extension(struct ast_channel *c, char *context, char *exten, int priority) 
620 {
621         return pbx_extension_helper(c, context, exten, priority, HELPER_EXISTS);
622 }
623
624 int ast_canmatch_extension(struct ast_channel *c, char *context, char *exten, int priority)
625 {
626         return pbx_extension_helper(c, context, exten, priority, HELPER_CANMATCH);
627 }
628
629 int ast_spawn_extension(struct ast_channel *c, char *context, char *exten, int priority) 
630 {
631         return pbx_extension_helper(c, context, exten, priority, HELPER_SPAWN);
632 }
633
634 int ast_pbx_run(struct ast_channel *c)
635 {
636         int firstpass = 1;
637         char digit;
638         char exten[256];
639         int pos;
640         int waittime;
641         int res=0;
642
643         /* A little initial setup here */
644         if (c->pbx)
645                 ast_log(LOG_WARNING, "%s already has PBX structure??\n");
646         c->pbx = malloc(sizeof(struct ast_pbx));
647         if (!c->pbx) {
648                 ast_log(LOG_WARNING, "Out of memory\n");
649                 return -1;
650         }
651         memset(c->pbx, 0, sizeof(struct ast_pbx));
652         /* Set reasonable defaults */
653         c->pbx->rtimeout = 10;
654         c->pbx->dtimeout = 5;
655
656         if (option_debug)
657                 ast_log(LOG_DEBUG, "PBX_THREAD(%s)\n", c->name);
658         else if (option_verbose > 1) {
659                 if (c->callerid)
660                         ast_verbose( VERBOSE_PREFIX_2 "Accepting call on '%s' (%s)\n", c->name, c->callerid);
661                 else
662                         ast_verbose( VERBOSE_PREFIX_2 "Accepting call on '%s'\n", c->name);
663         }
664                 
665         
666         /* Start by trying whatever the channel is set to */
667         if (!ast_exists_extension(c, c->context, c->exten, c->priority)) {
668                 strncpy(c->context, "default", sizeof(c->context));
669                 strncpy(c->exten, "s", sizeof(c->exten));
670                 c->priority = 1;
671         }
672         for(;;) {
673                 pos = 0;
674                 digit = 0;
675                 while(ast_exists_extension(c, c->context, c->exten, c->priority)) {
676                         memset(exten, 0, sizeof(exten));
677                         if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority))) {
678                                 /* Something bad happened, or a hangup has been requested. */
679                                 switch(res) {
680                                 case AST_PBX_KEEPALIVE:
681                                         if (option_debug)
682                                                 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
683                                         else if (option_verbose > 1)
684                                                 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
685                                 break;
686                                 default:
687                                         if (option_debug)
688                                                 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
689                                         else if (option_verbose > 1)
690                                                 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
691                                 }
692                                 goto out;
693                         }
694                         if (c->softhangup) {
695                                 ast_log(LOG_WARNING, "Extension %s, priority %d returned normally even though call was hung up\n",
696                                         c->exten, c->priority);
697                                 goto out;
698                         }
699                         /* If we're playing something in the background, wait for it to finish or for a digit */
700                         if (c->stream) {
701                                 digit = ast_waitstream(c, AST_DIGIT_ANY);
702                                 ast_stopstream(c);
703                                 /* Hang up if something goes wrong */
704                                 if (digit < 0) {
705                                         if (option_verbose > 2)
706                                                 ast_verbose(VERBOSE_PREFIX_3 "Lost connection on %s\n", c->name);
707                                         goto out;
708                                 }
709                                 else if (digit) {
710                                         exten[pos++] = digit;
711                                         break;
712                                 }
713                         }
714                         firstpass = 0;
715                         c->priority++;
716                 }
717                 if (!ast_exists_extension(c, c->context, c->exten, 1)) {
718                         /* It's not a valid extension anymore */
719                         if (ast_exists_extension(c, c->context, "i", 1)) {
720                                 if (option_verbose > 2)
721                                         ast_verbose(VERBOSE_PREFIX_3 "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, c->name);
722                                 strncpy(c->exten, "i", sizeof(c->exten));
723                                 c->priority = 1;
724                         } else {
725                                 ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n",
726                                         c->name, c->exten, c->context);
727                                 goto out;
728                         }
729                 } else {
730                         /* Done, wait for an extension */
731                         if (digit)
732                                 waittime = c->pbx->dtimeout;
733                         else
734                                 waittime = c->pbx->rtimeout;
735                         while(!ast_exists_extension(c, c->context, exten, 1) && 
736                                ast_canmatch_extension(c, c->context, exten, 1)) {
737                                 /* As long as we're willing to wait, and as long as it's not defined, 
738                                    keep reading digits until we can't possibly get a right answer anymore.  */
739                                 digit = ast_waitfordigit(c, waittime * 1000);
740                                 if (!digit)
741                                         /* No entry */
742                                         break;
743                                 if (digit < 0)
744                                         /* Error, maybe a  hangup */
745                                         goto out;
746                                 exten[pos++] = digit;
747                                 waittime = c->pbx->dtimeout;
748                         }
749                         if (ast_exists_extension(c, c->context, exten, 1)) {
750                                 /* Prepare the next cycle */
751                                 strncpy(c->exten, exten, sizeof(c->exten));
752                                 c->priority = 1;
753                         } else {
754                                 /* No such extension */
755                                 if (strlen(exten)) {
756                                         /* An invalid extension */
757                                         if (ast_exists_extension(c, c->context, "i", 1)) {
758                                                 if (option_verbose > 2)
759                                                         ast_verbose( VERBOSE_PREFIX_3 "Invalid extension '%s' in context '%s' on %s\n", exten, c->context, c->name);
760                                                 strncpy(c->exten, "i", sizeof(c->exten));
761                                                 c->priority = 1;
762                                         } else {
763                                                 ast_log(LOG_WARNING, "Invalid extension, but no rule 'i' in context '%s'\n", c->context);
764                                                 goto out;
765                                         }
766                                 } else {
767                                         /* A simple timeout */
768                                         if (ast_exists_extension(c, c->context, "t", 1)) {
769                                                 if (option_verbose > 2)
770                                                         ast_verbose( VERBOSE_PREFIX_3 "Timeout on %s\n", c->name);
771                                                 strncpy(c->exten, "t", sizeof(c->exten));
772                                                 c->priority = 1;
773                                         } else {
774                                                 ast_log(LOG_WARNING, "Timeout, but no rule 't' in context '%s'\n", c->context);
775                                                 goto out;
776                                         }
777                                 }       
778                         }
779                 }
780         }
781         if (firstpass) 
782                 ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name);
783 out:
784         pbx_destroy(c->pbx);
785         c->pbx = NULL;
786         if (res != AST_PBX_KEEPALIVE)
787                 ast_hangup(c);
788         return 0;
789 }
790
791 static void *pbx_thread(void *data)
792 {
793         /* Oh joyeous kernel, we're a new thread, with nothing to do but
794            answer this channel and get it going.  The setjmp stuff is fairly
795            confusing, but necessary to get smooth transitions between
796            the execution of different applications (without the use of
797            additional threads) */
798         struct ast_channel *c = data;
799         ast_pbx_run(c);
800         pthread_exit(NULL);
801         return NULL;
802 }
803
804 int ast_pbx_start(struct ast_channel *c)
805 {
806         pthread_t t;
807         pthread_attr_t attr;
808         if (!c) {
809                 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
810                 return -1;
811         }
812         /* Start a new thread, and get something handling this channel. */
813         pthread_attr_init(&attr);
814         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
815         if (pthread_create(&t, &attr, pbx_thread, c)) {
816                 ast_log(LOG_WARNING, "Failed to create new channel thread\n");
817                 return -1;
818         }
819         return 0;
820 }
821 #if 0
822 int ast_remove_extension(struct ast_context *con, char *extension, int priority)
823 {
824         /* XXX Implement me XXX */
825         return -1;
826 }
827 #endif
828 int ast_register_application(char *app, int (*execute)(struct ast_channel *, void *), char *synopsis, char *description)
829 {
830         struct ast_app *tmp;
831         if (ast_pthread_mutex_lock(&applock)) {
832                 ast_log(LOG_ERROR, "Unable to lock application list\n");
833                 return -1;
834         }
835         tmp = apps;
836         while(tmp) {
837                 if (!strcasecmp(app, tmp->name)) {
838                         ast_log(LOG_WARNING, "Already have an application '%s'\n", app);
839                         ast_pthread_mutex_unlock(&applock);
840                         return -1;
841                 }
842                 tmp = tmp->next;
843         }
844         tmp = malloc(sizeof(struct ast_app));
845         if (tmp) {
846                 strncpy(tmp->name, app, sizeof(tmp->name));
847                 tmp->execute = execute;
848                 tmp->synopsis = synopsis;
849                 tmp->description = description;
850                 tmp->next = apps;
851                 apps = tmp;
852         } else {
853                 ast_log(LOG_WARNING, "Out of memory\n");
854                 ast_pthread_mutex_unlock(&applock);
855                 return -1;
856         }
857         if (option_verbose > 1)
858                 ast_verbose( VERBOSE_PREFIX_2 "Registered application '%s'\n", tmp->name);
859         ast_pthread_mutex_unlock(&applock);
860         return 0;
861 }
862
863 static char app_help[] = 
864 "Usage: show application <application>\n"
865 "       Describes a particular application.\n";
866
867 static char apps_help[] =
868 "Usage: show applications\n"
869 "       List applications which are currently available.\n";
870
871 static char dialplan_help[] =
872 "Usage: show dialplan [[exten@]context]\n"
873 "       Displays dialplan.  Optionally takes a context (possibly preceeded by\n"
874 "       an extension) to limit the scope of the plan that is displayed.\n";
875
876 static int handle_show_applications(int fd, int argc, char *argv[])
877 {
878         struct ast_app *tmp;
879         char buf[256];
880         if (ast_pthread_mutex_lock(&applock)) {
881                 ast_log(LOG_ERROR, "Unable to lock application list\n");
882                 return -1;
883         }
884         tmp = apps;
885         ast_cli(fd, "\n    -= Registered Asterisk Applications =-\n");
886         while(tmp) {
887                 snprintf(buf, sizeof(buf), "  %15s: %s\n", tmp->name, tmp->synopsis ? tmp->synopsis : "<Synopsis not available>");
888                 ast_cli(fd, buf);
889                 tmp = tmp->next;
890         }
891         ast_pthread_mutex_unlock(&applock);
892         return RESULT_SUCCESS;
893 }
894
895 static char *complete_app(char *line, char *word, int pos, int state)
896 {
897         struct ast_app *tmp;
898         char *ret;
899         int which = 0;
900         if (ast_pthread_mutex_lock(&applock)) {
901                 ast_log(LOG_ERROR, "Unable to lock application list\n");
902                 return NULL;
903         }
904         tmp = apps;
905         while(tmp) {
906                 if (!strncasecmp(word, tmp->name, strlen(word))) {
907                         if (++which > state)
908                                 break;
909                 }
910                 tmp = tmp->next;
911         }
912         if (tmp)
913                 ret = tmp->name;
914         else
915                 ret = NULL;
916         ast_pthread_mutex_unlock(&applock);
917         
918         return ret ? strdup(ret) : ret;
919 }
920
921 static char *complete_context(char *line, char *word, int pos, int state)
922 {
923         struct ast_context *tmp;
924         char *ret;
925         int which = 0;
926         if (ast_pthread_mutex_lock(&conlock)) {
927                 ast_log(LOG_ERROR, "Unable to lock context list\n");
928                 return NULL;
929         }
930         tmp = contexts;
931         while(tmp) {
932                 if (!strncasecmp(word, tmp->name, strlen(word))) {
933                         if (++which > state)
934                                 break;
935                 }
936                 tmp = tmp->next;
937         }
938         if (tmp)
939                 ret = tmp->name;
940         else
941                 ret = NULL;
942         ast_pthread_mutex_unlock(&conlock);
943         
944         return ret ? strdup(ret) : ret;
945 }
946
947 static int handle_show_application(int fd, int argc, char *argv[])
948 {
949         struct ast_app *tmp;
950         char buf[2048];
951         if (argc != 3) 
952                 return RESULT_SHOWUSAGE;
953         if (ast_pthread_mutex_lock(&applock)) {
954                 ast_log(LOG_ERROR, "Unable to lock application list\n");
955                 return -1;
956         }
957         tmp = apps;
958         while(tmp) {
959                 if (!strcasecmp(tmp->name, argv[2])) {
960                         snprintf(buf, sizeof(buf), "\n  -= About Application '%s' =- \n\n"
961                                                                            "[Synopsis]:\n  %s\n\n"
962                                                                            "[Description:]\n%s\n\n", tmp->name, tmp->synopsis ? 
963                                                                                         tmp->synopsis : "Not available", tmp->description ?
964                                                                                                 tmp->description : "Not available\n");
965                         break;
966                 }
967                 tmp = tmp->next;
968         }
969         ast_pthread_mutex_unlock(&applock);
970         if (!tmp) 
971                 snprintf(buf, sizeof(buf), "No such application '%s' is registered.\n", argv[2]);
972         ast_cli(fd, buf);
973         return RESULT_SUCCESS;
974 }
975
976 static int handle_dialplan(int fd, int argc, char *argv[])
977 {
978         struct ast_context *con;
979         struct ast_exten *eroot, *e;
980         struct ast_include *inc;
981         char tmp[512];
982         char cpy[512];
983         char tmp2[512];
984         char *context;
985         char *exten;
986         int spaces;
987         
988         if ((argc < 2) || (argc > 3))
989                 return RESULT_SHOWUSAGE;
990
991         if (argc > 2) {
992                 strncpy(cpy, argv[2], sizeof(cpy));
993                 if ((context = strchr(cpy, '@'))) {
994                         *context = '\0';
995                         context++;
996                         exten = cpy;
997                 } else {
998                         context = cpy;
999                         exten = NULL;
1000                 }
1001         } else {
1002                 context = NULL;
1003                 exten = NULL;
1004         }
1005         ast_pthread_mutex_lock(&conlock);
1006         con = contexts;
1007         while(con) {
1008                 if (!context || (!strcasecmp(context, con->name))) {
1009                         ast_cli(fd, "\n [ Context '%s' created by '%s']\n", con->name, con->registrar);
1010                         eroot = con->root;
1011                         while(eroot) {
1012                                 if (!exten || (!strcasecmp(exten, eroot->exten))) {
1013                                         memset(tmp, ' ', sizeof(tmp));
1014                                         snprintf(tmp, sizeof(tmp), "  '%s' => ", eroot->exten);
1015                                         spaces = strlen(tmp);
1016                                         tmp[spaces] = ' ';
1017                                         if (spaces < 19)
1018                                                 spaces = 19;
1019                                         snprintf(tmp2, sizeof(tmp2), "%d. %s(%s)", eroot->priority, eroot->app, (char *)eroot->data);
1020                                         snprintf(tmp + spaces, sizeof(tmp) - spaces,     "%-45s [%s]\n", 
1021                                                         tmp2, eroot->registrar);
1022                                         ast_cli(fd, tmp);
1023                                         memset(tmp, ' ', spaces);
1024                                         e = eroot->peer;
1025                                         while(e) {
1026                                                 snprintf(tmp2, sizeof(tmp2), "%d. %s(%s)", e->priority, e->app, (char *)e->data);
1027                                                 snprintf(tmp + spaces, sizeof(tmp) - spaces,     "%-45s [%s]\n", 
1028                                                         tmp2, e->registrar);
1029                                                 ast_cli(fd, tmp);
1030                                                 e = e->peer;
1031                                         }
1032                                 }
1033                                 eroot = eroot->next;
1034                         }
1035                         inc = con->includes;
1036                         while(inc) {
1037                                 snprintf(tmp, sizeof(tmp), "   Include =>    '%s'", inc->name);
1038                                 ast_cli(fd, "%s [%s]\n", tmp, inc->registrar);
1039                                 inc = inc->next;
1040                         }
1041                 }
1042                 con = con->next;
1043         }
1044         ast_pthread_mutex_unlock(&conlock);
1045         return RESULT_SUCCESS;
1046 }
1047
1048 static struct ast_cli_entry showapps = { { "show", "applications", NULL }, 
1049         handle_show_applications, "Shows registered applications", apps_help };
1050
1051 static struct ast_cli_entry showdialplan = { { "show", "dialplan", NULL }, 
1052         handle_dialplan, "Displays all or part of dialplan", dialplan_help, complete_context };
1053
1054 static struct ast_cli_entry showapp = { { "show", "application", NULL }, 
1055         handle_show_application, "Describe a specific application", app_help, complete_app };
1056         
1057 int ast_unregister_application(char *app) {
1058         struct ast_app *tmp, *tmpl = NULL;
1059         if (ast_pthread_mutex_lock(&applock)) {
1060                 ast_log(LOG_ERROR, "Unable to lock application list\n");
1061                 return -1;
1062         }
1063         tmp = apps;
1064         while(tmp) {
1065                 if (!strcasecmp(app, tmp->name)) {
1066                         if (tmpl)
1067                                 tmpl->next = tmp->next;
1068                         else
1069                                 apps = tmp->next;
1070                         if (option_verbose > 1)
1071                                 ast_verbose( VERBOSE_PREFIX_2 "Unregistered application '%s'\n", tmp->name);
1072                         ast_pthread_mutex_unlock(&applock);
1073                         return 0;
1074                 }
1075                 tmpl = tmp;
1076                 tmp = tmp->next;
1077         }
1078         ast_pthread_mutex_unlock(&applock);
1079         return -1;
1080 }
1081
1082 struct ast_context *ast_context_create(char *name, char *registrar)
1083 {
1084         struct ast_context *tmp;
1085         
1086         ast_pthread_mutex_lock(&conlock);
1087         tmp = contexts;
1088         while(tmp) {
1089                 if (!strcasecmp(tmp->name, name)) {
1090                         ast_pthread_mutex_unlock(&conlock);
1091                         ast_log(LOG_WARNING, "Tried to register context '%s', already in use\n", name);
1092                         return NULL;
1093                 }
1094                 tmp = tmp->next;
1095         }
1096         tmp = malloc(sizeof(struct ast_context));
1097         if (tmp) {
1098                 pthread_mutex_init(&tmp->lock, NULL);
1099                 strncpy(tmp->name, name, sizeof(tmp->name));
1100                 tmp->root = NULL;
1101                 tmp->registrar = registrar;
1102                 tmp->next = contexts;
1103                 tmp->includes = NULL;
1104                 contexts = tmp;
1105                 if (option_debug)
1106                         ast_log(LOG_DEBUG, "Registered context '%s'\n", tmp->name);
1107                 else if (option_verbose > 2)
1108                         ast_verbose( VERBOSE_PREFIX_3 "Registered extension context '%s'\n", tmp->name);
1109         } else
1110                 ast_log(LOG_WARNING, "Out of memory\n");
1111         
1112         ast_pthread_mutex_unlock(&conlock);
1113         return tmp;
1114 }
1115
1116 int ast_context_add_include2(struct ast_context *con, char *value, char *registrar)
1117 {
1118         struct ast_include *inc, *incc, *incl = NULL;
1119         inc = malloc(sizeof(struct ast_include));
1120         if (!inc) {
1121                 ast_log(LOG_WARNING, "Out of memory\n");
1122                 return -1;
1123         }
1124         strncpy(inc->name, value, sizeof(inc->name));
1125         inc->next = NULL;
1126         inc->registrar = registrar;
1127         pthread_mutex_lock(&con->lock);
1128         incc = con->includes;
1129         while(incc) {
1130                 incl = incc;
1131                 if (!strcasecmp(incc->name, value)) {
1132                         /* Already there */
1133                         pthread_mutex_unlock(&con->lock);
1134                         return 0;
1135                 }
1136                 incc = incc->next;
1137         }
1138         if (incl) 
1139                 incl->next = inc;
1140         else
1141                 con->includes = inc;
1142         pthread_mutex_unlock(&con->lock);
1143         return 0;
1144         
1145 }
1146
1147 int ast_add_extension2(struct ast_context *con,
1148                                           int replace, char *extension, int priority,
1149                                           char *application, void *data, void (*datad)(void *),
1150                                           char *registrar)
1151 {
1152
1153 #define LOG {   if (option_debug) \
1154                 ast_log(LOG_DEBUG, "Added extension '%s' priority %d to %s\n", tmp->exten, tmp->priority, con->name); \
1155         else if (option_verbose > 2) \
1156                 ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d to %s\n", tmp->exten, tmp->priority, con->name); \
1157                 }
1158
1159         /*
1160          * This is a fairly complex routine.  Different extensions are kept
1161          * in order by the extension number.  Then, extensions of different
1162          * priorities (same extension) are kept in a list, according to the
1163          * peer pointer.
1164          */
1165         struct ast_exten *tmp, *e, *el = NULL, *ep = NULL;
1166         int res;
1167         /* Be optimistic:  Build the extension structure first */
1168         tmp = malloc(sizeof(struct ast_exten));
1169         if (tmp) {
1170                 strncpy(tmp->exten, extension, sizeof(tmp->exten));
1171                 tmp->priority = priority;
1172                 strncpy(tmp->app, application, sizeof(tmp->app));
1173                 tmp->data = data;
1174                 tmp->datad = datad;
1175                 tmp->registrar = registrar;
1176                 tmp->peer = NULL;
1177                 tmp->next =  NULL;
1178         } else {
1179                 ast_log(LOG_WARNING, "Out of memory\n");
1180                 return -1;
1181         }
1182         if (ast_pthread_mutex_lock(&con->lock)) {
1183                 free(tmp);
1184                 /* And properly destroy the data */
1185                 datad(data);
1186                 ast_log(LOG_WARNING, "Failed to lock context '%s'\n", con->name);
1187                 return -1;
1188         }
1189         e = con->root;
1190         while(e) {
1191                 res= strcasecmp(e->exten, extension);
1192                 if (res == 0) {
1193                         /* We have an exact match, now we find where we are
1194                            and be sure there's no duplicates */
1195                         while(e) {
1196                                 if (e->priority == tmp->priority) {
1197                                         /* Can't have something exactly the same.  Is this a
1198                                            replacement?  If so, replace, otherwise, bonk. */
1199                                         if (replace) {
1200                                                 if (ep) {
1201                                                         /* We're in the peer list, insert ourselves */
1202                                                         ep->peer = tmp;
1203                                                         tmp->peer = e->peer;
1204                                                 } else if (el) {
1205                                                         /* We're the first extension. Take over e's functions */
1206                                                         el->next = tmp;
1207                                                         tmp->next = e->next;
1208                                                         tmp->peer = e->peer;
1209                                                 } else {
1210                                                         /* We're the very first extension.  */
1211                                                         con->root = tmp;
1212                                                         tmp->next = e->next;
1213                                                         tmp->peer = e->peer;
1214                                                 }
1215                                                 /* Destroy the old one */
1216                                                 e->datad(e->data);
1217                                                 free(e);
1218                                                 ast_pthread_mutex_unlock(&con->lock);
1219                                                 /* And immediately return success. */
1220                                                 LOG;
1221                                                 return 0;
1222                                         } else {
1223                                                 ast_log(LOG_WARNING, "Unable to register extension '%s', priority %d in '%s', already in use\n", tmp->exten, tmp->priority, con->name);
1224                                                 tmp->datad(tmp->data);
1225                                                 free(tmp);
1226                                                 ast_pthread_mutex_unlock(&con->lock);
1227                                                 return -1;
1228                                         }
1229                                 } else if (e->priority > tmp->priority) {
1230                                         /* Slip ourselves in just before e */
1231                                         if (ep) {
1232                                                 /* Easy enough, we're just in the peer list */
1233                                                 ep->peer = tmp;
1234                                                 tmp->peer = e;
1235                                         } else if (el) {
1236                                                 /* We're the first extension in this peer list */
1237                                                 el->next = tmp;
1238                                                 tmp->next = e->next;
1239                                                 e->next = NULL;
1240                                                 tmp->peer = e;
1241                                         } else {
1242                                                 /* We're the very first extension altogether */
1243                                                 tmp->next = con->root;
1244                                                 /* Con->root must always exist or we couldn't get here */
1245                                                 tmp->peer = con->root->peer;
1246                                                 con->root = tmp;
1247                                         }
1248                                         ast_pthread_mutex_unlock(&con->lock);
1249                                         /* And immediately return success. */
1250                                         LOG;
1251                                         return 0;
1252                                 }
1253                                 ep = e;
1254                                 e = e->peer;
1255                         }
1256                         /* If we make it here, then it's time for us to go at the very end.
1257                            ep *must* be defined or we couldn't have gotten here. */
1258                         ep->peer = tmp;
1259                         ast_pthread_mutex_unlock(&con->lock);
1260                         /* And immediately return success. */
1261                         LOG;
1262                         return 0;
1263                                 
1264                 } else if (res > 0) {
1265                         /* Insert ourselves just before 'e'.  We're the first extension of
1266                            this kind */
1267                         tmp->next = e;
1268                         if (el) {
1269                                 /* We're in the list somewhere */
1270                                 el->next = tmp;
1271                         } else {
1272                                 /* We're at the top of the list */
1273                                 con->root = tmp;
1274                         }
1275                         ast_pthread_mutex_unlock(&con->lock);
1276                         /* And immediately return success. */
1277                         LOG;
1278                         return 0;
1279                 }                       
1280                         
1281                 el = e;
1282                 e = e->next;
1283         }
1284         /* If we fall all the way through to here, then we need to be on the end. */
1285         if (el)
1286                 el->next = tmp;
1287         else
1288                 con->root = tmp;
1289         ast_pthread_mutex_unlock(&con->lock);
1290         LOG;
1291         return 0;       
1292 }
1293
1294 void ast_context_destroy(struct ast_context *con, char *registrar)
1295 {
1296         struct ast_context *tmp, *tmpl=NULL;
1297         struct ast_include *tmpi, *tmpil= NULL;
1298         ast_pthread_mutex_lock(&conlock);
1299         tmp = contexts;
1300         while(tmp) {
1301                 if (((tmp == con) || !con) &&
1302                     (!registrar || !strcasecmp(registrar, tmp->registrar))) {
1303                         /* Okay, let's lock the structure to be sure nobody else
1304                            is searching through it. */
1305                         if (ast_pthread_mutex_lock(&tmp->lock)) {
1306                                 ast_log(LOG_WARNING, "Unable to lock context lock\n");
1307                                 return;
1308                         }
1309                         if (tmpl)
1310                                 tmpl->next = tmp->next;
1311                         else
1312                                 contexts = tmp->next;
1313                         /* Okay, now we're safe to let it go -- in a sense, we were
1314                            ready to let it go as soon as we locked it. */
1315                         ast_pthread_mutex_unlock(&tmp->lock);
1316                         for (tmpi = tmp->includes; tmpi; ) {
1317                                 /* Free includes */
1318                                 tmpil = tmpi;
1319                                 tmpi = tmpi->next;
1320                                 free(tmpil);
1321                                 tmpil = tmpi;
1322                         }
1323                         free(tmp);
1324                         if (!con) {
1325                                 /* Might need to get another one -- restart */
1326                                 tmp = contexts;
1327                                 tmpl = NULL;
1328                                 tmpil = NULL;
1329                                 continue;
1330                         }
1331                         ast_pthread_mutex_unlock(&conlock);
1332                         return;
1333                 }
1334                 tmpl = tmp;
1335                 tmp = tmp->next;
1336         }
1337         ast_pthread_mutex_unlock(&conlock);
1338 }
1339
1340 static void wait_for_hangup(struct ast_channel *chan)
1341 {
1342         int res;
1343         struct ast_frame *f;
1344         do {
1345                 res = ast_waitfor(chan, -1);
1346                 if (res < 0)
1347                         return;
1348                 f = ast_read(chan);
1349                 if (f)
1350                         ast_frfree(f);
1351         } while(f);
1352 }
1353
1354 static int pbx_builtin_ringing(struct ast_channel *chan, void *data)
1355 {
1356         ast_indicate(chan, AST_CONTROL_RINGING);
1357         return 0;
1358 }
1359
1360 static int pbx_builtin_busy(struct ast_channel *chan, void *data)
1361 {
1362         ast_indicate(chan, AST_CONTROL_BUSY);           
1363         wait_for_hangup(chan);
1364         return -1;
1365 }
1366
1367 static int pbx_builtin_congestion(struct ast_channel *chan, void *data)
1368 {
1369         ast_indicate(chan, AST_CONTROL_CONGESTION);
1370         wait_for_hangup(chan);
1371         return -1;
1372 }
1373
1374 static int pbx_builtin_answer(struct ast_channel *chan, void *data)
1375 {
1376         if (chan->state != AST_STATE_RING) {
1377                 if (option_debug)
1378                         ast_log(LOG_DEBUG, "Ignoring answer request since line is not ringing\n");
1379                 return 0;
1380         } else
1381                 return ast_answer(chan);
1382 }
1383
1384 static int pbx_builtin_setlanguage(struct ast_channel *chan, void *data)
1385 {
1386         /* Copy the language as specified */
1387         strncpy(chan->language, (char *)data, sizeof(chan->language));
1388         return 0;
1389 }
1390
1391 static int pbx_builtin_hangup(struct ast_channel *chan, void *data)
1392 {
1393         /* Just return non-zero and it will hang up */
1394         return -1;
1395 }
1396
1397 static int pbx_builtin_stripmsd(struct ast_channel *chan, void *data)
1398 {
1399         char newexten[AST_MAX_EXTENSION] = "";
1400         if (!data || !atoi(data)) {
1401                 ast_log(LOG_DEBUG, "Ignoring, since number of digits to strip is 0\n");
1402                 return 0;
1403         }
1404         if (strlen(chan->exten) > atoi(data)) {
1405                 strncpy(newexten, chan->exten + atoi(data), sizeof(newexten));
1406         }
1407         strncpy(chan->exten, newexten, sizeof(chan->exten));
1408         return 0;
1409 }
1410
1411 static int pbx_builtin_prefix(struct ast_channel *chan, void *data)
1412 {
1413         char newexten[AST_MAX_EXTENSION] = "";
1414         if (!data || !strlen(data)) {
1415                 ast_log(LOG_DEBUG, "Ignoring, since there is no prefix to add\n");
1416                 return 0;
1417         }
1418         snprintf(newexten, sizeof(newexten), "%s%s", (char *)data, chan->exten);
1419         strncpy(chan->exten, newexten, sizeof(chan->exten));
1420         if (option_verbose > 2)
1421                 ast_verbose(VERBOSE_PREFIX_3 "Prepended prefix, new extension is %s\n", chan->exten);
1422         return 0;
1423 }
1424
1425 static int pbx_builtin_wait(struct ast_channel *chan, void *data)
1426 {
1427         /* Wait for "n" seconds */
1428         if (data && atoi((char *)data))
1429                 sleep(atoi((char *)data));
1430         return 0;
1431 }
1432
1433 static int pbx_builtin_background(struct ast_channel *chan, void *data)
1434 {
1435         int res;
1436         /* Answer if need be */
1437         if (chan->state != AST_STATE_UP)
1438                 if (ast_answer(chan))
1439                         return -1;
1440         /* Stop anything playing */
1441         ast_stopstream(chan);
1442         /* Stream a file */
1443         res = ast_streamfile(chan, (char *)data, chan->language);
1444         return res;
1445 }
1446
1447 static int pbx_builtin_rtimeout(struct ast_channel *chan, void *data)
1448 {
1449         /* Set the timeout for how long to wait between digits */
1450         chan->pbx->rtimeout = atoi((char *)data);
1451         if (option_verbose > 2)
1452                 ast_verbose( VERBOSE_PREFIX_3 "Set Response Timeout to %d\n", chan->pbx->rtimeout);
1453         return 0;
1454 }
1455
1456 static int pbx_builtin_dtimeout(struct ast_channel *chan, void *data)
1457 {
1458         /* Set the timeout for how long to wait between digits */
1459         chan->pbx->dtimeout = atoi((char *)data);
1460         if (option_verbose > 2)
1461                 ast_verbose( VERBOSE_PREFIX_3 "Set Digit Timeout to %d\n", chan->pbx->dtimeout);
1462         return 0;
1463 }
1464
1465 static int pbx_builtin_goto(struct ast_channel *chan, void *data)
1466 {
1467         char *s;
1468         char *exten, *pri, *context;
1469         if (!data) {
1470                 ast_log(LOG_WARNING, "Goto requires an argument (optional context|optional extension|priority)\n");
1471                 return -1;
1472         }
1473         s = strdup((void *) data);
1474         context = strtok(s, "|");
1475         exten = strtok(NULL, "|");
1476         if (!exten) {
1477                 /* Only a priority in this one */
1478                 pri = context;
1479                 exten = NULL;
1480                 context = NULL;
1481         } else {
1482                 pri = strtok(NULL, "|");
1483                 if (!pri) {
1484                         /* Only an extension and priority in this one */
1485                         pri = exten;
1486                         exten = context;
1487                         context = NULL;
1488                 }
1489         }
1490         if (atoi(pri) < 0) {
1491                 ast_log(LOG_WARNING, "Priority '%s' must be a number > 0\n", pri);
1492                 free(s);
1493                 return -1;
1494         }
1495         /* At this point we have a priority and maybe an extension and a context */
1496         chan->priority = atoi(pri) - 1;
1497         if (exten && strcasecmp(exten, "BYEXTENSION"))
1498                 strncpy(chan->exten, exten, sizeof(chan->exten));
1499         if (context)
1500                 strncpy(chan->context, context, sizeof(chan->context));
1501         if (option_verbose > 2)
1502                 ast_verbose( VERBOSE_PREFIX_3 "Goto (%s,%s,%d)\n", chan->context,chan->exten, chan->priority+1);
1503         return 0;
1504 }
1505
1506 int load_pbx(void)
1507 {
1508         int x;
1509         /* Initialize the PBX */
1510         if (option_verbose) {
1511                 ast_verbose( "Asterisk PBX Core Initializing\n");
1512                 ast_verbose( "Registering builtin applications:\n");
1513         }
1514         ast_cli_register(&showapps);
1515         ast_cli_register(&showapp);
1516         ast_cli_register(&showdialplan);
1517         for (x=0;x<sizeof(builtins) / sizeof(struct pbx_builtin); x++) {
1518                 if (option_verbose)
1519                         ast_verbose( VERBOSE_PREFIX_1 "[%s]\n", builtins[x].name);
1520                 if (ast_register_application(builtins[x].name, builtins[x].execute, builtins[x].synopsis, builtins[x].description)) {
1521                         ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name);
1522                         return -1;
1523                 }
1524         }
1525         return 0;
1526 }
1527