Make ast_atomic_fetchadd_int_slow magically appear in extconf.
[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 #include "asterisk/paths.h"     /* we use AST_CONFIG_DIR */
29
30 #include <errno.h>
31 #include <time.h>
32 #include <sys/stat.h>
33 #include <sys/types.h>
34 #include <sys/time.h>
35 #include <sys/resource.h>
36 #include <sys/wait.h>
37 #include <stdarg.h>
38 #include <string.h>
39 #include <locale.h>
40 #include <ctype.h>
41 #if !defined(SOLARIS) && !defined(__CYGWIN__)
42 #include <err.h>
43 #endif
44 #include <regex.h>
45 #include <limits.h>
46 #include <pthread.h>
47 #include <netdb.h>
48 #include <sys/param.h>
49 #define ASINCLUDE_GLOB 1
50 #ifdef AST_INCLUDE_GLOB
51 #if defined(__Darwin__) || defined(__CYGWIN__)
52 #define GLOB_ABORTED GLOB_ABEND
53 #endif
54 # include <glob.h>
55 #endif
56
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) && defined(PTHREAD_MUTEX_RECURSIVE_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 #if defined(HAVE_OSX_ATOMICS)
1760 #include "libkern/OSAtomic.h"
1761 #endif
1762
1763 /*! \brief Atomically add v to *p and return * the previous value of *p.
1764  * This can be used to handle reference counts, and the return value
1765  * can be used to generate unique identifiers.
1766  */
1767
1768 #if defined(HAVE_GCC_ATOMICS)
1769 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
1770 {
1771         return __sync_fetch_and_add(p, v);
1772 })
1773 #elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 4)
1774 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
1775 {
1776         return OSAtomicAdd32(v, (int32_t *) p);
1777 })
1778 #elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 8)
1779 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
1780 {
1781         return OSAtomicAdd64(v, (int64_t *) p);
1782 #elif defined (__i386__) || defined(__x86_64__)
1783 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
1784 {
1785         __asm __volatile (
1786         "       lock   xaddl   %0, %1 ;        "
1787         : "+r" (v),                     /* 0 (result) */   
1788           "=m" (*p)                     /* 1 */
1789         : "m" (*p));                    /* 2 */
1790         return (v);
1791 })
1792 #else
1793 static int ast_atomic_fetchadd_int_slow(volatile int *p, int v)
1794 {
1795         int ret;
1796         ret = *p;
1797         *p += v;
1798         return ret;
1799 }
1800 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
1801 {
1802         return ast_atomic_fetchadd_int_slow(p, v);
1803 })
1804 #endif
1805
1806 /*! \brief decrement *p by 1 and return true if the variable has reached 0.
1807  * Useful e.g. to check if a refcount has reached 0.
1808  */
1809 #if defined(HAVE_GCC_ATOMICS)
1810 AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
1811 {
1812         return __sync_sub_and_fetch(p, 1) == 0;
1813 })
1814 #elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 4)
1815 AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
1816 {
1817         return OSAtomicAdd32( -1, (int32_t *) p) == 0;
1818 })
1819 #elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 8)
1820 AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
1821 {
1822         return OSAtomicAdd64( -1, (int64_t *) p) == 0;
1823 #else
1824 AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
1825 {
1826         int a = ast_atomic_fetchadd_int(p, -1);
1827         return a == 1; /* true if the value is 0 now (so it was 1 previously) */
1828 })
1829 #endif
1830
1831 #ifndef DEBUG_CHANNEL_LOCKS
1832 /*! \brief Lock a channel. If DEBUG_CHANNEL_LOCKS is defined 
1833         in the Makefile, print relevant output for debugging */
1834 #define ast_channel_lock(x)             ast_mutex_lock(&x->lock)
1835 /*! \brief Unlock a channel. If DEBUG_CHANNEL_LOCKS is defined 
1836         in the Makefile, print relevant output for debugging */
1837 #define ast_channel_unlock(x)           ast_mutex_unlock(&x->lock)
1838 /*! \brief Try locking a channel. If DEBUG_CHANNEL_LOCKS is defined 
1839         in the Makefile, print relevant output for debugging */
1840 #define ast_channel_trylock(x)          ast_mutex_trylock(&x->lock)
1841 #else
1842
1843 /*! \brief Lock AST channel (and print debugging output)
1844 \note You need to enable DEBUG_CHANNEL_LOCKS for this function */
1845 int ast_channel_lock(struct ast_channel *chan);
1846
1847 /*! \brief Unlock AST channel (and print debugging output)
1848 \note You need to enable DEBUG_CHANNEL_LOCKS for this function
1849 */
1850 int ast_channel_unlock(struct ast_channel *chan);
1851
1852 /*! \brief Lock AST channel (and print debugging output)
1853 \note   You need to enable DEBUG_CHANNEL_LOCKS for this function */
1854 int ast_channel_trylock(struct ast_channel *chan);
1855 #endif
1856
1857
1858 /* linkedlists.h */
1859
1860 #define AST_LIST_LOCK(head)                                             \
1861         ast_mutex_lock(&(head)->lock) 
1862
1863 /*!
1864   \brief Write locks a list.
1865   \param head This is a pointer to the list head structure
1866
1867   This macro attempts to place an exclusive write lock in the
1868   list head structure pointed to by head.
1869   Returns non-zero on success, 0 on failure
1870 */
1871 #define AST_RWLIST_WRLOCK(head)                                         \
1872         ast_rwlock_wrlock(&(head)->lock)
1873
1874 /*!
1875   \brief Read locks a list.
1876   \param head This is a pointer to the list head structure
1877
1878   This macro attempts to place a read lock in the
1879   list head structure pointed to by head.
1880   Returns non-zero on success, 0 on failure
1881 */
1882 #define AST_RWLIST_RDLOCK(head)                                         \
1883         ast_rwlock_rdlock(&(head)->lock)
1884         
1885 /*!
1886   \brief Locks a list, without blocking if the list is locked.
1887   \param head This is a pointer to the list head structure
1888
1889   This macro attempts to place an exclusive lock in the
1890   list head structure pointed to by head.
1891   Returns non-zero on success, 0 on failure
1892 */
1893 #define AST_LIST_TRYLOCK(head)                                          \
1894         ast_mutex_trylock(&(head)->lock) 
1895
1896 /*!
1897   \brief Write locks a list, without blocking if the list is locked.
1898   \param head This is a pointer to the list head structure
1899
1900   This macro attempts to place an exclusive write lock in the
1901   list head structure pointed to by head.
1902   Returns non-zero on success, 0 on failure
1903 */
1904 #define AST_RWLIST_TRYWRLOCK(head)                                      \
1905         ast_rwlock_trywrlock(&(head)->lock)
1906
1907 /*!
1908   \brief Read locks a list, without blocking if the list is locked.
1909   \param head This is a pointer to the list head structure
1910
1911   This macro attempts to place a read lock in the
1912   list head structure pointed to by head.
1913   Returns non-zero on success, 0 on failure
1914 */
1915 #define AST_RWLIST_TRYRDLOCK(head)                                      \
1916         ast_rwlock_tryrdlock(&(head)->lock)
1917         
1918 /*!
1919   \brief Attempts to unlock a list.
1920   \param head This is a pointer to the list head structure
1921
1922   This macro attempts to remove an exclusive lock from the
1923   list head structure pointed to by head. If the list
1924   was not locked by this thread, this macro has no effect.
1925 */
1926 #define AST_LIST_UNLOCK(head)                                           \
1927         ast_mutex_unlock(&(head)->lock)
1928
1929 /*!
1930   \brief Attempts to unlock a read/write based list.
1931   \param head This is a pointer to the list head structure
1932
1933   This macro attempts to remove a read or write lock from the
1934   list head structure pointed to by head. If the list
1935   was not locked by this thread, this macro has no effect.
1936 */
1937 #define AST_RWLIST_UNLOCK(head)                                         \
1938         ast_rwlock_unlock(&(head)->lock)
1939
1940 /*!
1941   \brief Defines a structure to be used to hold a list of specified type.
1942   \param name This will be the name of the defined structure.
1943   \param type This is the type of each list entry.
1944
1945   This macro creates a structure definition that can be used
1946   to hold a list of the entries of type \a type. It does not actually
1947   declare (allocate) a structure; to do that, either follow this
1948   macro with the desired name of the instance you wish to declare,
1949   or use the specified \a name to declare instances elsewhere.
1950
1951   Example usage:
1952   \code
1953   static AST_LIST_HEAD(entry_list, entry) entries;
1954   \endcode
1955
1956   This would define \c struct \c entry_list, and declare an instance of it named
1957   \a entries, all intended to hold a list of type \c struct \c entry.
1958 */
1959 #define AST_LIST_HEAD(name, type)                                       \
1960 struct name {                                                           \
1961         struct type *first;                                             \
1962         struct type *last;                                              \
1963         ast_mutex_t lock;                                               \
1964 }
1965
1966 /*!
1967   \brief Defines a structure to be used to hold a read/write list of specified type.
1968   \param name This will be the name of the defined structure.
1969   \param type This is the type of each list entry.
1970
1971   This macro creates a structure definition that can be used
1972   to hold a list of the entries of type \a type. It does not actually
1973   declare (allocate) a structure; to do that, either follow this
1974   macro with the desired name of the instance you wish to declare,
1975   or use the specified \a name to declare instances elsewhere.
1976
1977   Example usage:
1978   \code
1979   static AST_RWLIST_HEAD(entry_list, entry) entries;
1980   \endcode
1981
1982   This would define \c struct \c entry_list, and declare an instance of it named
1983   \a entries, all intended to hold a list of type \c struct \c entry.
1984 */
1985 #define AST_RWLIST_HEAD(name, type)                                     \
1986 struct name {                                                           \
1987         struct type *first;                                             \
1988         struct type *last;                                              \
1989         ast_rwlock_t lock;                                              \
1990 }
1991
1992 /*!
1993   \brief Defines a structure to be used to hold a list of specified type (with no lock).
1994   \param name This will be the name of the defined structure.
1995   \param type This is the type of each list entry.
1996
1997   This macro creates a structure definition that can be used
1998   to hold a list of the entries of type \a type. It does not actually
1999   declare (allocate) a structure; to do that, either follow this
2000   macro with the desired name of the instance you wish to declare,
2001   or use the specified \a name to declare instances elsewhere.
2002
2003   Example usage:
2004   \code
2005   static AST_LIST_HEAD_NOLOCK(entry_list, entry) entries;
2006   \endcode
2007
2008   This would define \c struct \c entry_list, and declare an instance of it named
2009   \a entries, all intended to hold a list of type \c struct \c entry.
2010 */
2011 #define AST_LIST_HEAD_NOLOCK(name, type)                                \
2012 struct name {                                                           \
2013         struct type *first;                                             \
2014         struct type *last;                                              \
2015 }
2016
2017 /*!
2018   \brief Defines initial values for a declaration of AST_LIST_HEAD
2019 */
2020 #define AST_LIST_HEAD_INIT_VALUE        {               \
2021         .first = NULL,                                  \
2022         .last = NULL,                                   \
2023         .lock = AST_MUTEX_INIT_VALUE,                   \
2024         }
2025
2026 /*!
2027   \brief Defines initial values for a declaration of AST_RWLIST_HEAD
2028 */
2029 #define AST_RWLIST_HEAD_INIT_VALUE      {               \
2030         .first = NULL,                                  \
2031         .last = NULL,                                   \
2032         .lock = AST_RWLOCK_INIT_VALUE,                  \
2033         }
2034
2035 /*!
2036   \brief Defines initial values for a declaration of AST_LIST_HEAD_NOLOCK
2037 */
2038 #define AST_LIST_HEAD_NOLOCK_INIT_VALUE {       \
2039         .first = NULL,                                  \
2040         .last = NULL,                                   \
2041         }
2042
2043 /*!
2044   \brief Defines a structure to be used to hold a list of specified type, statically initialized.
2045   \param name This will be the name of the defined structure.
2046   \param type This is the type of each list entry.
2047
2048   This macro creates a structure definition that can be used
2049   to hold a list of the entries of type \a type, and allocates an instance
2050   of it, initialized to be empty.
2051
2052   Example usage:
2053   \code
2054   static AST_LIST_HEAD_STATIC(entry_list, entry);
2055   \endcode
2056
2057   This would define \c struct \c entry_list, intended to hold a list of
2058   type \c struct \c entry.
2059 */
2060 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
2061 #define AST_LIST_HEAD_STATIC(name, type)                                \
2062 struct name {                                                           \
2063         struct type *first;                                             \
2064         struct type *last;                                              \
2065         ast_mutex_t lock;                                               \
2066 } name;                                                                 \
2067 static void  __attribute__ ((constructor)) init_##name(void)            \
2068 {                                                                       \
2069         AST_LIST_HEAD_INIT(&name);                                      \
2070 }                                                                       \
2071 static void  __attribute__ ((destructor)) fini_##name(void)             \
2072 {                                                                       \
2073         AST_LIST_HEAD_DESTROY(&name);                                   \
2074 }                                                                       \
2075 struct __dummy_##name
2076 #else
2077 #define AST_LIST_HEAD_STATIC(name, type)                                \
2078 struct name {                                                           \
2079         struct type *first;                                             \
2080         struct type *last;                                              \
2081         ast_mutex_t lock;                                               \
2082 } name = AST_LIST_HEAD_INIT_VALUE
2083 #endif
2084
2085 /*!
2086   \brief Defines a structure to be used to hold a read/write list of specified type, statically initialized.
2087   \param name This will be the name of the defined structure.
2088   \param type This is the type of each list entry.
2089
2090   This macro creates a structure definition that can be used
2091   to hold a list of the entries of type \a type, and allocates an instance
2092   of it, initialized to be empty.
2093
2094   Example usage:
2095   \code
2096   static AST_RWLIST_HEAD_STATIC(entry_list, entry);
2097   \endcode
2098
2099   This would define \c struct \c entry_list, intended to hold a list of
2100   type \c struct \c entry.
2101 */
2102 #ifndef AST_RWLOCK_INIT_VALUE
2103 #define AST_RWLIST_HEAD_STATIC(name, type)                              \
2104 struct name {                                                           \
2105         struct type *first;                                             \
2106         struct type *last;                                              \
2107         ast_rwlock_t lock;                                              \
2108 } name;                                                                 \
2109 static void  __attribute__ ((constructor)) init_##name(void)            \
2110 {                                                                       \
2111         AST_RWLIST_HEAD_INIT(&name);                                    \
2112 }                                                                       \
2113 static void  __attribute__ ((destructor)) fini_##name(void)             \
2114 {                                                                       \
2115         AST_RWLIST_HEAD_DESTROY(&name);                                 \
2116 }                                                                       \
2117 struct __dummy_##name
2118 #else
2119 #define AST_RWLIST_HEAD_STATIC(name, type)                              \
2120 struct name {                                                           \
2121         struct type *first;                                             \
2122         struct type *last;                                              \
2123         ast_rwlock_t lock;                                              \
2124 } name = AST_RWLIST_HEAD_INIT_VALUE
2125 #endif
2126
2127 /*!
2128   \brief Defines a structure to be used to hold a list of specified type, statically initialized.
2129
2130   This is the same as AST_LIST_HEAD_STATIC, except without the lock included.
2131 */
2132 #define AST_LIST_HEAD_NOLOCK_STATIC(name, type)                         \
2133 struct name {                                                           \
2134         struct type *first;                                             \
2135         struct type *last;                                              \
2136 } name = AST_LIST_HEAD_NOLOCK_INIT_VALUE
2137
2138 /*!
2139   \brief Initializes a list head structure with a specified first entry.
2140   \param head This is a pointer to the list head structure
2141   \param entry pointer to the list entry that will become the head of the list
2142
2143   This macro initializes a list head structure by setting the head
2144   entry to the supplied value and recreating the embedded lock.
2145 */
2146 #define AST_LIST_HEAD_SET(head, entry) do {                             \
2147         (head)->first = (entry);                                        \
2148         (head)->last = (entry);                                         \
2149         ast_mutex_init(&(head)->lock);                                  \
2150 } while (0)
2151
2152 /*!
2153   \brief Initializes an rwlist head structure with a specified first entry.
2154   \param head This is a pointer to the list head structure
2155   \param entry pointer to the list entry that will become the head of the list
2156
2157   This macro initializes a list head structure by setting the head
2158   entry to the supplied value and recreating the embedded lock.
2159 */
2160 #define AST_RWLIST_HEAD_SET(head, entry) do {                           \
2161         (head)->first = (entry);                                        \
2162         (head)->last = (entry);                                         \
2163         ast_rwlock_init(&(head)->lock);                                 \
2164 } while (0)
2165
2166 /*!
2167   \brief Initializes a list head structure with a specified first entry.
2168   \param head This is a pointer to the list head structure
2169   \param entry pointer to the list entry that will become the head of the list
2170
2171   This macro initializes a list head structure by setting the head
2172   entry to the supplied value.
2173 */
2174 #define AST_LIST_HEAD_SET_NOLOCK(head, entry) do {                      \
2175         (head)->first = (entry);                                        \
2176         (head)->last = (entry);                                         \
2177 } while (0)
2178
2179 /*!
2180   \brief Declare a forward link structure inside a list entry.
2181   \param type This is the type of each list entry.
2182
2183   This macro declares a structure to be used to link list entries together.
2184   It must be used inside the definition of the structure named in
2185   \a type, as follows:
2186
2187   \code
2188   struct list_entry {
2189         ...
2190         AST_LIST_ENTRY(list_entry) list;
2191   }
2192   \endcode
2193
2194   The field name \a list here is arbitrary, and can be anything you wish.
2195 */
2196 #define AST_LIST_ENTRY(type)                                            \
2197 struct {                                                                \
2198         struct type *next;                                              \
2199 }
2200
2201 #define AST_RWLIST_ENTRY AST_LIST_ENTRY
2202  
2203 /*!
2204   \brief Returns the first entry contained in a list.
2205   \param head This is a pointer to the list head structure
2206  */
2207 #define AST_LIST_FIRST(head)    ((head)->first)
2208
2209 #define AST_RWLIST_FIRST AST_LIST_FIRST
2210
2211 /*!
2212   \brief Returns the last entry contained in a list.
2213   \param head This is a pointer to the list head structure
2214  */
2215 #define AST_LIST_LAST(head)     ((head)->last)
2216
2217 #define AST_RWLIST_LAST AST_LIST_LAST
2218
2219 /*!
2220   \brief Returns the next entry in the list after the given entry.
2221   \param elm This is a pointer to the current entry.
2222   \param field This is the name of the field (declared using AST_LIST_ENTRY())
2223   used to link entries of this list together.
2224 */
2225 #define AST_LIST_NEXT(elm, field)       ((elm)->field.next)
2226
2227 #define AST_RWLIST_NEXT AST_LIST_NEXT
2228
2229 /*!
2230   \brief Checks whether the specified list contains any entries.
2231   \param head This is a pointer to the list head structure
2232
2233   Returns non-zero if the list has entries, zero if not.
2234  */
2235 #define AST_LIST_EMPTY(head)    (AST_LIST_FIRST(head) == NULL)
2236
2237 #define AST_RWLIST_EMPTY AST_LIST_EMPTY
2238
2239 /*!
2240   \brief Loops over (traverses) the entries in a list.
2241   \param head This is a pointer to the list head structure
2242   \param var This is the name of the variable that will hold a pointer to the
2243   current list entry on each iteration. It must be declared before calling
2244   this macro.
2245   \param field This is the name of the field (declared using AST_LIST_ENTRY())
2246   used to link entries of this list together.
2247
2248   This macro is use to loop over (traverse) the entries in a list. It uses a
2249   \a for loop, and supplies the enclosed code with a pointer to each list
2250   entry as it loops. It is typically used as follows:
2251   \code
2252   static AST_LIST_HEAD(entry_list, list_entry) entries;
2253   ...
2254   struct list_entry {
2255         ...
2256         AST_LIST_ENTRY(list_entry) list;
2257   }
2258   ...
2259   struct list_entry *current;
2260   ...
2261   AST_LIST_TRAVERSE(&entries, current, list) {
2262      (do something with current here)
2263   }
2264   \endcode
2265   \warning If you modify the forward-link pointer contained in the \a current entry while
2266   inside the loop, the behavior will be unpredictable. At a minimum, the following
2267   macros will modify the forward-link pointer, and should not be used inside
2268   AST_LIST_TRAVERSE() against the entry pointed to by the \a current pointer without
2269   careful consideration of their consequences:
2270   \li AST_LIST_NEXT() (when used as an lvalue)
2271   \li AST_LIST_INSERT_AFTER()
2272   \li AST_LIST_INSERT_HEAD()
2273   \li AST_LIST_INSERT_TAIL()
2274 */
2275 #define AST_LIST_TRAVERSE(head,var,field)                               \
2276         for((var) = (head)->first; (var); (var) = (var)->field.next)
2277
2278 #define AST_RWLIST_TRAVERSE AST_LIST_TRAVERSE
2279
2280 /*!
2281   \brief Loops safely over (traverses) the entries in a list.
2282   \param head This is a pointer to the list head structure
2283   \param var This is the name of the variable that will hold a pointer to the
2284   current list entry on each iteration. It must be declared before calling
2285   this macro.
2286   \param field This is the name of the field (declared using AST_LIST_ENTRY())
2287   used to link entries of this list together.
2288
2289   This macro is used to safely loop over (traverse) the entries in a list. It
2290   uses a \a for loop, and supplies the enclosed code with a pointer to each list
2291   entry as it loops. It is typically used as follows:
2292
2293   \code
2294   static AST_LIST_HEAD(entry_list, list_entry) entries;
2295   ...
2296   struct list_entry {
2297         ...
2298         AST_LIST_ENTRY(list_entry) list;
2299   }
2300   ...
2301   struct list_entry *current;
2302   ...
2303   AST_LIST_TRAVERSE_SAFE_BEGIN(&entries, current, list) {
2304      (do something with current here)
2305   }
2306   AST_LIST_TRAVERSE_SAFE_END;
2307   \endcode
2308
2309   It differs from AST_LIST_TRAVERSE() in that the code inside the loop can modify
2310   (or even free, after calling AST_LIST_REMOVE_CURRENT()) the entry pointed to by
2311   the \a current pointer without affecting the loop traversal.
2312 */
2313 #define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field) {                                \
2314         typeof((head)->first) __list_next;                                              \
2315         typeof((head)->first) __list_prev = NULL;                                       \
2316         typeof((head)->first) __new_prev = NULL;                                        \
2317         for ((var) = (head)->first, __new_prev = (var),                                 \
2318               __list_next = (var) ? (var)->field.next : NULL;                           \
2319              (var);                                                                     \
2320              __list_prev = __new_prev, (var) = __list_next,                             \
2321              __new_prev = (var),                                                        \
2322              __list_next = (var) ? (var)->field.next : NULL                             \
2323             )
2324
2325 #define AST_RWLIST_TRAVERSE_SAFE_BEGIN AST_LIST_TRAVERSE_SAFE_BEGIN
2326
2327 /*!
2328   \brief Removes the \a current entry from a list during a traversal.
2329   \param head This is a pointer to the list head structure
2330   \param field This is the name of the field (declared using AST_LIST_ENTRY())
2331   used to link entries of this list together.
2332
2333   \note This macro can \b only be used inside an AST_LIST_TRAVERSE_SAFE_BEGIN()
2334   block; it is used to unlink the current entry from the list without affecting
2335   the list traversal (and without having to re-traverse the list to modify the
2336   previous entry, if any).
2337  */
2338 #define AST_LIST_REMOVE_CURRENT(head, field)                                            \
2339         __new_prev->field.next = NULL;                                                  \
2340         __new_prev = __list_prev;                                                       \
2341         if (__list_prev)                                                                \
2342                 __list_prev->field.next = __list_next;                                  \
2343         else                                                                            \
2344                 (head)->first = __list_next;                                            \
2345         if (!__list_next)                                                               \
2346                 (head)->last = __list_prev;
2347
2348 #define AST_RWLIST_REMOVE_CURRENT AST_LIST_REMOVE_CURRENT
2349
2350 /*!
2351   \brief Inserts a list entry before the current entry during a traversal.
2352   \param head This is a pointer to the list head structure
2353   \param elm This is a pointer to the entry to be inserted.
2354   \param field This is the name of the field (declared using AST_LIST_ENTRY())
2355   used to link entries of this list together.
2356
2357   \note This macro can \b only be used inside an AST_LIST_TRAVERSE_SAFE_BEGIN()
2358   block.
2359  */
2360 #define AST_LIST_INSERT_BEFORE_CURRENT(head, elm, field) do {           \
2361         if (__list_prev) {                                              \
2362                 (elm)->field.next = __list_prev->field.next;            \
2363                 __list_prev->field.next = elm;                          \
2364         } else {                                                        \
2365                 (elm)->field.next = (head)->first;                      \
2366                 (head)->first = (elm);                                  \
2367         }                                                               \
2368         __new_prev = (elm);                                             \
2369 } while (0)
2370
2371 #define AST_RWLIST_INSERT_BEFORE_CURRENT AST_LIST_INSERT_BEFORE_CURRENT
2372
2373 /*!
2374   \brief Closes a safe loop traversal block.
2375  */
2376 #define AST_LIST_TRAVERSE_SAFE_END  }
2377
2378 #define AST_RWLIST_TRAVERSE_SAFE_END AST_LIST_TRAVERSE_SAFE_END
2379
2380 /*!
2381   \brief Initializes a list head structure.
2382   \param head This is a pointer to the list head structure
2383
2384   This macro initializes a list head structure by setting the head
2385   entry to \a NULL (empty list) and recreating the embedded lock.
2386 */
2387 #define AST_LIST_HEAD_INIT(head) {                                      \
2388         (head)->first = NULL;                                           \
2389         (head)->last = NULL;                                            \
2390         ast_mutex_init(&(head)->lock);                                  \
2391 }
2392
2393 /*!
2394   \brief Initializes an rwlist head structure.
2395   \param head This is a pointer to the list head structure
2396
2397   This macro initializes a list head structure by setting the head
2398   entry to \a NULL (empty list) and recreating the embedded lock.
2399 */
2400 #define AST_RWLIST_HEAD_INIT(head) {                                    \
2401         (head)->first = NULL;                                           \
2402         (head)->last = NULL;                                            \
2403         ast_rwlock_init(&(head)->lock);                                 \
2404 }
2405
2406 /*!
2407   \brief Destroys a list head structure.
2408   \param head This is a pointer to the list head structure
2409
2410   This macro destroys a list head structure by setting the head
2411   entry to \a NULL (empty list) and destroying the embedded lock.
2412   It does not free the structure from memory.
2413 */
2414 #define AST_LIST_HEAD_DESTROY(head) {                                   \
2415         (head)->first = NULL;                                           \
2416         (head)->last = NULL;                                            \
2417         ast_mutex_destroy(&(head)->lock);                               \
2418 }
2419
2420 /*!
2421   \brief Destroys an rwlist head structure.
2422   \param head This is a pointer to the list head structure
2423
2424   This macro destroys a list head structure by setting the head
2425   entry to \a NULL (empty list) and destroying the embedded lock.
2426   It does not free the structure from memory.
2427 */
2428 #define AST_RWLIST_HEAD_DESTROY(head) {                                 \
2429         (head)->first = NULL;                                           \
2430         (head)->last = NULL;                                            \
2431         ast_rwlock_destroy(&(head)->lock);                              \
2432 }
2433
2434 /*!
2435   \brief Initializes a list head structure.
2436   \param head This is a pointer to the list head structure
2437
2438   This macro initializes a list head structure by setting the head
2439   entry to \a NULL (empty list). There is no embedded lock handling
2440   with this macro.
2441 */
2442 #define AST_LIST_HEAD_INIT_NOLOCK(head) {                               \
2443         (head)->first = NULL;                                           \
2444         (head)->last = NULL;                                            \
2445 }
2446
2447 /*!
2448   \brief Inserts a list entry after a given entry.
2449   \param head This is a pointer to the list head structure
2450   \param listelm This is a pointer to the entry after which the new entry should
2451   be inserted.
2452   \param elm This is a pointer to the entry to be inserted.
2453   \param field This is the name of the field (declared using AST_LIST_ENTRY())
2454   used to link entries of this list together.
2455  */
2456 #define AST_LIST_INSERT_AFTER(head, listelm, elm, field) do {           \
2457         (elm)->field.next = (listelm)->field.next;                      \
2458         (listelm)->field.next = (elm);                                  \
2459         if ((head)->last == (listelm))                                  \
2460                 (head)->last = (elm);                                   \
2461 } while (0)
2462
2463 #define AST_RWLIST_INSERT_AFTER AST_LIST_INSERT_AFTER
2464
2465 /*!
2466   \brief Inserts a list entry at the head of a list.
2467   \param head This is a pointer to the list head structure
2468   \param elm This is a pointer to the entry to be inserted.
2469   \param field This is the name of the field (declared using AST_LIST_ENTRY())
2470   used to link entries of this list together.
2471  */
2472 #define AST_LIST_INSERT_HEAD(head, elm, field) do {                     \
2473                 (elm)->field.next = (head)->first;                      \
2474                 (head)->first = (elm);                                  \
2475                 if (!(head)->last)                                      \
2476                         (head)->last = (elm);                           \
2477 } while (0)
2478
2479 #define AST_RWLIST_INSERT_HEAD AST_LIST_INSERT_HEAD
2480
2481 /*!
2482   \brief Appends a list entry to the tail of a list.
2483   \param head This is a pointer to the list head structure
2484   \param elm This is a pointer to the entry to be appended.
2485   \param field This is the name of the field (declared using AST_LIST_ENTRY())
2486   used to link entries of this list together.
2487
2488   Note: The link field in the appended entry is \b not modified, so if it is
2489   actually the head of a list itself, the entire list will be appended
2490   temporarily (until the next AST_LIST_INSERT_TAIL is performed).
2491  */
2492 #define AST_LIST_INSERT_TAIL(head, elm, field) do {                     \
2493       if (!(head)->first) {                                             \
2494                 (head)->first = (elm);                                  \
2495                 (head)->last = (elm);                                   \
2496       } else {                                                          \
2497                 (head)->last->field.next = (elm);                       \
2498                 (head)->last = (elm);                                   \
2499       }                                                                 \
2500 } while (0)
2501
2502 #define AST_RWLIST_INSERT_TAIL AST_LIST_INSERT_TAIL
2503
2504 /*!
2505   \brief Appends a whole list to the tail of a list.
2506   \param head This is a pointer to the list head structure
2507   \param list This is a pointer to the list to be appended.
2508   \param field This is the name of the field (declared using AST_LIST_ENTRY())
2509   used to link entries of this list together.
2510  */
2511 #define AST_LIST_APPEND_LIST(head, list, field) do {                    \
2512       if (!(head)->first) {                                             \
2513                 (head)->first = (list)->first;                          \
2514                 (head)->last = (list)->last;                            \
2515       } else {                                                          \
2516                 (head)->last->field.next = (list)->first;               \
2517                 (head)->last = (list)->last;                            \
2518       }                                                                 \
2519 } while (0)
2520
2521 #define AST_RWLIST_APPEND_LIST AST_LIST_APPEND_LIST
2522
2523 /*!
2524   \brief Removes and returns the head entry from a list.
2525   \param head This is a pointer to the list head structure
2526   \param field This is the name of the field (declared using AST_LIST_ENTRY())
2527   used to link entries of this list together.
2528
2529   Removes the head entry from the list, and returns a pointer to it.
2530   This macro is safe to call on an empty list.
2531  */
2532 #define AST_LIST_REMOVE_HEAD(head, field) ({                            \
2533                 typeof((head)->first) cur = (head)->first;              \
2534                 if (cur) {                                              \
2535                         (head)->first = cur->field.next;                \
2536                         cur->field.next = NULL;                         \
2537                         if ((head)->last == cur)                        \
2538                                 (head)->last = NULL;                    \
2539                 }                                                       \
2540                 cur;                                                    \
2541         })
2542
2543 #define AST_RWLIST_REMOVE_HEAD AST_LIST_REMOVE_HEAD
2544
2545 /*!
2546   \brief Removes a specific entry from a list.
2547   \param head This is a pointer to the list head structure
2548   \param elm This is a pointer to the entry to be removed.
2549   \param field This is the name of the field (declared using AST_LIST_ENTRY())
2550   used to link entries of this list together.
2551   \warning The removed entry is \b not freed nor modified in any way.
2552  */
2553 #define AST_LIST_REMOVE(head, elm, field) do {                          \
2554         if ((head)->first == (elm)) {                                   \
2555                 (head)->first = (elm)->field.next;                      \
2556                 if ((head)->last == (elm))                      \
2557                         (head)->last = NULL;                    \
2558         } else {                                                                \
2559                 typeof(elm) curelm = (head)->first;                     \
2560                 while (curelm && (curelm->field.next != (elm)))                 \
2561                         curelm = curelm->field.next;                    \
2562                 if (curelm) { \
2563                         curelm->field.next = (elm)->field.next;                 \
2564                         if ((head)->last == (elm))                              \
2565                                 (head)->last = curelm;                          \
2566                 } \
2567         }                                                               \
2568         (elm)->field.next = NULL;                                       \
2569 } while (0)
2570
2571 #define AST_RWLIST_REMOVE AST_LIST_REMOVE
2572
2573 /* chanvars.h */
2574
2575 struct ast_var_t {
2576         AST_LIST_ENTRY(ast_var_t) entries;
2577         char *value;
2578         char name[0];
2579 };
2580
2581 AST_LIST_HEAD_NOLOCK(varshead, ast_var_t);
2582
2583 AST_RWLOCK_DEFINE_STATIC(globalslock);
2584 static struct varshead globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
2585
2586
2587 /* IN CONFLICT: struct ast_var_t *ast_var_assign(const char *name, const char *value); */
2588
2589 static struct ast_var_t *ast_var_assign(const char *name, const char *value);
2590
2591 static void ast_var_delete(struct ast_var_t *var);
2592
2593 /*from channel.h */
2594 #define AST_MAX_EXTENSION  80      /*!< Max length of an extension */
2595
2596
2597 /* from pbx.h */
2598 #define PRIORITY_HINT   -1      /*!< Special Priority for a hint */
2599
2600 enum ast_extension_states {
2601         AST_EXTENSION_REMOVED = -2,     /*!< Extension removed */
2602         AST_EXTENSION_DEACTIVATED = -1, /*!< Extension hint removed */
2603         AST_EXTENSION_NOT_INUSE = 0,    /*!< No device INUSE or BUSY  */
2604         AST_EXTENSION_INUSE = 1 << 0,   /*!< One or more devices INUSE */
2605         AST_EXTENSION_BUSY = 1 << 1,    /*!< All devices BUSY */
2606         AST_EXTENSION_UNAVAILABLE = 1 << 2, /*!< All devices UNAVAILABLE/UNREGISTERED */
2607         AST_EXTENSION_RINGING = 1 << 3, /*!< All devices RINGING */
2608         AST_EXTENSION_ONHOLD = 1 << 4,  /*!< All devices ONHOLD */
2609 };
2610
2611 struct ast_custom_function {
2612         const char *name;               /*!< Name */
2613         const char *synopsis;           /*!< Short description for "show functions" */
2614         const char *desc;               /*!< Help text that explains it all */
2615         const char *syntax;             /*!< Syntax description */
2616         int (*read)(struct ast_channel *, const char *, char *, char *, size_t);        /*!< Read function, if read is supported */
2617         int (*write)(struct ast_channel *, const char *, char *, const char *);         /*!< Write function, if write is supported */
2618         AST_RWLIST_ENTRY(ast_custom_function) acflist;
2619 };
2620
2621 typedef int (ast_switch_f)(struct ast_channel *chan, const char *context,
2622         const char *exten, int priority, const char *callerid, const char *data);
2623
2624 struct ast_switch {
2625         AST_LIST_ENTRY(ast_switch) list;
2626         const char *name;                       /*!< Name of the switch */
2627         const char *description;                /*!< Description of the switch */
2628         
2629         ast_switch_f *exists;
2630         ast_switch_f *canmatch;
2631         ast_switch_f *exec;
2632         ast_switch_f *matchmore;
2633 };
2634
2635
2636 static char *config = "extensions.conf";
2637 static char *registrar = "conf2ael";
2638 static char userscontext[AST_MAX_EXTENSION] = "default";
2639 static int static_config = 0;
2640 static int write_protect_config = 1;
2641 static int autofallthrough_config = 0;
2642 static int clearglobalvars_config = 0;
2643 /*! Go no deeper than this through includes (not counting loops) */
2644 #define AST_PBX_MAX_STACK       128
2645 static void pbx_substitute_variables_helper(struct ast_channel *c,const char *cp1,char *cp2,int count);
2646
2647
2648 /* stolen from callerid.c */
2649
2650 /*! \brief Clean up phone string
2651  * remove '(', ' ', ')', non-trailing '.', and '-' not in square brackets.
2652  * Basically, remove anything that could be invalid in a pattern.
2653  */
2654 static void ast_shrink_phone_number(char *n)
2655 {
2656         int x, y=0;
2657         int bracketed = 0;
2658
2659         for (x=0; n[x]; x++) {
2660                 switch(n[x]) {
2661                 case '[':
2662                         bracketed++;
2663                         n[y++] = n[x];
2664                         break;
2665                 case ']':
2666                         bracketed--;
2667                         n[y++] = n[x];
2668                         break;
2669                 case '-':
2670                         if (bracketed)
2671                                 n[y++] = n[x];
2672                         break;
2673                 case '.':
2674                         if (!n[x+1])
2675                                 n[y++] = n[x];
2676                         break;
2677                 default:
2678                         if (!strchr("()", n[x]))
2679                                 n[y++] = n[x];
2680                 }
2681         }
2682         n[y] = '\0';
2683 }
2684
2685
2686 /* stolen from chanvars.c */
2687
2688 static const char *ast_var_name(const struct ast_var_t *var)
2689 {
2690         const char *name;
2691
2692         if (var == NULL || (name = var->name) == NULL)
2693                 return NULL;
2694         /* Return the name without the initial underscores */
2695         if (name[0] == '_') {
2696                 name++;
2697                 if (name[0] == '_')
2698                         name++;
2699         }
2700         return name;
2701 }
2702
2703
2704 /* stolen from asterisk.c */
2705
2706 static struct ast_flags ast_options = { AST_DEFAULT_OPTIONS };
2707 static int option_verbose = 0;                         /*!< Verbosity level */
2708 static int option_debug = 0;                           /*!< Debug level */
2709
2710
2711 /* experiment 1: see if it's easier just to use existing config code
2712  *               to read in the extensions.conf file. In this scenario, 
2713                  I have to rip/copy code from other modules, because they
2714                  are staticly declared as-is. A solution would be to move
2715                  the ripped code to another location and make them available
2716                  to other modules and standalones */
2717
2718 /* Our own version of ast_log, since the expr parser uses it. -- stolen from utils/check_expr.c */
2719
2720 static void ast_log(int level, const char *file, int line, const char *function, const char *fmt, ...)
2721 {
2722         va_list vars;
2723         va_start(vars,fmt);
2724         
2725         printf("LOG: lev:%d file:%s  line:%d func: %s  ",
2726                    level, file, line, function);
2727         vprintf(fmt, vars);
2728         fflush(stdout);
2729         va_end(vars);
2730 }
2731
2732 static void ast_verbose(const char *fmt, ...)
2733 {
2734         va_list vars;
2735         va_start(vars,fmt);
2736         
2737         printf("VERBOSE: ");
2738         vprintf(fmt, vars);
2739         fflush(stdout);
2740         va_end(vars);
2741 }
2742
2743 /* stolen from main/utils.c */
2744 static char *ast_process_quotes_and_slashes(char *start, char find, char replace_with)
2745 {
2746         char *dataPut = start;
2747         int inEscape = 0;
2748         int inQuotes = 0;
2749
2750         for (; *start; start++) {
2751                 if (inEscape) {
2752                         *dataPut++ = *start;       /* Always goes verbatim */
2753                         inEscape = 0;
2754                 } else {
2755                         if (*start == '\\') {
2756                                 inEscape = 1;      /* Do not copy \ into the data */
2757                         } else if (*start == '\'') {
2758                                 inQuotes = 1 - inQuotes;   /* Do not copy ' into the data */
2759                         } else {
2760                                 /* Replace , with |, unless in quotes */
2761                                 *dataPut++ = inQuotes ? *start : ((*start == find) ? replace_with : *start);
2762                         }
2763                 }
2764         }
2765         if (start != dataPut)
2766                 *dataPut = 0;
2767         return dataPut;
2768 }
2769
2770 static int ast_true(const char *s)
2771 {
2772         if (ast_strlen_zero(s))
2773                 return 0;
2774
2775         /* Determine if this is a true value */
2776         if (!strcasecmp(s, "yes") ||
2777             !strcasecmp(s, "true") ||
2778             !strcasecmp(s, "y") ||
2779             !strcasecmp(s, "t") ||
2780             !strcasecmp(s, "1") ||
2781             !strcasecmp(s, "on"))
2782                 return -1;
2783
2784         return 0;
2785 }
2786
2787 /* stolen from pbx.c */
2788 #define VAR_BUF_SIZE 4096
2789
2790 #define VAR_NORMAL              1
2791 #define VAR_SOFTTRAN    2
2792 #define VAR_HARDTRAN    3
2793
2794 #define BACKGROUND_SKIP         (1 << 0)
2795 #define BACKGROUND_NOANSWER     (1 << 1)
2796 #define BACKGROUND_MATCHEXTEN   (1 << 2)
2797 #define BACKGROUND_PLAYBACK     (1 << 3)
2798
2799 /*!
2800    \brief ast_exten: An extension
2801         The dialplan is saved as a linked list with each context
2802         having it's own linked list of extensions - one item per
2803         priority.
2804 */
2805 struct ast_exten {
2806         char *exten;                    /*!< Extension name */
2807         int matchcid;                   /*!< Match caller id ? */
2808         const char *cidmatch;           /*!< Caller id to match for this extension */
2809         int priority;                   /*!< Priority */
2810         const char *label;              /*!< Label */
2811         struct ast_context *parent;     /*!< The context this extension belongs to  */
2812         const char *app;                /*!< Application to execute */
2813         struct ast_app *cached_app;     /*!< Cached location of application */
2814         void *data;                     /*!< Data to use (arguments) */
2815         void (*datad)(void *);          /*!< Data destructor */
2816         struct ast_exten *peer;         /*!< Next higher priority with our extension */
2817         const char *registrar;          /*!< Registrar */
2818         struct ast_exten *next;         /*!< Extension with a greater ID */
2819         char stuff[0];
2820 };
2821 /* from pbx.h */
2822 typedef int (*ast_state_cb_type)(char *context, char* id, enum ast_extension_states state, void *data);
2823 struct ast_timing {
2824         int hastime;                            /*!< If time construct exists */
2825         unsigned int monthmask;                 /*!< Mask for month */
2826         unsigned int daymask;                   /*!< Mask for date */
2827         unsigned int dowmask;                   /*!< Mask for day of week (mon-sun) */
2828         unsigned int minmask[24];               /*!< Mask for minute */
2829 };
2830 /* end of pbx.h */
2831 /*! \brief ast_include: include= support in extensions.conf */
2832 struct ast_include {
2833         const char *name;
2834         const char *rname;                      /*!< Context to include */
2835         const char *registrar;                  /*!< Registrar */
2836         int hastime;                            /*!< If time construct exists */
2837         struct ast_timing timing;               /*!< time construct */
2838         struct ast_include *next;               /*!< Link them together */
2839         char stuff[0];
2840 };
2841
2842 /*! \brief ast_sw: Switch statement in extensions.conf */
2843 struct ast_sw {
2844         char *name;
2845         const char *registrar;                  /*!< Registrar */
2846         char *data;                             /*!< Data load */
2847         int eval;
2848         AST_LIST_ENTRY(ast_sw) list;
2849         char *tmpdata;
2850         char stuff[0];
2851 };
2852
2853 /*! \brief ast_ignorepat: Ignore patterns in dial plan */
2854 struct ast_ignorepat {
2855         const char *registrar;
2856         struct ast_ignorepat *next;
2857         const char pattern[0];
2858 };
2859
2860 /*! \brief ast_context: An extension context */
2861 struct ast_context {
2862         ast_rwlock_t lock;                      /*!< A lock to prevent multiple threads from clobbering the context */
2863         struct ast_exten *root;                 /*!< The root of the list of extensions */
2864         struct ast_context *next;               /*!< Link them together */
2865         struct ast_include *includes;           /*!< Include other contexts */
2866         struct ast_ignorepat *ignorepats;       /*!< Patterns for which to continue playing dialtone */
2867         const char *registrar;                  /*!< Registrar */
2868         AST_LIST_HEAD_NOLOCK(, ast_sw) alts;    /*!< Alternative switches */
2869         ast_mutex_t macrolock;                  /*!< A lock to implement "exclusive" macros - held whilst a call is executing in the macro */
2870         char name[0];                           /*!< Name of the context */
2871 };
2872
2873
2874 /*! \brief ast_app: A registered application */
2875 struct ast_app {
2876         int (*execute)(struct ast_channel *chan, void *data);
2877         const char *synopsis;                   /*!< Synopsis text for 'show applications' */
2878         const char *description;                /*!< Description (help text) for 'show application &lt;name&gt;' */
2879         AST_RWLIST_ENTRY(ast_app) list;         /*!< Next app in list */
2880         void *module;                   /*!< Module this app belongs to */
2881         char name[0];                           /*!< Name of the application */
2882 };
2883
2884
2885 /*! \brief ast_state_cb: An extension state notify register item */
2886 struct ast_state_cb {
2887         int id;
2888         void *data;
2889         ast_state_cb_type callback;
2890         struct ast_state_cb *next;
2891 };
2892
2893 /*! \brief Structure for dial plan hints
2894
2895   \note Hints are pointers from an extension in the dialplan to one or
2896   more devices (tech/name) 
2897         - See \ref AstExtState
2898 */
2899 struct ast_hint {
2900         struct ast_exten *exten;        /*!< Extension */
2901         int laststate;                  /*!< Last known state */
2902         struct ast_state_cb *callbacks; /*!< Callback list for this extension */
2903         AST_RWLIST_ENTRY(ast_hint) list;/*!< Pointer to next hint in list */
2904 };
2905
2906 struct store_hint {
2907         char *context;
2908         char *exten;
2909         struct ast_state_cb *callbacks;
2910         int laststate;
2911         AST_LIST_ENTRY(store_hint) list;
2912         char data[1];
2913 };
2914
2915 AST_LIST_HEAD(store_hints, store_hint);
2916
2917 static const struct cfextension_states {
2918         int extension_state;
2919         const char * const text;
2920 } extension_states[] = {
2921         { AST_EXTENSION_NOT_INUSE,                     "Idle" },
2922         { AST_EXTENSION_INUSE,                         "InUse" },
2923         { AST_EXTENSION_BUSY,                          "Busy" },
2924         { AST_EXTENSION_UNAVAILABLE,                   "Unavailable" },
2925         { AST_EXTENSION_RINGING,                       "Ringing" },
2926         { AST_EXTENSION_INUSE | AST_EXTENSION_RINGING, "InUse&Ringing" },
2927         { AST_EXTENSION_ONHOLD,                        "Hold" },
2928         { AST_EXTENSION_INUSE | AST_EXTENSION_ONHOLD,  "InUse&Hold" }
2929 };
2930 #define STATUS_NO_CONTEXT       1
2931 #define STATUS_NO_EXTENSION     2
2932 #define STATUS_NO_PRIORITY      3
2933 #define STATUS_NO_LABEL         4
2934 #define STATUS_SUCCESS          5
2935
2936
2937 #if defined ( __i386__) && (defined(__FreeBSD__) || defined(linux))
2938 #if defined(__FreeBSD__)
2939 #include <machine/cpufunc.h>
2940 #elif defined(linux)
2941 static __inline uint64_t
2942 rdtsc(void)
2943
2944         uint64_t rv;
2945
2946         __asm __volatile(".byte 0x0f, 0x31" : "=A" (rv));
2947         return (rv);
2948 }
2949 #endif
2950 #else   /* supply a dummy function on other platforms */
2951 static __inline uint64_t
2952 rdtsc(void)
2953 {
2954         return 0;
2955 }
2956 #endif
2957
2958
2959 static struct ast_var_t *ast_var_assign(const char *name, const char *value)
2960 {       
2961         struct ast_var_t *var;
2962         int name_len = strlen(name) + 1;
2963         int value_len = strlen(value) + 1;
2964
2965         if (!(var = ast_calloc(sizeof(*var) + name_len + value_len, sizeof(char)))) {
2966                 return NULL;
2967         }
2968
2969         ast_copy_string(var->name, name, name_len);
2970         var->value = var->name + name_len;
2971         ast_copy_string(var->value, value, value_len);
2972         
2973         return var;
2974 }       
2975         
2976 static void ast_var_delete(struct ast_var_t *var)
2977 {
2978         if (var)
2979                 free(var);
2980 }
2981
2982
2983 /* chopped this one off at the knees! */
2984 static int ast_func_write(struct ast_channel *chan, const char *function, const char *value)
2985 {
2986
2987         /* ast_log(LOG_ERROR, "Function %s not registered\n", function); we are not interested in the details here */
2988
2989         return -1;
2990 }
2991
2992 static unsigned int ast_app_separate_args(char *buf, char delim, char **array, int arraylen)
2993 {
2994         int argc;
2995         char *scan;
2996         int paren = 0, quote = 0;
2997
2998         if (!buf || !array || !arraylen)
2999                 return 0;
3000
3001         memset(array, 0, arraylen * sizeof(*array));
3002
3003         scan = buf;
3004
3005         for (argc = 0; *scan && (argc < arraylen - 1); argc++) {
3006                 array[argc] = scan;
3007                 for (; *scan; scan++) {
3008                         if (*scan == '(')
3009                                 paren++;
3010                         else if (*scan == ')') {
3011                                 if (paren)
3012                                         paren--;
3013                         } else if (*scan == '"' && delim != '"') {
3014                                 quote = quote ? 0 : 1;
3015                                 /* Remove quote character from argument */
3016                                 memmove(scan, scan + 1, strlen(scan));
3017                                 scan--;
3018                         } else if (*scan == '\\') {
3019                                 /* Literal character, don't parse */
3020                                 memmove(scan, scan + 1, strlen(scan));
3021                         } else if ((*scan == delim) && !paren && !quote) {
3022                                 *scan++ = '\0';
3023                                 break;
3024                         }
3025                 }
3026         }
3027
3028         if (*scan)
3029                 array[argc++] = scan;
3030
3031         return argc;
3032 }
3033
3034 static void pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
3035 {
3036         struct ast_var_t *newvariable;
3037         struct varshead *headp;
3038         const char *nametail = name;
3039
3040         /* XXX may need locking on the channel ? */
3041         if (name[strlen(name)-1] == ')') {
3042                 char *function = ast_strdupa(name);
3043
3044                 ast_func_write(chan, function, value);
3045                 return;
3046         }
3047
3048         headp = &globals;
3049
3050         /* For comparison purposes, we have to strip leading underscores */
3051         if (*nametail == '_') {
3052                 nametail++;
3053                 if (*nametail == '_')
3054                         nametail++;
3055         }
3056
3057         AST_LIST_TRAVERSE (headp, newvariable, entries) {
3058                 if (strcasecmp(ast_var_name(newvariable), nametail) == 0) {
3059                         /* there is already such a variable, delete it */
3060                         AST_LIST_REMOVE(headp, newvariable, entries);
3061                         ast_var_delete(newvariable);
3062                         break;
3063                 }
3064         }
3065
3066         if (value) {
3067                 if ((option_verbose > 1) && (headp == &globals))
3068                         ast_verbose(VERBOSE_PREFIX_2 "Setting global variable '%s' to '%s'\n", name, value);
3069                 newvariable = ast_var_assign(name, value);
3070                 AST_LIST_INSERT_HEAD(headp, newvariable, entries);
3071         }
3072
3073 }
3074
3075 static int pbx_builtin_setvar(struct ast_channel *chan, void *data)
3076 {
3077         char *name, *value, *mydata;
3078         int argc;
3079         char *argv[24];         /* this will only support a maximum of 24 variables being set in a single operation */
3080         int global = 0;
3081         int x;
3082
3083         if (ast_strlen_zero(data)) {
3084                 ast_log(LOG_WARNING, "Set requires at least one variable name/value pair.\n");
3085                 return 0;
3086         }
3087
3088         mydata = ast_strdupa(data);
3089         argc = ast_app_separate_args(mydata, '|', argv, sizeof(argv) / sizeof(argv[0]));
3090
3091         /* check for a trailing flags argument */
3092         if ((argc > 1) && !strchr(argv[argc-1], '=')) {
3093                 argc--;
3094                 if (strchr(argv[argc], 'g'))
3095                         global = 1;
3096         }
3097
3098         for (x = 0; x < argc; x++) {
3099                 name = argv[x];
3100                 if ((value = strchr(name, '='))) {
3101                         *value++ = '\0';
3102                         pbx_builtin_setvar_helper((global) ? NULL : chan, name, value);
3103                 } else
3104                         ast_log(LOG_WARNING, "Ignoring entry '%s' with no = (and not last 'options' entry)\n", name);
3105         }
3106
3107         return(0);
3108 }
3109
3110 int localized_pbx_builtin_setvar(struct ast_channel *chan, void *data);
3111
3112 int localized_pbx_builtin_setvar(struct ast_channel *chan, void *data)
3113 {
3114         return pbx_builtin_setvar(chan, data);
3115 }
3116
3117
3118 /*! \brief Helper for get_range.
3119  * return the index of the matching entry, starting from 1.
3120  * If names is not supplied, try numeric values.
3121  */
3122
3123 static int lookup_name(const char *s, char *const names[], int max)
3124 {
3125         int i;
3126
3127         if (names) {
3128                 for (i = 0; names[i]; i++) {
3129                         if (!strcasecmp(s, names[i]))
3130                                 return i+1;
3131                 }
3132         } else if (sscanf(s, "%d", &i) == 1 && i >= 1 && i <= max) {
3133                 return i;
3134         }
3135         return 0; /* error return */
3136 }
3137
3138 /*! \brief helper function to return a range up to max (7, 12, 31 respectively).
3139  * names, if supplied, is an array of names that should be mapped to numbers.
3140  */
3141 static unsigned get_range(char *src, int max, char *const names[], const char *msg)
3142 {
3143         int s, e; /* start and ending position */
3144         unsigned int mask = 0;
3145
3146         /* Check for whole range */
3147         if (ast_strlen_zero(src) || !strcmp(src, "*")) {
3148                 s = 0;
3149                 e = max - 1;
3150         } else {
3151                 /* Get start and ending position */
3152                 char *c = strchr(src, '-');
3153                 if (c)
3154                         *c++ = '\0';
3155                 /* Find the start */
3156                 s = lookup_name(src, names, max);
3157                 if (!s) {
3158                         ast_log(LOG_WARNING, "Invalid %s '%s', assuming none\n", msg, src);
3159                         return 0;
3160                 }
3161                 s--;
3162                 if (c) { /* find end of range */
3163                         e = lookup_name(c, names, max);
3164                         if (!e) {
3165                                 ast_log(LOG_WARNING, "Invalid end %s '%s', assuming none\n", msg, c);
3166                                 return 0;
3167                         }
3168                         e--;
3169                 } else
3170                         e = s;
3171         }
3172         /* Fill the mask. Remember that ranges are cyclic */
3173         mask = 1 << e;  /* initialize with last element */
3174         while (s != e) {
3175                 if (s >= max) {
3176                         s = 0;
3177                         mask |= (1 << s);
3178                 } else {
3179                         mask |= (1 << s);
3180                         s++;
3181                 }
3182         }
3183         return mask;
3184 }
3185
3186 /*! \brief store a bitmask of valid times, one bit each 2 minute */
3187 static void get_timerange(struct ast_timing *i, char *times)
3188 {
3189         char *e;
3190         int x;
3191         int s1, s2;
3192         int e1, e2;
3193         /*      int cth, ctm; */
3194
3195         /* start disabling all times, fill the fields with 0's, as they may contain garbage */
3196         memset(i->minmask, 0, sizeof(i->minmask));
3197
3198         /* 2-minutes per bit, since the mask has only 32 bits :( */
3199         /* Star is all times */
3200         if (ast_strlen_zero(times) || !strcmp(times, "*")) {
3201                 for (x=0; x<24; x++)
3202                         i->minmask[x] = 0x3fffffff; /* 30 bits */
3203                 return;
3204         }
3205         /* Otherwise expect a range */
3206         e = strchr(times, '-');
3207         if (!e) {
3208                 ast_log(LOG_WARNING, "Time range is not valid. Assuming no restrictions based on time.\n");
3209                 return;
3210         }
3211         *e++ = '\0';
3212         /* XXX why skip non digits ? */
3213         while (*e && !isdigit(*e))
3214                 e++;
3215         if (!*e) {
3216                 ast_log(LOG_WARNING, "Invalid time range.  Assuming no restrictions based on time.\n");
3217                 return;
3218         }
3219         if (sscanf(times, "%d:%d", &s1, &s2) != 2) {
3220                 ast_log(LOG_WARNING, "%s isn't a time.  Assuming no restrictions based on time.\n", times);
3221                 return;
3222         }
3223         if (sscanf(e, "%d:%d", &e1, &e2) != 2) {
3224                 ast_log(LOG_WARNING, "%s isn't a time.  Assuming no restrictions based on time.\n", e);
3225                 return;
3226         }
3227         /* XXX this needs to be optimized */
3228 #if 1
3229         s1 = s1 * 30 + s2/2;
3230         if ((s1 < 0) || (s1 >= 24*30)) {
3231                 ast_log(LOG_WARNING, "%s isn't a valid start time. Assuming no time.\n", times);
3232                 return;
3233         }
3234         e1 = e1 * 30 + e2/2;
3235         if ((e1 < 0) || (e1 >= 24*30)) {
3236                 ast_log(LOG_WARNING, "%s isn't a valid end time. Assuming no time.\n", e);
3237                 return;
3238         }
3239         /* Go through the time and enable each appropriate bit */
3240         for (x=s1;x != e1;x = (x + 1) % (24 * 30)) {
3241                 i->minmask[x/30] |= (1 << (x % 30));
3242         }
3243         /* Do the last one */
3244         i->minmask[x/30] |= (1 << (x % 30));
3245 #else
3246         for (cth=0; cth<24; cth++) {
3247                 /* Initialize masks to blank */
3248                 i->minmask[cth] = 0;
3249                 for (ctm=0; ctm<30; ctm++) {
3250                         if (
3251                         /* First hour with more than one hour */
3252                               (((cth == s1) && (ctm >= s2)) &&
3253                                ((cth < e1)))
3254                         /* Only one hour */
3255                         ||    (((cth == s1) && (ctm >= s2)) &&
3256                                ((cth == e1) && (ctm <= e2)))
3257                         /* In between first and last hours (more than 2 hours) */
3258                         ||    ((cth > s1) &&
3259                                (cth < e1))
3260                         /* Last hour with more than one hour */
3261                         ||    ((cth > s1) &&
3262                                ((cth == e1) && (ctm <= e2)))
3263                         )
3264                                 i->minmask[cth] |= (1 << (ctm / 2));
3265                 }
3266         }
3267 #endif
3268         /* All done */
3269         return;
3270 }
3271
3272 static void null_datad(void *foo)
3273 {
3274 }
3275
3276 /*! \brief Find realtime engine for realtime family */
3277 static struct ast_config_engine *find_engine(const char *family, char *database, int dbsiz, char *table, int tabsiz) 
3278 {
3279         struct ast_config_engine *eng, *ret = NULL;
3280         struct ast_config_map *map;
3281
3282
3283         for (map = config_maps; map; map = map->next) {
3284                 if (!strcasecmp(family, map->name)) {
3285                         if (database)
3286                                 ast_copy_string(database, map->database, dbsiz);
3287                         if (table)
3288                                 ast_copy_string(table, map->table ? map->table : family, tabsiz);
3289                         break;
3290                 }
3291         }
3292
3293         /* Check if the required driver (engine) exist */
3294         if (map) {
3295                 for (eng = config_engine_list; !ret && eng; eng = eng->next) {
3296                         if (!strcasecmp(eng->name, map->driver))
3297                                 ret = eng;
3298                 }
3299         }
3300         
3301         
3302         /* if we found a mapping, but the engine is not available, then issue a warning */
3303         if (map && !ret)
3304                 ast_log(LOG_WARNING, "Realtime mapping for '%s' found to engine '%s', but the engine is not available\n", map->name, map->driver);
3305         
3306         return ret;
3307 }
3308
3309 struct ast_category *ast_config_get_current_category(const struct ast_config *cfg);
3310
3311 struct ast_category *ast_config_get_current_category(const struct ast_config *cfg)
3312 {
3313         return cfg->current;
3314 }
3315
3316 static struct ast_category *ast_category_new(const char *name, const char *in_file, int lineno);
3317
3318 static struct ast_category *ast_category_new(const char *name, const char *in_file, int lineno)
3319 {
3320         struct ast_category *category;
3321
3322         if ((category = ast_calloc(1, sizeof(*category))))
3323                 ast_copy_string(category->name, name, sizeof(category->name));
3324         category->file = strdup(in_file);
3325         category->lineno = lineno; /* if you don't know the lineno, set it to 999999 or something real big */
3326         return category;
3327 }
3328
3329 struct ast_category *localized_category_get(const struct ast_config *config, const char *category_name);
3330
3331 struct ast_category *localized_category_get(const struct ast_config *config, const char *category_name)
3332 {
3333         return category_get(config, category_name, 0);
3334 }
3335
3336 static void move_variables(struct ast_category *old, struct ast_category *new)
3337 {
3338         struct ast_variable *var = old->root;
3339         old->root = NULL;
3340 #if 1
3341         /* we can just move the entire list in a single op */
3342         ast_variable_append(new, var);
3343 #else
3344         while (var) {
3345                 struct ast_variable *next = var->next;
3346                 var->next = NULL;
3347                 ast_variable_append(new, var);
3348                 var = next;
3349         }
3350 #endif
3351 }
3352
3353 static void inherit_category(struct ast_category *new, const struct ast_category *base)
3354 {
3355         struct ast_variable *var;
3356
3357         for (var = base->root; var; var = var->next)
3358                 ast_variable_append(new, variable_clone(var));
3359 }
3360
3361 static void ast_category_append(struct ast_config *config, struct ast_category *category);
3362
3363 static void ast_category_append(struct ast_config *config, struct ast_category *category)
3364 {
3365         if (config->last)
3366                 config->last->next = category;
3367         else
3368                 config->root = category;
3369         config->last = category;
3370         config->current = category;
3371 }
3372
3373 static void ast_category_destroy(struct ast_category *cat);
3374
3375 static void ast_category_destroy(struct ast_category *cat)
3376 {
3377         ast_variables_destroy(cat->root);
3378         if (cat->file)
3379                 free(cat->file);
3380         
3381         free(cat);
3382 }
3383
3384 static struct ast_config_engine text_file_engine = {
3385         .name = "text",
3386         .load_func = config_text_file_load,
3387 };
3388
3389
3390 static struct ast_config *ast_config_internal_load(const char *filename, struct ast_config *cfg, int withcomments, const char *suggested_incl_file);
3391
3392 static struct ast_config *ast_config_internal_load(const char *filename, struct ast_config *cfg, int withcomments, const char *suggested_incl_file)
3393 {
3394         char db[256];
3395         char table[256];
3396         struct ast_config_engine *loader = &text_file_engine;
3397         struct ast_config *result; 
3398
3399         if (cfg->include_level == cfg->max_include_level) {
3400                 ast_log(LOG_WARNING, "Maximum Include level (%d) exceeded\n", cfg->max_include_level);
3401                 return NULL;
3402         }
3403
3404         cfg->include_level++;
3405         /*  silence is golden!
3406                 ast_log(LOG_WARNING, "internal loading file %s level=%d\n", filename, cfg->include_level);
3407         */
3408
3409         if (strcmp(filename, extconfig_conf) && strcmp(filename, "asterisk.conf") && config_engine_list) {
3410                 struct ast_config_engine *eng;
3411
3412                 eng = find_engine(filename, db, sizeof(db), table, sizeof(table));
3413
3414
3415                 if (eng && eng->load_func) {
3416                         loader = eng;
3417                 } else {
3418                         eng = find_engine("global", db, sizeof(db), table, sizeof(table));
3419                         if (eng && eng->load_func)
3420                                 loader = eng;
3421                 }
3422         }
3423
3424         result = loader->load_func(db, table, filename, cfg, withcomments, suggested_incl_file);
3425         /* silence is golden 
3426            ast_log(LOG_WARNING, "finished internal loading file %s level=%d\n", filename, cfg->include_level);
3427         */
3428
3429         if (result)
3430                 result->include_level--;
3431
3432         return result;
3433 }
3434
3435
3436 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)
3437 {
3438         char *c;
3439         char *cur = buf;
3440         struct ast_variable *v;
3441         char cmd[512], exec_file[512];
3442         int object, do_exec, do_include;
3443
3444         /* Actually parse the entry */
3445         if (cur[0] == '[') {
3446                 struct ast_category *newcat = NULL;
3447                 char *catname;
3448
3449                 /* A category header */
3450                 c = strchr(cur, ']');
3451                 if (!c) {
3452                         ast_log(LOG_WARNING, "parse error: no closing ']', line %d of %s\n", lineno, configfile);
3453                         return -1;
3454                 }
3455                 *c++ = '\0';
3456                 cur++;
3457                 if (*c++ != '(')
3458                         c = NULL;
3459                 catname = cur;
3460                 if (!(*cat = newcat = ast_category_new(catname, ast_strlen_zero(suggested_include_file)?configfile:suggested_include_file, lineno))) {
3461                         return -1;
3462                 }
3463                 (*cat)->lineno = lineno;
3464         
3465                 /* add comments */
3466                 if (withcomments && comment_buffer && comment_buffer[0] ) {
3467                         newcat->precomments = ALLOC_COMMENT(comment_buffer);
3468                 }
3469                 if (withcomments && lline_buffer && lline_buffer[0] ) {
3470                         newcat->sameline = ALLOC_COMMENT(lline_buffer);
3471                 }
3472                 if( withcomments )
3473                         CB_RESET();
3474                 
3475                 /* If there are options or categories to inherit from, process them now */
3476                 if (c) {
3477                         if (!(cur = strchr(c, ')'))) {
3478                                 ast_log(LOG_WARNING, "parse error: no closing ')', line %d of %s\n", lineno, configfile);
3479                                 return -1;
3480                         }
3481                         *cur = '\0';
3482                         while ((cur = strsep(&c, ","))) {
3483                                 if (!strcasecmp(cur, "!")) {
3484                                         (*cat)->ignored = 1;
3485                                 } else if (!strcasecmp(cur, "+")) {
3486                                         *cat = category_get(cfg, catname, 1);
3487                                         if (!*cat) {
3488                                                 ast_config_destroy(cfg);
3489                                                 if (newcat)
3490                                                         ast_category_destroy(newcat);
3491                                                 ast_log(LOG_WARNING, "Category addition requested, but category '%s' does not exist, line %d of %s\n", catname, lineno, configfile);
3492                                                 return -1;
3493                                         }
3494                                         if (newcat) {
3495                                                 move_variables(newcat, *cat);
3496                                                 ast_category_destroy(newcat);
3497                                                 newcat = NULL;
3498                                         }
3499                                 } else {
3500                                         struct ast_category *base;
3501                                 
3502                                         base = category_get(cfg, cur, 1);
3503                                         if (!base) {
3504                                                 ast_log(LOG_WARNING, "Inheritance requested, but category '%s' does not exist, line %d of %s\n", cur, lineno, configfile);
3505                                                 return -1;
3506                                         }
3507                                         inherit_category(*cat, base);
3508                                 }
3509                         }
3510                 }
3511                 if (newcat)
3512                         ast_category_append(cfg, *cat);
3513         } else if (cur[0] == '#') {
3514                 /* A directive */
3515                 cur++;
3516                 c = cur;
3517                 while(*c && (*c > 32)) c++;
3518                 if (*c) {
3519                         *c = '\0';
3520                         /* Find real argument */
3521                         c = ast_skip_blanks(c + 1);
3522                         if (!*c)
3523                                 c = NULL;
3524                 } else 
3525                         c = NULL;
3526                 do_include = !strcasecmp(cur, "include");
3527                 if(!do_include)
3528                         do_exec = !strcasecmp(cur, "exec");
3529                 else
3530                         do_exec = 0;
3531                 if (do_exec && !ast_opt_exec_includes) {
3532                         ast_log(LOG_WARNING, "Cannot perform #exec unless execincludes option is enabled in asterisk.conf (options section)!\n");
3533                         do_exec = 0;
3534                 }
3535                 if (do_include || do_exec) {
3536                         if (c) {
3537                                 char *cur2;
3538                                 char real_inclusion_name[256];
3539                                 struct ast_config_include *inclu;
3540                 
3541                                 /* Strip off leading and trailing "'s and <>'s */
3542                                 while((*c == '<') || (*c == '>') || (*c == '\"')) c++;
3543                                 /* Get rid of leading mess */
3544                                 cur = c;
3545                                 cur2 = cur;
3546                                 while (!ast_strlen_zero(cur)) {
3547                                         c = cur + strlen(cur) - 1;
3548                                         if ((*c == '>') || (*c == '<') || (*c == '\"'))
3549                                                 *c = '\0';
3550                                         else
3551                                                 break;
3552                                 }
3553                                 /* #exec </path/to/executable>
3554                                    We create a tmp file, then we #include it, then we delete it. */
3555                                 if (do_exec) { 
3556                                         snprintf(exec_file, sizeof(exec_file), "/var/tmp/exec.%d.%ld", (int)time(NULL), (long)pthread_self());
3557                                         snprintf(cmd, sizeof(cmd), "%s > %s 2>&1", cur, exec_file);
3558                                         ast_safe_system(cmd);
3559                                         cur = exec_file;
3560                                 } else
3561                                         exec_file[0] = '\0';
3562                                 /* A #include */
3563                                 /* ast_log(LOG_WARNING, "Reading in included file %s withcomments=%d\n", cur, withcomments); */
3564                                 
3565                                 /* record this inclusion */
3566                                 inclu = ast_include_new(cfg, configfile, cur, do_exec, cur2, lineno, real_inclusion_name, sizeof(real_inclusion_name));
3567                                 
3568                                 do_include = ast_config_internal_load(cur, cfg, withcomments, real_inclusion_name) ? 1 : 0;
3569                                 if(!ast_strlen_zero(exec_file))
3570                                         unlink(exec_file);
3571                                 if(!do_include)
3572                                         return 0;
3573                                 /* ast_log(LOG_WARNING, "Done reading in included file %s withcomments=%d\n", cur, withcomments); */
3574                                 
3575                         } else {
3576                                 ast_log(LOG_WARNING, "Directive '#%s' needs an argument (%s) at line %d of %s\n", 
3577                                                 do_exec ? "exec" : "include",
3578                                                 do_exec ? "/path/to/executable" : "filename",
3579                                                 lineno,
3580                                                 configfile);
3581                         }
3582                 }
3583                 else 
3584                         ast_log(LOG_WARNING, "Unknown directive '%s' at line %d of %s\n", cur, lineno, configfile);
3585         } else {
3586                 /* Just a line (variable = value) */
3587                 if (!*cat) {
3588                         ast_log(LOG_WARNING,
3589                                 "parse error: No category context for line %d of %s\n", lineno, configfile);
3590                         return -1;
3591                 }
3592                 c = strchr(cur, '=');
3593                 if (c) {
3594                         *c = 0;
3595                         c++;
3596                         /* Ignore > in => */
3597                         if (*c== '>') {
3598                                 object = 1;
3599                                 c++;
3600                         } else
3601                                 object = 0;
3602                         if ((v = ast_variable_new(ast_strip(cur), ast_strip(c), configfile))) {
3603                                 v->lineno = lineno;
3604                                 v->object = object;
3605                                 /* Put and reset comments */
3606                                 v->blanklines = 0;
3607                                 ast_variable_append(*cat, v);
3608                                 /* add comments */
3609                                 if (withcomments && comment_buffer && comment_buffer[0] ) {
3610                                         v->precomments = ALLOC_COMMENT(comment_buffer);
3611                                 }
3612                                 if (withcomments && lline_buffer && lline_buffer[0] ) {
3613                                         v->sameline = ALLOC_COMMENT(lline_buffer);
3614                                 }
3615                                 if( withcomments )
3616                                         CB_RESET();
3617                                 
3618                         } else {
3619                                 return -1;
3620                         }
3621                 } else {
3622                         ast_log(LOG_WARNING, "EXTENSIONS.CONF: No '=' (equal sign) in line %d of %s\n", lineno, configfile);
3623                 }
3624         }
3625         return 0;
3626 }
3627
3628 static int use_local_dir = 1;
3629
3630 void localized_use_local_dir(void);
3631 void localized_use_conf_dir(void);
3632
3633 void localized_use_local_dir(void)
3634 {
3635         use_local_dir = 1;
3636 }
3637
3638 void localized_use_conf_dir(void)
3639 {
3640         use_local_dir = 0;
3641 }
3642
3643
3644 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)
3645 {
3646         char fn[256];
3647         char buf[8192];
3648         char *new_buf, *comment_p, *process_buf;
3649         FILE *f;
3650         int lineno=0;
3651         int comment = 0, nest[MAX_NESTED_COMMENTS];
3652         struct ast_category *cat = NULL;
3653         int count = 0;
3654         struct stat statbuf;
3655         
3656         cat = ast_config_get_current_category(cfg);
3657
3658         if (filename[0] == '/') {
3659                 ast_copy_string(fn, filename, sizeof(fn));
3660         } else {
3661                 if (use_local_dir)
3662                         snprintf(fn, sizeof(fn), "./%s", filename);
3663                 else
3664                         snprintf(fn, sizeof(fn), "%s/%s", ast_config_AST_CONFIG_DIR, filename);
3665         }
3666
3667         if (withcomments && cfg && cfg->include_level < 2 ) {
3668                 CB_INIT();
3669         }
3670         
3671 #ifdef AST_INCLUDE_GLOB
3672         {
3673                 int glob_ret;
3674                 glob_t globbuf;
3675
3676                 globbuf.gl_offs = 0;    /* initialize it to silence gcc */
3677 #ifdef SOLARIS
3678                 glob_ret = glob(fn, GLOB_NOCHECK, NULL, &globbuf);
3679 #else
3680                 glob_ret = glob(fn, GLOB_NOMAGIC|GLOB_BRACE, NULL, &globbuf);
3681 #endif
3682                 if (glob_ret == GLOB_NOSPACE)
3683                         ast_log(LOG_WARNING,
3684                                 "Glob Expansion of pattern '%s' failed: Not enough memory\n", fn);
3685                 else if (glob_ret  == GLOB_ABORTED)
3686                         ast_log(LOG_WARNING,
3687                                 "Glob Expansion of pattern '%s' failed: Read error\n", fn);
3688                 else  {
3689                         /* loop over expanded files */
3690                         int i;
3691                         for (i=0; i<globbuf.gl_pathc; i++) {
3692                                 ast_copy_string(fn, globbuf.gl_pathv[i], sizeof(fn));
3693 #endif
3694         do {
3695                 if (stat(fn, &statbuf))
3696                         continue;
3697
3698                 if (!S_ISREG(statbuf.st_mode)) {
3699                         ast_log(LOG_WARNING, "'%s' is not a regular file, ignoring\n", fn);
3700                         continue;
3701                 }
3702                 if (option_verbose > 1) {
3703                         ast_verbose(VERBOSE_PREFIX_2 "Parsing '%s': ", fn);
3704                         fflush(stdout);
3705                 }
3706                 if (!(f = fopen(fn, "r"))) {
3707                         if (option_debug)
3708                                 ast_log(LOG_DEBUG, "No file to parse: %s\n", fn);
3709                         if (option_verbose > 1)
3710                                 ast_verbose( "Not found (%s)\n", strerror(errno));
3711                         continue;
3712                 }
3713                 count++;
3714                 if (option_debug)
3715                         ast_log(LOG_DEBUG, "Parsing %s\n", fn);
3716                 if (option_verbose > 1)
3717                         ast_verbose("Found\n");
3718                 while(!feof(f)) {
3719                         lineno++;
3720                         if (fgets(buf, sizeof(buf), f)) {
3721                                 if ( withcomments ) {    
3722                                         CB_ADD(lline_buffer);       /* add the current lline buffer to the comment buffer */
3723                                         lline_buffer[0] = 0;        /* erase the lline buffer */
3724                                 }
3725                                 
3726                                 new_buf = buf;
3727                                 if (comment) 
3728                                         process_buf = NULL;
3729                                 else
3730                                         process_buf = buf;
3731                                 
3732                                 while ((comment_p = strchr(new_buf, COMMENT_META))) {
3733                                         if ((comment_p > new_buf) && (*(comment_p-1) == '\\')) {
3734                                                 /* Yuck, gotta memmove */
3735                                                 memmove(comment_p - 1, comment_p, strlen(comment_p) + 1);
3736                                                 new_buf = comment_p;
3737                                         } else if(comment_p[1] == COMMENT_TAG && comment_p[2] == COMMENT_TAG && (comment_p[3] != '-')) {
3738                                                 /* Meta-Comment start detected ";--" */
3739                                                 if (comment < MAX_NESTED_COMMENTS) {
3740                                                         *comment_p = '\0';
3741                                           &