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