Version 0.1.1 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/pbx.h>
16 #include <asterisk/channel.h>
17 #include <asterisk/options.h>
18 #include <asterisk/logger.h>
19 #include <asterisk/file.h>
20 #include <string.h>
21 #include <unistd.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <setjmp.h>
25 #include <ctype.h>
26 #include "asterisk.h"
27
28 /*
29  * I M P O R T A N T :
30  *
31  *              The speed of extension handling will likely be among the most important
32  * aspects of this PBX.  The switching scheme as it exists right now isn't
33  * terribly bad (it's O(N+M), where N is the # of extensions and M is the avg #
34  * of priorities, but a constant search time here would be great ;-) 
35  *
36  */
37
38
39 struct ast_context;
40
41 struct ast_pbx {
42         int dtimeout;                                   /* Timeout between digits (seconds) */
43         int rtimeout;                                   /* Timeout for response (seconds) */
44 };
45
46 /* An extension */
47 struct ast_exten {
48         char exten[AST_MAX_EXTENSION];
49         int priority;
50         /* An extension */
51         struct ast_context *parent;
52         /* Application to execute */
53         char app[AST_MAX_EXTENSION];
54         /* Data to use */
55         void *data;
56         /* Data destructor */
57         void (*datad)(void *);
58         /* Next highest priority with our extension */
59         struct ast_exten *peer;
60         /* Extension with a greater ID */
61         struct ast_exten *next;
62 };
63
64 /* An extension context */
65 struct ast_context {
66         /* Name of the context */
67         char name[AST_MAX_EXTENSION];
68         /* A lock to prevent multiple threads from clobbering the context */
69         pthread_mutex_t lock;
70         /* The root of the list of extensions */
71         struct ast_exten *root;
72         /* Link them together */
73         struct ast_context *next;
74 };
75
76
77 /* An application */
78 struct ast_app {
79         /* Name of the application */
80         char name[AST_MAX_APP];
81         int (*execute)(struct ast_channel *chan, void *data);
82         struct ast_app *next;
83 };
84
85 static int pbx_builtin_answer(struct ast_channel *, void *);
86 static int pbx_builtin_goto(struct ast_channel *, void *);
87 static int pbx_builtin_hangup(struct ast_channel *, void *);
88 static int pbx_builtin_background(struct ast_channel *, void *);
89 static int pbx_builtin_dtimeout(struct ast_channel *, void *);
90 static int pbx_builtin_rtimeout(struct ast_channel *, void *);
91 static int pbx_builtin_wait(struct ast_channel *, void *);
92
93 static struct pbx_builtin {
94         char name[AST_MAX_APP];
95         int (*execute)(struct ast_channel *chan, void *data);
96 } builtins[] = 
97 {
98         /* These applications are built into the PBX core and do not
99            need separate modules */
100         { "Answer", pbx_builtin_answer },
101         { "Goto", pbx_builtin_goto },
102         { "Hangup", pbx_builtin_hangup },
103         { "DigitTimeout", pbx_builtin_dtimeout },
104         { "ResponseTimeout", pbx_builtin_rtimeout },
105         { "BackGround", pbx_builtin_background },
106         { "Wait", pbx_builtin_wait },
107 };
108
109 /* Lock for the application list */
110 static pthread_mutex_t applock = PTHREAD_MUTEX_INITIALIZER;
111 static struct ast_context *contexts = NULL;
112 /* Lock for the ast_context list */
113 static pthread_mutex_t conlock = PTHREAD_MUTEX_INITIALIZER;
114 static struct ast_app *apps = NULL;
115
116 static int pbx_exec(struct ast_channel *c, /* Channel */
117                                         int (*execute)(struct ast_channel *chan, void *data), 
118                                         void *data,                             /* Data for execution */
119                                         int newstack)                   /* Force stack increment */
120 {
121         /* This function is special.  It saves the stack so that no matter
122            how many times it is called, it returns to the same place */
123         int res;
124         int stack = c->stack;
125         if (newstack && stack > AST_CHANNEL_MAX_STACK - 2) {
126                 /* Don't allow us to go over the max number of stacks we
127                    permit saving. */
128                 ast_log(LOG_WARNING, "Stack overflow, cannot create another stack\n");
129                 return -1;
130         }
131         if (newstack && (res = setjmp(c->jmp[++c->stack]))) {
132                 /* Okay, here's where it gets weird.  If newstack is non-zero, 
133                    then we increase the stack increment, but setjmp is not going
134                    to return until longjmp is called -- when the application
135                    exec'd is finished running. */
136                 if (res == 1)
137                         res = 0;
138                 if (c->stack != stack + 1) 
139                         ast_log(LOG_WARNING, "Stack returned to an unexpected place!\n");
140                 else if (c->app[c->stack])
141                         ast_log(LOG_WARNING, "Application may have forgotten to free its memory\n");
142                 c->stack = stack;
143                 return res;
144         } else {
145                 res = execute(c, data);
146                 /* Any application that returns, we longjmp back, just in case. */
147                 if (c->stack != stack + 1)
148                         ast_log(LOG_WARNING, "Stack is not at expected value\n");
149                 longjmp(c->jmp[stack+1], res);
150                 /* Never returns */
151         }
152 }
153
154
155 #define HELPER_EXISTS 0
156 #define HELPER_SPAWN 1
157 #define HELPER_EXEC 2
158
159 static struct ast_app *pbx_findapp(char *app) 
160 {
161         struct ast_app *tmp;
162         if (pthread_mutex_lock(&applock)) {
163                 ast_log(LOG_WARNING, "Unable to obtain application lock\n");
164                 return NULL;
165         }
166         tmp = apps;
167         while(tmp) {
168                 if (!strcasecmp(tmp->name, app))
169                         break;
170                 tmp = tmp->next;
171         }
172         pthread_mutex_unlock(&applock);
173         return tmp;
174 }
175
176 static void pbx_destroy(struct ast_pbx *p)
177 {
178         free(p);
179 }
180
181 static int extension_match(char *pattern, char *data)
182 {
183         int match;
184         /* If they're the same return */
185         if (!strcasecmp(pattern, data))
186                 return 1;
187         /* All patterns begin with _ */
188         if (pattern[0] != '_') 
189                 return 0;
190         /* Obviously must be the same length */
191         if (strlen(pattern) != strlen(data) + 1)
192                 return 0;
193         /* Start optimistic */
194         match=1;
195         pattern++;
196         while(match && *data && *pattern) {
197                 switch(toupper(*pattern)) {
198                 case 'N':
199                         if ((*data < '2') || (*data > '9'))
200                                 match=0;
201                         break;
202                 case 'X':
203                         if ((*data < '0') || (*data > '9'))
204                                 match = 0;
205                         break;
206                 default:
207                         if (*data != *pattern)
208                                 match =0;
209                 }
210                 data++;
211                 pattern++;
212         }
213         return match;
214 }
215
216 static int pbx_extension_helper(struct ast_channel *c, char *context, char *exten, int priority, int action) 
217 {
218         struct ast_context *tmp;
219         struct ast_exten *e;
220         struct ast_app *app;
221         int newstack = 0;
222         int res;
223         if (pthread_mutex_lock(&conlock)) {
224                 ast_log(LOG_WARNING, "Unable to obtain lock\n");
225                 if (action == HELPER_EXISTS)
226                         return 0;
227                 else
228                         return -1;
229         }
230         tmp = contexts;
231         while(tmp) {
232                 if (!strcasecmp(tmp->name, context)) {
233                         /* By locking tmp, not only can the state of its entries not
234                            change, but it cannot be destroyed either. */
235                         pthread_mutex_lock(&tmp->lock);
236                         /* But we can relieve the conlock, as tmp will not change */
237                         pthread_mutex_unlock(&conlock);
238                         e = tmp->root;
239                         while(e) {
240                                 if (extension_match(e->exten, exten)) {
241                                         while(e) {
242                                                 if (e->priority == priority) {
243                                                         pthread_mutex_unlock(&tmp->lock);
244                                                         /* We have a winner! Maybe there are some races
245                                                            in here though. XXX */
246                                                         switch(action) {
247                                                         case HELPER_EXISTS:
248                                                                 return -1;
249                                                         case HELPER_SPAWN:
250                                                                 newstack++;
251                                                                 /* Fall through */
252                                                         case HELPER_EXEC:
253                                                                 app = pbx_findapp(e->app);
254                                                                 if (app) {
255                                                                         strncpy(c->context, context, sizeof(c->context));
256                                                                         strncpy(c->exten, exten, sizeof(c->exten));
257                                                                         c->priority = priority;
258                                                                         if (option_debug)
259                                                                                 ast_log(LOG_DEBUG, "Launching '%s'\n", app->name);
260                                                                         else if (option_verbose > 2)
261                                                                                 ast_verbose( VERBOSE_PREFIX_3 "Executing %s(\"%s\", \"%s\") %s\n", 
262                                                                                                 app->name, c->name, (e->data ? (char *)e->data : NULL), (newstack ? "in new stack" : "in same stack"));
263                                                                         c->appl = app->name;
264                                                                         c->data = e->data;              
265                                                                         res = pbx_exec(c, app->execute, e->data, newstack);
266                                                                         c->appl = NULL;
267                                                                         c->data = NULL;
268                                                                         return res;
269                                                                 } else {
270                                                                         ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority);
271                                                                         return -1;
272                                                                 }
273                                                         default:
274                                                                 ast_log(LOG_WARNING, "Huh (%d)?\n", action);
275                                                         }
276                                                 }
277                                                 e = e->peer;
278                                         }
279                                         pthread_mutex_unlock(&tmp->lock);
280                                         if (action != HELPER_EXISTS) {
281                                                 ast_log(LOG_WARNING, "No such priority '%d' in '%s' in '%s'\n", priority, exten, context);
282                                                 return -1;
283                                         } else
284                                                 return 0;
285                                 }
286                                 e = e->next;
287                         }
288                         pthread_mutex_unlock(&tmp->lock);
289                         if (action != HELPER_EXISTS) {
290                                 ast_log(LOG_WARNING, "No such extension '%s' in '%s'\n", exten, context);
291                                 return -1;
292                         } else
293                                 return 0;
294                 }
295                 tmp = tmp->next;
296         }
297         pthread_mutex_unlock(&conlock);
298         if (action != HELPER_EXISTS) {
299                 ast_log(LOG_WARNING, "No such context '%s'\n", context);
300                 return -1;
301         } else
302                 return 0;
303 }
304 int ast_pbx_longest_extension(char *context) 
305 {
306         struct ast_context *tmp;
307         struct ast_exten *e;
308         int len = 0;
309         if (pthread_mutex_lock(&conlock)) {
310                 ast_log(LOG_WARNING, "Unable to obtain lock\n");
311                 return -1;
312         }
313         tmp = contexts;
314         while(tmp) {
315                 if (!strcasecmp(tmp->name, context)) {
316                         /* By locking tmp, not only can the state of its entries not
317                            change, but it cannot be destroyed either. */
318                         pthread_mutex_lock(&tmp->lock);
319                         /* But we can relieve the conlock, as tmp will not change */
320                         pthread_mutex_unlock(&conlock);
321                         e = tmp->root;
322                         while(e) {
323                                 if (strlen(e->exten) > len)
324                                         len = strlen(e->exten);
325                                 e = e->next;
326                         }
327                         pthread_mutex_unlock(&tmp->lock);
328                         return len;
329                 }
330                 tmp = tmp->next;
331         }
332         ast_log(LOG_WARNING, "No such context '%s'\n", context);
333         return -1;
334 }
335
336 int ast_exists_extension(struct ast_channel *c, char *context, char *exten, int priority) 
337 {
338         return pbx_extension_helper(c, context, exten, priority, HELPER_EXISTS);
339 }
340
341 int ast_spawn_extension(struct ast_channel *c, char *context, char *exten, int priority) 
342 {
343         return pbx_extension_helper(c, context, exten, priority, HELPER_SPAWN);
344 }
345
346 static void *pbx_thread(void *data)
347 {
348         /* Oh joyeous kernel, we're a new thread, with nothing to do but
349            answer this channel and get it going.  The setjmp stuff is fairly
350            confusing, but necessary to get smooth transitions between
351            the execution of different applications (without the use of
352            additional threads) */
353         struct ast_channel *c = data;
354         int firstpass = 1;
355         char digit;
356         char exten[256];
357         int pos;
358         int waittime;
359         if (option_debug)
360                 ast_log(LOG_DEBUG, "PBX_THREAD(%s)\n", c->name);
361         else if (option_verbose > 1)
362                 ast_verbose( VERBOSE_PREFIX_2 "Accepting call on '%s'\n", c->name);
363                 
364         
365         /* Start by trying whatever the channel is set to */
366         if (!ast_exists_extension(c, c->context, c->exten, c->priority)) {
367                 strncpy(c->context, "default", sizeof(c->context));
368                 strncpy(c->exten, "s", sizeof(c->exten));
369                 c->priority = 1;
370         }
371         for(;;) {
372                 memset(exten, 0, sizeof(exten));
373                 pos = 0;
374                 digit = 0;
375                 while(ast_exists_extension(c, c->context, c->exten, c->priority)) {
376                         if (ast_spawn_extension(c, c->context, c->exten, c->priority)) {
377                                 /* Something bad happened, or a hangup has been requested. */
378                                 if (option_debug)
379                                         ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
380                                 else if (option_verbose > 1)
381                                         ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
382                                 goto out;
383                         }
384                         /* If we're playing something in the background, wait for it to finish or for a digit */
385                         if (c->stream) {
386                                 digit = ast_waitstream(c, AST_DIGIT_ANY);
387                                 ast_stopstream(c);
388                                 /* Hang up if something goes wrong */
389                                 if (digit < 0)
390                                         goto out;
391                                 else if (digit) {
392                                         ast_stopstream(c);
393                                         exten[pos++] = digit;
394                                         break;
395                                 }
396                         }
397                         firstpass = 0;
398                         c->priority++;
399                 }
400                 /* Done, wait for an extension */
401                 if (digit)
402                         waittime = c->pbx->dtimeout;
403                 else
404                         waittime = c->pbx->rtimeout;
405                 while(!ast_exists_extension(c, c->context, exten, 1) && (
406                        strlen(exten) < ast_pbx_longest_extension(c->context))) {
407                         /* As long as we're willing to wait, and as long as it's not defined, 
408                            keep reading digits until we can't possibly get a right answer anymore.  */
409                         digit = ast_waitfordigit(c, waittime * 1000);
410                         if (!digit)
411                                 /* No entry */
412                                 break;
413                         if (digit < 0)
414                                 /* Error, maybe a  hangup */
415                                 goto out;
416                         exten[pos++] = digit;
417                         waittime = c->pbx->dtimeout;
418                 }
419                 if (ast_exists_extension(c, c->context, exten, 1)) {
420                         /* Prepare the next cycle */
421                         strncpy(c->exten, exten, sizeof(c->exten));
422                         c->priority = 1;
423                 } else {
424                         /* No such extension */
425                         if (strlen(exten)) {
426                                 /* An invalid extension */
427                                 if (ast_exists_extension(c, c->context, "i", 1)) {
428                                         if (option_verbose > 2)
429                                                 ast_verbose( VERBOSE_PREFIX_3 "Invalid extension '%s' in context '%s' on %s\n", exten, c->context, c->name);
430                                         strncpy(c->exten, "i", sizeof(c->exten));
431                                         c->priority = 1;
432                                 } else {
433                                         ast_log(LOG_WARNING, "Invalid extension, but no rule 'i' in context '%s'\n", c->context);
434                                         goto out;
435                                 }
436                         } else {
437                                 /* A simple timeout */
438                                 if (ast_exists_extension(c, c->context, "t", 1)) {
439                                         if (option_verbose > 2)
440                                                 ast_verbose( VERBOSE_PREFIX_3 "Timeout on %s\n", c->name);
441                                         strncpy(c->exten, "t", sizeof(c->exten));
442                                         c->priority = 1;
443                                 } else {
444                                         ast_log(LOG_WARNING, "Timeout, but no rule 't' in context '%s'\n", c->context);
445                                         goto out;
446                                 }
447                         }       
448                 }
449         }
450         if (firstpass) 
451                 ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name);
452 out:
453         pbx_destroy(c->pbx);
454         c->pbx = NULL;
455         ast_hangup(c);
456         pthread_exit(NULL);
457         
458 }
459
460 int ast_pbx_start(struct ast_channel *c)
461 {
462         pthread_t t;
463         if (!c) {
464                 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
465                 return -1;
466         }
467         if (c->pbx)
468                 ast_log(LOG_WARNING, "%s already has PBX structure??\n");
469         c->pbx = malloc(sizeof(struct ast_pbx));
470         if (!c->pbx) {
471                 ast_log(LOG_WARNING, "Out of memory\n");
472                 return -1;
473         }
474         memset(c->pbx, 0, sizeof(struct ast_pbx));
475         /* Set reasonable defaults */
476         c->pbx->rtimeout = 10;
477         c->pbx->dtimeout = 5;
478         /* Start a new thread, and get something handling this channel. */
479         if (pthread_create(&t, NULL, pbx_thread, c)) {
480                 ast_log(LOG_WARNING, "Failed to create new channel thread\n");
481                 return -1;
482         }
483         return 0;
484 }
485 #if 0
486 int ast_remove_extension(struct ast_context *con, char *extension, int priority)
487 {
488         /* XXX Implement me XXX */
489         return -1;
490 }
491 #endif
492 int ast_register_application(char *app, int (*execute)(struct ast_channel *, void *))
493 {
494         struct ast_app *tmp;
495         if (pthread_mutex_lock(&applock)) {
496                 ast_log(LOG_ERROR, "Unable to lock application list\n");
497                 return -1;
498         }
499         tmp = apps;
500         while(tmp) {
501                 if (!strcasecmp(app, tmp->name)) {
502                         ast_log(LOG_WARNING, "Already have an application '%s'\n", app);
503                         pthread_mutex_unlock(&applock);
504                         return -1;
505                 }
506                 tmp = tmp->next;
507         }
508         tmp = malloc(sizeof(struct ast_app));
509         if (tmp) {
510                 strncpy(tmp->name, app, sizeof(tmp->name));
511                 tmp->execute = execute;
512                 tmp->next = apps;
513                 apps = tmp;
514         } else {
515                 ast_log(LOG_WARNING, "Out of memory\n");
516                 pthread_mutex_unlock(&applock);
517                 return -1;
518         }
519         if (option_verbose > 1)
520                 ast_verbose( VERBOSE_PREFIX_2 "Registered application '%s'\n", tmp->name);
521         pthread_mutex_unlock(&applock);
522         return 0;
523 }
524
525 int ast_unregister_application(char *app) {
526         struct ast_app *tmp, *tmpl = NULL;
527         if (pthread_mutex_lock(&applock)) {
528                 ast_log(LOG_ERROR, "Unable to lock application list\n");
529                 return -1;
530         }
531         tmp = apps;
532         while(tmp) {
533                 if (!strcasecmp(app, tmp->name)) {
534                         if (tmpl)
535                                 tmpl->next = tmp->next;
536                         else
537                                 apps = tmp->next;
538                         if (option_verbose > 1)
539                                 ast_verbose( VERBOSE_PREFIX_2 "Unregistered application '%s'\n", tmp->name);
540                         pthread_mutex_unlock(&applock);
541                         return 0;
542                 }
543                 tmpl = tmp;
544                 tmp = tmp->next;
545         }
546         pthread_mutex_unlock(&applock);
547         return -1;
548 }
549
550 struct ast_context *ast_context_create(char *name)
551 {
552         struct ast_context *tmp;
553         
554         pthread_mutex_lock(&conlock);
555         tmp = contexts;
556         while(tmp) {
557                 if (!strcasecmp(tmp->name, name)) {
558                         pthread_mutex_unlock(&conlock);
559                         ast_log(LOG_WARNING, "Tried to register context '%s', already in use\n", name);
560                         return NULL;
561                 }
562                 tmp = tmp->next;
563         }
564         tmp = malloc(sizeof(struct ast_context));
565         if (tmp) {
566                 pthread_mutex_init(&tmp->lock, NULL);
567                 strncpy(tmp->name, name, sizeof(tmp->name));
568                 tmp->root = NULL;
569                 tmp->next = contexts;
570                 contexts = tmp;
571                 if (option_debug)
572                         ast_log(LOG_DEBUG, "Registered context '%s'\n", tmp->name);
573                 else if (option_verbose > 2)
574                         ast_verbose( VERBOSE_PREFIX_3 "Registered extension context '%s'\n", tmp->name);
575         } else
576                 ast_log(LOG_WARNING, "Out of memory\n");
577         
578         pthread_mutex_unlock(&conlock);
579         return tmp;
580 }
581
582 int ast_add_extension2(struct ast_context *con,
583                                           int replace, char *extension, int priority,
584                                           char *application, void *data, void (*datad)(void *))
585 {
586
587 #define LOG {   if (option_debug) \
588                 ast_log(LOG_DEBUG, "Added extension '%s' priority %d to %s\n", tmp->exten, tmp->priority, con->name); \
589         else if (option_verbose > 2) \
590                 ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d to %s\n", tmp->exten, tmp->priority, con->name); \
591                 }
592
593         /*
594          * This is a fairly complex routine.  Different extensions are kept
595          * in order by the extension number.  Then, extensions of different
596          * priorities (same extension) are kept in a list, according to the
597          * peer pointer.
598          */
599         struct ast_exten *tmp, *e, *el = NULL, *ep = NULL;
600         int res;
601         /* Be optimistic:  Build the extension structure first */
602         tmp = malloc(sizeof(struct ast_exten));
603         if (tmp) {
604                 strncpy(tmp->exten, extension, sizeof(tmp->exten));
605                 tmp->priority = priority;
606                 strncpy(tmp->app, application, sizeof(tmp->app));
607                 tmp->data = data;
608                 tmp->datad = datad;
609                 tmp->peer = NULL;
610                 tmp->next =  NULL;
611         } else {
612                 ast_log(LOG_WARNING, "Out of memory\n");
613                 return -1;
614         }
615         if (pthread_mutex_lock(&con->lock)) {
616                 free(tmp);
617                 /* And properly destroy the data */
618                 datad(data);
619                 ast_log(LOG_WARNING, "Failed to lock context '%s'\n", con->name);
620                 return -1;
621         }
622         e = con->root;
623         while(e) {
624                 res= strcasecmp(e->exten, extension);
625                 if (res == 0) {
626                         /* We have an exact match, now we find where we are
627                            and be sure there's no duplicates */
628                         while(e) {
629                                 if (e->priority == tmp->priority) {
630                                         /* Can't have something exactly the same.  Is this a
631                                            replacement?  If so, replace, otherwise, bonk. */
632                                         if (replace) {
633                                                 if (ep) {
634                                                         /* We're in the peer list, insert ourselves */
635                                                         ep->peer = tmp;
636                                                         tmp->peer = e->peer;
637                                                 } else if (el) {
638                                                         /* We're the first extension. Take over e's functions */
639                                                         el->next = tmp;
640                                                         tmp->next = e->next;
641                                                         tmp->peer = e->peer;
642                                                 } else {
643                                                         /* We're the very first extension.  */
644                                                         con->root = tmp;
645                                                         tmp->next = e->next;
646                                                         tmp->peer = e->peer;
647                                                 }
648                                                 /* Destroy the old one */
649                                                 e->datad(e->data);
650                                                 free(e);
651                                                 pthread_mutex_unlock(&con->lock);
652                                                 /* And immediately return success. */
653                                                 LOG;
654                                                 return 0;
655                                         } else {
656                                                 ast_log(LOG_WARNING, "Unable to register extension '%s', priority %d in '%s', already in use\n", tmp->exten, tmp->priority, con->name);
657                                                 tmp->datad(tmp->data);
658                                                 free(tmp);
659                                                 pthread_mutex_unlock(&con->lock);
660                                                 return -1;
661                                         }
662                                 } else if (e->priority > tmp->priority) {
663                                         /* Slip ourselves in just before e */
664                                         if (ep) {
665                                                 /* Easy enough, we're just in the peer list */
666                                                 ep->peer = tmp;
667                                                 tmp->peer = e;
668                                         } else if (el) {
669                                                 /* We're the first extension in this peer list */
670                                                 el->next = tmp;
671                                                 tmp->next = e->next;
672                                                 e->next = NULL;
673                                                 tmp->peer = e;
674                                         } else {
675                                                 /* We're the very first extension altogether */
676                                                 tmp->next = con->root;
677                                                 /* Con->root must always exist or we couldn't get here */
678                                                 tmp->peer = con->root->peer;
679                                                 con->root = tmp;
680                                         }
681                                         pthread_mutex_unlock(&con->lock);
682                                         /* And immediately return success. */
683                                         LOG;
684                                         return 0;
685                                 }
686                                 ep = e;
687                                 e = e->peer;
688                         }
689                         /* If we make it here, then it's time for us to go at the very end.
690                            ep *must* be defined or we couldn't have gotten here. */
691                         ep->peer = tmp;
692                         pthread_mutex_unlock(&con->lock);
693                         /* And immediately return success. */
694                         LOG;
695                         return 0;
696                                 
697                 } else if (res > 0) {
698                         /* Insert ourselves just before 'e'.  We're the first extension of
699                            this kind */
700                         tmp->next = e;
701                         if (el) {
702                                 /* We're in the list somewhere */
703                                 el->next = tmp;
704                         } else {
705                                 /* We're at the top of the list */
706                                 con->root = tmp;
707                         }
708                         pthread_mutex_unlock(&con->lock);
709                         /* And immediately return success. */
710                         LOG;
711                         return 0;
712                 }                       
713                         
714                 el = e;
715                 e = e->next;
716         }
717         /* If we fall all the way through to here, then we need to be on the end. */
718         if (el)
719                 el->next = tmp;
720         else
721                 con->root = tmp;
722         pthread_mutex_unlock(&con->lock);
723         LOG;
724         return 0;       
725 }
726
727 void ast_context_destroy(struct ast_context *con)
728 {
729         struct ast_context *tmp, *tmpl=NULL;
730         pthread_mutex_lock(&conlock);
731         tmp = contexts;
732         while(tmp) {
733                 if (tmp == con) {
734                         /* Okay, let's lock the structure to be sure nobody else
735                            is searching through it. */
736                         if (pthread_mutex_lock(&tmp->lock)) {
737                                 ast_log(LOG_WARNING, "Unable to lock context lock\n");
738                                 return;
739                         }
740                         if (tmpl)
741                                 tmpl->next = tmp->next;
742                         else
743                                 contexts = tmp->next;
744                         /* Okay, now we're safe to let it go -- in a sense, we were
745                            ready to let it go as soon as we locked it. */
746                         pthread_mutex_unlock(&tmp->lock);
747                         free(tmp);
748                         pthread_mutex_unlock(&conlock);
749                         return;
750                 }
751                 tmpl = tmp;
752                 tmp = tmp->next;
753         }
754         pthread_mutex_unlock(&conlock);
755 }
756
757 int pbx_builtin_answer(struct ast_channel *chan, void *data)
758 {
759         if (chan->state != AST_STATE_RING) {
760                 if (option_debug)
761                         ast_log(LOG_DEBUG, "Ignoring answer request since line is not ringing\n");
762                 return 0;
763         } else
764                 return ast_answer(chan);
765 }
766
767 int pbx_builtin_hangup(struct ast_channel *chan, void *data)
768 {
769         /* Just return non-zero and it will hang up */
770         return -1;
771 }
772
773 int pbx_builtin_wait(struct ast_channel *chan, void *data)
774 {
775         /* Wait for "n" seconds */
776         if (data && atoi((char *)data))
777                 sleep(atoi((char *)data));
778         return 0;
779 }
780
781 int pbx_builtin_background(struct ast_channel *chan, void *data)
782 {
783         int res;
784         /* Stop anything playing */
785         ast_stopstream(chan);
786         /* Stream a file */
787         res = ast_streamfile(chan, (char *)data);
788         return res;
789 }
790
791 int pbx_builtin_rtimeout(struct ast_channel *chan, void *data)
792 {
793         /* Set the timeout for how long to wait between digits */
794         chan->pbx->rtimeout = atoi((char *)data);
795         if (option_verbose > 2)
796                 ast_verbose( VERBOSE_PREFIX_3 "Set Response Timeout to %d\n", chan->pbx->rtimeout);
797         return 0;
798 }
799
800 int pbx_builtin_dtimeout(struct ast_channel *chan, void *data)
801 {
802         /* Set the timeout for how long to wait between digits */
803         chan->pbx->dtimeout = atoi((char *)data);
804         if (option_verbose > 2)
805                 ast_verbose( VERBOSE_PREFIX_3 "Set Digit Timeout to %d\n", chan->pbx->dtimeout);
806         return 0;
807 }
808
809 int pbx_builtin_goto(struct ast_channel *chan, void *data)
810 {
811         char *s;
812         char *exten, *pri, *context;
813         if (!data) {
814                 ast_log(LOG_WARNING, "Goto requires an argument (optional context|optional extension|priority)\n");
815                 return -1;
816         }
817         s = strdup((void *) data);
818         context = strtok(s, "|");
819         exten = strtok(NULL, "|");
820         if (!exten) {
821                 /* Only a priority in this one */
822                 pri = context;
823                 exten = NULL;
824                 context = NULL;
825         } else {
826                 pri = strtok(NULL, "|");
827                 if (!pri) {
828                         /* Only an extension and priority in this one */
829                         pri = exten;
830                         exten = context;
831                         context = NULL;
832                 }
833         }
834         if (atoi(pri) < 0) {
835                 ast_log(LOG_WARNING, "Priority '%s' must be a number > 0\n", pri);
836                 free(s);
837                 return -1;
838         }
839         /* At this point we have a priority and maybe an extension and a context */
840         chan->priority = atoi(pri) - 1;
841         if (exten)
842                 strncpy(chan->exten, exten, sizeof(chan->exten));
843         if (context)
844                 strncpy(chan->context, context, sizeof(chan->context));
845         if (option_verbose > 2)
846                 ast_verbose( VERBOSE_PREFIX_3 "Goto (%s,%s,%d)\n", chan->context,chan->exten, chan->priority+1);
847         return 0;
848 }
849 int load_pbx(void)
850 {
851         int x;
852         /* Initialize the PBX */
853         if (option_verbose) {
854                 ast_verbose( "Asterisk PBX Core Initializing\n");
855                 ast_verbose( "Registering builtin applications:\n");
856         }
857         for (x=0;x<sizeof(builtins) / sizeof(struct pbx_builtin); x++) {
858                 if (option_verbose)
859                         ast_verbose( VERBOSE_PREFIX_1 "[%s]\n", builtins[x].name);
860                 if (ast_register_application(builtins[x].name, builtins[x].execute)) {
861                         ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name);
862                         return -1;
863                 }
864         }
865         return 0;
866 }
867