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