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