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