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