Several manager changes:
[asterisk/asterisk.git] / main / 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 "asterisk.h"
27
28 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
29
30 #include "asterisk/_private.h"
31 #include "asterisk/paths.h"     /* use ast_config_AST_SYSTEM_NAME */
32 #include <ctype.h>
33 #include <time.h>
34 #include <sys/time.h>
35 #if defined(HAVE_SYSINFO)
36 #include <sys/sysinfo.h>
37 #endif
38 #if defined(SOLARIS)
39 #include <sys/loadavg.h>
40 #endif
41
42 #include "asterisk/lock.h"
43 #include "asterisk/cli.h"
44 #include "asterisk/pbx.h"
45 #include "asterisk/channel.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/stringfields.h"
62 #include "asterisk/event.h"
63 #include "asterisk/hashtab.h"
64 #include "asterisk/module.h"
65 #include "asterisk/indications.h"
66
67 /*!
68  * \note I M P O R T A N T :
69  *
70  *              The speed of extension handling will likely be among the most important
71  * aspects of this PBX.  The switching scheme as it exists right now isn't
72  * terribly bad (it's O(N+M), where N is the # of extensions and M is the avg #
73  * of priorities, but a constant search time here would be great ;-)
74  *
75  * A new algorithm to do searching based on a 'compiled' pattern tree is introduced
76  * here, and shows a fairly flat (constant) search time, even for over
77  * 1000 patterns. Might Still needs some work-- there are some fine points of the matching
78  * spec about tie-breaking based on the characters in character sets, but this
79  * should be do-able via the weight system currently being used.
80  *
81  * Also, using a hash table for context/priority name lookup can help prevent
82  * the find_extension routines from absorbing exponential cpu cycles. I've tested
83  * find_extension with red-black trees, which have O(log2(n)) speed. Right now,
84  * I'm using hash tables, which do searches (ideally) in O(1) time.
85  *
86  */
87
88 #ifdef LOW_MEMORY
89 #define EXT_DATA_SIZE 256
90 #else
91 #define EXT_DATA_SIZE 8192
92 #endif
93
94 #define SWITCH_DATA_LENGTH 256
95
96 #define VAR_BUF_SIZE 4096
97
98 #define VAR_NORMAL              1
99 #define VAR_SOFTTRAN    2
100 #define VAR_HARDTRAN    3
101
102 #define BACKGROUND_SKIP         (1 << 0)
103 #define BACKGROUND_NOANSWER     (1 << 1)
104 #define BACKGROUND_MATCHEXTEN   (1 << 2)
105 #define BACKGROUND_PLAYBACK     (1 << 3)
106
107 AST_APP_OPTIONS(background_opts, {
108         AST_APP_OPTION('s', BACKGROUND_SKIP),
109         AST_APP_OPTION('n', BACKGROUND_NOANSWER),
110         AST_APP_OPTION('m', BACKGROUND_MATCHEXTEN),
111         AST_APP_OPTION('p', BACKGROUND_PLAYBACK),
112 });
113
114 #define WAITEXTEN_MOH           (1 << 0)
115 #define WAITEXTEN_DIALTONE      (1 << 1)
116
117 AST_APP_OPTIONS(waitexten_opts, {
118         AST_APP_OPTION_ARG('m', WAITEXTEN_MOH, 0),
119         AST_APP_OPTION_ARG('d', WAITEXTEN_DIALTONE, 0),
120 });
121
122 struct ast_context;
123 struct ast_app;
124
125 /*!
126    \brief ast_exten: An extension
127         The dialplan is saved as a linked list with each context
128         having it's own linked list of extensions - one item per
129         priority.
130 */
131 struct ast_exten {
132         char *exten;                    /*!< Extension name */
133         int matchcid;                   /*!< Match caller id ? */
134         const char *cidmatch;           /*!< Caller id to match for this extension */
135         int priority;                   /*!< Priority */
136         const char *label;              /*!< Label */
137         struct ast_context *parent;     /*!< The context this extension belongs to  */
138         const char *app;                /*!< Application to execute */
139         struct ast_app *cached_app;     /*!< Cached location of application */
140         void *data;                     /*!< Data to use (arguments) */
141         void (*datad)(void *);          /*!< Data destructor */
142         struct ast_exten *peer;         /*!< Next higher priority with our extension */
143         struct ast_hashtab *peer_tree;    /*!< Priorities list in tree form -- only on the head of the peer list */
144         struct ast_hashtab *peer_label_tree; /*!< labeled priorities in the peer list -- only on the head of the peer list */
145         const char *registrar;          /*!< Registrar */
146         struct ast_exten *next;         /*!< Extension with a greater ID */
147         char stuff[0];
148 };
149
150 /*! \brief ast_include: include= support in extensions.conf */
151 struct ast_include {
152         const char *name;
153         const char *rname;                      /*!< Context to include */
154         const char *registrar;                  /*!< Registrar */
155         int hastime;                            /*!< If time construct exists */
156         struct ast_timing timing;               /*!< time construct */
157         struct ast_include *next;               /*!< Link them together */
158         char stuff[0];
159 };
160
161 /*! \brief ast_sw: Switch statement in extensions.conf */
162 struct ast_sw {
163         char *name;
164         const char *registrar;                  /*!< Registrar */
165         char *data;                             /*!< Data load */
166         int eval;
167         AST_LIST_ENTRY(ast_sw) list;
168         char *tmpdata;
169         char stuff[0];
170 };
171
172 /*! \brief ast_ignorepat: Ignore patterns in dial plan */
173 struct ast_ignorepat {
174         const char *registrar;
175         struct ast_ignorepat *next;
176         const char pattern[0];
177 };
178
179 /*! \brief match_char: forms a syntax tree for quick matching of extension patterns */
180 struct match_char
181 {
182         int is_pattern; /* the pattern started with '_' */
183         int deleted;    /* if this is set, then... don't return it */
184         char *x;       /* the pattern itself-- matches a single char */
185         int specificity; /* simply the strlen of x, or 10 for X, 9 for Z, and 8 for N; and '.' and '!' will add 11 ? */
186         struct match_char *alt_char;
187         struct match_char *next_char;
188         struct ast_exten *exten; /* attached to last char of a pattern for exten */
189 };
190
191 struct scoreboard  /* make sure all fields are 0 before calling new_find_extension */
192 {
193         int total_specificity;
194         int total_length;
195         char last_char;   /* set to ! or . if they are the end of the pattern */
196         int canmatch;     /* if the string to match was just too short */
197         struct match_char *node;
198         struct ast_exten *canmatch_exten;
199         struct ast_exten *exten;
200 };
201
202 /*! \brief ast_context: An extension context */
203 struct ast_context {
204         ast_rwlock_t lock;                      /*!< A lock to prevent multiple threads from clobbering the context */
205         struct ast_exten *root;                 /*!< The root of the list of extensions */
206         struct ast_hashtab *root_tree;            /*!< For exact matches on the extensions in the pattern tree, and for traversals of the pattern_tree  */
207         struct match_char *pattern_tree;        /*!< A tree to speed up extension pattern matching */
208         struct ast_context *next;               /*!< Link them together */
209         struct ast_include *includes;           /*!< Include other contexts */
210         struct ast_ignorepat *ignorepats;       /*!< Patterns for which to continue playing dialtone */
211         const char *registrar;                  /*!< Registrar */
212         AST_LIST_HEAD_NOLOCK(, ast_sw) alts;    /*!< Alternative switches */
213         ast_mutex_t macrolock;                  /*!< A lock to implement "exclusive" macros - held whilst a call is executing in the macro */
214         char name[0];                           /*!< Name of the context */
215 };
216
217
218 /*! \brief ast_app: A registered application */
219 struct ast_app {
220         int (*execute)(struct ast_channel *chan, void *data);
221         const char *synopsis;                   /*!< Synopsis text for 'show applications' */
222         const char *description;                /*!< Description (help text) for 'show application &lt;name&gt;' */
223         AST_RWLIST_ENTRY(ast_app) list;         /*!< Next app in list */
224         struct ast_module *module;              /*!< Module this app belongs to */
225         char name[0];                           /*!< Name of the application */
226 };
227
228 /*! \brief ast_state_cb: An extension state notify register item */
229 struct ast_state_cb {
230         int id;
231         void *data;
232         ast_state_cb_type callback;
233         struct ast_state_cb *next;
234 };
235
236 /*! \brief Structure for dial plan hints
237
238   \note Hints are pointers from an extension in the dialplan to one or
239   more devices (tech/name) 
240         - See \ref AstExtState
241 */
242 struct ast_hint {
243         struct ast_exten *exten;        /*!< Extension */
244         int laststate;                  /*!< Last known state */
245         struct ast_state_cb *callbacks; /*!< Callback list for this extension */
246         AST_RWLIST_ENTRY(ast_hint) list;/*!< Pointer to next hint in list */
247 };
248
249 static const struct cfextension_states {
250         int extension_state;
251         const char * const text;
252 } extension_states[] = {
253         { AST_EXTENSION_NOT_INUSE,                     "Idle" },
254         { AST_EXTENSION_INUSE,                         "InUse" },
255         { AST_EXTENSION_BUSY,                          "Busy" },
256         { AST_EXTENSION_UNAVAILABLE,                   "Unavailable" },
257         { AST_EXTENSION_RINGING,                       "Ringing" },
258         { AST_EXTENSION_INUSE | AST_EXTENSION_RINGING, "InUse&Ringing" },
259         { AST_EXTENSION_ONHOLD,                        "Hold" },
260         { AST_EXTENSION_INUSE | AST_EXTENSION_ONHOLD,  "InUse&Hold" }
261 };
262
263 struct statechange {
264         AST_LIST_ENTRY(statechange) entry;
265         char dev[0];
266 };
267
268 /*!
269  * \brief Data used by the device state thread
270  */
271 static struct {
272         /*! Set to 1 to stop the thread */
273         unsigned int stop:1;
274         /*! The device state monitoring thread */
275         pthread_t thread;
276         /*! Lock for the state change queue */
277         ast_mutex_t lock;
278         /*! Condition for the state change queue */
279         ast_cond_t cond;
280         /*! Queue of state changes */
281         AST_LIST_HEAD_NOLOCK(, statechange) state_change_q;
282 } device_state = {
283         .thread = AST_PTHREADT_NULL,
284 };
285
286 struct pbx_exception {
287         AST_DECLARE_STRING_FIELDS(
288                 AST_STRING_FIELD(context);      /*!< Context associated with this exception */
289                 AST_STRING_FIELD(exten);        /*!< Exten associated with this exception */
290                 AST_STRING_FIELD(reason);               /*!< The exception reason */
291         );
292
293         int priority;                           /*!< Priority associated with this exception */
294 };
295
296 static int pbx_builtin_answer(struct ast_channel *, void *);
297 static int pbx_builtin_goto(struct ast_channel *, void *);
298 static int pbx_builtin_hangup(struct ast_channel *, void *);
299 static int pbx_builtin_background(struct ast_channel *, void *);
300 static int pbx_builtin_wait(struct ast_channel *, void *);
301 static int pbx_builtin_waitexten(struct ast_channel *, void *);
302 static int pbx_builtin_keepalive(struct ast_channel *, void *);
303 static int pbx_builtin_resetcdr(struct ast_channel *, void *);
304 static int pbx_builtin_setamaflags(struct ast_channel *, void *);
305 static int pbx_builtin_ringing(struct ast_channel *, void *);
306 static int pbx_builtin_progress(struct ast_channel *, void *);
307 static int pbx_builtin_congestion(struct ast_channel *, void *);
308 static int pbx_builtin_busy(struct ast_channel *, void *);
309 static int pbx_builtin_noop(struct ast_channel *, void *);
310 static int pbx_builtin_gotoif(struct ast_channel *, void *);
311 static int pbx_builtin_gotoiftime(struct ast_channel *, void *);
312 static int pbx_builtin_execiftime(struct ast_channel *, void *);
313 static int pbx_builtin_saynumber(struct ast_channel *, void *);
314 static int pbx_builtin_saydigits(struct ast_channel *, void *);
315 static int pbx_builtin_saycharacters(struct ast_channel *, void *);
316 static int pbx_builtin_sayphonetic(struct ast_channel *, void *);
317 static int matchcid(const char *cidpattern, const char *callerid);
318 int pbx_builtin_setvar(struct ast_channel *, void *);
319 void log_match_char_tree(struct match_char *node, char *prefix); /* for use anywhere */
320 static int pbx_builtin_setvar_multiple(struct ast_channel *, void *);
321 static int pbx_builtin_importvar(struct ast_channel *, void *);
322 static void set_ext_pri(struct ast_channel *c, const char *exten, int pri); 
323 static void new_find_extension(const char *str, struct scoreboard *score, struct match_char *tree, int length, int spec, const char *callerid);
324 static struct match_char *already_in_tree(struct match_char *current, char *pat);
325 static struct match_char *add_exten_to_pattern_tree(struct ast_context *con, struct ast_exten *e1, int findonly);
326 static struct match_char *add_pattern_node(struct ast_context *con, struct match_char *current, char *pattern, int is_pattern, int already, int specificity);
327 static void create_match_char_tree(struct ast_context *con);
328 static struct ast_exten *get_canmatch_exten(struct match_char *node);
329 static void destroy_pattern_tree(struct match_char *pattern_tree);
330 static int hashtab_compare_contexts(const void *ah_a, const void *ah_b);
331 static int hashtab_compare_extens(const void *ha_a, const void *ah_b);
332 static int hashtab_compare_exten_numbers(const void *ah_a, const void *ah_b);
333 static int hashtab_compare_exten_labels(const void *ah_a, const void *ah_b);
334 static unsigned int hashtab_hash_contexts(const void *obj);
335 static unsigned int hashtab_hash_extens(const void *obj);
336 static unsigned int hashtab_hash_priority(const void *obj);
337 static unsigned int hashtab_hash_labels(const void *obj);
338
339 /* labels, contexts are case sensitive  priority numbers are ints */
340 static int hashtab_compare_contexts(const void *ah_a, const void *ah_b)
341 {
342         const struct ast_context *ac = ah_a;
343         const struct ast_context *bc = ah_b;
344         /* assume context names are registered in a string table! */
345         return strcmp(ac->name, bc->name);
346 }
347
348 static int hashtab_compare_extens(const void *ah_a, const void *ah_b)
349 {
350         const struct ast_exten *ac = ah_a;
351         const struct ast_exten *bc = ah_b;
352         int x = strcmp(ac->exten, bc->exten);
353         if (x) /* if exten names are diff, then return */
354                 return x;
355         /* but if they are the same, do the cidmatch values match? */
356         if (ac->matchcid && bc->matchcid) {
357                 return strcmp(ac->cidmatch,bc->cidmatch);
358         } else if (!ac->matchcid && !bc->matchcid) {
359                 return 0; /* if there's no matchcid on either side, then this is a match */
360         } else {
361                 return 1; /* if there's matchcid on one but not the other, they are different */
362         }
363 }
364
365 static int hashtab_compare_exten_numbers(const void *ah_a, const void *ah_b)
366 {
367         const struct ast_exten *ac = ah_a;
368         const struct ast_exten *bc = ah_b;
369         return ac->priority != bc->priority;
370 }
371
372 static int hashtab_compare_exten_labels(const void *ah_a, const void *ah_b)
373 {
374         const struct ast_exten *ac = ah_a;
375         const struct ast_exten *bc = ah_b;
376         return strcmp(ac->label, bc->label);
377 }
378
379 static unsigned int hashtab_hash_contexts(const void *obj)
380 {
381         const struct ast_context *ac = obj;
382         return ast_hashtab_hash_string(ac->name);
383 }
384
385 static unsigned int hashtab_hash_extens(const void *obj)
386 {
387         const struct ast_exten *ac = obj;
388         unsigned int x = ast_hashtab_hash_string(ac->exten);
389         unsigned int y = 0;
390         if (ac->matchcid)
391                 y = ast_hashtab_hash_string(ac->cidmatch);
392         return x+y;
393 }
394
395 static unsigned int hashtab_hash_priority(const void *obj)
396 {
397         const struct ast_exten *ac = obj;
398         return ast_hashtab_hash_int(ac->priority);
399 }
400
401 static unsigned int hashtab_hash_labels(const void *obj)
402 {
403         const struct ast_exten *ac = obj;
404         return ast_hashtab_hash_string(ac->label);
405 }
406
407
408 AST_RWLOCK_DEFINE_STATIC(globalslock);
409 static struct varshead globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
410
411 static int autofallthrough = 1;
412 static int extenpatternmatchnew = 0;
413
414 /*! \brief Subscription for device state change events */
415 static struct ast_event_sub *device_state_sub;
416
417 AST_MUTEX_DEFINE_STATIC(maxcalllock);
418 static int countcalls;
419 static int totalcalls;
420
421 static AST_RWLIST_HEAD_STATIC(acf_root, ast_custom_function);
422
423 /*! \brief Declaration of builtin applications */
424 static struct pbx_builtin {
425         char name[AST_MAX_APP];
426         int (*execute)(struct ast_channel *chan, void *data);
427         char *synopsis;
428         char *description;
429 } builtins[] =
430 {
431         /* These applications are built into the PBX core and do not
432            need separate modules */
433
434         { "Answer", pbx_builtin_answer,
435         "Answer a channel if ringing",
436         "  Answer([delay]): If the call has not been answered, this application will\n"
437         "answer it. Otherwise, it has no effect on the call. If a delay is specified,\n"
438         "Asterisk will wait this number of milliseconds before returning to\n"
439         "the dialplan after answering the call.\n"
440         },
441
442         { "BackGround", pbx_builtin_background,
443         "Play an audio file while waiting for digits of an extension to go to.",
444         "  Background(filename1[&filename2...][,options[,langoverride][,context]]):\n"
445         "This application will play the given list of files (do not put extension)\n"
446         "while waiting for an extension to be dialed by the calling channel. To\n"
447         "continue waiting for digits after this application has finished playing\n"
448         "files, the WaitExten application should be used. The 'langoverride' option\n"
449         "explicitly specifies which language to attempt to use for the requested sound\n"
450         "files. If a 'context' is specified, this is the dialplan context that this\n"
451         "application will use when exiting to a dialed extension."
452         "  If one of the requested sound files does not exist, call processing will be\n"
453         "terminated.\n"
454         "  Options:\n"
455         "    s - Causes the playback of the message to be skipped\n"
456         "          if the channel is not in the 'up' state (i.e. it\n"
457         "          hasn't been answered yet). If this happens, the\n"
458         "          application will return immediately.\n"
459         "    n - Don't answer the channel before playing the files.\n"
460         "    m - Only break if a digit hit matches a one digit\n"
461         "          extension in the destination context.\n"
462         "This application sets the following channel variable upon completion:\n"
463         " BACKGROUNDSTATUS    The status of the background attempt as a text string, one of\n"
464         "               SUCCESS | FAILED\n"
465         },
466
467         { "Busy", pbx_builtin_busy,
468         "Indicate the Busy condition",
469         "  Busy([timeout]): This application will indicate the busy condition to\n"
470         "the calling channel. If the optional timeout is specified, the calling channel\n"
471         "will be hung up after the specified number of seconds. Otherwise, this\n"
472         "application will wait until the calling channel hangs up.\n"
473         },
474
475         { "Congestion", pbx_builtin_congestion,
476         "Indicate the Congestion condition",
477         "  Congestion([timeout]): This application will indicate the congestion\n"
478         "condition to the calling channel. If the optional timeout is specified, the\n"
479         "calling channel will be hung up after the specified number of seconds.\n"
480         "Otherwise, this application will wait until the calling channel hangs up.\n"
481         },
482
483         { "ExecIfTime", pbx_builtin_execiftime,
484         "Conditional application execution based on the current time",
485         "  ExecIfTime(<times>,<weekdays>,<mdays>,<months>?appname[(appargs)]):\n"
486         "This application will execute the specified dialplan application, with optional\n"
487         "arguments, if the current time matches the given time specification.\n"
488         },
489
490         { "Goto", pbx_builtin_goto,
491         "Jump to a particular priority, extension, or context",
492         "  Goto([[context,]extension,]priority): This application will set the current\n"
493         "context, extension, and priority in the channel structure. After it completes, the\n"
494         "pbx engine will continue dialplan execution at the specified location.\n"
495         "If no specific extension, or extension and context, are specified, then this\n"
496         "application will just set the specified priority of the current extension.\n"
497         "  At least a priority is required as an argument, or the goto will return a -1,\n"
498         "and the channel and call will be terminated.\n"
499         "  If the location that is put into the channel information is bogus, and asterisk cannot\n"
500         "find that location in the dialplan,\n"
501         "then the execution engine will try to find and execute the code in the 'i' (invalid)\n"
502         "extension in the current context. If that does not exist, it will try to execute the\n"
503         "'h' extension. If either or neither the 'h' or 'i' extensions have been defined, the\n"
504         "channel is hung up, and the execution of instructions on the channel is terminated.\n"
505         "What this means is that, for example, you specify a context that does not exist, then\n"
506         "it will not be possible to find the 'h' or 'i' extensions, and the call will terminate!\n"
507         },
508
509         { "GotoIf", pbx_builtin_gotoif,
510         "Conditional goto",
511         "  GotoIf(condition?[labeliftrue]:[labeliffalse]): This application will set the current\n"
512         "context, extension, and priority in the channel structure based on the evaluation of\n"
513         "the given condition. After this application completes, the\n"
514         "pbx engine will continue dialplan execution at the specified location in the dialplan.\n"
515         "The channel will continue at\n"
516         "'labeliftrue' if the condition is true, or 'labeliffalse' if the condition is\n"
517         "false. The labels are specified with the same syntax as used within the Goto\n"
518         "application.  If the label chosen by the condition is omitted, no jump is\n"
519         "performed, and the execution passes to the next instruction.\n"
520         "If the target location is bogus, and does not exist, the execution engine will try \n"
521         "to find and execute the code in the 'i' (invalid)\n"
522         "extension in the current context. If that does not exist, it will try to execute the\n"
523         "'h' extension. If either or neither the 'h' or 'i' extensions have been defined, the\n"
524         "channel is hung up, and the execution of instructions on the channel is terminated.\n"
525         "Remember that this command can set the current context, and if the context specified\n"
526         "does not exist, then it will not be able to find any 'h' or 'i' extensions there, and\n"
527         "the channel and call will both be terminated!\n"
528         },
529
530         { "GotoIfTime", pbx_builtin_gotoiftime,
531         "Conditional Goto based on the current time",
532         "  GotoIfTime(<times>,<weekdays>,<mdays>,<months>?[[context,]exten,]priority):\n"
533         "This application will set the context, extension, and priority in the channel structure\n"
534         "if the current time matches the given time specification. Otherwise, nothing is done.\n"
535         "Further information on the time specification can be found in examples\n"
536         "illustrating how to do time-based context includes in the dialplan.\n" 
537         "If the target jump location is bogus, the same actions would be taken as for Goto.\n"
538         },
539
540         { "ImportVar", pbx_builtin_importvar,
541         "Import a variable from a channel into a new variable",
542         "  ImportVar(newvar=channelname,variable): This application imports a variable\n"
543         "from the specified channel (as opposed to the current one) and stores it as\n"
544         "a variable in the current channel (the channel that is calling this\n"
545         "application). Variables created by this application have the same inheritance\n"
546         "properties as those created with the Set application. See the documentation for\n"
547         "Set for more information.\n"
548         },
549
550         { "Hangup", pbx_builtin_hangup,
551         "Hang up the calling channel",
552         "  Hangup([causecode]): This application will hang up the calling channel.\n"
553         "If a causecode is given the channel's hangup cause will be set to the given\n"
554         "value.\n"
555         },
556
557         { "NoOp", pbx_builtin_noop,
558         "Do Nothing (No Operation)",
559         "  NoOp(): This application does nothing. However, it is useful for debugging\n"
560         "purposes. Any text that is provided as arguments to this application can be\n"
561         "viewed at the Asterisk CLI. This method can be used to see the evaluations of\n"
562         "variables or functions without having any effect. Alternatively, see the\n"
563   "Verbose() application for finer grain control of output at custom verbose levels.\n"
564         },
565
566         { "Progress", pbx_builtin_progress,
567         "Indicate progress",
568         "  Progress(): This application will request that in-band progress information\n"
569         "be provided to the calling channel.\n"
570         },
571
572         { "RaiseException", pbx_builtin_raise_exception,
573         "Handle an exceptional condition",
574         "  RaiseException(<reason>): This application will jump to the \"e\" extension\n"
575         "in the current context, setting the dialplan function EXCEPTION(). If the \"e\"\n"
576         "extension does not exist, the call will hangup.\n"
577         },
578
579         { "ResetCDR", pbx_builtin_resetcdr,
580         "Resets the Call Data Record",
581         "  ResetCDR([options]):  This application causes the Call Data Record to be\n"
582         "reset.\n"
583         "  Options:\n"
584         "    w -- Store the current CDR record before resetting it.\n"
585         "    a -- Store any stacked records.\n"
586         "    v -- Save CDR variables.\n"
587         },
588
589         { "Ringing", pbx_builtin_ringing,
590         "Indicate ringing tone",
591         "  Ringing(): This application will request that the channel indicate a ringing\n"
592         "tone to the user.\n"
593         },
594
595         { "SayAlpha", pbx_builtin_saycharacters,
596         "Say Alpha",
597         "  SayAlpha(string): This application will play the sounds that correspond to\n"
598         "the letters of the given string.\n"
599         },
600
601         { "SayDigits", pbx_builtin_saydigits,
602         "Say Digits",
603         "  SayDigits(digits): This application will play the sounds that correspond\n"
604         "to the digits of the given number. This will use the language that is currently\n"
605         "set for the channel. See the LANGUAGE function for more information on setting\n"
606         "the language for the channel.\n"
607         },
608
609         { "SayNumber", pbx_builtin_saynumber,
610         "Say Number",
611         "  SayNumber(digits[,gender]): This application will play the sounds that\n"
612         "correspond to the given number. Optionally, a gender may be specified.\n"
613         "This will use the language that is currently set for the channel. See the\n"
614         "LANGUAGE function for more information on setting the language for the channel.\n"
615         },
616
617         { "SayPhonetic", pbx_builtin_sayphonetic,
618         "Say Phonetic",
619         "  SayPhonetic(string): This application will play the sounds from the phonetic\n"
620         "alphabet that correspond to the letters in the given string.\n"
621         },
622
623         { "Set", pbx_builtin_setvar,
624         "Set channel variable or function value",
625         "  Set(name=value)\n"
626         "This function can be used to set the value of channel variables or dialplan\n"
627         "functions. When setting variables, if the variable name is prefixed with _,\n"
628         "the variable will be inherited into channels created from the current\n"
629         "channel. If the variable name is prefixed with __, the variable will be\n"
630         "inherited into channels created from the current channel and all children\n"
631         "channels.\n"
632         },
633
634         { "MSet", pbx_builtin_setvar_multiple,
635         "Set channel variable(s) or function value(s)",
636         "  MSet(name1=value1,name2=value2,...)\n"
637         "This function can be used to set the value of channel variables or dialplan\n"
638         "functions. When setting variables, if the variable name is prefixed with _,\n"
639         "the variable will be inherited into channels created from the current\n"
640         "channel. If the variable name is prefixed with __, the variable will be\n"
641         "inherited into channels created from the current channel and all children\n"
642         "channels.\n\n"
643         "MSet behaves in a similar fashion to the way Set worked in 1.2/1.4 and is thus\n"
644         "prone to doing things that you may not expect.  Avoid its use if possible.\n"
645         },
646
647         { "SetAMAFlags", pbx_builtin_setamaflags,
648         "Set the AMA Flags",
649         "  SetAMAFlags([flag]): This application will set the channel's AMA Flags for\n"
650         "  billing purposes.\n"
651         },
652
653         { "Wait", pbx_builtin_wait,
654         "Waits for some time",
655         "  Wait(seconds): This application waits for a specified number of seconds.\n"
656         "Then, dialplan execution will continue at the next priority.\n"
657         "  Note that the seconds can be passed with fractions of a second. For example,\n"
658         "'1.5' will ask the application to wait for 1.5 seconds.\n"
659         },
660
661         { "WaitExten", pbx_builtin_waitexten,
662         "Waits for an extension to be entered",
663         "  WaitExten([seconds][,options]): This application waits for the user to enter\n"
664         "a new extension for a specified number of seconds.\n"
665         "  Note that the seconds can be passed with fractions of a second. For example,\n"
666         "'1.5' will ask the application to wait for 1.5 seconds.\n"
667         "  Options:\n"
668         "    m[(x)] - Provide music on hold to the caller while waiting for an extension.\n"
669         "               Optionally, specify the class for music on hold within parenthesis.\n"
670         },
671
672         { "KeepAlive", pbx_builtin_keepalive,
673         "returns AST_PBX_KEEPALIVE value",
674         "  KeepAlive(): This application is chiefly meant for internal use with Gosubs.\n"
675         "Please do not run it alone from the dialplan!\n"
676         },
677
678 };
679
680 static struct ast_context *contexts;
681 static struct ast_hashtab *contexts_tree = NULL;
682
683 AST_RWLOCK_DEFINE_STATIC(conlock);              /*!< Lock for the ast_context list */
684
685 static AST_RWLIST_HEAD_STATIC(apps, ast_app);
686
687 static AST_RWLIST_HEAD_STATIC(switches, ast_switch);
688
689 static int stateid = 1;
690 /* WARNING:
691    When holding this list's lock, do _not_ do anything that will cause conlock
692    to be taken, unless you _already_ hold it. The ast_merge_contexts_and_delete
693    function will take the locks in conlock/hints order, so any other
694    paths that require both locks must also take them in that order.
695 */
696 static AST_RWLIST_HEAD_STATIC(hints, ast_hint);
697 struct ast_state_cb *statecbs;
698
699 /*
700    \note This function is special. It saves the stack so that no matter
701    how many times it is called, it returns to the same place */
702 int pbx_exec(struct ast_channel *c,             /*!< Channel */
703              struct ast_app *app,               /*!< Application */
704              void *data)                        /*!< Data for execution */
705 {
706         int res;
707         struct ast_module_user *u = NULL;
708         const char *saved_c_appl;
709         const char *saved_c_data;
710
711         if (c->cdr &&  !ast_check_hangup(c))
712                 ast_cdr_setapp(c->cdr, app->name, data);
713
714         /* save channel values */
715         saved_c_appl= c->appl;
716         saved_c_data= c->data;
717
718         c->appl = app->name;
719         c->data = data;
720         if (app->module)
721                 u = __ast_module_user_add(app->module, c);
722         res = app->execute(c, data);
723         if (app->module && u)
724                 __ast_module_user_remove(app->module, u);
725         /* restore channel values */
726         c->appl = saved_c_appl;
727         c->data = saved_c_data;
728         return res;
729 }
730
731
732 /*! Go no deeper than this through includes (not counting loops) */
733 #define AST_PBX_MAX_STACK       128
734
735 /*! \brief Find application handle in linked list
736  */
737 struct ast_app *pbx_findapp(const char *app)
738 {
739         struct ast_app *tmp;
740
741         AST_RWLIST_RDLOCK(&apps);
742         AST_RWLIST_TRAVERSE(&apps, tmp, list) {
743                 if (!strcasecmp(tmp->name, app))
744                         break;
745         }
746         AST_RWLIST_UNLOCK(&apps);
747
748         return tmp;
749 }
750
751 static struct ast_switch *pbx_findswitch(const char *sw)
752 {
753         struct ast_switch *asw;
754
755         AST_RWLIST_RDLOCK(&switches);
756         AST_RWLIST_TRAVERSE(&switches, asw, list) {
757                 if (!strcasecmp(asw->name, sw))
758                         break;
759         }
760         AST_RWLIST_UNLOCK(&switches);
761
762         return asw;
763 }
764
765 static inline int include_valid(struct ast_include *i)
766 {
767         if (!i->hastime)
768                 return 1;
769
770         return ast_check_timing(&(i->timing));
771 }
772
773 static void pbx_destroy(struct ast_pbx *p)
774 {
775         ast_free(p);
776 }
777
778 /* form a tree that fully describes all the patterns in a context's extensions 
779  * in this tree, a "node" consists of a series of match_char structs linked in a chain
780  * via the alt_char pointers. More than one pattern can share the same parts of the 
781  * tree as other extensions with the same pattern to that point. The algorithm to
782  * find which pattern best matches a string, would follow **all** matching paths. As
783  * complete matches are found, a "max" match record would be updated if the match first involves 
784  * a longer string, then, on a tie, a smaller total of specificity. This can be accomplished
785  * by recursive calls affecting a shared scoreboard.
786  * As and example, consider these 4 extensions:
787  * (a) NXXNXXXXXX
788  * (b) 307754XXXX 
789  * (c) fax
790  * (d) NXXXXXXXXX
791  *
792  * In the above, between (a) and (d), (a) is a more specific pattern than (d), and would win over
793  * most numbers. For all numbers beginning with 307754, (b) should always win.
794  *
795  * These pattern should form a tree that looks like this:
796  *   { "N" }  --next-->  { "X" }  --next--> { "X" } --next--> { "N" } --next--> { "X" } ... blah ... --> { "X" exten_match: (a) }
797  *      |                                                        |
798  *      |                                                        |alt
799  *      |alt                                                     |
800  *      |                                                     { "X" } --next--> { "X" } ... blah ... --> { "X" exten_match: (d) }
801  *      |
802  *   { "3" }  --next-->  { "0" }  --next--> { "7" } --next--> { "7" } --next--> { "5" } ... blah ... --> { "X" exten_match: (b) }
803  *      |
804  *      |alt
805  *      |
806  *   { "f" }  --next-->  { "a" }  --next--> { "x"  exten_match: (c) }
807  *
808  *   In the above, I could easily turn "N" into "23456789", but I think that a quick "if( *z >= '2' && *z <= '9' )" might take
809  *   fewer CPU cycles than a call to index("23456789",*z), where *z is the char to match...
810  *
811  *   traversal is pretty simple: one routine merely traverses the alt list, and for each match in the pattern,  it calls itself
812  *   on the corresponding next pointer, incrementing also the pointer of the string to be matched, and passing the total specificity and length.
813  *   We pass a pointer to a scoreboard down through, also.
814  *   When an exten_match pointer is set, or a '.' or a '!' is encountered, we update the scoreboard only if the length is greater, or in case
815  *   of equal length, if the specificity is lower, and return. Hope the limit on stack depth won't be a problem... this routine should 
816  *   be pretty lean as far a stack usage goes. Any non-match terminates the recursion down a branch.
817  *
818  *   In the above example, with the number "3077549999" as the pattern, the traversor should match extensions a, b and d.  All are
819  *   of length 10; but they have total specificities of  96, 46, and 98, respectively. (b) wins with its lower specificity number!
820  *
821  *   Just how much time this algorithm might save over a plain linear traversal over all possible patterns is unknown. But, it should
822  *   be pretty close to optimal for this sort of overall algorithm.
823  *
824  * */
825
826 /* you only really update the scoreboard, if the new score is BETTER than the 
827  * one stored there. ignore it otherwise.
828  */
829
830
831 static void update_scoreboard(struct scoreboard *board, int length, int spec, struct ast_exten *exten, char last, const char *callerid, int deleted, struct match_char *node)
832 {
833         /* doing a matchcid() check here would be easy and cheap, but...
834            unfortunately, it only works if an extension can have only one 
835            cid to match. That's not real life. CID patterns need to exist 
836            in the tree for this sort of thing to work properly. */
837
838         /* if this extension is marked as deleted, then skip this -- if it never shows
839            on the scoreboard, it will never be found */
840         if (deleted)
841                 return;
842         if (length > board->total_length) {
843                 board->total_specificity = spec;
844                 board->total_length = length;
845                 board->exten = exten;
846                 board->last_char = last;
847                 board->node = node;
848         } else if (length == board->total_length && spec < board->total_specificity) {
849                 board->total_specificity = spec;
850                 board->total_length = length;
851                 board->exten = exten;
852                 board->last_char = last;
853                 board->node = node;
854         }
855 }
856
857 void log_match_char_tree(struct match_char *node, char *prefix)
858 {
859         char my_prefix[1024];
860         char extenstr[40];
861         
862         extenstr[0] = 0;
863         if (node && node->exten && node->exten)
864                 sprintf(extenstr,"(%p)",node->exten);
865         
866         if (strlen(node->x) > 1 )
867                 ast_log(LOG_DEBUG,"%s[%s]:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y':'N', node->deleted? 'D':'-', node->specificity, node->exten? "EXTEN:":"", node->exten ? node->exten->exten : "", extenstr);
868         else
869                 ast_log(LOG_DEBUG,"%s%s:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y':'N', node->deleted? 'D':'-', node->specificity, node->exten? "EXTEN:":"", node->exten ? node->exten->exten : "", extenstr);
870         strcpy(my_prefix,prefix);
871         strcat(my_prefix,"+       ");
872         if (node->next_char)
873                 log_match_char_tree(node->next_char, my_prefix);
874         if (node->alt_char)
875                 log_match_char_tree(node->alt_char, prefix);
876 }
877
878 static void cli_match_char_tree(struct match_char *node, char *prefix, int fd)
879 {
880         char my_prefix[1024];
881         char extenstr[40];
882         
883         extenstr[0] = 0;
884         if (node && node->exten && node->exten)
885                 sprintf(extenstr,"(%p)",node->exten);
886         
887         if (strlen(node->x) > 1)
888                 ast_cli(fd, "%s[%s]:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y':'N', node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:":"", node->exten ? node->exten->exten : "", extenstr);
889         else
890                 ast_cli(fd, "%s%s:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y':'N', node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:":"", node->exten ? node->exten->exten : "", extenstr);
891         strcpy(my_prefix,prefix);
892         strcat(my_prefix,"+       ");
893         if (node->next_char)
894                 cli_match_char_tree(node->next_char, my_prefix, fd);
895         if (node->alt_char)
896                 cli_match_char_tree(node->alt_char, prefix, fd);
897 }
898
899 static struct ast_exten *get_canmatch_exten(struct match_char *node)
900 {
901         /* find the exten at the end of the rope */
902         struct match_char *node2 = node;
903         for (node2 = node; node2; node2 = node2->next_char)
904                 if (node2->exten)
905                         return node2->exten;
906         return 0;
907 }
908
909 static struct ast_exten *trie_find_next_match(struct match_char *node)
910 {
911         struct match_char *m3;
912         struct match_char *m4;
913         struct ast_exten *e3;
914         
915         if (node && node->x[0] == '.' && !node->x[1]) /* dot and ! will ALWAYS be next match in a matchmore */
916                 return node->exten;
917         
918         if (node && node->x[0] == '!' && !node->x[1])
919                 return node->exten;
920         
921         if (!node || !node->next_char)
922                 return NULL;
923         
924         m3 = node->next_char;
925
926         if (m3->exten)
927                 return m3->exten;
928         for(m4=m3->alt_char; m4; m4 = m4->alt_char) {
929                 if (m4->exten)
930                         return m4->exten;
931         }
932         for(m4=m3; m4; m4 = m4->alt_char) {
933                 e3 = trie_find_next_match(m3);
934                 if (e3)
935                         return e3;
936         }
937         return NULL;
938 }
939
940 static void new_find_extension(const char *str, struct scoreboard *score, struct match_char *tree, int length, int spec, const char *callerid)
941 {
942         struct match_char *p; /* note minimal stack storage requirements */
943 #ifdef DEBUG_THIS
944         if (tree)
945                 ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree %s\n", str, tree->x);
946         else
947                 ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree NULL\n", str);
948 #endif
949         for (p=tree; p; p=p->alt_char) {
950                 if (p->x[0] == 'N' && p->x[1] == 0 && *str >= '2' && *str <= '9' ) {
951                         if (p->exten && !(*(str+1))) /* if a shorter pattern matches along the way, might as well report it */
952                                 update_scoreboard(score, length+1, spec+p->specificity, p->exten,0,callerid, p->deleted, p);
953
954                         if (p->next_char && ( *(str+1) || (p->next_char->x[0] == '/' && p->next_char->x[1] == 0))) {
955                                 if (*(str+1))
956                                         new_find_extension(str+1, score, p->next_char, length+1, spec+p->specificity, callerid);
957                                 else
958                                         new_find_extension("/", score, p->next_char, length+1, spec+p->specificity, callerid);
959                         } else if (p->next_char && !*(str+1)) {
960                                 score->canmatch = 1;
961                                 score->canmatch_exten = get_canmatch_exten(p);
962                         } else {
963                                 return;
964                         }
965                 } else if (p->x[0] == 'Z' && p->x[1] == 0 && *str >= '1' && *str <= '9' ) {
966                         if (p->exten && !(*(str+1))) /* if a shorter pattern matches along the way, might as well report it */
967                                 update_scoreboard(score, length+1, spec+p->specificity, p->exten,0,callerid, p->deleted,p);
968
969                         if (p->next_char && ( *(str+1) || (p->next_char->x[0] == '/' && p->next_char->x[1] == 0))) {
970                                 if (*(str+1))
971                                         new_find_extension(str+1, score, p->next_char, length+1, spec+p->specificity, callerid);
972                                 else
973                                         new_find_extension("/", score, p->next_char, length+1, spec+p->specificity, callerid);
974                         } else if (p->next_char && !*(str+1)) {
975                                 score->canmatch = 1;
976                                 score->canmatch_exten = get_canmatch_exten(p);
977                         } else {
978                                 return;
979                         }
980                 } else if (p->x[0] == 'X' && p->x[1] == 0 && *str >= '0' && *str <= '9' ) {
981                         if (p->exten && !(*(str+1))) /* if a shorter pattern matches along the way, might as well report it */
982                                 update_scoreboard(score, length+1, spec+p->specificity, p->exten,0,callerid, p->deleted,p);
983
984                         if (p->next_char && ( *(str+1) || (p->next_char->x[0] == '/' && p->next_char->x[1] == 0))) {
985                                 if (*(str+1))
986                                         new_find_extension(str+1, score, p->next_char, length+1, spec+p->specificity, callerid);
987                                 else
988                                         new_find_extension("/", score, p->next_char, length+1, spec+p->specificity, callerid);
989                         } else if (p->next_char && !*(str+1)) {
990                                 score->canmatch = 1;
991                                 score->canmatch_exten = get_canmatch_exten(p);
992                         } else {
993                                 return;
994                         }
995                 } else if (p->x[0] == '.' && p->x[1] == 0) {
996                         /* how many chars will the . match against? */
997                         int i = 0;
998                         const char *str2 = str;
999                         while (*str2++) {
1000                                 i++;
1001                         }
1002                         if (p->exten && !(*(str+1)))
1003                                 update_scoreboard(score, length+i, spec+(i*p->specificity), p->exten, '.', callerid, p->deleted, p);
1004                         if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) {
1005                                 new_find_extension("/", score, p->next_char, length+i, spec+(p->specificity*i), callerid);
1006                         }
1007                         return;
1008                 } else if (p->x[0] == '!' && p->x[1] == 0) {
1009                         /* how many chars will the . match against? */
1010                         int i = 0;
1011                         const char *str2 = str;
1012                         while (*str2++) {
1013                                 i++;
1014                         }
1015                         if (p->exten && !(*(str+1)))
1016                                 update_scoreboard(score, length+1, spec+(p->specificity*i), p->exten, '!', callerid, p->deleted, p);
1017                         if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) {
1018                                 new_find_extension("/", score, p->next_char, length+i, spec+(p->specificity*i), callerid);
1019                         }
1020                         return;
1021                 } else if (p->x[0] == '/' && p->x[1] == 0) {
1022                         /* the pattern in the tree includes the cid match! */
1023                         if (p->next_char && callerid && *callerid) {
1024                                 new_find_extension(callerid, score, p->next_char, length+1, spec, callerid);
1025                         }
1026                 } else if (index(p->x, *str)) {
1027                         if (p->exten && !(*(str+1))) /* if a shorter pattern matches along the way, might as well report it */
1028                                 update_scoreboard(score, length+1, spec+p->specificity, p->exten,0,callerid, p->deleted, p);
1029
1030
1031                         if (p->next_char && ( *(str+1) || (p->next_char->x[0] == '/' && p->next_char->x[1] == 0))) {
1032                                 if (*(str+1)) {
1033                                         new_find_extension(str+1, score, p->next_char, length+1, spec+p->specificity, callerid);
1034                                 } else {
1035                                         new_find_extension("/", score, p->next_char, length+1, spec+p->specificity, callerid);
1036                                 }
1037                         } else if (p->next_char && !*(str+1)) {
1038                                 score->canmatch = 1;
1039                                 score->canmatch_exten = get_canmatch_exten(p);
1040                         } else {
1041                                 return;
1042                         }
1043                 }
1044         }
1045 }
1046
1047 /* the algorithm for forming the extension pattern tree is also a bit simple; you 
1048  * traverse all the extensions in a context, and for each char of the extension,
1049  * you see if it exists in the tree; if it doesn't, you add it at the appropriate
1050  * spot. What more can I say? At the end of the list, you cap it off by adding the
1051  * address of the extension involved. Duplicate patterns will be complained about.
1052  *
1053  * Ideally, this would be done for each context after it is created and fully 
1054  * filled. It could be done as a finishing step after extensions.conf or .ael is
1055  * loaded, or it could be done when the first search is encountered. It should only
1056  * have to be done once, until the next unload or reload.
1057  *
1058  * I guess forming this pattern tree would be analogous to compiling a regex.
1059  */
1060
1061 static struct match_char *already_in_tree(struct match_char *current, char *pat)
1062 {
1063         struct match_char *t;
1064         if (!current)
1065                 return 0;
1066         for (t=current; t; t=t->alt_char) {
1067                 if (strcmp(pat,t->x) == 0) /* uh, we may want to sort exploded [] contents to make matching easy */
1068                         return t;
1069         }
1070         return 0;
1071 }
1072
1073 static struct match_char *add_pattern_node(struct ast_context *con, struct match_char *current, char *pattern, int is_pattern, int already, int specificity)
1074 {
1075         struct match_char *m = ast_calloc(1,sizeof(struct match_char));
1076         m->x = ast_strdup(pattern);
1077         m->is_pattern = is_pattern;
1078         if (specificity == 1 && is_pattern && pattern[0] == 'N')
1079                 m->specificity = 98;
1080         else if (specificity == 1 && is_pattern && pattern[0] == 'Z')
1081                 m->specificity = 99;
1082         else if (specificity == 1 && is_pattern && pattern[0] == 'X')
1083                 m->specificity = 100;
1084         else if (specificity == 1 && is_pattern && pattern[0] == '.')
1085                 m->specificity = 200;
1086         else if (specificity == 1 && is_pattern && pattern[0] == '!')
1087                 m->specificity = 200;
1088         else
1089                 m->specificity = specificity;
1090         
1091         if (!con->pattern_tree) {
1092                 con->pattern_tree = m;
1093         } else {
1094                 if (already) { /* switch to the new regime (traversing vs appending)*/
1095                         m->alt_char = current->alt_char;
1096                         current->alt_char = m;
1097                 } else {
1098                         if (current->next_char) {
1099                                 m->alt_char = current->next_char->alt_char;
1100                                 current->next_char = m;
1101                         } else {
1102                                 current->next_char = m;
1103                         }
1104                 }
1105         }
1106         return m;
1107 }
1108
1109 static struct match_char *add_exten_to_pattern_tree(struct ast_context *con, struct ast_exten *e1, int findonly)
1110 {
1111         struct match_char *m1=0,*m2=0;
1112         int specif;
1113         int already;
1114         int pattern = 0;
1115         char buf[256];
1116         char extenbuf[512];
1117         char *s1 = extenbuf;
1118         int l1 = strlen(e1->exten) + strlen(e1->cidmatch) + 2;
1119         
1120
1121         strncpy(extenbuf,e1->exten,sizeof(extenbuf));
1122         if (e1->matchcid &&  l1 <= sizeof(extenbuf)) {
1123                 strcat(extenbuf,"/");
1124                 strcat(extenbuf,e1->cidmatch);
1125         } else if (l1 > sizeof(extenbuf)) {
1126                 ast_log(LOG_ERROR,"The pattern %s/%s is too big to deal with: it will be ignored! Disaster!\n", e1->exten, e1->cidmatch);
1127                 return 0;
1128         }
1129 #ifdef NEED_DEBUG
1130         ast_log(LOG_DEBUG,"Adding exten %s%c%s to tree\n", s1, e1->matchcid? '/':' ', e1->matchcid? e1->cidmatch : "");
1131 #endif
1132         m1 = con->pattern_tree; /* each pattern starts over at the root of the pattern tree */
1133         already = 1;
1134
1135         if ( *s1 == '_') {
1136                 pattern = 1;
1137                 s1++;
1138         }
1139         while( *s1 ) {
1140                 if (pattern && *s1 == '[' && *(s1-1) != '\\') {
1141                         char *s2 = buf;
1142                         buf[0] = 0;
1143                         s1++; /* get past the '[' */
1144                         while (*s1 != ']' && *(s1-1) != '\\' ) {
1145                                 if (*s1 == '\\') {
1146                                         if (*(s1+1) == ']') {
1147                                                 *s2++ = ']';
1148                                                 s1++;s1++;
1149                                         } else if (*(s1+1) == '\\') {
1150                                                 *s2++ = '\\';
1151                                                 s1++;s1++;
1152                                         } else if (*(s1+1) == '-') {
1153                                                 *s2++ = '-';
1154                                                 s1++; s1++;
1155                                         } else if (*(s1+1) == '[') {
1156                                                 *s2++ = '[';
1157                                                 s1++; s1++;
1158                                         }
1159                                 } else if (*s1 == '-') { /* remember to add some error checking to all this! */
1160                                         char s3 = *(s1-1);
1161                                         char s4 = *(s1+1);
1162                                         for (s3++; s3 <= s4; s3++) {
1163                                                 *s2++ = s3;
1164                                         }
1165                                         s1++; s1++;
1166                                 } else {
1167                                         *s2++ = *s1++;
1168                                 }
1169                         }
1170                         *s2 = 0; /* null terminate the exploded range */
1171                         specif = strlen(buf);
1172                 } else {
1173                         
1174                         if (*s1 == '\\') {
1175                                 s1++;
1176                                 buf[0] = *s1;
1177                         } else {
1178                                 if (pattern) {
1179                                         if (*s1 == 'n') /* make sure n,x,z patterns are canonicalized to N,X,Z */
1180                                                 *s1 = 'N';
1181                                         else if (*s1 == 'x')
1182                                                 *s1 = 'X';
1183                                         else if (*s1 == 'z')
1184                                                 *s1 = 'Z';
1185                                 }
1186                                 buf[0] = *s1;
1187                         }
1188                         buf[1] = 0;
1189                         specif = 1;
1190                 }
1191                 m2 = 0;
1192                 if (already && (m2=already_in_tree(m1,buf)) && m2->next_char) {
1193                         if (!(*(s1+1))) {  /* if this is the end of the pattern, but not the end of the tree, then mark this node with the exten...
1194                                                                 a shorter pattern might win if the longer one doesn't match */
1195                                 m2->exten = e1;
1196                                 m2->deleted = 0;
1197                         }
1198                         m1 = m2->next_char; /* m1 points to the node to compare against */
1199                 } else {
1200                         if (m2) {
1201                                 if (findonly)
1202                                         return m2;
1203                                 m1 = m2;
1204                         } else {
1205                                 if (findonly)
1206                                         return m1;
1207                                 m1 = add_pattern_node(con, m1, buf, pattern, already,specif); /* m1 is the node just added */
1208                         }
1209                         
1210                         if (!(*(s1+1))) {
1211                                 m1->deleted = 0;
1212                                 m1->exten = e1;
1213                         }
1214                         
1215                         already = 0;
1216                 }
1217                 s1++; /* advance to next char */
1218         }
1219         return m1;
1220 }
1221
1222 static void create_match_char_tree(struct ast_context *con)
1223 {
1224         struct ast_hashtab_iter *t1;
1225         struct ast_exten *e1;
1226 #ifdef NEED_DEBUG
1227         int biggest_bucket, resizes, numobjs, numbucks;
1228         
1229         ast_log(LOG_DEBUG,"Creating Extension Trie for context %s\n", con->name);
1230         ast_hashtab_get_stats(con->root_tree, &biggest_bucket, &resizes, &numobjs, &numbucks);
1231         ast_log(LOG_DEBUG,"This tree has %d objects in %d bucket lists, longest list=%d objects, and has resized %d times\n",
1232                         numobjs, numbucks, biggest_bucket, resizes);
1233 #endif
1234         t1 = ast_hashtab_start_traversal(con->root_tree);
1235         while( (e1 = ast_hashtab_next(t1)) ) {
1236                 if (e1->exten)
1237                         add_exten_to_pattern_tree(con, e1, 0);
1238                 else
1239                         ast_log(LOG_ERROR,"Attempt to create extension with no extension name.\n");
1240         }
1241         ast_hashtab_end_traversal(t1);
1242 }
1243
1244 static void destroy_pattern_tree(struct match_char *pattern_tree) /* pattern tree is a simple binary tree, sort of, so the proper way to destroy it is... recursively! */
1245 {
1246         /* destroy all the alternates */
1247         if (pattern_tree->alt_char) {
1248                 destroy_pattern_tree(pattern_tree->alt_char);
1249                 pattern_tree->alt_char = 0;
1250         }
1251         /* destroy all the nexts */
1252         if (pattern_tree->next_char) {
1253                 destroy_pattern_tree(pattern_tree->next_char);
1254                 pattern_tree->next_char = 0;
1255         }
1256         pattern_tree->exten = 0; /* never hurts to make sure there's no pointers laying around */
1257         if (pattern_tree->x)
1258                 free(pattern_tree->x);
1259         free(pattern_tree);
1260 }
1261
1262 /*
1263  * Special characters used in patterns:
1264  *      '_'     underscore is the leading character of a pattern.
1265  *              In other position it is treated as a regular char.
1266  *      ' ' '-' space and '-' are separator and ignored.
1267  *      .       one or more of any character. Only allowed at the end of
1268  *              a pattern.
1269  *      !       zero or more of anything. Also impacts the result of CANMATCH
1270  *              and MATCHMORE. Only allowed at the end of a pattern.
1271  *              In the core routine, ! causes a match with a return code of 2.
1272  *              In turn, depending on the search mode: (XXX check if it is implemented)
1273  *              - E_MATCH retuns 1 (does match)
1274  *              - E_MATCHMORE returns 0 (no match)
1275  *              - E_CANMATCH returns 1 (does match)
1276  *
1277  *      /       should not appear as it is considered the separator of the CID info.
1278  *              XXX at the moment we may stop on this char.
1279  *
1280  *      X Z N   match ranges 0-9, 1-9, 2-9 respectively.
1281  *      [       denotes the start of a set of character. Everything inside
1282  *              is considered literally. We can have ranges a-d and individual
1283  *              characters. A '[' and '-' can be considered literally if they
1284  *              are just before ']'.
1285  *              XXX currently there is no way to specify ']' in a range, nor \ is
1286  *              considered specially.
1287  *
1288  * When we compare a pattern with a specific extension, all characters in the extension
1289  * itself are considered literally with the only exception of '-' which is considered
1290  * as a separator and thus ignored.
1291  * XXX do we want to consider space as a separator as well ?
1292  * XXX do we want to consider the separators in non-patterns as well ?
1293  */
1294
1295 /*!
1296  * \brief helper functions to sort extensions and patterns in the desired way,
1297  * so that more specific patterns appear first.
1298  *
1299  * ext_cmp1 compares individual characters (or sets of), returning
1300  * an int where bits 0-7 are the ASCII code of the first char in the set,
1301  * while bit 8-15 are the cardinality of the set minus 1.
1302  * This way more specific patterns (smaller cardinality) appear first.
1303  * Wildcards have a special value, so that we can directly compare them to
1304  * sets by subtracting the two values. In particular:
1305  *      0x000xx         one character, xx
1306  *      0x0yyxx         yy character set starting with xx
1307  *      0x10000         '.' (one or more of anything)
1308  *      0x20000         '!' (zero or more of anything)
1309  *      0x30000         NUL (end of string)
1310  *      0x40000         error in set.
1311  * The pointer to the string is advanced according to needs.
1312  * NOTES:
1313  *      1. the empty set is equivalent to NUL.
1314  *      2. given that a full set has always 0 as the first element,
1315  *         we could encode the special cases as 0xffXX where XX
1316  *         is 1, 2, 3, 4 as used above.
1317  */
1318 static int ext_cmp1(const char **p)
1319 {
1320         uint32_t chars[8];
1321         int c, cmin = 0xff, count = 0;
1322         const char *end;
1323
1324         /* load, sign extend and advance pointer until we find
1325          * a valid character.
1326          */
1327         while ( (c = *(*p)++) && (c == ' ' || c == '-') )
1328                 ;       /* ignore some characters */
1329
1330         /* always return unless we have a set of chars */
1331         switch (c) {
1332         default:        /* ordinary character */
1333                 return 0x0000 | (c & 0xff);
1334
1335         case 'N':       /* 2..9 */
1336                 return 0x0700 | '2' ;
1337
1338         case 'X':       /* 0..9 */
1339                 return 0x0900 | '0';
1340
1341         case 'Z':       /* 1..9 */
1342                 return 0x0800 | '1';
1343
1344         case '.':       /* wildcard */
1345                 return 0x10000;
1346
1347         case '!':       /* earlymatch */
1348                 return 0x20000; /* less specific than NULL */
1349
1350         case '\0':      /* empty string */
1351                 *p = NULL;
1352                 return 0x30000;
1353
1354         case '[':       /* pattern */
1355                 break;
1356         }
1357         /* locate end of set */
1358         end = strchr(*p, ']');  
1359
1360         if (end == NULL) {
1361                 ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n");
1362                 return 0x40000; /* XXX make this entry go last... */
1363         }
1364
1365         bzero(chars, sizeof(chars));    /* clear all chars in the set */
1366         for (; *p < end  ; (*p)++) {
1367                 unsigned char c1, c2;   /* first-last char in range */
1368                 c1 = (unsigned char)((*p)[0]);
1369                 if (*p + 2 < end && (*p)[1] == '-') { /* this is a range */
1370                         c2 = (unsigned char)((*p)[2]);
1371                         *p += 2;        /* skip a total of 3 chars */
1372                 } else                  /* individual character */
1373                         c2 = c1;
1374                 if (c1 < cmin)
1375                         cmin = c1;
1376                 for (; c1 <= c2; c1++) {
1377                         uint32_t mask = 1 << (c1 % 32);
1378                         if ( (chars[ c1 / 32 ] & mask) == 0)
1379                                 count += 0x100;
1380                         chars[ c1 / 32 ] |= mask;
1381                 }
1382         }
1383         (*p)++;
1384         return count == 0 ? 0x30000 : (count | cmin);
1385 }
1386
1387 /*!
1388  * \brief the full routine to compare extensions in rules.
1389  */
1390 static int ext_cmp(const char *a, const char *b)
1391 {
1392         /* make sure non-patterns come first.
1393          * If a is not a pattern, it either comes first or
1394          * we use strcmp to compare the strings.
1395          */
1396         int ret = 0;
1397
1398         if (a[0] != '_')
1399                 return (b[0] == '_') ? -1 : strcmp(a, b);
1400
1401         /* Now we know a is a pattern; if b is not, a comes first */
1402         if (b[0] != '_')
1403                 return 1;
1404 #if 0   /* old mode for ext matching */
1405         return strcmp(a, b);
1406 #endif
1407         /* ok we need full pattern sorting routine */
1408         while (!ret && a && b)
1409                 ret = ext_cmp1(&a) - ext_cmp1(&b);
1410         if (ret == 0)
1411                 return 0;
1412         else
1413                 return (ret > 0) ? 1 : -1;
1414 }
1415
1416 int ast_extension_cmp(const char *a, const char *b)
1417 {
1418         return ext_cmp(a, b);
1419 }
1420
1421 /*!
1422  * \internal
1423  * \brief used ast_extension_{match|close}
1424  * mode is as follows:
1425  *      E_MATCH         success only on exact match
1426  *      E_MATCHMORE     success only on partial match (i.e. leftover digits in pattern)
1427  *      E_CANMATCH      either of the above.
1428  * \retval 0 on no-match
1429  * \retval 1 on match
1430  * \retval 2 on early match.
1431  */
1432
1433 static int _extension_match_core(const char *pattern, const char *data, enum ext_match_t mode)
1434 {
1435         mode &= E_MATCH_MASK;   /* only consider the relevant bits */
1436
1437         if ( (mode == E_MATCH) && (pattern[0] == '_') && (strcasecmp(pattern,data)==0) ) /* note: if this test is left out, then _x. will not match _x. !!! */
1438                 return 1;
1439
1440         if (pattern[0] != '_') { /* not a pattern, try exact or partial match */
1441                 int ld = strlen(data), lp = strlen(pattern);
1442
1443                 if (lp < ld)            /* pattern too short, cannot match */
1444                         return 0;
1445                 /* depending on the mode, accept full or partial match or both */
1446                 if (mode == E_MATCH)
1447                         return !strcmp(pattern, data); /* 1 on match, 0 on fail */
1448                 if (ld == 0 || !strncasecmp(pattern, data, ld)) /* partial or full match */
1449                         return (mode == E_MATCHMORE) ? lp > ld : 1; /* XXX should consider '!' and '/' ? */
1450                 else
1451                         return 0;
1452         }
1453         pattern++; /* skip leading _ */
1454         /*
1455          * XXX below we stop at '/' which is a separator for the CID info. However we should
1456          * not store '/' in the pattern at all. When we insure it, we can remove the checks.
1457          */
1458         while (*data && *pattern && *pattern != '/') {
1459                 const char *end;
1460
1461                 if (*data == '-') { /* skip '-' in data (just a separator) */
1462                         data++;
1463                         continue;
1464                 }
1465                 switch (toupper(*pattern)) {
1466                 case '[':       /* a range */
1467                         end = strchr(pattern+1, ']'); /* XXX should deal with escapes ? */
1468                         if (end == NULL) {
1469                                 ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n");
1470                                 return 0;       /* unconditional failure */
1471                         }
1472                         for (pattern++; pattern != end; pattern++) {
1473                                 if (pattern+2 < end && pattern[1] == '-') { /* this is a range */
1474                                         if (*data >= pattern[0] && *data <= pattern[2])
1475                                                 break;  /* match found */
1476                                         else {
1477                                                 pattern += 2; /* skip a total of 3 chars */
1478                                                 continue;
1479                                         }
1480                                 } else if (*data == pattern[0])
1481                                         break;  /* match found */
1482                         }
1483                         if (pattern == end)
1484                                 return 0;
1485                         pattern = end;  /* skip and continue */
1486                         break;
1487                 case 'N':
1488                         if (*data < '2' || *data > '9')
1489                                 return 0;
1490                         break;
1491                 case 'X':
1492                         if (*data < '0' || *data > '9')
1493                                 return 0;
1494                         break;
1495                 case 'Z':
1496                         if (*data < '1' || *data > '9')
1497                                 return 0;
1498                         break;
1499                 case '.':       /* Must match, even with more digits */
1500                         return 1;
1501                 case '!':       /* Early match */
1502                         return 2;
1503                 case ' ':
1504                 case '-':       /* Ignore these in patterns */
1505                         data--; /* compensate the final data++ */
1506                         break;
1507                 default:
1508                         if (*data != *pattern)
1509                                 return 0;
1510                 }
1511                 data++;
1512                 pattern++;
1513         }
1514         if (*data)                      /* data longer than pattern, no match */
1515                 return 0;
1516         /*
1517          * match so far, but ran off the end of the data.
1518          * Depending on what is next, determine match or not.
1519          */
1520         if (*pattern == '\0' || *pattern == '/')        /* exact match */
1521                 return (mode == E_MATCHMORE) ? 0 : 1;   /* this is a failure for E_MATCHMORE */
1522         else if (*pattern == '!')                       /* early match */
1523                 return 2;
1524         else                                            /* partial match */
1525                 return (mode == E_MATCH) ? 0 : 1;       /* this is a failure for E_MATCH */
1526 }
1527
1528 /*
1529  * Wrapper around _extension_match_core() to do performance measurement
1530  * using the profiling code.
1531  */
1532 static int extension_match_core(const char *pattern, const char *data, enum ext_match_t mode)
1533 {
1534         int i;
1535         static int prof_id = -2;        /* marker for 'unallocated' id */
1536         if (prof_id == -2)
1537                 prof_id = ast_add_profile("ext_match", 0);
1538         ast_mark(prof_id, 1);
1539         i = _extension_match_core(pattern, data, mode);
1540         ast_mark(prof_id, 0);
1541         return i;
1542 }
1543
1544 int ast_extension_match(const char *pattern, const char *data)
1545 {
1546         return extension_match_core(pattern, data, E_MATCH);
1547 }
1548
1549 int ast_extension_close(const char *pattern, const char *data, int needmore)
1550 {
1551         if (needmore != E_MATCHMORE && needmore != E_CANMATCH)
1552                 ast_log(LOG_WARNING, "invalid argument %d\n", needmore);
1553         return extension_match_core(pattern, data, needmore);
1554 }
1555
1556 struct fake_context /* this struct is purely for matching in the hashtab */
1557 {
1558         ast_rwlock_t lock;                      
1559         struct ast_exten *root;         
1560         struct ast_hashtab *root_tree;            
1561         struct match_char *pattern_tree;       
1562         struct ast_context *next;       
1563         struct ast_include *includes;           
1564         struct ast_ignorepat *ignorepats;       
1565         const char *registrar;  
1566         AST_LIST_HEAD_NOLOCK(, ast_sw) alts;    
1567         ast_mutex_t macrolock;          
1568         char name[256];         
1569 };
1570
1571 struct ast_context *ast_context_find(const char *name)
1572 {
1573         struct ast_context *tmp = NULL;
1574         struct fake_context item;
1575         strncpy(item.name,name,256);
1576         ast_rdlock_contexts();
1577         if( contexts_tree ) {
1578                 tmp = ast_hashtab_lookup(contexts_tree,&item);
1579         } else {
1580                 while ( (tmp = ast_walk_contexts(tmp)) ) {
1581                         if (!name || !strcasecmp(name, tmp->name))
1582                                 break;
1583                 }
1584         }
1585         ast_unlock_contexts();
1586         return tmp;
1587 }
1588
1589 #define STATUS_NO_CONTEXT       1
1590 #define STATUS_NO_EXTENSION     2
1591 #define STATUS_NO_PRIORITY      3
1592 #define STATUS_NO_LABEL         4
1593 #define STATUS_SUCCESS          5
1594
1595 static int matchcid(const char *cidpattern, const char *callerid)
1596 {
1597         /* If the Caller*ID pattern is empty, then we're matching NO Caller*ID, so
1598            failing to get a number should count as a match, otherwise not */
1599
1600         if (ast_strlen_zero(callerid))
1601                 return ast_strlen_zero(cidpattern) ? 1 : 0;
1602
1603         return ast_extension_match(cidpattern, callerid);
1604 }
1605
1606 struct ast_exten *pbx_find_extension(struct ast_channel *chan,
1607         struct ast_context *bypass, struct pbx_find_info *q,
1608         const char *context, const char *exten, int priority,
1609         const char *label, const char *callerid, enum ext_match_t action)
1610 {
1611         int x, res;
1612         struct ast_context *tmp=0;
1613         struct ast_exten *e=0, *eroot=0;
1614         struct ast_include *i = 0;
1615         struct ast_sw *sw = 0;
1616         struct ast_exten pattern = {0};
1617         struct scoreboard score = {0};
1618
1619         pattern.label = label;
1620         pattern.priority = priority;
1621 #ifdef NEED_DEBUG
1622         ast_log(LOG_NOTICE,"Looking for cont/ext/prio/label/action = %s/%s/%d/%s/%d\n", context, exten, priority, label, (int)action);
1623 #endif
1624         /* Initialize status if appropriate */
1625         if (q->stacklen == 0) {
1626                 q->status = STATUS_NO_CONTEXT;
1627                 q->swo = NULL;
1628                 q->data = NULL;
1629                 q->foundcontext = NULL;
1630         } else if (q->stacklen >= AST_PBX_MAX_STACK) {
1631                 ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n");
1632                 return NULL;
1633         }
1634
1635         /* Check first to see if we've already been checked */
1636         for (x = 0; x < q->stacklen; x++) {
1637                 if (!strcasecmp(q->incstack[x], context))
1638                         return NULL;
1639         }
1640
1641         if (bypass)     /* bypass means we only look there */
1642                 tmp = bypass;
1643         else {  /* look in contexts */
1644                 struct fake_context item;
1645                 strncpy(item.name,context,256);
1646                 tmp = ast_hashtab_lookup(contexts_tree,&item);
1647 #ifdef NOTNOW
1648                 tmp = NULL;
1649                 while ((tmp = ast_walk_contexts(tmp)) ) {
1650                         if (!strcmp(tmp->name, context))
1651                                 break;
1652                 }
1653 #endif
1654                 if (!tmp)
1655                         return NULL;
1656                 
1657         }
1658
1659         if (q->status < STATUS_NO_EXTENSION)
1660                 q->status = STATUS_NO_EXTENSION;
1661         
1662         /* Do a search for matching extension */
1663
1664         eroot = NULL;
1665         score.total_specificity = 0;
1666         score.exten = 0;
1667         score.total_length = 0;
1668         if (!tmp->pattern_tree && tmp->root_tree)
1669         {
1670                 create_match_char_tree(tmp);
1671 #ifdef NEED_DEBUG
1672                 ast_log(LOG_DEBUG,"Tree Created in context %s:\n", context);
1673                 log_match_char_tree(tmp->pattern_tree," ");
1674 #endif
1675         }
1676 #ifdef NEED_DEBUG
1677         ast_log(LOG_NOTICE,"The Trie we are searching in:\n");
1678         log_match_char_tree(tmp->pattern_tree, "::  ");
1679 #endif
1680
1681         if (extenpatternmatchnew) {
1682                 new_find_extension(exten, &score, tmp->pattern_tree, 0, 0, callerid);
1683                 eroot = score.exten;
1684                 
1685                 if (score.last_char == '!' && action == E_MATCHMORE) {
1686                         /* We match an extension ending in '!'.
1687                          * The decision in this case is final and is NULL (no match).
1688                          */
1689 #ifdef NEED_DEBUG
1690                         ast_log(LOG_NOTICE,"Returning MATCHMORE NULL with exclamation point.\n");
1691 #endif
1692                         return NULL;
1693                 }
1694                 
1695                 if (!eroot && (action == E_CANMATCH || action == E_MATCHMORE) && score.canmatch_exten) {
1696                         q->status = STATUS_SUCCESS;
1697 #ifdef NEED_DEBUG
1698                         ast_log(LOG_NOTICE,"Returning CANMATCH exten %s\n", score.canmatch_exten->exten);
1699 #endif
1700                         return score.canmatch_exten;
1701                 }
1702                 
1703                 if ((action == E_MATCHMORE || action == E_CANMATCH)  && eroot) {
1704                         if (score.node) {
1705                                 struct ast_exten *z = trie_find_next_match(score.node);
1706 #ifdef NEED_DEBUG
1707                                 if (z)
1708                                         ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten %s\n", z->exten);
1709                                 else
1710                                         ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten NULL\n");
1711 #endif
1712                                 return z;
1713                         }
1714 #ifdef NEED_DEBUG
1715                         ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE NULL (no next_match)\n");
1716 #endif
1717                         return NULL;  /* according to the code, complete matches are null matches in MATCHMORE mode */
1718                 }
1719                 
1720                 if (eroot) {
1721                         /* found entry, now look for the right priority */
1722                         if (q->status < STATUS_NO_PRIORITY)
1723                                 q->status = STATUS_NO_PRIORITY;
1724                         e = NULL;
1725                         if (action == E_FINDLABEL && label ) {
1726                                 if (q->status < STATUS_NO_LABEL)
1727                                         q->status = STATUS_NO_LABEL;
1728                                 e = ast_hashtab_lookup(eroot->peer_label_tree, &pattern);
1729                         } else {
1730                                 e = ast_hashtab_lookup(eroot->peer_tree, &pattern);
1731                         }
1732                         if (e) {        /* found a valid match */
1733                                 q->status = STATUS_SUCCESS;
1734                                 q->foundcontext = context;
1735 #ifdef NEED_DEBUG
1736                                 ast_log(LOG_NOTICE,"Returning complete match of exten %s\n", e->exten);
1737 #endif
1738                                 return e;
1739                         }
1740                 }
1741         } else {
1742                 
1743                 /* scan the list trying to match extension and CID */
1744                 eroot = NULL;
1745                 while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) {
1746                         int match = extension_match_core(eroot->exten, exten, action);
1747                         /* 0 on fail, 1 on match, 2 on earlymatch */
1748                         
1749                         if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid)))
1750                                 continue;       /* keep trying */
1751                         if (match == 2 && action == E_MATCHMORE) {
1752                                 /* We match an extension ending in '!'.
1753                                  * The decision in this case is final and is NULL (no match).
1754                                  */
1755                                 return NULL;
1756                         }
1757                         /* found entry, now look for the right priority */
1758                         if (q->status < STATUS_NO_PRIORITY)
1759                                 q->status = STATUS_NO_PRIORITY;
1760                         e = NULL;
1761                         if (action == E_FINDLABEL && label ) {
1762                                 if (q->status < STATUS_NO_LABEL)
1763                                         q->status = STATUS_NO_LABEL;
1764                                 e = ast_hashtab_lookup(eroot->peer_label_tree, &pattern);
1765                         } else {
1766                                 e = ast_hashtab_lookup(eroot->peer_tree, &pattern);
1767                         }
1768 #ifdef NOTNOW
1769                         while ( (e = ast_walk_extension_priorities(eroot, e)) ) {
1770                                 /* Match label or priority */
1771                                 if (action == E_FINDLABEL) {
1772                                         if (q->status < STATUS_NO_LABEL)
1773                                                 q->status = STATUS_NO_LABEL;
1774                                         if (label && e->label && !strcmp(label, e->label))
1775                                                 break;  /* found it */
1776                                 } else if (e->priority == priority) {
1777                                         break;  /* found it */
1778                                 } /* else keep searching */
1779                         }
1780 #endif
1781                         if (e) {        /* found a valid match */
1782                                 q->status = STATUS_SUCCESS;
1783                                 q->foundcontext = context;
1784                                 return e;
1785                         }
1786                 }
1787         }
1788         
1789         
1790         /* Check alternative switches */
1791         AST_LIST_TRAVERSE(&tmp->alts, sw, list) {
1792                 struct ast_switch *asw = pbx_findswitch(sw->name);
1793                 ast_switch_f *aswf = NULL;
1794                 char *datap;
1795
1796                 if (!asw) {
1797                         ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name);
1798                         continue;
1799                 }
1800                 /* Substitute variables now */
1801                 
1802                 if (sw->eval)
1803                         pbx_substitute_variables_helper(chan, sw->data, sw->tmpdata, SWITCH_DATA_LENGTH - 1);
1804
1805                 /* equivalent of extension_match_core() at the switch level */
1806                 if (action == E_CANMATCH)
1807                         aswf = asw->canmatch;
1808                 else if (action == E_MATCHMORE)
1809                         aswf = asw->matchmore;
1810                 else /* action == E_MATCH */
1811                         aswf = asw->exists;
1812                 datap = sw->eval ? sw->tmpdata : sw->data;
1813                 if (!aswf)
1814                         res = 0;
1815                 else {
1816                         if (chan)
1817                                 ast_autoservice_start(chan);
1818                         res = aswf(chan, context, exten, priority, callerid, datap);
1819                         if (chan)
1820                                 ast_autoservice_stop(chan);
1821                 }
1822                 if (res) {      /* Got a match */
1823                         q->swo = asw;
1824                         q->data = datap;
1825                         q->foundcontext = context;
1826                         /* XXX keep status = STATUS_NO_CONTEXT ? */
1827                         return NULL;
1828                 }
1829         }
1830         q->incstack[q->stacklen++] = tmp->name; /* Setup the stack */
1831         /* Now try any includes we have in this context */
1832         for (i = tmp->includes; i; i = i->next) {
1833                 if (include_valid(i)) {
1834                         if ((e = pbx_find_extension(chan, bypass, q, i->rname, exten, priority, label, callerid, action))) {
1835 #ifdef NEED_DEBUG
1836                                 ast_log(LOG_NOTICE,"Returning recursive match of %s\n", e->exten);
1837 #endif
1838                                 return e;
1839                         }
1840                         if (q->swo)
1841                                 return NULL;
1842                 }
1843         }
1844         return NULL;
1845 }
1846
1847 /*! 
1848  * \brief extract offset:length from variable name.
1849  * \return 1 if there is a offset:length part, which is
1850  * trimmed off (values go into variables)
1851  */
1852 static int parse_variable_name(char *var, int *offset, int *length, int *isfunc)
1853 {
1854         int parens=0;
1855
1856         *offset = 0;
1857         *length = INT_MAX;
1858         *isfunc = 0;
1859         for (; *var; var++) {
1860                 if (*var == '(') {
1861                         (*isfunc)++;
1862                         parens++;
1863                 } else if (*var == ')') {
1864                         parens--;
1865                 } else if (*var == ':' && parens == 0) {
1866                         *var++ = '\0';
1867                         sscanf(var, "%d:%d", offset, length);
1868                         return 1; /* offset:length valid */
1869                 }
1870         }
1871         return 0;
1872 }
1873
1874 /*! 
1875  *\brief takes a substring. It is ok to call with value == workspace.
1876  * \param value
1877  * \param offset < 0 means start from the end of the string and set the beginning
1878  *   to be that many characters back.
1879  * \param length is the length of the substring, a value less than 0 means to leave
1880  * that many off the end.
1881  * \param workspace
1882  * \param workspace_len
1883  * Always return a copy in workspace.
1884  */
1885 static char *substring(const char *value, int offset, int length, char *workspace, size_t workspace_len)
1886 {
1887         char *ret = workspace;
1888         int lr; /* length of the input string after the copy */
1889
1890         ast_copy_string(workspace, value, workspace_len); /* always make a copy */
1891
1892         lr = strlen(ret); /* compute length after copy, so we never go out of the workspace */
1893
1894         /* Quick check if no need to do anything */
1895         if (offset == 0 && length >= lr)        /* take the whole string */
1896                 return ret;
1897
1898         if (offset < 0) {       /* translate negative offset into positive ones */
1899                 offset = lr + offset;
1900                 if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */
1901                         offset = 0;
1902         }
1903
1904         /* too large offset result in empty string so we know what to return */
1905         if (offset >= lr)
1906                 return ret + lr;        /* the final '\0' */
1907
1908         ret += offset;          /* move to the start position */
1909         if (length >= 0 && length < lr - offset)        /* truncate if necessary */
1910                 ret[length] = '\0';
1911         else if (length < 0) {
1912                 if (lr > offset - length) /* After we remove from the front and from the rear, is there anything left? */
1913                         ret[lr + length - offset] = '\0';
1914                 else
1915                         ret[0] = '\0';
1916         }
1917
1918         return ret;
1919 }
1920
1921 /*! \brief  Support for Asterisk built-in variables in the dialplan
1922
1923 \note   See also
1924         - \ref AstVar   Channel variables
1925         - \ref AstCauses The HANGUPCAUSE variable
1926  */
1927 void pbx_retrieve_variable(struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp)
1928 {
1929         const char not_found = '\0';
1930         char *tmpvar;
1931         const char *s;  /* the result */
1932         int offset, length;
1933         int i, need_substring;
1934         struct varshead *places[2] = { headp, &globals };       /* list of places where we may look */
1935
1936         if (c) {
1937                 ast_channel_lock(c);
1938                 places[0] = &c->varshead;
1939         }
1940         /*
1941          * Make a copy of var because parse_variable_name() modifies the string.
1942          * Then if called directly, we might need to run substring() on the result;
1943          * remember this for later in 'need_substring', 'offset' and 'length'
1944          */
1945         tmpvar = ast_strdupa(var);      /* parse_variable_name modifies the string */
1946         need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */);
1947
1948         /*
1949          * Look first into predefined variables, then into variable lists.
1950          * Variable 's' points to the result, according to the following rules:
1951          * s == &not_found (set at the beginning) means that we did not find a
1952          *      matching variable and need to look into more places.
1953          * If s != &not_found, s is a valid result string as follows:
1954          * s = NULL if the variable does not have a value;
1955          *      you typically do this when looking for an unset predefined variable.
1956          * s = workspace if the result has been assembled there;
1957          *      typically done when the result is built e.g. with an snprintf(),
1958          *      so we don't need to do an additional copy.
1959          * s != workspace in case we have a string, that needs to be copied
1960          *      (the ast_copy_string is done once for all at the end).
1961          *      Typically done when the result is already available in some string.
1962          */
1963         s = &not_found; /* default value */
1964         if (c) {        /* This group requires a valid channel */
1965                 /* Names with common parts are looked up a piece at a time using strncmp. */
1966                 if (!strncmp(var, "CALL", 4)) {
1967                         if (!strncmp(var + 4, "ING", 3)) {
1968                                 if (!strcmp(var + 7, "PRES")) {                 /* CALLINGPRES */
1969                                         snprintf(workspace, workspacelen, "%d", c->cid.cid_pres);
1970                                         s = workspace;
1971                                 } else if (!strcmp(var + 7, "ANI2")) {          /* CALLINGANI2 */
1972                                         snprintf(workspace, workspacelen, "%d", c->cid.cid_ani2);
1973                                         s = workspace;
1974                                 } else if (!strcmp(var + 7, "TON")) {           /* CALLINGTON */
1975                                         snprintf(workspace, workspacelen, "%d", c->cid.cid_ton);
1976                                         s = workspace;
1977                                 } else if (!strcmp(var + 7, "TNS")) {           /* CALLINGTNS */
1978                                         snprintf(workspace, workspacelen, "%d", c->cid.cid_tns);
1979                                         s = workspace;
1980                                 }
1981                         }
1982                 } else if (!strcmp(var, "HINT")) {
1983                         s = ast_get_hint(workspace, workspacelen, NULL, 0, c, c->context, c->exten) ? workspace : NULL;
1984                 } else if (!strcmp(var, "HINTNAME")) {
1985                         s = ast_get_hint(NULL, 0, workspace, workspacelen, c, c->context, c->exten) ? workspace : NULL;
1986                 } else if (!strcmp(var, "EXTEN")) {
1987                         s = c->exten;
1988                 } else if (!strcmp(var, "CONTEXT")) {
1989                         s = c->context;
1990                 } else if (!strcmp(var, "PRIORITY")) {
1991                         snprintf(workspace, workspacelen, "%d", c->priority);
1992                         s = workspace;
1993                 } else if (!strcmp(var, "CHANNEL")) {
1994                         s = c->name;
1995                 } else if (!strcmp(var, "UNIQUEID")) {
1996                         s = c->uniqueid;
1997                 } else if (!strcmp(var, "HANGUPCAUSE")) {
1998                         snprintf(workspace, workspacelen, "%d", c->hangupcause);
1999                         s = workspace;
2000                 }
2001         }
2002         if (s == &not_found) { /* look for more */
2003                 if (!strcmp(var, "EPOCH")) {
2004                         snprintf(workspace, workspacelen, "%u",(int)time(NULL));
2005                         s = workspace;
2006                 } else if (!strcmp(var, "SYSTEMNAME")) {
2007                         s = ast_config_AST_SYSTEM_NAME;
2008                 }
2009         }
2010         /* if not found, look into chanvars or global vars */
2011         for (i = 0; s == &not_found && i < (sizeof(places) / sizeof(places[0])); i++) {
2012                 struct ast_var_t *variables;
2013                 if (!places[i])
2014                         continue;
2015                 if (places[i] == &globals)
2016                         ast_rwlock_rdlock(&globalslock);
2017                 AST_LIST_TRAVERSE(places[i], variables, entries) {
2018                         if (strcasecmp(ast_var_name(variables), var)==0) {
2019                                 s = ast_var_value(variables);
2020                                 break;
2021                         }
2022                 }
2023                 if (places[i] == &globals)
2024                         ast_rwlock_unlock(&globalslock);
2025         }
2026         if (s == &not_found || s == NULL)
2027                 *ret = NULL;
2028         else {
2029                 if (s != workspace)
2030                         ast_copy_string(workspace, s, workspacelen);
2031                 *ret = workspace;
2032                 if (need_substring)
2033                         *ret = substring(*ret, offset, length, workspace, workspacelen);
2034         }
2035
2036         if (c)
2037                 ast_channel_unlock(c);
2038 }
2039
2040 static void exception_store_free(void *data)
2041 {
2042         struct pbx_exception *exception = data;
2043         ast_string_field_free_memory(exception);
2044         ast_free(exception);
2045 }
2046
2047 static struct ast_datastore_info exception_store_info = {
2048         .type = "EXCEPTION",
2049         .destroy = exception_store_free,
2050 };
2051
2052 int pbx_builtin_raise_exception(struct ast_channel *chan, void *vreason)
2053 {
2054         const char *reason = vreason;
2055         struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL);
2056         struct pbx_exception *exception = NULL;
2057
2058         if (!ds) {
2059                 ds = ast_channel_datastore_alloc(&exception_store_info, NULL);
2060                 if (!ds)
2061                         return -1;
2062                 exception = ast_calloc(1, sizeof(struct pbx_exception));
2063                 if (!exception) {
2064                         ast_channel_datastore_free(ds);
2065                         return -1;
2066                 }
2067                 if (ast_string_field_init(exception, 128)) {
2068                         ast_free(exception);
2069                         ast_channel_datastore_free(ds);
2070                         return -1;
2071                 }
2072                 ds->data = exception;
2073                 ast_channel_datastore_add(chan, ds);
2074         } else
2075                 exception = ds->data;
2076
2077         ast_string_field_set(exception, reason, reason);
2078         ast_string_field_set(exception, context, chan->context);
2079         ast_string_field_set(exception, exten, chan->exten);
2080         exception->priority = chan->priority;
2081         set_ext_pri(chan, "e", 0);
2082         return 0;
2083 }
2084
2085 static int acf_exception_read(struct ast_channel *chan, const char *name, char *data, char *buf, size_t buflen)
2086 {
2087         struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL);
2088         struct pbx_exception *exception = NULL;
2089         if (!ds || !ds->data)
2090                 return -1;
2091         exception = ds->data;
2092         if (!strcasecmp(data, "REASON"))
2093                 ast_copy_string(buf, exception->reason, buflen);
2094         else if (!strcasecmp(data, "CONTEXT"))
2095                 ast_copy_string(buf, exception->context, buflen);
2096         else if (!strncasecmp(data, "EXTEN", 5))
2097                 ast_copy_string(buf, exception->exten, buflen);
2098         else if (!strcasecmp(data, "PRIORITY"))
2099                 snprintf(buf, buflen, "%d", exception->priority);
2100         else
2101                 return -1;
2102         return 0;
2103 }
2104
2105 static struct ast_custom_function exception_function = {
2106         .name = "EXCEPTION",
2107         .synopsis = "Retrieve the details of the current dialplan exception",
2108         .desc =
2109 "The following fields are available for retrieval:\n"
2110 "  reason    INVALID, ERROR, RESPONSETIMEOUT, ABSOLUTETIMEOUT, or custom\n"
2111 "               value set by the RaiseException() application\n"
2112 "  context   The context executing when the exception occurred\n"
2113 "  exten     The extension executing when the exception occurred\n"
2114 "  priority  The numeric priority executing when the exception occurred\n",
2115         .syntax = "EXCEPTION(<field>)",
2116         .read = acf_exception_read,
2117 };
2118
2119 static char *handle_show_functions(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2120 {
2121         struct ast_custom_function *acf;
2122         int count_acf = 0;
2123         int like = 0;
2124
2125         switch (cmd) {
2126         case CLI_INIT:
2127                 e->command = "core show functions [like]";
2128                 e->usage = 
2129                         "Usage: core show functions [like <text>]\n"
2130                         "       List builtin functions, optionally only those matching a given string\n";
2131                 return NULL;
2132         case CLI_GENERATE:
2133                 return NULL;
2134         }
2135
2136         if (a->argc == 5 && (!strcmp(a->argv[3], "like")) ) {
2137                 like = 1;
2138         } else if (a->argc != 3) {
2139                 return CLI_SHOWUSAGE;
2140         }
2141
2142         ast_cli(a->fd, "%s Custom Functions:\n--------------------------------------------------------------------------------\n", like ? "Matching" : "Installed");
2143
2144         AST_RWLIST_RDLOCK(&acf_root);
2145         AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) {
2146                 if (!like || strstr(acf->name, a->argv[4])) {
2147                         count_acf++;
2148                         ast_cli(a->fd, "%-20.20s  %-35.35s  %s\n", acf->name, acf->syntax, acf->synopsis);
2149                 }
2150         }
2151         AST_RWLIST_UNLOCK(&acf_root);
2152
2153         ast_cli(a->fd, "%d %scustom functions installed.\n", count_acf, like ? "matching " : "");
2154
2155         return CLI_SUCCESS;
2156 }
2157
2158 static char *handle_show_function(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2159 {
2160         struct ast_custom_function *acf;
2161         /* Maximum number of characters added by terminal coloring is 22 */
2162         char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40];
2163         char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL;
2164         char stxtitle[40], *syntax = NULL;
2165         int synopsis_size, description_size, syntax_size;
2166         char *ret = NULL;
2167         int which = 0;
2168         int wordlen;
2169
2170         switch (cmd) {
2171         case CLI_INIT:
2172                 e->command = "core show function";
2173                 e->usage = 
2174                         "Usage: core show function <function>\n"
2175                         "       Describe a particular dialplan function.\n";
2176                 return NULL;
2177         case CLI_GENERATE:      
2178                 wordlen = strlen(a->word);
2179                 /* case-insensitive for convenience in this 'complete' function */
2180                 AST_RWLIST_RDLOCK(&acf_root);
2181                 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) {
2182                         if (!strncasecmp(a->word, acf->name, wordlen) && ++which > a->n) {
2183                                 ret = ast_strdup(acf->name);
2184                                 break;
2185                         }
2186                 }
2187                 AST_RWLIST_UNLOCK(&acf_root);
2188
2189                 return ret;
2190         }
2191
2192         if (a->argc < 4)
2193                 return CLI_SHOWUSAGE;
2194
2195         if (!(acf = ast_custom_function_find(a->argv[3]))) {
2196                 ast_cli(a->fd, "No function by that name registered.\n");
2197                 return CLI_FAILURE;
2198
2199         }
2200
2201         if (acf->synopsis)
2202                 synopsis_size = strlen(acf->synopsis) + 23;
2203         else
2204                 synopsis_size = strlen("Not available") + 23;
2205         synopsis = alloca(synopsis_size);
2206
2207         if (acf->desc)
2208                 description_size = strlen(acf->desc) + 23;
2209         else
2210                 description_size = strlen("Not available") + 23;
2211         description = alloca(description_size);
2212
2213         if (acf->syntax)
2214                 syntax_size = strlen(acf->syntax) + 23;
2215         else
2216                 syntax_size = strlen("Not available") + 23;
2217         syntax = alloca(syntax_size);
2218
2219         snprintf(info, 64 + AST_MAX_APP, "\n  -= Info about function '%s' =- \n\n", acf->name);
2220         term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22);
2221         term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40);
2222         term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
2223         term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
2224         term_color(syntax,
2225                    acf->syntax ? acf->syntax : "Not available",
2226                    COLOR_CYAN, 0, syntax_size);
2227         term_color(synopsis,
2228                    acf->synopsis ? acf->synopsis : "Not available",
2229                    COLOR_CYAN, 0, synopsis_size);
2230         term_color(description,
2231                    acf->desc ? acf->desc : "Not available",
2232                    COLOR_CYAN, 0, description_size);
2233
2234         ast_cli(a->fd,"%s%s%s\n\n%s%s\n\n%s%s\n", infotitle, stxtitle, syntax, syntitle, synopsis, destitle, description);
2235
2236         return CLI_SUCCESS;
2237 }
2238
2239 struct ast_custom_function *ast_custom_function_find(const char *name)
2240 {
2241         struct ast_custom_function *acf = NULL;
2242
2243         AST_RWLIST_RDLOCK(&acf_root);
2244         AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) {
2245                 if (!strcmp(name, acf->name))
2246                         break;
2247         }
2248         AST_RWLIST_UNLOCK(&acf_root);
2249
2250         return acf;
2251 }
2252
2253 int ast_custom_function_unregister(struct ast_custom_function *acf)
2254 {
2255         struct ast_custom_function *cur;
2256
2257         if (!acf)
2258                 return -1;
2259
2260         AST_RWLIST_WRLOCK(&acf_root);
2261         if ((cur = AST_RWLIST_REMOVE(&acf_root, acf, acflist)))
2262                 ast_verb(2, "Unregistered custom function %s\n", cur->name);
2263         AST_RWLIST_UNLOCK(&acf_root);
2264
2265         return cur ? 0 : -1;
2266 }
2267
2268 int __ast_custom_function_register(struct ast_custom_function *acf, struct ast_module *mod)
2269 {
2270         struct ast_custom_function *cur;
2271         char tmps[80];
2272
2273         if (!acf)
2274                 return -1;
2275
2276         acf->mod = mod;
2277
2278         AST_RWLIST_WRLOCK(&acf_root);
2279
2280         AST_RWLIST_TRAVERSE(&acf_root, cur, acflist) {
2281                 if (!strcmp(acf->name, cur->name)) {
2282                         ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name);
2283                         AST_RWLIST_UNLOCK(&acf_root);
2284                         return -1;
2285                 }
2286         }
2287
2288         /* Store in alphabetical order */
2289         AST_RWLIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) {
2290                 if (strcasecmp(acf->name, cur->name) < 0) {
2291                         AST_RWLIST_INSERT_BEFORE_CURRENT(acf, acflist);
2292                         break;
2293                 }
2294         }
2295         AST_RWLIST_TRAVERSE_SAFE_END;
2296         if (!cur)
2297                 AST_RWLIST_INSERT_TAIL(&acf_root, acf, acflist);
2298
2299         AST_RWLIST_UNLOCK(&acf_root);
2300
2301         ast_verb(2, "Registered custom function '%s'\n", term_color(tmps, acf->name, COLOR_BRCYAN, 0, sizeof(tmps)));
2302
2303         return 0;
2304 }
2305
2306 /*! \brief return a pointer to the arguments of the function,
2307  * and terminates the function name with '\\0'
2308  */
2309 static char *func_args(char *function)
2310 {
2311         char *args = strchr(function, '(');
2312
2313         if (!args)
2314                 ast_log(LOG_WARNING, "Function doesn't contain parentheses.  Assuming null argument.\n");
2315         else {
2316                 char *p;
2317                 *args++ = '\0';
2318                 if ((p = strrchr(args, ')')) )
2319                         *p = '\0';
2320                 else
2321                         ast_log(LOG_WARNING, "Can't find trailing parenthesis?\n");
2322         }
2323         return args;
2324 }
2325
2326 int ast_func_read(struct ast_channel *chan, const char *function, char *workspace, size_t len)
2327 {
2328         char *copy = ast_strdupa(function);
2329         char *args = func_args(copy);
2330         struct ast_custom_function *acfptr = ast_custom_function_find(copy);
2331
2332         if (acfptr == NULL)
2333                 ast_log(LOG_ERROR, "Function %s not registered\n", copy);
2334         else if (!acfptr->read)
2335                 ast_log(LOG_ERROR, "Function %s cannot be read\n", copy);
2336         else {
2337                 int res;
2338                 struct ast_module_user *u = NULL;
2339                 if (acfptr->mod)
2340                         u = __ast_module_user_add(acfptr->mod, chan);
2341                 res = acfptr->read(chan, copy, args, workspace, len);
2342                 if (acfptr->mod && u)
2343                         __ast_module_user_remove(acfptr->mod, u);
2344                 return res;
2345         }
2346         return -1;
2347 }
2348
2349 int ast_func_write(struct ast_channel *chan, const char *function, const char *value)
2350 {
2351         char *copy = ast_strdupa(function);
2352         char *args = func_args(copy);
2353         struct ast_custom_function *acfptr = ast_custom_function_find(copy);
2354
2355         if (acfptr == NULL)
2356                 ast_log(LOG_ERROR, "Function %s not registered\n", copy);
2357         else if (!acfptr->write)
2358                 ast_log(LOG_ERROR, "Function %s cannot be written to\n", copy);
2359         else {
2360                 int res;
2361                 struct ast_module_user *u = NULL;
2362                 if (acfptr->mod)
2363                         u = __ast_module_user_add(acfptr->mod, chan);
2364                 res = acfptr->write(chan, copy, args, value);
2365                 if (acfptr->mod && u)
2366                         __ast_module_user_remove(acfptr->mod, u);
2367                 return res;
2368         }
2369
2370         return -1;
2371 }
2372
2373 static void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count)
2374 {
2375         /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!!  */
2376         char *cp4;
2377         const char *tmp, *whereweare;
2378         int length, offset, offset2, isfunction;
2379         char *workspace = NULL;
2380         char *ltmp = NULL, *var = NULL;
2381         char *nextvar, *nextexp, *nextthing;
2382         char *vars, *vare;
2383         int pos, brackets, needsub, len;
2384         
2385         *cp2 = 0; /* just in case nothing ends up there */
2386         whereweare=tmp=cp1;
2387         while (!ast_strlen_zero(whereweare) && count) {
2388                 /* Assume we're copying the whole remaining string */
2389                 pos = strlen(whereweare);
2390                 nextvar = NULL;
2391                 nextexp = NULL;
2392                 nextthing = strchr(whereweare, '$');
2393                 if (nextthing) {
2394                         switch (nextthing[1]) {
2395                         case '{':
2396                                 nextvar = nextthing;
2397                                 pos = nextvar - whereweare;
2398                                 break;
2399                         case '[':
2400                                 nextexp = nextthing;
2401                                 pos = nextexp - whereweare;
2402                                 break;
2403                         default:
2404                                 pos = 1;
2405                         }
2406                 }
2407
2408                 if (pos) {
2409                         /* Can't copy more than 'count' bytes */
2410                         if (pos > count)
2411                                 pos = count;
2412
2413                         /* Copy that many bytes */
2414                         memcpy(cp2, whereweare, pos);
2415
2416                         count -= pos;
2417                         cp2 += pos;
2418                         whereweare += pos;
2419                         *cp2 = 0;
2420                 }
2421
2422                 if (nextvar) {
2423                         /* We have a variable.  Find the start and end, and determine
2424                            if we are going to have to recursively call ourselves on the
2425                            contents */
2426                         vars = vare = nextvar + 2;
2427                         brackets = 1;
2428                         needsub = 0;
2429
2430                         /* Find the end of it */
2431                         while (brackets && *vare) {
2432                                 if ((vare[0] == '$') && (vare[1] == '{')) {
2433                                         needsub++;
2434                                 } else if (vare[0] == '{') {
2435                                         brackets++;
2436                                 } else if (vare[0] == '}') {
2437                                         brackets--;
2438                                 } else if ((vare[0] == '$') && (vare[1] == '['))
2439                                         needsub++;
2440                                 vare++;
2441                         }
2442                         if (brackets)
2443                                 ast_log(LOG_NOTICE, "Error in extension logic (missing '}')\n");
2444                         len = vare - vars - 1;
2445
2446                         /* Skip totally over variable string */
2447                         whereweare += (len + 3);
2448
2449                         if (!var)
2450                                 var = alloca(VAR_BUF_SIZE);
2451
2452                         /* Store variable name (and truncate) */
2453                         ast_copy_string(var, vars, len + 1);
2454
2455                         /* Substitute if necessary */
2456                         if (needsub) {
2457                                 if (!ltmp)
2458                                         ltmp = alloca(VAR_BUF_SIZE);
2459
2460                                 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1);
2461                                 vars = ltmp;
2462                         } else {
2463                                 vars = var;
2464                         }
2465
2466                         if (!workspace)
2467                                 workspace = alloca(VAR_BUF_SIZE);
2468
2469                         workspace[0] = '\0';
2470
2471                         parse_variable_name(vars, &offset, &offset2, &isfunction);
2472                         if (isfunction) {
2473                                 /* Evaluate function */
2474                                 if (c || !headp)
2475                                         cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
2476                                 else {
2477                                         struct varshead old;
2478                                         struct ast_channel *c = ast_channel_alloc(0, 0, "", "", "", "", "", 0, "Bogus/%p", vars);
2479                                         if (c) {
2480                                                 memcpy(&old, &c->varshead, sizeof(old));
2481                                                 memcpy(&c->varshead, headp, sizeof(c->varshead));
2482                                                 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
2483                                                 /* Don't deallocate the varshead that was passed in */
2484                                                 memcpy(&c->varshead, &old, sizeof(c->varshead));
2485                                                 ast_channel_free(c);
2486                                         } else
2487                                                 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution.  Function results may be blank.\n");
2488                                 }
2489                                 ast_debug(1, "Function result is '%s'\n", cp4 ? cp4 : "(null)");
2490                         } else {
2491                                 /* Retrieve variable value */
2492                                 pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp);
2493                         }
2494                         if (cp4) {
2495                                 cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE);
2496
2497                                 length = strlen(cp4);
2498                                 if (length > count)
2499                                         length = count;
2500                                 memcpy(cp2, cp4, length);
2501                                 count -= length;
2502                                 cp2 += length;
2503                                 *cp2 = 0;
2504                         }
2505                 } else if (nextexp) {
2506                         /* We have an expression.  Find the start and end, and determine
2507                            if we are going to have to recursively call ourselves on the
2508                            contents */
2509                         vars = vare = nextexp + 2;
2510                         brackets = 1;
2511                         needsub = 0;
2512
2513                         /* Find the end of it */
2514                         while (brackets && *vare) {
2515                                 if ((vare[0] == '$') && (vare[1] == '[')) {
2516                                         needsub++;
2517                                         brackets++;
2518                                         vare++;
2519                                 } else if (vare[0] == '[') {
2520                                         brackets++;
2521                                 } else if (vare[0] == ']') {
2522                                         brackets--;
2523                                 } else if ((vare[0] == '$') && (vare[1] == '{')) {
2524                                         needsub++;
2525                                         vare++;
2526                                 }
2527                                 vare++;
2528                         }
2529                         if (brackets)
2530                                 ast_log(LOG_NOTICE, "Error in extension logic (missing ']')\n");
2531                         len = vare - vars - 1;
2532
2533                         /* Skip totally over expression */
2534                         whereweare += (len + 3);
2535
2536                         if (!var)
2537                                 var = alloca(VAR_BUF_SIZE);
2538
2539                         /* Store variable name (and truncate) */
2540                         ast_copy_string(var, vars, len + 1);
2541
2542                         /* Substitute if necessary */
2543                         if (needsub) {
2544                                 if (!ltmp)
2545                                         ltmp = alloca(VAR_BUF_SIZE);
2546
2547                                 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1);
2548                                 vars = ltmp;
2549                         } else {
2550                                 vars = var;
2551                         }
2552
2553                         length = ast_expr(vars, cp2, count, c);
2554
2555                         if (length) {
2556                                 ast_debug(1, "Expression result is '%s'\n", cp2);
2557                                 count -= length;
2558                                 cp2 += length;
2559                                 *cp2 = 0;
2560                         }
2561                 }
2562         }
2563 }
2564
2565 void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count)
2566 {
2567         pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count);
2568 }
2569
2570 void pbx_substitute_variables_varshead(struct varshead *headp, const char *cp1, char *cp2, int count)
2571 {
2572         pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count);
2573 }
2574
2575 static void pbx_substitute_variables(char *passdata, int datalen, struct ast_channel *c, struct ast_exten *e)
2576 {
2577         const char *tmp;
2578
2579         /* Nothing more to do */
2580         if (!e->data)
2581                 return;
2582
2583         /* No variables or expressions in e->data, so why scan it? */
2584         if ((!(tmp = strchr(e->data, '$'))) || (!strstr(tmp, "${") && !strstr(tmp, "$["))) {
2585                 ast_copy_string(passdata, e->data, datalen);
2586                 return;
2587         }
2588
2589         pbx_substitute_variables_helper(c, e->data, passdata, datalen - 1);
2590 }
2591
2592 /*! 
2593  * \brief The return value depends on the action:
2594  *
2595  * E_MATCH, E_CANMATCH, E_MATCHMORE require a real match,
2596  *      and return 0 on failure, -1 on match;
2597  * E_FINDLABEL maps the label to a priority, and returns
2598  *      the priority on success, ... XXX
2599  * E_SPAWN, spawn an application,
2600  *      
2601  * \retval 0 on success.
2602  * \retval  -1 on failure.
2603  *
2604  * \note The channel is auto-serviced in this function, because doing an extension
2605  * match may block for a long time.  For example, if the lookup has to use a network
2606  * dialplan switch, such as DUNDi or IAX2, it may take a while.  However, the channel
2607  * auto-service code will queue up any important signalling frames to be processed
2608  * after this is done.
2609  */
2610 static int pbx_extension_helper(struct ast_channel *c, struct ast_context *con,
2611   const char *context, const char *exten, int priority,
2612   const char *label, const char *callerid, enum ext_match_t action, int *found, int combined_find_spawn)
2613 {
2614         struct ast_exten *e;
2615         struct ast_app *app;
2616         int res;
2617         struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */
2618         char passdata[EXT_DATA_SIZE];
2619
2620         int matching_action = (action == E_MATCH || action == E_CANMATCH || action == E_MATCHMORE);
2621
2622         ast_rdlock_contexts();
2623         if (found)
2624                 *found = 0;
2625
2626         e = pbx_find_extension(c, con, &q, context, exten, priority, label, callerid, action);
2627         if (e) {
2628                 if (found)
2629                         *found = 1;
2630                 if (matching_action) {
2631                         ast_unlock_contexts();
2632                         return -1;      /* success, we found it */
2633                 } else if (action == E_FINDLABEL) { /* map the label to a priority */
2634                         res = e->priority;
2635                         ast_unlock_contexts();
2636                         return res;     /* the priority we were looking for */
2637                 } else {        /* spawn */
2638                         if (!e->cached_app)
2639                                 e->cached_app = pbx_findapp(e->app);
2640                         app = e->cached_app;
2641                         ast_unlock_contexts();
2642                         if (!app) {
2643                                 ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority);
2644                                 return -1;
2645                         }
2646                         if (c->context != context)
2647                                 ast_copy_string(c->context, context, sizeof(c->context));
2648                         if (c->exten != exten)
2649                                 ast_copy_string(c->exten, exten, sizeof(c->exten));
2650                         c->priority = priority;
2651                         pbx_substitute_variables(passdata, sizeof(passdata), c, e);
2652                         ast_debug(1, "Launching '%s'\n", app->name);
2653                         if (VERBOSITY_ATLEAST(3)) {
2654                                 char tmp[80], tmp2[80], tmp3[EXT_DATA_SIZE];
2655                                 ast_verb(3, "Executing [%s@%s:%d] %s(\"%s\", \"%s\") %s\n",
2656                                         exten, context, priority,
2657                                         term_color(tmp, app->name, COLOR_BRCYAN, 0, sizeof(tmp)),
2658                                         term_color(tmp2, c->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)),
2659                                         term_color(tmp3, passdata, COLOR_BRMAGENTA, 0, sizeof(tmp3)),
2660                                         "in new stack");
2661                         }
2662                         manager_event(EVENT_FLAG_DIALPLAN, "Newexten",
2663                                         "Channel: %s\r\n"
2664                                         "Context: %s\r\n"
2665                                         "Extension: %s\r\n"
2666                                         "Priority: %d\r\n"
2667                                         "Application: %s\r\n"
2668                                         "AppData: %s\r\n"
2669                                         "Uniqueid: %s\r\n",
2670                                         c->name, c->context, c->exten, c->priority, app->name, passdata, c->uniqueid);
2671                         return pbx_exec(c, app, passdata);      /* 0 on success, -1 on failure */
2672                 }
2673         } else if (q.swo) {     /* not found here, but in another switch */
2674                 ast_unlock_contexts();
2675                 if (matching_action) {
2676                         return -1;
2677                 } else {
2678                         if (!q.swo->exec) {
2679                                 ast_log(LOG_WARNING, "No execution engine for switch %s\n", q.swo->name);
2680                                 res = -1;
2681                         }
2682                         return q.swo->exec(c, q.foundcontext ? q.foundcontext : context, exten, priority, callerid, q.data);
2683                 }
2684         } else {        /* not found anywhere, see what happened */
2685                 ast_unlock_contexts();
2686                 switch (q.status) {
2687                 case STATUS_NO_CONTEXT:
2688                         if (!matching_action && !combined_find_spawn)
2689                                 ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", context);
2690                         break;
2691                 case STATUS_NO_EXTENSION:
2692                         if (!matching_action && !combined_find_spawn)
2693                                 ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, context);
2694                         break;
2695                 case STATUS_NO_PRIORITY:
2696                         if (!matching_action && !combined_find_spawn)
2697                                 ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, context);
2698                         break;
2699                 case STATUS_NO_LABEL:
2700                         if (context && !combined_find_spawn)
2701                                 ast_log(LOG_NOTICE, "No such label '%s' in extension '%s' in context '%s'\n", label, exten, context);
2702                         break;
2703                 default:
2704                         ast_debug(1, "Shouldn't happen!\n");
2705                 }
2706
2707                 return (matching_action) ? 0 : -1;
2708         }
2709 }
2710
2711 /*! \brief Find hint for given extension in context */
2712 static struct ast_exten *ast_hint_extension(struct ast_channel *c, const char *context, const char *exten)
2713 {
2714         struct ast_exten *e;
2715         struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */
2716
2717         ast_rdlock_contexts();
2718         e = pbx_find_extension(c, NULL, &q, context, exten, PRIORITY_HINT, NULL, "", E_MATCH);
2719         ast_unlock_contexts();
2720
2721         return e;
2722 }
2723
2724 /*! \brief Check state of extension by using hints */
2725 static int ast_extension_state2(struct ast_exten *e)
2726 {
2727         char hint[AST_MAX_EXTENSION];
2728         char *cur, *rest;
2729         int allunavailable = 1, allbusy = 1, allfree = 1, allonhold = 1;
2730         int busy = 0, inuse = 0, ring = 0;
2731
2732         if (!e)
2733                 return -1;
2734
2735         ast_copy_string(hint, ast_get_extension_app(e), sizeof(hint));
2736
2737         rest = hint;    /* One or more devices separated with a & character */
2738         while ( (cur = strsep(&rest, "&")) ) {
2739                 int res = ast_device_state(cur);
2740                 switch (res) {
2741                 case AST_DEVICE_NOT_INUSE:
2742                         allunavailable = 0;
2743                         allbusy = 0;
2744                         allonhold = 0;
2745                         break;
2746                 case AST_DEVICE_INUSE:
2747                         inuse = 1;
2748                         allunavailable = 0;
2749                         allfree = 0;
2750                         allonhold = 0;
2751                         break;
2752                 case AST_DEVICE_RINGING:
2753                         ring = 1;
2754                         allunavailable = 0;
2755                         allfree = 0;
2756                         allonhold = 0;
2757                         break;
2758                 case AST_DEVICE_RINGINUSE:
2759                         inuse = 1;
2760                         ring = 1;
2761                         allunavailable = 0;
2762                         allfree = 0;
2763                         allonhold = 0;
2764                         break;
2765                 case AST_DEVICE_ONHOLD:
2766                         allunavailable = 0;
2767                         allfree = 0;
2768                         break;
2769                 case AST_DEVICE_BUSY:
2770                         allunavailable = 0;
2771                         allfree = 0;
2772                         allonhold = 0;
2773                         busy = 1;
2774                         break;
2775                 case AST_DEVICE_UNAVAILABLE:
2776                 case AST_DEVICE_INVALID:
2777                         allbusy = 0;
2778                         allfree = 0;
2779                         allonhold = 0;
2780                         break;
2781                 default:
2782                         allunavailable = 0;
2783                         allbusy = 0;
2784                         allfree = 0;
2785                         allonhold = 0;
2786                 }
2787         }
2788
2789         if (!inuse && ring)
2790                 return AST_EXTENSION_RINGING;
2791         if (inuse && ring)
2792                 return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING);
2793         if (inuse)
2794                 return AST_EXTENSION_INUSE;
2795         if (allfree)
2796                 return AST_EXTENSION_NOT_INUSE;
2797         if (allonhold)
2798                 return AST_EXTENSION_ONHOLD;
2799         if (allbusy)
2800                 return AST_EXTENSION_BUSY;
2801         if (allunavailable)
2802                 return AST_EXTENSION_UNAVAILABLE;
2803         if (busy)
2804                 return AST_EXTENSION_INUSE;
2805
2806         return AST_EXTENSION_NOT_INUSE;
2807 }
2808
2809 /*! \brief Return extension_state as string */
2810 const char *ast_extension_state2str(int extension_state)
2811 {
2812         int i;
2813
2814         for (i = 0; (i < (sizeof(extension_states) / sizeof(extension_states[0]))); i++) {
2815                 if (extension_states[i].extension_state == extension_state)
2816                         return extension_states[i].text;
2817         }
2818         return "Unknown";
2819 }
2820
2821 /*! \brief Check extension state for an extension by using hint */
2822 int ast_extension_state(struct ast_channel *c, const char *context, const char *exten)
2823 {
2824         struct ast_exten *e;
2825
2826         e = ast_hint_extension(c, context, exten);      /* Do we have a hint for this extension ? */
2827         if (!e)
2828                 return -1;                              /* No hint, return -1 */
2829
2830         return ast_extension_state2(e);                 /* Check all devices in the hint */
2831 }
2832
2833 static void handle_statechange(const char *device)
2834 {
2835         struct ast_hint *hint;
2836
2837         AST_RWLIST_RDLOCK(&hints);
2838
2839         AST_RWLIST_TRAVERSE(&hints, hint, list) {
2840                 struct ast_state_cb *cblist;
2841                 char buf[AST_MAX_EXTENSION];
2842                 char *parse = buf;
2843                 char *cur;
2844                 int state;
2845
2846                 ast_copy_string(buf, ast_get_extension_app(hint->exten), sizeof(buf));
2847                 while ( (cur = strsep(&parse, "&")) ) {
2848                         if (!strcasecmp(cur, device))
2849                                 break;
2850                 }
2851                 if (!cur)
2852                         continue;
2853
2854                 /* Get device state for this hint */
2855                 state = ast_extension_state2(hint->exten);
2856
2857                 if ((state == -1) || (state == hint->laststate))
2858                         continue;
2859
2860                 /* Device state changed since last check - notify the watchers */
2861
2862                 /* For general callbacks */
2863                 for (cblist = statecbs; cblist; cblist = cblist->next)
2864                         cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data);
2865
2866                 /* For extension callbacks */
2867                 for (cblist = hint->callbacks; cblist; cblist = cblist->next)
2868                         cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data);
2869
2870                 hint->laststate = state;        /* record we saw the change */
2871         }
2872
2873         AST_RWLIST_UNLOCK(&hints);
2874 }
2875
2876 static int statechange_queue(const char *dev)
2877 {
2878         struct statechange *sc;
2879
2880         if (!(sc = ast_calloc(1, sizeof(*sc) + strlen(dev) + 1)))
2881                 return 0;
2882
2883         strcpy(sc->dev, dev);
2884
2885         ast_mutex_lock(&device_state.lock);
2886         AST_LIST_INSERT_TAIL(&device_state.state_change_q, sc, entry);
2887         ast_cond_signal(&device_state.cond);
2888         ast_mutex_unlock(&device_state.lock);
2889
2890         return 0;
2891 }
2892
2893 static void *device_state_thread(void *data)
2894 {
2895         struct statechange *sc;
2896
2897         while (!device_state.stop) {
2898                 ast_mutex_lock(&device_state.lock);
2899                 while (!(sc = AST_LIST_REMOVE_HEAD(&device_state.state_change_q, entry))) {
2900                         ast_cond_wait(&device_state.cond, &device_state.lock);
2901                         /* Check to see if we were woken up to see the request to stop */
2902                         if (device_state.stop) {
2903                                 ast_mutex_unlock(&device_state.lock);
2904                                 return NULL;
2905                         }
2906                 }
2907                 ast_mutex_unlock(&device_state.lock);
2908
2909                 handle_statechange(sc->dev);
2910
2911                 ast_free(sc);
2912         }
2913
2914         return NULL;
2915 }
2916
2917 /*! \brief  Add watcher for extension states */
2918 int ast_extension_state_add(const char *context, const char *exten,
2919                             ast_state_cb_type callback, void *data)
2920 {
2921         struct ast_hint *hint;
2922         struct ast_state_cb *cblist;
2923         struct ast_exten *e;
2924
2925         /* If there's no context and extension:  add callback to statecbs list */
2926         if (!context && !exten) {
2927                 AST_RWLIST_WRLOCK(&hints);
2928
2929                 for (cblist = statecbs; cblist; cblist = cblist->next) {
2930                         if (cblist->callback == callback) {
2931                                 cblist->data = data;
2932                                 AST_RWLIST_UNLOCK(&hints);
2933                                 return 0;
2934                         }
2935                 }
2936
2937                 /* Now insert the callback */
2938                 if (!(cblist = ast_calloc(1, sizeof(*cblist)))) {
2939                         AST_RWLIST_UNLOCK(&hints);
2940                         return -1;
2941                 }
2942                 cblist->id = 0;
2943                 cblist->callback = callback;
2944                 cblist->data = data;
2945
2946                 cblist->next = statecbs;
2947                 statecbs = cblist;
2948
2949                 AST_RWLIST_UNLOCK(&hints);
2950                 return 0;
2951         }
2952
2953         if (!context || !exten)
2954                 return -1;
2955
2956         /* This callback type is for only one hint, so get the hint */
2957         e = ast_hint_extension(NULL, context, exten);
2958         if (!e) {
2959                 return -1;
2960         }
2961
2962         /* Find the hint in the list of hints */
2963         AST_RWLIST_WRLOCK(&hints);
2964
2965         AST_RWLIST_TRAVERSE(&hints, hint, list) {
2966                 if (hint->exten == e)
2967                         break;
2968         }
2969
2970         if (!hint) {
2971                 /* We have no hint, sorry */
2972                 AST_RWLIST_UNLOCK(&hints);
2973                 return -1;
2974         }
2975
2976         /* Now insert the callback in the callback list  */
2977         if (!(cblist = ast_calloc(1, sizeof(*cblist)))) {
2978                 AST_RWLIST_UNLOCK(&hints);
2979                 return -1;
2980         }
2981         cblist->id = stateid++;         /* Unique ID for this callback */
2982         cblist->callback = callback;    /* Pointer to callback routine */
2983         cblist->data = data;            /* Data for the callback */
2984
2985         cblist->next = hint->callbacks;
2986         hint->callbacks = cblist;
2987
2988         AST_RWLIST_UNLOCK(&hints);
2989         return cblist->id;
2990 }
2991
2992 /*! \brief Remove a watcher from the callback list */
2993 int ast_extension_state_del(int id, ast_state_cb_type callback)
2994 {
2995         struct ast_state_cb **p_cur = NULL;     /* address of pointer to us */
2996         int ret = -1;
2997
2998         if (!id && !callback)
2999                 return -1;
3000
3001         AST_RWLIST_WRLOCK(&hints);
3002
3003         if (!id) {      /* id == 0 is a callback without extension */
3004                 for (p_cur = &statecbs; *p_cur; p_cur = &(*p_cur)->next) {
3005                         if ((*p_cur)->callback == callback)
3006                                 break;
3007                 }
3008         } else { /* callback with extension, find the callback based on ID */
3009                 struct ast_hint *hint;
3010                 AST_RWLIST_TRAVERSE(&hints, hint, list) {
3011                         for (p_cur = &hint->callbacks; *p_cur; p_cur = &(*p_cur)->next) {
3012                                 if ((*p_cur)->id == id)
3013                                         break;
3014                         }
3015                         if (*p_cur)     /* found in the inner loop */
3016                                 break;
3017                 }
3018         }
3019         if (p_cur && *p_cur) {
3020                 struct ast_state_cb *cur = *p_cur;
3021                 *p_cur = cur->next;
3022                 ast_free(cur);
3023                 ret = 0;
3024         }
3025         AST_RWLIST_UNLOCK(&hints);
3026         return ret;
3027 }
3028
3029 /*! \brief Add hint to hint list, check initial extension state */
3030 static int ast_add_hint(struct ast_exten *e)
3031 {
3032         struct ast_hint *hint;
3033
3034         if (!e)
3035                 return -1;
3036
3037         AST_RWLIST_WRLOCK(&hints);
3038
3039         /* Search if hint exists, do nothing */
3040         AST_RWLIST_TRAVERSE(&hints, hint, list) {
3041                 if (hint->exten == e) {
3042                         AST_RWLIST_UNLOCK(&hints);
3043                         ast_debug(2, "HINTS: Not re-adding existing hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e));
3044                         return -1;
3045                 }
3046         }
3047
3048         ast_debug(2, "HINTS: Adding hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e));
3049
3050         if (!(hint = ast_calloc(1, sizeof(*hint)))) {
3051                 AST_RWLIST_UNLOCK(&hints);
3052                 return -1;
3053         }
3054         /* Initialize and insert new item at the top */
3055         hint->exten = e;
3056         hint->laststate = ast_extension_state2(e);
3057         AST_RWLIST_INSERT_HEAD(&hints, hint, list);
3058
3059         AST_RWLIST_UNLOCK(&hints);
3060         return 0;
3061 }
3062
3063 /*! \brief Change hint for an extension */
3064 static int ast_change_hint(struct ast_exten *oe, struct ast_exten *ne)
3065 {
3066         struct ast_hint *hint;
3067         int res = -1;
3068
3069         AST_RWLIST_WRLOCK(&hints);
3070         AST_RWLIST_TRAVERSE(&hints, hint, list) {
3071                 if (hint->exten == oe) {
3072                         hint->exten = ne;
3073                         res = 0;
3074                         break;
3075                 }
3076         }
3077         AST_RWLIST_UNLOCK(&hints);
3078
3079         return res;
3080 }
3081
3082 /*! \brief Remove hint from extension */
3083 static int ast_remove_hint(struct ast_exten *e)
3084 {
3085         /* Cleanup the Notifys if hint is removed */
3086         struct ast_hint *hint;
3087         struct ast_state_cb *cblist, *cbprev;
3088         int res = -1;
3089
3090         if (!e)
3091                 return -1;
3092
3093         AST_RWLIST_TRAVERSE_SAFE_BEGIN(&hints, hint, list) {
3094                 if (hint->exten == e) {
3095                         cbprev = NULL;
3096                         cblist = hint->callbacks;
3097                         while (cblist) {
3098                                 /* Notify with -1 and remove all callbacks */
3099                                 cbprev = cblist;
3100                                 cblist = cblist->next;
3101                                 cbprev->callback(hint->exten->parent->name, hint->exten->exten, AST_EXTENSION_DEACTIVATED, cbprev->data);