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