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