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