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