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