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