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