Version 0.1.3 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                                         goto out;
476                                 else if (digit) {
477                                         exten[pos++] = digit;
478                                         break;
479                                 }
480                         }
481                         firstpass = 0;
482                         c->priority++;
483                 }
484                 /* Done, wait for an extension */
485                 if (digit)
486                         waittime = c->pbx->dtimeout;
487                 else
488                         waittime = c->pbx->rtimeout;
489                 while(!ast_exists_extension(c, c->context, exten, 1) && 
490                       ast_canmatch_extension(c, c->context, exten, 1)) {
491                         /* As long as we're willing to wait, and as long as it's not defined, 
492                            keep reading digits until we can't possibly get a right answer anymore.  */
493                         digit = ast_waitfordigit(c, waittime * 1000);
494                         if (!digit)
495                                 /* No entry */
496                                 break;
497                         if (digit < 0)
498                                 /* Error, maybe a  hangup */
499                                 goto out;
500                         exten[pos++] = digit;
501                         waittime = c->pbx->dtimeout;
502                 }
503                 if (ast_exists_extension(c, c->context, exten, 1)) {
504                         /* Prepare the next cycle */
505                         strncpy(c->exten, exten, sizeof(c->exten));
506                         c->priority = 1;
507                 } else {
508                         /* No such extension */
509                         if (strlen(exten)) {
510                                 /* An invalid extension */
511                                 if (ast_exists_extension(c, c->context, "i", 1)) {
512                                         if (option_verbose > 2)
513                                                 ast_verbose( VERBOSE_PREFIX_3 "Invalid extension '%s' in context '%s' on %s\n", exten, c->context, c->name);
514                                         strncpy(c->exten, "i", sizeof(c->exten));
515                                         c->priority = 1;
516                                 } else {
517                                         ast_log(LOG_WARNING, "Invalid extension, but no rule 'i' in context '%s'\n", c->context);
518                                         goto out;
519                                 }
520                         } else {
521                                 /* A simple timeout */
522                                 if (ast_exists_extension(c, c->context, "t", 1)) {
523                                         if (option_verbose > 2)
524                                                 ast_verbose( VERBOSE_PREFIX_3 "Timeout on %s\n", c->name);
525                                         strncpy(c->exten, "t", sizeof(c->exten));
526                                         c->priority = 1;
527                                 } else {
528                                         ast_log(LOG_WARNING, "Timeout, but no rule 't' in context '%s'\n", c->context);
529                                         goto out;
530                                 }
531                         }       
532                 }
533         }
534         if (firstpass) 
535                 ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name);
536 out:
537         pbx_destroy(c->pbx);
538         c->pbx = NULL;
539         if (res != AST_PBX_KEEPALIVE)
540                 ast_hangup(c);
541         pthread_exit(NULL);
542         
543 }
544
545 int ast_pbx_start(struct ast_channel *c)
546 {
547         pthread_t t;
548         if (!c) {
549                 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
550                 return -1;
551         }
552         if (c->pbx)
553                 ast_log(LOG_WARNING, "%s already has PBX structure??\n");
554         c->pbx = malloc(sizeof(struct ast_pbx));
555         if (!c->pbx) {
556                 ast_log(LOG_WARNING, "Out of memory\n");
557                 return -1;
558         }
559         memset(c->pbx, 0, sizeof(struct ast_pbx));
560         /* Set reasonable defaults */
561         c->pbx->rtimeout = 10;
562         c->pbx->dtimeout = 5;
563         /* Start a new thread, and get something handling this channel. */
564         if (pthread_create(&t, NULL, pbx_thread, c)) {
565                 ast_log(LOG_WARNING, "Failed to create new channel thread\n");
566                 return -1;
567         }
568         return 0;
569 }
570 #if 0
571 int ast_remove_extension(struct ast_context *con, char *extension, int priority)
572 {
573         /* XXX Implement me XXX */
574         return -1;
575 }
576 #endif
577 int ast_register_application(char *app, int (*execute)(struct ast_channel *, void *))
578 {
579         struct ast_app *tmp;
580         if (pthread_mutex_lock(&applock)) {
581                 ast_log(LOG_ERROR, "Unable to lock application list\n");
582                 return -1;
583         }
584         tmp = apps;
585         while(tmp) {
586                 if (!strcasecmp(app, tmp->name)) {
587                         ast_log(LOG_WARNING, "Already have an application '%s'\n", app);
588                         pthread_mutex_unlock(&applock);
589                         return -1;
590                 }
591                 tmp = tmp->next;
592         }
593         tmp = malloc(sizeof(struct ast_app));
594         if (tmp) {
595                 strncpy(tmp->name, app, sizeof(tmp->name));
596                 tmp->execute = execute;
597                 tmp->next = apps;
598                 apps = tmp;
599         } else {
600                 ast_log(LOG_WARNING, "Out of memory\n");
601                 pthread_mutex_unlock(&applock);
602                 return -1;
603         }
604         if (option_verbose > 1)
605                 ast_verbose( VERBOSE_PREFIX_2 "Registered application '%s'\n", tmp->name);
606         pthread_mutex_unlock(&applock);
607         return 0;
608 }
609
610 int ast_unregister_application(char *app) {
611         struct ast_app *tmp, *tmpl = NULL;
612         if (pthread_mutex_lock(&applock)) {
613                 ast_log(LOG_ERROR, "Unable to lock application list\n");
614                 return -1;
615         }
616         tmp = apps;
617         while(tmp) {
618                 if (!strcasecmp(app, tmp->name)) {
619                         if (tmpl)
620                                 tmpl->next = tmp->next;
621                         else
622                                 apps = tmp->next;
623                         if (option_verbose > 1)
624                                 ast_verbose( VERBOSE_PREFIX_2 "Unregistered application '%s'\n", tmp->name);
625                         pthread_mutex_unlock(&applock);
626                         return 0;
627                 }
628                 tmpl = tmp;
629                 tmp = tmp->next;
630         }
631         pthread_mutex_unlock(&applock);
632         return -1;
633 }
634
635 struct ast_context *ast_context_create(char *name)
636 {
637         struct ast_context *tmp;
638         
639         pthread_mutex_lock(&conlock);
640         tmp = contexts;
641         while(tmp) {
642                 if (!strcasecmp(tmp->name, name)) {
643                         pthread_mutex_unlock(&conlock);
644                         ast_log(LOG_WARNING, "Tried to register context '%s', already in use\n", name);
645                         return NULL;
646                 }
647                 tmp = tmp->next;
648         }
649         tmp = malloc(sizeof(struct ast_context));
650         if (tmp) {
651                 pthread_mutex_init(&tmp->lock, NULL);
652                 strncpy(tmp->name, name, sizeof(tmp->name));
653                 tmp->root = NULL;
654                 tmp->next = contexts;
655                 contexts = tmp;
656                 if (option_debug)
657                         ast_log(LOG_DEBUG, "Registered context '%s'\n", tmp->name);
658                 else if (option_verbose > 2)
659                         ast_verbose( VERBOSE_PREFIX_3 "Registered extension context '%s'\n", tmp->name);
660         } else
661                 ast_log(LOG_WARNING, "Out of memory\n");
662         
663         pthread_mutex_unlock(&conlock);
664         return tmp;
665 }
666
667 int ast_add_extension2(struct ast_context *con,
668                                           int replace, char *extension, int priority,
669                                           char *application, void *data, void (*datad)(void *))
670 {
671
672 #define LOG {   if (option_debug) \
673                 ast_log(LOG_DEBUG, "Added extension '%s' priority %d to %s\n", tmp->exten, tmp->priority, con->name); \
674         else if (option_verbose > 2) \
675                 ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d to %s\n", tmp->exten, tmp->priority, con->name); \
676                 }
677
678         /*
679          * This is a fairly complex routine.  Different extensions are kept
680          * in order by the extension number.  Then, extensions of different
681          * priorities (same extension) are kept in a list, according to the
682          * peer pointer.
683          */
684         struct ast_exten *tmp, *e, *el = NULL, *ep = NULL;
685         int res;
686         /* Be optimistic:  Build the extension structure first */
687         tmp = malloc(sizeof(struct ast_exten));
688         if (tmp) {
689                 strncpy(tmp->exten, extension, sizeof(tmp->exten));
690                 tmp->priority = priority;
691                 strncpy(tmp->app, application, sizeof(tmp->app));
692                 tmp->data = data;
693                 tmp->datad = datad;
694                 tmp->peer = NULL;
695                 tmp->next =  NULL;
696         } else {
697                 ast_log(LOG_WARNING, "Out of memory\n");
698                 return -1;
699         }
700         if (pthread_mutex_lock(&con->lock)) {
701                 free(tmp);
702                 /* And properly destroy the data */
703                 datad(data);
704                 ast_log(LOG_WARNING, "Failed to lock context '%s'\n", con->name);
705                 return -1;
706         }
707         e = con->root;
708         while(e) {
709                 res= strcasecmp(e->exten, extension);
710                 if (res == 0) {
711                         /* We have an exact match, now we find where we are
712                            and be sure there's no duplicates */
713                         while(e) {
714                                 if (e->priority == tmp->priority) {
715                                         /* Can't have something exactly the same.  Is this a
716                                            replacement?  If so, replace, otherwise, bonk. */
717                                         if (replace) {
718                                                 if (ep) {
719                                                         /* We're in the peer list, insert ourselves */
720                                                         ep->peer = tmp;
721                                                         tmp->peer = e->peer;
722                                                 } else if (el) {
723                                                         /* We're the first extension. Take over e's functions */
724                                                         el->next = tmp;
725                                                         tmp->next = e->next;
726                                                         tmp->peer = e->peer;
727                                                 } else {
728                                                         /* We're the very first extension.  */
729                                                         con->root = tmp;
730                                                         tmp->next = e->next;
731                                                         tmp->peer = e->peer;
732                                                 }
733                                                 /* Destroy the old one */
734                                                 e->datad(e->data);
735                                                 free(e);
736                                                 pthread_mutex_unlock(&con->lock);
737                                                 /* And immediately return success. */
738                                                 LOG;
739                                                 return 0;
740                                         } else {
741                                                 ast_log(LOG_WARNING, "Unable to register extension '%s', priority %d in '%s', already in use\n", tmp->exten, tmp->priority, con->name);
742                                                 tmp->datad(tmp->data);
743                                                 free(tmp);
744                                                 pthread_mutex_unlock(&con->lock);
745                                                 return -1;
746                                         }
747                                 } else if (e->priority > tmp->priority) {
748                                         /* Slip ourselves in just before e */
749                                         if (ep) {
750                                                 /* Easy enough, we're just in the peer list */
751                                                 ep->peer = tmp;
752                                                 tmp->peer = e;
753                                         } else if (el) {
754                                                 /* We're the first extension in this peer list */
755                                                 el->next = tmp;
756                                                 tmp->next = e->next;
757                                                 e->next = NULL;
758                                                 tmp->peer = e;
759                                         } else {
760                                                 /* We're the very first extension altogether */
761                                                 tmp->next = con->root;
762                                                 /* Con->root must always exist or we couldn't get here */
763                                                 tmp->peer = con->root->peer;
764                                                 con->root = tmp;
765                                         }
766                                         pthread_mutex_unlock(&con->lock);
767                                         /* And immediately return success. */
768                                         LOG;
769                                         return 0;
770                                 }
771                                 ep = e;
772                                 e = e->peer;
773                         }
774                         /* If we make it here, then it's time for us to go at the very end.
775                            ep *must* be defined or we couldn't have gotten here. */
776                         ep->peer = tmp;
777                         pthread_mutex_unlock(&con->lock);
778                         /* And immediately return success. */
779                         LOG;
780                         return 0;
781                                 
782                 } else if (res > 0) {
783                         /* Insert ourselves just before 'e'.  We're the first extension of
784                            this kind */
785                         tmp->next = e;
786                         if (el) {
787                                 /* We're in the list somewhere */
788                                 el->next = tmp;
789                         } else {
790                                 /* We're at the top of the list */
791                                 con->root = tmp;
792                         }
793                         pthread_mutex_unlock(&con->lock);
794                         /* And immediately return success. */
795                         LOG;
796                         return 0;
797                 }                       
798                         
799                 el = e;
800                 e = e->next;
801         }
802         /* If we fall all the way through to here, then we need to be on the end. */
803         if (el)
804                 el->next = tmp;
805         else
806                 con->root = tmp;
807         pthread_mutex_unlock(&con->lock);
808         LOG;
809         return 0;       
810 }
811
812 void ast_context_destroy(struct ast_context *con)
813 {
814         struct ast_context *tmp, *tmpl=NULL;
815         pthread_mutex_lock(&conlock);
816         tmp = contexts;
817         while(tmp) {
818                 if (tmp == con) {
819                         /* Okay, let's lock the structure to be sure nobody else
820                            is searching through it. */
821                         if (pthread_mutex_lock(&tmp->lock)) {
822                                 ast_log(LOG_WARNING, "Unable to lock context lock\n");
823                                 return;
824                         }
825                         if (tmpl)
826                                 tmpl->next = tmp->next;
827                         else
828                                 contexts = tmp->next;
829                         /* Okay, now we're safe to let it go -- in a sense, we were
830                            ready to let it go as soon as we locked it. */
831                         pthread_mutex_unlock(&tmp->lock);
832                         free(tmp);
833                         pthread_mutex_unlock(&conlock);
834                         return;
835                 }
836                 tmpl = tmp;
837                 tmp = tmp->next;
838         }
839         pthread_mutex_unlock(&conlock);
840 }
841
842 int pbx_builtin_answer(struct ast_channel *chan, void *data)
843 {
844         if (chan->state != AST_STATE_RING) {
845                 if (option_debug)
846                         ast_log(LOG_DEBUG, "Ignoring answer request since line is not ringing\n");
847                 return 0;
848         } else
849                 return ast_answer(chan);
850 }
851
852 int pbx_builtin_setlanguage(struct ast_channel *chan, void *data)
853 {
854         /* Copy the language as specified */
855         strncpy(chan->language, (char *)data, sizeof(chan->language));
856         return 0;
857 }
858
859 int pbx_builtin_hangup(struct ast_channel *chan, void *data)
860 {
861         /* Just return non-zero and it will hang up */
862         return -1;
863 }
864
865 int pbx_builtin_stripmsd(struct ast_channel *chan, void *data)
866 {
867         char newexten[AST_MAX_EXTENSION] = "";
868         if (!data || !atoi(data)) {
869                 ast_log(LOG_DEBUG, "Ignoring, since number of digits to strip is 0\n");
870                 return 0;
871         }
872         if (strlen(chan->exten) > atoi(data)) {
873                 strncpy(newexten, chan->exten + atoi(data), sizeof(newexten));
874         }
875         strncpy(chan->exten, newexten, sizeof(chan->exten));
876         return 0;
877 }
878
879 int pbx_builtin_prefix(struct ast_channel *chan, void *data)
880 {
881         char newexten[AST_MAX_EXTENSION] = "";
882         if (!data || !strlen(data)) {
883                 ast_log(LOG_DEBUG, "Ignoring, since there is no prefix to add\n");
884                 return 0;
885         }
886         snprintf(newexten, sizeof(newexten), "%s%s", (char *)data, chan->exten);
887         strncpy(chan->exten, newexten, sizeof(chan->exten));
888         return 0;
889 }
890
891 int pbx_builtin_wait(struct ast_channel *chan, void *data)
892 {
893         /* Wait for "n" seconds */
894         if (data && atoi((char *)data))
895                 sleep(atoi((char *)data));
896         return 0;
897 }
898
899 int pbx_builtin_background(struct ast_channel *chan, void *data)
900 {
901         int res;
902         /* Answer if need be */
903         if (chan->state != AST_STATE_UP)
904                 if (ast_answer(chan))
905                         return -1;
906         /* Stop anything playing */
907         ast_stopstream(chan);
908         /* Stream a file */
909         res = ast_streamfile(chan, (char *)data, chan->language);
910         return res;
911 }
912
913 int pbx_builtin_rtimeout(struct ast_channel *chan, void *data)
914 {
915         /* Set the timeout for how long to wait between digits */
916         chan->pbx->rtimeout = atoi((char *)data);
917         if (option_verbose > 2)
918                 ast_verbose( VERBOSE_PREFIX_3 "Set Response Timeout to %d\n", chan->pbx->rtimeout);
919         return 0;
920 }
921
922 int pbx_builtin_dtimeout(struct ast_channel *chan, void *data)
923 {
924         /* Set the timeout for how long to wait between digits */
925         chan->pbx->dtimeout = atoi((char *)data);
926         if (option_verbose > 2)
927                 ast_verbose( VERBOSE_PREFIX_3 "Set Digit Timeout to %d\n", chan->pbx->dtimeout);
928         return 0;
929 }
930
931 int pbx_builtin_goto(struct ast_channel *chan, void *data)
932 {
933         char *s;
934         char *exten, *pri, *context;
935         if (!data) {
936                 ast_log(LOG_WARNING, "Goto requires an argument (optional context|optional extension|priority)\n");
937                 return -1;
938         }
939         s = strdup((void *) data);
940         context = strtok(s, "|");
941         exten = strtok(NULL, "|");
942         if (!exten) {
943                 /* Only a priority in this one */
944                 pri = context;
945                 exten = NULL;
946                 context = NULL;
947         } else {
948                 pri = strtok(NULL, "|");
949                 if (!pri) {
950                         /* Only an extension and priority in this one */
951                         pri = exten;
952                         exten = context;
953                         context = NULL;
954                 }
955         }
956         if (atoi(pri) < 0) {
957                 ast_log(LOG_WARNING, "Priority '%s' must be a number > 0\n", pri);
958                 free(s);
959                 return -1;
960         }
961         /* At this point we have a priority and maybe an extension and a context */
962         chan->priority = atoi(pri) - 1;
963         if (exten)
964                 strncpy(chan->exten, exten, sizeof(chan->exten));
965         if (context)
966                 strncpy(chan->context, context, sizeof(chan->context));
967         if (option_verbose > 2)
968                 ast_verbose( VERBOSE_PREFIX_3 "Goto (%s,%s,%d)\n", chan->context,chan->exten, chan->priority+1);
969         return 0;
970 }
971 int load_pbx(void)
972 {
973         int x;
974         /* Initialize the PBX */
975         if (option_verbose) {
976                 ast_verbose( "Asterisk PBX Core Initializing\n");
977                 ast_verbose( "Registering builtin applications:\n");
978         }
979         for (x=0;x<sizeof(builtins) / sizeof(struct pbx_builtin); x++) {
980                 if (option_verbose)
981                         ast_verbose( VERBOSE_PREFIX_1 "[%s]\n", builtins[x].name);
982                 if (ast_register_application(builtins[x].name, builtins[x].execute)) {
983                         ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name);
984                         return -1;
985                 }
986         }
987         return 0;
988 }
989