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