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