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