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