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