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