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