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