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