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