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