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