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