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