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