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