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