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