Support hold/unhold in Zap, update IAX2 parser to know about modern commands, forward...
[asterisk/asterisk.git] / 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
40 #include "asterisk/lock.h"
41 #include "asterisk/cli.h"
42 #include "asterisk/pbx.h"
43 #include "asterisk/channel.h"
44 #include "asterisk/options.h"
45 #include "asterisk/logger.h"
46 #include "asterisk/file.h"
47 #include "asterisk/callerid.h"
48 #include "asterisk/cdr.h"
49 #include "asterisk/config.h"
50 #include "asterisk/term.h"
51 #include "asterisk/manager.h"
52 #include "asterisk/ast_expr.h"
53 #include "asterisk/linkedlists.h"
54 #define SAY_STUBS       /* generate declarations and stubs for say methods */
55 #include "asterisk/say.h"
56 #include "asterisk/utils.h"
57 #include "asterisk/causes.h"
58 #include "asterisk/musiconhold.h"
59 #include "asterisk/app.h"
60 #include "asterisk/devicestate.h"
61 #include "asterisk/stringfields.h"
62
63 /*!
64  * \note I M P O R T A N T :
65  *
66  *              The speed of extension handling will likely be among the most important
67  * aspects of this PBX.  The switching scheme as it exists right now isn't
68  * terribly bad (it's O(N+M), where N is the # of extensions and M is the avg #
69  * of priorities, but a constant search time here would be great ;-)
70  *
71  */
72
73 #ifdef LOW_MEMORY
74 #define EXT_DATA_SIZE 256
75 #else
76 #define EXT_DATA_SIZE 8192
77 #endif
78
79 #define SWITCH_DATA_LENGTH 256
80
81 #define VAR_BUF_SIZE 4096
82
83 #define VAR_NORMAL              1
84 #define VAR_SOFTTRAN    2
85 #define VAR_HARDTRAN    3
86
87 #define BACKGROUND_SKIP         (1 << 0)
88 #define BACKGROUND_NOANSWER     (1 << 1)
89 #define BACKGROUND_MATCHEXTEN   (1 << 2)
90 #define BACKGROUND_PLAYBACK     (1 << 3)
91
92 AST_APP_OPTIONS(background_opts, {
93         AST_APP_OPTION('s', BACKGROUND_SKIP),
94         AST_APP_OPTION('n', BACKGROUND_NOANSWER),
95         AST_APP_OPTION('m', BACKGROUND_MATCHEXTEN),
96         AST_APP_OPTION('p', BACKGROUND_PLAYBACK),
97 });
98
99 #define WAITEXTEN_MOH           (1 << 0)
100
101 AST_APP_OPTIONS(waitexten_opts, {
102         AST_APP_OPTION_ARG('m', WAITEXTEN_MOH, 1),
103 });
104
105 struct ast_context;
106
107 /*!
108    \brief ast_exten: An extension
109         The dialplan is saved as a linked list with each context
110         having it's own linked list of extensions - one item per
111         priority.
112 */
113 struct ast_exten {
114         char *exten;                    /*!< Extension name */
115         int matchcid;                   /*!< Match caller id ? */
116         const char *cidmatch;           /*!< Caller id to match for this extension */
117         int priority;                   /*!< Priority */
118         const char *label;              /*!< Label */
119         struct ast_context *parent;     /*!< The context this extension belongs to  */
120         const char *app;                /*!< Application to execute */
121         void *data;                     /*!< Data to use (arguments) */
122         void (*datad)(void *);          /*!< Data destructor */
123         struct ast_exten *peer;         /*!< Next higher priority with our extension */
124         const char *registrar;          /*!< Registrar */
125         struct ast_exten *next;         /*!< Extension with a greater ID */
126         char stuff[0];
127 };
128
129 /*! \brief ast_include: include= support in extensions.conf */
130 struct ast_include {
131         const char *name;
132         const char *rname;                      /*!< Context to include */
133         const char *registrar;                  /*!< Registrar */
134         int hastime;                            /*!< If time construct exists */
135         struct ast_timing timing;               /*!< time construct */
136         struct ast_include *next;               /*!< Link them together */
137         char stuff[0];
138 };
139
140 /*! \brief ast_sw: Switch statement in extensions.conf */
141 struct ast_sw {
142         char *name;
143         const char *registrar;                  /*!< Registrar */
144         char *data;                             /*!< Data load */
145         int eval;
146         AST_LIST_ENTRY(ast_sw) list;
147         char *tmpdata;
148         char stuff[0];
149 };
150
151 /*! \brief ast_ignorepat: Ignore patterns in dial plan */
152 struct ast_ignorepat {
153         const char *registrar;
154         struct ast_ignorepat *next;
155         const char pattern[0];
156 };
157
158 /*! \brief ast_context: An extension context */
159 struct ast_context {
160         ast_mutex_t lock;                       /*!< A lock to prevent multiple threads from clobbering the context */
161         struct ast_exten *root;                 /*!< The root of the list of extensions */
162         struct ast_context *next;               /*!< Link them together */
163         struct ast_include *includes;           /*!< Include other contexts */
164         struct ast_ignorepat *ignorepats;       /*!< Patterns for which to continue playing dialtone */
165         const char *registrar;                  /*!< Registrar */
166         AST_LIST_HEAD_NOLOCK(, ast_sw) alts;    /*!< Alternative switches */
167         char name[0];                           /*!< Name of the context */
168 };
169
170
171 /*! \brief ast_app: A registered application */
172 struct ast_app {
173         int (*execute)(struct ast_channel *chan, void *data);
174         const char *synopsis;                   /*!< Synopsis text for 'show applications' */
175         const char *description;                /*!< Description (help text) for 'show application &lt;name&gt;' */
176         AST_LIST_ENTRY(ast_app) list;           /*!< Next app in list */
177         struct module *module;                  /*!< Module this app belongs to */
178         char name[0];                           /*!< Name of the application */
179 };
180
181 /*! \brief ast_state_cb: An extension state notify register item */
182 struct ast_state_cb {
183         int id;
184         void *data;
185         ast_state_cb_type callback;
186         struct ast_state_cb *next;
187 };
188
189 /*! \brief Structure for dial plan hints
190
191   \note Hints are pointers from an extension in the dialplan to one or
192   more devices (tech/name) */
193 struct ast_hint {
194         struct ast_exten *exten;        /*!< Extension */
195         int laststate;                  /*!< Last known state */
196         struct ast_state_cb *callbacks; /*!< Callback list for this extension */
197         AST_LIST_ENTRY(ast_hint) list;  /*!< Pointer to next hint in list */
198 };
199
200 static const struct cfextension_states {
201         int extension_state;
202         const char * const text;
203 } extension_states[] = {
204         { AST_EXTENSION_NOT_INUSE,                     "Idle" },
205         { AST_EXTENSION_INUSE,                         "InUse" },
206         { AST_EXTENSION_BUSY,                          "Busy" },
207         { AST_EXTENSION_UNAVAILABLE,                   "Unavailable" },
208         { AST_EXTENSION_RINGING,                       "Ringing" },
209         { AST_EXTENSION_INUSE | AST_EXTENSION_RINGING, "InUse&Ringing" },
210         { AST_EXTENSION_ONHOLD,                        "Hold" },
211         { AST_EXTENSION_INUSE | AST_EXTENSION_ONHOLD,  "InUse&Hold" }
212 };
213
214 int ast_pbx_outgoing_cdr_failed(void);
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;
242
243 static int autofallthrough = 0;
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.\n",
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 static int _extension_match_core(const char *pattern, const char *data, enum ext_match_t mode)
740 {
741         mode &= E_MATCH_MASK;   /* only consider the relevant bits */
742
743         if (pattern[0] != '_') { /* not a pattern, try exact or partial match */
744                 int ld = strlen(data), lp = strlen(pattern);
745
746                 if (lp < ld)            /* pattern too short, cannot match */
747                         return 0;
748                 /* depending on the mode, accept full or partial match or both */
749                 if (mode == E_MATCH)
750                         return !strcmp(pattern, data); /* 1 on match, 0 on fail */
751                 if (ld == 0 || !strncasecmp(pattern, data, ld)) /* partial or full match */
752                         return (mode == E_MATCHMORE) ? lp > ld : 1; /* XXX should consider '!' and '/' ? */
753                 else
754                         return 0;
755         }
756         pattern++; /* skip leading _ */
757         /*
758          * XXX below we stop at '/' which is a separator for the CID info. However we should
759          * not store '/' in the pattern at all. When we insure it, we can remove the checks.
760          */
761         while (*data && *pattern && *pattern != '/') {
762                 const char *end;
763
764                 if (*data == '-') { /* skip '-' in data (just a separator) */
765                         data++;
766                         continue;
767                 }
768                 switch (toupper(*pattern)) {
769                 case '[':       /* a range */
770                         end = strchr(pattern+1, ']'); /* XXX should deal with escapes ? */
771                         if (end == NULL) {
772                                 ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n");
773                                 return 0;       /* unconditional failure */
774                         }
775                         for (pattern++; pattern != end; pattern++) {
776                                 if (pattern+2 < end && pattern[1] == '-') { /* this is a range */
777                                         if (*data >= pattern[0] && *data <= pattern[2])
778                                                 break;  /* match found */
779                                         else {
780                                                 pattern += 2; /* skip a total of 3 chars */
781                                                 continue;
782                                         }
783                                 } else if (*data == pattern[0])
784                                         break;  /* match found */
785                         }
786                         if (pattern == end)
787                                 return 0;
788                         pattern = end;  /* skip and continue */
789                         break;
790                 case 'N':
791                         if (*data < '2' || *data > '9')
792                                 return 0;
793                         break;
794                 case 'X':
795                         if (*data < '0' || *data > '9')
796                                 return 0;
797                         break;
798                 case 'Z':
799                         if (*data < '1' || *data > '9')
800                                 return 0;
801                         break;
802                 case '.':       /* Must match, even with more digits */
803                         return 1;
804                 case '!':       /* Early match */
805                         return 2;
806                 case ' ':
807                 case '-':       /* Ignore these in patterns */
808                         data--; /* compensate the final data++ */
809                         break;
810                 default:
811                         if (*data != *pattern)
812                                 return 0;
813                 }
814                 data++;
815                 pattern++;
816         }
817         if (*data)                      /* data longer than pattern, no match */
818                 return 0;
819         /*
820          * match so far, but ran off the end of the data.
821          * Depending on what is next, determine match or not.
822          */
823         if (*pattern == '\0' || *pattern == '/')        /* exact match */
824                 return (mode == E_MATCHMORE) ? 0 : 1;   /* this is a failure for E_MATCHMORE */
825         else if (*pattern == '!')                       /* early match */
826                 return 2;
827         else                                            /* partial match */
828                 return (mode == E_MATCH) ? 0 : 1;       /* this is a failure for E_MATCH */
829 }
830
831 /*
832  * Wrapper around _extension_match_core() to do performance measurement
833  * using the profiling code.
834  */
835 static int extension_match_core(const char *pattern, const char *data, enum ext_match_t mode)
836 {
837         int i;
838         static int prof_id = -2;        /* marker for 'unallocated' id */
839         if (prof_id == -2)
840                 prof_id = ast_add_profile("ext_match", 0);
841         ast_mark(prof_id, 1);
842         i = _extension_match_core(pattern, data, mode);
843         ast_mark(prof_id, 0);
844         return i;
845 }
846
847 int ast_extension_match(const char *pattern, const char *data)
848 {
849         return extension_match_core(pattern, data, E_MATCH);
850 }
851
852 int ast_extension_close(const char *pattern, const char *data, int needmore)
853 {
854         if (needmore != E_MATCHMORE && needmore != E_CANMATCH)
855                 ast_log(LOG_WARNING, "invalid argument %d\n", needmore);
856         return extension_match_core(pattern, data, needmore);
857 }
858
859 struct ast_context *ast_context_find(const char *name)
860 {
861         struct ast_context *tmp = NULL;
862         ast_mutex_lock(&conlock);
863         while ( (tmp = ast_walk_contexts(tmp)) ) {
864                 if (!name || !strcasecmp(name, tmp->name))
865                         break;
866         }
867         ast_mutex_unlock(&conlock);
868         return tmp;
869 }
870
871 #define STATUS_NO_CONTEXT       1
872 #define STATUS_NO_EXTENSION     2
873 #define STATUS_NO_PRIORITY      3
874 #define STATUS_NO_LABEL         4
875 #define STATUS_SUCCESS          5
876
877 static int matchcid(const char *cidpattern, const char *callerid)
878 {
879         /* If the Caller*ID pattern is empty, then we're matching NO Caller*ID, so
880            failing to get a number should count as a match, otherwise not */
881
882         if (ast_strlen_zero(callerid))
883                 return ast_strlen_zero(cidpattern) ? 1 : 0;
884
885         return ast_extension_match(cidpattern, callerid);
886 }
887
888 /* request and result for pbx_find_extension */
889 struct pbx_find_info {
890 #if 0
891         const char *context;
892         const char *exten;
893         int priority;
894 #endif
895
896         char *incstack[AST_PBX_MAX_STACK];      /* filled during the search */
897         int stacklen;                   /* modified during the search */
898         int status;                     /* set on return */
899         struct ast_switch *swo;         /* set on return */
900         const char *data;               /* set on return */
901         const char *foundcontext;       /* set on return */
902 };
903
904 static struct ast_exten *pbx_find_extension(struct ast_channel *chan,
905         struct ast_context *bypass, struct pbx_find_info *q,
906         const char *context, const char *exten, int priority,
907         const char *label, const char *callerid, enum ext_match_t action)
908 {
909         int x, res;
910         struct ast_context *tmp;
911         struct ast_exten *e, *eroot;
912         struct ast_include *i;
913         struct ast_sw *sw;
914
915         /* Initialize status if appropriate */
916         if (q->stacklen == 0) {
917                 q->status = STATUS_NO_CONTEXT;
918                 q->swo = NULL;
919                 q->data = NULL;
920                 q->foundcontext = NULL;
921         }
922         /* Check for stack overflow */
923         if (q->stacklen >= AST_PBX_MAX_STACK) {
924                 ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n");
925                 return NULL;
926         }
927         /* Check first to see if we've already been checked */
928         for (x = 0; x < q->stacklen; x++) {
929                 if (!strcasecmp(q->incstack[x], context))
930                         return NULL;
931         }
932         if (bypass)     /* bypass means we only look there */
933                 tmp = bypass;
934         else {  /* look in contexts */
935                 tmp = NULL;
936                 while ((tmp = ast_walk_contexts(tmp)) ) {
937                         if (!strcmp(tmp->name, context))
938                                 break;
939                 }
940                 if (!tmp)
941                         return NULL;
942         }
943         if (q->status < STATUS_NO_EXTENSION)
944                 q->status = STATUS_NO_EXTENSION;
945
946         /* scan the list trying to match extension and CID */
947         eroot = NULL;
948         while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) {
949                 int match = extension_match_core(eroot->exten, exten, action);
950                 /* 0 on fail, 1 on match, 2 on earlymatch */
951
952                 if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid)))
953                         continue;       /* keep trying */
954                 if (match == 2 && action == E_MATCHMORE) {
955                         /* We match an extension ending in '!'.
956                          * The decision in this case is final and is NULL (no match).
957                          */
958                         return NULL;
959                 }
960                 /* found entry, now look for the right priority */
961                 if (q->status < STATUS_NO_PRIORITY)
962                         q->status = STATUS_NO_PRIORITY;
963                 e = NULL;
964                 while ( (e = ast_walk_extension_priorities(eroot, e)) ) {
965                         /* Match label or priority */
966                         if (action == E_FINDLABEL) {
967                                 if (q->status < STATUS_NO_LABEL)
968                                         q->status = STATUS_NO_LABEL;
969                                 if (label && e->label && !strcmp(label, e->label))
970                                         break;  /* found it */
971                         } else if (e->priority == priority) {
972                                 break;  /* found it */
973                         } /* else keep searching */
974                 }
975                 if (e) {        /* found a valid match */
976                         q->status = STATUS_SUCCESS;
977                         q->foundcontext = context;
978                         return e;
979                 }
980         }
981         /* Check alternative switches */
982         AST_LIST_TRAVERSE(&tmp->alts, sw, list) {
983                 struct ast_switch *asw = pbx_findswitch(sw->name);
984                 ast_switch_f *aswf = NULL;
985                 char *datap;
986
987                 if (!asw) {
988                         ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name);
989                         continue;
990                 }
991                 /* Substitute variables now */
992                 if (sw->eval)
993                         pbx_substitute_variables_helper(chan, sw->data, sw->tmpdata, SWITCH_DATA_LENGTH - 1);
994
995                 /* equivalent of extension_match_core() at the switch level */
996                 if (action == E_CANMATCH)
997                         aswf = asw->canmatch;
998                 else if (action == E_MATCHMORE)
999                         aswf = asw->matchmore;
1000                 else /* action == E_MATCH */
1001                         aswf = asw->exists;
1002                 datap = sw->eval ? sw->tmpdata : sw->data;
1003                 res = !aswf ? 0 : aswf(chan, context, exten, priority, callerid, datap);
1004                 if (res) {      /* Got a match */
1005                         q->swo = asw;
1006                         q->data = datap;
1007                         q->foundcontext = context;
1008                         /* XXX keep status = STATUS_NO_CONTEXT ? */
1009                         return NULL;
1010                 }
1011         }
1012         q->incstack[q->stacklen++] = tmp->name; /* Setup the stack */
1013         /* Now try any includes we have in this context */
1014         for (i = tmp->includes; i; i = i->next) {
1015                 if (include_valid(i)) {
1016                         if ((e = pbx_find_extension(chan, bypass, q, i->rname, exten, priority, label, callerid, action)))
1017                                 return e;
1018                         if (q->swo)
1019                                 return NULL;
1020                 }
1021         }
1022         return NULL;
1023 }
1024
1025 /* Note that it's negative -- that's important later. */
1026 #define DONT_HAVE_LENGTH        0x80000000
1027
1028 /*! \brief extract offset:length from variable name.
1029  * Returns 1 if there is a offset:length part, which is
1030  * trimmed off (values go into variables)
1031  */
1032 static int parse_variable_name(char *var, int *offset, int *length, int *isfunc)
1033 {
1034         int parens=0;
1035
1036         *offset = 0;
1037         *length = DONT_HAVE_LENGTH;
1038         *isfunc = 0;
1039         for (; *var; var++) {
1040                 if (*var == '(') {
1041                         (*isfunc)++;
1042                         parens++;
1043                 } else if (*var == ')') {
1044                         parens--;
1045                 } else if (*var == ':' && parens == 0) {
1046                         *var++ = '\0';
1047                         sscanf(var, "%d:%d", offset, length);
1048                         return 1; /* offset:length valid */
1049                 }
1050         }
1051         return 0;
1052 }
1053
1054 /*! \brief takes a substring. It is ok to call with value == workspace.
1055  *
1056  * offset < 0 means start from the end of the string and set the beginning
1057  *   to be that many characters back.
1058  * length is the length of the substring, -1 means unlimited
1059  * (we take any negative value).
1060  * Always return a copy in workspace.
1061  */
1062 static char *substring(const char *value, int offset, int length, char *workspace, size_t workspace_len)
1063 {
1064         char *ret = workspace;
1065         int lr; /* length of the input string after the copy */
1066
1067         ast_copy_string(workspace, value, workspace_len); /* always make a copy */
1068
1069         /* Quick check if no need to do anything */
1070         if (offset == 0 && length < 0)  /* take the whole string */
1071                 return ret;
1072
1073         lr = strlen(ret); /* compute length after copy, so we never go out of the workspace */
1074
1075         if (offset < 0) {       /* translate negative offset into positive ones */
1076                 offset = lr + offset;
1077                 if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */
1078                         offset = 0;
1079         }
1080
1081         /* too large offset result in empty string so we know what to return */
1082         if (offset >= lr)
1083                 return ret + lr;        /* the final '\0' */
1084
1085         ret += offset;          /* move to the start position */
1086         if (length >= 0 && length < lr - offset)        /* truncate if necessary */
1087                 ret[length] = '\0';
1088
1089         return ret;
1090 }
1091
1092 /*! \brief  pbx_retrieve_variable: Support for Asterisk built-in variables and
1093       functions in the dialplan
1094   ---*/
1095 void pbx_retrieve_variable(struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp)
1096 {
1097         const char not_found = '\0';
1098         char *tmpvar;
1099         const char *s;  /* the result */
1100         int offset, length;
1101         int i, need_substring;
1102         struct varshead *places[2] = { headp, &globals };       /* list of places where we may look */
1103
1104         if (c) {
1105                 places[0] = &c->varshead;
1106         }
1107         /*
1108          * Make a copy of var because parse_variable_name() modifies the string.
1109          * Then if called directly, we might need to run substring() on the result;
1110          * remember this for later in 'need_substring', 'offset' and 'length'
1111          */
1112         tmpvar = ast_strdupa(var);      /* parse_variable_name modifies the string */
1113         need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */);
1114
1115         /*
1116          * Look first into predefined variables, then into variable lists.
1117          * Variable 's' points to the result, according to the following rules:
1118          * s == &not_found (set at the beginning) means that we did not find a
1119          *      matching variable and need to look into more places.
1120          * If s != &not_found, s is a valid result string as follows:
1121          * s = NULL if the variable does not have a value;
1122          *      you typically do this when looking for an unset predefined variable.
1123          * s = workspace if the result has been assembled there;
1124          *      typically done when the result is built e.g. with an snprintf(),
1125          *      so we don't need to do an additional copy.
1126          * s != workspace in case we have a string, that needs to be copied
1127          *      (the ast_copy_string is done once for all at the end).
1128          *      Typically done when the result is already available in some string.
1129          */
1130         s = &not_found; /* default value */
1131         if (c) {        /* This group requires a valid channel */
1132                 /* Names with common parts are looked up a piece at a time using strncmp. */
1133                 if (!strncmp(var, "CALL", 4)) {
1134                         if (!strncmp(var + 4, "ING", 3)) {
1135                                 if (!strcmp(var + 7, "PRES")) {                 /* CALLINGPRES */
1136                                         snprintf(workspace, workspacelen, "%d", c->cid.cid_pres);
1137                                         s = workspace;
1138                                 } else if (!strcmp(var + 7, "ANI2")) {          /* CALLINGANI2 */
1139                                         snprintf(workspace, workspacelen, "%d", c->cid.cid_ani2);
1140                                         s = workspace;
1141                                 } else if (!strcmp(var + 7, "TON")) {           /* CALLINGTON */
1142                                         snprintf(workspace, workspacelen, "%d", c->cid.cid_ton);
1143                                         s = workspace;
1144                                 } else if (!strcmp(var + 7, "TNS")) {           /* CALLINGTNS */
1145                                         snprintf(workspace, workspacelen, "%d", c->cid.cid_tns);
1146                                         s = workspace;
1147                                 }
1148                         }
1149                 } else if (!strcmp(var, "HINT")) {
1150                         s = ast_get_hint(workspace, workspacelen, NULL, 0, c, c->context, c->exten) ? workspace : NULL;
1151                 } else if (!strcmp(var, "HINTNAME")) {
1152                         s = ast_get_hint(NULL, 0, workspace, workspacelen, c, c->context, c->exten) ? workspace : NULL;
1153                 } else if (!strcmp(var, "EXTEN")) {
1154                         s = c->exten;
1155                 } else if (!strcmp(var, "CONTEXT")) {
1156                         s = c->context;
1157                 } else if (!strcmp(var, "PRIORITY")) {
1158                         snprintf(workspace, workspacelen, "%d", c->priority);
1159                         s = workspace;
1160                 } else if (!strcmp(var, "CHANNEL")) {
1161                         s = c->name;
1162                 } else if (!strcmp(var, "UNIQUEID")) {
1163                         s = c->uniqueid;
1164                 } else if (!strcmp(var, "HANGUPCAUSE")) {
1165                         snprintf(workspace, workspacelen, "%d", c->hangupcause);
1166                         s = workspace;
1167                 }
1168         }
1169         if (s == &not_found) { /* look for more */
1170                 if (!strcmp(var, "EPOCH")) {
1171                         snprintf(workspace, workspacelen, "%u",(int)time(NULL));
1172                         s = workspace;
1173                 } else if (!strcmp(var, "SYSTEMNAME")) {
1174                         s = ast_config_AST_SYSTEM_NAME;
1175                 }
1176         }
1177         /* if not found, look into chanvars or global vars */
1178         for (i = 0; s == &not_found && i < (sizeof(places) / sizeof(places[0])); i++) {
1179                 struct ast_var_t *variables;
1180                 if (!places[i])
1181                         continue;
1182                 if (places[i] == &globals)
1183                         ast_mutex_lock(&globalslock);
1184                 AST_LIST_TRAVERSE(places[i], variables, entries) {
1185                         if (strcasecmp(ast_var_name(variables), var)==0) {
1186                                 s = ast_var_value(variables);
1187                                 break;
1188                         }
1189                 }
1190                 if (places[i] == &globals)
1191                         ast_mutex_unlock(&globalslock);
1192         }
1193         if (s == &not_found || s == NULL)
1194                 *ret = NULL;
1195         else {
1196                 if (s != workspace)
1197                         ast_copy_string(workspace, s, workspacelen);
1198                 *ret = workspace;
1199                 if (need_substring)
1200                         *ret = substring(*ret, offset, length, workspace, workspacelen);
1201         }
1202 }
1203
1204 /*! \brief CLI function to show installed custom functions
1205     \addtogroup CLI_functions
1206  */
1207 static int handle_show_functions(int fd, int argc, char *argv[])
1208 {
1209         struct ast_custom_function *acf;
1210         int count_acf = 0;
1211         int like = 0;
1212
1213         if (argc == 4 && (!strcmp(argv[2], "like")) ) {
1214                 like = 1;
1215         } else if (argc != 2) {
1216                 return RESULT_SHOWUSAGE;
1217         }
1218
1219         ast_cli(fd, "%s Custom Functions:\n--------------------------------------------------------------------------------\n", like ? "Matching" : "Installed");
1220
1221         AST_LIST_LOCK(&acf_root);
1222         AST_LIST_TRAVERSE(&acf_root, acf, acflist) {
1223                 if (!like || strstr(acf->name, argv[3])) {
1224                         count_acf++;
1225                         ast_cli(fd, "%-20.20s  %-35.35s  %s\n", acf->name, acf->syntax, acf->synopsis);
1226                 }
1227         }
1228         AST_LIST_UNLOCK(&acf_root);
1229
1230         ast_cli(fd, "%d %scustom functions installed.\n", count_acf, like ? "matching " : "");
1231
1232         return RESULT_SUCCESS;
1233 }
1234
1235 static int handle_show_function(int fd, int argc, char *argv[])
1236 {
1237         struct ast_custom_function *acf;
1238         /* Maximum number of characters added by terminal coloring is 22 */
1239         char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40];
1240         char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL;
1241         char stxtitle[40], *syntax = NULL;
1242         int synopsis_size, description_size, syntax_size;
1243
1244         if (argc < 3)
1245                 return RESULT_SHOWUSAGE;
1246
1247         if (!(acf = ast_custom_function_find(argv[2]))) {
1248                 ast_cli(fd, "No function by that name registered.\n");
1249                 return RESULT_FAILURE;
1250
1251         }
1252
1253         if (acf->synopsis)
1254                 synopsis_size = strlen(acf->synopsis) + 23;
1255         else
1256                 synopsis_size = strlen("Not available") + 23;
1257         synopsis = alloca(synopsis_size);
1258
1259         if (acf->desc)
1260                 description_size = strlen(acf->desc) + 23;
1261         else
1262                 description_size = strlen("Not available") + 23;
1263         description = alloca(description_size);
1264
1265         if (acf->syntax)
1266                 syntax_size = strlen(acf->syntax) + 23;
1267         else
1268                 syntax_size = strlen("Not available") + 23;
1269         syntax = alloca(syntax_size);
1270
1271         snprintf(info, 64 + AST_MAX_APP, "\n  -= Info about function '%s' =- \n\n", acf->name);
1272         term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22);
1273         term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40);
1274         term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
1275         term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
1276         term_color(syntax,
1277                    acf->syntax ? acf->syntax : "Not available",
1278                    COLOR_CYAN, 0, syntax_size);
1279         term_color(synopsis,
1280                    acf->synopsis ? acf->synopsis : "Not available",
1281                    COLOR_CYAN, 0, synopsis_size);
1282         term_color(description,
1283                    acf->desc ? acf->desc : "Not available",
1284                    COLOR_CYAN, 0, description_size);
1285
1286         ast_cli(fd,"%s%s%s\n\n%s%s\n\n%s%s\n", infotitle, stxtitle, syntax, syntitle, synopsis, destitle, description);
1287
1288         return RESULT_SUCCESS;
1289 }
1290
1291 static char *complete_show_function(const char *line, const char *word, int pos, int state)
1292 {
1293         struct ast_custom_function *acf;
1294         char *ret = NULL;
1295         int which = 0;
1296         int wordlen = strlen(word);
1297
1298         /* case-insensitive for convenience in this 'complete' function */
1299         AST_LIST_LOCK(&acf_root);
1300         AST_LIST_TRAVERSE(&acf_root, acf, acflist) {
1301                 if (!strncasecmp(word, acf->name, wordlen) && ++which > state) {
1302                         ret = strdup(acf->name);
1303                         break;
1304                 }
1305         }
1306         AST_LIST_UNLOCK(&acf_root);
1307
1308         return ret;
1309 }
1310
1311 struct ast_custom_function *ast_custom_function_find(const char *name)
1312 {
1313         struct ast_custom_function *acf = NULL;
1314
1315         AST_LIST_LOCK(&acf_root);
1316         AST_LIST_TRAVERSE(&acf_root, acf, acflist) {
1317                 if (!strcmp(name, acf->name))
1318                         break;
1319         }
1320         AST_LIST_UNLOCK(&acf_root);
1321
1322         return acf;
1323 }
1324
1325 int ast_custom_function_unregister(struct ast_custom_function *acf)
1326 {
1327         struct ast_custom_function *cur;
1328
1329         if (!acf)
1330                 return -1;
1331
1332         AST_LIST_LOCK(&acf_root);
1333         AST_LIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) {
1334                 if (cur == acf) {
1335                         AST_LIST_REMOVE_CURRENT(&acf_root, acflist);
1336                         if (option_verbose > 1)
1337                                 ast_verbose(VERBOSE_PREFIX_2 "Unregistered custom function %s\n", acf->name);
1338                         break;
1339                 }
1340         }
1341         AST_LIST_TRAVERSE_SAFE_END
1342         AST_LIST_UNLOCK(&acf_root);
1343
1344         return acf ? 0 : -1;
1345 }
1346
1347 int ast_custom_function_register(struct ast_custom_function *acf)
1348 {
1349         struct ast_custom_function *cur;
1350
1351         if (!acf)
1352                 return -1;
1353
1354         AST_LIST_LOCK(&acf_root);
1355
1356         if (ast_custom_function_find(acf->name)) {
1357                 ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name);
1358                 AST_LIST_UNLOCK(&acf_root);
1359                 return -1;
1360         }
1361
1362         /* Store in alphabetical order */
1363         AST_LIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) {
1364                 if (strcasecmp(acf->name, cur->name) < 0) {
1365                         AST_LIST_INSERT_BEFORE_CURRENT(&acf_root, acf, acflist);
1366                         break;
1367                 }
1368         }
1369         AST_LIST_TRAVERSE_SAFE_END
1370         if (!cur)
1371                 AST_LIST_INSERT_TAIL(&acf_root, acf, acflist);
1372
1373         AST_LIST_UNLOCK(&acf_root);
1374
1375         if (option_verbose > 1)
1376                 ast_verbose(VERBOSE_PREFIX_2 "Registered custom function %s\n", acf->name);
1377
1378         return 0;
1379 }
1380
1381 /*! \brief return a pointer to the arguments of the function,
1382  * and terminates the function name with '\\0'
1383  */
1384 static char *func_args(char *function)
1385 {
1386         char *args = strchr(function, '(');
1387
1388         if (!args)
1389                 ast_log(LOG_WARNING, "Function doesn't contain parentheses.  Assuming null argument.\n");
1390         else {
1391                 char *p;
1392                 *args++ = '\0';
1393                 if ((p = strrchr(args, ')')) )
1394                         *p = '\0';
1395                 else
1396                         ast_log(LOG_WARNING, "Can't find trailing parenthesis?\n");
1397         }
1398         return args;
1399 }
1400
1401 int ast_func_read(struct ast_channel *chan, char *function, char *workspace, size_t len)
1402 {
1403         char *args = func_args(function);
1404         struct ast_custom_function *acfptr = ast_custom_function_find(function);
1405
1406         if (acfptr == NULL)
1407                 ast_log(LOG_ERROR, "Function %s not registered\n", function);
1408         else if (!acfptr->read)
1409                 ast_log(LOG_ERROR, "Function %s cannot be read\n", function);
1410         else
1411                 return acfptr->read(chan, function, args, workspace, len);
1412         return -1;
1413 }
1414
1415 int ast_func_write(struct ast_channel *chan, char *function, const char *value)
1416 {
1417         char *args = func_args(function);
1418         struct ast_custom_function *acfptr = ast_custom_function_find(function);
1419
1420         if (acfptr == NULL)
1421                 ast_log(LOG_ERROR, "Function %s not registered\n", function);
1422         else if (!acfptr->write)
1423                 ast_log(LOG_ERROR, "Function %s cannot be written to\n", function);
1424         else
1425                 return acfptr->write(chan, function, args, value);
1426
1427         return -1;
1428 }
1429
1430 static void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count)
1431 {
1432         /* Substitutes variables into cp2, based on string cp1, and assuming cp2 to be
1433            zero-filled */
1434         char *cp4;
1435         const char *tmp, *whereweare;
1436         int length, offset, offset2, isfunction;
1437         char *workspace = NULL;
1438         char *ltmp = NULL, *var = NULL;
1439         char *nextvar, *nextexp, *nextthing;
1440         char *vars, *vare;
1441         int pos, brackets, needsub, len;
1442
1443         whereweare=tmp=cp1;
1444         while (!ast_strlen_zero(whereweare) && count) {
1445                 /* Assume we're copying the whole remaining string */
1446                 pos = strlen(whereweare);
1447                 nextvar = NULL;
1448                 nextexp = NULL;
1449                 nextthing = strchr(whereweare, '$');
1450                 if (nextthing) {
1451                         switch(nextthing[1]) {
1452                         case '{':
1453                                 nextvar = nextthing;
1454                                 pos = nextvar - whereweare;
1455                                 break;
1456                         case '[':
1457                                 nextexp = nextthing;
1458                                 pos = nextexp - whereweare;
1459                                 break;
1460                         }
1461                 }
1462
1463                 if (pos) {
1464                         /* Can't copy more than 'count' bytes */
1465                         if (pos > count)
1466                                 pos = count;
1467
1468                         /* Copy that many bytes */
1469                         memcpy(cp2, whereweare, pos);
1470
1471                         count -= pos;
1472                         cp2 += pos;
1473                         whereweare += pos;
1474                 }
1475
1476                 if (nextvar) {
1477                         /* We have a variable.  Find the start and end, and determine
1478                            if we are going to have to recursively call ourselves on the
1479                            contents */
1480                         vars = vare = nextvar + 2;
1481                         brackets = 1;
1482                         needsub = 0;
1483
1484                         /* Find the end of it */
1485                         while (brackets && *vare) {
1486                                 if ((vare[0] == '$') && (vare[1] == '{')) {
1487                                         needsub++;
1488                                 } else if (vare[0] == '{') {
1489                                         brackets++;
1490                                 } else if (vare[0] == '}') {
1491                                         brackets--;
1492                                 } else if ((vare[0] == '$') && (vare[1] == '['))
1493                                         needsub++;
1494                                 vare++;
1495                         }
1496                         if (brackets)
1497                                 ast_log(LOG_NOTICE, "Error in extension logic (missing '}')\n");
1498                         len = vare - vars - 1;
1499
1500                         /* Skip totally over variable string */
1501                         whereweare += (len + 3);
1502
1503                         if (!var)
1504                                 var = alloca(VAR_BUF_SIZE);
1505
1506                         /* Store variable name (and truncate) */
1507                         ast_copy_string(var, vars, len + 1);
1508
1509                         /* Substitute if necessary */
1510                         if (needsub) {
1511                                 if (!ltmp)
1512                                         ltmp = alloca(VAR_BUF_SIZE);
1513
1514                                 memset(ltmp, 0, VAR_BUF_SIZE);
1515                                 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1);
1516                                 vars = ltmp;
1517                         } else {
1518                                 vars = var;
1519                         }
1520
1521                         if (!workspace)
1522                                 workspace = alloca(VAR_BUF_SIZE);
1523
1524                         workspace[0] = '\0';
1525
1526                         parse_variable_name(vars, &offset, &offset2, &isfunction);
1527                         if (isfunction) {
1528                                 /* Evaluate function */
1529                                 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
1530
1531                                 ast_log(LOG_DEBUG, "Function result is '%s'\n", cp4 ? cp4 : "(null)");
1532                         } else {
1533                                 /* Retrieve variable value */
1534                                 pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp);
1535                         }
1536                         if (cp4) {
1537                                 cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE);
1538
1539                                 length = strlen(cp4);
1540                                 if (length > count)
1541                                         length = count;
1542                                 memcpy(cp2, cp4, length);
1543                                 count -= length;
1544                                 cp2 += length;
1545                         }
1546                 } else if (nextexp) {
1547                         /* We have an expression.  Find the start and end, and determine
1548                            if we are going to have to recursively call ourselves on the
1549                            contents */
1550                         vars = vare = nextexp + 2;
1551                         brackets = 1;
1552                         needsub = 0;
1553
1554                         /* Find the end of it */
1555                         while(brackets && *vare) {
1556                                 if ((vare[0] == '$') && (vare[1] == '[')) {
1557                                         needsub++;
1558                                         brackets++;
1559                                         vare++;
1560                                 } else if (vare[0] == '[') {
1561                                         brackets++;
1562                                 } else if (vare[0] == ']') {
1563                                         brackets--;
1564                                 } else if ((vare[0] == '$') && (vare[1] == '{')) {
1565                                         needsub++;
1566                                         vare++;
1567                                 }
1568                                 vare++;
1569                         }
1570                         if (brackets)
1571                                 ast_log(LOG_NOTICE, "Error in extension logic (missing ']')\n");
1572                         len = vare - vars - 1;
1573
1574                         /* Skip totally over expression */
1575                         whereweare += (len + 3);
1576
1577                         if (!var)
1578                                 var = alloca(VAR_BUF_SIZE);
1579
1580                         /* Store variable name (and truncate) */
1581                         ast_copy_string(var, vars, len + 1);
1582
1583                         /* Substitute if necessary */
1584                         if (needsub) {
1585                                 if (!ltmp)
1586                                         ltmp = alloca(VAR_BUF_SIZE);
1587
1588                                 memset(ltmp, 0, VAR_BUF_SIZE);
1589                                 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1);
1590                                 vars = ltmp;
1591                         } else {
1592                                 vars = var;
1593                         }
1594
1595                         length = ast_expr(vars, cp2, count);
1596
1597                         if (length) {
1598                                 ast_log(LOG_DEBUG, "Expression result is '%s'\n", cp2);
1599                                 count -= length;
1600                                 cp2 += length;
1601                         }
1602                 } else
1603                         break;
1604         }
1605 }
1606
1607 void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count)
1608 {
1609         pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count);
1610 }
1611
1612 void pbx_substitute_variables_varshead(struct varshead *headp, const char *cp1, char *cp2, int count)
1613 {
1614         pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count);
1615 }
1616
1617 static void pbx_substitute_variables(char *passdata, int datalen, struct ast_channel *c, struct ast_exten *e)
1618 {
1619         memset(passdata, 0, datalen);
1620
1621         /* No variables or expressions in e->data, so why scan it? */
1622         if (!strchr(e->data, '$') && !strstr(e->data,"${") && !strstr(e->data,"$[") && !strstr(e->data,"$(")) {
1623                 ast_copy_string(passdata, e->data, datalen);
1624                 return;
1625         }
1626
1627         pbx_substitute_variables_helper(c, e->data, passdata, datalen - 1);
1628 }
1629
1630 /*! \brief The return value depends on the action:
1631  *
1632  * E_MATCH, E_CANMATCH, E_MATCHMORE require a real match,
1633  *      and return 0 on failure, -1 on match;
1634  * E_FINDLABEL maps the label to a priority, and returns
1635  *      the priority on success, ... XXX
1636  * E_SPAWN, spawn an application,
1637  *      and return 0 on success, -1 on failure.
1638  */
1639 static int pbx_extension_helper(struct ast_channel *c, struct ast_context *con,
1640         const char *context, const char *exten, int priority,
1641         const char *label, const char *callerid, enum ext_match_t action)
1642 {
1643         struct ast_exten *e;
1644         struct ast_app *app;
1645         int res;
1646         struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */
1647         char passdata[EXT_DATA_SIZE];
1648
1649         int matching_action = (action == E_MATCH || action == E_CANMATCH || action == E_MATCHMORE);
1650
1651         ast_mutex_lock(&conlock);
1652         e = pbx_find_extension(c, con, &q, context, exten, priority, label, callerid, action);
1653         if (e) {
1654                 if (matching_action) {
1655                         ast_mutex_unlock(&conlock);
1656                         return -1;      /* success, we found it */
1657                 } else if (action == E_FINDLABEL) { /* map the label to a priority */
1658                         res = e->priority;
1659                         ast_mutex_unlock(&conlock);
1660                         return res;     /* the priority we were looking for */
1661                 } else {        /* spawn */
1662                         app = pbx_findapp(e->app);
1663                         ast_mutex_unlock(&conlock);
1664                         if (!app) {
1665                                 ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority);
1666                                 return -1;
1667                         }
1668                         if (c->context != context)
1669                                 ast_copy_string(c->context, context, sizeof(c->context));
1670                         if (c->exten != exten)
1671                                 ast_copy_string(c->exten, exten, sizeof(c->exten));
1672                         c->priority = priority;
1673                         pbx_substitute_variables(passdata, sizeof(passdata), c, e);
1674                         if (option_debug) {
1675                                 char atmp[80];
1676                                 char atmp2[EXT_DATA_SIZE+100];
1677                                 ast_log(LOG_DEBUG, "Launching '%s'\n", app->name);
1678                                 snprintf(atmp, sizeof(atmp), "STACK-%s-%s-%d", context, exten, priority);
1679                                 snprintf(atmp2, sizeof(atmp2), "%s(\"%s\", \"%s\") %s",
1680                                         app->name, c->name, passdata, "in new stack");
1681                                 pbx_builtin_setvar_helper(c, atmp, atmp2);
1682                         }
1683                         if (option_verbose > 2) {
1684                                 char tmp[80], tmp2[80], tmp3[EXT_DATA_SIZE];
1685                                 ast_verbose( VERBOSE_PREFIX_3 "Executing [%s@%s:%d] %s(\"%s\", \"%s\") %s\n",
1686                                         exten, context, priority,
1687                                         term_color(tmp, app->name, COLOR_BRCYAN, 0, sizeof(tmp)),
1688                                         term_color(tmp2, c->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)),
1689                                         term_color(tmp3, passdata, COLOR_BRMAGENTA, 0, sizeof(tmp3)),
1690                                         "in new stack");
1691                         }
1692                         manager_event(EVENT_FLAG_CALL, "Newexten",
1693                                         "Channel: %s\r\n"
1694                                         "Context: %s\r\n"
1695                                         "Extension: %s\r\n"
1696                                         "Priority: %d\r\n"
1697                                         "Application: %s\r\n"
1698                                         "AppData: %s\r\n"
1699                                         "Uniqueid: %s\r\n",
1700                                         c->name, c->context, c->exten, c->priority, app->name, passdata, c->uniqueid);
1701                         return pbx_exec(c, app, passdata);      /* 0 on success, -1 on failure */
1702                 }
1703         } else if (q.swo) {     /* not found here, but in another switch */
1704                 ast_mutex_unlock(&conlock);
1705                 if (matching_action)
1706                         return -1;
1707                 else {
1708                         if (!q.swo->exec) {
1709                                 ast_log(LOG_WARNING, "No execution engine for switch %s\n", q.swo->name);
1710                                 res = -1;
1711                         }
1712                         return q.swo->exec(c, q.foundcontext ? q.foundcontext : context, exten, priority, callerid, q.data);
1713                 }
1714         } else {        /* not found anywhere, see what happened */
1715                 ast_mutex_unlock(&conlock);
1716                 switch (q.status) {
1717                 case STATUS_NO_CONTEXT:
1718                         if (!matching_action)
1719                                 ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", context);
1720                         break;
1721                 case STATUS_NO_EXTENSION:
1722                         if (!matching_action)
1723                                 ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, context);
1724                         break;
1725                 case STATUS_NO_PRIORITY:
1726                         if (!matching_action)
1727                                 ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, context);
1728                         break;
1729                 case STATUS_NO_LABEL:
1730                         if (context)
1731                                 ast_log(LOG_NOTICE, "No such label '%s' in extension '%s' in context '%s'\n", label, exten, context);
1732                         break;
1733                 default:
1734                         ast_log(LOG_DEBUG, "Shouldn't happen!\n");
1735                 }
1736
1737                 return (matching_action) ? 0 : -1;
1738         }
1739 }
1740
1741 /*! \brief  ast_hint_extension: Find hint for given extension in context */
1742 static struct ast_exten *ast_hint_extension(struct ast_channel *c, const char *context, const char *exten)
1743 {
1744         struct ast_exten *e;
1745         struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */
1746
1747         ast_mutex_lock(&conlock);
1748         e = pbx_find_extension(c, NULL, &q, context, exten, PRIORITY_HINT, NULL, "", E_MATCH);
1749         ast_mutex_unlock(&conlock);
1750
1751         return e;
1752 }
1753
1754 /*! \brief  ast_extensions_state2: Check state of extension by using hints */
1755 static int ast_extension_state2(struct ast_exten *e)
1756 {
1757         char hint[AST_MAX_EXTENSION];
1758         char *cur, *rest;
1759         int allunavailable = 1, allbusy = 1, allfree = 1, allonhold = 1;
1760         int busy = 0, inuse = 0, ring = 0;
1761
1762         if (!e)
1763                 return -1;
1764
1765         ast_copy_string(hint, ast_get_extension_app(e), sizeof(hint));
1766
1767         rest = hint;    /* One or more devices separated with a & character */
1768         while ( (cur = strsep(&rest, "&")) ) {
1769                 int res = ast_device_state(cur);
1770                 switch (res) {
1771                 case AST_DEVICE_NOT_INUSE:
1772                         allunavailable = 0;
1773                         allbusy = 0;
1774                         allonhold = 0;
1775                         break;
1776                 case AST_DEVICE_INUSE:
1777                         inuse = 1;
1778                         allunavailable = 0;
1779                         allfree = 0;
1780                         allonhold = 0;
1781                         break;
1782                 case AST_DEVICE_RINGING:
1783                         ring = 1;
1784                         allunavailable = 0;
1785                         allfree = 0;
1786                         allonhold = 0;
1787                         break;
1788                 case AST_DEVICE_RINGINUSE:
1789                         inuse = 1;
1790                         ring = 1;
1791                         allunavailable = 0;
1792                         allfree = 0;
1793                         allonhold = 0;
1794                         break;
1795                 case AST_DEVICE_ONHOLD:
1796                         allunavailable = 0;
1797                         allfree = 0;
1798                         break;
1799                 case AST_DEVICE_BUSY:
1800                         allunavailable = 0;
1801                         allfree = 0;
1802                         allonhold = 0;
1803                         busy = 1;
1804                         break;
1805                 case AST_DEVICE_UNAVAILABLE:
1806                 case AST_DEVICE_INVALID:
1807                         allbusy = 0;
1808                         allfree = 0;
1809                         allonhold = 0;
1810                         break;
1811                 default:
1812                         allunavailable = 0;
1813                         allbusy = 0;
1814                         allfree = 0;
1815                         allonhold = 0;
1816                 }
1817         }
1818
1819         if (!inuse && ring)
1820                 return AST_EXTENSION_RINGING;
1821         if (inuse && ring)
1822                 return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING);
1823         if (inuse)
1824                 return AST_EXTENSION_INUSE;
1825         if (allfree)
1826                 return AST_EXTENSION_NOT_INUSE;
1827         if (allonhold)
1828                 return AST_EXTENSION_ONHOLD;
1829         if (allbusy)
1830                 return AST_EXTENSION_BUSY;
1831         if (allunavailable)
1832                 return AST_EXTENSION_UNAVAILABLE;
1833         if (busy)
1834                 return AST_EXTENSION_INUSE;
1835
1836         return AST_EXTENSION_NOT_INUSE;
1837 }
1838
1839 /*! \brief  ast_extension_state2str: Return extension_state as string */
1840 const char *ast_extension_state2str(int extension_state)
1841 {
1842         int i;
1843
1844         for (i = 0; (i < (sizeof(extension_states) / sizeof(extension_states[0]))); i++) {
1845                 if (extension_states[i].extension_state == extension_state)
1846                         return extension_states[i].text;
1847         }
1848         return "Unknown";
1849 }
1850
1851 /*! \brief  ast_extension_state: Check extension state for an extension by using hint */
1852 int ast_extension_state(struct ast_channel *c, const char *context, const char *exten)
1853 {
1854         struct ast_exten *e;
1855
1856         e = ast_hint_extension(c, context, exten);      /* Do we have a hint for this extension ? */
1857         if (!e)
1858                 return -1;                              /* No hint, return -1 */
1859
1860         return ast_extension_state2(e);                 /* Check all devices in the hint */
1861 }
1862
1863 void ast_hint_state_changed(const char *device)
1864 {
1865         struct ast_hint *hint;
1866
1867         AST_LIST_LOCK(&hints);
1868
1869         AST_LIST_TRAVERSE(&hints, hint, list) {
1870                 struct ast_state_cb *cblist;
1871                 char buf[AST_MAX_EXTENSION];
1872                 char *parse = buf;
1873                 char *cur;
1874                 int state;
1875
1876                 ast_copy_string(buf, ast_get_extension_app(hint->exten), sizeof(buf));
1877                 while ( (cur = strsep(&parse, "&")) ) {
1878                         if (!strcasecmp(cur, device))
1879                                 break;
1880                 }
1881                 if (!cur)
1882                         continue;
1883
1884                 /* Get device state for this hint */
1885                 state = ast_extension_state2(hint->exten);
1886
1887                 if ((state == -1) || (state == hint->laststate))
1888                         continue;
1889
1890                 /* Device state changed since last check - notify the watchers */
1891
1892                 /* For general callbacks */
1893                 for (cblist = statecbs; cblist; cblist = cblist->next)
1894                         cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data);
1895
1896                 /* For extension callbacks */
1897                 for (cblist = hint->callbacks; cblist; cblist = cblist->next)
1898                         cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data);
1899
1900                 hint->laststate = state;        /* record we saw the change */
1901         }
1902
1903         AST_LIST_UNLOCK(&hints);
1904 }
1905
1906 /*! \brief  ast_extension_state_add: Add watcher for extension states */
1907 int ast_extension_state_add(const char *context, const char *exten,
1908                             ast_state_cb_type callback, void *data)
1909 {
1910         struct ast_hint *hint;
1911         struct ast_state_cb *cblist;
1912         struct ast_exten *e;
1913
1914         /* If there's no context and extension:  add callback to statecbs list */
1915         if (!context && !exten) {
1916                 AST_LIST_LOCK(&hints);
1917
1918                 for (cblist = statecbs; cblist; cblist = cblist->next) {
1919                         if (cblist->callback == callback) {
1920                                 cblist->data = data;
1921                                 AST_LIST_UNLOCK(&hints);
1922                                 return 0;
1923                         }
1924                 }
1925
1926                 /* Now insert the callback */
1927                 if (!(cblist = ast_calloc(1, sizeof(*cblist)))) {
1928                         AST_LIST_UNLOCK(&hints);
1929                         return -1;
1930                 }
1931                 cblist->id = 0;
1932                 cblist->callback = callback;
1933                 cblist->data = data;
1934
1935                 cblist->next = statecbs;
1936                 statecbs = cblist;
1937
1938                 AST_LIST_UNLOCK(&hints);
1939                 return 0;
1940         }
1941
1942         if (!context || !exten)
1943                 return -1;
1944
1945         /* This callback type is for only one hint, so get the hint */
1946         e = ast_hint_extension(NULL, context, exten);
1947         if (!e) {
1948                 return -1;
1949         }
1950
1951         /* Find the hint in the list of hints */
1952         AST_LIST_LOCK(&hints);
1953
1954         AST_LIST_TRAVERSE(&hints, hint, list) {
1955                 if (hint->exten == e)
1956                         break;
1957         }
1958
1959         if (!hint) {
1960                 /* We have no hint, sorry */
1961                 AST_LIST_UNLOCK(&hints);
1962                 return -1;
1963         }
1964
1965         /* Now insert the callback in the callback list  */
1966         if (!(cblist = ast_calloc(1, sizeof(*cblist)))) {
1967                 AST_LIST_UNLOCK(&hints);
1968                 return -1;
1969         }
1970         cblist->id = stateid++;         /* Unique ID for this callback */
1971         cblist->callback = callback;    /* Pointer to callback routine */
1972         cblist->data = data;            /* Data for the callback */
1973
1974         cblist->next = hint->callbacks;
1975         hint->callbacks = cblist;
1976
1977         AST_LIST_UNLOCK(&hints);
1978         return cblist->id;
1979 }
1980
1981 /*! \brief  ast_extension_state_del: Remove a watcher from the callback list */
1982 int ast_extension_state_del(int id, ast_state_cb_type callback)
1983 {
1984         struct ast_state_cb **p_cur = NULL;     /* address of pointer to us */
1985         int ret = -1;
1986
1987         if (!id && !callback)
1988                 return -1;
1989
1990         AST_LIST_LOCK(&hints);
1991
1992         if (!id) {      /* id == 0 is a callback without extension */
1993                 for (p_cur = &statecbs; *p_cur; p_cur = &(*p_cur)->next) {
1994                         if ((*p_cur)->callback == callback)
1995                                 break;
1996                 }
1997         } else { /* callback with extension, find the callback based on ID */
1998                 struct ast_hint *hint;
1999                 AST_LIST_TRAVERSE(&hints, hint, list) {
2000                         for (p_cur = &hint->callbacks; *p_cur; p_cur = &(*p_cur)->next) {
2001                                 if ((*p_cur)->id == id)
2002                                         break;
2003                         }
2004                         if (*p_cur)     /* found in the inner loop */
2005                                 break;
2006                 }
2007         }
2008         if (p_cur && *p_cur) {
2009                 struct ast_state_cb *cur = *p_cur;
2010                 *p_cur = cur->next;
2011                 free(cur);
2012                 ret = 0;
2013         }
2014         AST_LIST_UNLOCK(&hints);
2015         return ret;
2016 }
2017
2018 /*! \brief  ast_add_hint: Add hint to hint list, check initial extension state */
2019 static int ast_add_hint(struct ast_exten *e)
2020 {
2021         struct ast_hint *hint;
2022
2023         if (!e)
2024                 return -1;
2025
2026         AST_LIST_LOCK(&hints);
2027
2028         /* Search if hint exists, do nothing */
2029         AST_LIST_TRAVERSE(&hints, hint, list) {
2030                 if (hint->exten == e) {
2031                         AST_LIST_UNLOCK(&hints);
2032                         if (option_debug > 1)
2033                                 ast_log(LOG_DEBUG, "HINTS: Not re-adding existing hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e));
2034                         return -1;
2035                 }
2036         }
2037
2038         if (option_debug > 1)
2039                 ast_log(LOG_DEBUG, "HINTS: Adding hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e));
2040
2041         if (!(hint = ast_calloc(1, sizeof(*hint)))) {
2042                 AST_LIST_UNLOCK(&hints);
2043                 return -1;
2044         }
2045         /* Initialize and insert new item at the top */
2046         hint->exten = e;
2047         hint->laststate = ast_extension_state2(e);
2048         AST_LIST_INSERT_HEAD(&hints, hint, list);
2049
2050         AST_LIST_UNLOCK(&hints);
2051         return 0;
2052 }
2053
2054 /*! \brief  ast_change_hint: Change hint for an extension */
2055 static int ast_change_hint(struct ast_exten *oe, struct ast_exten *ne)
2056 {
2057         struct ast_hint *hint;
2058         int res = -1;
2059
2060         AST_LIST_LOCK(&hints);
2061         AST_LIST_TRAVERSE(&hints, hint, list) {
2062                 if (hint->exten == oe) {
2063                         hint->exten = ne;
2064                         res = 0;
2065                         break;
2066                 }
2067         }
2068         AST_LIST_UNLOCK(&hints);
2069
2070         return res;
2071 }
2072
2073 /*! \brief  ast_remove_hint: Remove hint from extension */
2074 static int ast_remove_hint(struct ast_exten *e)
2075 {
2076         /* Cleanup the Notifys if hint is removed */
2077         struct ast_hint *hint;
2078         struct ast_state_cb *cblist, *cbprev;
2079         int res = -1;
2080
2081         if (!e)
2082                 return -1;
2083
2084         AST_LIST_LOCK(&hints);
2085         AST_LIST_TRAVERSE_SAFE_BEGIN(&hints, hint, list) {
2086                 if (hint->exten == e) {
2087                         cbprev = NULL;
2088                         cblist = hint->callbacks;
2089                         while (cblist) {
2090                                 /* Notify with -1 and remove all callbacks */
2091                                 cbprev = cblist;
2092                                 cblist = cblist->next;
2093                                 cbprev->callback(hint->exten->parent->name, hint->exten->exten, AST_EXTENSION_DEACTIVATED, cbprev->data);
2094                                 free(cbprev);
2095                         }
2096                         hint->callbacks = NULL;
2097                         AST_LIST_REMOVE_CURRENT(&hints, list);
2098                         free(hint);
2099                         res = 0;
2100                         break;
2101                 }
2102         }
2103         AST_LIST_TRAVERSE_SAFE_END
2104         AST_LIST_UNLOCK(&hints);
2105
2106         return res;
2107 }
2108
2109
2110 /*! \brief  ast_get_hint: Get hint for channel */
2111 int ast_get_hint(char *hint, int hintsize, char *name, int namesize, struct ast_channel *c, const char *context, const char *exten)
2112 {
2113         struct ast_exten *e = ast_hint_extension(c, context, exten);
2114
2115         if (e) {
2116                 if (hint)
2117                         ast_copy_string(hint, ast_get_extension_app(e), hintsize);
2118                 if (name) {
2119                         const char *tmp = ast_get_extension_app_data(e);
2120                         if (tmp)
2121                                 ast_copy_string(name, tmp, namesize);
2122                 }
2123                 return -1;
2124         }
2125         return 0;
2126 }
2127
2128 int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
2129 {
2130         return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH);
2131 }
2132
2133 int ast_findlabel_extension(struct ast_channel *c, const char *context, const char *exten, const char *label, const char *callerid)
2134 {
2135         return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL);
2136 }
2137
2138 int ast_findlabel_extension2(struct ast_channel *c, struct ast_context *con, const char *exten, const char *label, const char *callerid)
2139 {
2140         return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL);
2141 }
2142
2143 int ast_canmatch_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
2144 {
2145         return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH);
2146 }
2147
2148 int ast_matchmore_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
2149 {
2150         return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE);
2151 }
2152
2153 int ast_spawn_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
2154 {
2155         return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN);
2156 }
2157
2158 /* helper function to set extension and priority */
2159 static void set_ext_pri(struct ast_channel *c, const char *exten, int pri)
2160 {
2161         ast_copy_string(c->exten, exten, sizeof(c->exten));
2162         c->priority = pri;
2163 }
2164
2165 /*!
2166  * \brief collect digits from the channel into the buffer,
2167  * return -1 on error, 0 on timeout or done.
2168  */
2169 static int collect_digits(struct ast_channel *c, int waittime, char *buf, int buflen, int pos)
2170 {
2171         int digit;
2172
2173         buf[pos] = '\0';        /* make sure it is properly terminated */
2174         while (ast_matchmore_extension(c, c->context, buf, 1, c->cid.cid_num)) {
2175                 /* As long as we're willing to wait, and as long as it's not defined,
2176                    keep reading digits until we can't possibly get a right answer anymore.  */
2177                 digit = ast_waitfordigit(c, waittime * 1000);
2178                 if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
2179                         c->_softhangup = 0;
2180                 } else {
2181                         if (!digit)     /* No entry */
2182                                 break;
2183                         if (digit < 0)  /* Error, maybe a  hangup */
2184                                 return -1;
2185                         if (pos < buflen - 1) { /* XXX maybe error otherwise ? */
2186                                 buf[pos++] = digit;
2187                                 buf[pos] = '\0';
2188                         }
2189                         waittime = c->pbx->dtimeout;
2190                 }
2191         }
2192         return 0;
2193 }
2194
2195 static int __ast_pbx_run(struct ast_channel *c)
2196 {
2197         int found = 0;  /* set if we find at least one match */
2198         int res = 0;
2199         int autoloopflag;
2200         int error = 0;          /* set an error conditions */
2201
2202         /* A little initial setup here */
2203         if (c->pbx) {
2204                 ast_log(LOG_WARNING, "%s already has PBX structure??\n", c->name);
2205                 /* XXX and now what ? */
2206                 free(c->pbx);
2207         }
2208         if (!(c->pbx = ast_calloc(1, sizeof(*c->pbx))))
2209                 return -1;
2210         if (c->amaflags) {
2211                 if (!c->cdr) {
2212                         c->cdr = ast_cdr_alloc();
2213                         if (!c->cdr) {
2214                                 ast_log(LOG_WARNING, "Unable to create Call Detail Record\n");
2215                                 free(c->pbx);
2216                                 return -1;
2217                         }
2218                         ast_cdr_init(c->cdr, c);
2219                 }
2220         }
2221         /* Set reasonable defaults */
2222         c->pbx->rtimeout = 10;
2223         c->pbx->dtimeout = 5;
2224
2225         autoloopflag = ast_test_flag(c, AST_FLAG_IN_AUTOLOOP);  /* save value to restore at the end */
2226         ast_set_flag(c, AST_FLAG_IN_AUTOLOOP);
2227
2228         /* Start by trying whatever the channel is set to */
2229         if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) {
2230                 /* If not successful fall back to 's' */
2231                 if (option_verbose > 1)
2232                         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);
2233                 /* XXX the original code used the existing priority in the call to
2234                  * ast_exists_extension(), and reset it to 1 afterwards.
2235                  * I believe the correct thing is to set it to 1 immediately.
2236                  */
2237                 set_ext_pri(c, "s", 1);
2238                 if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) {
2239                         /* JK02: And finally back to default if everything else failed */
2240                         if (option_verbose > 1)
2241                                 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);
2242                         ast_copy_string(c->context, "default", sizeof(c->context));
2243                 }
2244         }
2245         if (c->cdr && ast_tvzero(c->cdr->start))
2246                 ast_cdr_start(c->cdr);
2247         for (;;) {
2248                 char dst_exten[256];    /* buffer to accumulate digits */
2249                 int pos = 0;            /* XXX should check bounds */
2250                 int digit = 0;
2251
2252                 /* loop on priorities in this context/exten */
2253                 while (ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) {
2254                         found = 1;
2255                         if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num))) {
2256                                 /* Something bad happened, or a hangup has been requested. */
2257                                 if (strchr("0123456789ABCDEF*#", res)) {
2258                                         ast_log(LOG_DEBUG, "Oooh, got something to jump out with ('%c')!\n", res);
2259                                         pos = 0;
2260                                         dst_exten[pos++] = digit = res;
2261                                         dst_exten[pos] = '\0';
2262                                         break;
2263                                 }
2264                                 if (res == AST_PBX_KEEPALIVE) {
2265                                         if (option_debug)
2266                                                 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
2267                                         else if (option_verbose > 1)
2268                                                 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
2269                                         error = 1;
2270                                         break;
2271                                 }
2272                                 if (option_debug)
2273                                         ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
2274                                 else if (option_verbose > 1)
2275                                         ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
2276                                 if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
2277                                         c->_softhangup =0;
2278                                 } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) {
2279                                         /* atimeout, nothing bad */
2280                                 } else {
2281                                         if (c->cdr)
2282                                                 ast_cdr_update(c);
2283                                         error = 1;
2284                                         break;
2285                                 }
2286                         }
2287                         if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT && ast_exists_extension(c,c->context,"T",1,c->cid.cid_num)) {
2288                                 set_ext_pri(c, "T", 0); /* 0 will become 1 with the c->priority++; at the end */
2289                                 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
2290                                 c->whentohangup = 0;
2291                                 c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT;
2292                         } else if (c->_softhangup) {
2293                                 ast_log(LOG_DEBUG, "Extension %s, priority %d returned normally even though call was hung up\n",
2294                                         c->exten, c->priority);
2295                                 error = 1;
2296                                 break;
2297                         }
2298                         c->priority++;
2299                 } /* end while  - from here on we can use 'break' to go out */
2300                 if (error)
2301                         break;
2302
2303                 /* XXX we get here on non-existing extension or a keypress or hangup ? */
2304
2305                 if (!ast_exists_extension(c, c->context, c->exten, 1, c->cid.cid_num)) {
2306                         /* If there is no match at priority 1, it is not a valid extension anymore.
2307                          * Try to continue at "i", 1 or exit if the latter does not exist.
2308                          */
2309                         if (ast_exists_extension(c, c->context, "i", 1, c->cid.cid_num)) {
2310                                 if (option_verbose > 2)
2311                                         ast_verbose(VERBOSE_PREFIX_3 "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, c->name);
2312                                 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", c->exten);
2313                                 set_ext_pri(c, "i", 1);
2314                         } else {
2315                                 ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n",
2316                                         c->name, c->exten, c->context);
2317                                 error = 1; /* we know what to do with it */
2318                                 break;
2319                         }
2320                 } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) {
2321                         /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */
2322                         c->_softhangup = 0;
2323                 } else {        /* keypress received, get more digits for a full extension */
2324                         int waittime = 0;
2325                         if (digit)
2326                                 waittime = c->pbx->dtimeout;
2327                         else if (!autofallthrough)
2328                                 waittime = c->pbx->rtimeout;
2329                         if (!waittime) {
2330                                 const char *status = pbx_builtin_getvar_helper(c, "DIALSTATUS");
2331                                 if (!status)
2332                                         status = "UNKNOWN";
2333                                 if (option_verbose > 2)
2334                                         ast_verbose(VERBOSE_PREFIX_2 "Auto fallthrough, channel '%s' status is '%s'\n", c->name, status);
2335                                 if (!strcasecmp(status, "CONGESTION"))
2336                                         res = pbx_builtin_congestion(c, "10");
2337                                 else if (!strcasecmp(status, "CHANUNAVAIL"))
2338                                         res = pbx_builtin_congestion(c, "10");
2339                                 else if (!strcasecmp(status, "BUSY"))
2340                                         res = pbx_builtin_busy(c, "10");
2341                                 error = 1; /* XXX disable message */
2342                                 break;  /* exit from the 'for' loop */
2343                         }
2344
2345                         if (collect_digits(c, waittime, dst_exten, sizeof(dst_exten), pos))
2346                                 break;
2347                         if (ast_exists_extension(c, c->context, dst_exten, 1, c->cid.cid_num)) /* Prepare the next cycle */
2348                                 set_ext_pri(c, dst_exten, 1);
2349                         else {
2350                                 /* No such extension */
2351                                 if (!ast_strlen_zero(dst_exten)) {
2352                                         /* An invalid extension */
2353                                         if (ast_exists_extension(c, c->context, "i", 1, c->cid.cid_num)) {
2354                                                 if (option_verbose > 2)
2355                                                         ast_verbose( VERBOSE_PREFIX_3 "Invalid extension '%s' in context '%s' on %s\n", dst_exten, c->context, c->name);
2356                                                 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", dst_exten);
2357                                                 set_ext_pri(c, "i", 1);
2358                                         } else {
2359                                                 ast_log(LOG_WARNING, "Invalid extension '%s', but no rule 'i' in context '%s'\n", dst_exten, c->context);
2360                                                 found = 1; /* XXX disable message */
2361                                                 break;
2362                                         }
2363                                 } else {
2364                                         /* A simple timeout */
2365                                         if (ast_exists_extension(c, c->context, "t", 1, c->cid.cid_num)) {
2366                                                 if (option_verbose > 2)
2367                                                         ast_verbose( VERBOSE_PREFIX_3 "Timeout on %s\n", c->name);
2368                                                 set_ext_pri(c, "t", 1);
2369                                         } else {
2370                                                 ast_log(LOG_WARNING, "Timeout, but no rule 't' in context '%s'\n", c->context);
2371                                                 found = 1; /* XXX disable message */
2372                                                 break;
2373                                         }
2374                                 }
2375                         }
2376                         if (c->cdr) {
2377                                 if (option_verbose > 2)
2378                                         ast_verbose(VERBOSE_PREFIX_2 "CDR updated on %s\n",c->name);
2379                                 ast_cdr_update(c);
2380                         }
2381                 }
2382         }
2383         if (!found && !error)
2384                 ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name);
2385         if ((res != AST_PBX_KEEPALIVE) && ast_exists_extension(c, c->context, "h", 1, c->cid.cid_num)) {
2386                 if (c->cdr && ast_opt_end_cdr_before_h_exten)
2387                         ast_cdr_end(c->cdr);
2388                 set_ext_pri(c, "h", 1);
2389                 while(ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) {
2390                         if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num))) {
2391                                 /* Something bad happened, or a hangup has been requested. */
2392                                 if (option_debug)
2393                                         ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
2394                                 else if (option_verbose > 1)
2395                                         ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
2396                                 break;
2397                         }
2398                         c->priority++;
2399                 }
2400         }
2401         ast_set2_flag(c, autoloopflag, AST_FLAG_IN_AUTOLOOP);
2402
2403         pbx_destroy(c->pbx);
2404         c->pbx = NULL;
2405         if (res != AST_PBX_KEEPALIVE)
2406                 ast_hangup(c);
2407         return 0;
2408 }
2409
2410 /* Returns 0 on success, non-zero if call limit was reached */
2411 static int increase_call_count(const struct ast_channel *c)
2412 {
2413         int failed = 0;
2414         double curloadavg;
2415         ast_mutex_lock(&maxcalllock);
2416         if (option_maxcalls) {
2417                 if (countcalls >= option_maxcalls) {
2418                         ast_log(LOG_NOTICE, "Maximum call limit of %d calls exceeded by '%s'!\n", option_maxcalls, c->name);
2419                         failed = -1;
2420                 }
2421         }
2422         if (option_maxload) {
2423                 getloadavg(&curloadavg, 1);
2424                 if (curloadavg >= option_maxload) {
2425                         ast_log(LOG_NOTICE, "Maximum loadavg limit of %f load exceeded by '%s' (currently %f)!\n", option_maxload, c->name, curloadavg);
2426                         failed = -1;
2427                 }
2428         }
2429         if (!failed)
2430                 countcalls++;
2431         ast_mutex_unlock(&maxcalllock);
2432
2433         return failed;
2434 }
2435
2436 static void decrease_call_count(void)
2437 {
2438         ast_mutex_lock(&maxcalllock);
2439         if (countcalls > 0)
2440                 countcalls--;
2441         ast_mutex_unlock(&maxcalllock);
2442 }
2443
2444 static void destroy_exten(struct ast_exten *e)
2445 {
2446         if (e->priority == PRIORITY_HINT)
2447                 ast_remove_hint(e);
2448
2449         if (e->datad)
2450                 e->datad(e->data);
2451         free(e);
2452 }
2453
2454 static void *pbx_thread(void *data)
2455 {
2456         /* Oh joyeous kernel, we're a new thread, with nothing to do but
2457            answer this channel and get it going.
2458         */
2459         /* NOTE:
2460            The launcher of this function _MUST_ increment 'countcalls'
2461            before invoking the function; it will be decremented when the
2462            PBX has finished running on the channel
2463          */
2464         struct ast_channel *c = data;
2465
2466         __ast_pbx_run(c);
2467         decrease_call_count();
2468
2469         pthread_exit(NULL);
2470
2471         return NULL;
2472 }
2473
2474 enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
2475 {
2476         pthread_t t;
2477         pthread_attr_t attr;
2478
2479         if (!c) {
2480                 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
2481                 return AST_PBX_FAILED;
2482         }
2483
2484         if (increase_call_count(c))
2485                 return AST_PBX_CALL_LIMIT;
2486
2487         /* Start a new thread, and get something handling this channel. */
2488         pthread_attr_init(&attr);
2489         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
2490         if (ast_pthread_create(&t, &attr, pbx_thread, c)) {
2491                 ast_log(LOG_WARNING, "Failed to create new channel thread\n");
2492                 return AST_PBX_FAILED;
2493         }
2494
2495         return AST_PBX_SUCCESS;
2496 }
2497
2498 enum ast_pbx_result ast_pbx_run(struct ast_channel *c)
2499 {
2500         enum ast_pbx_result res = AST_PBX_SUCCESS;
2501
2502         if (increase_call_count(c))
2503                 return AST_PBX_CALL_LIMIT;
2504
2505         res = __ast_pbx_run(c);
2506         decrease_call_count();
2507
2508         return res;
2509 }
2510
2511 int ast_active_calls(void)
2512 {
2513         return countcalls;
2514 }
2515
2516 int pbx_set_autofallthrough(int newval)
2517 {
2518         int oldval = autofallthrough;
2519         autofallthrough = newval;
2520         return oldval;
2521 }
2522
2523 /* lookup for a context with a given name,
2524  * return with conlock held if found, NULL if not found
2525  */
2526 static struct ast_context *find_context_locked(const char *context)
2527 {
2528         struct ast_context *c = NULL;
2529
2530         ast_lock_contexts();
2531         while ( (c = ast_walk_contexts(c)) ) {
2532                 if (!strcmp(ast_get_context_name(c), context))
2533                         return c;
2534         }
2535         ast_unlock_contexts();
2536
2537         return NULL;
2538 }
2539
2540 /*
2541  * This function locks contexts list by &conlist, search for the right context
2542  * structure, leave context list locked and call ast_context_remove_include2
2543  * which removes include, unlock contexts list and return ...
2544  */
2545 int ast_context_remove_include(const char *context, const char *include, const char *registrar)
2546 {
2547         int ret = -1;
2548         struct ast_context *c = find_context_locked(context);
2549
2550         if (c) {
2551                 /* found, remove include from this context ... */
2552                 ret = ast_context_remove_include2(c, include, registrar);
2553                 ast_unlock_contexts();
2554         }
2555         return ret;
2556 }
2557
2558 /*
2559  * When we call this function, &conlock lock must be locked, because when
2560  * we giving *con argument, some process can remove/change this context
2561  * and after that there can be segfault.
2562  *
2563  * This function locks given context, removes include, unlock context and
2564  * return.
2565  */
2566 int ast_context_remove_include2(struct ast_context *con, const char *include, const char *registrar)
2567 {
2568         struct ast_include *i, *pi = NULL;
2569         int ret = -1;
2570
2571         ast_mutex_lock(&con->lock);
2572
2573         /* find our include */
2574         for (i = con->includes; i; pi = i, i = i->next) {
2575                 if (!strcmp(i->name, include) &&
2576                                 (!registrar || !strcmp(i->registrar, registrar))) {
2577                         /* remove from list */
2578                         if (pi)
2579                                 pi->next = i->next;
2580                         else
2581                                 con->includes = i->next;
2582                         /* free include and return */
2583                         free(i);
2584                         ret = 0;
2585                         break;
2586                 }
2587         }
2588
2589         ast_mutex_unlock(&con->lock);
2590         return ret;
2591 }
2592
2593 /*!
2594  * \note This function locks contexts list by &conlist, search for the rigt context
2595  * structure, leave context list locked and call ast_context_remove_switch2
2596  * which removes switch, unlock contexts list and return ...
2597  */
2598 int ast_context_remove_switch(const char *context, const char *sw, const char *data, const char *registrar)
2599 {
2600         int ret = -1; /* default error return */
2601         struct ast_context *c = find_context_locked(context);
2602
2603         if (c) {
2604                 /* remove switch from this context ... */
2605                 ret = ast_context_remove_switch2(c, sw, data, registrar);
2606                 ast_unlock_contexts();
2607         }
2608         return ret;
2609 }
2610
2611 /*!
2612  * \brief This function locks given context, removes switch, unlock context and
2613  * return.
2614  * \note When we call this function, &conlock lock must be locked, because when
2615  * we giving *con argument, some process can remove/change this context
2616  * and after that there can be segfault.
2617  *
2618  */
2619 int ast_context_remove_switch2(struct ast_context *con, const char *sw, const char *data, const char *registrar)
2620 {
2621         struct ast_sw *i;
2622         int ret = -1;
2623
2624         ast_mutex_lock(&con->lock);
2625
2626         /* walk switches */
2627         AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) {
2628                 if (!strcmp(i->name, sw) && !strcmp(i->data, data) &&
2629                         (!registrar || !strcmp(i->registrar, registrar))) {
2630                         /* found, remove from list */
2631                         AST_LIST_REMOVE_CURRENT(&con->alts, list);
2632                         free(i); /* free switch and return */
2633                         ret = 0;
2634                         break;
2635                 }
2636         }
2637         AST_LIST_TRAVERSE_SAFE_END
2638
2639         ast_mutex_unlock(&con->lock);
2640
2641         return ret;
2642 }
2643
2644 /*
2645  * \note This functions lock contexts list, search for the right context,
2646  * call ast_context_remove_extension2, unlock contexts list and return.
2647  * In this function we are using
2648  */
2649 int ast_context_remove_extension(const char *context, const char *extension, int priority, const char *registrar)
2650 {
2651         int ret = -1; /* default error return */
2652         struct ast_context *c = find_context_locked(context);
2653
2654         if (c) { /* ... remove extension ... */
2655                 ret = ast_context_remove_extension2(c, extension, priority, registrar);
2656                 ast_unlock_contexts();
2657         }
2658         return ret;
2659 }
2660
2661 /*!
2662  * \brief This functionc locks given context, search for the right extension and
2663  * fires out all peer in this extensions with given priority. If priority
2664  * is set to 0, all peers are removed. After that, unlock context and
2665  * return.
2666  * \note When do you want to call this function, make sure that &conlock is locked,
2667  * because some process can handle with your *con context before you lock
2668  * it.
2669  *
2670  */
2671 int ast_context_remove_extension2(struct ast_context *con, const char *extension, int priority, const char *registrar)
2672 {
2673         struct ast_exten *exten, *prev_exten = NULL;
2674         struct ast_exten *peer;
2675
2676         ast_mutex_lock(&con->lock);
2677
2678         /* scan the extension list to find matching extension-registrar */
2679         for (exten = con->root; exten; prev_exten = exten, exten = exten->next) {
2680                 if (!strcmp(exten->exten, extension) &&
2681                         (!registrar || !strcmp(exten->registrar, registrar)))
2682                         break;
2683         }
2684         if (!exten) {
2685                 /* we can't find right extension */
2686                 ast_mutex_unlock(&con->lock);
2687                 return -1;
2688         }
2689
2690         /* should we free all peers in this extension? (priority == 0)? */
2691         if (priority == 0) {
2692                 /* remove this extension from context list */
2693                 if (prev_exten)
2694                         prev_exten->next = exten->next;
2695                 else
2696                         con->root = exten->next;
2697
2698                 /* fire out all peers */
2699                 while ( (peer = exten) ) {
2700                         exten = peer->peer; /* prepare for next entry */
2701                         destroy_exten(peer);
2702                 }
2703         } else {
2704                 /* scan the priority list to remove extension with exten->priority == priority */
2705                 struct ast_exten *previous_peer = NULL;
2706
2707                 for (peer = exten; peer; previous_peer = peer, peer = peer->peer) {
2708                         if (peer->priority == priority &&
2709                                         (!registrar || !strcmp(peer->registrar, registrar) ))
2710                                 break; /* found our priority */
2711                 }
2712                 if (!peer) { /* not found */
2713                         ast_mutex_unlock(&con->lock);
2714                         return -1;
2715                 }
2716                 /* we are first priority extension? */
2717                 if (!previous_peer) {
2718                         /*
2719                          * We are first in the priority chain, so must update the extension chain.
2720                          * The next node is either the next priority or the next extension
2721                          */
2722                         struct ast_exten *next_node = peer->peer ? peer->peer : peer->next;
2723
2724                         if (!prev_exten)        /* change the root... */
2725                                 con->root = next_node;
2726                         else
2727                                 prev_exten->next = next_node; /* unlink */
2728                         if (peer->peer) /* XXX update the new head of the pri list */
2729                                 peer->peer->next = peer->next;
2730                 } else { /* easy, we are not first priority in extension */
2731                         previous_peer->peer = peer->peer;
2732                 }
2733
2734                 /* now, free whole priority extension */
2735                 destroy_exten(peer);
2736                 /* XXX should we return -1 ? */
2737         }
2738         ast_mutex_unlock(&con->lock);
2739         return 0;
2740 }
2741
2742
2743 /*! \brief Dynamically register a new dial plan application */
2744 int ast_register_application(const char *app, int (*execute)(struct ast_channel *, void *), const char *synopsis, const char *description)
2745 {
2746         struct ast_app *tmp, *cur = NULL;
2747         char tmps[80];
2748         int length;
2749
2750         AST_LIST_LOCK(&apps);
2751         AST_LIST_TRAVERSE(&apps, tmp, list) {
2752                 if (!strcasecmp(app, tmp->name)) {
2753                         ast_log(LOG_WARNING, "Already have an application '%s'\n", app);
2754                         AST_LIST_UNLOCK(&apps);
2755                         return -1;
2756                 }
2757         }
2758
2759         length = sizeof(*tmp) + strlen(app) + 1;
2760
2761         if (!(tmp = ast_calloc(1, length))) {
2762                 AST_LIST_UNLOCK(&apps);
2763                 return -1;
2764         }
2765
2766         strcpy(tmp->name, app);
2767         tmp->execute = execute;
2768         tmp->synopsis = synopsis;
2769         tmp->description = description;
2770
2771         /* Store in alphabetical order */
2772         AST_LIST_TRAVERSE_SAFE_BEGIN(&apps, cur, list) {
2773                 if (strcasecmp(tmp->name, cur->name) < 0) {
2774                         AST_LIST_INSERT_BEFORE_CURRENT(&apps, tmp, list);
2775                         break;
2776                 }
2777         }
2778         AST_LIST_TRAVERSE_SAFE_END
2779         if (!cur)
2780                 AST_LIST_INSERT_TAIL(&apps, tmp, list);
2781
2782         if (option_verbose > 1)
2783                 ast_verbose( VERBOSE_PREFIX_2 "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps)));
2784
2785         AST_LIST_UNLOCK(&apps);
2786
2787         return 0;
2788 }
2789
2790 /*
2791  * Append to the list. We don't have a tail pointer because we need
2792  * to scan the list anyways to check for duplicates during insertion.
2793  */
2794 int ast_register_switch(struct ast_switch *sw)
2795 {
2796         struct ast_switch *tmp;
2797
2798         AST_LIST_LOCK(&switches);
2799         AST_LIST_TRAVERSE(&switches, tmp, list) {
2800                 if (!strcasecmp(tmp->name, sw->name)) {
2801                         AST_LIST_UNLOCK(&switches);
2802                         ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name);
2803                         return -1;
2804                 }
2805         }
2806         AST_LIST_INSERT_TAIL(&switches, sw, list);
2807         AST_LIST_UNLOCK(&switches);
2808
2809         return 0;
2810 }
2811
2812 void ast_unregister_switch(struct ast_switch *sw)
2813 {
2814         AST_LIST_LOCK(&switches);
2815         AST_LIST_REMOVE(&switches, sw, list);
2816         AST_LIST_UNLOCK(&switches);
2817 }
2818
2819 /*
2820  * Help for CLI commands ...
2821  */
2822 static char show_application_help[] =
2823 "Usage: show application <application> [<application> [<application> [...]]]\n"
2824 "       Describes a particular application.\n";
2825
2826 static char show_functions_help[] =
2827 "Usage: show functions [like <text>]\n"
2828 "       List builtin functions, optionally only those matching a given string\n";
2829
2830 static char show_function_help[] =
2831 "Usage: show function <function>\n"
2832 "       Describe a particular dialplan function.\n";
2833
2834 static char show_applications_help[] =
2835 "Usage: show applications [{like|describing} <text>]\n"
2836 "       List applications which are currently available.\n"
2837 "       If 'like', <text> will be a substring of the app name\n"
2838 "       If 'describing', <text> will be a substring of the description\n";
2839
2840 static char show_dialplan_help[] =
2841 "Usage: show dialplan [exten@][context]\n"
2842 "       Show dialplan\n";
2843
2844 static char show_switches_help[] =
2845 "Usage: show switches\n"
2846 "       Show registered switches\n";
2847
2848 static char show_hints_help[] =
2849 "Usage: show hints\n"
2850 "       Show registered hints\n";
2851
2852 static char show_globals_help[] =
2853 "Usage: show globals\n"
2854 "       Show current global dialplan variables and their values\n";
2855
2856 static char set_global_help[] =
2857 "Usage: set global <name> <value>\n"
2858 "       Set global dialplan variable <name> to <value>\n";
2859
2860
2861 /*
2862  * IMPLEMENTATION OF CLI FUNCTIONS IS IN THE SAME ORDER AS COMMANDS HELPS
2863  *
2864  */
2865
2866 /*
2867  * \brief 'show application' CLI command implementation functions ...
2868  */
2869
2870 /*
2871  * There is a possibility to show informations about more than one
2872  * application at one time. You can type 'show application Dial Echo' and
2873  * you will see informations about these two applications ...
2874  */
2875 static char *complete_show_application(const char *line, const char *word, int pos, int state)
2876 {
2877         struct ast_app *a;
2878         char *ret = NULL;
2879         int which = 0;
2880         int wordlen = strlen(word);
2881
2882         /* return the n-th [partial] matching entry */
2883         AST_LIST_LOCK(&apps);
2884         AST_LIST_TRAVERSE(&apps, a, list) {
2885                 if (!strncasecmp(word, a->name, wordlen) && ++which > state) {
2886                         ret = strdup(a->name);
2887                         break;
2888                 }
2889         }
2890         AST_LIST_UNLOCK(&apps);
2891
2892         return ret;
2893 }
2894
2895 static int handle_show_application(int fd, int argc, char *argv[])
2896 {
2897         struct ast_app *a;
2898         int app, no_registered_app = 1;
2899
2900         if (argc < 3)
2901                 return RESULT_SHOWUSAGE;
2902
2903         /* ... go through all applications ... */
2904         AST_LIST_LOCK(&apps);
2905         AST_LIST_TRAVERSE(&apps, a, list) {
2906                 /* ... compare this application name with all arguments given
2907                  * to 'show application' command ... */
2908                 for (app = 2; app < argc; app++) {
2909                         if (!strcasecmp(a->name, argv[app])) {
2910                                 /* Maximum number of characters added by terminal coloring is 22 */
2911                                 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40];
2912                                 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL;
2913                                 int synopsis_size, description_size;
2914
2915                                 no_registered_app = 0;
2916
2917                                 if (a->synopsis)
2918                                         synopsis_size = strlen(a->synopsis) + 23;
2919                                 else
2920                                         synopsis_size = strlen("Not available") + 23;
2921                                 synopsis = alloca(synopsis_size);
2922
2923                                 if (a->description)
2924                                         description_size = strlen(a->description) + 23;
2925                                 else
2926                                         description_size = strlen("Not available") + 23;
2927                                 description = alloca(description_size);
2928
2929                                 if (synopsis && description) {
2930                                         snprintf(info, 64 + AST_MAX_APP, "\n  -= Info about application '%s' =- \n\n", a->name);
2931                                         term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22);
2932                                         term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
2933                                         term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
2934                                         term_color(synopsis,
2935                                                                         a->synopsis ? a->synopsis : "Not available",
2936                                                                         COLOR_CYAN, 0, synopsis_size);
2937                                         term_color(description,
2938                                                                         a->description ? a->description : "Not available",
2939                                                                         COLOR_CYAN, 0, description_size);
2940
2941                                         ast_cli(fd,"%s%s%s\n\n%s%s\n", infotitle, syntitle, synopsis, destitle, description);
2942                                 } else {
2943                                         /* ... one of our applications, show info ...*/
2944                                         ast_cli(fd,"\n  -= Info about application '%s' =- \n\n"
2945                                                 "[Synopsis]\n  %s\n\n"
2946                                                 "[Description]\n%s\n",
2947                                                 a->name,
2948                                                 a->synopsis ? a->synopsis : "Not available",
2949                                                 a->description ? a->description : "Not available");
2950                                 }
2951                         }
2952                 }
2953         }
2954         AST_LIST_UNLOCK(&apps);
2955
2956         /* we found at least one app? no? */
2957         if (no_registered_app) {
2958                 ast_cli(fd, "Your application(s) is (are) not registered\n");
2959                 return RESULT_FAILURE;
2960         }
2961
2962         return RESULT_SUCCESS;
2963 }
2964
2965 /*! \brief  handle_show_hints: CLI support for listing registred dial plan hints */
2966 static int handle_show_hints(int fd, int argc, char *argv[])
2967 {
2968         struct ast_hint *hint;
2969         int num = 0;
2970         int watchers;
2971         struct ast_state_cb *watcher;
2972
2973         if (AST_LIST_EMPTY(&hints)) {
2974                 ast_cli(fd, "There are no registered dialplan hints\n");
2975                 return RESULT_SUCCESS;
2976         }
2977         /* ... we have hints ... */
2978         ast_cli(fd, "\n    -= Registered Asterisk Dial Plan Hints =-\n");
2979         AST_LIST_LOCK(&hints);
2980         AST_LIST_TRAVERSE(&hints, hint, list) {
2981                 watchers = 0;
2982                 for (watcher = hint->callbacks; watcher; watcher = watcher->next)
2983                         watchers++;
2984                 ast_cli(fd, "   %20s@%-20.20s: %-20.20s  State:%-15.15s Watchers %2d\n",
2985                         ast_get_extension_name(hint->exten),
2986                         ast_get_context_name(ast_get_extension_context(hint->exten)),
2987                         ast_get_extension_app(hint->exten),
2988                         ast_extension_state2str(hint->laststate), watchers);
2989                 num++;
2990         }
2991         ast_cli(fd, "----------------\n");
2992         ast_cli(fd, "- %d hints registered\n", num);
2993         AST_LIST_UNLOCK(&hints);
2994         return RESULT_SUCCESS;
2995 }
2996
2997 /*! \brief  handle_show_switches: CLI support for listing registred dial plan switches */
2998 static int handle_show_switches(int fd, int argc, char *argv[])
2999 {
3000         struct ast_switch *sw;
3001
3002         AST_LIST_LOCK(&switches);
3003
3004         if (AST_LIST_EMPTY(&switches)) {
3005                 AST_LIST_UNLOCK(&switches);
3006                 ast_cli(fd, "There are no registered alternative switches\n");
3007                 return RESULT_SUCCESS;
3008         }
3009
3010         ast_cli(fd, "\n    -= Registered Asterisk Alternative Switches =-\n");
3011         AST_LIST_TRAVERSE(&switches, sw, list)
3012                 ast_cli(fd, "%s: %s\n", sw->name, sw->description);
3013
3014         AST_LIST_UNLOCK(&switches);
3015
3016         return RESULT_SUCCESS;
3017 }
3018
3019 /*
3020  * 'show applications' CLI command implementation functions ...
3021  */
3022 static int handle_show_applications(int fd, int argc, char *argv[])
3023 {
3024         struct ast_app *a;
3025         int like = 0, describing = 0;
3026         int total_match = 0;    /* Number of matches in like clause */
3027         int total_apps = 0;     /* Number of apps registered */
3028
3029         AST_LIST_LOCK(&apps);
3030
3031         if (AST_LIST_EMPTY(&apps)) {
3032                 ast_cli(fd, "There are no registered applications\n");
3033                 AST_LIST_UNLOCK(&apps);
3034                 return -1;
3035         }
3036
3037         /* show applications like <keyword> */
3038         if ((argc == 4) && (!strcmp(argv[2], "like"))) {
3039                 like = 1;
3040         } else if ((argc > 3) && (!strcmp(argv[2], "describing"))) {
3041                 describing = 1;
3042         }
3043
3044         /* show applications describing <keyword1> [<keyword2>] [...] */
3045         if ((!like) && (!describing)) {
3046                 ast_cli(fd, "    -= Registered Asterisk Applications =-\n");
3047         } else {
3048                 ast_cli(fd, "    -= Matching Asterisk Applications =-\n");
3049         }
3050
3051         AST_LIST_TRAVERSE(&apps, a, list) {
3052                 int printapp = 0;
3053                 total_apps++;
3054                 if (like) {
3055                         if (strcasestr(a->name, argv[3])) {
3056                                 printapp = 1;
3057                                 total_match++;
3058                         }
3059                 } else if (describing) {
3060                         if (a->description) {
3061                                 /* Match all words on command line */
3062                                 int i;
3063                                 printapp = 1;
3064                                 for (i = 3; i < argc; i++) {
3065                                         if (!strcasestr(a->description, argv[i])) {
3066                                                 printapp = 0;
3067                                         } else {
3068                                                 total_match++;
3069                                         }
3070                                 }
3071                         }
3072                 } else {
3073                         printapp = 1;
3074                 }
3075
3076                 if (printapp) {
3077                         ast_cli(fd,"  %20s: %s\n", a->name, a->synopsis ? a->synopsis : "<Synopsis not available>");
3078                 }
3079         }
3080         if ((!like) && (!describing)) {
3081                 ast_cli(fd, "    -= %d Applications Registered =-\n",total_apps);
3082         } else {
3083                 ast_cli(fd, "    -= %d Applications Matching =-\n",total_match);
3084         }
3085
3086         AST_LIST_UNLOCK(&apps);
3087
3088         return RESULT_SUCCESS;
3089 }
3090
3091 static char *complete_show_applications(const char *line, const char *word, int pos, int state)
3092 {
3093         static char* choices[] = { "like", "describing", NULL };
3094
3095         return (pos != 2) ? NULL : ast_cli_complete(word, choices, state);
3096 }
3097
3098 /*
3099  * 'show dialplan' CLI command implementation functions ...
3100  */
3101 static char *complete_show_dialplan_context(const char *line, const char *word, int pos,
3102         int state)
3103 {
3104         struct ast_context *c = NULL;
3105         char *ret = NULL;
3106         int which = 0;
3107         int wordlen;
3108
3109         /* we are do completion of [exten@]context on second position only */
3110         if (pos != 2)
3111                 return NULL;
3112
3113         ast_lock_contexts();
3114
3115         wordlen = strlen(word);
3116
3117         /* walk through all contexts and return the n-th match */
3118         while ( (c = ast_walk_contexts(c)) ) {
3119                 if (!strncasecmp(word, ast_get_context_name(c), wordlen) && ++which > state) {
3120                         ret = ast_strdup(ast_get_context_name(c));
3121                         break;
3122                 }
3123         }
3124
3125         ast_unlock_contexts();
3126
3127         return ret;
3128 }
3129
3130 struct dialplan_counters {
3131         int total_context;
3132         int total_exten;
3133         int total_prio;
3134         int context_existence;
3135         int extension_existence;
3136 };
3137
3138 /*! \brief helper function to print an extension */
3139 static void print_ext(struct ast_exten *e, char * buf, int buflen)
3140 {
3141         int prio = ast_get_extension_priority(e);
3142         if (prio == PRIORITY_HINT) {
3143                 snprintf(buf, buflen, "hint: %s",
3144                         ast_get_extension_app(e));
3145         } else {
3146                 snprintf(buf, buflen, "%d. %s(%s)",
3147                         prio, ast_get_extension_app(e),
3148                         (char *)ast_get_extension_app_data(e));
3149         }
3150 }
3151
3152 /* XXX not verified */
3153 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[])
3154 {
3155         struct ast_context *c = NULL;
3156         int res = 0, old_total_exten = dpc->total_exten;
3157
3158         ast_lock_contexts();
3159
3160         /* walk all contexts ... */
3161         while ( (c = ast_walk_contexts(c)) ) {
3162                 struct ast_exten *e;
3163                 struct ast_include *i;
3164                 struct ast_ignorepat *ip;
3165                 char buf[256], buf2[256];
3166                 int context_info_printed = 0;
3167
3168                 if (context && strcmp(ast_get_context_name(c), context))
3169                         continue;       /* skip this one, name doesn't match */
3170
3171                 dpc->context_existence = 1;
3172
3173                 ast_lock_context(c);
3174
3175                 /* are we looking for exten too? if yes, we print context
3176                  * only if we find our extension.
3177                  * Otherwise print context even if empty ?
3178                  * XXX i am not sure how the rinclude is handled.
3179                  * I think it ought to go inside.
3180                  */
3181                 if (!exten) {
3182                         dpc->total_context++;
3183                         ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
3184                                 ast_get_context_name(c), ast_get_context_registrar(c));
3185                         context_info_printed = 1;
3186                 }
3187
3188                 /* walk extensions ... */
3189                 e = NULL;
3190