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