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