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