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