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