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