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