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