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