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