Stephn Davies reports that this will help make things work on 64-bit machines
[asterisk/asterisk.git] / utils / extconf.c
1 /*  
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2006, Digium, Inc.
5  *
6  * Steve Murphy <murf@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
20 /*
21  *
22  * A condensation of the pbx_config stuff, to read into exensions.conf, and provide an interface to the data there,
23  * for operations outside of asterisk. A huge, awful hack.
24  *
25  */
26
27 #include "asterisk/autoconfig.h"
28
29 #include <stdio.h>
30 #include <unistd.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <errno.h>
34 #include <time.h>
35 #include <sys/stat.h>
36 #include <sys/types.h>
37 #include <sys/time.h>
38 #include <sys/resource.h>
39 #include <sys/wait.h>
40 #include <stdarg.h>
41 #include <string.h>
42 #include <locale.h>
43 #include <ctype.h>
44 #if !defined(SOLARIS) && !defined(__CYGWIN__)
45 #include <err.h>
46 #endif
47 #include <regex.h>
48 #include <limits.h>
49 #include <pthread.h>
50 #include <netdb.h>
51 #include <sys/param.h>
52 #define ASINCLUDE_GLOB 1
53 #ifdef AST_INCLUDE_GLOB
54 #if defined(__Darwin__) || defined(__CYGWIN__)
55 #define GLOB_ABORTED GLOB_ABEND
56 #endif
57 # include <glob.h>
58 #endif
59
60 static char ast_config_AST_CONFIG_DIR[PATH_MAX] = {"/etc/asterisk"};
61 #define AST_API_MODULE  1 /* gimme the inline defs! */
62 struct ast_channel 
63 {
64         char x; /* basically empty! */
65 };
66
67
68
69 #include "asterisk/inline_api.h"
70 #include "asterisk/compat.h"
71 #include "asterisk/compiler.h"
72 #include "asterisk/endian.h"
73 #include "asterisk/ast_expr.h"
74 #include "asterisk/ael_structs.h"
75 #include "asterisk/pval.h"
76
77 /* logger.h */
78 #define EVENTLOG "event_log"
79 #define QUEUELOG        "queue_log"
80
81 #define DEBUG_M(a) { \
82         a; \
83 }
84
85 #define VERBOSE_PREFIX_1 " "
86 #define VERBOSE_PREFIX_2 "  == "
87 #define VERBOSE_PREFIX_3 "    -- "
88 #define VERBOSE_PREFIX_4 "       > "
89
90 /* IN CONFLICT: void ast_log(int level, const char *file, int line, const char *function, const char *fmt, ...)
91    __attribute__ ((format (printf, 5, 6))); */
92
93 static void ast_log(int level, const char *file, int line, const char *function, const char *fmt, ...) __attribute__ ((format (printf,5,6)));
94
95
96 void ast_backtrace(void);
97
98 void ast_queue_log(const char *queuename, const char *callid, const char *agent, const char *event, const char *fmt, ...)
99         __attribute__ ((format (printf, 5, 6)));
100
101 /* IN CONFLICT: void ast_verbose(const char *fmt, ...)
102    __attribute__ ((format (printf, 1, 2))); */
103
104 int ast_register_verbose(void (*verboser)(const char *string));
105 int ast_unregister_verbose(void (*verboser)(const char *string));
106
107 void ast_console_puts(const char *string);
108
109 void ast_console_puts_mutable(const char *string);
110 void ast_console_toggle_mute(int fd);
111
112 #define _A_ __FILE__, __LINE__, __PRETTY_FUNCTION__
113
114 #ifdef LOG_DEBUG
115 #undef LOG_DEBUG
116 #endif
117 #define __LOG_DEBUG    0
118 #define LOG_DEBUG      __LOG_DEBUG, _A_
119
120 #ifdef LOG_EVENT
121 #undef LOG_EVENT
122 #endif
123 #define __LOG_EVENT    1
124 #define LOG_EVENT      __LOG_EVENT, _A_
125
126 #ifdef LOG_NOTICE
127 #undef LOG_NOTICE
128 #endif
129 #define __LOG_NOTICE   2
130 #define LOG_NOTICE     __LOG_NOTICE, _A_
131
132 #ifdef LOG_WARNING
133 #undef LOG_WARNING
134 #endif
135 #define __LOG_WARNING  3
136 #define LOG_WARNING    __LOG_WARNING, _A_
137
138 #ifdef LOG_ERROR
139 #undef LOG_ERROR
140 #endif
141 #define __LOG_ERROR    4
142 #define LOG_ERROR      __LOG_ERROR, _A_
143
144 #ifdef LOG_VERBOSE
145 #undef LOG_VERBOSE
146 #endif
147 #define __LOG_VERBOSE  5
148 #define LOG_VERBOSE    __LOG_VERBOSE, _A_
149
150 #ifdef LOG_DTMF
151 #undef LOG_DTMF
152 #endif
153 #define __LOG_DTMF  6
154 #define LOG_DTMF    __LOG_DTMF, _A_
155
156 /* from utils.h */
157
158 static unsigned int __unsigned_int_flags_dummy;
159
160 struct ast_flags {  /* stolen from utils.h */
161         unsigned int flags;
162 };
163 #define ast_test_flag(p,flag)           ({ \
164                                         typeof ((p)->flags) __p = (p)->flags; \
165                                         typeof (__unsigned_int_flags_dummy) __x = 0; \
166                                         (void) (&__p == &__x); \
167                                         ((p)->flags & (flag)); \
168                                         })
169
170 #define ast_set2_flag(p,value,flag)     do { \
171                                         typeof ((p)->flags) __p = (p)->flags; \
172                                         typeof (__unsigned_int_flags_dummy) __x = 0; \
173                                         (void) (&__p == &__x); \
174                                         if (value) \
175                                                 (p)->flags |= (flag); \
176                                         else \
177                                                 (p)->flags &= ~(flag); \
178                                         } while (0)
179
180
181 #ifdef __AST_DEBUG_MALLOC
182 static void ast_free(void *ptr) attribute_unused;
183 static void ast_free(void *ptr)
184 {
185         free(ptr);
186 }
187 #else
188 #define ast_free free
189 #endif
190
191 #ifndef __AST_DEBUG_MALLOC
192
193 #define MALLOC_FAILURE_MSG \
194         ast_log(LOG_ERROR, "Memory Allocation Failure in function %s at line %d of %s\n", func, lineno, file);
195 /*!
196  * \brief A wrapper for malloc()
197  *
198  * ast_malloc() is a wrapper for malloc() that will generate an Asterisk log
199  * message in the case that the allocation fails.
200  *
201  * The argument and return value are the same as malloc()
202  */
203 #define ast_malloc(len) \
204         _ast_malloc((len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
205
206 AST_INLINE_API(
207 void * attribute_malloc _ast_malloc(size_t len, const char *file, int lineno, const char *func),
208 {
209         void *p;
210
211         if (!(p = malloc(len)))
212                 MALLOC_FAILURE_MSG;
213
214         return p;
215 }
216 )
217
218 /*!
219  * \brief A wrapper for calloc()
220  *
221  * ast_calloc() is a wrapper for calloc() that will generate an Asterisk log
222  * message in the case that the allocation fails.
223  *
224  * The arguments and return value are the same as calloc()
225  */
226 #define ast_calloc(num, len) \
227         _ast_calloc((num), (len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
228
229 AST_INLINE_API(
230 void * attribute_malloc _ast_calloc(size_t num, size_t len, const char *file, int lineno, const char *func),
231 {
232         void *p;
233
234         if (!(p = calloc(num, len)))
235                 MALLOC_FAILURE_MSG;
236
237         return p;
238 }
239 )
240
241 /*!
242  * \brief A wrapper for calloc() for use in cache pools
243  *
244  * ast_calloc_cache() is a wrapper for calloc() that will generate an Asterisk log
245  * message in the case that the allocation fails. When memory debugging is in use,
246  * the memory allocated by this function will be marked as 'cache' so it can be
247  * distinguished from normal memory allocations.
248  *
249  * The arguments and return value are the same as calloc()
250  */
251 #define ast_calloc_cache(num, len) \
252         _ast_calloc((num), (len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
253
254 /*!
255  * \brief A wrapper for realloc()
256  *
257  * ast_realloc() is a wrapper for realloc() that will generate an Asterisk log
258  * message in the case that the allocation fails.
259  *
260  * The arguments and return value are the same as realloc()
261  */
262 #define ast_realloc(p, len) \
263         _ast_realloc((p), (len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
264
265 AST_INLINE_API(
266 void * attribute_malloc _ast_realloc(void *p, size_t len, const char *file, int lineno, const char *func),
267 {
268         void *newp;
269
270         if (!(newp = realloc(p, len)))
271                 MALLOC_FAILURE_MSG;
272
273         return newp;
274 }
275 )
276
277 /*!
278  * \brief A wrapper for strdup()
279  *
280  * ast_strdup() is a wrapper for strdup() that will generate an Asterisk log
281  * message in the case that the allocation fails.
282  *
283  * ast_strdup(), unlike strdup(), can safely accept a NULL argument. If a NULL
284  * argument is provided, ast_strdup will return NULL without generating any
285  * kind of error log message.
286  *
287  * The argument and return value are the same as strdup()
288  */
289 #define ast_strdup(str) \
290         _ast_strdup((str), __FILE__, __LINE__, __PRETTY_FUNCTION__)
291
292 AST_INLINE_API(
293 char * attribute_malloc _ast_strdup(const char *str, const char *file, int lineno, const char *func),
294 {
295         char *newstr = NULL;
296
297         if (str) {
298                 if (!(newstr = strdup(str)))
299                         MALLOC_FAILURE_MSG;
300         }
301
302         return newstr;
303 }
304 )
305
306 /*!
307  * \brief A wrapper for strndup()
308  *
309  * ast_strndup() is a wrapper for strndup() that will generate an Asterisk log
310  * message in the case that the allocation fails.
311  *
312  * ast_strndup(), unlike strndup(), can safely accept a NULL argument for the
313  * string to duplicate. If a NULL argument is provided, ast_strdup will return  
314  * NULL without generating any kind of error log message.
315  *
316  * The arguments and return value are the same as strndup()
317  */
318 #define ast_strndup(str, len) \
319         _ast_strndup((str), (len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
320
321 AST_INLINE_API(
322 char * attribute_malloc _ast_strndup(const char *str, size_t len, const char *file, int lineno, const char *func),
323 {
324         char *newstr = NULL;
325
326         if (str) {
327                 if (!(newstr = strndup(str, len)))
328                         MALLOC_FAILURE_MSG;
329         }
330
331         return newstr;
332 }
333 )
334
335 /*!
336  * \brief A wrapper for asprintf()
337  *
338  * ast_asprintf() is a wrapper for asprintf() that will generate an Asterisk log
339  * message in the case that the allocation fails.
340  *
341  * The arguments and return value are the same as asprintf()
342  */
343 #define ast_asprintf(ret, fmt, ...) \
344         _ast_asprintf((ret), __FILE__, __LINE__, __PRETTY_FUNCTION__, fmt, __VA_ARGS__)
345
346 AST_INLINE_API(
347 int _ast_asprintf(char **ret, const char *file, int lineno, const char *func, const char *fmt, ...),
348 {
349         int res;
350         va_list ap;
351
352         va_start(ap, fmt);
353         if ((res = vasprintf(ret, fmt, ap)) == -1)
354                 MALLOC_FAILURE_MSG;
355         va_end(ap);
356
357         return res;
358 }
359 )
360
361 /*!
362  * \brief A wrapper for vasprintf()
363  *
364  * ast_vasprintf() is a wrapper for vasprintf() that will generate an Asterisk log
365  * message in the case that the allocation fails.
366  *
367  * The arguments and return value are the same as vasprintf()
368  */
369 #define ast_vasprintf(ret, fmt, ap) \
370         _ast_vasprintf((ret), __FILE__, __LINE__, __PRETTY_FUNCTION__, (fmt), (ap))
371
372 AST_INLINE_API(
373 int _ast_vasprintf(char **ret, const char *file, int lineno, const char *func, const char *fmt, va_list ap),
374 {
375         int res;
376
377         if ((res = vasprintf(ret, fmt, ap)) == -1)
378                 MALLOC_FAILURE_MSG;
379
380         return res;
381 }
382 )
383
384 #else
385
386 /* If astmm is in use, let it handle these.  Otherwise, it will report that
387    all allocations are coming from this header file */
388
389 #define ast_malloc(a)           malloc(a)
390 #define ast_calloc(a,b)         calloc(a,b)
391 #define ast_realloc(a,b)        realloc(a,b)
392 #define ast_strdup(a)           strdup(a)
393 #define ast_strndup(a,b)        strndup(a,b)
394 #define ast_asprintf(a,b,c)     asprintf(a,b,c)
395 #define ast_vasprintf(a,b,c)    vasprintf(a,b,c)
396
397 #endif /* AST_DEBUG_MALLOC */
398
399 #if !defined(ast_strdupa) && defined(__GNUC__)
400 /*!
401   \brief duplicate a string in memory from the stack
402   \param s The string to duplicate
403
404   This macro will duplicate the given string.  It returns a pointer to the stack
405   allocatted memory for the new string.
406 */
407 #define ast_strdupa(s)                                                    \
408         (__extension__                                                    \
409         ({                                                                \
410                 const char *__old = (s);                                  \
411                 size_t __len = strlen(__old) + 1;                         \
412                 char *__new = __builtin_alloca(__len);                    \
413                 memcpy (__new, __old, __len);                             \
414                 __new;                                                    \
415         }))
416 #endif
417
418
419 /* from config.c */
420
421 #define MAX_NESTED_COMMENTS 128
422 #define COMMENT_START ";--"
423 #define COMMENT_END "--;"
424 #define COMMENT_META ';'
425 #define COMMENT_TAG '-'
426
427 static char *extconfig_conf = "extconfig.conf";
428
429 /*! Growable string buffer */
430 static char *comment_buffer;   /*!< this will be a comment collector.*/
431 static int   comment_buffer_size;  /*!< the amount of storage so far alloc'd for the comment_buffer */
432
433 static char *lline_buffer;    /*!< A buffer for stuff behind the ; */
434 static int  lline_buffer_size;
435
436 #define CB_INCR 250
437
438 struct ast_comment {
439         struct ast_comment *next;
440         char cmt[0];
441 };
442
443 static void CB_INIT(void)
444 {
445         if (!comment_buffer) {
446                 comment_buffer = ast_malloc(CB_INCR);
447                 if (!comment_buffer)
448                         return;
449                 comment_buffer[0] = 0;
450                 comment_buffer_size = CB_INCR;
451                 lline_buffer = ast_malloc(CB_INCR);
452                 if (!lline_buffer)
453                         return;
454                 lline_buffer[0] = 0;
455                 lline_buffer_size = CB_INCR;
456         } else {
457                 comment_buffer[0] = 0;
458                 lline_buffer[0] = 0;
459         }
460 }
461
462 static void  CB_ADD(char *str)
463 {
464         int rem = comment_buffer_size - strlen(comment_buffer) - 1;
465         int siz = strlen(str);
466         if (rem < siz+1) {
467                 comment_buffer = ast_realloc(comment_buffer, comment_buffer_size + CB_INCR + siz + 1);
468                 if (!comment_buffer)
469                         return;
470                 comment_buffer_size += CB_INCR+siz+1;
471         }
472         strcat(comment_buffer,str);
473 }
474
475 static void  CB_ADD_LEN(char *str, int len)
476 {
477         int cbl = strlen(comment_buffer) + 1;
478         int rem = comment_buffer_size - cbl;
479         if (rem < len+1) {
480                 comment_buffer = ast_realloc(comment_buffer, comment_buffer_size + CB_INCR + len + 1);
481                 if (!comment_buffer)
482                         return;
483                 comment_buffer_size += CB_INCR+len+1;
484         }
485         strncat(comment_buffer,str,len);
486         comment_buffer[cbl+len-1] = 0;
487 }
488
489 static void  LLB_ADD(char *str)
490 {
491         int rem = lline_buffer_size - strlen(lline_buffer) - 1;
492         int siz = strlen(str);
493         if (rem < siz+1) {
494                 lline_buffer = ast_realloc(lline_buffer, lline_buffer_size + CB_INCR + siz + 1);
495                 if (!lline_buffer) 
496                         return;
497                 lline_buffer_size += CB_INCR + siz + 1;
498         }
499         strcat(lline_buffer,str);
500 }
501
502 static void CB_RESET(void )  
503
504         comment_buffer[0] = 0; 
505         lline_buffer[0] = 0;
506 }
507                 
508 /*! \brief Keep track of how many threads are currently trying to wait*() on
509  *  a child process */
510 static unsigned int safe_system_level = 0;
511 static void *safe_system_prev_handler;
512
513 /*! \brief NULL handler so we can collect the child exit status */
514 static void null_sig_handler(int signal)
515 {
516
517 }
518
519 void ast_replace_sigchld(void);
520
521 void ast_replace_sigchld(void)
522 {
523         unsigned int level;
524
525         level = safe_system_level++;
526
527         /* only replace the handler if it has not already been done */
528         if (level == 0)
529                 safe_system_prev_handler = signal(SIGCHLD, null_sig_handler);
530
531 }
532
533 void ast_unreplace_sigchld(void);
534
535 void ast_unreplace_sigchld(void)
536 {
537         unsigned int level;
538
539         level = --safe_system_level;
540
541         /* only restore the handler if we are the last one */
542         if (level == 0)
543                 signal(SIGCHLD, safe_system_prev_handler);
544
545 }
546
547 int ast_safe_system(const char *s);
548
549 int ast_safe_system(const char *s)
550 {
551         pid_t pid;
552 #ifdef HAVE_WORKING_FORK
553         int x;
554 #endif
555         int res;
556         struct rusage rusage;
557         int status;
558
559 #if defined(HAVE_WORKING_FORK) || defined(HAVE_WORKING_VFORK)
560         ast_replace_sigchld();
561
562 #ifdef HAVE_WORKING_FORK
563         pid = fork();
564 #else
565         pid = vfork();
566 #endif  
567
568         if (pid == 0) {
569 #ifdef HAVE_WORKING_FORK
570                 /* Close file descriptors and launch system command */
571                 for (x = STDERR_FILENO + 1; x < 4096; x++)
572                         close(x);
573 #endif
574                 execl("/bin/sh", "/bin/sh", "-c", s, (char *) NULL);
575                 _exit(1);
576         } else if (pid > 0) {
577                 for(;;) {
578                         res = wait4(pid, &status, 0, &rusage);
579                         if (res > -1) {
580                                 res = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
581                                 break;
582                         } else if (errno != EINTR) 
583                                 break;
584                 }
585         } else {
586                 ast_log(LOG_WARNING, "Fork failed: %s\n", strerror(errno));
587                 res = -1;
588         }
589
590         ast_unreplace_sigchld();
591 #else
592         res = -1;
593 #endif
594
595         return res;
596 }
597
598 static struct ast_comment *ALLOC_COMMENT(const char *buffer)
599
600         struct ast_comment *x = ast_calloc(1,sizeof(struct ast_comment)+strlen(buffer)+1);
601         strcpy(x->cmt, buffer);
602         return x;
603 }
604
605 static struct ast_config_map {
606         struct ast_config_map *next;
607         char *name;
608         char *driver;
609         char *database;
610         char *table;
611         char stuff[0];
612 } *config_maps = NULL;
613
614 static struct ast_config_engine *config_engine_list;
615
616 #define MAX_INCLUDE_LEVEL 10
617
618
619 struct ast_category {
620         char name[80];
621         int ignored;                    /*!< do not let user of the config see this category */
622         int include_level;      
623         struct ast_comment *precomments;
624         struct ast_comment *sameline;
625         struct ast_variable *root;
626         struct ast_variable *last;
627         struct ast_category *next;
628 };
629
630 struct ast_config {
631         struct ast_category *root;
632         struct ast_category *last;
633         struct ast_category *current;
634         struct ast_category *last_browse;               /*!< used to cache the last category supplied via category_browse */
635         int include_level;
636         int max_include_level;
637 };
638
639 typedef struct ast_config *config_load_func(const char *database, const char *table, const char *configfile, struct ast_config *config, int withcomments);
640 typedef struct ast_variable *realtime_var_get(const char *database, const char *table, va_list ap);
641 typedef struct ast_config *realtime_multi_get(const char *database, const char *table, va_list ap);
642 typedef int realtime_update(const char *database, const char *table, const char *keyfield, const char *entity, va_list ap);
643
644 /*! \brief Configuration engine structure, used to define realtime drivers */
645 struct ast_config_engine {
646         char *name;
647         config_load_func *load_func;
648         realtime_var_get *realtime_func;
649         realtime_multi_get *realtime_multi_func;
650         realtime_update *update_func;
651         struct ast_config_engine *next;
652 };
653
654 static struct ast_config_engine *config_engine_list;
655
656 /* from config.h */
657
658 struct ast_variable {
659         char *name;
660         char *value;
661         int lineno;
662         int object;             /*!< 0 for variable, 1 for object */
663         int blanklines;         /*!< Number of blanklines following entry */
664         struct ast_comment *precomments;
665         struct ast_comment *sameline;
666         struct ast_variable *next;
667         char stuff[0];
668 };
669
670 static const char *ast_variable_retrieve(const struct ast_config *config, const char *category, const char *variable);
671 static struct ast_config *config_text_file_load(const char *database, const char *table, const char *filename, struct ast_config *cfg, int withcomments);
672
673 struct ast_config *localized_config_load_with_comments(const char *filename);
674 static char *ast_category_browse(struct ast_config *config, const char *prev);
675 static struct ast_variable *ast_variable_browse(const struct ast_config *config, const char *category);
676 static void ast_variables_destroy(struct ast_variable *v);
677 static void ast_config_destroy(struct ast_config *cfg);
678
679 static struct ast_variable *ast_variable_new(const char *name, const char *value);
680
681 static struct ast_variable *ast_variable_new(const char *name, const char *value) 
682 {
683         struct ast_variable *variable;
684         int name_len = strlen(name) + 1;        
685
686         if ((variable = ast_calloc(1, name_len + strlen(value) + 1 + sizeof(*variable)))) {
687                 variable->name = variable->stuff;
688                 variable->value = variable->stuff + name_len;           
689                 strcpy(variable->name,name);
690                 strcpy(variable->value,value);
691         }
692
693         return variable;
694 }
695
696 static void ast_variable_append(struct ast_category *category, struct ast_variable *variable);
697
698 static void ast_variable_append(struct ast_category *category, struct ast_variable *variable)
699 {
700         if (!variable)
701                 return;
702         if (category->last)
703                 category->last->next = variable;
704         else
705                 category->root = variable;
706         category->last = variable;
707         while (category->last->next)
708                 category->last = category->last->next;
709 }
710
711 static struct ast_category *category_get(const struct ast_config *config, const char *category_name, int ignored);
712
713 static struct ast_category *category_get(const struct ast_config *config, const char *category_name, int ignored)
714 {
715         struct ast_category *cat;
716
717         /* try exact match first, then case-insensitive match */
718         for (cat = config->root; cat; cat = cat->next) {
719                 if (cat->name == category_name && (ignored || !cat->ignored))
720                         return cat;
721         }
722
723         for (cat = config->root; cat; cat = cat->next) {
724                 if (!strcasecmp(cat->name, category_name) && (ignored || !cat->ignored))
725                         return cat;
726         }
727
728         return NULL;
729 }
730
731 static struct ast_category *ast_category_get(const struct ast_config *config, const char *category_name)
732 {
733         return category_get(config, category_name, 0);
734 }
735
736 static struct ast_variable *ast_variable_browse(const struct ast_config *config, const char *category)
737 {
738         struct ast_category *cat = NULL;
739
740         if (category && config->last_browse && (config->last_browse->name == category))
741                 cat = config->last_browse;
742         else
743                 cat = ast_category_get(config, category);
744
745         return (cat) ? cat->root : NULL;
746 }
747
748 static const char *ast_variable_retrieve(const struct ast_config *config, const char *category, const char *variable)
749 {
750         struct ast_variable *v;
751
752         if (category) {
753                 for (v = ast_variable_browse(config, category); v; v = v->next) {
754                         if (!strcasecmp(variable, v->name))
755                                 return v->value;
756                 }
757         } else {
758                 struct ast_category *cat;
759
760                 for (cat = config->root; cat; cat = cat->next)
761                         for (v = cat->root; v; v = v->next)
762                                 if (!strcasecmp(variable, v->name))
763                                         return v->value;
764         }
765
766         return NULL;
767 }
768
769 static struct ast_variable *variable_clone(const struct ast_variable *old)
770 {
771         struct ast_variable *new = ast_variable_new(old->name, old->value);
772
773         if (new) {
774                 new->lineno = old->lineno;
775                 new->object = old->object;
776                 new->blanklines = old->blanklines;
777                 /* TODO: clone comments? */
778         }
779
780         return new;
781 }
782  
783 static void ast_variables_destroy(struct ast_variable *v)
784 {
785         struct ast_variable *vn;
786
787         while (v) {
788                 vn = v;
789                 v = v->next;
790                 free(vn);
791         }
792 }
793
794 static void ast_config_destroy(struct ast_config *cfg)
795 {
796         struct ast_category *cat, *catn;
797
798         if (!cfg)
799                 return;
800
801         cat = cfg->root;
802         while (cat) {
803                 ast_variables_destroy(cat->root);
804                 catn = cat;
805                 cat = cat->next;
806                 free(catn);
807         }
808         free(cfg);
809 }
810
811
812 /* options.h declars ast_options extern; I need it static? */
813
814 #define AST_CACHE_DIR_LEN       512
815 #define AST_FILENAME_MAX        80
816
817 /*! \ingroup main_options */
818 enum ast_option_flags {
819         /*! Allow \#exec in config files */
820         AST_OPT_FLAG_EXEC_INCLUDES = (1 << 0),
821         /*! Do not fork() */
822         AST_OPT_FLAG_NO_FORK = (1 << 1),
823         /*! Keep quiet */
824         AST_OPT_FLAG_QUIET = (1 << 2),
825         /*! Console mode */
826         AST_OPT_FLAG_CONSOLE = (1 << 3),
827         /*! Run in realtime Linux priority */
828         AST_OPT_FLAG_HIGH_PRIORITY = (1 << 4),
829         /*! Initialize keys for RSA authentication */
830         AST_OPT_FLAG_INIT_KEYS = (1 << 5),
831         /*! Remote console */
832         AST_OPT_FLAG_REMOTE = (1 << 6),
833         /*! Execute an asterisk CLI command upon startup */
834         AST_OPT_FLAG_EXEC = (1 << 7),
835         /*! Don't use termcap colors */
836         AST_OPT_FLAG_NO_COLOR = (1 << 8),
837         /*! Are we fully started yet? */
838         AST_OPT_FLAG_FULLY_BOOTED = (1 << 9),
839         /*! Trascode via signed linear */
840         AST_OPT_FLAG_TRANSCODE_VIA_SLIN = (1 << 10),
841         /*! Enable priority jumping in applications */
842         AST_OPT_FLAG_PRIORITY_JUMPING = (1 << 11),
843         /*! Dump core on a seg fault */
844         AST_OPT_FLAG_DUMP_CORE = (1 << 12),
845         /*! Cache sound files */
846         AST_OPT_FLAG_CACHE_RECORD_FILES = (1 << 13),
847         /*! Display timestamp in CLI verbose output */
848         AST_OPT_FLAG_TIMESTAMP = (1 << 14),
849         /*! Override config */
850         AST_OPT_FLAG_OVERRIDE_CONFIG = (1 << 15),
851         /*! Reconnect */
852         AST_OPT_FLAG_RECONNECT = (1 << 16),
853         /*! Transmit Silence during Record() */
854         AST_OPT_FLAG_TRANSMIT_SILENCE = (1 << 17),
855         /*! Suppress some warnings */
856         AST_OPT_FLAG_DONT_WARN = (1 << 18),
857         /*! End CDRs before the 'h' extension */
858         AST_OPT_FLAG_END_CDR_BEFORE_H_EXTEN = (1 << 19),
859         /*! Use Zaptel Timing for generators if available */
860         AST_OPT_FLAG_INTERNAL_TIMING = (1 << 20),
861         /*! Always fork, even if verbose or debug settings are non-zero */
862         AST_OPT_FLAG_ALWAYS_FORK = (1 << 21),
863         /*! Disable log/verbose output to remote consoles */
864         AST_OPT_FLAG_MUTE = (1 << 22)
865 };
866
867 /*! These are the options that set by default when Asterisk starts */
868 #define AST_DEFAULT_OPTIONS AST_OPT_FLAG_TRANSCODE_VIA_SLIN
869
870 #define ast_opt_exec_includes           ast_test_flag(&ast_options, AST_OPT_FLAG_EXEC_INCLUDES)
871 #define ast_opt_no_fork                 ast_test_flag(&ast_options, AST_OPT_FLAG_NO_FORK)
872 #define ast_opt_quiet                   ast_test_flag(&ast_options, AST_OPT_FLAG_QUIET)
873 #define ast_opt_console                 ast_test_flag(&ast_options, AST_OPT_FLAG_CONSOLE)
874 #define ast_opt_high_priority           ast_test_flag(&ast_options, AST_OPT_FLAG_HIGH_PRIORITY)
875 #define ast_opt_init_keys               ast_test_flag(&ast_options, AST_OPT_FLAG_INIT_KEYS)
876 #define ast_opt_remote                  ast_test_flag(&ast_options, AST_OPT_FLAG_REMOTE)
877 #define ast_opt_exec                    ast_test_flag(&ast_options, AST_OPT_FLAG_EXEC)
878 #define ast_opt_no_color                ast_test_flag(&ast_options, AST_OPT_FLAG_NO_COLOR)
879 #define ast_fully_booted                ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)
880 #define ast_opt_transcode_via_slin      ast_test_flag(&ast_options, AST_OPT_FLAG_TRANSCODE_VIA_SLIN)
881 #define ast_opt_priority_jumping        ast_test_flag(&ast_options, AST_OPT_FLAG_PRIORITY_JUMPING)
882 #define ast_opt_dump_core               ast_test_flag(&ast_options, AST_OPT_FLAG_DUMP_CORE)
883 #define ast_opt_cache_record_files      ast_test_flag(&ast_options, AST_OPT_FLAG_CACHE_RECORD_FILES)
884 #define ast_opt_timestamp               ast_test_flag(&ast_options, AST_OPT_FLAG_TIMESTAMP)
885 #define ast_opt_override_config         ast_test_flag(&ast_options, AST_OPT_FLAG_OVERRIDE_CONFIG)
886 #define ast_opt_reconnect               ast_test_flag(&ast_options, AST_OPT_FLAG_RECONNECT)
887 #define ast_opt_transmit_silence        ast_test_flag(&ast_options, AST_OPT_FLAG_TRANSMIT_SILENCE)
888 #define ast_opt_dont_warn               ast_test_flag(&ast_options, AST_OPT_FLAG_DONT_WARN)
889 #define ast_opt_end_cdr_before_h_exten  ast_test_flag(&ast_options, AST_OPT_FLAG_END_CDR_BEFORE_H_EXTEN)
890 #define ast_opt_internal_timing         ast_test_flag(&ast_options, AST_OPT_FLAG_INTERNAL_TIMING)
891 #define ast_opt_always_fork             ast_test_flag(&ast_options, AST_OPT_FLAG_ALWAYS_FORK)
892 #define ast_opt_mute                    ast_test_flag(&ast_options, AST_OPT_FLAG_MUTE)
893
894 /*  IN CONFLICT: extern int option_verbose; */
895 /*  IN CONFLICT: extern int option_debug;       */      /*!< Debugging */
896 extern int option_maxcalls;             /*!< Maximum number of simultaneous channels */
897 extern double option_maxload;
898 extern char defaultlanguage[];
899
900 extern time_t ast_startuptime;
901 extern time_t ast_lastreloadtime;
902 extern pid_t ast_mainpid;
903
904 extern char record_cache_dir[AST_CACHE_DIR_LEN];
905 extern char debug_filename[AST_FILENAME_MAX];
906
907 extern int ast_language_is_prefix;
908
909
910
911 /* lock.h */
912
913 #ifndef HAVE_MTX_PROFILE
914 #define __MTX_PROF(a)   return pthread_mutex_lock((a))
915 #else
916 #define __MTX_PROF(a)   do {                    \
917         int i;                                  \
918         /* profile only non-blocking events */  \
919         ast_mark(mtx_prof, 1);                  \
920         i = pthread_mutex_trylock((a));         \
921         ast_mark(mtx_prof, 0);                  \
922         if (!i)                                 \
923                 return i;                       \
924         else                                    \
925                 return pthread_mutex_lock((a)); \
926         } while (0)
927 #endif  /* HAVE_MTX_PROFILE */
928
929 #define AST_PTHREADT_NULL (pthread_t) -1
930 #define AST_PTHREADT_STOP (pthread_t) -2
931
932 #if defined(SOLARIS) || defined(BSD)
933 #define AST_MUTEX_INIT_W_CONSTRUCTORS
934 #endif /* SOLARIS || BSD */
935
936 /* Asterisk REQUIRES recursive (not error checking) mutexes
937    and will not run without them. */
938 #if defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP)
939 #define PTHREAD_MUTEX_INIT_VALUE        PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
940 #define AST_MUTEX_KIND                  PTHREAD_MUTEX_RECURSIVE_NP
941 #else
942 #define PTHREAD_MUTEX_INIT_VALUE        PTHREAD_MUTEX_INITIALIZER
943 #define AST_MUTEX_KIND                  PTHREAD_MUTEX_RECURSIVE
944 #endif /* PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP */
945
946 #ifdef DEBUG_THREADS
947
948 #define __ast_mutex_logger(...)  do { if (canlog) ast_log(LOG_ERROR, __VA_ARGS__); else fprintf(stderr, __VA_ARGS__); } while (0)
949
950 #ifdef THREAD_CRASH
951 #define DO_THREAD_CRASH do { *((int *)(0)) = 1; } while(0)
952 #else
953 #define DO_THREAD_CRASH do { } while (0)
954 #endif
955
956 #define AST_MUTEX_INIT_VALUE { PTHREAD_MUTEX_INIT_VALUE, { NULL }, { 0 }, 0, { NULL }, { 0 } }
957
958 #define AST_MAX_REENTRANCY 10
959
960 struct ast_mutex_info {
961         pthread_mutex_t mutex;
962         /*! Track which thread holds this lock */
963         unsigned int track:1;
964         const char *file[AST_MAX_REENTRANCY];
965         int lineno[AST_MAX_REENTRANCY];
966         int reentrancy;
967         const char *func[AST_MAX_REENTRANCY];
968         pthread_t thread[AST_MAX_REENTRANCY];
969 };
970
971 typedef struct ast_mutex_info ast_mutex_t;
972
973 typedef pthread_cond_t ast_cond_t;
974
975 static pthread_mutex_t empty_mutex;
976
977 static void __attribute__((constructor)) init_empty_mutex(void)
978 {
979         memset(&empty_mutex, 0, sizeof(empty_mutex));
980 }
981
982 static inline int __ast_pthread_mutex_init_attr(const char *filename, int lineno, const char *func,
983                                                 const char *mutex_name, ast_mutex_t *t,
984                                                 pthread_mutexattr_t *attr) 
985 {
986 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
987         int canlog = strcmp(filename, "logger.c");
988
989         if ((t->mutex) != ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
990                 if ((t->mutex) != (empty_mutex)) {
991                         __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is already initialized.\n",
992                                            filename, lineno, func, mutex_name);
993                         __ast_mutex_logger("%s line %d (%s): Error: previously initialization of mutex '%s'.\n",
994                                            t->file[0], t->lineno[0], t->func[0], mutex_name);
995                         DO_THREAD_CRASH;
996                         return 0;
997                 }
998         }
999 #endif
1000
1001         t->file[0] = filename;
1002         t->lineno[0] = lineno;
1003         t->func[0] = func;
1004         t->thread[0]  = 0;
1005         t->reentrancy = 0;
1006
1007         return pthread_mutex_init(&t->mutex, attr);
1008 }
1009
1010 static inline int __ast_pthread_mutex_init(const char *filename, int lineno, const char *func,
1011                                            const char *mutex_name, ast_mutex_t *t)
1012 {
1013         static pthread_mutexattr_t  attr;
1014
1015         pthread_mutexattr_init(&attr);
1016         pthread_mutexattr_settype(&attr, AST_MUTEX_KIND);
1017
1018         return __ast_pthread_mutex_init_attr(filename, lineno, func, mutex_name, t, &attr);
1019 }
1020 #define ast_mutex_init(pmutex) __ast_pthread_mutex_init(__FILE__, __LINE__, __PRETTY_FUNCTION__, #pmutex, pmutex)
1021
1022 static inline int __ast_pthread_mutex_destroy(const char *filename, int lineno, const char *func,
1023                                                 const char *mutex_name, ast_mutex_t *t)
1024 {
1025         int res;
1026         int canlog = strcmp(filename, "logger.c");
1027
1028 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
1029         if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
1030                 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
1031                                    filename, lineno, func, mutex_name);
1032         }
1033 #endif
1034
1035         res = pthread_mutex_trylock(&t->mutex);
1036         switch (res) {
1037         case 0:
1038                 pthread_mutex_unlock(&t->mutex);
1039                 break;
1040         case EINVAL:
1041                 __ast_mutex_logger("%s line %d (%s): Error: attempt to destroy invalid mutex '%s'.\n",
1042                                   filename, lineno, func, mutex_name);
1043                 break;
1044         case EBUSY:
1045                 __ast_mutex_logger("%s line %d (%s): Error: attempt to destroy locked mutex '%s'.\n",
1046                                    filename, lineno, func, mutex_name);
1047                 __ast_mutex_logger("%s line %d (%s): Error: '%s' was locked here.\n",
1048                                    t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
1049                 break;
1050         }
1051
1052         if ((res = pthread_mutex_destroy(&t->mutex)))
1053                 __ast_mutex_logger("%s line %d (%s): Error destroying mutex: %s\n",
1054                                    filename, lineno, func, strerror(res));
1055 #ifndef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
1056         else
1057                 t->mutex = PTHREAD_MUTEX_INIT_VALUE;
1058 #endif
1059         t->file[0] = filename;
1060         t->lineno[0] = lineno;
1061         t->func[0] = func;
1062
1063         return res;
1064 }
1065
1066 static inline int __ast_pthread_mutex_lock(const char *filename, int lineno, const char *func,
1067                                            const char* mutex_name, ast_mutex_t *t)
1068 {
1069         int res;
1070         int canlog = strcmp(filename, "logger.c");
1071
1072 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
1073         if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
1074                 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
1075                                  filename, lineno, func, mutex_name);
1076                 ast_mutex_init(t);
1077         }
1078 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
1079
1080 #ifdef DETECT_DEADLOCKS
1081         {
1082                 time_t seconds = time(NULL);
1083                 time_t current;
1084                 do {
1085 #ifdef  HAVE_MTX_PROFILE
1086                         ast_mark(mtx_prof, 1);
1087 #endif
1088                         res = pthread_mutex_trylock(&t->mutex);
1089 #ifdef  HAVE_MTX_PROFILE
1090                         ast_mark(mtx_prof, 0);
1091 #endif
1092                         if (res == EBUSY) {
1093                                 current = time(NULL);
1094                                 if ((current - seconds) && (!((current - seconds) % 5))) {
1095                                         __ast_mutex_logger("%s line %d (%s): Deadlock? waited %d sec for mutex '%s'?\n",
1096                                                            filename, lineno, func, (int)(current - seconds), mutex_name);
1097                                         __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
1098                                                            t->file[t->reentrancy-1], t->lineno[t->reentrancy-1],
1099                                                            t->func[t->reentrancy-1], mutex_name);
1100                                 }
1101                                 usleep(200);
1102                         }
1103                 } while (res == EBUSY);
1104         }
1105 #else
1106 #ifdef  HAVE_MTX_PROFILE
1107         ast_mark(mtx_prof, 1);
1108         res = pthread_mutex_trylock(&t->mutex);
1109         ast_mark(mtx_prof, 0);
1110         if (res)
1111 #endif
1112         res = pthread_mutex_lock(&t->mutex);
1113 #endif /* DETECT_DEADLOCKS */
1114
1115         if (!res) {
1116                 if (t->reentrancy < AST_MAX_REENTRANCY) {
1117                         t->file[t->reentrancy] = filename;
1118                         t->lineno[t->reentrancy] = lineno;
1119                         t->func[t->reentrancy] = func;
1120                         t->thread[t->reentrancy] = pthread_self();
1121                         t->reentrancy++;
1122                 } else {
1123                         __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
1124                                                            filename, lineno, func, mutex_name);
1125                 }
1126         } else {
1127                 __ast_mutex_logger("%s line %d (%s): Error obtaining mutex: %s\n",
1128                                    filename, lineno, func, strerror(errno));
1129                 DO_THREAD_CRASH;
1130         }
1131
1132         return res;
1133 }
1134
1135 static inline int __ast_pthread_mutex_trylock(const char *filename, int lineno, const char *func,
1136                                               const char* mutex_name, ast_mutex_t *t)
1137 {
1138         int res;
1139         int canlog = strcmp(filename, "logger.c");
1140
1141 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
1142         if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
1143                 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
1144                                    filename, lineno, func, mutex_name);
1145                 ast_mutex_init(t);
1146         }
1147 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
1148
1149         if (!(res = pthread_mutex_trylock(&t->mutex))) {
1150                 if (t->reentrancy < AST_MAX_REENTRANCY) {
1151                         t->file[t->reentrancy] = filename;
1152                         t->lineno[t->reentrancy] = lineno;
1153                         t->func[t->reentrancy] = func;
1154                         t->thread[t->reentrancy] = pthread_self();
1155                         t->reentrancy++;
1156                 } else {
1157                         __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
1158                                            filename, lineno, func, mutex_name);
1159                 }
1160         } else {
1161                 __ast_mutex_logger("%s line %d (%s): Warning: '%s' was locked here.\n",
1162                                    t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
1163         }
1164
1165         return res;
1166 }
1167
1168 static inline int __ast_pthread_mutex_unlock(const char *filename, int lineno, const char *func,
1169                                              const char *mutex_name, ast_mutex_t *t)
1170 {
1171         int res;
1172         int canlog = strcmp(filename, "logger.c");
1173
1174 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
1175         if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
1176                 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
1177                                    filename, lineno, func, mutex_name);
1178         }
1179 #endif
1180
1181         if (t->reentrancy && (t->thread[t->reentrancy-1] != pthread_self())) {
1182                 __ast_mutex_logger("%s line %d (%s): attempted unlock mutex '%s' without owning it!\n",
1183                                    filename, lineno, func, mutex_name);
1184                 __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
1185                                    t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
1186                 DO_THREAD_CRASH;
1187         }
1188
1189         if (--t->reentrancy < 0) {
1190                 __ast_mutex_logger("%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
1191                                    filename, lineno, func, mutex_name);
1192                 t->reentrancy = 0;
1193         }
1194
1195         if (t->reentrancy < AST_MAX_REENTRANCY) {
1196                 t->file[t->reentrancy] = NULL;
1197                 t->lineno[t->reentrancy] = 0;
1198                 t->func[t->reentrancy] = NULL;
1199                 t->thread[t->reentrancy] = 0;
1200         }
1201
1202         if ((res = pthread_mutex_unlock(&t->mutex))) {
1203                 __ast_mutex_logger("%s line %d (%s): Error releasing mutex: %s\n", 
1204                                    filename, lineno, func, strerror(res));
1205                 DO_THREAD_CRASH;
1206         }
1207
1208         return res;
1209 }
1210
1211 static inline int __ast_cond_init(const char *filename, int lineno, const char *func,
1212                                   const char *cond_name, ast_cond_t *cond, pthread_condattr_t *cond_attr)
1213 {
1214         return pthread_cond_init(cond, cond_attr);
1215 }
1216
1217 static inline int __ast_cond_signal(const char *filename, int lineno, const char *func,
1218                                     const char *cond_name, ast_cond_t *cond)
1219 {
1220         return pthread_cond_signal(cond);
1221 }
1222
1223 static inline int __ast_cond_broadcast(const char *filename, int lineno, const char *func,
1224                                        const char *cond_name, ast_cond_t *cond)
1225 {
1226         return pthread_cond_broadcast(cond);
1227 }
1228
1229 static inline int __ast_cond_destroy(const char *filename, int lineno, const char *func,
1230                                      const char *cond_name, ast_cond_t *cond)
1231 {
1232         return pthread_cond_destroy(cond);
1233 }
1234
1235 static inline int __ast_cond_wait(const char *filename, int lineno, const char *func,
1236                                   const char *cond_name, const char *mutex_name,
1237                                   ast_cond_t *cond, ast_mutex_t *t)
1238 {
1239         int res;
1240         int canlog = strcmp(filename, "logger.c");
1241
1242 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
1243         if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
1244                 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
1245                                    filename, lineno, func, mutex_name);
1246         }
1247 #endif
1248
1249         if (t->reentrancy && (t->thread[t->reentrancy-1] != pthread_self())) {
1250                 __ast_mutex_logger("%s line %d (%s): attempted unlock mutex '%s' without owning it!\n",
1251                                    filename, lineno, func, mutex_name);
1252                 __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
1253                                    t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
1254                 DO_THREAD_CRASH;
1255         }
1256
1257         if (--t->reentrancy < 0) {
1258                 __ast_mutex_logger("%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
1259                                    filename, lineno, func, mutex_name);
1260                 t->reentrancy = 0;
1261         }
1262
1263         if (t->reentrancy < AST_MAX_REENTRANCY) {
1264                 t->file[t->reentrancy] = NULL;
1265                 t->lineno[t->reentrancy] = 0;
1266                 t->func[t->reentrancy] = NULL;
1267                 t->thread[t->reentrancy] = 0;
1268         }
1269
1270         if ((res = pthread_cond_wait(cond, &t->mutex))) {
1271                 __ast_mutex_logger("%s line %d (%s): Error waiting on condition mutex '%s'\n", 
1272                                    filename, lineno, func, strerror(res));
1273                 DO_THREAD_CRASH;
1274         } else {
1275                 if (t->reentrancy < AST_MAX_REENTRANCY) {
1276                         t->file[t->reentrancy] = filename;
1277                         t->lineno[t->reentrancy] = lineno;
1278                         t->func[t->reentrancy] = func;
1279                         t->thread[t->reentrancy] = pthread_self();
1280                         t->reentrancy++;
1281                 } else {
1282                         __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
1283                                                            filename, lineno, func, mutex_name);
1284                 }
1285         }
1286
1287         return res;
1288 }
1289
1290 static inline int __ast_cond_timedwait(const char *filename, int lineno, const char *func,
1291                                        const char *cond_name, const char *mutex_name, ast_cond_t *cond,
1292                                        ast_mutex_t *t, const struct timespec *abstime)
1293 {
1294         int res;
1295         int canlog = strcmp(filename, "logger.c");
1296
1297 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
1298         if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
1299                 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
1300                                    filename, lineno, func, mutex_name);
1301         }
1302 #endif
1303
1304         if (t->reentrancy && (t->thread[t->reentrancy-1] != pthread_self())) {
1305                 __ast_mutex_logger("%s line %d (%s): attempted unlock mutex '%s' without owning it!\n",
1306                                    filename, lineno, func, mutex_name);
1307                 __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
1308                                    t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
1309                 DO_THREAD_CRASH;
1310         }
1311
1312         if (--t->reentrancy < 0) {
1313                 __ast_mutex_logger("%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
1314                                    filename, lineno, func, mutex_name);
1315                 t->reentrancy = 0;
1316         }
1317
1318         if (t->reentrancy < AST_MAX_REENTRANCY) {
1319                 t->file[t->reentrancy] = NULL;
1320                 t->lineno[t->reentrancy] = 0;
1321                 t->func[t->reentrancy] = NULL;
1322                 t->thread[t->reentrancy] = 0;
1323         }
1324
1325         if ((res = pthread_cond_timedwait(cond, &t->mutex, abstime)) && (res != ETIMEDOUT)) {
1326                 __ast_mutex_logger("%s line %d (%s): Error waiting on condition mutex '%s'\n", 
1327                                    filename, lineno, func, strerror(res));
1328                 DO_THREAD_CRASH;
1329         } else {
1330                 if (t->reentrancy < AST_MAX_REENTRANCY) {
1331                         t->file[t->reentrancy] = filename;
1332                         t->lineno[t->reentrancy] = lineno;
1333                         t->func[t->reentrancy] = func;
1334                         t->thread[t->reentrancy] = pthread_self();
1335                         t->reentrancy++;
1336                 } else {
1337                         __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
1338                                                            filename, lineno, func, mutex_name);
1339                 }
1340         }
1341
1342         return res;
1343 }
1344
1345 #define ast_mutex_destroy(a) __ast_pthread_mutex_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
1346 #define ast_mutex_lock(a) __ast_pthread_mutex_lock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
1347 #define ast_mutex_unlock(a) __ast_pthread_mutex_unlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
1348 #define ast_mutex_trylock(a) __ast_pthread_mutex_trylock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
1349 #define ast_cond_init(cond, attr) __ast_cond_init(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond, attr)
1350 #define ast_cond_destroy(cond) __ast_cond_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond)
1351 #define ast_cond_signal(cond) __ast_cond_signal(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond)
1352 #define ast_cond_broadcast(cond) __ast_cond_broadcast(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond)
1353 #define ast_cond_wait(cond, mutex) __ast_cond_wait(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, #mutex, cond, mutex)
1354 #define ast_cond_timedwait(cond, mutex, time) __ast_cond_timedwait(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, #mutex, cond, mutex, time)
1355
1356 #else /* !DEBUG_THREADS */
1357
1358
1359 typedef pthread_mutex_t ast_mutex_t;
1360
1361 #define AST_MUTEX_INIT_VALUE    ((ast_mutex_t) PTHREAD_MUTEX_INIT_VALUE)
1362
1363 static inline int ast_mutex_init(ast_mutex_t *pmutex)
1364 {
1365         pthread_mutexattr_t attr;
1366
1367         pthread_mutexattr_init(&attr);
1368         pthread_mutexattr_settype(&attr, AST_MUTEX_KIND);
1369
1370         return pthread_mutex_init(pmutex, &attr);
1371 }
1372
1373 #define ast_pthread_mutex_init(pmutex,a) pthread_mutex_init(pmutex,a)
1374
1375 static inline int ast_mutex_unlock(ast_mutex_t *pmutex)
1376 {
1377         return pthread_mutex_unlock(pmutex);
1378 }
1379
1380 static inline int ast_mutex_destroy(ast_mutex_t *pmutex)
1381 {
1382         return pthread_mutex_destroy(pmutex);
1383 }
1384
1385 static inline int ast_mutex_lock(ast_mutex_t *pmutex)
1386 {
1387         __MTX_PROF(pmutex);
1388 }
1389
1390 static inline int ast_mutex_trylock(ast_mutex_t *pmutex)
1391 {
1392         return pthread_mutex_trylock(pmutex);
1393 }
1394
1395 typedef pthread_cond_t ast_cond_t;
1396
1397 static inline int ast_cond_init(ast_cond_t *cond, pthread_condattr_t *cond_attr)
1398 {
1399         return pthread_cond_init(cond, cond_attr);
1400 }
1401
1402 static inline int ast_cond_signal(ast_cond_t *cond)
1403 {
1404         return pthread_cond_signal(cond);
1405 }
1406
1407 static inline int ast_cond_broadcast(ast_cond_t *cond)
1408 {
1409         return pthread_cond_broadcast(cond);
1410 }
1411
1412 static inline int ast_cond_destroy(ast_cond_t *cond)
1413 {
1414         return pthread_cond_destroy(cond);
1415 }
1416
1417 static inline int ast_cond_wait(ast_cond_t *cond, ast_mutex_t *t)
1418 {
1419         return pthread_cond_wait(cond, t);
1420 }
1421
1422 static inline int ast_cond_timedwait(ast_cond_t *cond, ast_mutex_t *t, const struct timespec *abstime)
1423 {
1424         return pthread_cond_timedwait(cond, t, abstime);
1425 }
1426
1427 #endif /* !DEBUG_THREADS */
1428
1429 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
1430 /* If AST_MUTEX_INIT_W_CONSTRUCTORS is defined, use file scope
1431  constructors/destructors to create/destroy mutexes.  */
1432 #define __AST_MUTEX_DEFINE(scope, mutex) \
1433         scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE; \
1434 static void  __attribute__ ((constructor)) init_##mutex(void) \
1435 { \
1436         ast_mutex_init(&mutex); \
1437 } \
1438 static void  __attribute__ ((destructor)) fini_##mutex(void) \
1439 { \
1440         ast_mutex_destroy(&mutex); \
1441 }
1442 #else /* !AST_MUTEX_INIT_W_CONSTRUCTORS */
1443 /* By default, use static initialization of mutexes. */ 
1444 #define __AST_MUTEX_DEFINE(scope, mutex) \
1445         scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE
1446 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
1447
1448 #define pthread_mutex_t use_ast_mutex_t_instead_of_pthread_mutex_t
1449 #define pthread_mutex_lock use_ast_mutex_lock_instead_of_pthread_mutex_lock
1450 #define pthread_mutex_unlock use_ast_mutex_unlock_instead_of_pthread_mutex_unlock
1451 #define pthread_mutex_trylock use_ast_mutex_trylock_instead_of_pthread_mutex_trylock
1452 #define pthread_mutex_init use_ast_mutex_init_instead_of_pthread_mutex_init
1453 #define pthread_mutex_destroy use_ast_mutex_destroy_instead_of_pthread_mutex_destroy
1454 #define pthread_cond_t use_ast_cond_t_instead_of_pthread_cond_t
1455 #define pthread_cond_init use_ast_cond_init_instead_of_pthread_cond_init
1456 #define pthread_cond_destroy use_ast_cond_destroy_instead_of_pthread_cond_destroy
1457 #define pthread_cond_signal use_ast_cond_signal_instead_of_pthread_cond_signal
1458 #define pthread_cond_broadcast use_ast_cond_broadcast_instead_of_pthread_cond_broadcast
1459 #define pthread_cond_wait use_ast_cond_wait_instead_of_pthread_cond_wait
1460 #define pthread_cond_timedwait use_ast_cond_timedwait_instead_of_pthread_cond_timedwait
1461
1462 #define AST_MUTEX_DEFINE_STATIC(mutex) __AST_MUTEX_DEFINE(static, mutex)
1463
1464 #define AST_MUTEX_INITIALIZER __use_AST_MUTEX_DEFINE_STATIC_rather_than_AST_MUTEX_INITIALIZER__
1465
1466 #define gethostbyname __gethostbyname__is__not__reentrant__use__ast_gethostbyname__instead__
1467
1468 #ifndef __linux__
1469 #define pthread_create __use_ast_pthread_create_instead__
1470 #endif
1471
1472 typedef pthread_rwlock_t ast_rwlock_t;
1473
1474 static inline int ast_rwlock_init(ast_rwlock_t *prwlock)
1475 {
1476         pthread_rwlockattr_t attr;
1477
1478         pthread_rwlockattr_init(&attr);
1479
1480 #ifdef HAVE_PTHREAD_RWLOCK_PREFER_WRITER_NP
1481         pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NP);
1482 #endif
1483
1484         return pthread_rwlock_init(prwlock, &attr);
1485 }
1486
1487 static inline int ast_rwlock_destroy(ast_rwlock_t *prwlock)
1488 {
1489         return pthread_rwlock_destroy(prwlock);
1490 }
1491
1492 static inline int ast_rwlock_unlock(ast_rwlock_t *prwlock)
1493 {
1494         return pthread_rwlock_unlock(prwlock);
1495 }
1496
1497 static inline int ast_rwlock_rdlock(ast_rwlock_t *prwlock)
1498 {
1499         return pthread_rwlock_rdlock(prwlock);
1500 }
1501
1502 static inline int ast_rwlock_tryrdlock(ast_rwlock_t *prwlock)
1503 {
1504         return pthread_rwlock_tryrdlock(prwlock);
1505 }
1506
1507 static inline int ast_rwlock_wrlock(ast_rwlock_t *prwlock)
1508 {
1509         return pthread_rwlock_wrlock(prwlock);
1510 }
1511
1512 static inline int ast_rwlock_trywrlock(ast_rwlock_t *prwlock)
1513 {
1514         return pthread_rwlock_trywrlock(prwlock);
1515 }
1516
1517 /* Statically declared read/write locks */
1518
1519 #ifndef HAVE_PTHREAD_RWLOCK_INITIALIZER
1520 #define __AST_RWLOCK_DEFINE(scope, rwlock) \
1521         scope ast_rwlock_t rwlock; \
1522 static void  __attribute__ ((constructor)) init_##rwlock(void) \
1523 { \
1524         ast_rwlock_init(&rwlock); \
1525 } \
1526 static void  __attribute__ ((destructor)) fini_##rwlock(void) \
1527 { \
1528         ast_rwlock_destroy(&rwlock); \
1529 }
1530 #else
1531 #define AST_RWLOCK_INIT_VALUE PTHREAD_RWLOCK_INITIALIZER
1532 #define __AST_RWLOCK_DEFINE(scope, rwlock) \
1533         scope ast_rwlock_t rwlock = AST_RWLOCK_INIT_VALUE
1534 #endif
1535
1536 #define AST_RWLOCK_DEFINE_STATIC(rwlock) __AST_RWLOCK_DEFINE(static, rwlock)
1537
1538 /*
1539  * Initial support for atomic instructions.
1540  * For platforms that have it, use the native cpu instruction to
1541  * implement them. For other platforms, resort to a 'slow' version
1542  * (defined in utils.c) that protects the atomic instruction with
1543  * a single lock.
1544  * The slow versions is always available, for testing purposes,
1545  * as ast_atomic_fetchadd_int_slow()
1546  */
1547
1548 int ast_atomic_fetchadd_int_slow(volatile int *p, int v);
1549
1550 #if defined(HAVE_OSX_ATOMICS)
1551 #include "libkern/OSAtomic.h"
1552 #endif
1553
1554 /*! \brief Atomically add v to *p and return * the previous value of *p.
1555  * This can be used to handle reference counts, and the return value
1556  * can be used to generate unique identifiers.
1557  */
1558
1559 #if defined(HAVE_GCC_ATOMICS)
1560 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
1561 {
1562         return __sync_fetch_and_add(p, v);
1563 })
1564 #elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 4)
1565 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
1566 {
1567         return OSAtomicAdd32(v, (int32_t *) p);
1568 })
1569 #elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 8)
1570 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
1571 {
1572         return OSAtomicAdd64(v, (int64_t *) p);
1573 #elif defined (__i386__) || defined(__x86_64__)
1574 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
1575 {
1576         __asm __volatile (
1577         "       lock   xaddl   %0, %1 ;        "
1578         : "+r" (v),                     /* 0 (result) */   
1579           "=m" (*p)                     /* 1 */
1580         : "m" (*p));                    /* 2 */
1581         return (v);
1582 })
1583 #else   /* low performance version in utils.c */
1584 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
1585 {
1586         return ast_atomic_fetchadd_int_slow(p, v);
1587 })
1588 #endif
1589
1590 /*! \brief decrement *p by 1 and return true if the variable has reached 0.
1591  * Useful e.g. to check if a refcount has reached 0.
1592  */
1593 #if defined(HAVE_GCC_ATOMICS)
1594 AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
1595 {
1596         return __sync_sub_and_fetch(p, 1) == 0;
1597 })
1598 #elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 4)
1599 AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
1600 {
1601         return OSAtomicAdd32( -1, (int32_t *) p) == 0;
1602 })
1603 #elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 8)
1604 AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
1605 {
1606         return OSAtomicAdd64( -1, (int64_t *) p) == 0;
1607 #else
1608 AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
1609 {
1610         int a = ast_atomic_fetchadd_int(p, -1);
1611         return a == 1; /* true if the value is 0 now (so it was 1 previously) */
1612 })
1613 #endif
1614
1615 #ifndef DEBUG_CHANNEL_LOCKS
1616 /*! \brief Lock a channel. If DEBUG_CHANNEL_LOCKS is defined 
1617         in the Makefile, print relevant output for debugging */
1618 #define ast_channel_lock(x)             ast_mutex_lock(&x->lock)
1619 /*! \brief Unlock a channel. If DEBUG_CHANNEL_LOCKS is defined 
1620         in the Makefile, print relevant output for debugging */
1621 #define ast_channel_unlock(x)           ast_mutex_unlock(&x->lock)
1622 /*! \brief Try locking a channel. If DEBUG_CHANNEL_LOCKS is defined 
1623         in the Makefile, print relevant output for debugging */
1624 #define ast_channel_trylock(x)          ast_mutex_trylock(&x->lock)
1625 #else
1626
1627 struct ast_channel;
1628
1629 /*! \brief Lock AST channel (and print debugging output)
1630 \note You need to enable DEBUG_CHANNEL_LOCKS for this function */
1631 int ast_channel_lock(struct ast_channel *chan);
1632
1633 /*! \brief Unlock AST channel (and print debugging output)
1634 \note You need to enable DEBUG_CHANNEL_LOCKS for this function
1635 */
1636 int ast_channel_unlock(struct ast_channel *chan);
1637
1638 /*! \brief Lock AST channel (and print debugging output)
1639 \note   You need to enable DEBUG_CHANNEL_LOCKS for this function */
1640 int ast_channel_trylock(struct ast_channel *chan);
1641 #endif
1642
1643
1644 /* linkedlists.h */
1645
1646 #define AST_LIST_LOCK(head)                                             \
1647         ast_mutex_lock(&(head)->lock) 
1648
1649 /*!
1650   \brief Write locks a list.
1651   \param head This is a pointer to the list head structure
1652
1653   This macro attempts to place an exclusive write lock in the
1654   list head structure pointed to by head.
1655   Returns non-zero on success, 0 on failure
1656 */
1657 #define AST_RWLIST_WRLOCK(head)                                         \
1658         ast_rwlock_wrlock(&(head)->lock)
1659
1660 /*!
1661   \brief Read locks a list.
1662   \param head This is a pointer to the list head structure
1663
1664   This macro attempts to place a read lock in the
1665   list head structure pointed to by head.
1666   Returns non-zero on success, 0 on failure
1667 */
1668 #define AST_RWLIST_RDLOCK(head)                                         \
1669         ast_rwlock_rdlock(&(head)->lock)
1670         
1671 /*!
1672   \brief Locks a list, without blocking if the list is locked.
1673   \param head This is a pointer to the list head structure
1674
1675   This macro attempts to place an exclusive lock in the
1676   list head structure pointed to by head.
1677   Returns non-zero on success, 0 on failure
1678 */
1679 #define AST_LIST_TRYLOCK(head)                                          \
1680         ast_mutex_trylock(&(head)->lock) 
1681
1682 /*!
1683   \brief Write locks a list, without blocking if the list is locked.
1684   \param head This is a pointer to the list head structure
1685
1686   This macro attempts to place an exclusive write lock in the
1687   list head structure pointed to by head.
1688   Returns non-zero on success, 0 on failure
1689 */
1690 #define AST_RWLIST_TRYWRLOCK(head)                                      \
1691         ast_rwlock_trywrlock(&(head)->lock)
1692
1693 /*!
1694   \brief Read locks a list, without blocking if the list is locked.
1695   \param head This is a pointer to the list head structure
1696
1697   This macro attempts to place a read lock in the
1698   list head structure pointed to by head.
1699   Returns non-zero on success, 0 on failure
1700 */
1701 #define AST_RWLIST_TRYRDLOCK(head)                                      \
1702         ast_rwlock_tryrdlock(&(head)->lock)
1703         
1704 /*!
1705   \brief Attempts to unlock a list.
1706   \param head This is a pointer to the list head structure
1707
1708   This macro attempts to remove an exclusive lock from the
1709   list head structure pointed to by head. If the list
1710   was not locked by this thread, this macro has no effect.
1711 */
1712 #define AST_LIST_UNLOCK(head)                                           \
1713         ast_mutex_unlock(&(head)->lock)
1714
1715 /*!
1716   \brief Attempts to unlock a read/write based list.
1717   \param head This is a pointer to the list head structure
1718
1719   This macro attempts to remove a read or write lock from the
1720   list head structure pointed to by head. If the list
1721   was not locked by this thread, this macro has no effect.
1722 */
1723 #define AST_RWLIST_UNLOCK(head)                                         \
1724         ast_rwlock_unlock(&(head)->lock)
1725
1726 /*!
1727   \brief Defines a structure to be used to hold a list of specified type.
1728   \param name This will be the name of the defined structure.
1729   \param type This is the type of each list entry.
1730
1731   This macro creates a structure definition that can be used
1732   to hold a list of the entries of type \a type. It does not actually
1733   declare (allocate) a structure; to do that, either follow this
1734   macro with the desired name of the instance you wish to declare,
1735   or use the specified \a name to declare instances elsewhere.
1736
1737   Example usage:
1738   \code
1739   static AST_LIST_HEAD(entry_list, entry) entries;
1740   \endcode
1741
1742   This would define \c struct \c entry_list, and declare an instance of it named
1743   \a entries, all intended to hold a list of type \c struct \c entry.
1744 */
1745 #define AST_LIST_HEAD(name, type)                                       \
1746 struct name {                                                           \
1747         struct type *first;                                             \
1748         struct type *last;                                              \
1749         ast_mutex_t lock;                                               \
1750 }
1751
1752 /*!
1753   \brief Defines a structure to be used to hold a read/write list of specified type.
1754   \param name This will be the name of the defined structure.
1755   \param type This is the type of each list entry.
1756
1757   This macro creates a structure definition that can be used
1758   to hold a list of the entries of type \a type. It does not actually
1759   declare (allocate) a structure; to do that, either follow this
1760   macro with the desired name of the instance you wish to declare,
1761   or use the specified \a name to declare instances elsewhere.
1762
1763   Example usage:
1764   \code
1765   static AST_RWLIST_HEAD(entry_list, entry) entries;
1766   \endcode
1767
1768   This would define \c struct \c entry_list, and declare an instance of it named
1769   \a entries, all intended to hold a list of type \c struct \c entry.
1770 */
1771 #define AST_RWLIST_HEAD(name, type)                                     \
1772 struct name {                                                           \
1773         struct type *first;                                             \
1774         struct type *last;                                              \
1775         ast_rwlock_t lock;                                              \
1776 }
1777
1778 /*!
1779   \brief Defines a structure to be used to hold a list of specified type (with no lock).
1780   \param name This will be the name of the defined structure.
1781   \param type This is the type of each list entry.
1782
1783   This macro creates a structure definition that can be used
1784   to hold a list of the entries of type \a type. It does not actually
1785   declare (allocate) a structure; to do that, either follow this
1786   macro with the desired name of the instance you wish to declare,
1787   or use the specified \a name to declare instances elsewhere.
1788
1789   Example usage:
1790   \code
1791   static AST_LIST_HEAD_NOLOCK(entry_list, entry) entries;
1792   \endcode
1793
1794   This would define \c struct \c entry_list, and declare an instance of it named
1795   \a entries, all intended to hold a list of type \c struct \c entry.
1796 */
1797 #define AST_LIST_HEAD_NOLOCK(name, type)                                \
1798 struct name {                                                           \
1799         struct type *first;                                             \
1800         struct type *last;                                              \
1801 }
1802
1803 /*!
1804   \brief Defines initial values for a declaration of AST_LIST_HEAD
1805 */
1806 #define AST_LIST_HEAD_INIT_VALUE        {               \
1807         .first = NULL,                                  \
1808         .last = NULL,                                   \
1809         .lock = AST_MUTEX_INIT_VALUE,                   \
1810         }
1811
1812 /*!
1813   \brief Defines initial values for a declaration of AST_RWLIST_HEAD
1814 */
1815 #define AST_RWLIST_HEAD_INIT_VALUE      {               \
1816         .first = NULL,                                  \
1817         .last = NULL,                                   \
1818         .lock = AST_RWLOCK_INIT_VALUE,                  \
1819         }
1820
1821 /*!
1822   \brief Defines initial values for a declaration of AST_LIST_HEAD_NOLOCK
1823 */
1824 #define AST_LIST_HEAD_NOLOCK_INIT_VALUE {       \
1825         .first = NULL,                                  \
1826         .last = NULL,                                   \
1827         }
1828
1829 /*!
1830   \brief Defines a structure to be used to hold a list of specified type, statically initialized.
1831   \param name This will be the name of the defined structure.
1832   \param type This is the type of each list entry.
1833
1834   This macro creates a structure definition that can be used
1835   to hold a list of the entries of type \a type, and allocates an instance
1836   of it, initialized to be empty.
1837
1838   Example usage:
1839   \code
1840   static AST_LIST_HEAD_STATIC(entry_list, entry);
1841   \endcode
1842
1843   This would define \c struct \c entry_list, intended to hold a list of
1844   type \c struct \c entry.
1845 */
1846 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
1847 #define AST_LIST_HEAD_STATIC(name, type)                                \
1848 struct name {                                                           \
1849         struct type *first;                                             \
1850         struct type *last;                                              \
1851         ast_mutex_t lock;                                               \
1852 } name;                                                                 \
1853 static void  __attribute__ ((constructor)) init_##name(void)            \
1854 {                                                                       \
1855         AST_LIST_HEAD_INIT(&name);                                      \
1856 }                                                                       \
1857 static void  __attribute__ ((destructor)) fini_##name(void)             \
1858 {                                                                       \
1859         AST_LIST_HEAD_DESTROY(&name);                                   \
1860 }                                                                       \
1861 struct __dummy_##name
1862 #else
1863 #define AST_LIST_HEAD_STATIC(name, type)                                \
1864 struct name {                                                           \
1865         struct type *first;                                             \
1866         struct type *last;                                              \
1867         ast_mutex_t lock;                                               \
1868 } name = AST_LIST_HEAD_INIT_VALUE
1869 #endif
1870
1871 /*!
1872   \brief Defines a structure to be used to hold a read/write list of specified type, statically initialized.
1873   \param name This will be the name of the defined structure.
1874   \param type This is the type of each list entry.
1875
1876   This macro creates a structure definition that can be used
1877   to hold a list of the entries of type \a type, and allocates an instance
1878   of it, initialized to be empty.
1879
1880   Example usage:
1881   \code
1882   static AST_RWLIST_HEAD_STATIC(entry_list, entry);
1883   \endcode
1884
1885   This would define \c struct \c entry_list, intended to hold a list of
1886   type \c struct \c entry.
1887 */
1888 #ifndef AST_RWLOCK_INIT_VALUE
1889 #define AST_RWLIST_HEAD_STATIC(name, type)                              \
1890 struct name {                                                           \
1891         struct type *first;                                             \
1892         struct type *last;                                              \
1893         ast_rwlock_t lock;                                              \
1894 } name;                                                                 \
1895 static void  __attribute__ ((constructor)) init_##name(void)            \
1896 {                                                                       \
1897         AST_RWLIST_HEAD_INIT(&name);                                    \
1898 }                                                                       \
1899 static void  __attribute__ ((destructor)) fini_##name(void)             \
1900 {                                                                       \
1901         AST_RWLIST_HEAD_DESTROY(&name);                                 \
1902 }                                                                       \
1903 struct __dummy_##name
1904 #else
1905 #define AST_RWLIST_HEAD_STATIC(name, type)                              \
1906 struct name {                                                           \
1907         struct type *first;                                             \
1908         struct type *last;                                              \
1909         ast_rwlock_t lock;                                              \
1910 } name = AST_RWLIST_HEAD_INIT_VALUE
1911 #endif
1912
1913 /*!
1914   \brief Defines a structure to be used to hold a list of specified type, statically initialized.
1915
1916   This is the same as AST_LIST_HEAD_STATIC, except without the lock included.
1917 */
1918 #define AST_LIST_HEAD_NOLOCK_STATIC(name, type)                         \
1919 struct name {                                                           \
1920         struct type *first;                                             \
1921         struct type *last;                                              \
1922 } name = AST_LIST_HEAD_NOLOCK_INIT_VALUE
1923
1924 /*!
1925   \brief Initializes a list head structure with a specified first entry.
1926   \param head This is a pointer to the list head structure
1927   \param entry pointer to the list entry that will become the head of the list
1928
1929   This macro initializes a list head structure by setting the head
1930   entry to the supplied value and recreating the embedded lock.
1931 */
1932 #define AST_LIST_HEAD_SET(head, entry) do {                             \
1933         (head)->first = (entry);                                        \
1934         (head)->last = (entry);                                         \
1935         ast_mutex_init(&(head)->lock);                                  \
1936 } while (0)
1937
1938 /*!
1939   \brief Initializes an rwlist head structure with a specified first entry.
1940   \param head This is a pointer to the list head structure
1941   \param entry pointer to the list entry that will become the head of the list
1942
1943   This macro initializes a list head structure by setting the head
1944   entry to the supplied value and recreating the embedded lock.
1945 */
1946 #define AST_RWLIST_HEAD_SET(head, entry) do {                           \
1947         (head)->first = (entry);                                        \
1948         (head)->last = (entry);                                         \
1949         ast_rwlock_init(&(head)->lock);                                 \
1950 } while (0)
1951
1952 /*!
1953   \brief Initializes a list head structure with a specified first entry.
1954   \param head This is a pointer to the list head structure
1955   \param entry pointer to the list entry that will become the head of the list
1956
1957   This macro initializes a list head structure by setting the head
1958   entry to the supplied value.
1959 */
1960 #define AST_LIST_HEAD_SET_NOLOCK(head, entry) do {                      \
1961         (head)->first = (entry);                                        \
1962         (head)->last = (entry);                                         \
1963 } while (0)
1964
1965 /*!
1966   \brief Declare a forward link structure inside a list entry.
1967   \param type This is the type of each list entry.
1968
1969   This macro declares a structure to be used to link list entries together.
1970   It must be used inside the definition of the structure named in
1971   \a type, as follows:
1972
1973   \code
1974   struct list_entry {
1975         ...
1976         AST_LIST_ENTRY(list_entry) list;
1977   }
1978   \endcode
1979
1980   The field name \a list here is arbitrary, and can be anything you wish.
1981 */
1982 #define AST_LIST_ENTRY(type)                                            \
1983 struct {                                                                \
1984         struct type *next;                                              \
1985 }
1986
1987 #define AST_RWLIST_ENTRY AST_LIST_ENTRY
1988  
1989 /*!
1990   \brief Returns the first entry contained in a list.
1991   \param head This is a pointer to the list head structure
1992  */
1993 #define AST_LIST_FIRST(head)    ((head)->first)
1994
1995 #define AST_RWLIST_FIRST AST_LIST_FIRST
1996
1997 /*!
1998   \brief Returns the last entry contained in a list.
1999   \param head This is a pointer to the list head structure
2000  */
2001 #define AST_LIST_LAST(head)     ((head)->last)
2002
2003 #define AST_RWLIST_LAST AST_LIST_LAST
2004
2005 /*!
2006   \brief Returns the next entry in the list after the given entry.
2007   \param elm This is a pointer to the current entry.
2008   \param field This is the name of the field (declared using AST_LIST_ENTRY())
2009   used to link entries of this list together.
2010 */
2011 #define AST_LIST_NEXT(elm, field)       ((elm)->field.next)
2012
2013 #define AST_RWLIST_NEXT AST_LIST_NEXT
2014
2015 /*!
2016   \brief Checks whether the specified list contains any entries.
2017   \param head This is a pointer to the list head structure
2018
2019   Returns non-zero if the list has entries, zero if not.
2020  */
2021 #define AST_LIST_EMPTY(head)    (AST_LIST_FIRST(head) == NULL)
2022
2023 #define AST_RWLIST_EMPTY AST_LIST_EMPTY
2024
2025 /*!
2026   \brief Loops over (traverses) the entries in a list.
2027   \param head This is a pointer to the list head structure
2028   \param var This is the name of the variable that will hold a pointer to the
2029   current list entry on each iteration. It must be declared before calling
2030   this macro.
2031   \param field This is the name of the field (declared using AST_LIST_ENTRY())
2032   used to link entries of this list together.
2033
2034   This macro is use to loop over (traverse) the entries in a list. It uses a
2035   \a for loop, and supplies the enclosed code with a pointer to each list
2036   entry as it loops. It is typically used as follows:
2037   \code
2038   static AST_LIST_HEAD(entry_list, list_entry) entries;
2039   ...
2040   struct list_entry {
2041         ...
2042         AST_LIST_ENTRY(list_entry) list;
2043   }
2044   ...
2045   struct list_entry *current;
2046   ...
2047   AST_LIST_TRAVERSE(&entries, current, list) {
2048      (do something with current here)
2049   }
2050   \endcode
2051   \warning If you modify the forward-link pointer contained in the \a current entry while
2052   inside the loop, the behavior will be unpredictable. At a minimum, the following
2053   macros will modify the forward-link pointer, and should not be used inside
2054   AST_LIST_TRAVERSE() against the entry pointed to by the \a current pointer without
2055   careful consideration of their consequences:
2056   \li AST_LIST_NEXT() (when used as an lvalue)
2057   \li AST_LIST_INSERT_AFTER()
2058   \li AST_LIST_INSERT_HEAD()
2059   \li AST_LIST_INSERT_TAIL()
2060 */
2061 #define AST_LIST_TRAVERSE(head,var,field)                               \
2062         for((var) = (head)->first; (var); (var) = (var)->field.next)
2063
2064 #define AST_RWLIST_TRAVERSE AST_LIST_TRAVERSE
2065
2066 /*!
2067   \brief Loops safely over (traverses) the entries in a list.
2068   \param head This is a pointer to the list head structure
2069   \param var This is the name of the variable that will hold a pointer to the
2070   current list entry on each iteration. It must be declared before calling
2071   this macro.
2072   \param field This is the name of the field (declared using AST_LIST_ENTRY())
2073   used to link entries of this list together.
2074
2075   This macro is used to safely loop over (traverse) the entries in a list. It
2076   uses a \a for loop, and supplies the enclosed code with a pointer to each list
2077   entry as it loops. It is typically used as follows:
2078
2079   \code
2080   static AST_LIST_HEAD(entry_list, list_entry) entries;
2081   ...
2082   struct list_entry {
2083         ...
2084         AST_LIST_ENTRY(list_entry) list;
2085   }
2086   ...
2087   struct list_entry *current;
2088   ...
2089   AST_LIST_TRAVERSE_SAFE_BEGIN(&entries, current, list) {
2090      (do something with current here)
2091   }
2092   AST_LIST_TRAVERSE_SAFE_END;
2093   \endcode
2094
2095   It differs from AST_LIST_TRAVERSE() in that the code inside the loop can modify
2096   (or even free, after calling AST_LIST_REMOVE_CURRENT()) the entry pointed to by
2097   the \a current pointer without affecting the loop traversal.
2098 */
2099 #define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field) {                                \
2100         typeof((head)->first) __list_next;                                              \
2101         typeof((head)->first) __list_prev = NULL;                                       \
2102         typeof((head)->first) __new_prev = NULL;                                        \
2103         for ((var) = (head)->first, __new_prev = (var),                                 \
2104               __list_next = (var) ? (var)->field.next : NULL;                           \
2105              (var);                                                                     \
2106              __list_prev = __new_prev, (var) = __list_next,                             \
2107              __new_prev = (var),                                                        \
2108              __list_next = (var) ? (var)->field.next : NULL                             \
2109             )
2110
2111 #define AST_RWLIST_TRAVERSE_SAFE_BEGIN AST_LIST_TRAVERSE_SAFE_BEGIN
2112
2113 /*!
2114   \brief Removes the \a current entry from a list during a traversal.
2115   \param head This is a pointer to the list head structure
2116   \param field This is the name of the field (declared using AST_LIST_ENTRY())
2117   used to link entries of this list together.
2118
2119   \note This macro can \b only be used inside an AST_LIST_TRAVERSE_SAFE_BEGIN()
2120   block; it is used to unlink the current entry from the list without affecting
2121   the list traversal (and without having to re-traverse the list to modify the
2122   previous entry, if any).
2123  */
2124 #define AST_LIST_REMOVE_CURRENT(head, field)                                            \
2125         __new_prev->field.next = NULL;                                                  \
2126         __new_prev = __list_prev;                                                       \
2127         if (__list_prev)                                                                \
2128                 __list_prev->field.next = __list_next;                                  \
2129         else                                                                            \
2130                 (head)->first = __list_next;                                            \
2131         if (!__list_next)                                                               \
2132                 (head)->last = __list_prev;
2133
2134 #define AST_RWLIST_REMOVE_CURRENT AST_LIST_REMOVE_CURRENT
2135
2136 /*!
2137   \brief Inserts a list entry before the current entry during a traversal.
2138   \param head This is a pointer to the list head structure
2139   \param elm This is a pointer to the entry to be inserted.
2140   \param field This is the name of the field (declared using AST_LIST_ENTRY())
2141   used to link entries of this list together.
2142
2143   \note This macro can \b only be used inside an AST_LIST_TRAVERSE_SAFE_BEGIN()
2144   block.
2145  */
2146 #define AST_LIST_INSERT_BEFORE_CURRENT(head, elm, field) do {           \
2147         if (__list_prev) {                                              \
2148                 (elm)->field.next = __list_prev->field.next;            \
2149                 __list_prev->field.next = elm;                          \
2150         } else {                                                        \
2151                 (elm)->field.next = (head)->first;                      \
2152                 (head)->first = (elm);                                  \
2153         }                                                               \
2154         __new_prev = (elm);                                             \
2155 } while (0)
2156
2157 #define AST_RWLIST_INSERT_BEFORE_CURRENT AST_LIST_INSERT_BEFORE_CURRENT
2158
2159 /*!
2160   \brief Closes a safe loop traversal block.
2161  */
2162 #define AST_LIST_TRAVERSE_SAFE_END  }
2163
2164 #define AST_RWLIST_TRAVERSE_SAFE_END AST_LIST_TRAVERSE_SAFE_END
2165
2166 /*!
2167   \brief Initializes a list head structure.
2168   \param head This is a pointer to the list head structure
2169
2170   This macro initializes a list head structure by setting the head
2171   entry to \a NULL (empty list) and recreating the embedded lock.
2172 */
2173 #define AST_LIST_HEAD_INIT(head) {                                      \
2174         (head)->first = NULL;                                           \
2175         (head)->last = NULL;                                            \
2176         ast_mutex_init(&(head)->lock);                                  \
2177 }
2178
2179 /*!
2180   \brief Initializes an rwlist head structure.
2181   \param head This is a pointer to the list head structure
2182
2183   This macro initializes a list head structure by setting the head
2184   entry to \a NULL (empty list) and recreating the embedded lock.
2185 */
2186 #define AST_RWLIST_HEAD_INIT(head) {                                    \
2187         (head)->first = NULL;                                           \
2188         (head)->last = NULL;                                            \
2189         ast_rwlock_init(&(head)->lock);                                 \
2190 }
2191
2192 /*!
2193   \brief Destroys a list head structure.
2194   \param head This is a pointer to the list head structure
2195
2196   This macro destroys a list head structure by setting the head
2197   entry to \a NULL (empty list) and destroying the embedded lock.
2198   It does not free the structure from memory.
2199 */
2200 #define AST_LIST_HEAD_DESTROY(head) {                                   \
2201         (head)->first = NULL;                                           \
2202         (head)->last = NULL;                                            \
2203         ast_mutex_destroy(&(head)->lock);                               \
2204 }
2205
2206 /*!
2207   \brief Destroys an rwlist head structure.
2208   \param head This is a pointer to the list head structure
2209
2210   This macro destroys a list head structure by setting the head
2211   entry to \a NULL (empty list) and destroying the embedded lock.
2212   It does not free the structure from memory.
2213 */
2214 #define AST_RWLIST_HEAD_DESTROY(head) {                                 \
2215         (head)->first = NULL;                                           \
2216         (head)->last = NULL;                                            \
2217         ast_rwlock_destroy(&(head)->lock);                              \
2218 }
2219
2220 /*!
2221   \brief Initializes a list head structure.
2222   \param head This is a pointer to the list head structure
2223
2224   This macro initializes a list head structure by setting the head
2225   entry to \a NULL (empty list). There is no embedded lock handling
2226   with this macro.
2227 */
2228 #define AST_LIST_HEAD_INIT_NOLOCK(head) {                               \
2229         (head)->first = NULL;                                           \
2230         (head)->last = NULL;                                            \
2231 }
2232
2233 /*!
2234   \brief Inserts a list entry after a given entry.
2235   \param head This is a pointer to the list head structure
2236   \param listelm This is a pointer to the entry after which the new entry should
2237   be inserted.
2238   \param elm This is a pointer to the entry to be inserted.
2239   \param field This is the name of the field (declared using AST_LIST_ENTRY())
2240   used to link entries of this list together.
2241  */
2242 #define AST_LIST_INSERT_AFTER(head, listelm, elm, field) do {           \
2243         (elm)->field.next = (listelm)->field.next;                      \
2244         (listelm)->field.next = (elm);                                  \
2245         if ((head)->last == (listelm))                                  \
2246                 (head)->last = (elm);                                   \
2247 } while (0)
2248
2249 #define AST_RWLIST_INSERT_AFTER AST_LIST_INSERT_AFTER
2250
2251 /*!
2252   \brief Inserts a list entry at the head of a list.
2253   \param head This is a pointer to the list head structure
2254   \param elm This is a pointer to the entry to be inserted.
2255   \param field This is the name of the field (declared using AST_LIST_ENTRY())
2256   used to link entries of this list together.
2257  */
2258 #define AST_LIST_INSERT_HEAD(head, elm, field) do {                     \
2259                 (elm)->field.next = (head)->first;                      \
2260                 (head)->first = (elm);                                  \
2261                 if (!(head)->last)                                      \
2262                         (head)->last = (elm);                           \
2263 } while (0)
2264
2265 #define AST_RWLIST_INSERT_HEAD AST_LIST_INSERT_HEAD
2266
2267 /*!
2268   \brief Appends a list entry to the tail of a list.
2269   \param head This is a pointer to the list head structure
2270   \param elm This is a pointer to the entry to be appended.
2271   \param field This is the name of the field (declared using AST_LIST_ENTRY())
2272   used to link entries of this list together.
2273
2274   Note: The link field in the appended entry is \b not modified, so if it is
2275   actually the head of a list itself, the entire list will be appended
2276   temporarily (until the next AST_LIST_INSERT_TAIL is performed).
2277  */
2278 #define AST_LIST_INSERT_TAIL(head, elm, field) do {                     \
2279       if (!(head)->first) {                                             \
2280                 (head)->first = (elm);                                  \
2281                 (head)->last = (elm);                                   \
2282       } else {                                                          \
2283                 (head)->last->field.next = (elm);                       \
2284                 (head)->last = (elm);                                   \
2285       }                                                                 \
2286 } while (0)
2287
2288 #define AST_RWLIST_INSERT_TAIL AST_LIST_INSERT_TAIL
2289
2290 /*!
2291   \brief Appends a whole list to the tail of a list.
2292   \param head This is a pointer to the list head structure
2293   \param list This is a pointer to the list to be appended.
2294   \param field This is the name of the field (declared using AST_LIST_ENTRY())
2295   used to link entries of this list together.
2296  */
2297 #define AST_LIST_APPEND_LIST(head, list, field) do {                    \
2298       if (!(head)->first) {                                             \
2299                 (head)->first = (list)->first;                          \
2300                 (head)->last = (list)->last;                            \
2301       } else {                                                          \
2302                 (head)->last->field.next = (list)->first;               \
2303                 (head)->last = (list)->last;                            \
2304       }                                                                 \
2305 } while (0)
2306
2307 #define AST_RWLIST_APPEND_LIST AST_LIST_APPEND_LIST
2308
2309 /*!
2310   \brief Removes and returns the head entry from a list.
2311   \param head This is a pointer to the list head structure
2312   \param field This is the name of the field (declared using AST_LIST_ENTRY())
2313   used to link entries of this list together.
2314
2315   Removes the head entry from the list, and returns a pointer to it.
2316   This macro is safe to call on an empty list.
2317  */
2318 #define AST_LIST_REMOVE_HEAD(head, field) ({                            \
2319                 typeof((head)->first) cur = (head)->first;              \
2320                 if (cur) {                                              \
2321                         (head)->first = cur->field.next;                \
2322                         cur->field.next = NULL;                         \
2323                         if ((head)->last == cur)                        \
2324                                 (head)->last = NULL;                    \
2325                 }                                                       \
2326                 cur;                                                    \
2327         })
2328
2329 #define AST_RWLIST_REMOVE_HEAD AST_LIST_REMOVE_HEAD
2330
2331 /*!
2332   \brief Removes a specific entry from a list.
2333   \param head This is a pointer to the list head structure
2334   \param elm This is a pointer to the entry to be removed.
2335   \param field This is the name of the field (declared using AST_LIST_ENTRY())
2336   used to link entries of this list together.
2337   \warning The removed entry is \b not freed nor modified in any way.
2338  */
2339 #define AST_LIST_REMOVE(head, elm, field) do {                          \
2340         if ((head)->first == (elm)) {                                   \
2341                 (head)->first = (elm)->field.next;                      \
2342                 if ((head)->last == (elm))                      \
2343                         (head)->last = NULL;                    \
2344         } else {                                                                \
2345                 typeof(elm) curelm = (head)->first;                     \
2346                 while (curelm && (curelm->field.next != (elm)))                 \
2347                         curelm = curelm->field.next;                    \
2348                 if (curelm) { \
2349                         curelm->field.next = (elm)->field.next;                 \
2350                         if ((head)->last == (elm))                              \
2351                                 (head)->last = curelm;                          \
2352                 } \
2353         }                                                               \
2354         (elm)->field.next = NULL;                                       \
2355 } while (0)
2356
2357 #define AST_RWLIST_REMOVE AST_LIST_REMOVE
2358
2359 /* chanvars.h */
2360
2361 struct ast_var_t {
2362         AST_LIST_ENTRY(ast_var_t) entries;
2363         char *value;
2364         char name[0];
2365 };
2366
2367 AST_LIST_HEAD_NOLOCK(varshead, ast_var_t);
2368
2369 AST_RWLOCK_DEFINE_STATIC(globalslock);
2370 static struct varshead globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
2371
2372
2373 /* IN CONFLICT: struct ast_var_t *ast_var_assign(const char *name, const char *value); */
2374
2375 static struct ast_var_t *ast_var_assign(const char *name, const char *value);
2376
2377 static void ast_var_delete(struct ast_var_t *var);
2378
2379 /*from channel.h */
2380 #define AST_MAX_EXTENSION  80      /*!< Max length of an extension */
2381
2382
2383 /* from pbx.h */
2384 #define PRIORITY_HINT   -1      /*!< Special Priority for a hint */
2385
2386 enum ast_extension_states {
2387         AST_EXTENSION_REMOVED = -2,     /*!< Extension removed */
2388         AST_EXTENSION_DEACTIVATED = -1, /*!< Extension hint removed */
2389         AST_EXTENSION_NOT_INUSE = 0,    /*!< No device INUSE or BUSY  */
2390         AST_EXTENSION_INUSE = 1 << 0,   /*!< One or more devices INUSE */
2391         AST_EXTENSION_BUSY = 1 << 1,    /*!< All devices BUSY */
2392         AST_EXTENSION_UNAVAILABLE = 1 << 2, /*!< All devices UNAVAILABLE/UNREGISTERED */
2393         AST_EXTENSION_RINGING = 1 << 3, /*!< All devices RINGING */
2394         AST_EXTENSION_ONHOLD = 1 << 4,  /*!< All devices ONHOLD */
2395 };
2396
2397 struct ast_custom_function {
2398         const char *name;               /*!< Name */
2399         const char *synopsis;           /*!< Short description for "show functions" */
2400         const char *desc;               /*!< Help text that explains it all */
2401         const char *syntax;             /*!< Syntax description */
2402         int (*read)(struct ast_channel *, const char *, char *, char *, size_t);        /*!< Read function, if read is supported */
2403         int (*write)(struct ast_channel *, const char *, char *, const char *);         /*!< Write function, if write is supported */
2404         AST_RWLIST_ENTRY(ast_custom_function) acflist;
2405 };
2406
2407 typedef int (ast_switch_f)(struct ast_channel *chan, const char *context,
2408         const char *exten, int priority, const char *callerid, const char *data);
2409
2410 struct ast_switch {
2411         AST_LIST_ENTRY(ast_switch) list;
2412         const char *name;                       /*!< Name of the switch */
2413         const char *description;                /*!< Description of the switch */
2414         
2415         ast_switch_f *exists;
2416         ast_switch_f *canmatch;
2417         ast_switch_f *exec;
2418         ast_switch_f *matchmore;
2419 };
2420
2421
2422 static char *config = "extensions.conf";
2423 static char *registrar = "conf2ael";
2424 static char userscontext[AST_MAX_EXTENSION] = "default";
2425 static int static_config = 0;
2426 static int write_protect_config = 1;
2427 static int autofallthrough_config = 0;
2428 static int clearglobalvars_config = 0;
2429 /*! Go no deeper than this through includes (not counting loops) */
2430 #define AST_PBX_MAX_STACK       128
2431 static void pbx_substitute_variables_helper(struct ast_channel *c,const char *cp1,char *cp2,int count);
2432
2433
2434 /* taken from strings.h */
2435
2436 static force_inline int ast_strlen_zero(const char *s)
2437 {
2438         return (!s || (*s == '\0'));
2439 }
2440
2441 #define S_OR(a, b)      (!ast_strlen_zero(a) ? (a) : (b))
2442
2443 AST_INLINE_API(
2444 void ast_copy_string(char *dst, const char *src, size_t size),
2445 {
2446         while (*src && size) {
2447                 *dst++ = *src++;
2448                 size--;
2449         }
2450         if (__builtin_expect(!size, 0))
2451                 dst--;
2452         *dst = '\0';
2453 }
2454 )
2455
2456 AST_INLINE_API(
2457 char *ast_skip_blanks(const char *str),
2458 {
2459         while (*str && *str < 33)
2460                 str++;
2461         return (char *)str;
2462 }
2463 )
2464
2465 /*!
2466   \brief Trims trailing whitespace characters from a string.
2467   \param ast_trim_blanks function being used
2468   \param str the input string
2469   \return a pointer to the modified string
2470  */
2471 AST_INLINE_API(
2472 char *ast_trim_blanks(char *str),
2473 {
2474         char *work = str;
2475
2476         if (work) {
2477                 work += strlen(work) - 1;
2478                 /* It's tempting to only want to erase after we exit this loop, 
2479                    but since ast_trim_blanks *could* receive a constant string
2480                    (which we presumably wouldn't have to touch), we shouldn't
2481                    actually set anything unless we must, and it's easier just
2482                    to set each position to \0 than to keep track of a variable
2483                    for it */
2484                 while ((work >= str) && *work < 33)
2485                         *(work--) = '\0';
2486         }
2487         return str;
2488 }
2489 )
2490
2491 /*!
2492   \brief Strip leading/trailing whitespace from a string.
2493   \param s The string to be stripped (will be modified).
2494   \return The stripped string.
2495
2496   This functions strips all leading and trailing whitespace
2497   characters from the input string, and returns a pointer to
2498   the resulting string. The string is modified in place.
2499 */
2500 AST_INLINE_API(
2501 char *ast_strip(char *s),
2502 {
2503         s = ast_skip_blanks(s);
2504         if (s)
2505                 ast_trim_blanks(s);
2506         return s;
2507
2508 )
2509
2510
2511 /* stolen from callerid.c */
2512
2513 /*! \brief Clean up phone string
2514  * remove '(', ' ', ')', non-trailing '.', and '-' not in square brackets.
2515  * Basically, remove anything that could be invalid in a pattern.
2516  */
2517 static void ast_shrink_phone_number(char *n)
2518 {
2519         int x, y=0;
2520         int bracketed = 0;
2521
2522         for (x=0; n[x]; x++) {
2523                 switch(n[x]) {
2524                 case '[':
2525                         bracketed++;
2526                         n[y++] = n[x];
2527                         break;
2528                 case ']':
2529                         bracketed--;
2530                         n[y++] = n[x];
2531                         break;
2532                 case '-':
2533                         if (bracketed)
2534                                 n[y++] = n[x];
2535                         break;
2536                 case '.':
2537                         if (!n[x+1])
2538                                 n[y++] = n[x];
2539                         break;
2540                 default:
2541                         if (!strchr("()", n[x]))
2542                                 n[y++] = n[x];
2543                 }
2544         }
2545         n[y] = '\0';
2546 }
2547
2548
2549 /* stolen from chanvars.c */
2550
2551 static const char *ast_var_name(const struct ast_var_t *var)
2552 {
2553         const char *name;
2554
2555         if (var == NULL || (name = var->name) == NULL)
2556                 return NULL;
2557         /* Return the name without the initial underscores */
2558         if (name[0] == '_') {
2559                 name++;
2560                 if (name[0] == '_')
2561                         name++;
2562         }
2563         return name;
2564 }
2565
2566
2567 /* stolen from asterisk.c */
2568
2569 static struct ast_flags ast_options = { AST_DEFAULT_OPTIONS };
2570 static int option_verbose = 0;                         /*!< Verbosity level */
2571 static int option_debug = 0;                           /*!< Debug level */
2572
2573
2574 /* experiment 1: see if it's easier just to use existing config code
2575  *               to read in the extensions.conf file. In this scenario, 
2576                  I have to rip/copy code from other modules, because they
2577                  are staticly declared as-is. A solution would be to move
2578                  the ripped code to another location and make them available
2579                  to other modules and standalones */
2580
2581 /* Our own version of ast_log, since the expr parser uses it. -- stolen from utils/check_expr.c */
2582
2583 static void ast_log(int level, const char *file, int line, const char *function, const char *fmt, ...)
2584 {
2585         va_list vars;
2586         va_start(vars,fmt);
2587         
2588         printf("LOG: lev:%d file:%s  line:%d func: %s  ",
2589                    level, file, line, function);
2590         vprintf(fmt, vars);
2591         fflush(stdout);
2592         va_end(vars);
2593 }
2594
2595 static void ast_verbose(const char *fmt, ...)
2596 {
2597         va_list vars;
2598         va_start(vars,fmt);
2599         
2600         printf("VERBOSE: ");
2601         vprintf(fmt, vars);
2602         fflush(stdout);
2603         va_end(vars);
2604 }
2605
2606 /* stolen from main/utils.c */
2607 static char *ast_process_quotes_and_slashes(char *start, char find, char replace_with)
2608 {
2609         char *dataPut = start;
2610         int inEscape = 0;
2611         int inQuotes = 0;
2612
2613         for (; *start; start++) {
2614                 if (inEscape) {
2615                         *dataPut++ = *start;       /* Always goes verbatim */
2616                         inEscape = 0;
2617                 } else {
2618                         if (*start == '\\') {
2619                                 inEscape = 1;      /* Do not copy \ into the data */
2620                         } else if (*start == '\'') {
2621                                 inQuotes = 1 - inQuotes;   /* Do not copy ' into the data */
2622                         } else {
2623                                 /* Replace , with |, unless in quotes */
2624                                 *dataPut++ = inQuotes ? *start : ((*start == find) ? replace_with : *start);
2625                         }
2626                 }
2627         }
2628         if (start != dataPut)
2629                 *dataPut = 0;
2630         return dataPut;
2631 }
2632
2633 static int ast_true(const char *s)
2634 {
2635         if (ast_strlen_zero(s))
2636                 return 0;
2637
2638         /* Determine if this is a true value */
2639         if (!strcasecmp(s, "yes") ||
2640             !strcasecmp(s, "true") ||
2641             !strcasecmp(s, "y") ||
2642             !strcasecmp(s, "t") ||
2643             !strcasecmp(s, "1") ||
2644             !strcasecmp(s, "on"))
2645                 return -1;
2646
2647         return 0;
2648 }
2649
2650 /* stolen from pbx.c */
2651 #define VAR_BUF_SIZE 4096
2652
2653 #define VAR_NORMAL              1
2654 #define VAR_SOFTTRAN    2
2655 #define VAR_HARDTRAN    3
2656
2657 #define BACKGROUND_SKIP         (1 << 0)
2658 #define BACKGROUND_NOANSWER     (1 << 1)
2659 #define BACKGROUND_MATCHEXTEN   (1 << 2)
2660 #define BACKGROUND_PLAYBACK     (1 << 3)
2661
2662 /*!
2663    \brief ast_exten: An extension
2664         The dialplan is saved as a linked list with each context
2665         having it's own linked list of extensions - one item per
2666         priority.
2667 */
2668 struct ast_exten {
2669         char *exten;                    /*!< Extension name */
2670         int matchcid;                   /*!< Match caller id ? */
2671         const char *cidmatch;           /*!< Caller id to match for this extension */
2672         int priority;                   /*!< Priority */
2673         const char *label;              /*!< Label */
2674         struct ast_context *parent;     /*!< The context this extension belongs to  */
2675         const char *app;                /*!< Application to execute */
2676         struct ast_app *cached_app;     /*!< Cached location of application */
2677         void *data;                     /*!< Data to use (arguments) */
2678         void (*datad)(void *);          /*!< Data destructor */
2679         struct ast_exten *peer;         /*!< Next higher priority with our extension */
2680         const char *registrar;          /*!< Registrar */
2681         struct ast_exten *next;         /*!< Extension with a greater ID */
2682         char stuff[0];
2683 };
2684 /* from pbx.h */
2685 typedef int (*ast_state_cb_type)(char *context, char* id, enum ast_extension_states state, void *data);
2686 struct ast_timing {
2687         int hastime;                            /*!< If time construct exists */
2688         unsigned int monthmask;                 /*!< Mask for month */
2689         unsigned int daymask;                   /*!< Mask for date */
2690         unsigned int dowmask;                   /*!< Mask for day of week (mon-sun) */
2691         unsigned int minmask[24];               /*!< Mask for minute */
2692 };
2693 /* end of pbx.h */
2694 /*! \brief ast_include: include= support in extensions.conf */
2695 struct ast_include {
2696         const char *name;
2697         const char *rname;                      /*!< Context to include */
2698         const char *registrar;                  /*!< Registrar */
2699         int hastime;                            /*!< If time construct exists */
2700         struct ast_timing timing;               /*!< time construct */
2701         struct ast_include *next;               /*!< Link them together */
2702         char stuff[0];
2703 };
2704
2705 /*! \brief ast_sw: Switch statement in extensions.conf */
2706 struct ast_sw {
2707         char *name;
2708         const char *registrar;                  /*!< Registrar */
2709         char *data;                             /*!< Data load */
2710         int eval;
2711         AST_LIST_ENTRY(ast_sw) list;
2712         char *tmpdata;
2713         char stuff[0];
2714 };
2715
2716 /*! \brief ast_ignorepat: Ignore patterns in dial plan */
2717 struct ast_ignorepat {
2718         const char *registrar;
2719         struct ast_ignorepat *next;
2720         const char pattern[0];
2721 };
2722
2723 /*! \brief ast_context: An extension context */
2724 struct ast_context {
2725         ast_rwlock_t lock;                      /*!< A lock to prevent multiple threads from clobbering the context */
2726         struct ast_exten *root;                 /*!< The root of the list of extensions */
2727         struct ast_context *next;               /*!< Link them together */
2728         struct ast_include *includes;           /*!< Include other contexts */
2729         struct ast_ignorepat *ignorepats;       /*!< Patterns for which to continue playing dialtone */
2730         const char *registrar;                  /*!< Registrar */
2731         AST_LIST_HEAD_NOLOCK(, ast_sw) alts;    /*!< Alternative switches */
2732         ast_mutex_t macrolock;                  /*!< A lock to implement "exclusive" macros - held whilst a call is executing in the macro */
2733         char name[0];                           /*!< Name of the context */
2734 };
2735
2736
2737 /*! \brief ast_app: A registered application */
2738 struct ast_app {
2739         int (*execute)(struct ast_channel *chan, void *data);
2740         const char *synopsis;                   /*!< Synopsis text for 'show applications' */
2741         const char *description;                /*!< Description (help text) for 'show application &lt;name&gt;' */
2742         AST_RWLIST_ENTRY(ast_app) list;         /*!< Next app in list */
2743         void *module;                   /*!< Module this app belongs to */
2744         char name[0];                           /*!< Name of the application */
2745 };
2746
2747
2748 /*! \brief ast_state_cb: An extension state notify register item */
2749 struct ast_state_cb {
2750         int id;
2751         void *data;
2752         ast_state_cb_type callback;
2753         struct ast_state_cb *next;
2754 };
2755
2756 /*! \brief Structure for dial plan hints
2757
2758   \note Hints are pointers from an extension in the dialplan to one or
2759   more devices (tech/name) 
2760         - See \ref AstExtState
2761 */
2762 struct ast_hint {
2763         struct ast_exten *exten;        /*!< Extension */
2764         int laststate;                  /*!< Last known state */
2765         struct ast_state_cb *callbacks; /*!< Callback list for this extension */
2766         AST_RWLIST_ENTRY(ast_hint) list;/*!< Pointer to next hint in list */
2767 };
2768
2769 struct store_hint {
2770         char *context;
2771         char *exten;
2772         struct ast_state_cb *callbacks;
2773         int laststate;
2774         AST_LIST_ENTRY(store_hint) list;
2775         char data[1];
2776 };
2777
2778 AST_LIST_HEAD(store_hints, store_hint);
2779
2780 static const struct cfextension_states {
2781         int extension_state;
2782         const char * const text;
2783 } extension_states[] = {
2784         { AST_EXTENSION_NOT_INUSE,                     "Idle" },
2785         { AST_EXTENSION_INUSE,                         "InUse" },
2786         { AST_EXTENSION_BUSY,                          "Busy" },
2787         { AST_EXTENSION_UNAVAILABLE,                   "Unavailable" },
2788         { AST_EXTENSION_RINGING,                       "Ringing" },
2789         { AST_EXTENSION_INUSE | AST_EXTENSION_RINGING, "InUse&Ringing" },
2790         { AST_EXTENSION_ONHOLD,                        "Hold" },
2791         { AST_EXTENSION_INUSE | AST_EXTENSION_ONHOLD,  "InUse&Hold" }
2792 };
2793 #define STATUS_NO_CONTEXT       1
2794 #define STATUS_NO_EXTENSION     2
2795 #define STATUS_NO_PRIORITY      3
2796 #define STATUS_NO_LABEL         4
2797 #define STATUS_SUCCESS          5
2798
2799
2800 #if defined ( __i386__) && (defined(__FreeBSD__) || defined(linux))
2801 #if defined(__FreeBSD__)
2802 #include <machine/cpufunc.h>
2803 #elif defined(linux)
2804 static __inline uint64_t
2805 rdtsc(void)
2806
2807         uint64_t rv;
2808
2809         __asm __volatile(".byte 0x0f, 0x31" : "=A" (rv));
2810         return (rv);
2811 }
2812 #endif
2813 #else   /* supply a dummy function on other platforms */
2814 static __inline uint64_t
2815 rdtsc(void)
2816 {
2817         return 0;
2818 }
2819 #endif
2820
2821
2822 static struct ast_var_t *ast_var_assign(const char *name, const char *value)
2823 {       
2824         struct ast_var_t *var;
2825         int name_len = strlen(name) + 1;
2826         int value_len = strlen(value) + 1;
2827
2828         if (!(var = ast_calloc(sizeof(*var) + name_len + value_len, sizeof(char)))) {
2829                 return NULL;
2830         }
2831
2832         ast_copy_string(var->name, name, name_len);
2833         var->value = var->name + name_len;
2834         ast_copy_string(var->value, value, value_len);
2835         
2836         return var;
2837 }       
2838         
2839 static void ast_var_delete(struct ast_var_t *var)
2840 {
2841         if (var)
2842                 free(var);
2843 }
2844
2845
2846 /* chopped this one off at the knees! */
2847 static int ast_func_write(struct ast_channel *chan, const char *function, const char *value)
2848 {
2849
2850         /* ast_log(LOG_ERROR, "Function %s not registered\n", function); we are not interested in the details here */
2851
2852         return -1;
2853 }
2854
2855 static unsigned int ast_app_separate_args(char *buf, char delim, char **array, int arraylen)
2856 {
2857         int argc;
2858         char *scan;
2859         int paren = 0, quote = 0;
2860
2861         if (!buf || !array || !arraylen)
2862                 return 0;
2863
2864         memset(array, 0, arraylen * sizeof(*array));
2865
2866         scan = buf;
2867
2868         for (argc = 0; *scan && (argc < arraylen - 1); argc++) {
2869                 array[argc] = scan;
2870                 for (; *scan; scan++) {
2871                         if (*scan == '(')
2872                                 paren++;
2873                         else if (*scan == ')') {
2874                                 if (paren)
2875                                         paren--;
2876                         } else if (*scan == '"' && delim != '"') {
2877                                 quote = quote ? 0 : 1;
2878                                 /* Remove quote character from argument */
2879                                 memmove(scan, scan + 1, strlen(scan));
2880                                 scan--;
2881                         } else if (*scan == '\\') {
2882                                 /* Literal character, don't parse */
2883                                 memmove(scan, scan + 1, strlen(scan));
2884                         } else if ((*scan == delim) && !paren && !quote) {
2885                                 *scan++ = '\0';
2886                                 break;
2887                         }
2888                 }
2889         }
2890
2891         if (*scan)
2892                 array[argc++] = scan;
2893
2894         return argc;
2895 }
2896
2897 static void pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
2898 {
2899         struct ast_var_t *newvariable;
2900         struct varshead *headp;
2901         const char *nametail = name;
2902
2903         /* XXX may need locking on the channel ? */
2904         if (name[strlen(name)-1] == ')') {
2905                 char *function = ast_strdupa(name);
2906
2907                 ast_func_write(chan, function, value);
2908                 return;
2909         }
2910
2911         headp = &globals;
2912
2913         /* For comparison purposes, we have to strip leading underscores */
2914         if (*nametail == '_') {
2915                 nametail++;
2916                 if (*nametail == '_')
2917                         nametail++;
2918         }
2919
2920         AST_LIST_TRAVERSE (headp, newvariable, entries) {
2921                 if (strcasecmp(ast_var_name(newvariable), nametail) == 0) {
2922                         /* there is already such a variable, delete it */
2923                         AST_LIST_REMOVE(headp, newvariable, entries);
2924                         ast_var_delete(newvariable);
2925                         break;
2926                 }
2927         }
2928
2929         if (value) {
2930                 if ((option_verbose > 1) && (headp == &globals))
2931                         ast_verbose(VERBOSE_PREFIX_2 "Setting global variable '%s' to '%s'\n", name, value);
2932                 newvariable = ast_var_assign(name, value);
2933                 AST_LIST_INSERT_HEAD(headp, newvariable, entries);
2934         }
2935
2936 }
2937
2938 static int pbx_builtin_setvar(struct ast_channel *chan, void *data)
2939 {
2940         char *name, *value, *mydata;
2941         int argc;
2942         char *argv[24];         /* this will only support a maximum of 24 variables being set in a single operation */
2943         int global = 0;
2944         int x;
2945
2946         if (ast_strlen_zero(data)) {
2947                 ast_log(LOG_WARNING, "Set requires at least one variable name/value pair.\n");
2948                 return 0;
2949         }
2950
2951         mydata = ast_strdupa(data);
2952         argc = ast_app_separate_args(mydata, '|', argv, sizeof(argv) / sizeof(argv[0]));
2953
2954         /* check for a trailing flags argument */
2955         if ((argc > 1) && !strchr(argv[argc-1], '=')) {
2956                 argc--;
2957                 if (strchr(argv[argc], 'g'))
2958                         global = 1;
2959         }
2960
2961         for (x = 0; x < argc; x++) {
2962                 name = argv[x];
2963                 if ((value = strchr(name, '='))) {
2964                         *value++ = '\0';
2965                         pbx_builtin_setvar_helper((global) ? NULL : chan, name, value);
2966                 } else
2967                         ast_log(LOG_WARNING, "Ignoring entry '%s' with no = (and not last 'options' entry)\n", name);
2968         }
2969
2970         return(0);
2971 }
2972
2973 int localized_pbx_builtin_setvar(struct ast_channel *chan, void *data);
2974
2975 int localized_pbx_builtin_setvar(struct ast_channel *chan, void *data)
2976 {
2977         return pbx_builtin_setvar(chan, data);
2978 }
2979
2980
2981 /*! \brief Helper for get_range.
2982  * return the index of the matching entry, starting from 1.
2983  * If names is not supplied, try numeric values.
2984  */
2985
2986 static int lookup_name(const char *s, char *const names[], int max)
2987 {
2988         int i;
2989
2990         if (names) {
2991                 for (i = 0; names[i]; i++) {
2992                         if (!strcasecmp(s, names[i]))
2993                                 return i+1;
2994                 }
2995         } else if (sscanf(s, "%d", &i) == 1 && i >= 1 && i <= max) {
2996                 return i;
2997         }
2998         return 0; /* error return */
2999 }
3000
3001 /*! \brief helper function to return a range up to max (7, 12, 31 respectively).
3002  * names, if supplied, is an array of names that should be mapped to numbers.
3003  */
3004 static unsigned get_range(char *src, int max, char *const names[], const char *msg)
3005 {
3006         int s, e; /* start and ending position */
3007         unsigned int mask = 0;
3008
3009         /* Check for whole range */
3010         if (ast_strlen_zero(src) || !strcmp(src, "*")) {
3011                 s = 0;
3012                 e = max - 1;
3013         } else {
3014                 /* Get start and ending position */
3015                 char *c = strchr(src, '-');
3016                 if (c)
3017                         *c++ = '\0';
3018                 /* Find the start */
3019                 s = lookup_name(src, names, max);
3020                 if (!s) {
3021                         ast_log(LOG_WARNING, "Invalid %s '%s', assuming none\n", msg, src);
3022                         return 0;
3023                 }
3024                 s--;
3025                 if (c) { /* find end of range */
3026                         e = lookup_name(c, names, max);
3027                         if (!e) {
3028                                 ast_log(LOG_WARNING, "Invalid end %s '%s', assuming none\n", msg, c);
3029                                 return 0;
3030                         }
3031                         e--;
3032                 } else
3033                         e = s;
3034         }
3035         /* Fill the mask. Remember that ranges are cyclic */
3036         mask = 1 << e;  /* initialize with last element */
3037         while (s != e) {
3038                 if (s >= max) {
3039                         s = 0;
3040                         mask |= (1 << s);
3041                 } else {
3042                         mask |= (1 << s);
3043                         s++;
3044                 }
3045         }
3046         return mask;
3047 }
3048
3049 /*! \brief store a bitmask of valid times, one bit each 2 minute */
3050 static void get_timerange(struct ast_timing *i, char *times)
3051 {
3052         char *e;
3053         int x;
3054         int s1, s2;
3055         int e1, e2;
3056         /*      int cth, ctm; */
3057
3058         /* start disabling all times, fill the fields with 0's, as they may contain garbage */
3059         memset(i->minmask, 0, sizeof(i->minmask));
3060
3061         /* 2-minutes per bit, since the mask has only 32 bits :( */
3062         /* Star is all times */
3063         if (ast_strlen_zero(times) || !strcmp(times, "*")) {
3064                 for (x=0; x<24; x++)
3065                         i->minmask[x] = 0x3fffffff; /* 30 bits */
3066                 return;
3067         }
3068         /* Otherwise expect a range */
3069         e = strchr(times, '-');
3070         if (!e) {
3071                 ast_log(LOG_WARNING, "Time range is not valid. Assuming no restrictions based on time.\n");
3072                 return;
3073         }
3074         *e++ = '\0';
3075         /* XXX why skip non digits ? */
3076         while (*e && !isdigit(*e))
3077                 e++;
3078         if (!*e) {
3079                 ast_log(LOG_WARNING, "Invalid time range.  Assuming no restrictions based on time.\n");
3080                 return;
3081         }
3082         if (sscanf(times, "%d:%d", &s1, &s2) != 2) {
3083                 ast_log(LOG_WARNING, "%s isn't a time.  Assuming no restrictions based on time.\n", times);
3084                 return;
3085         }
3086         if (sscanf(e, "%d:%d", &e1, &e2) != 2) {
3087                 ast_log(LOG_WARNING, "%s isn't a time.  Assuming no restrictions based on time.\n", e);
3088                 return;
3089         }
3090         /* XXX this needs to be optimized */
3091 #if 1
3092         s1 = s1 * 30 + s2/2;
3093         if ((s1 < 0) || (s1 >= 24*30)) {
3094                 ast_log(LOG_WARNING, "%s isn't a valid start time. Assuming no time.\n", times);
3095                 return;
3096         }
3097         e1 = e1 * 30 + e2/2;
3098         if ((e1 < 0) || (e1 >= 24*30)) {
3099                 ast_log(LOG_WARNING, "%s isn't a valid end time. Assuming no time.\n", e);
3100                 return;
3101         }
3102         /* Go through the time and enable each appropriate bit */
3103         for (x=s1;x != e1;x = (x + 1) % (24 * 30)) {
3104                 i->minmask[x/30] |= (1 << (x % 30));
3105         }
3106         /* Do the last one */
3107         i->minmask[x/30] |= (1 << (x % 30));
3108 #else
3109         for (cth=0; cth<24; cth++) {
3110                 /* Initialize masks to blank */
3111                 i->minmask[cth] = 0;
3112                 for (ctm=0; ctm<30; ctm++) {
3113                         if (
3114                         /* First hour with more than one hour */
3115                               (((cth == s1) && (ctm >= s2)) &&
3116                                ((cth < e1)))
3117                         /* Only one hour */
3118                         ||    (((cth == s1) && (ctm >= s2)) &&
3119                                ((cth == e1) && (ctm <= e2)))
3120                         /* In between first and last hours (more than 2 hours) */
3121                         ||    ((cth > s1) &&
3122                                (cth < e1))
3123                         /* Last hour with more than one hour */
3124                         ||    ((cth > s1) &&
3125                                ((cth == e1) && (ctm <= e2)))
3126                         )
3127                                 i->minmask[cth] |= (1 << (ctm / 2));
3128                 }
3129         }
3130 #endif
3131         /* All done */
3132         return;
3133 }
3134
3135 static void null_datad(void *foo)
3136 {
3137 }
3138
3139 /*! \brief Find realtime engine for realtime family */
3140 static struct ast_config_engine *find_engine(const char *family, char *database, int dbsiz, char *table, int tabsiz) 
3141 {
3142         struct ast_config_engine *eng, *ret = NULL;
3143         struct ast_config_map *map;
3144
3145
3146         for (map = config_maps; map; map = map->next) {
3147                 if (!strcasecmp(family, map->name)) {
3148                         if (database)
3149                                 ast_copy_string(database, map->database, dbsiz);
3150                         if (table)
3151                                 ast_copy_string(table, map->table ? map->table : family, tabsiz);
3152                         break;
3153                 }
3154         }
3155
3156         /* Check if the required driver (engine) exist */
3157         if (map) {
3158                 for (eng = config_engine_list; !ret && eng; eng = eng->next) {
3159                         if (!strcasecmp(eng->name, map->driver))
3160                                 ret = eng;
3161                 }
3162         }
3163
3164         
3165         /* if we found a mapping, but the engine is not available, then issue a warning */
3166         if (map && !ret)
3167                 ast_log(LOG_WARNING, "Realtime mapping for '%s' found to engine '%s', but the engine is not available\n", map->name, map->driver);
3168
3169         return ret;
3170 }
3171
3172 struct ast_category *ast_config_get_current_category(const struct ast_config *cfg);
3173
3174 struct ast_category *ast_config_get_current_category(const struct ast_config *cfg)
3175 {
3176         return cfg->current;
3177 }
3178
3179 static struct ast_category *ast_category_new(const char *name);
3180
3181 static struct ast_category *ast_category_new(const char *name) 
3182 {
3183         struct ast_category *category;
3184
3185         if ((category = ast_calloc(1, sizeof(*category))))
3186                 ast_copy_string(category->name, name, sizeof(category->name));
3187         return category;
3188 }
3189
3190 struct ast_category *localized_category_get(const struct ast_config *config, const char *category_name);
3191
3192 struct ast_category *localized_category_get(const struct ast_config *config, const char *category_name)
3193 {
3194         return category_get(config, category_name, 0);
3195 }
3196
3197 static void move_variables(struct ast_category *old, struct ast_category *new)
3198 {
3199         struct ast_variable *var = old->root;
3200         old->root = NULL;
3201 #if 1
3202         /* we can just move the entire list in a single op */
3203         ast_variable_append(new, var);
3204 #else
3205         while (var) {
3206                 struct ast_variable *next = var->next;
3207                 var->next = NULL;
3208                 ast_variable_append(new, var);
3209                 var = next;
3210         }
3211 #endif
3212 }
3213
3214 static void inherit_category(struct ast_category *new, const struct ast_category *base)
3215 {
3216         struct ast_variable *var;
3217
3218         for (var = base->root; var; var = var->next)
3219                 ast_variable_append(new, variable_clone(var));
3220 }
3221
3222 static void ast_category_append(struct ast_config *config, struct ast_category *category);
3223
3224 static void ast_category_append(struct ast_config *config, struct ast_category *category)
3225 {
3226         if (config->last)
3227                 config->last->next = category;
3228         else
3229                 config->root = category;
3230         config->last = category;
3231         config->current = category;
3232 }
3233
3234 static void ast_category_destroy(struct ast_category *cat);
3235
3236 static void ast_category_destroy(struct ast_category *cat)
3237 {
3238         ast_variables_destroy(cat->root);
3239         free(cat);
3240 }
3241
3242 static struct ast_config_engine text_file_engine = {
3243         .name = "text",
3244         .load_func = config_text_file_load,
3245 };
3246
3247
3248 static struct ast_config *ast_config_internal_load(const char *filename, struct ast_config *cfg, int withcomments);
3249
3250 static struct ast_config *ast_config_internal_load(const char *filename, struct ast_config *cfg, int withcomments)
3251 {
3252         char db[256];
3253         char table[256];
3254         struct ast_config_engine *loader = &text_file_engine;
3255         struct ast_config *result; 
3256
3257         if (cfg->include_level == cfg->max_include_level) {
3258                 ast_log(LOG_WARNING, "Maximum Include level (%d) exceeded\n", cfg->max_include_level);
3259                 return NULL;
3260         }
3261
3262         cfg->include_level++;
3263         /*  silence is golden!
3264                 ast_log(LOG_WARNING, "internal loading file %s level=%d\n", filename, cfg->include_level);
3265         */
3266
3267         if (strcmp(filename, extconfig_conf) && strcmp(filename, "asterisk.conf") && config_engine_list) {
3268                 struct ast_config_engine *eng;
3269
3270                 eng = find_engine(filename, db, sizeof(db), table, sizeof(table));
3271
3272
3273                 if (eng && eng->load_func) {
3274                         loader = eng;
3275                 } else {
3276                         eng = find_engine("global", db, sizeof(db), table, sizeof(table));
3277                         if (eng && eng->load_func)
3278                                 loader = eng;
3279                 }
3280         }
3281
3282         result = loader->load_func(db, table, filename, cfg, withcomments);
3283         /* silence is golden 
3284            ast_log(LOG_WARNING, "finished internal loading file %s level=%d\n", filename, cfg->include_level);
3285         */
3286
3287         if (result)
3288                 result->include_level--;
3289
3290         return result;
3291 }
3292
3293
3294 static int process_text_line(struct ast_config *cfg, struct ast_category **cat, char *buf, int lineno, const char *configfile, int withcomments)
3295 {
3296         char *c;
3297         char *cur = buf;
3298         struct ast_variable *v;
3299         char cmd[512], exec_file[512];
3300         int object, do_exec, do_include;
3301
3302         /* Actually parse the entry */
3303         if (cur[0] == '[') {
3304                 struct ast_category *newcat = NULL;
3305                 char *catname;
3306
3307                 /* A category header */
3308                 c = strchr(cur, ']');
3309                 if (!c) {
3310                         ast_log(LOG_WARNING, "parse error: no closing ']', line %d of %s\n", lineno, configfile);
3311                         return -1;
3312                 }
3313                 *c++ = '\0';
3314                 cur++;
3315                 if (*c++ != '(')
3316                         c = NULL;
3317                 catname = cur;
3318                 if (!(*cat = newcat = ast_category_new(catname))) {
3319                         return -1;
3320                 }
3321                 /* add comments */
3322                 if (withcomments && comment_buffer && comment_buffer[0] ) {
3323                         newcat->precomments = ALLOC_COMMENT(comment_buffer);
3324                 }
3325                 if (withcomments && lline_buffer && lline_buffer[0] ) {
3326                         newcat->sameline = ALLOC_COMMENT(lline_buffer);
3327                 }
3328                 if( withcomments )
3329                         CB_RESET();
3330                 
3331                 /* If there are options or categories to inherit from, process them now */
3332                 if (c) {
3333                         if (!(cur = strchr(c, ')'))) {
3334                                 ast_log(LOG_WARNING, "parse error: no closing ')', line %d of %s\n", lineno, configfile);
3335                                 return -1;
3336                         }
3337                         *cur = '\0';
3338                         while ((cur = strsep(&c, ","))) {
3339                                 if (!strcasecmp(cur, "!")) {
3340                                         (*cat)->ignored = 1;
3341                                 } else if (!strcasecmp(cur, "+")) {
3342                                         *cat = category_get(cfg, catname, 1);
3343                                         if (!*cat) {
3344                                                 ast_config_destroy(cfg);
3345                                                 if (newcat)
3346                                                         ast_category_destroy(newcat);
3347                                                 ast_log(LOG_WARNING, "Category addition requested, but category '%s' does not exist, line %d of %s\n", catname, lineno, configfile);
3348                                                 return -1;
3349                                         }
3350                                         if (newcat) {
3351                                                 move_variables(newcat, *cat);
3352                                                 ast_category_destroy(newcat);
3353                                                 newcat = NULL;
3354                                         }
3355                                 } else {
3356                                         struct ast_category *base;
3357                                 
3358                                         base = category_get(cfg, cur, 1);
3359                                         if (!base) {
3360                                                 ast_log(LOG_WARNING, "Inheritance requested, but category '%s' does not exist, line %d of %s\n", cur, lineno, configfile);
3361                                                 return -1;
3362                                         }
3363                                         inherit_category(*cat, base);
3364                                 }
3365                         }
3366                 }
3367                 if (newcat)
3368                         ast_category_append(cfg, *cat);
3369         } else if (cur[0] == '#') {
3370                 /* A directive */
3371                 cur++;
3372                 c = cur;
3373                 while(*c && (*c > 32)) c++;
3374                 if (*c) {
3375                         *c = '\0';
3376                         /* Find real argument */
3377                         c = ast_skip_blanks(c + 1);
3378                         if (!*c)
3379                                 c = NULL;
3380                 } else 
3381                         c = NULL;
3382                 do_include = !strcasecmp(cur, "include");
3383                 if(!do_include)
3384                         do_exec = !strcasecmp(cur, "exec");
3385                 else
3386                         do_exec = 0;
3387                 if (do_exec && !ast_opt_exec_includes) {
3388                         ast_log(LOG_WARNING, "Cannot perform #exec unless execincludes option is enabled in asterisk.conf (options section)!\n");
3389                         do_exec = 0;
3390                 }
3391                 if (do_include || do_exec) {
3392                         if (c) {
3393                                 /* Strip off leading and trailing "'s and <>'s */
3394                                 while((*c == '<') || (*c == '>') || (*c == '\"')) c++;
3395                                 /* Get rid of leading mess */
3396                                 cur = c;
3397                                 while (!ast_strlen_zero(cur)) {
3398                                         c = cur + strlen(cur) - 1;
3399                                         if ((*c == '>') || (*c == '<') || (*c == '\"'))
3400                                                 *c = '\0';
3401                                         else
3402                                                 break;
3403                                 }
3404                                 /* #exec </path/to/executable>
3405                                    We create a tmp file, then we #include it, then we delete it. */
3406                                 if (do_exec) { 
3407                                         snprintf(exec_file, sizeof(exec_file), "/var/tmp/exec.%d.%ld", (int)time(NULL), (long)pthread_self());
3408                                         snprintf(cmd, sizeof(cmd), "%s > %s 2>&1", cur, exec_file);
3409                                         ast_safe_system(cmd);
3410                                         cur = exec_file;
3411                                 } else
3412                                         exec_file[0] = '\0';
3413                                 /* A #include */
3414                                 /* ast_log(LOG_WARNING, "Reading in included file %s withcomments=%d\n", cur, withcomments); */
3415                                 
3416                                 do_include = ast_config_internal_load(cur, cfg, withcomments) ? 1 : 0;
3417                                 if(!ast_strlen_zero(exec_file))
3418                                         unlink(exec_file);
3419                                 if(!do_include)
3420                                         return 0;
3421                                 /* ast_log(LOG_WARNING, "Done reading in included file %s withcomments=%d\n", cur, withcomments); */
3422                                 
3423                         } else {
3424                                 ast_log(LOG_WARNING, "Directive '#%s' needs an argument (%s) at line %d of %s\n", 
3425                                                 do_exec ? "exec" : "include",
3426                                                 do_exec ? "/path/to/executable" : "filename",
3427                                                 lineno,
3428                                                 configfile);
3429                         }
3430                 }
3431                 else 
3432                         ast_log(LOG_WARNING, "Unknown directive '%s' at line %d of %s\n", cur, lineno, configfile);
3433         } else {
3434                 /* Just a line (variable = value) */
3435                 if (!*cat) {
3436                         ast_log(LOG_WARNING,
3437                                 "parse error: No category context for line %d of %s\n", lineno, configfile);
3438                         return -1;
3439                 }
3440                 c = strchr(cur, '=');
3441                 if (c) {
3442                         *c = 0;
3443                         c++;
3444                         /* Ignore > in => */
3445                         if (*c== '>') {
3446                                 object = 1;
3447                                 c++;
3448                         } else
3449                                 object = 0;
3450                         if ((v = ast_variable_new(ast_strip(cur), ast_strip(c)))) {
3451                                 v->lineno = lineno;
3452                                 v->object = object;
3453                                 /* Put and reset comments */
3454                                 v->blanklines = 0;
3455                                 ast_variable_append(*cat, v);
3456                                 /* add comments */
3457                                 if (withcomments && comment_buffer && comment_buffer[0] ) {
3458                                         v->precomments = ALLOC_COMMENT(comment_buffer);
3459                                 }
3460                                 if (withcomments && lline_buffer && lline_buffer[0] ) {
3461                                         v->sameline = ALLOC_COMMENT(lline_buffer);
3462                                 }
3463                                 if( withcomments )
3464                                         CB_RESET();
3465                                 
3466                         } else {
3467                                 return -1;
3468                         }
3469                 } else {
3470                         ast_log(LOG_WARNING, "EXTENSIONS.CONF: No '=' (equal sign) in line %d of %s\n", lineno, configfile);
3471                 }
3472         }
3473         return 0;
3474 }
3475
3476 static int use_local_dir = 1;
3477
3478 void localized_use_local_dir(void);
3479 void localized_use_conf_dir(void);
3480
3481 void localized_use_local_dir(void)
3482 {
3483         use_local_dir = 1;
3484 }
3485
3486 void localized_use_conf_dir(void)
3487 {
3488         use_local_dir = 0;
3489 }
3490
3491
3492 static struct ast_config *config_text_file_load(const char *database, const char *table, const char *filename, struct ast_config *cfg, int withcomments)
3493 {
3494         char fn[256];
3495         char buf[8192];
3496         char *new_buf, *comment_p, *process_buf;
3497         FILE *f;
3498         int lineno=0;
3499         int comment = 0, nest[MAX_NESTED_COMMENTS];
3500         struct ast_category *cat = NULL;
3501         int count = 0;
3502         struct stat statbuf;
3503         
3504         cat = ast_config_get_current_category(cfg);
3505
3506         if (filename[0] == '/') {
3507                 ast_copy_string(fn, filename, sizeof(fn));
3508         } else {
3509                 if (use_local_dir)
3510                         snprintf(fn, sizeof(fn), "./%s", filename);
3511                 else
3512                         snprintf(fn, sizeof(fn), "%s/%s", (char *)ast_config_AST_CONFIG_DIR, filename);
3513         }
3514
3515         if (withcomments && cfg && cfg->include_level < 2 ) {
3516                 CB_INIT();
3517         }
3518         
3519 #ifdef AST_INCLUDE_GLOB
3520         {
3521                 int glob_ret;
3522                 glob_t globbuf;
3523
3524                 globbuf.gl_offs = 0;    /* initialize it to silence gcc */
3525 #ifdef SOLARIS
3526                 glob_ret = glob(fn, GLOB_NOCHECK, NULL, &globbuf);
3527 #else
3528                 glob_ret = glob(fn, GLOB_NOMAGIC|GLOB_BRACE, NULL, &globbuf);
3529 #endif
3530                 if (glob_ret == GLOB_NOSPACE)
3531                         ast_log(LOG_WARNING,
3532                                 "Glob Expansion of pattern '%s' failed: Not enough memory\n", fn);
3533                 else if (glob_ret  == GLOB_ABORTED)
3534                         ast_log(LOG_WARNING,
3535                                 "Glob Expansion of pattern '%s' failed: Read error\n", fn);
3536                 else  {
3537                         /* loop over expanded files */
3538                         int i;
3539                         for (i=0; i<globbuf.gl_pathc; i++) {
3540                                 ast_copy_string(fn, globbuf.gl_pathv[i], sizeof(fn));
3541 #endif
3542         do {
3543                 if (stat(fn, &statbuf))
3544                         continue;
3545
3546                 if (!S_ISREG(statbuf.st_mode)) {
3547                         ast_log(LOG_WARNING, "'%s' is not a regular file, ignoring\n", fn);
3548                         continue;
3549                 }
3550                 if (option_verbose > 1) {
3551                         ast_verbose(VERBOSE_PREFIX_2 "Parsing '%s': ", fn);
3552                         fflush(stdout);
3553                 }
3554                 if (!(f = fopen(fn, "r"))) {
3555                         if (option_debug)
3556                                 ast_log(LOG_DEBUG, "No file to parse: %s\n", fn);
3557                         if (option_verbose > 1)
3558                                 ast_verbose( "Not found (%s)\n", strerror(errno));
3559                         continue;
3560                 }
3561                 count++;
3562                 if (option_debug)
3563                         ast_log(LOG_DEBUG, "Parsing %s\n", fn);
3564                 if (option_verbose > 1)
3565                         ast_verbose("Found\n");
3566                 while(!feof(f)) {
3567                         lineno++;
3568                         if (fgets(buf, sizeof(buf), f)) {
3569                                 if ( withcomments ) {    
3570                                         CB_ADD(lline_buffer);       /* add the current lline buffer to the comment buffer */
3571                                         lline_buffer[0] = 0;        /* erase the lline buffer */
3572                                 }
3573                                 
3574                                 new_buf = buf;
3575                                 if (comment) 
3576                                         process_buf = NULL;
3577                                 else
3578                                         process_buf = buf;
3579                                 
3580                                 while ((comment_p = strchr(new_buf, COMMENT_META))) {
3581                                         if ((comment_p > new_buf) && (*(comment_p-1) == '\\')) {
3582                                                 /* Yuck, gotta memmove */
3583                                                 memmove(comment_p - 1, comment_p, strlen(comment_p) + 1);
3584                                                 new_buf = comment_p;
3585                                         } else if(comment_p[1] == COMMENT_TAG && comment_p[2] == COMMENT_TAG && (comment_p[3] != '-')) {
3586                                                 /* Meta-Comment start detected ";--" */
3587                                                 if (comment < MAX_NESTED_COMMENTS) {
3588                                                         *comment_p = '\0';
3589                                                         new_buf = comment_p + 3;
3590                                                         comment++;
3591                                                         nest[comment-1] = lineno;
3592                                                 } else {
3593                                                         ast_log(LOG_ERROR, "Maximum nest limit of %d reached.\n", MAX_NESTED_COMMENTS);
3594                                                 }
3595                                         } else if ((comment_p >= new_buf + 2) &&
3596                                                    (*(comment_p - 1) == COMMENT_TAG) &&
3597                                                    (*(comment_p - 2) == COMMENT_TAG)) {
3598                                                 /* Meta-Comment end detected */
3599                                                 comment--;
3600                                                 new_buf = comment_p + 1;
3601                                                 if (!comment) {
3602                                                         /* Back to non-comment now */
3603                                                         if (process_buf) {
3604                                                                 /* Actually have to move what's left over the top, then continue */
3605                                                                 char *oldptr;
3606                                                                 oldptr = process_buf + strlen(process_buf);
3607                                                                 if ( withcomments ) {
3608                                                                         CB_ADD(";");
3609                                                                         CB_ADD_LEN(oldptr+1,new_buf-oldptr-1);
3610                                                                 }
3611                                                                 
3612                                                                 memmove(oldptr, new_buf, strlen(new_buf) + 1);
3613                                                                 new_buf = oldptr;
3614                                                         } else
3615                                                                 process_buf = new_buf;
3616                                                 }
3617                                         } else {
3618                                                 if (!comment) {
3619                                                         /* If ; is found, and we are not nested in a comment, 
3620                                                            we immediately stop all comment processing */
3621                                                         if ( withcomments ) {
3622                                                                 LLB_ADD(comment_p);
3623                                                         }
3624                                                         *comment_p = '\0'; 
3625                                                         new_buf = comment_p;
3626                                                 } else
3627                                                         new_buf = comment_p + 1;
3628                                         }
3629                                 }
3630                                 if( withcomments && comment && !process_buf )
3631                                 {
3632                                         CB_ADD(buf);  /* the whole line is a comment, store it */
3633                                 }
3634                                 
3635                                 if (process_buf) {
3636                                         char *buf = ast_strip(process_buf);
3637                                         if (!ast_strlen_zero(buf)) {
3638                                                 if (process_text_line(cfg, &cat, buf, lineno, filename, withcomments)) {
3639                                                         cfg = NULL;
3640                                                         break;
3641                                                 }
3642                                         }
3643                                 }
3644                         }
3645                 }
3646                 fclose(f);              
3647         } while(0);
3648         if (comment) {
3649                 ast_log(LOG_WARNING,"Unterminated comment detected beginning on line %d\n", nest[comment]);
3650         }
3651 #ifdef AST_INCLUDE_GLOB
3652                                         if (!cfg)
3653                                                 break;
3654                                 }
3655                                 globfree(&globbuf);
3656                         }
3657                 }
3658 #endif
3659         if (cfg && cfg->include_level == 1 && withcomments && comment_buffer) {
3660                 if (comment_buffer) { 
3661                         free(comment_buffer);
3662                         free(lline_buffer);
3663                         comment_buffer=0; 
3664                         lline_buffer=0; 
3665                         comment_buffer_size=0; 
3666                         lline_buffer_size=0;
3667                 }
3668         }
3669         if (count == 0)
3670                 return NULL;
3671
3672         return cfg;
3673 }
3674
3675
3676 static struct ast_config *ast_config_new(void) ;
3677
3678 static struct ast_config *ast_config_new(void) 
3679 {
3680         struct ast_config *config;
3681
3682         if ((config = ast_calloc(1, sizeof(*config))))
3683                 config->max_include_level = MAX_INCLUDE_LEVEL;
3684         return config;
3685 }
3686
3687 struct ast_config *localized_config_load(const char *filename);
3688
3689 struct ast_config *localized_config_load(const char *filename)
3690 {
3691         struct ast_config *cfg;
3692         struct ast_config *result;
3693
3694         cfg = ast_config_new();
3695         if (!cfg)
3696                 return NULL;
3697
3698         result = ast_config_internal_load(filename, cfg, 0);
3699         if (!result)
3700                 ast_config_destroy(cfg);
3701
3702         return result;
3703 }
3704
3705 struct ast_config *localized_config_load_with_comments(const char *filename);
3706
3707 struct ast_config *localized_config_load_with_comments(const char *filename)
3708 {
3709         struct ast_config *cfg;
3710         struct ast_config *result;
3711
3712         cfg = ast_config_new();
3713         if (!cfg)
3714                 return NULL;
3715
3716         result = ast_config_internal_load(filename, cfg, 1);
3717         if (!result)
3718                 ast_config_destroy(cfg);
3719
3720         return result;
3721 }