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