Merged revisions 90967 via svnmerge from
[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                 if (!aswf)
1813                         res = 0;
1814                 else {
1815                         if (chan)
1816                                 ast_autoservice_start(chan);
1817                         res = aswf(chan, context, exten, priority, callerid, datap);
1818                         if (chan)
1819                                 ast_autoservice_stop(chan);
1820                 }
1821                 if (res) {      /* Got a match */
1822                         q->swo = asw;
1823                         q->data = datap;
1824                         q->foundcontext = context;
1825                         /* XXX keep status = STATUS_NO_CONTEXT ? */
1826                         return NULL;
1827                 }
1828         }
1829         q->incstack[q->stacklen++] = tmp->name; /* Setup the stack */
1830         /* Now try any includes we have in this context */
1831         for (i = tmp->includes; i; i = i->next) {
1832                 if (include_valid(i)) {
1833                         if ((e = pbx_find_extension(chan, bypass, q, i->rname, exten, priority, label, callerid, action))) {
1834 #ifdef NEED_DEBUG
1835                                 ast_log(LOG_NOTICE,"Returning recursive match of %s\n", e->exten);
1836 #endif
1837                                 return e;
1838                         }
1839                         if (q->swo)
1840                                 return NULL;
1841                 }
1842         }
1843         return NULL;
1844 }
1845
1846 /*! 
1847  * \brief extract offset:length from variable name.
1848  * \return 1 if there is a offset:length part, which is
1849  * trimmed off (values go into variables)
1850  */
1851 static int parse_variable_name(char *var, int *offset, int *length, int *isfunc)
1852 {
1853         int parens=0;
1854
1855         *offset = 0;
1856         *length = INT_MAX;
1857         *isfunc = 0;
1858         for (; *var; var++) {
1859                 if (*var == '(') {
1860                         (*isfunc)++;
1861                         parens++;
1862                 } else if (*var == ')') {
1863                         parens--;
1864                 } else if (*var == ':' && parens == 0) {
1865                         *var++ = '\0';
1866                         sscanf(var, "%d:%d", offset, length);
1867                         return 1; /* offset:length valid */
1868                 }
1869         }
1870         return 0;
1871 }
1872
1873 /*! 
1874  *\brief takes a substring. It is ok to call with value == workspace.
1875  * \param value
1876  * \param offset < 0 means start from the end of the string and set the beginning
1877  *   to be that many characters back.
1878  * \param length is the length of the substring, a value less than 0 means to leave
1879  * that many off the end.
1880  * \param workspace
1881  * \param workspace_len
1882  * Always return a copy in workspace.
1883  */
1884 static char *substring(const char *value, int offset, int length, char *workspace, size_t workspace_len)
1885 {
1886         char *ret = workspace;
1887         int lr; /* length of the input string after the copy */
1888
1889         ast_copy_string(workspace, value, workspace_len); /* always make a copy */
1890
1891         lr = strlen(ret); /* compute length after copy, so we never go out of the workspace */
1892
1893         /* Quick check if no need to do anything */
1894         if (offset == 0 && length >= lr)        /* take the whole string */
1895                 return ret;
1896
1897         if (offset < 0) {       /* translate negative offset into positive ones */
1898                 offset = lr + offset;
1899                 if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */
1900                         offset = 0;
1901         }
1902
1903         /* too large offset result in empty string so we know what to return */
1904         if (offset >= lr)
1905                 return ret + lr;        /* the final '\0' */
1906
1907         ret += offset;          /* move to the start position */
1908         if (length >= 0 && length < lr - offset)        /* truncate if necessary */
1909                 ret[length] = '\0';
1910         else if (length < 0) {
1911                 if (lr > offset - length) /* After we remove from the front and from the rear, is there anything left? */
1912                         ret[lr + length - offset] = '\0';
1913                 else
1914                         ret[0] = '\0';
1915         }
1916
1917         return ret;
1918 }
1919
1920 /*! \brief  Support for Asterisk built-in variables in the dialplan
1921
1922 \note   See also
1923         - \ref AstVar   Channel variables
1924         - \ref AstCauses The HANGUPCAUSE variable
1925  */
1926 void pbx_retrieve_variable(struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp)
1927 {
1928         const char not_found = '\0';
1929         char *tmpvar;
1930         const char *s;  /* the result */
1931         int offset, length;
1932         int i, need_substring;
1933         struct varshead *places[2] = { headp, &globals };       /* list of places where we may look */
1934
1935         if (c) {
1936                 ast_channel_lock(c);
1937                 places[0] = &c->varshead;
1938         }
1939         /*
1940          * Make a copy of var because parse_variable_name() modifies the string.
1941          * Then if called directly, we might need to run substring() on the result;
1942          * remember this for later in 'need_substring', 'offset' and 'length'
1943          */
1944         tmpvar = ast_strdupa(var);      /* parse_variable_name modifies the string */
1945         need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */);
1946
1947         /*
1948          * Look first into predefined variables, then into variable lists.
1949          * Variable 's' points to the result, according to the following rules:
1950          * s == &not_found (set at the beginning) means that we did not find a
1951          *      matching variable and need to look into more places.
1952          * If s != &not_found, s is a valid result string as follows:
1953          * s = NULL if the variable does not have a value;
1954          *      you typically do this when looking for an unset predefined variable.
1955          * s = workspace if the result has been assembled there;
1956          *      typically done when the result is built e.g. with an snprintf(),
1957          *      so we don't need to do an additional copy.
1958          * s != workspace in case we have a string, that needs to be copied
1959          *      (the ast_copy_string is done once for all at the end).
1960          *      Typically done when the result is already available in some string.
1961          */
1962         s = &not_found; /* default value */
1963         if (c) {        /* This group requires a valid channel */
1964                 /* Names with common parts are looked up a piece at a time using strncmp. */
1965                 if (!strncmp(var, "CALL", 4)) {
1966                         if (!strncmp(var + 4, "ING", 3)) {
1967                                 if (!strcmp(var + 7, "PRES")) {                 /* CALLINGPRES */
1968                                         snprintf(workspace, workspacelen, "%d", c->cid.cid_pres);
1969                                         s = workspace;
1970                                 } else if (!strcmp(var + 7, "ANI2")) {          /* CALLINGANI2 */
1971                                         snprintf(workspace, workspacelen, "%d", c->cid.cid_ani2);
1972                                         s = workspace;
1973                                 } else if (!strcmp(var + 7, "TON")) {           /* CALLINGTON */
1974                                         snprintf(workspace, workspacelen, "%d", c->cid.cid_ton);
1975                                         s = workspace;
1976                                 } else if (!strcmp(var + 7, "TNS")) {           /* CALLINGTNS */
1977                                         snprintf(workspace, workspacelen, "%d", c->cid.cid_tns);
1978                                         s = workspace;
1979                                 }
1980                         }
1981                 } else if (!strcmp(var, "HINT")) {
1982                         s = ast_get_hint(workspace, workspacelen, NULL, 0, c, c->context, c->exten) ? workspace : NULL;
1983                 } else if (!strcmp(var, "HINTNAME")) {
1984                         s = ast_get_hint(NULL, 0, workspace, workspacelen, c, c->context, c->exten) ? workspace : NULL;
1985                 } else if (!strcmp(var, "EXTEN")) {
1986                         s = c->exten;
1987                 } else if (!strcmp(var, "CONTEXT")) {
1988                         s = c->context;
1989                 } else if (!strcmp(var, "PRIORITY")) {
1990                         snprintf(workspace, workspacelen, "%d", c->priority);
1991                         s = workspace;
1992                 } else if (!strcmp(var, "CHANNEL")) {
1993                         s = c->name;
1994                 } else if (!strcmp(var, "UNIQUEID")) {
1995                         s = c->uniqueid;
1996                 } else if (!strcmp(var, "HANGUPCAUSE")) {
1997                         snprintf(workspace, workspacelen, "%d", c->hangupcause);
1998                         s = workspace;
1999                 }
2000         }
2001         if (s == &not_found) { /* look for more */
2002                 if (!strcmp(var, "EPOCH")) {
2003                         snprintf(workspace, workspacelen, "%u",(int)time(NULL));
2004                         s = workspace;
2005                 } else if (!strcmp(var, "SYSTEMNAME")) {
2006                         s = ast_config_AST_SYSTEM_NAME;
2007                 }
2008         }
2009         /* if not found, look into chanvars or global vars */
2010         for (i = 0; s == &not_found && i < (sizeof(places) / sizeof(places[0])); i++) {
2011                 struct ast_var_t *variables;
2012                 if (!places[i])
2013                         continue;
2014                 if (places[i] == &globals)
2015                         ast_rwlock_rdlock(&globalslock);
2016                 AST_LIST_TRAVERSE(places[i], variables, entries) {
2017                         if (strcasecmp(ast_var_name(variables), var)==0) {
2018                                 s = ast_var_value(variables);
2019                                 break;
2020                         }
2021                 }
2022                 if (places[i] == &globals)
2023                         ast_rwlock_unlock(&globalslock);
2024         }
2025         if (s == &not_found || s == NULL)
2026                 *ret = NULL;
2027         else {
2028                 if (s != workspace)
2029                         ast_copy_string(workspace, s, workspacelen);
2030                 *ret = workspace;
2031                 if (need_substring)
2032                         *ret = substring(*ret, offset, length, workspace, workspacelen);
2033         }
2034
2035         if (c)
2036                 ast_channel_unlock(c);
2037 }
2038
2039 static void exception_store_free(void *data)
2040 {
2041         struct pbx_exception *exception = data;
2042         ast_string_field_free_memory(exception);
2043         ast_free(exception);
2044 }
2045
2046 static struct ast_datastore_info exception_store_info = {
2047         .type = "EXCEPTION",
2048         .destroy = exception_store_free,
2049 };
2050
2051 int pbx_builtin_raise_exception(struct ast_channel *chan, void *vreason)
2052 {
2053         const char *reason = vreason;
2054         struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL);
2055         struct pbx_exception *exception = NULL;
2056
2057         if (!ds) {
2058                 ds = ast_channel_datastore_alloc(&exception_store_info, NULL);
2059                 if (!ds)
2060                         return -1;
2061                 exception = ast_calloc(1, sizeof(struct pbx_exception));
2062                 if (!exception) {
2063                         ast_channel_datastore_free(ds);
2064                         return -1;
2065                 }
2066                 if (ast_string_field_init(exception, 128)) {
2067                         ast_free(exception);
2068                         ast_channel_datastore_free(ds);
2069                         return -1;
2070                 }
2071                 ds->data = exception;
2072                 ast_channel_datastore_add(chan, ds);
2073         } else
2074                 exception = ds->data;
2075
2076         ast_string_field_set(exception, reason, reason);
2077         ast_string_field_set(exception, context, chan->context);
2078         ast_string_field_set(exception, exten, chan->exten);
2079         exception->priority = chan->priority;
2080         set_ext_pri(chan, "e", 0);
2081         return 0;
2082 }
2083
2084 static int acf_exception_read(struct ast_channel *chan, const char *name, char *data, char *buf, size_t buflen)
2085 {
2086         struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL);
2087         struct pbx_exception *exception = NULL;
2088         if (!ds || !ds->data)
2089                 return -1;
2090         exception = ds->data;
2091         if (!strcasecmp(data, "REASON"))
2092                 ast_copy_string(buf, exception->reason, buflen);
2093         else if (!strcasecmp(data, "CONTEXT"))
2094                 ast_copy_string(buf, exception->context, buflen);
2095         else if (!strncasecmp(data, "EXTEN", 5))
2096                 ast_copy_string(buf, exception->exten, buflen);
2097         else if (!strcasecmp(data, "PRIORITY"))
2098                 snprintf(buf, buflen, "%d", exception->priority);
2099         else
2100                 return -1;
2101         return 0;
2102 }
2103
2104 static struct ast_custom_function exception_function = {
2105         .name = "EXCEPTION",
2106         .synopsis = "Retrieve the details of the current dialplan exception",
2107         .desc =
2108 "The following fields are available for retrieval:\n"
2109 "  reason    INVALID, ERROR, RESPONSETIMEOUT, ABSOLUTETIMEOUT, or custom\n"
2110 "               value set by the RaiseException() application\n"
2111 "  context   The context executing when the exception occurred\n"
2112 "  exten     The extension executing when the exception occurred\n"
2113 "  priority  The numeric priority executing when the exception occurred\n",
2114         .syntax = "EXCEPTION(<field>)",
2115         .read = acf_exception_read,
2116 };
2117
2118 static char *handle_show_functions(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2119 {
2120         struct ast_custom_function *acf;
2121         int count_acf = 0;
2122         int like = 0;
2123
2124         switch (cmd) {
2125         case CLI_INIT:
2126                 e->command = "core show functions [like]";
2127                 e->usage = 
2128                         "Usage: core show functions [like <text>]\n"
2129                         "       List builtin functions, optionally only those matching a given string\n";
2130                 return NULL;
2131         case CLI_GENERATE:
2132                 return NULL;
2133         }
2134
2135         if (a->argc == 5 && (!strcmp(a->argv[3], "like")) ) {
2136                 like = 1;
2137         } else if (a->argc != 3) {
2138                 return CLI_SHOWUSAGE;
2139         }
2140
2141         ast_cli(a->fd, "%s Custom Functions:\n--------------------------------------------------------------------------------\n", like ? "Matching" : "Installed");
2142
2143         AST_RWLIST_RDLOCK(&acf_root);
2144         AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) {
2145                 if (!like || strstr(acf->name, a->argv[4])) {
2146                         count_acf++;
2147                         ast_cli(a->fd, "%-20.20s  %-35.35s  %s\n", acf->name, acf->syntax, acf->synopsis);
2148                 }
2149         }
2150         AST_RWLIST_UNLOCK(&acf_root);
2151
2152         ast_cli(a->fd, "%d %scustom functions installed.\n", count_acf, like ? "matching " : "");
2153
2154         return CLI_SUCCESS;
2155 }
2156
2157 static char *handle_show_function(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2158 {
2159         struct ast_custom_function *acf;
2160         /* Maximum number of characters added by terminal coloring is 22 */
2161         char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40];
2162         char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL;
2163         char stxtitle[40], *syntax = NULL;
2164         int synopsis_size, description_size, syntax_size;
2165         char *ret = NULL;
2166         int which = 0;
2167         int wordlen;
2168
2169         switch (cmd) {
2170         case CLI_INIT:
2171                 e->command = "core show function";
2172                 e->usage = 
2173                         "Usage: core show function <function>\n"
2174                         "       Describe a particular dialplan function.\n";
2175                 return NULL;
2176         case CLI_GENERATE:      
2177                 wordlen = strlen(a->word);
2178                 /* case-insensitive for convenience in this 'complete' function */
2179                 AST_RWLIST_RDLOCK(&acf_root);
2180                 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) {
2181                         if (!strncasecmp(a->word, acf->name, wordlen) && ++which > a->n) {
2182                                 ret = ast_strdup(acf->name);
2183                                 break;
2184                         }
2185                 }
2186                 AST_RWLIST_UNLOCK(&acf_root);
2187
2188                 return ret;
2189         }
2190
2191         if (a->argc < 4)
2192                 return CLI_SHOWUSAGE;
2193
2194         if (!(acf = ast_custom_function_find(a->argv[3]))) {
2195                 ast_cli(a->fd, "No function by that name registered.\n");
2196                 return CLI_FAILURE;
2197
2198         }
2199
2200         if (acf->synopsis)
2201                 synopsis_size = strlen(acf->synopsis) + 23;
2202         else
2203                 synopsis_size = strlen("Not available") + 23;
2204         synopsis = alloca(synopsis_size);
2205
2206         if (acf->desc)
2207                 description_size = strlen(acf->desc) + 23;
2208         else
2209                 description_size = strlen("Not available") + 23;
2210         description = alloca(description_size);
2211
2212         if (acf->syntax)
2213                 syntax_size = strlen(acf->syntax) + 23;
2214         else
2215                 syntax_size = strlen("Not available") + 23;
2216         syntax = alloca(syntax_size);
2217
2218         snprintf(info, 64 + AST_MAX_APP, "\n  -= Info about function '%s' =- \n\n", acf->name);
2219         term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22);
2220         term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40);
2221         term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
2222         term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
2223         term_color(syntax,
2224                    acf->syntax ? acf->syntax : "Not available",
2225                    COLOR_CYAN, 0, syntax_size);
2226         term_color(synopsis,
2227                    acf->synopsis ? acf->synopsis : "Not available",
2228                    COLOR_CYAN, 0, synopsis_size);
2229         term_color(description,
2230                    acf->desc ? acf->desc : "Not available",
2231                    COLOR_CYAN, 0, description_size);
2232
2233         ast_cli(a->fd,"%s%s%s\n\n%s%s\n\n%s%s\n", infotitle, stxtitle, syntax, syntitle, synopsis, destitle, description);
2234
2235         return CLI_SUCCESS;
2236 }
2237
2238 struct ast_custom_function *ast_custom_function_find(const char *name)
2239 {
2240         struct ast_custom_function *acf = NULL;
2241
2242         AST_RWLIST_RDLOCK(&acf_root);
2243         AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) {
2244                 if (!strcmp(name, acf->name))
2245                         break;
2246         }
2247         AST_RWLIST_UNLOCK(&acf_root);
2248
2249         return acf;
2250 }
2251
2252 int ast_custom_function_unregister(struct ast_custom_function *acf)
2253 {
2254         struct ast_custom_function *cur;
2255
2256         if (!acf)
2257                 return -1;
2258
2259         AST_RWLIST_WRLOCK(&acf_root);
2260         if ((cur = AST_RWLIST_REMOVE(&acf_root, acf, acflist)))
2261                 ast_verb(2, "Unregistered custom function %s\n", cur->name);
2262         AST_RWLIST_UNLOCK(&acf_root);
2263
2264         return cur ? 0 : -1;
2265 }
2266
2267 int __ast_custom_function_register(struct ast_custom_function *acf, struct ast_module *mod)
2268 {
2269         struct ast_custom_function *cur;
2270
2271         if (!acf)
2272                 return -1;
2273
2274         acf->mod = mod;
2275
2276         AST_RWLIST_WRLOCK(&acf_root);
2277
2278         AST_RWLIST_TRAVERSE(&acf_root, cur, acflist) {
2279                 if (!strcmp(acf->name, cur->name)) {
2280                         ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name);
2281                         AST_RWLIST_UNLOCK(&acf_root);
2282                         return -1;
2283                 }
2284         }
2285
2286         /* Store in alphabetical order */
2287         AST_RWLIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) {
2288                 if (strcasecmp(acf->name, cur->name) < 0) {
2289                         AST_RWLIST_INSERT_BEFORE_CURRENT(acf, acflist);
2290                         break;
2291                 }
2292         }
2293         AST_RWLIST_TRAVERSE_SAFE_END;
2294         if (!cur)
2295                 AST_RWLIST_INSERT_TAIL(&acf_root, acf, acflist);
2296
2297         AST_RWLIST_UNLOCK(&acf_root);
2298
2299         ast_verb(2, "Registered custom function %s\n", acf->name);
2300
2301         return 0;
2302 }
2303
2304 /*! \brief return a pointer to the arguments of the function,
2305  * and terminates the function name with '\\0'
2306  */
2307 static char *func_args(char *function)
2308 {
2309         char *args = strchr(function, '(');
2310
2311         if (!args)
2312                 ast_log(LOG_WARNING, "Function doesn't contain parentheses.  Assuming null argument.\n");
2313         else {
2314                 char *p;
2315                 *args++ = '\0';
2316                 if ((p = strrchr(args, ')')) )
2317                         *p = '\0';
2318                 else
2319                         ast_log(LOG_WARNING, "Can't find trailing parenthesis?\n");
2320         }
2321         return args;
2322 }
2323
2324 int ast_func_read(struct ast_channel *chan, const char *function, char *workspace, size_t len)
2325 {
2326         char *copy = ast_strdupa(function);
2327         char *args = func_args(copy);
2328         struct ast_custom_function *acfptr = ast_custom_function_find(copy);
2329
2330         if (acfptr == NULL)
2331                 ast_log(LOG_ERROR, "Function %s not registered\n", copy);
2332         else if (!acfptr->read)
2333                 ast_log(LOG_ERROR, "Function %s cannot be read\n", copy);
2334         else {
2335                 int res;
2336                 struct ast_module_user *u = NULL;
2337                 if (acfptr->mod)
2338                         u = __ast_module_user_add(acfptr->mod, chan);
2339                 res = acfptr->read(chan, copy, args, workspace, len);
2340                 if (acfptr->mod && u)
2341                         __ast_module_user_remove(acfptr->mod, u);
2342                 return res;
2343         }
2344         return -1;
2345 }
2346
2347 int ast_func_write(struct ast_channel *chan, const char *function, const char *value)
2348 {
2349         char *copy = ast_strdupa(function);
2350         char *args = func_args(copy);
2351         struct ast_custom_function *acfptr = ast_custom_function_find(copy);
2352
2353         if (acfptr == NULL)
2354                 ast_log(LOG_ERROR, "Function %s not registered\n", copy);
2355         else if (!acfptr->write)
2356                 ast_log(LOG_ERROR, "Function %s cannot be written to\n", copy);
2357         else {
2358                 int res;
2359                 struct ast_module_user *u = NULL;
2360                 if (acfptr->mod)
2361                         u = __ast_module_user_add(acfptr->mod, chan);
2362                 res = acfptr->write(chan, copy, args, value);
2363                 if (acfptr->mod && u)
2364                         __ast_module_user_remove(acfptr->mod, u);
2365                 return res;
2366         }
2367
2368         return -1;
2369 }
2370
2371 static void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count)
2372 {
2373         /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!!  */
2374         char *cp4;
2375         const char *tmp, *whereweare;
2376         int length, offset, offset2, isfunction;
2377         char *workspace = NULL;
2378         char *ltmp = NULL, *var = NULL;
2379         char *nextvar, *nextexp, *nextthing;
2380         char *vars, *vare;
2381         int pos, brackets, needsub, len;
2382         
2383         *cp2 = 0; /* just in case nothing ends up there */
2384         whereweare=tmp=cp1;
2385         while (!ast_strlen_zero(whereweare) && count) {
2386                 /* Assume we're copying the whole remaining string */
2387                 pos = strlen(whereweare);
2388                 nextvar = NULL;
2389                 nextexp = NULL;
2390                 nextthing = strchr(whereweare, '$');
2391                 if (nextthing) {
2392                         switch (nextthing[1]) {
2393                         case '{':
2394                                 nextvar = nextthing;
2395                                 pos = nextvar - whereweare;
2396                                 break;
2397                         case '[':
2398                                 nextexp = nextthing;
2399                                 pos = nextexp - whereweare;
2400                                 break;
2401                         default:
2402                                 pos = 1;
2403                         }
2404                 }
2405
2406                 if (pos) {
2407                         /* Can't copy more than 'count' bytes */
2408                         if (pos > count)
2409                                 pos = count;
2410
2411                         /* Copy that many bytes */
2412                         memcpy(cp2, whereweare, pos);
2413
2414                         count -= pos;
2415                         cp2 += pos;
2416                         whereweare += pos;
2417                         *cp2 = 0;
2418                 }
2419
2420                 if (nextvar) {
2421                         /* We have a variable.  Find the start and end, and determine
2422                            if we are going to have to recursively call ourselves on the
2423                            contents */
2424                         vars = vare = nextvar + 2;
2425                         brackets = 1;
2426                         needsub = 0;
2427
2428                         /* Find the end of it */
2429                         while (brackets && *vare) {
2430                                 if ((vare[0] == '$') && (vare[1] == '{')) {
2431                                         needsub++;
2432                                 } else if (vare[0] == '{') {
2433                                         brackets++;
2434                                 } else if (vare[0] == '}') {
2435                                         brackets--;
2436                                 } else if ((vare[0] == '$') && (vare[1] == '['))
2437                                         needsub++;
2438                                 vare++;
2439                         }
2440                         if (brackets)
2441                                 ast_log(LOG_NOTICE, "Error in extension logic (missing '}')\n");
2442                         len = vare - vars - 1;
2443
2444                         /* Skip totally over variable string */
2445                         whereweare += (len + 3);
2446
2447                         if (!var)
2448                                 var = alloca(VAR_BUF_SIZE);
2449
2450                         /* Store variable name (and truncate) */
2451                         ast_copy_string(var, vars, len + 1);
2452
2453                         /* Substitute if necessary */
2454                         if (needsub) {
2455                                 if (!ltmp)
2456                                         ltmp = alloca(VAR_BUF_SIZE);
2457
2458                                 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1);
2459                                 vars = ltmp;
2460                         } else {
2461                                 vars = var;
2462                         }
2463
2464                         if (!workspace)
2465                                 workspace = alloca(VAR_BUF_SIZE);
2466
2467                         workspace[0] = '\0';
2468
2469                         parse_variable_name(vars, &offset, &offset2, &isfunction);
2470                         if (isfunction) {
2471                                 /* Evaluate function */
2472                                 if (c || !headp)
2473                                         cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
2474                                 else {
2475                                         struct varshead old;
2476                                         struct ast_channel *c = ast_channel_alloc(0, 0, "", "", "", "", "", 0, "Bogus/%p", vars);
2477                                         if (c) {
2478                                                 memcpy(&old, &c->varshead, sizeof(old));
2479                                                 memcpy(&c->varshead, headp, sizeof(c->varshead));
2480                                                 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
2481                                                 /* Don't deallocate the varshead that was passed in */
2482                                                 memcpy(&c->varshead, &old, sizeof(c->varshead));
2483                                                 ast_channel_free(c);
2484                                         } else
2485                                                 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution.  Function results may be blank.\n");
2486                                 }
2487                                 ast_debug(1, "Function result is '%s'\n", cp4 ? cp4 : "(null)");
2488                         } else {
2489                                 /* Retrieve variable value */
2490                                 pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp);
2491                         }
2492                         if (cp4) {
2493                                 cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE);
2494
2495                                 length = strlen(cp4);
2496                                 if (length > count)
2497                                         length = count;
2498                                 memcpy(cp2, cp4, length);
2499                                 count -= length;
2500                                 cp2 += length;
2501                                 *cp2 = 0;
2502                         }
2503                 } else if (nextexp) {
2504                         /* We have an expression.  Find the start and end, and determine
2505                            if we are going to have to recursively call ourselves on the
2506                            contents */
2507                         vars = vare = nextexp + 2;
2508                         brackets = 1;
2509                         needsub = 0;
2510
2511                         /* Find the end of it */
2512                         while (brackets && *vare) {
2513                                 if ((vare[0] == '$') && (vare[1] == '[')) {
2514                                         needsub++;
2515                                         brackets++;
2516                                         vare++;
2517                                 } else if (vare[0] == '[') {
2518                                         brackets++;
2519                                 } else if (vare[0] == ']') {
2520                                         brackets--;
2521                                 } else if ((vare[0] == '$') && (vare[1] == '{')) {
2522                                         needsub++;
2523                                         vare++;
2524                                 }
2525                                 vare++;
2526                         }
2527                         if (brackets)
2528                                 ast_log(LOG_NOTICE, "Error in extension logic (missing ']')\n");
2529                         len = vare - vars - 1;
2530
2531                         /* Skip totally over expression */
2532                         whereweare += (len + 3);
2533
2534                         if (!var)
2535                                 var = alloca(VAR_BUF_SIZE);
2536
2537                         /* Store variable name (and truncate) */
2538                         ast_copy_string(var, vars, len + 1);
2539
2540                         /* Substitute if necessary */
2541                         if (needsub) {
2542                                 if (!ltmp)
2543                                         ltmp = alloca(VAR_BUF_SIZE);
2544
2545                                 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1);
2546                                 vars = ltmp;
2547                         } else {
2548                                 vars = var;
2549                         }
2550
2551                         length = ast_expr(vars, cp2, count, c);
2552
2553                         if (length) {
2554                                 ast_debug(1, "Expression result is '%s'\n", cp2);
2555                                 count -= length;
2556                                 cp2 += length;
2557                                 *cp2 = 0;
2558                         }
2559                 }
2560         }
2561 }
2562
2563 void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count)
2564 {
2565         pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count);
2566 }
2567
2568 void pbx_substitute_variables_varshead(struct varshead *headp, const char *cp1, char *cp2, int count)
2569 {
2570         pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count);
2571 }
2572
2573 static void pbx_substitute_variables(char *passdata, int datalen, struct ast_channel *c, struct ast_exten *e)
2574 {
2575         const char *tmp;
2576
2577         /* Nothing more to do */
2578         if (!e->data)
2579                 return;
2580
2581         /* No variables or expressions in e->data, so why scan it? */
2582         if ((!(tmp = strchr(e->data, '$'))) || (!strstr(tmp, "${") && !strstr(tmp, "$["))) {
2583                 ast_copy_string(passdata, e->data, datalen);
2584                 return;
2585         }
2586
2587         pbx_substitute_variables_helper(c, e->data, passdata, datalen - 1);
2588 }
2589
2590 /*! 
2591  * \brief The return value depends on the action:
2592  *
2593  * E_MATCH, E_CANMATCH, E_MATCHMORE require a real match,
2594  *      and return 0 on failure, -1 on match;
2595  * E_FINDLABEL maps the label to a priority, and returns
2596  *      the priority on success, ... XXX
2597  * E_SPAWN, spawn an application,
2598  *      
2599  * \retval 0 on success.
2600  * \retval  -1 on failure.
2601  *
2602  * \note The channel is auto-serviced in this function, because doing an extension
2603  * match may block for a long time.  For example, if the lookup has to use a network
2604  * dialplan switch, such as DUNDi or IAX2, it may take a while.  However, the channel
2605  * auto-service code will queue up any important signalling frames to be processed
2606  * after this is done.
2607  */
2608 static int pbx_extension_helper(struct ast_channel *c, struct ast_context *con,
2609   const char *context, const char *exten, int priority,
2610   const char *label, const char *callerid, enum ext_match_t action, int *found, int combined_find_spawn)
2611 {
2612         struct ast_exten *e;
2613         struct ast_app *app;
2614         int res;
2615         struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */
2616         char passdata[EXT_DATA_SIZE];
2617
2618         int matching_action = (action == E_MATCH || action == E_CANMATCH || action == E_MATCHMORE);
2619
2620         ast_rdlock_contexts();
2621         if (found)
2622                 *found = 0;
2623
2624         e = pbx_find_extension(c, con, &q, context, exten, priority, label, callerid, action);
2625         if (e) {
2626                 if (found)
2627                         *found = 1;
2628                 if (matching_action) {
2629                         ast_unlock_contexts();
2630                         return -1;      /* success, we found it */
2631                 } else if (action == E_FINDLABEL) { /* map the label to a priority */
2632                         res = e->priority;
2633                         ast_unlock_contexts();
2634                         return res;     /* the priority we were looking for */
2635                 } else {        /* spawn */
2636                         if (!e->cached_app)
2637                                 e->cached_app = pbx_findapp(e->app);
2638                         app = e->cached_app;
2639                         ast_unlock_contexts();
2640                         if (!app) {
2641                                 ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority);
2642                                 return -1;
2643                         }
2644                         if (c->context != context)
2645                                 ast_copy_string(c->context, context, sizeof(c->context));
2646                         if (c->exten != exten)
2647                                 ast_copy_string(c->exten, exten, sizeof(c->exten));
2648                         c->priority = priority;
2649                         pbx_substitute_variables(passdata, sizeof(passdata), c, e);
2650                         ast_debug(1, "Launching '%s'\n", app->name);
2651                         if (option_verbose > 2) {
2652                                 char tmp[80], tmp2[80], tmp3[EXT_DATA_SIZE];
2653                                 ast_verb(3, "Executing [%s@%s:%d] %s(\"%s\", \"%s\") %s\n",
2654                                         exten, context, priority,
2655                                         term_color(tmp, app->name, COLOR_BRCYAN, 0, sizeof(tmp)),
2656                                         term_color(tmp2, c->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)),
2657                                         term_color(tmp3, passdata, COLOR_BRMAGENTA, 0, sizeof(tmp3)),
2658                                         "in new stack");
2659                         }
2660                         manager_event(EVENT_FLAG_CALL, "Newexten",
2661                                         "Channel: %s\r\n"
2662                                         "Context: %s\r\n"
2663                                         "Extension: %s\r\n"
2664                                         "Priority: %d\r\n"
2665                                         "Application: %s\r\n"
2666                                         "AppData: %s\r\n"
2667                                         "Uniqueid: %s\r\n",
2668                                         c->name, c->context, c->exten, c->priority, app->name, passdata, c->uniqueid);
2669                         return pbx_exec(c, app, passdata);      /* 0 on success, -1 on failure */
2670                 }
2671         } else if (q.swo) {     /* not found here, but in another switch */
2672                 ast_unlock_contexts();
2673                 if (matching_action) {
2674                         return -1;
2675                 } else {
2676                         if (!q.swo->exec) {
2677                                 ast_log(LOG_WARNING, "No execution engine for switch %s\n", q.swo->name);
2678                                 res = -1;
2679                         }
2680                         return q.swo->exec(c, q.foundcontext ? q.foundcontext : context, exten, priority, callerid, q.data);
2681                 }
2682         } else {        /* not found anywhere, see what happened */
2683                 ast_unlock_contexts();
2684                 switch (q.status) {
2685                 case STATUS_NO_CONTEXT:
2686                         if (!matching_action && !combined_find_spawn)
2687                                 ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", context);
2688                         break;
2689                 case STATUS_NO_EXTENSION:
2690                         if (!matching_action && !combined_find_spawn)
2691                                 ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, context);
2692                         break;
2693                 case STATUS_NO_PRIORITY:
2694                         if (!matching_action && !combined_find_spawn)
2695                                 ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, context);
2696                         break;
2697                 case STATUS_NO_LABEL:
2698                         if (context && !combined_find_spawn)
2699                                 ast_log(LOG_NOTICE, "No such label '%s' in extension '%s' in context '%s'\n", label, exten, context);
2700                         break;
2701                 default:
2702                         ast_debug(1, "Shouldn't happen!\n");
2703                 }
2704
2705                 return (matching_action) ? 0 : -1;
2706         }
2707 }
2708
2709 /*! \brief Find hint for given extension in context */
2710 static struct ast_exten *ast_hint_extension(struct ast_channel *c, const char *context, const char *exten)
2711 {
2712         struct ast_exten *e;
2713         struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */
2714
2715         ast_rdlock_contexts();
2716         e = pbx_find_extension(c, NULL, &q, context, exten, PRIORITY_HINT, NULL, "", E_MATCH);
2717         ast_unlock_contexts();
2718
2719         return e;
2720 }
2721
2722 /*! \brief Check state of extension by using hints */
2723 static int ast_extension_state2(struct ast_exten *e)
2724 {
2725         char hint[AST_MAX_EXTENSION];
2726         char *cur, *rest;
2727         int allunavailable = 1, allbusy = 1, allfree = 1, allonhold = 1;
2728         int busy = 0, inuse = 0, ring = 0;
2729
2730         if (!e)
2731                 return -1;
2732
2733         ast_copy_string(hint, ast_get_extension_app(e), sizeof(hint));
2734
2735         rest = hint;    /* One or more devices separated with a & character */
2736         while ( (cur = strsep(&rest, "&")) ) {
2737                 int res = ast_device_state(cur);
2738                 switch (res) {
2739                 case AST_DEVICE_NOT_INUSE:
2740                         allunavailable = 0;
2741                         allbusy = 0;
2742                         allonhold = 0;
2743                         break;
2744                 case AST_DEVICE_INUSE:
2745                         inuse = 1;
2746                         allunavailable = 0;
2747                         allfree = 0;
2748                         allonhold = 0;
2749                         break;
2750                 case AST_DEVICE_RINGING:
2751                         ring = 1;
2752                         allunavailable = 0;
2753                         allfree = 0;
2754                         allonhold = 0;
2755                         break;
2756                 case AST_DEVICE_RINGINUSE:
2757                         inuse = 1;
2758                         ring = 1;
2759                         allunavailable = 0;
2760                         allfree = 0;
2761                         allonhold = 0;
2762                         break;
2763                 case AST_DEVICE_ONHOLD:
2764                         allunavailable = 0;
2765                         allfree = 0;
2766                         break;
2767                 case AST_DEVICE_BUSY:
2768                         allunavailable = 0;
2769                         allfree = 0;
2770                         allonhold = 0;
2771                         busy = 1;
2772                         break;
2773                 case AST_DEVICE_UNAVAILABLE:
2774                 case AST_DEVICE_INVALID:
2775                         allbusy = 0;
2776                         allfree = 0;
2777                         allonhold = 0;
2778                         break;
2779                 default:
2780                         allunavailable = 0;
2781                         allbusy = 0;
2782                         allfree = 0;
2783                         allonhold = 0;
2784                 }
2785         }
2786
2787         if (!inuse && ring)
2788                 return AST_EXTENSION_RINGING;
2789         if (inuse && ring)
2790                 return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING);
2791         if (inuse)
2792                 return AST_EXTENSION_INUSE;
2793         if (allfree)
2794                 return AST_EXTENSION_NOT_INUSE;
2795         if (allonhold)
2796                 return AST_EXTENSION_ONHOLD;
2797         if (allbusy)
2798                 return AST_EXTENSION_BUSY;
2799         if (allunavailable)
2800                 return AST_EXTENSION_UNAVAILABLE;
2801         if (busy)
2802                 return AST_EXTENSION_INUSE;
2803
2804         return AST_EXTENSION_NOT_INUSE;
2805 }
2806
2807 /*! \brief Return extension_state as string */
2808 const char *ast_extension_state2str(int extension_state)
2809 {
2810         int i;
2811
2812         for (i = 0; (i < (sizeof(extension_states) / sizeof(extension_states[0]))); i++) {
2813                 if (extension_states[i].extension_state == extension_state)
2814                         return extension_states[i].text;
2815         }
2816         return "Unknown";
2817 }
2818
2819 /*! \brief Check extension state for an extension by using hint */
2820 int ast_extension_state(struct ast_channel *c, const char *context, const char *exten)
2821 {
2822         struct ast_exten *e;
2823
2824         e = ast_hint_extension(c, context, exten);      /* Do we have a hint for this extension ? */
2825         if (!e)
2826                 return -1;                              /* No hint, return -1 */
2827
2828         return ast_extension_state2(e);                 /* Check all devices in the hint */
2829 }
2830
2831 static void handle_statechange(const char *device)
2832 {
2833         struct ast_hint *hint;
2834
2835         AST_RWLIST_RDLOCK(&hints);
2836
2837         AST_RWLIST_TRAVERSE(&hints, hint, list) {
2838                 struct ast_state_cb *cblist;
2839                 char buf[AST_MAX_EXTENSION];
2840                 char *parse = buf;
2841                 char *cur;
2842                 int state;
2843
2844                 ast_copy_string(buf, ast_get_extension_app(hint->exten), sizeof(buf));
2845                 while ( (cur = strsep(&parse, "&")) ) {
2846                         if (!strcasecmp(cur, device))
2847                                 break;
2848                 }
2849                 if (!cur)
2850                         continue;
2851
2852                 /* Get device state for this hint */
2853                 state = ast_extension_state2(hint->exten);
2854
2855                 if ((state == -1) || (state == hint->laststate))
2856                         continue;
2857
2858                 /* Device state changed since last check - notify the watchers */
2859
2860                 /* For general callbacks */
2861                 for (cblist = statecbs; cblist; cblist = cblist->next)
2862                         cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data);
2863
2864                 /* For extension callbacks */
2865                 for (cblist = hint->callbacks; cblist; cblist = cblist->next)
2866                         cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data);
2867
2868                 hint->laststate = state;        /* record we saw the change */
2869         }
2870
2871         AST_RWLIST_UNLOCK(&hints);
2872 }
2873
2874 static int statechange_queue(const char *dev)
2875 {
2876         struct statechange *sc;
2877
2878         if (!(sc = ast_calloc(1, sizeof(*sc) + strlen(dev) + 1)))
2879                 return 0;
2880
2881         strcpy(sc->dev, dev);
2882
2883         ast_mutex_lock(&device_state.lock);
2884         AST_LIST_INSERT_TAIL(&device_state.state_change_q, sc, entry);
2885         ast_cond_signal(&device_state.cond);
2886         ast_mutex_unlock(&device_state.lock);
2887
2888         return 0;
2889 }
2890
2891 static void *device_state_thread(void *data)
2892 {
2893         struct statechange *sc;
2894
2895         while (!device_state.stop) {
2896                 ast_mutex_lock(&device_state.lock);
2897                 while (!(sc = AST_LIST_REMOVE_HEAD(&device_state.state_change_q, entry))) {
2898                         ast_cond_wait(&device_state.cond, &device_state.lock);
2899                         /* Check to see if we were woken up to see the request to stop */
2900                         if (device_state.stop) {
2901                                 ast_mutex_unlock(&device_state.lock);
2902                                 return NULL;
2903                         }
2904                 }
2905                 ast_mutex_unlock(&device_state.lock);
2906
2907                 handle_statechange(sc->dev);
2908
2909                 ast_free(sc);
2910         }
2911
2912         return NULL;
2913 }
2914
2915 /*! \brief  Add watcher for extension states */
2916 int ast_extension_state_add(const char *context, const char *exten,
2917                             ast_state_cb_type callback, void *data)
2918 {
2919         struct ast_hint *hint;
2920         struct ast_state_cb *cblist;
2921         struct ast_exten *e;
2922
2923         /* If there's no context and extension:  add callback to statecbs list */
2924         if (!context && !exten) {
2925                 AST_RWLIST_WRLOCK(&hints);
2926
2927                 for (cblist = statecbs; cblist; cblist = cblist->next) {
2928                         if (cblist->callback == callback) {
2929                                 cblist->data = data;
2930                                 AST_RWLIST_UNLOCK(&hints);
2931                                 return 0;
2932                         }
2933                 }
2934
2935                 /* Now insert the callback */
2936                 if (!(cblist = ast_calloc(1, sizeof(*cblist)))) {
2937                         AST_RWLIST_UNLOCK(&hints);
2938                         return -1;
2939                 }
2940                 cblist->id = 0;
2941                 cblist->callback = callback;
2942                 cblist->data = data;
2943
2944                 cblist->next = statecbs;
2945                 statecbs = cblist;
2946
2947                 AST_RWLIST_UNLOCK(&hints);
2948                 return 0;
2949         }
2950
2951         if (!context || !exten)
2952                 return -1;
2953
2954         /* This callback type is for only one hint, so get the hint */
2955         e = ast_hint_extension(NULL, context, exten);
2956         if (!e) {
2957                 return -1;
2958         }
2959
2960         /* Find the hint in the list of hints */
2961         AST_RWLIST_WRLOCK(&hints);
2962
2963         AST_RWLIST_TRAVERSE(&hints, hint, list) {
2964                 if (hint->exten == e)
2965                         break;
2966         }
2967
2968         if (!hint) {
2969                 /* We have no hint, sorry */
2970                 AST_RWLIST_UNLOCK(&hints);
2971                 return -1;
2972         }
2973
2974         /* Now insert the callback in the callback list  */
2975         if (!(cblist = ast_calloc(1, sizeof(*cblist)))) {
2976                 AST_RWLIST_UNLOCK(&hints);
2977                 return -1;
2978         }
2979         cblist->id = stateid++;         /* Unique ID for this callback */
2980         cblist->callback = callback;    /* Pointer to callback routine */
2981         cblist->data = data;            /* Data for the callback */
2982
2983         cblist->next = hint->callbacks;
2984         hint->callbacks = cblist;
2985
2986         AST_RWLIST_UNLOCK(&hints);
2987         return cblist->id;
2988 }
2989
2990 /*! \brief Remove a watcher from the callback list */
2991 int ast_extension_state_del(int id, ast_state_cb_type callback)
2992 {
2993         struct ast_state_cb **p_cur = NULL;     /* address of pointer to us */
2994         int ret = -1;
2995
2996         if (!id && !callback)
2997                 return -1;
2998
2999         AST_RWLIST_WRLOCK(&hints);
3000
3001         if (!id) {      /* id == 0 is a callback without extension */
3002                 for (p_cur = &statecbs; *p_cur; p_cur = &(*p_cur)->next) {
3003                         if ((*p_cur)->callback == callback)
3004                                 break;
3005                 }
3006         } else { /* callback with extension, find the callback based on ID */
3007                 struct ast_hint *hint;
3008                 AST_RWLIST_TRAVERSE(&hints, hint, list) {
3009                         for (p_cur = &hint->callbacks; *p_cur; p_cur = &(*p_cur)->next) {
3010                                 if ((*p_cur)->id == id)
3011                                         break;
3012                         }
3013                         if (*p_cur)     /* found in the inner loop */
3014                                 break;
3015                 }
3016         }
3017         if (p_cur && *p_cur) {
3018                 struct ast_state_cb *cur = *p_cur;
3019                 *p_cur = cur->next;
3020                 ast_free(cur);
3021                 ret = 0;
3022         }
3023         AST_RWLIST_UNLOCK(&hints);
3024         return ret;
3025 }
3026
3027 /*! \brief Add hint to hint list, check initial extension state */
3028 static int ast_add_hint(struct ast_exten *e)
3029 {
3030         struct ast_hint *hint;
3031
3032         if (!e)
3033                 return -1;
3034
3035         AST_RWLIST_WRLOCK(&hints);
3036
3037         /* Search if hint exists, do nothing */
3038         AST_RWLIST_TRAVERSE(&hints, hint, list) {
3039                 if (hint->exten == e) {
3040                         AST_RWLIST_UNLOCK(&hints);
3041                         ast_debug(2, "HINTS: Not re-adding existing hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e));
3042                         return -1;
3043                 }
3044         }
3045
3046         ast_debug(2, "HINTS: Adding hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e));
3047
3048         if (!(hint = ast_calloc(1, sizeof(*hint)))) {
3049                 AST_RWLIST_UNLOCK(&hints);
3050                 return -1;
3051         }
3052         /* Initialize and insert new item at the top */
3053         hint->exten = e;
3054         hint->laststate = ast_extension_state2(e);
3055         AST_RWLIST_INSERT_HEAD(&hints, hint, list);
3056
3057         AST_RWLIST_UNLOCK(&hints);
3058         return 0;
3059 }
3060
3061 /*! \brief Change hint for an extension */
3062 static int ast_change_hint(struct ast_exten *oe, struct ast_exten *ne)
3063 {
3064         struct ast_hint *hint;
3065         int res = -1;
3066
3067         AST_RWLIST_WRLOCK(&hints);
3068         AST_RWLIST_TRAVERSE(&hints, hint, list) {
3069                 if (hint->exten == oe) {
3070                         hint->exten = ne;
3071                         res = 0;
3072                         break;
3073                 }
3074         }
3075         AST_RWLIST_UNLOCK(&hints);
3076
3077         return res;
3078 }
3079
3080 /*! \brief Remove hint from extension */
3081 static int ast_remove_hint(struct ast_exten *e)
3082 {
3083         /* Cleanup the Notifys if hint is removed */
3084         struct ast_hint *hint;
3085         struct ast_state_cb *cblist, *cbprev;
3086         int res = -1;
3087
3088         if (!e)
3089                 return -1;
3090
3091         AST_RWLIST_TRAVERSE_SAFE_BEGIN(&hints, hint, list) {
3092                 if (hint->exten == e) {
3093                         cbprev = NULL;
3094                         cblist = hint->callbacks;
3095                         while (cblist) {
3096                                 /* Notify with -1 and remove all callbacks */
3097                                 cbprev = cblist;
3098                                 cblist = cblist->next;
3099                                 cbprev->callback(hint->exten->parent->name, hint->exten->exten, AST_EXTENSION_DEACTIVATED, cbprev->data);
3100                                 ast_free(cbprev);
3101