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