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