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