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