more small simplifications
[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 /*! \brief return a pointer to the arguments of the function,
1201  * and terminates the function name with '\0'
1202  */
1203 static char *func_args(char *function)
1204 {
1205         char *args = strchr(function, '(');
1206
1207         if (!args)
1208                 ast_log(LOG_WARNING, "Function doesn't contain parentheses.  Assuming null argument.\n");
1209         else {
1210                 char *p;
1211                 *args++ = '\0';
1212                 if ((p = strrchr(args, ')')) )
1213                         *p = '\0';
1214                 else
1215                         ast_log(LOG_WARNING, "Can't find trailing parenthesis?\n");
1216         }
1217         return args;
1218 }
1219
1220 int ast_func_read(struct ast_channel *chan, char *function, char *workspace, size_t len)
1221 {
1222         char *args = func_args(function);
1223         struct ast_custom_function *acfptr = ast_custom_function_find(function);
1224
1225         if (acfptr == NULL)
1226                 ast_log(LOG_ERROR, "Function %s not registered\n", function);
1227         else if (!acfptr->read)
1228                 ast_log(LOG_ERROR, "Function %s cannot be read\n", function);
1229         else
1230                 return acfptr->read(chan, function, args, workspace, len);
1231         return -1;
1232 }
1233
1234 int ast_func_write(struct ast_channel *chan, char *function, const char *value)
1235 {
1236         char *args = func_args(function);
1237         struct ast_custom_function *acfptr = ast_custom_function_find(function);
1238
1239         if (acfptr == NULL)
1240                 ast_log(LOG_ERROR, "Function %s not registered\n", function);
1241         else if (!acfptr->write)
1242                 ast_log(LOG_ERROR, "Function %s cannot be written to\n", function);
1243         else
1244                 return acfptr->write(chan, function, args, value);
1245
1246         return -1;
1247 }
1248
1249 static void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count)
1250 {
1251         char *cp4;
1252         const char *tmp, *whereweare;
1253         int length, offset, offset2, isfunction;
1254         char *workspace = NULL;
1255         char *ltmp = NULL, *var = NULL;
1256         char *nextvar, *nextexp, *nextthing;
1257         char *vars, *vare;
1258         int pos, brackets, needsub, len;
1259         
1260         /* Substitutes variables into cp2, based on string cp1, and assuming cp2 to be
1261            zero-filled */
1262         whereweare=tmp=cp1;
1263         while (!ast_strlen_zero(whereweare) && count) {
1264                 /* Assume we're copying the whole remaining string */
1265                 pos = strlen(whereweare);
1266                 nextvar = NULL;
1267                 nextexp = NULL;
1268                 nextthing = strchr(whereweare, '$');
1269                 if (nextthing) {
1270                         switch(nextthing[1]) {
1271                         case '{':
1272                                 nextvar = nextthing;
1273                                 pos = nextvar - whereweare;
1274                                 break;
1275                         case '[':
1276                                 nextexp = nextthing;
1277                                 pos = nextexp - whereweare;
1278                                 break;
1279                         }
1280                 }
1281
1282                 if (pos) {
1283                         /* Can't copy more than 'count' bytes */
1284                         if (pos > count)
1285                                 pos = count;
1286                         
1287                         /* Copy that many bytes */
1288                         memcpy(cp2, whereweare, pos);
1289                         
1290                         count -= pos;
1291                         cp2 += pos;
1292                         whereweare += pos;
1293                 }
1294                 
1295                 if (nextvar) {
1296                         /* We have a variable.  Find the start and end, and determine
1297                            if we are going to have to recursively call ourselves on the
1298                            contents */
1299                         vars = vare = nextvar + 2;
1300                         brackets = 1;
1301                         needsub = 0;
1302
1303                         /* Find the end of it */
1304                         while (brackets && *vare) {
1305                                 if ((vare[0] == '$') && (vare[1] == '{')) {
1306                                         needsub++;
1307                                 } else if (vare[0] == '{') {
1308                                         brackets++;
1309                                 } else if (vare[0] == '}') {
1310                                         brackets--;
1311                                 } else if ((vare[0] == '$') && (vare[1] == '['))
1312                                         needsub++;
1313                                 vare++;
1314                         }
1315                         if (brackets)
1316                                 ast_log(LOG_NOTICE, "Error in extension logic (missing '}')\n");
1317                         len = vare - vars - 1;
1318
1319                         /* Skip totally over variable string */
1320                         whereweare += (len + 3);
1321
1322                         if (!var)
1323                                 var = alloca(VAR_BUF_SIZE);
1324
1325                         /* Store variable name (and truncate) */
1326                         ast_copy_string(var, vars, len + 1);
1327
1328                         /* Substitute if necessary */
1329                         if (needsub) {
1330                                 if (!ltmp)
1331                                         ltmp = alloca(VAR_BUF_SIZE);
1332
1333                                 memset(ltmp, 0, VAR_BUF_SIZE);
1334                                 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1);
1335                                 vars = ltmp;
1336                         } else {
1337                                 vars = var;
1338                         }
1339
1340                         if (!workspace)
1341                                 workspace = alloca(VAR_BUF_SIZE);
1342
1343                         workspace[0] = '\0';
1344
1345                         parse_variable_name(vars, &offset, &offset2, &isfunction);
1346                         if (isfunction) {
1347                                 /* Evaluate function */
1348                                 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
1349
1350                                 ast_log(LOG_DEBUG, "Function result is '%s'\n", cp4 ? cp4 : "(null)");
1351                         } else {
1352                                 /* Retrieve variable value */
1353                                 pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp);
1354                         }
1355                         if (cp4) {
1356                                 cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE);
1357
1358                                 length = strlen(cp4);
1359                                 if (length > count)
1360                                         length = count;
1361                                 memcpy(cp2, cp4, length);
1362                                 count -= length;
1363                                 cp2 += length;
1364                         }
1365                 } else if (nextexp) {
1366                         /* We have an expression.  Find the start and end, and determine
1367                            if we are going to have to recursively call ourselves on the
1368                            contents */
1369                         vars = vare = nextexp + 2;
1370                         brackets = 1;
1371                         needsub = 0;
1372
1373                         /* Find the end of it */
1374                         while(brackets && *vare) {
1375                                 if ((vare[0] == '$') && (vare[1] == '[')) {
1376                                         needsub++;
1377                                         brackets++;
1378                                         vare++;
1379                                 } else if (vare[0] == '[') {
1380                                         brackets++;
1381                                 } else if (vare[0] == ']') {
1382                                         brackets--;
1383                                 } else if ((vare[0] == '$') && (vare[1] == '{')) {
1384                                         needsub++;
1385                                         vare++;
1386                                 }
1387                                 vare++;
1388                         }
1389                         if (brackets)
1390                                 ast_log(LOG_NOTICE, "Error in extension logic (missing ']')\n");
1391                         len = vare - vars - 1;
1392                         
1393                         /* Skip totally over expression */
1394                         whereweare += (len + 3);
1395                         
1396                         if (!var)
1397                                 var = alloca(VAR_BUF_SIZE);
1398
1399                         /* Store variable name (and truncate) */
1400                         ast_copy_string(var, vars, len + 1);
1401                         
1402                         /* Substitute if necessary */
1403                         if (needsub) {
1404                                 if (!ltmp)
1405                                         ltmp = alloca(VAR_BUF_SIZE);
1406
1407                                 memset(ltmp, 0, VAR_BUF_SIZE);
1408                                 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1);
1409                                 vars = ltmp;
1410                         } else {
1411                                 vars = var;
1412                         }
1413
1414                         length = ast_expr(vars, cp2, count);
1415
1416                         if (length) {
1417                                 ast_log(LOG_DEBUG, "Expression result is '%s'\n", cp2);
1418                                 count -= length;
1419                                 cp2 += length;
1420                         }
1421                 } else
1422                         break;
1423         }
1424 }
1425
1426 void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count)
1427 {
1428         pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count);
1429 }
1430
1431 void pbx_substitute_variables_varshead(struct varshead *headp, const char *cp1, char *cp2, int count)
1432 {
1433         pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count);
1434 }
1435
1436 static void pbx_substitute_variables(char *passdata, int datalen, struct ast_channel *c, struct ast_exten *e)
1437 {
1438         memset(passdata, 0, datalen);
1439                 
1440         /* No variables or expressions in e->data, so why scan it? */
1441         if (!strchr(e->data, '$') && !strstr(e->data,"${") && !strstr(e->data,"$[") && !strstr(e->data,"$(")) {
1442                 ast_copy_string(passdata, e->data, datalen);
1443                 return;
1444         }
1445         
1446         pbx_substitute_variables_helper(c, e->data, passdata, datalen - 1);
1447 }                                                               
1448
1449 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) 
1450 {
1451         struct ast_exten *e;
1452         struct ast_app *app;
1453         struct ast_switch *sw;
1454         char *data;
1455         const char *foundcontext=NULL;
1456         int res;
1457         int status = 0;
1458         char *incstack[AST_PBX_MAX_STACK];
1459         char passdata[EXT_DATA_SIZE];
1460         int stacklen = 0;
1461         char tmp[80];
1462         char tmp2[80];
1463         char tmp3[EXT_DATA_SIZE];
1464         char atmp[80];
1465         char atmp2[EXT_DATA_SIZE+100];
1466
1467         ast_mutex_lock(&conlock);
1468
1469         e = pbx_find_extension(c, con, context, exten, priority, label, callerid, action, incstack, &stacklen, &status, &sw, &data, &foundcontext);
1470         if (e) {
1471                 switch(action) {
1472                 case HELPER_CANMATCH:
1473                         ast_mutex_unlock(&conlock);
1474                         return -1;
1475                 case HELPER_EXISTS:
1476                         ast_mutex_unlock(&conlock);
1477                         return -1;
1478                 case HELPER_FINDLABEL:
1479                         res = e->priority;
1480                         ast_mutex_unlock(&conlock);
1481                         return res;
1482                 case HELPER_MATCHMORE:
1483                         ast_mutex_unlock(&conlock);
1484                         return -1;
1485                 case HELPER_SPAWN:
1486                         app = pbx_findapp(e->app);
1487                         ast_mutex_unlock(&conlock);
1488                         if (app) {
1489                                 if (c->context != context)
1490                                         ast_copy_string(c->context, context, sizeof(c->context));
1491                                 if (c->exten != exten)
1492                                         ast_copy_string(c->exten, exten, sizeof(c->exten));
1493                                 c->priority = priority;
1494                                 pbx_substitute_variables(passdata, sizeof(passdata), c, e);
1495                                 if (option_debug) {
1496                                                 ast_log(LOG_DEBUG, "Launching '%s'\n", app->name);
1497                                                 snprintf(atmp, 80, "STACK-%s-%s-%d", context, exten, priority);
1498                                                 snprintf(atmp2, EXT_DATA_SIZE+100, "%s(\"%s\", \"%s\") %s", app->name, c->name, passdata, "in new stack");
1499                                                 pbx_builtin_setvar_helper(c, atmp, atmp2);
1500                                 }
1501                                 if (option_verbose > 2)
1502                                                 ast_verbose( VERBOSE_PREFIX_3 "Executing %s(\"%s\", \"%s\") %s\n", 
1503                                                                 term_color(tmp, app->name, COLOR_BRCYAN, 0, sizeof(tmp)),
1504                                                                 term_color(tmp2, c->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)),
1505                                                                 term_color(tmp3, passdata, COLOR_BRMAGENTA, 0, sizeof(tmp3)),
1506                                                                 "in new stack");
1507                                 manager_event(EVENT_FLAG_CALL, "Newexten", 
1508                                         "Channel: %s\r\n"
1509                                         "Context: %s\r\n"
1510                                         "Extension: %s\r\n"
1511                                         "Priority: %d\r\n"
1512                                         "Application: %s\r\n"
1513                                         "AppData: %s\r\n"
1514                                         "Uniqueid: %s\r\n",
1515                                         c->name, c->context, c->exten, c->priority, app->name, passdata, c->uniqueid);
1516                                 res = pbx_exec(c, app, passdata);
1517                                 return res;
1518                         } else {
1519                                 ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority);
1520                                 return -1;
1521                         }
1522                 default:
1523                         ast_log(LOG_WARNING, "Huh (%d)?\n", action);
1524                         return -1;
1525                 }
1526         } else if (sw) {
1527                 switch(action) {
1528                 case HELPER_CANMATCH:
1529                         ast_mutex_unlock(&conlock);
1530                         return -1;
1531                 case HELPER_EXISTS:
1532                         ast_mutex_unlock(&conlock);
1533                         return -1;
1534                 case HELPER_MATCHMORE:
1535                         ast_mutex_unlock(&conlock);
1536                         return -1;
1537                 case HELPER_FINDLABEL:
1538                         ast_mutex_unlock(&conlock);
1539                         return -1;
1540                 case HELPER_SPAWN:
1541                         ast_mutex_unlock(&conlock);
1542                         if (sw->exec)
1543                                 res = sw->exec(c, foundcontext ? foundcontext : context, exten, priority, callerid, data);
1544                         else {
1545                                 ast_log(LOG_WARNING, "No execution engine for switch %s\n", sw->name);
1546                                 res = -1;
1547                         }
1548                         return res;
1549                 default:
1550                         ast_log(LOG_WARNING, "Huh (%d)?\n", action);
1551                         return -1;
1552                 }
1553         } else {
1554                 ast_mutex_unlock(&conlock);
1555                 switch(status) {
1556                 case STATUS_NO_CONTEXT:
1557                         if ((action != HELPER_EXISTS) && (action != HELPER_MATCHMORE))
1558                                 ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", context);
1559                         break;
1560                 case STATUS_NO_EXTENSION:
1561                         if ((action != HELPER_EXISTS) && (action !=  HELPER_CANMATCH) && (action != HELPER_MATCHMORE))
1562                                 ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, context);
1563                         break;
1564                 case STATUS_NO_PRIORITY:
1565                         if ((action != HELPER_EXISTS) && (action !=  HELPER_CANMATCH) && (action != HELPER_MATCHMORE))
1566                                 ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, context);
1567                         break;
1568                 case STATUS_NO_LABEL:
1569                         if (context)
1570                                 ast_log(LOG_NOTICE, "No such label '%s' in extension '%s' in context '%s'\n", label, exten, context);
1571                         break;
1572                 default:
1573                         ast_log(LOG_DEBUG, "Shouldn't happen!\n");
1574                 }
1575                 
1576                 if ((action != HELPER_EXISTS) && (action != HELPER_CANMATCH) && (action != HELPER_MATCHMORE))
1577                         return -1;
1578                 else
1579                         return 0;
1580         }
1581
1582 }
1583
1584 /*! \brief  ast_hint_extension: Find hint for given extension in context */
1585 static struct ast_exten *ast_hint_extension(struct ast_channel *c, const char *context, const char *exten)
1586 {
1587         struct ast_exten *e;
1588         struct ast_switch *sw;
1589         char *data;
1590         const char *foundcontext = NULL;
1591         int status = 0;
1592         char *incstack[AST_PBX_MAX_STACK];
1593         int stacklen = 0;
1594
1595         ast_mutex_lock(&conlock);
1596         e = pbx_find_extension(c, NULL, context, exten, PRIORITY_HINT, NULL, "", HELPER_EXISTS, incstack, &stacklen, &status, &sw, &data, &foundcontext);
1597         ast_mutex_unlock(&conlock);
1598
1599         return e;
1600 }
1601
1602 /*! \brief  ast_extensions_state2: Check state of extension by using hints */
1603 static int ast_extension_state2(struct ast_exten *e)
1604 {
1605         char hint[AST_MAX_EXTENSION];
1606         char *cur, *rest;
1607         int allunavailable = 1, allbusy = 1, allfree = 1;
1608         int busy = 0, inuse = 0, ring = 0;
1609
1610         if (!e)
1611                 return -1;
1612
1613         ast_copy_string(hint, ast_get_extension_app(e), sizeof(hint));
1614
1615         rest = hint;    /* One or more devices separated with a & character */
1616         while ( (cur = strsep(&rest, "&")) ) {
1617                 int res = ast_device_state(cur);
1618                 switch (res) {
1619                 case AST_DEVICE_NOT_INUSE:
1620                         allunavailable = 0;
1621                         allbusy = 0;
1622                         break;
1623                 case AST_DEVICE_INUSE:
1624                         inuse = 1;
1625                         allunavailable = 0;
1626                         allfree = 0;
1627                         break;
1628                 case AST_DEVICE_RINGING:
1629                         ring = 1;
1630                         allunavailable = 0;
1631                         allfree = 0;
1632                         break;
1633                 case AST_DEVICE_BUSY:
1634                         allunavailable = 0;
1635                         allfree = 0;
1636                         busy = 1;
1637                         break;
1638                 case AST_DEVICE_UNAVAILABLE:
1639                 case AST_DEVICE_INVALID:
1640                         allbusy = 0;
1641                         allfree = 0;
1642                         break;
1643                 default:
1644                         allunavailable = 0;
1645                         allbusy = 0;
1646                         allfree = 0;
1647                 }
1648         }
1649
1650         if (!inuse && ring)
1651                 return AST_EXTENSION_RINGING;
1652         if (inuse && ring)
1653                 return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING);
1654         if (inuse)
1655                 return AST_EXTENSION_INUSE;
1656         if (allfree)
1657                 return AST_EXTENSION_NOT_INUSE;
1658         if (allbusy)            
1659                 return AST_EXTENSION_BUSY;
1660         if (allunavailable)
1661                 return AST_EXTENSION_UNAVAILABLE;
1662         if (busy) 
1663                 return AST_EXTENSION_INUSE;
1664         
1665         return AST_EXTENSION_NOT_INUSE;
1666 }
1667
1668 /*! \brief  ast_extension_state2str: Return extension_state as string */
1669 const char *ast_extension_state2str(int extension_state)
1670 {
1671         int i;
1672
1673         for (i = 0; (i < (sizeof(extension_states) / sizeof(extension_states[0]))); i++) {
1674                 if (extension_states[i].extension_state == extension_state)
1675                         return extension_states[i].text;
1676         }
1677         return "Unknown";       
1678 }
1679
1680 /*! \brief  ast_extension_state: Check extension state for an extension by using hint */
1681 int ast_extension_state(struct ast_channel *c, const char *context, const char *exten)
1682 {
1683         struct ast_exten *e;
1684
1685         e = ast_hint_extension(c, context, exten);      /* Do we have a hint for this extension ? */ 
1686         if (!e) 
1687                 return -1;                              /* No hint, return -1 */
1688
1689         return ast_extension_state2(e);                 /* Check all devices in the hint */
1690 }
1691
1692 void ast_hint_state_changed(const char *device)
1693 {
1694         struct ast_hint *hint;
1695
1696         AST_LIST_LOCK(&hints);
1697
1698         AST_LIST_TRAVERSE(&hints, hint, list) {
1699                 struct ast_state_cb *cblist;
1700                 char buf[AST_MAX_EXTENSION];
1701                 char *parse = buf;
1702                 char *cur;
1703                 int state;
1704
1705                 ast_copy_string(buf, ast_get_extension_app(hint->exten), sizeof(buf));
1706                 while ( (cur = strsep(&parse, "&")) ) {
1707                         if (!strcasecmp(cur, device))
1708                                 break;
1709                 }
1710                 if (!cur)
1711                         continue;
1712
1713                 /* Get device state for this hint */
1714                 state = ast_extension_state2(hint->exten);
1715                         
1716                 if ((state == -1) || (state == hint->laststate))
1717                         continue;
1718
1719                 /* Device state changed since last check - notify the watchers */
1720                         
1721                 /* For general callbacks */
1722                 for (cblist = statecbs; cblist; cblist = cblist->next)
1723                         cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data);
1724                 
1725                 /* For extension callbacks */
1726                 for (cblist = hint->callbacks; cblist; cblist = cblist->next)
1727                         cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data);
1728                         
1729                 hint->laststate = state;
1730         }
1731
1732         AST_LIST_UNLOCK(&hints);
1733 }
1734                         
1735 /*! \brief  ast_extension_state_add: Add watcher for extension states */
1736 int ast_extension_state_add(const char *context, const char *exten, 
1737                             ast_state_cb_type callback, void *data)
1738 {
1739         struct ast_hint *hint;
1740         struct ast_state_cb *cblist;
1741         struct ast_exten *e;
1742
1743         /* If there's no context and extension:  add callback to statecbs list */
1744         if (!context && !exten) {
1745                 AST_LIST_LOCK(&hints);
1746
1747                 for (cblist = statecbs; cblist; cblist = cblist->next) {
1748                         if (cblist->callback == callback) {
1749                                 cblist->data = data;
1750                                 AST_LIST_UNLOCK(&hints);
1751                                 return 0;
1752                         }
1753                 }
1754         
1755                 /* Now insert the callback */
1756                 if (!(cblist = ast_calloc(1, sizeof(*cblist)))) {
1757                         AST_LIST_UNLOCK(&hints);        
1758                         return -1;
1759                 }
1760                 cblist->id = 0;
1761                 cblist->callback = callback;
1762                 cblist->data = data;
1763         
1764                 cblist->next = statecbs;
1765                 statecbs = cblist;
1766
1767                 AST_LIST_UNLOCK(&hints);
1768                 return 0;
1769         }
1770
1771         if (!context || !exten)
1772                 return -1;
1773
1774         /* This callback type is for only one hint, so get the hint */
1775         e = ast_hint_extension(NULL, context, exten);    
1776         if (!e) {
1777                 return -1;
1778         }
1779
1780         /* Find the hint in the list of hints */
1781         AST_LIST_LOCK(&hints);
1782         
1783         AST_LIST_TRAVERSE(&hints, hint, list) {
1784                 if (hint->exten == e)
1785                         break;      
1786         }
1787
1788         if (!hint) {
1789                 /* We have no hint, sorry */
1790                 AST_LIST_UNLOCK(&hints);
1791                 return -1;
1792         }
1793
1794         /* Now insert the callback in the callback list  */
1795         if (!(cblist = ast_calloc(1, sizeof(*cblist)))) {
1796                 AST_LIST_UNLOCK(&hints);
1797                 return -1;
1798         }
1799         cblist->id = stateid++;         /* Unique ID for this callback */
1800         cblist->callback = callback;    /* Pointer to callback routine */
1801         cblist->data = data;            /* Data for the callback */
1802
1803         cblist->next = hint->callbacks;
1804         hint->callbacks = cblist;
1805
1806         AST_LIST_UNLOCK(&hints);
1807         return cblist->id;
1808 }
1809
1810 /*! \brief  ast_extension_state_del: Remove a watcher from the callback list */
1811 int ast_extension_state_del(int id, ast_state_cb_type callback)
1812 {
1813         struct ast_state_cb **p_cur = NULL;     /* address of pointer to us */
1814         int ret = -1;
1815
1816         if (!id && !callback)
1817                 return -1;
1818
1819         AST_LIST_LOCK(&hints);
1820
1821         /* id is zero is a callback without extension */
1822         if (!id) {      /* id == 0 is a callback without extension */
1823                 for (p_cur = &statecbs; *p_cur; p_cur = &(*p_cur)->next) {
1824                         if ((*p_cur)->callback == callback)
1825                                 break;
1826                 }
1827         } else { /* callback with extension, find the callback based on ID */
1828                 struct ast_hint *hint;
1829                 AST_LIST_TRAVERSE(&hints, hint, list) {
1830                         for (p_cur = &hint->callbacks; *p_cur; p_cur = &(*p_cur)->next) {
1831                                 if ((*p_cur)->id == id)
1832                                         break;
1833                         }
1834                         if (*p_cur)     /* found in the inner loop */
1835                                 break;
1836                 }
1837         }
1838         if (p_cur && *p_cur) {
1839                 struct ast_state_cb *cur = *p_cur;
1840                 *p_cur = cur->next;
1841                 free(cur);
1842                 ret = 0;
1843         }
1844         AST_LIST_UNLOCK(&hints);
1845         return ret;
1846 }
1847
1848 /*! \brief  ast_add_hint: Add hint to hint list, check initial extension state */
1849 static int ast_add_hint(struct ast_exten *e)
1850 {
1851         struct ast_hint *hint;
1852
1853         if (!e) 
1854                 return -1;
1855
1856         AST_LIST_LOCK(&hints);
1857
1858         /* Search if hint exists, do nothing */
1859         AST_LIST_TRAVERSE(&hints, hint, list) {
1860                 if (hint->exten == e) {
1861                         AST_LIST_UNLOCK(&hints);
1862                         if (option_debug > 1)
1863                                 ast_log(LOG_DEBUG, "HINTS: Not re-adding existing hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e));
1864                         return -1;
1865                 }
1866         }
1867
1868         if (option_debug > 1)
1869                 ast_log(LOG_DEBUG, "HINTS: Adding hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e));
1870
1871         if (!(hint = ast_calloc(1, sizeof(*hint)))) {
1872                 AST_LIST_UNLOCK(&hints);
1873                 return -1;
1874         }
1875         /* Initialize and insert new item at the top */
1876         hint->exten = e;
1877         hint->laststate = ast_extension_state2(e);
1878         AST_LIST_INSERT_HEAD(&hints, hint, list);
1879
1880         AST_LIST_UNLOCK(&hints);
1881         return 0;
1882 }
1883
1884 /*! \brief  ast_change_hint: Change hint for an extension */
1885 static int ast_change_hint(struct ast_exten *oe, struct ast_exten *ne)
1886
1887         struct ast_hint *hint;
1888         int res = -1;
1889
1890         AST_LIST_LOCK(&hints);
1891         AST_LIST_TRAVERSE(&hints, hint, list) {
1892                 if (hint->exten == oe) {
1893                         hint->exten = ne;
1894                         res = 0;
1895                         break;
1896                 }
1897         }
1898         AST_LIST_UNLOCK(&hints);
1899
1900         return res;
1901 }
1902
1903 /*! \brief  ast_remove_hint: Remove hint from extension */
1904 static int ast_remove_hint(struct ast_exten *e)
1905 {
1906         /* Cleanup the Notifys if hint is removed */
1907         struct ast_hint *hint;
1908         struct ast_state_cb *cblist, *cbprev;
1909         int res = -1;
1910
1911         if (!e) 
1912                 return -1;
1913
1914         AST_LIST_LOCK(&hints);
1915         AST_LIST_TRAVERSE_SAFE_BEGIN(&hints, hint, list) {
1916                 if (hint->exten == e) {
1917                         cbprev = NULL;
1918                         cblist = hint->callbacks;
1919                         while (cblist) {
1920                                 /* Notify with -1 and remove all callbacks */
1921                                 cbprev = cblist;            
1922                                 cblist = cblist->next;
1923                                 cbprev->callback(hint->exten->parent->name, hint->exten->exten, AST_EXTENSION_DEACTIVATED, cbprev->data);
1924                                 free(cbprev);
1925                         }
1926                         hint->callbacks = NULL;
1927                         AST_LIST_REMOVE_CURRENT(&hints, list);
1928                         free(hint);
1929                         res = 0;
1930                         break; 
1931                 }
1932         }
1933         AST_LIST_TRAVERSE_SAFE_END
1934         AST_LIST_UNLOCK(&hints);
1935         
1936         return res;
1937 }
1938
1939
1940 /*! \brief  ast_get_hint: Get hint for channel */
1941 int ast_get_hint(char *hint, int hintsize, char *name, int namesize, struct ast_channel *c, const char *context, const char *exten)
1942 {
1943         struct ast_exten *e = ast_hint_extension(c, context, exten);
1944
1945         if (e) {
1946                 if (hint) 
1947                         ast_copy_string(hint, ast_get_extension_app(e), hintsize);
1948                 if (name) {
1949                         const char *tmp = ast_get_extension_app_data(e);
1950                         if (tmp)
1951                                 ast_copy_string(name, tmp, namesize);
1952                 }
1953                 return -1;
1954         }
1955         return 0;       
1956 }
1957
1958 int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid) 
1959 {
1960         return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, HELPER_EXISTS);
1961 }
1962
1963 int ast_findlabel_extension(struct ast_channel *c, const char *context, const char *exten, const char *label, const char *callerid) 
1964 {
1965         return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, HELPER_FINDLABEL);
1966 }
1967
1968 int ast_findlabel_extension2(struct ast_channel *c, struct ast_context *con, const char *exten, const char *label, const char *callerid) 
1969 {
1970         return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, HELPER_FINDLABEL);
1971 }
1972
1973 int ast_canmatch_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
1974 {
1975         return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, HELPER_CANMATCH);
1976 }
1977
1978 int ast_matchmore_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
1979 {
1980         return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, HELPER_MATCHMORE);
1981 }
1982
1983 int ast_spawn_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid) 
1984 {
1985         return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, HELPER_SPAWN);
1986 }
1987
1988 /* helper function to set extension and priority */
1989 static void set_ext_pri(struct ast_channel *c, const char *exten, int pri)
1990 {
1991         ast_copy_string(c->exten, exten, sizeof(c->exten));
1992         c->priority = pri;
1993 }
1994
1995 static int __ast_pbx_run(struct ast_channel *c)
1996 {
1997         int firstpass = 1;
1998         int digit;
1999         char exten[256];
2000         int pos;
2001         int waittime;
2002         int res=0;
2003         int autoloopflag;
2004
2005         /* A little initial setup here */
2006         if (c->pbx) {
2007                 ast_log(LOG_WARNING, "%s already has PBX structure??\n", c->name);
2008                 /* XXX and now what ? */
2009                 free(c->pbx);
2010         }
2011         if (!(c->pbx = ast_calloc(1, sizeof(*c->pbx))))
2012                 return -1;
2013         if (c->amaflags) {
2014                 if (!c->cdr) {
2015                         c->cdr = ast_cdr_alloc();
2016                         if (!c->cdr) {
2017                                 ast_log(LOG_WARNING, "Unable to create Call Detail Record\n");
2018                                 free(c->pbx);
2019                                 return -1;
2020                         }
2021                         ast_cdr_init(c->cdr, c);
2022                 }
2023         }
2024         /* Set reasonable defaults */
2025         c->pbx->rtimeout = 10;
2026         c->pbx->dtimeout = 5;
2027
2028         autoloopflag = ast_test_flag(c, AST_FLAG_IN_AUTOLOOP);  /* save value to restore at the end */
2029         ast_set_flag(c, AST_FLAG_IN_AUTOLOOP);
2030
2031         /* Start by trying whatever the channel is set to */
2032         if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) {
2033                 /* If not successful fall back to 's' */
2034                 if (option_verbose > 1)
2035                         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);
2036                 /* XXX the original code used the existing priority in the call to
2037                  * ast_exists_extension(), and reset it to 1 afterwards.
2038                  * I believe the correct thing is to set it to 1 immediately.
2039                  */
2040                 set_ext_pri(c, "s", 1);
2041                 if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) {
2042                         /* JK02: And finally back to default if everything else failed */
2043                         if (option_verbose > 1)
2044                                 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);
2045                         ast_copy_string(c->context, "default", sizeof(c->context));
2046                 }
2047         }
2048         if (c->cdr && ast_tvzero(c->cdr->start))
2049                 ast_cdr_start(c->cdr);
2050         for (;;) {
2051                 pos = 0;
2052                 digit = 0;
2053                 while (ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) {
2054                         memset(exten, 0, sizeof(exten));
2055                         if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num))) {
2056                                 /* Something bad happened, or a hangup has been requested. */
2057                                 if (((res >= '0') && (res <= '9')) || ((res >= 'A') && (res <= 'F')) ||
2058                                         (res == '*') || (res == '#')) {
2059                                         ast_log(LOG_DEBUG, "Oooh, got something to jump out with ('%c')!\n", res);
2060                                         memset(exten, 0, sizeof(exten));
2061                                         pos = 0;
2062                                         exten[pos++] = digit = res;
2063                                         break;
2064                                 }
2065                                 switch(res) {
2066                                 case AST_PBX_KEEPALIVE:
2067                                         if (option_debug)
2068                                                 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
2069                                         else if (option_verbose > 1)
2070                                                 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
2071                                         goto out;
2072                                         break;
2073                                 default:
2074                                         if (option_debug)
2075                                                 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
2076                                         else if (option_verbose > 1)
2077                                                 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
2078                                         if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
2079                                                 c->_softhangup =0;
2080                                                 break;
2081                                         }
2082                                         /* atimeout */
2083                                         if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) {
2084                                                 break;
2085                                         }
2086
2087                                         if (c->cdr) {
2088                                                 ast_cdr_update(c);
2089                                         }
2090                                         goto out;
2091                                 }
2092                         }
2093                         if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT && ast_exists_extension(c,c->context,"T",1,c->cid.cid_num)) {
2094                                 set_ext_pri(c, "T", 0); /* 0 will become 1 with the c->priority++; at the end */
2095                                 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
2096                                 c->whentohangup = 0;
2097                                 c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT;
2098                         } else if (c->_softhangup) {
2099                                 ast_log(LOG_DEBUG, "Extension %s, priority %d returned normally even though call was hung up\n",
2100                                         c->exten, c->priority);
2101                                 goto out;
2102                         }
2103                         firstpass = 0;
2104                         c->priority++;
2105                 }
2106                 if (!ast_exists_extension(c, c->context, c->exten, 1, c->cid.cid_num)) {
2107                         /* If there is no match at priority 1, it is not a valid extension anymore.
2108                          * Try to continue at "i", 1 or exit if the latter does not exist.
2109                          */
2110                         if (ast_exists_extension(c, c->context, "i", 1, c->cid.cid_num)) {
2111                                 if (option_verbose > 2)
2112                                         ast_verbose(VERBOSE_PREFIX_3 "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, c->name);
2113                                 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", c->exten);
2114                                 set_ext_pri(c, "i", 1);
2115                         } else {
2116                                 ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n",
2117                                         c->name, c->exten, c->context);
2118                                 goto out;
2119                         }
2120                 } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) {
2121                         /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */
2122                         c->_softhangup = 0;
2123                 } else {
2124                         /* Done, wait for an extension */
2125                         waittime = 0;
2126                         if (digit)
2127                                 waittime = c->pbx->dtimeout;
2128                         else if (!autofallthrough)
2129                                 waittime = c->pbx->rtimeout;
2130                         if (waittime) {
2131                                 while (ast_matchmore_extension(c, c->context, exten, 1, c->cid.cid_num)) {
2132                                         /* As long as we're willing to wait, and as long as it's not defined, 
2133                                            keep reading digits until we can't possibly get a right answer anymore.  */
2134                                         digit = ast_waitfordigit(c, waittime * 1000);
2135                                         if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
2136                                                 c->_softhangup = 0;
2137                                         } else {
2138                                                 if (!digit)
2139                                                         /* No entry */
2140                                                         break;
2141                                                 if (digit < 0)
2142                                                         /* Error, maybe a  hangup */
2143                                                         goto out;
2144                                                 exten[pos++] = digit;
2145                                                 waittime = c->pbx->dtimeout;
2146                                         }
2147                                 }
2148                                 if (ast_exists_extension(c, c->context, exten, 1, c->cid.cid_num)) {
2149                                         /* Prepare the next cycle */
2150                                         set_ext_pri(c, exten, 1);
2151                                 } else {
2152                                         /* No such extension */
2153                                         if (!ast_strlen_zero(exten)) {
2154                                                 /* An invalid extension */
2155                                                 if (ast_exists_extension(c, c->context, "i", 1, c->cid.cid_num)) {
2156                                                         if (option_verbose > 2)
2157                                                                 ast_verbose( VERBOSE_PREFIX_3 "Invalid extension '%s' in context '%s' on %s\n", exten, c->context, c->name);
2158                                                         pbx_builtin_setvar_helper(c, "INVALID_EXTEN", exten);
2159                                                         set_ext_pri(c, "i", 1);
2160                                                 } else {
2161                                                         ast_log(LOG_WARNING, "Invalid extension '%s', but no rule 'i' in context '%s'\n", exten, c->context);
2162                                                         goto out;
2163                                                 }
2164                                         } else {
2165                                                 /* A simple timeout */
2166                                                 if (ast_exists_extension(c, c->context, "t", 1, c->cid.cid_num)) {
2167                                                         if (option_verbose > 2)
2168                                                                 ast_verbose( VERBOSE_PREFIX_3 "Timeout on %s\n", c->name);
2169                                                         set_ext_pri(c, "t", 1);
2170                                                 } else {
2171                                                         ast_log(LOG_WARNING, "Timeout, but no rule 't' in context '%s'\n", c->context);
2172                                                         goto out;
2173                                                 }
2174                                         }       
2175                                 }
2176                                 if (c->cdr) {
2177                                         if (option_verbose > 2)
2178                                                 ast_verbose(VERBOSE_PREFIX_2 "CDR updated on %s\n",c->name);    
2179                                         ast_cdr_update(c);
2180                             }
2181                         } else {
2182                                 const char *status;
2183
2184                                 status = pbx_builtin_getvar_helper(c, "DIALSTATUS");
2185                                 if (!status)
2186                                         status = "UNKNOWN";
2187                                 if (option_verbose > 2)
2188                                         ast_verbose(VERBOSE_PREFIX_2 "Auto fallthrough, channel '%s' status is '%s'\n", c->name, status);
2189                                 if (!strcasecmp(status, "CONGESTION"))
2190                                         res = pbx_builtin_congestion(c, "10");
2191                                 else if (!strcasecmp(status, "CHANUNAVAIL"))
2192                                         res = pbx_builtin_congestion(c, "10");
2193                                 else if (!strcasecmp(status, "BUSY"))
2194                                         res = pbx_builtin_busy(c, "10");
2195                                 goto out;
2196                         }
2197                 }
2198         }
2199         if (firstpass) 
2200                 ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name);
2201 out:
2202         if ((res != AST_PBX_KEEPALIVE) && ast_exists_extension(c, c->context, "h", 1, c->cid.cid_num)) {
2203                 if (c->cdr && ast_opt_end_cdr_before_h_exten)
2204                         ast_cdr_end(c->cdr);
2205                 set_ext_pri(c, "h", 1);
2206                 while(ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) {
2207                         if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num))) {
2208                                 /* Something bad happened, or a hangup has been requested. */
2209                                 if (option_debug)
2210                                         ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
2211                                 else if (option_verbose > 1)
2212                                         ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
2213                                 break;
2214                         }
2215                         c->priority++;
2216                 }
2217         }
2218         ast_set2_flag(c, autoloopflag, AST_FLAG_IN_AUTOLOOP);
2219
2220         pbx_destroy(c->pbx);
2221         c->pbx = NULL;
2222         if (res != AST_PBX_KEEPALIVE)
2223                 ast_hangup(c);
2224         return 0;
2225 }
2226
2227 /* Returns 0 on success, non-zero if call limit was reached */
2228 static int increase_call_count(const struct ast_channel *c)
2229 {
2230         int failed = 0;
2231         double curloadavg;
2232         ast_mutex_lock(&maxcalllock);
2233         if (option_maxcalls) {
2234                 if (countcalls >= option_maxcalls) {
2235                         ast_log(LOG_NOTICE, "Maximum call limit of %d calls exceeded by '%s'!\n", option_maxcalls, c->name);
2236                         failed = -1;
2237                 }
2238         }
2239         if (option_maxload) {
2240                 getloadavg(&curloadavg, 1);
2241                 if (curloadavg >= option_maxload) {
2242                         ast_log(LOG_NOTICE, "Maximum loadavg limit of %f load exceeded by '%s' (currently %f)!\n", option_maxload, c->name, curloadavg);
2243                         failed = -1;
2244                 }
2245         }
2246         if (!failed)
2247                 countcalls++;   
2248         ast_mutex_unlock(&maxcalllock);
2249
2250         return failed;
2251 }
2252
2253 static void decrease_call_count(void)
2254 {
2255         ast_mutex_lock(&maxcalllock);
2256         if (countcalls > 0)
2257                 countcalls--;
2258         ast_mutex_unlock(&maxcalllock);
2259 }
2260
2261 static void *pbx_thread(void *data)
2262 {
2263         /* Oh joyeous kernel, we're a new thread, with nothing to do but
2264            answer this channel and get it going.
2265         */
2266         /* NOTE:
2267            The launcher of this function _MUST_ increment 'countcalls'
2268            before invoking the function; it will be decremented when the
2269            PBX has finished running on the channel
2270          */
2271         struct ast_channel *c = data;
2272
2273         __ast_pbx_run(c);
2274         decrease_call_count();
2275
2276         pthread_exit(NULL);
2277
2278         return NULL;
2279 }
2280
2281 enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
2282 {
2283         pthread_t t;
2284         pthread_attr_t attr;
2285
2286         if (!c) {
2287                 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
2288                 return AST_PBX_FAILED;
2289         }
2290            
2291         if (increase_call_count(c))
2292                 return AST_PBX_CALL_LIMIT;
2293
2294         /* Start a new thread, and get something handling this channel. */
2295         pthread_attr_init(&attr);
2296         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
2297         if (ast_pthread_create(&t, &attr, pbx_thread, c)) {
2298                 ast_log(LOG_WARNING, "Failed to create new channel thread\n");
2299                 return AST_PBX_FAILED;
2300         }
2301
2302         return AST_PBX_SUCCESS;
2303 }
2304
2305 enum ast_pbx_result ast_pbx_run(struct ast_channel *c)
2306 {
2307         enum ast_pbx_result res = AST_PBX_SUCCESS;
2308
2309         if (increase_call_count(c))
2310                 return AST_PBX_CALL_LIMIT;
2311
2312         res = __ast_pbx_run(c);
2313         decrease_call_count();
2314
2315         return res;
2316 }
2317
2318 int ast_active_calls(void)
2319 {
2320         return countcalls;
2321 }
2322
2323 int pbx_set_autofallthrough(int newval)
2324 {
2325         int oldval = autofallthrough;
2326         autofallthrough = newval;
2327         return oldval;
2328 }
2329
2330 /* lookup for a context with a given name,
2331  * return with conlock held if found, NULL if not found
2332  */
2333 static struct ast_context *find_context_locked(const char *context)
2334 {
2335         struct ast_context *c = NULL;
2336
2337         ast_lock_contexts();
2338         while ( (c = ast_walk_contexts(c)) ) {
2339                 if (!strcmp(ast_get_context_name(c), context))
2340                         return c;
2341         }
2342         ast_unlock_contexts();
2343
2344         return NULL;
2345 }
2346
2347 /*
2348  * This function locks contexts list by &conlist, search for the right context
2349  * structure, leave context list locked and call ast_context_remove_include2
2350  * which removes include, unlock contexts list and return ...
2351  */
2352 int ast_context_remove_include(const char *context, const char *include, const char *registrar)
2353 {
2354         int ret = -1;
2355         struct ast_context *c = find_context_locked(context);
2356
2357         if (c) {
2358                 /* found, remove include from this context ... */
2359                 ret = ast_context_remove_include2(c, include, registrar);
2360                 ast_unlock_contexts();
2361         }
2362         return ret;
2363 }
2364
2365 /*
2366  * When we call this function, &conlock lock must be locked, because when
2367  * we giving *con argument, some process can remove/change this context
2368  * and after that there can be segfault.
2369  *
2370  * This function locks given context, removes include, unlock context and
2371  * return.
2372  */
2373 int ast_context_remove_include2(struct ast_context *con, const char *include, const char *registrar)
2374 {
2375         struct ast_include *i, *pi = NULL;
2376         int ret = -1;
2377
2378         ast_mutex_lock(&con->lock);
2379
2380         /* find our include */
2381         for (i = con->includes; i; pi = i, i = i->next) {
2382                 if (!strcmp(i->name, include) && 
2383                                 (!registrar || !strcmp(i->registrar, registrar))) {
2384                         /* remove from list */
2385                         if (pi)
2386                                 pi->next = i->next;
2387                         else
2388                                 con->includes = i->next;
2389                         /* free include and return */
2390                         free(i);
2391                         ret = 0;
2392                         break;
2393                 }
2394         }
2395
2396         ast_mutex_unlock(&con->lock);
2397         return ret;
2398 }
2399
2400 /*!
2401  * \note This function locks contexts list by &conlist, search for the rigt context
2402  * structure, leave context list locked and call ast_context_remove_switch2
2403  * which removes switch, unlock contexts list and return ...
2404  */
2405 int ast_context_remove_switch(const char *context, const char *sw, const char *data, const char *registrar)
2406 {
2407         int ret = -1; /* default error return */
2408         struct ast_context *c = find_context_locked(context);
2409
2410         if (c) {
2411                 /* remove switch from this context ... */       
2412                 ret = ast_context_remove_switch2(c, sw, data, registrar);
2413                 ast_unlock_contexts();
2414         }
2415         return ret;
2416 }
2417
2418 /*!
2419  * \brief This function locks given context, removes switch, unlock context and
2420  * return.
2421  * \note When we call this function, &conlock lock must be locked, because when
2422  * we giving *con argument, some process can remove/change this context
2423  * and after that there can be segfault.
2424  *
2425  */
2426 int ast_context_remove_switch2(struct ast_context *con, const char *sw, const char *data, const char *registrar)
2427 {
2428         struct ast_sw *i;
2429         int ret = -1;
2430
2431         ast_mutex_lock(&con->lock);
2432
2433         /* walk switches */
2434         AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) {
2435                 if (!strcmp(i->name, sw) && !strcmp(i->data, data) && 
2436                         (!registrar || !strcmp(i->registrar, registrar))) {
2437                         /* found, remove from list */
2438                         AST_LIST_REMOVE_CURRENT(&con->alts, list);
2439                         free(i); /* free switch and return */
2440                         ret = 0;
2441                         break;
2442                 }
2443         }
2444         AST_LIST_TRAVERSE_SAFE_END
2445
2446         ast_mutex_unlock(&con->lock);
2447
2448         return ret;
2449 }
2450
2451 /*
2452  * \note This functions lock contexts list, search for the right context,
2453  * call ast_context_remove_extension2, unlock contexts list and return.
2454  * In this function we are using
2455  */
2456 int ast_context_remove_extension(const char *context, const char *extension, int priority, const char *registrar)
2457 {
2458         int ret = -1; /* default error return */
2459         struct ast_context *c = find_context_locked(context);
2460
2461         if (c) { /* ... remove extension ... */
2462                 ret = ast_context_remove_extension2(c, extension, priority, registrar);
2463                 ast_unlock_contexts();
2464         }
2465         return ret;
2466 }
2467
2468 /*!
2469  * \brief This functionc locks given context, search for the right extension and
2470  * fires out all peer in this extensions with given priority. If priority
2471  * is set to 0, all peers are removed. After that, unlock context and
2472  * return.
2473  * \note When do you want to call this function, make sure that &conlock is locked,
2474  * because some process can handle with your *con context before you lock
2475  * it.
2476  *
2477  */
2478 int ast_context_remove_extension2(struct ast_context *con, const char *extension, int priority, const char *registrar)
2479 {
2480         struct ast_exten *exten, *prev_exten = NULL;
2481
2482         ast_mutex_lock(&con->lock);
2483
2484         /* go through all extensions in context and search the right one ... */
2485         exten = con->root;
2486         while (exten) {
2487
2488                 /* look for right extension */
2489                 if (!strcmp(exten->exten, extension) &&
2490                         (!registrar || !strcmp(exten->registrar, registrar))) {
2491                         struct ast_exten *peer;
2492
2493                         /* should we free all peers in this extension? (priority == 0)? */
2494                         if (priority == 0) {
2495                                 /* remove this extension from context list */
2496                                 if (prev_exten)
2497                                         prev_exten->next = exten->next;
2498                                 else
2499                                         con->root = exten->next;
2500
2501                                 /* fire out all peers */
2502                                 peer = exten; 
2503                                 while (peer) {
2504                                         exten = peer->peer;
2505                                         
2506                                         if (!peer->priority==PRIORITY_HINT) 
2507                                             ast_remove_hint(peer);
2508
2509                                         peer->datad(peer->data);
2510                                         free(peer);
2511
2512                                         peer = exten;
2513                                 }
2514
2515                                 ast_mutex_unlock(&con->lock);
2516                                 return 0;
2517                         } else {
2518                                 /* remove only extension with exten->priority == priority */
2519                                 struct ast_exten *previous_peer = NULL;
2520
2521                                 peer = exten;
2522                                 while (peer) {
2523                                         /* is this our extension? */
2524                                         if (peer->priority == priority &&
2525                                                 (!registrar || !strcmp(peer->registrar, registrar) )) {
2526                                                 /* we are first priority extension? */
2527                                                 if (!previous_peer) {
2528                                                         /* exists previous extension here? */
2529                                                         if (prev_exten) {
2530                                                                 /* yes, so we must change next pointer in
2531                                                                  * previous connection to next peer
2532                                                                  */
2533                                                                 if (peer->peer) {
2534                                                                         prev_exten->next = peer->peer;
2535                                                                         peer->peer->next = exten->next;
2536                                                                 } else
2537                                                                         prev_exten->next = exten->next;
2538                                                         } else {
2539                                                                 /* no previous extension, we are first
2540                                                                  * extension, so change con->root ...
2541                                                                  */
2542                                                                 if (peer->peer)
2543                                                                         con->root = peer->peer;
2544                                                                 else
2545                                                                         con->root = exten->next; 
2546                                                         }
2547                                                 } else {
2548                                                         /* we are not first priority in extension */
2549                                                         previous_peer->peer = peer->peer;
2550                                                 }
2551
2552                                                 /* now, free whole priority extension */
2553                                                 if (peer->priority==PRIORITY_HINT)
2554                                                     ast_remove_hint(peer);
2555                                                 peer->datad(peer->data);
2556                                                 free(peer);
2557
2558                                                 ast_mutex_unlock(&con->lock);
2559                                                 return 0;
2560                                         } else {
2561                                                 /* this is not right extension, skip to next peer */
2562                                                 previous_peer = peer;
2563                                                 peer = peer->peer;
2564                                         }
2565                                 }
2566
2567                                 ast_mutex_unlock(&con->lock);
2568                                 return -1;
2569                         }
2570                 }
2571
2572                 prev_exten = exten;
2573                 exten = exten->next;
2574         }
2575
2576         /* we can't find right extension */
2577         ast_mutex_unlock(&con->lock);
2578         return -1;
2579 }
2580
2581
2582 /*! \brief Dynamically register a new dial plan application */
2583 int ast_register_application(const char *app, int (*execute)(struct ast_channel *, void *), const char *synopsis, const char *description)
2584 {
2585         struct ast_app *tmp, *cur = NULL;
2586         char tmps[80];
2587         int length;
2588
2589         AST_LIST_LOCK(&apps);
2590         AST_LIST_TRAVERSE(&apps, tmp, list) {
2591                 if (!strcasecmp(app, tmp->name)) {
2592                         ast_log(LOG_WARNING, "Already have an application '%s'\n", app);
2593                         AST_LIST_UNLOCK(&apps);
2594                         return -1;
2595                 }
2596         }
2597         
2598         length = sizeof(*tmp) + strlen(app) + 1;
2599         
2600         if (!(tmp = ast_calloc(1, length))) {
2601                 AST_LIST_UNLOCK(&apps);
2602                 return -1;
2603         }
2604
2605         strcpy(tmp->name, app);
2606         tmp->execute = execute;
2607         tmp->synopsis = synopsis;
2608         tmp->description = description;
2609
2610         /* Store in alphabetical order */
2611         AST_LIST_TRAVERSE_SAFE_BEGIN(&apps, cur, list) {
2612                 if (strcasecmp(tmp->name, cur->name) < 0) {
2613                         AST_LIST_INSERT_BEFORE_CURRENT(&apps, tmp, list);       
2614                         break;
2615                 }
2616         }
2617         AST_LIST_TRAVERSE_SAFE_END
2618         if (!cur)
2619                 AST_LIST_INSERT_TAIL(&apps, tmp, list);
2620
2621         if (option_verbose > 1)
2622                 ast_verbose( VERBOSE_PREFIX_2 "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps)));
2623
2624         AST_LIST_UNLOCK(&apps);
2625
2626         return 0;
2627 }
2628
2629 /*
2630  * Append to the list. We don't have a tail pointer because we need
2631  * to scan the list anyways to check for duplicates during insertion.
2632  */
2633 int ast_register_switch(struct ast_switch *sw)
2634 {
2635         struct ast_switch *tmp;
2636
2637         AST_LIST_LOCK(&switches);
2638         AST_LIST_TRAVERSE(&switches, tmp, list) {
2639                 if (!strcasecmp(tmp->name, sw->name)) {
2640                         AST_LIST_UNLOCK(&switches);
2641                         ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name);
2642                         return -1;
2643                 }
2644         }
2645         AST_LIST_INSERT_TAIL(&switches, sw, list);
2646         AST_LIST_UNLOCK(&switches);
2647         
2648         return 0;
2649 }
2650
2651 void ast_unregister_switch(struct ast_switch *sw)
2652 {
2653         AST_LIST_LOCK(&switches);
2654         AST_LIST_REMOVE(&switches, sw, list);
2655         AST_LIST_UNLOCK(&switches);
2656 }
2657
2658 /*
2659  * Help for CLI commands ...
2660  */
2661 static char show_application_help[] = 
2662 "Usage: show application <application> [<application> [<application> [...]]]\n"
2663 "       Describes a particular application.\n";
2664
2665 static char show_functions_help[] =
2666 "Usage: show functions [like <text>]\n"
2667 "       List builtin functions, optionally only those matching a given string\n";
2668
2669 static char show_function_help[] =
2670 "Usage: show function <function>\n"
2671 "       Describe a particular dialplan function.\n";
2672
2673 static char show_applications_help[] =
2674 "Usage: show applications [{like|describing} <text>]\n"
2675 "       List applications which are currently available.\n"
2676 "       If 'like', <text> will be a substring of the app name\n"
2677 "       If 'describing', <text> will be a substring of the description\n";
2678
2679 static char show_dialplan_help[] =
2680 "Usage: show dialplan [exten@][context]\n"
2681 "       Show dialplan\n";
2682
2683 static char show_switches_help[] = 
2684 "Usage: show switches\n"
2685 "       Show registered switches\n";
2686
2687 static char show_hints_help[] = 
2688 "Usage: show hints\n"
2689 "       Show registered hints\n";
2690
2691 static char show_globals_help[] = 
2692 "Usage: show globals\n"
2693 "       Show current global dialplan variables and their values\n";
2694
2695 static char set_global_help[] = 
2696 "Usage: set global <name> <value>\n"
2697 "       Set global dialplan variable <name> to <value>\n";
2698
2699
2700 /*
2701  * IMPLEMENTATION OF CLI FUNCTIONS IS IN THE SAME ORDER AS COMMANDS HELPS
2702  *
2703  */
2704
2705 /*
2706  * \brief 'show application' CLI command implementation functions ...
2707  */
2708
2709 /*
2710  * There is a possibility to show informations about more than one
2711  * application at one time. You can type 'show application Dial Echo' and
2712  * you will see informations about these two applications ...
2713  */
2714 static char *complete_show_application(const char *line, const char *word, int pos, int state)
2715 {
2716         struct ast_app *a;
2717         char *ret = NULL;
2718         int which = 0;
2719         int wordlen = strlen(word);
2720
2721         /* return the n-th [partial] matching entry */
2722         AST_LIST_LOCK(&apps);
2723         AST_LIST_TRAVERSE(&apps, a, list) {
2724                 if (!strncasecmp(word, a->name, wordlen) && ++which > state)
2725                         ret = strdup(a->name);
2726         }
2727         AST_LIST_UNLOCK(&apps);
2728
2729         return ret; 
2730 }
2731
2732 static int handle_show_application(int fd, int argc, char *argv[])
2733 {
2734         struct ast_app *a;
2735         int app, no_registered_app = 1;
2736
2737         if (argc < 3)
2738                 return RESULT_SHOWUSAGE;
2739
2740         /* ... go through all applications ... */
2741         AST_LIST_LOCK(&apps);
2742         AST_LIST_TRAVERSE(&apps, a, list) {
2743                 /* ... compare this application name with all arguments given
2744                  * to 'show application' command ... */
2745                 for (app = 2; app < argc; app++) {
2746                         if (!strcasecmp(a->name, argv[app])) {
2747                                 /* Maximum number of characters added by terminal coloring is 22 */
2748                                 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40];
2749                                 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL;
2750                                 int synopsis_size, description_size;
2751
2752                                 no_registered_app = 0;
2753
2754                                 if (a->synopsis)
2755                                         synopsis_size = strlen(a->synopsis) + 23;
2756                                 else
2757                                         synopsis_size = strlen("Not available") + 23;
2758                                 synopsis = alloca(synopsis_size);
2759
2760                                 if (a->description)
2761                                         description_size = strlen(a->description) + 23;
2762                                 else
2763                                         description_size = strlen("Not available") + 23;
2764                                 description = alloca(description_size);
2765
2766                                 if (synopsis && description) {
2767                                         snprintf(info, 64 + AST_MAX_APP, "\n  -= Info about application '%s' =- \n\n", a->name);
2768                                         term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22);
2769                                         term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
2770                                         term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
2771                                         term_color(synopsis,
2772                                                                         a->synopsis ? a->synopsis : "Not available",
2773                                                                         COLOR_CYAN, 0, synopsis_size);
2774                                         term_color(description,
2775                                                                         a->description ? a->description : "Not available",
2776                                                                         COLOR_CYAN, 0, description_size);
2777
2778                                         ast_cli(fd,"%s%s%s\n\n%s%s\n", infotitle, syntitle, synopsis, destitle, description);
2779                                 } else {
2780                                         /* ... one of our applications, show info ...*/
2781                                         ast_cli(fd,"\n  -= Info about application '%s' =- \n\n"
2782                                                 "[Synopsis]\n  %s\n\n"
2783                                                 "[Description]\n%s\n",
2784                                                 a->name,
2785                                                 a->synopsis ? a->synopsis : "Not available",
2786                                                 a->description ? a->description : "Not available");
2787                                 }
2788                         }
2789                 }
2790         }
2791         AST_LIST_UNLOCK(&apps);
2792
2793         /* we found at least one app? no? */
2794         if (no_registered_app) {
2795                 ast_cli(fd, "Your application(s) is (are) not registered\n");
2796                 return RESULT_FAILURE;
2797         }
2798
2799         return RESULT_SUCCESS;
2800 }
2801
2802 /*! \brief  handle_show_hints: CLI support for listing registred dial plan hints */
2803 static int handle_show_hints(int fd, int argc, char *argv[])
2804 {
2805         struct ast_hint *hint;
2806         int num = 0;
2807         int watchers;
2808         struct ast_state_cb *watcher;
2809
2810         if (AST_LIST_EMPTY(&hints)) {
2811                 ast_cli(fd, "There are no registered dialplan hints\n");
2812                 return RESULT_SUCCESS;
2813         }
2814         /* ... we have hints ... */
2815         ast_cli(fd, "\n    -= Registered Asterisk Dial Plan Hints =-\n");
2816         AST_LIST_LOCK(&hints);
2817         AST_LIST_TRAVERSE(&hints, hint, list) {
2818                 watchers = 0;
2819                 for (watcher = hint->callbacks; watcher; watcher = watcher->next)
2820                         watchers++;
2821                 ast_cli(fd, "   %20s@%-20.20s: %-20.20s  State:%-15.15s Watchers %2d\n",
2822                         ast_get_extension_name(hint->exten),
2823                         ast_get_context_name(ast_get_extension_context(hint->exten)),
2824                         ast_get_extension_app(hint->exten),
2825                         ast_extension_state2str(hint->laststate), watchers);
2826                 num++;
2827         }
2828         ast_cli(fd, "----------------\n");
2829         ast_cli(fd, "- %d hints registered\n", num);
2830         AST_LIST_UNLOCK(&hints);
2831         return RESULT_SUCCESS;
2832 }
2833
2834 /*! \brief  handle_show_switches: CLI support for listing registred dial plan switches */
2835 static int handle_show_switches(int fd, int argc, char *argv[])
2836 {
2837         struct ast_switch *sw;
2838
2839         AST_LIST_LOCK(&switches);
2840         
2841         if (AST_LIST_EMPTY(&switches)) {
2842                 AST_LIST_UNLOCK(&switches);
2843                 ast_cli(fd, "There are no registered alternative switches\n");
2844                 return RESULT_SUCCESS;
2845         }
2846
2847         ast_cli(fd, "\n    -= Registered Asterisk Alternative Switches =-\n");
2848         AST_LIST_TRAVERSE(&switches, sw, list)
2849                 ast_cli(fd, "%s: %s\n", sw->name, sw->description);
2850
2851         AST_LIST_UNLOCK(&switches);
2852
2853         return RESULT_SUCCESS;
2854 }
2855
2856 /*
2857  * 'show applications' CLI command implementation functions ...
2858  */
2859 static int handle_show_applications(int fd, int argc, char *argv[])
2860 {
2861         struct ast_app *a;
2862         int like = 0, describing = 0;
2863         int total_match = 0;    /* Number of matches in like clause */
2864         int total_apps = 0;     /* Number of apps registered */
2865         
2866         AST_LIST_LOCK(&apps);
2867
2868         if (AST_LIST_EMPTY(&apps)) {
2869                 ast_cli(fd, "There are no registered applications\n");
2870                 AST_LIST_UNLOCK(&apps);
2871                 return -1;
2872         }
2873
2874         /* show applications like <keyword> */
2875         if ((argc == 4) && (!strcmp(argv[2], "like"))) {
2876                 like = 1;
2877         } else if ((argc > 3) && (!strcmp(argv[2], "describing"))) {
2878                 describing = 1;
2879         }
2880
2881         /* show applications describing <keyword1> [<keyword2>] [...] */
2882         if ((!like) && (!describing)) {
2883                 ast_cli(fd, "    -= Registered Asterisk Applications =-\n");
2884         } else {
2885                 ast_cli(fd, "    -= Matching Asterisk Applications =-\n");
2886         }
2887
2888         AST_LIST_TRAVERSE(&apps, a, list) {
2889                 int printapp = 0;
2890                 total_apps++;
2891                 if (like) {
2892                         if (strcasestr(a->name, argv[3])) {
2893                                 printapp = 1;
2894                                 total_match++;
2895                         }
2896                 } else if (describing) {
2897                         if (a->description) {
2898                                 /* Match all words on command line */
2899                                 int i;
2900                                 printapp = 1;
2901                                 for (i = 3; i < argc; i++) {
2902                                         if (!strcasestr(a->description, argv[i])) {
2903                                                 printapp = 0;
2904                                         } else {
2905                                                 total_match++;
2906                                         }
2907                                 }
2908                         }
2909                 } else {
2910                         printapp = 1;
2911                 }
2912
2913                 if (printapp) {
2914                         ast_cli(fd,"  %20s: %s\n", a->name, a->synopsis ? a->synopsis : "<Synopsis not available>");
2915                 }
2916         }
2917         if ((!like) && (!describing)) {
2918                 ast_cli(fd, "    -= %d Applications Registered =-\n",total_apps);
2919         } else {
2920                 ast_cli(fd, "    -= %d Applications Matching =-\n",total_match);
2921         }
2922
2923         AST_LIST_UNLOCK(&apps);
2924
2925         return RESULT_SUCCESS;
2926 }
2927
2928 static char *complete_show_applications(const char *line, const char *word, int pos, int state)
2929 {
2930         static char* choices[] = { "like", "describing", NULL };
2931
2932         return (pos != 2) ? NULL : ast_cli_complete(word, choices, state);
2933 }
2934
2935 /*
2936  * 'show dialplan' CLI command implementation functions ...
2937  */
2938 static char *complete_show_dialplan_context(const char *line, const char *word, int pos,
2939         int state)
2940 {
2941         struct ast_context *c = NULL;
2942         char *ret = NULL;
2943         int which = 0;
2944         int wordlen;
2945
2946         /* we are do completion of [exten@]context on second position only */
2947         if (pos != 2)
2948                 return NULL;
2949
2950         ast_lock_contexts();
2951
2952         wordlen = strlen(word);
2953
2954         /* walk through all contexts and return the n-th match */
2955         while ( (c = ast_walk_contexts(c)) ) {
2956                 if (!strncasecmp(word, ast_get_context_name(c), wordlen) && ++which > state) {
2957                         ret = ast_strdup(ast_get_context_name(c));
2958                         break;
2959                 }
2960         }
2961
2962         ast_unlock_contexts();
2963
2964         return ret;
2965 }
2966
2967 struct dialplan_counters {
2968         int total_context;
2969         int total_exten;
2970         int total_prio;
2971         int context_existence;
2972         int extension_existence;
2973 };
2974
2975 /*! \brief helper function to print an extension */
2976 static void print_ext(struct ast_exten *e, char * buf, int buflen)
2977 {
2978         int prio = ast_get_extension_priority(e);
2979         if (prio == PRIORITY_HINT) {
2980                 snprintf(buf, buflen, "hint: %s",
2981                         ast_get_extension_app(e));
2982         } else {
2983                 snprintf(buf, buflen, "%d. %s(%s)",
2984                         prio, ast_get_extension_app(e),
2985                         (char *)ast_get_extension_app_data(e));
2986         }
2987 }
2988
2989 /* XXX not verified */
2990 static int show_dialplan_helper(int fd, const char *context, const char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude, int includecount, char *includes[])   
2991 {
2992         struct ast_context *c = NULL;
2993         int res = 0, old_total_exten = dpc->total_exten;
2994
2995         ast_lock_contexts();
2996
2997         /* walk all contexts ... */
2998         while ( (c = ast_walk_contexts(c)) ) {
2999                 struct ast_exten *e;
3000                 struct ast_include *i;
3001                 struct ast_ignorepat *ip;
3002                 char buf[256], buf2[256];
3003                 int context_info_printed = 0;
3004
3005                 if (context && strcmp(ast_get_context_name(c), context))
3006                         continue;       /* skip this one, name doesn't match */
3007
3008                 dpc->context_existence = 1;
3009
3010                 ast_lock_context(c);
3011
3012                 /* are we looking for exten too? if yes, we print context
3013                  * only if we find our extension.
3014                  * Otherwise print context even if empty ?
3015                  * XXX i am not sure how the rinclude is handled.
3016                  * I think it ought to go inside.
3017                  */
3018                 if (!exten) {
3019                         dpc->total_context++;
3020                         ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
3021                                 ast_get_context_name(c), ast_get_context_registrar(c));
3022                         context_info_printed = 1;
3023                 }
3024
3025                 /* walk extensions ... */
3026                 e = NULL;
3027                 while ( (e = ast_walk_context_extensions(c, e)) ) {
3028                         struct ast_exten *p;
3029
3030                         if (exten && !ast_extension_match(ast_get_extension_name(e), exten))
3031                                 continue;       /* skip, extension match failed */
3032
3033                         dpc->extension_existence = 1;
3034
3035                         /* may we print context info? */        
3036                         if (!context_info_printed) {
3037                                 dpc->total_context++;
3038                                 if (rinclude) { /* TODO Print more info about rinclude */
3039                                         ast_cli(fd, "[ Included context '%s' created by '%s' ]\n",
3040                                                 ast_get_context_name(c), ast_get_context_registrar(c));
3041                                 } else {
3042                                         ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
3043                                                 ast_get_context_name(c), ast_get_context_registrar(c));
3044                                 }
3045                                 context_info_printed = 1;
3046                         }
3047                         dpc->total_prio++;
3048
3049                         /* write extension name and first peer */       
3050                         snprintf(buf, sizeof(buf), "'%s' =>", ast_get_extension_name(e));
3051
3052                         print_ext(e, buf2, sizeof(buf2));
3053
3054                         ast_cli(fd, "  %-17s %-45s [%s]\n", buf, buf2,
3055                                 ast_get_extension_registrar(e));
3056
3057                         dpc->total_exten++;
3058                         /* walk next extension peers */
3059                         p = e;  /* skip the first one, we already got it */
3060                         while ( (p = ast_walk_extension_priorities(e, p)) ) {
3061                                 const char *el = ast_get_extension_label(p);
3062                                 dpc->total_prio++;
3063                                 if (el)
3064                                         snprintf(buf, sizeof(buf), "   [%s]", el);
3065                                 else
3066                                         buf[0] = '\0';
3067                                 print_ext(p, buf2, sizeof(buf2));
3068
3069                                 ast_cli(fd,"  %-17s %-45s [%s]\n", buf, buf2,
3070                                         ast_get_extension_registrar(p));
3071                         }
3072                 }
3073
3074                 /* walk included and write info ... */
3075                 i = NULL;
3076                 while ( (i = ast_walk_context_includes(c, i)) ) {
3077                         snprintf(buf, sizeof(buf), "'%s'", ast_get_include_name(i));
3078                         if (exten) {
3079                                 /* Check all includes for the requested extension */
3080                                 if (includecount >= AST_PBX_MAX_STACK) {
3081                                         ast_log(LOG_NOTICE, "Maximum include depth exceeded!\n");
3082                                 } else {
3083                                         int dupe=0;
3084                                         int x;
3085                                         for (x=0;x<includecount;x++) {
3086                                                 if (!strcasecmp(includes[x], ast_get_include_name(i))) {
3087                                                         dupe++;
3088                                                         break;
3089                                                 }
3090                                         }
3091                                         if (!dupe) {
3092                                                 includes[includecount] = (char *)ast_get_include_name(i);
3093                                                 show_dialplan_helper(fd, ast_get_include_name(i), exten, dpc, i, includecount + 1, includes);
3094                                         } else {
3095                                                 ast_log(LOG_WARNING, "Avoiding circular include of %s within %s\n", ast_get_include_name(i), context);
3096                                         }
3097                                 }
3098                         } else {