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