Asterisk - The Open Source Telephony Project  21.4.1
extconf.c
Go to the documentation of this file.
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  * \file
22  * A condensation of the pbx_config stuff, to read into extensions.conf, and provide an interface to the data there,
23  * for operations outside of asterisk. A huge, awful hack.
24  *
25  */
26 
27 /*!
28  * \li \ref extconf.c uses the configuration file \ref extconfig.conf and \ref extensions.conf and \ref asterisk.conf
29  * \addtogroup configuration_file Configuration Files
30  */
31 
32 /*!
33  * \page extconfig.conf extconfig.conf
34  * \verbinclude extconfig.conf.sample
35  */
36 
37 /*!
38  * \page extensions.conf extensions.conf
39  * \verbinclude extensions.conf.sample
40  */
41 
42 /*** MODULEINFO
43  <support_level>extended</support_level>
44  ***/
45 
46 #define ASTMM_LIBC ASTMM_IGNORE
47 #include "asterisk.h"
48 
49 #undef DEBUG_THREADS
50 
51 #include "asterisk/compat.h"
52 #include "asterisk/paths.h" /* we use AST_CONFIG_DIR */
53 
54 #include <errno.h>
55 #include <time.h>
56 #include <sys/stat.h>
57 #include <sys/types.h>
58 #include <sys/time.h>
59 #include <sys/resource.h>
60 #include <sys/wait.h>
61 #include <stdarg.h>
62 #include <string.h>
63 #include <locale.h>
64 #include <ctype.h>
65 #if !defined(SOLARIS) && !defined(__CYGWIN__)
66 #include <err.h>
67 #endif
68 #include <regex.h>
69 #include <limits.h>
70 #include <pthread.h>
71 #include <netdb.h>
72 #include <sys/param.h>
73 #include <signal.h>
74 
75 static void ast_log(int level, const char *file, int line, const char *function, const char *fmt, ...) __attribute__((format(printf, 5, 6)));
76 void ast_verbose(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
77 
78 #define AST_API_MODULE 1 /* gimme the inline defs! */
79 struct ast_channel
80 {
81  char x; /* basically empty! */
82 };
83 
84 
85 
86 #include "asterisk/inline_api.h"
87 #include "asterisk/endian.h"
88 #include "asterisk/ast_expr.h"
89 #include "asterisk/extconf.h"
90 
91 /* logger.h */
92 
93 #define EVENTLOG "event_log"
94 #define QUEUELOG "queue_log"
95 
96 #define DEBUG_M(a) { \
97  a; \
98 }
99 
100 #define VERBOSE_PREFIX_1 " "
101 #define VERBOSE_PREFIX_2 " == "
102 #define VERBOSE_PREFIX_3 " -- "
103 #define VERBOSE_PREFIX_4 " > "
104 
105 void ast_log_backtrace(void);
106 
107 void ast_queue_log(const char *queuename, const char *callid, const char *agent, const char *event, const char *fmt, ...)
108  __attribute__((format(printf, 5, 6)));
109 
110 /* IN CONFLICT: void ast_verbose(const char *fmt, ...)
111  __attribute__((format(printf, 1, 2))); */
112 
113 void ast_console_puts(const char *string);
114 
115 #define _A_ __FILE__, __LINE__, __PRETTY_FUNCTION__
116 
117 #ifdef LOG_DEBUG
118 #undef LOG_DEBUG
119 #endif
120 #define __LOG_DEBUG 0
121 #define LOG_DEBUG __LOG_DEBUG, _A_
122 
123 #ifdef LOG_EVENT
124 #undef LOG_EVENT
125 #endif
126 #define __LOG_EVENT 1
127 #define LOG_EVENT __LOG_EVENT, _A_
128 
129 #ifdef LOG_NOTICE
130 #undef LOG_NOTICE
131 #endif
132 #define __LOG_NOTICE 2
133 #define LOG_NOTICE __LOG_NOTICE, _A_
134 
135 #ifdef LOG_WARNING
136 #undef LOG_WARNING
137 #endif
138 #define __LOG_WARNING 3
139 #define LOG_WARNING __LOG_WARNING, _A_
140 
141 #ifdef LOG_ERROR
142 #undef LOG_ERROR
143 #endif
144 #define __LOG_ERROR 4
145 #define LOG_ERROR __LOG_ERROR, _A_
146 
147 #ifdef LOG_VERBOSE
148 #undef LOG_VERBOSE
149 #endif
150 #define __LOG_VERBOSE 5
151 #define LOG_VERBOSE __LOG_VERBOSE, _A_
152 
153 #ifdef LOG_DTMF
154 #undef LOG_DTMF
155 #endif
156 #define __LOG_DTMF 6
157 #define LOG_DTMF __LOG_DTMF, _A_
158 
159 /* lock.h */
160 #define _ASTERISK_LOCK_H /* A small indication that this is horribly wrong. */
161 
162 #ifndef HAVE_MTX_PROFILE
163 #define __MTX_PROF(a) return pthread_mutex_lock((a))
164 #else
165 int mtx_prof = -1;
166 
167 #define __MTX_PROF(a) do { \
168  int i; \
169  /* profile only non-blocking events */ \
170  ast_mark(mtx_prof, 1); \
171  i = pthread_mutex_trylock((a)); \
172  ast_mark(mtx_prof, 0); \
173  if (!i) \
174  return i; \
175  else \
176  return pthread_mutex_lock((a)); \
177  } while (0)
178 #endif /* HAVE_MTX_PROFILE */
179 
180 #define AST_PTHREADT_NULL (pthread_t) -1
181 #define AST_PTHREADT_STOP (pthread_t) -2
182 
183 #if defined(SOLARIS) || defined(BSD)
184 #define AST_MUTEX_INIT_W_CONSTRUCTORS
185 #endif /* SOLARIS || BSD */
186 
187 /* Asterisk REQUIRES recursive (not error checking) mutexes
188  and will not run without them. */
189 #if defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP) && defined(PTHREAD_MUTEX_RECURSIVE_NP)
190 #define PTHREAD_MUTEX_INIT_VALUE PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
191 #define AST_MUTEX_KIND PTHREAD_MUTEX_RECURSIVE_NP
192 #else
193 #define PTHREAD_MUTEX_INIT_VALUE PTHREAD_MUTEX_INITIALIZER
194 #define AST_MUTEX_KIND PTHREAD_MUTEX_RECURSIVE
195 #endif /* PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP */
196 
197 #ifdef DEBUG_THREADS
198 
199 #define log_mutex_error(canlog, ...) do { if (canlog) ast_log(LOG_ERROR, __VA_ARGS__); else fprintf(stderr, __VA_ARGS__); } while (0)
200 
201 #ifdef THREAD_CRASH
202 #define DO_THREAD_CRASH do { *((int *)(0)) = 1; } while(0)
203 #else
204 #define DO_THREAD_CRASH do { } while (0)
205 #endif
206 
207 #define AST_MUTEX_INIT_VALUE { PTHREAD_MUTEX_INIT_VALUE, { NULL }, { 0 }, 0, { NULL }, { 0 } }
208 
209 #define AST_MAX_REENTRANCY 10
210 
211 struct ast_mutex_info {
212  pthread_mutex_t mutex;
213  /*! Track which thread holds this lock */
214  unsigned int track:1;
215  const char *file[AST_MAX_REENTRANCY];
216  int lineno[AST_MAX_REENTRANCY];
217  int reentrancy;
218  const char *func[AST_MAX_REENTRANCY];
219  pthread_t thread[AST_MAX_REENTRANCY];
220 };
221 
222 typedef struct ast_mutex_info ast_mutex_t;
223 
224 typedef pthread_cond_t ast_cond_t;
225 
226 static pthread_mutex_t empty_mutex;
227 
228 static void __attribute__((constructor)) init_empty_mutex(void)
229 {
230  memset(&empty_mutex, 0, sizeof(empty_mutex));
231 }
232 
233 static inline int __ast_pthread_mutex_init_attr(const char *filename, int lineno, const char *func,
234  const char *mutex_name, ast_mutex_t *t,
235  pthread_mutexattr_t *attr)
236 {
237 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
238  int canlog = strcmp(filename, "logger.c");
239 
240  if ((t->mutex) != ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
241  if ((t->mutex) != (empty_mutex)) {
242  log_mutex_error(canlog, "%s line %d (%s): Error: mutex '%s' is already initialized.\n",
243  filename, lineno, func, mutex_name);
244  log_mutex_error(canlog, "%s line %d (%s): Error: previously initialization of mutex '%s'.\n",
245  t->file[0], t->lineno[0], t->func[0], mutex_name);
246  DO_THREAD_CRASH;
247  return 0;
248  }
249  }
250 #endif
251 
252  t->file[0] = filename;
253  t->lineno[0] = lineno;
254  t->func[0] = func;
255  t->thread[0] = 0;
256  t->reentrancy = 0;
257 
258  return pthread_mutex_init(&t->mutex, attr);
259 }
260 
261 static inline int __ast_pthread_mutex_init(const char *filename, int lineno, const char *func,
262  const char *mutex_name, ast_mutex_t *t)
263 {
264  static pthread_mutexattr_t attr;
265 
266  pthread_mutexattr_init(&attr);
267  pthread_mutexattr_settype(&attr, AST_MUTEX_KIND);
268 
269  return __ast_pthread_mutex_init_attr(filename, lineno, func, mutex_name, t, &attr);
270 }
271 #define ast_mutex_init(pmutex) __ast_pthread_mutex_init(__FILE__, __LINE__, __PRETTY_FUNCTION__, #pmutex, pmutex)
272 
273 static inline int __ast_pthread_mutex_destroy(const char *filename, int lineno, const char *func,
274  const char *mutex_name, ast_mutex_t *t)
275 {
276  int res;
277  int canlog = strcmp(filename, "logger.c");
278 
279 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
280  if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
281  log_mutex_error(canlog, "%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
282  filename, lineno, func, mutex_name);
283  }
284 #endif
285 
286  res = pthread_mutex_trylock(&t->mutex);
287  switch (res) {
288  case 0:
289  pthread_mutex_unlock(&t->mutex);
290  break;
291  case EINVAL:
292  log_mutex_error(canlog, "%s line %d (%s): Error: attempt to destroy invalid mutex '%s'.\n",
293  filename, lineno, func, mutex_name);
294  break;
295  case EBUSY:
296  log_mutex_error(canlog, "%s line %d (%s): Error: attempt to destroy locked mutex '%s'.\n",
297  filename, lineno, func, mutex_name);
298  log_mutex_error(canlog, "%s line %d (%s): Error: '%s' was locked here.\n",
299  t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
300  break;
301  }
302 
303  if ((res = pthread_mutex_destroy(&t->mutex)))
304  log_mutex_error(canlog, "%s line %d (%s): Error destroying mutex: %s\n",
305  filename, lineno, func, strerror(res));
306 #ifndef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
307  else
308  t->mutex = PTHREAD_MUTEX_INIT_VALUE;
309 #endif
310  t->file[0] = filename;
311  t->lineno[0] = lineno;
312  t->func[0] = func;
313 
314  return res;
315 }
316 
317 static inline int __ast_pthread_mutex_lock(const char *filename, int lineno, const char *func,
318  const char* mutex_name, ast_mutex_t *t)
319 {
320  int res;
321  int canlog = strcmp(filename, "logger.c");
322 
323 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
324  if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
325  log_mutex_error(canlog, "%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
326  filename, lineno, func, mutex_name);
327  ast_mutex_init(t);
328  }
329 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
330 
331 #ifdef DETECT_DEADLOCKS
332  {
333  time_t seconds = time(NULL);
334  time_t current;
335  do {
336 #ifdef HAVE_MTX_PROFILE
337  ast_mark(mtx_prof, 1);
338 #endif
339  res = pthread_mutex_trylock(&t->mutex);
340 #ifdef HAVE_MTX_PROFILE
341  ast_mark(mtx_prof, 0);
342 #endif
343  if (res == EBUSY) {
344  current = time(NULL);
345  if ((current - seconds) && (!((current - seconds) % 5))) {
346  log_mutex_error(canlog, "%s line %d (%s): Deadlock? waited %d sec for mutex '%s'?\n",
347  filename, lineno, func, (int)(current - seconds), mutex_name);
348  log_mutex_error(canlog, "%s line %d (%s): '%s' was locked here.\n",
349  t->file[t->reentrancy-1], t->lineno[t->reentrancy-1],
350  t->func[t->reentrancy-1], mutex_name);
351  }
352  usleep(200);
353  }
354  } while (res == EBUSY);
355  }
356 #else
357 #ifdef HAVE_MTX_PROFILE
358  ast_mark(mtx_prof, 1);
359  res = pthread_mutex_trylock(&t->mutex);
360  ast_mark(mtx_prof, 0);
361  if (res)
362 #endif
363  res = pthread_mutex_lock(&t->mutex);
364 #endif /* DETECT_DEADLOCKS */
365 
366  if (!res) {
367  if (t->reentrancy < AST_MAX_REENTRANCY) {
368  t->file[t->reentrancy] = filename;
369  t->lineno[t->reentrancy] = lineno;
370  t->func[t->reentrancy] = func;
371  t->thread[t->reentrancy] = pthread_self();
372  t->reentrancy++;
373  } else {
374  log_mutex_error(canlog, "%s line %d (%s): '%s' really deep reentrancy!\n",
375  filename, lineno, func, mutex_name);
376  }
377  } else {
378  log_mutex_error(canlog, "%s line %d (%s): Error obtaining mutex: %s\n",
379  filename, lineno, func, strerror(errno));
380  DO_THREAD_CRASH;
381  }
382 
383  return res;
384 }
385 
386 static inline int __ast_pthread_mutex_trylock(const char *filename, int lineno, const char *func,
387  const char* mutex_name, ast_mutex_t *t)
388 {
389  int res;
390  int canlog = strcmp(filename, "logger.c");
391 
392 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
393  if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
394  log_mutex_error(canlog, "%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
395  filename, lineno, func, mutex_name);
396  ast_mutex_init(t);
397  }
398 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
399 
400  if (!(res = pthread_mutex_trylock(&t->mutex))) {
401  if (t->reentrancy < AST_MAX_REENTRANCY) {
402  t->file[t->reentrancy] = filename;
403  t->lineno[t->reentrancy] = lineno;
404  t->func[t->reentrancy] = func;
405  t->thread[t->reentrancy] = pthread_self();
406  t->reentrancy++;
407  } else {
408  log_mutex_error(canlog, "%s line %d (%s): '%s' really deep reentrancy!\n",
409  filename, lineno, func, mutex_name);
410  }
411  } else {
412  log_mutex_error(canlog, "%s line %d (%s): Warning: '%s' was locked here.\n",
413  t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
414  }
415 
416  return res;
417 }
418 
419 static inline int __ast_pthread_mutex_unlock(const char *filename, int lineno, const char *func,
420  const char *mutex_name, ast_mutex_t *t)
421 {
422  int res;
423  int canlog = strcmp(filename, "logger.c");
424 
425 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
426  if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
427  log_mutex_error(canlog, "%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
428  filename, lineno, func, mutex_name);
429  }
430 #endif
431 
432  if (t->reentrancy && (t->thread[t->reentrancy-1] != pthread_self())) {
433  log_mutex_error(canlog, "%s line %d (%s): attempted unlock mutex '%s' without owning it!\n",
434  filename, lineno, func, mutex_name);
435  log_mutex_error(canlog, "%s line %d (%s): '%s' was locked here.\n",
436  t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
437  DO_THREAD_CRASH;
438  }
439 
440  if (--t->reentrancy < 0) {
441  log_mutex_error(canlog, "%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
442  filename, lineno, func, mutex_name);
443  t->reentrancy = 0;
444  }
445 
446  if (t->reentrancy < AST_MAX_REENTRANCY) {
447  t->file[t->reentrancy] = NULL;
448  t->lineno[t->reentrancy] = 0;
449  t->func[t->reentrancy] = NULL;
450  t->thread[t->reentrancy] = 0;
451  }
452 
453  if ((res = pthread_mutex_unlock(&t->mutex))) {
454  log_mutex_error(canlog, "%s line %d (%s): Error releasing mutex: %s\n",
455  filename, lineno, func, strerror(res));
456  DO_THREAD_CRASH;
457  }
458 
459  return res;
460 }
461 
462 #else /* !DEBUG_THREADS */
463 
464 
465 typedef pthread_mutex_t ast_mutex_t;
466 
467 #define AST_MUTEX_INIT_VALUE ((ast_mutex_t) PTHREAD_MUTEX_INIT_VALUE)
468 
469 static inline int ast_mutex_init(ast_mutex_t *pmutex)
470 {
471  pthread_mutexattr_t attr;
472 
473  pthread_mutexattr_init(&attr);
474  pthread_mutexattr_settype(&attr, AST_MUTEX_KIND);
475 
476  return pthread_mutex_init(pmutex, &attr);
477 }
478 
479 #define ast_pthread_mutex_init(pmutex,a) pthread_mutex_init(pmutex,a)
480 
481 typedef pthread_cond_t ast_cond_t;
482 
483 #endif /* !DEBUG_THREADS */
484 
485 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
486 /* If AST_MUTEX_INIT_W_CONSTRUCTORS is defined, use file scope
487  constructors/destructors to create/destroy mutexes. */
488 #define __AST_MUTEX_DEFINE(scope, mutex) \
489  scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE; \
490 static void __attribute__((constructor)) init_##mutex(void) \
491 { \
492  ast_mutex_init(&mutex); \
493 }
494 #else /* !AST_MUTEX_INIT_W_CONSTRUCTORS */
495 /* By default, use static initialization of mutexes. */
496 #define __AST_MUTEX_DEFINE(scope, mutex) \
497  scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE
498 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
499 
500 #define pthread_mutex_t use_ast_mutex_t_instead_of_pthread_mutex_t
501 #define pthread_mutex_init use_ast_mutex_init_instead_of_pthread_mutex_init
502 #define pthread_cond_t use_ast_cond_t_instead_of_pthread_cond_t
503 
504 #define AST_MUTEX_DEFINE_STATIC(mutex) __AST_MUTEX_DEFINE(static, mutex)
505 
506 #define AST_MUTEX_INITIALIZER __use_AST_MUTEX_DEFINE_STATIC_rather_than_AST_MUTEX_INITIALIZER__
507 
508 #define gethostbyname __gethostbyname__is__not__reentrant__use__ast_gethostbyname__instead__
509 
510 #ifndef __linux__
511 #define pthread_create __use_ast_pthread_create_instead__
512 #endif
513 
514 typedef pthread_rwlock_t ast_rwlock_t;
515 
516 static inline int ast_rwlock_init(ast_rwlock_t *prwlock)
517 {
518  pthread_rwlockattr_t attr;
519 
520  pthread_rwlockattr_init(&attr);
521 
522 #ifdef HAVE_PTHREAD_RWLOCK_PREFER_WRITER_NP
523  pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NP);
524 #endif
525 
526  return pthread_rwlock_init(prwlock, &attr);
527 }
528 
529 static inline int ast_rwlock_destroy(ast_rwlock_t *prwlock)
530 {
531  return pthread_rwlock_destroy(prwlock);
532 }
533 
534 static inline int ast_rwlock_unlock(ast_rwlock_t *prwlock)
535 {
536  return pthread_rwlock_unlock(prwlock);
537 }
538 
539 static inline int ast_rwlock_rdlock(ast_rwlock_t *prwlock)
540 {
541  return pthread_rwlock_rdlock(prwlock);
542 }
543 
544 static inline int ast_rwlock_wrlock(ast_rwlock_t *prwlock)
545 {
546  return pthread_rwlock_wrlock(prwlock);
547 }
548 
549 /* Statically declared read/write locks */
550 
551 #ifndef HAVE_PTHREAD_RWLOCK_INITIALIZER
552 #define __AST_RWLOCK_DEFINE(scope, rwlock) \
553  scope ast_rwlock_t rwlock; \
554 static void __attribute__((constructor)) init_##rwlock(void) \
555 { \
556  ast_rwlock_init(&rwlock); \
557 } \
558 static void __attribute__((destructor)) fini_##rwlock(void) \
559 { \
560  ast_rwlock_destroy(&rwlock); \
561 }
562 #else
563 #define AST_RWLOCK_INIT_VALUE PTHREAD_RWLOCK_INITIALIZER
564 #define __AST_RWLOCK_DEFINE(scope, rwlock) \
565  scope ast_rwlock_t rwlock = AST_RWLOCK_INIT_VALUE
566 #endif
567 
568 #define AST_RWLOCK_DEFINE_STATIC(rwlock) __AST_RWLOCK_DEFINE(static, rwlock)
569 
570 /*
571  * Initial support for atomic instructions.
572  * For platforms that have it, use the native cpu instruction to
573  * implement them. For other platforms, resort to a 'slow' version
574  * (defined in utils.c) that protects the atomic instruction with
575  * a single lock.
576  * The slow versions is always available, for testing purposes,
577  * as ast_atomic_fetchadd_int_slow()
578  */
579 
580 #if defined(HAVE_OSX_ATOMICS)
581 #include "libkern/OSAtomic.h"
582 #endif
583 
584 /*! \brief Atomically add v to *p and return * the previous value of *p.
585  * This can be used to handle reference counts, and the return value
586  * can be used to generate unique identifiers.
587  */
588 
589 #if defined(HAVE_GCC_ATOMICS)
590 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
591 {
592  return __sync_fetch_and_add(p, v);
593 })
594 #elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 4)
595 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
596 {
597  return OSAtomicAdd32(v, (int32_t *) p);
598 })
599 #elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 8)
600 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
601 {
602  return OSAtomicAdd64(v, (int64_t *) p);
603 #elif defined (__i386__) || defined(__x86_64__)
604 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
605 {
606  __asm __volatile (
607  " lock xaddl %0, %1 ; "
608  : "+r" (v), /* 0 (result) */
609  "=m" (*p) /* 1 */
610  : "m" (*p)); /* 2 */
611  return (v);
612 })
613 #else
614 static int ast_atomic_fetchadd_int_slow(volatile int *p, int v)
615 {
616  int ret;
617  ret = *p;
618  *p += v;
619  return ret;
620 }
621 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
622 {
623  return ast_atomic_fetchadd_int_slow(p, v);
624 })
625 #endif
626 
627 /*! \brief decrement *p by 1 and return true if the variable has reached 0.
628  * Useful e.g. to check if a refcount has reached 0.
629  */
630 #if defined(HAVE_GCC_ATOMICS)
631 AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
632 {
633  return __sync_sub_and_fetch(p, 1) == 0;
634 })
635 #elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 4)
636 AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
637 {
638  return OSAtomicAdd32( -1, (int32_t *) p) == 0;
639 })
640 #elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 8)
641 AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
642 {
643  return OSAtomicAdd64( -1, (int64_t *) p) == 0;
644 #else
645 AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
646 {
647  int a = ast_atomic_fetchadd_int(p, -1);
648  return a == 1; /* true if the value is 0 now (so it was 1 previously) */
649 })
650 #endif
651 
652 #ifdef DEBUG_CHANNEL_LOCKS
653 /*! \brief Lock AST channel (and print debugging output)
654 \note You need to enable DEBUG_CHANNEL_LOCKS for this function */
655 int ast_channel_lock(struct ast_channel *chan);
656 
657 /*! \brief Unlock AST channel (and print debugging output)
658 \note You need to enable DEBUG_CHANNEL_LOCKS for this function
659 */
660 int ast_channel_unlock(struct ast_channel *chan);
661 
662 /*! \brief Lock AST channel (and print debugging output)
663 \note You need to enable DEBUG_CHANNEL_LOCKS for this function */
664 int ast_channel_trylock(struct ast_channel *chan);
665 #endif
666 
667 
668 #include "asterisk/hashtab.h"
669 #include "asterisk/ael_structs.h"
670 #include "asterisk/pval.h"
671 
672 /* from utils.h */
673 
674 struct ast_flags { /* stolen from utils.h */
675  unsigned int flags;
676 };
677 #define ast_test_flag(p,flag) ({ \
678  typeof ((p)->flags) __p = (p)->flags; \
679  unsigned int __x = 0; \
680  (void) (&__p == &__x); \
681  ((p)->flags & (flag)); \
682  })
683 
684 #define ast_set2_flag(p,value,flag) do { \
685  typeof ((p)->flags) __p = (p)->flags; \
686  unsigned int __x = 0; \
687  (void) (&__p == &__x); \
688  if (value) \
689  (p)->flags |= (flag); \
690  else \
691  (p)->flags &= ~(flag); \
692  } while (0)
693 
694 /* from config.c */
695 
696 #define MAX_NESTED_COMMENTS 128
697 #define COMMENT_START ";--"
698 #define COMMENT_END "--;"
699 #define COMMENT_META ';'
700 #define COMMENT_TAG '-'
701 
702 static char *extconfig_conf = "extconfig.conf";
703 
704 /*! Growable string buffer */
705 static char *comment_buffer; /*!< this will be a comment collector.*/
706 static int comment_buffer_size; /*!< the amount of storage so far alloc'd for the comment_buffer */
707 
708 static char *lline_buffer; /*!< A buffer for stuff behind the ; */
709 static int lline_buffer_size;
710 
711 #define CB_INCR 250
712 
713 struct ast_comment {
714  struct ast_comment *next;
715  char cmt[0];
716 };
717 
718 static void CB_INIT(void)
719 {
720  if (!comment_buffer) {
721  comment_buffer = ast_malloc(CB_INCR);
722  if (!comment_buffer)
723  return;
724  comment_buffer[0] = 0;
725  comment_buffer_size = CB_INCR;
726  lline_buffer = ast_malloc(CB_INCR);
727  if (!lline_buffer)
728  return;
729  lline_buffer[0] = 0;
730  lline_buffer_size = CB_INCR;
731  } else {
732  comment_buffer[0] = 0;
733  lline_buffer[0] = 0;
734  }
735 }
736 
737 static void CB_ADD(char *str)
738 {
739  int rem = comment_buffer_size - strlen(comment_buffer) - 1;
740  int siz = strlen(str);
741  if (rem < siz+1) {
742  comment_buffer = ast_realloc(comment_buffer, comment_buffer_size + CB_INCR + siz + 1);
743  if (!comment_buffer)
744  return;
745  comment_buffer_size += CB_INCR+siz+1;
746  }
747  strcat(comment_buffer,str);
748 }
749 
750 static void CB_ADD_LEN(char *str, int len)
751 {
752  int cbl = strlen(comment_buffer) + 1;
753  int rem = comment_buffer_size - cbl;
754  if (rem < len+1) {
755  comment_buffer = ast_realloc(comment_buffer, comment_buffer_size + CB_INCR + len + 1);
756  if (!comment_buffer)
757  return;
758  comment_buffer_size += CB_INCR+len+1;
759  }
760  strncat(comment_buffer,str,len); /* safe */
761  comment_buffer[cbl+len-1] = 0;
762 }
763 
764 static void LLB_ADD(char *str)
765 {
766  int rem = lline_buffer_size - strlen(lline_buffer) - 1;
767  int siz = strlen(str);
768  if (rem < siz+1) {
769  lline_buffer = ast_realloc(lline_buffer, lline_buffer_size + CB_INCR + siz + 1);
770  if (!lline_buffer)
771  return;
772  lline_buffer_size += CB_INCR + siz + 1;
773  }
774  strcat(lline_buffer,str);
775 }
776 
777 static void CB_RESET(void )
778 {
779  comment_buffer[0] = 0;
780  lline_buffer[0] = 0;
781 }
782 
783 /*! \brief Keep track of how many threads are currently trying to wait*() on
784  * a child process */
785 static unsigned int safe_system_level = 0;
786 static struct sigaction safe_system_prev_handler;
787 
788 /*! \brief NULL handler so we can collect the child exit status */
789 static void _null_sig_handler(int sig)
790 {
791 
792 }
793 
794 static struct sigaction null_sig_handler = {
795  .sa_handler = _null_sig_handler,
796  .sa_flags = SA_RESTART,
797 };
798 
799 void ast_replace_sigchld(void);
800 
802 {
803  unsigned int level;
804 
805  level = safe_system_level++;
806 
807  /* only replace the handler if it has not already been done */
808  if (level == 0) {
809  sigaction(SIGCHLD, &null_sig_handler, &safe_system_prev_handler);
810  }
811 }
812 
813 void ast_unreplace_sigchld(void);
814 
816 {
817  unsigned int level;
818 
819  level = --safe_system_level;
820 
821  /* only restore the handler if we are the last one */
822  if (level == 0) {
823  sigaction(SIGCHLD, &safe_system_prev_handler, NULL);
824  }
825 }
826 
827 int ast_safe_system(const char *s);
828 
829 int ast_safe_system(const char *s)
830 {
831  pid_t pid;
832 #ifdef HAVE_WORKING_FORK
833  int x;
834 #endif
835  int res;
836  int status;
837 
838 #if defined(HAVE_WORKING_FORK) || defined(HAVE_WORKING_VFORK)
840 
841 #ifdef HAVE_WORKING_FORK
842  pid = fork();
843 #else
844  pid = vfork();
845 #endif
846 
847  if (pid == 0) {
848 #ifdef HAVE_WORKING_FORK
849  /* Close file descriptors and launch system command */
850  for (x = STDERR_FILENO + 1; x < 4096; x++)
851  close(x);
852 #endif
853  execl("/bin/sh", "/bin/sh", "-c", s, (char *) NULL);
854  _exit(1);
855  } else if (pid > 0) {
856  for(;;) {
857  res = waitpid(pid, &status, 0);
858  if (res > -1) {
859  res = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
860  break;
861  } else if (errno != EINTR)
862  break;
863  }
864  } else {
865  ast_log(LOG_WARNING, "Fork failed: %s\n", strerror(errno));
866  res = -1;
867  }
868 
870 #else
871  res = -1;
872 #endif
873 
874  return res;
875 }
876 
877 static struct ast_comment *ALLOC_COMMENT(const char *buffer)
878 {
879  struct ast_comment *x = ast_calloc(1,sizeof(struct ast_comment)+strlen(buffer)+1);
880  strcpy(x->cmt, buffer);
881  return x;
882 }
883 
884 static struct ast_config_map {
885  struct ast_config_map *next;
886  char *name;
887  char *driver;
888  char *database;
889  char *table;
890  char stuff[0];
891 } *config_maps = NULL;
892 
893 static struct ast_config_engine *config_engine_list;
894 
895 #define MAX_INCLUDE_LEVEL 10
896 
897 
898 struct ast_category {
899  char name[80];
900  int ignored; /*!< do not let user of the config see this category */
901  int include_level;
902  char *file; /*!< the file name from whence this declaration was read */
903  int lineno;
904  struct ast_comment *precomments;
905  struct ast_comment *sameline;
906  struct ast_variable *root;
907  struct ast_variable *last;
908  struct ast_category *next;
909 };
910 
911 struct ast_config {
912  struct ast_category *root;
913  struct ast_category *last;
914  struct ast_category *current;
915  struct ast_category *last_browse; /*!< used to cache the last category supplied via category_browse */
916  int include_level;
917  int max_include_level;
918  struct ast_config_include *includes; /*!< a list of inclusions, which should describe the entire tree */
919 };
920 
921 struct ast_config_include {
922  char *include_location_file; /*!< file name in which the include occurs */
923  int include_location_lineno; /*!< lineno where include occurred */
924  int exec; /*!< set to non-zero if itsa #exec statement */
925  char *exec_file; /*!< if it's an exec, you'll have both the /var/tmp to read, and the original script */
926  char *included_file; /*!< file name included */
927  int inclusion_count; /*!< if the file is included more than once, a running count thereof -- but, worry not,
928  we explode the instances and will include those-- so all entries will be unique */
929  int output; /*!< a flag to indicate if the inclusion has been output */
930  struct ast_config_include *next; /*!< ptr to next inclusion in the list */
931 };
932 
933 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);
934 typedef struct ast_variable *realtime_var_get(const char *database, const char *table, va_list ap);
935 typedef struct ast_config *realtime_multi_get(const char *database, const char *table, va_list ap);
936 typedef int realtime_update(const char *database, const char *table, const char *keyfield, const char *entity, va_list ap);
937 
938 /*! \brief Configuration engine structure, used to define realtime drivers */
939 struct ast_config_engine {
940  char *name;
941  config_load_func *load_func;
942  realtime_var_get *realtime_func;
943  realtime_multi_get *realtime_multi_func;
944  realtime_update *update_func;
945  struct ast_config_engine *next;
946 };
947 
948 static struct ast_config_engine *config_engine_list;
949 
950 /* taken from strings.h */
951 
952 static force_inline int ast_strlen_zero(const char *s)
953 {
954  return (!s || (*s == '\0'));
955 }
956 
957 #define S_OR(a, b) (!ast_strlen_zero(a) ? (a) : (b))
958 
959 AST_INLINE_API(
960 void ast_copy_string(char *dst, const char *src, size_t size),
961 {
962  while (*src && size) {
963  *dst++ = *src++;
964  size--;
965  }
966  if (__builtin_expect(!size, 0))
967  dst--;
968  *dst = '\0';
969 }
970 )
971 
972 AST_INLINE_API(
973 char *ast_skip_blanks(const char *str),
974 {
975  while (*str && *str < 33)
976  str++;
977  return (char *)str;
978 }
979 )
980 
981 /*!
982  \brief Trims trailing whitespace characters from a string.
983  \param str the input string
984  \return a pointer to the modified string
985  */
986 AST_INLINE_API(
987 char *ast_trim_blanks(char *str),
988 {
989  char *work = str;
990 
991  if (work) {
992  work += strlen(work) - 1;
993  /* It's tempting to only want to erase after we exit this loop,
994  but since ast_trim_blanks *could* receive a constant string
995  (which we presumably wouldn't have to touch), we shouldn't
996  actually set anything unless we must, and it's easier just
997  to set each position to \0 than to keep track of a variable
998  for it */
999  while ((work >= str) && *work < 33)
1000  *(work--) = '\0';
1001  }
1002  return str;
1003 }
1005 
1006 /*!
1007  \brief Strip leading/trailing whitespace from a string.
1008  \param s The string to be stripped (will be modified).
1009  \return The stripped string.
1010 
1011  This functions strips all leading and trailing whitespace
1012  characters from the input string, and returns a pointer to
1013  the resulting string. The string is modified in place.
1014 */
1015 AST_INLINE_API(
1016 char *ast_strip(char *s),
1017 {
1018  s = ast_skip_blanks(s);
1019  if (s)
1020  ast_trim_blanks(s);
1021  return s;
1022 }
1024 
1025 
1026 /* from config.h */
1027 
1028 struct ast_variable {
1029  char *name;
1030  char *value;
1031  char *file;
1032  int lineno;
1033  int object; /*!< 0 for variable, 1 for object */
1034  int blanklines; /*!< Number of blanklines following entry */
1035  struct ast_comment *precomments;
1036  struct ast_comment *sameline;
1037  struct ast_variable *next;
1038  char stuff[0];
1039 };
1040 
1041 static const char *ast_variable_retrieve(const struct ast_config *config, const char *category, const char *variable);
1042 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);
1043 
1044 struct ast_config *localized_config_load_with_comments(const char *filename);
1045 static char *ast_category_browse(struct ast_config *config, const char *prev);
1046 static struct ast_variable *ast_variable_browse(const struct ast_config *config, const char *category);
1047 static void ast_variables_destroy(struct ast_variable *v);
1048 static void ast_config_destroy(struct ast_config *cfg);
1049 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);
1050 static struct ast_config_include *ast_include_find(struct ast_config *conf, const char *included_file);
1051 void localized_ast_include_rename(struct ast_config *conf, const char *from_file, const char *to_file);
1052 
1053 static struct ast_variable *ast_variable_new(const char *name, const char *value, const char *filename);
1054 
1055 static struct ast_variable *ast_variable_new(const char *name, const char *value, const char *filename)
1056 {
1057  struct ast_variable *variable;
1058  int name_len = strlen(name) + 1;
1059  size_t value_len = strlen(value) + 1;
1060  size_t filename_len = strlen(filename) + 1;
1061 
1062  if ((variable = ast_calloc(1, name_len + value_len + filename_len + sizeof(*variable)))) {
1063  variable->name = variable->stuff;
1064  variable->value = variable->stuff + name_len;
1065  variable->file = variable->value + value_len;
1066  strcpy(variable->name,name);
1067  ast_copy_string(variable->value, value, value_len);
1068  ast_copy_string(variable->file, filename, filename_len);
1069  }
1070 
1071  return variable;
1072 }
1073 
1074 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)
1075 {
1076  /* a file should be included ONCE. Otherwise, if one of the instances is changed,
1077  then all be changed. -- how do we know to include it? -- Handling modified
1078  instances is possible, I'd have
1079  to create a new master for each instance. */
1080  struct ast_config_include *inc;
1081 
1082  inc = ast_include_find(conf, included_file);
1083  if (inc)
1084  {
1085  inc->inclusion_count++;
1086  snprintf(real_included_file_name, real_included_file_name_size, "%s~~%d", included_file, inc->inclusion_count);
1087  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);
1088  } else
1089  *real_included_file_name = 0;
1090 
1091  inc = ast_calloc(1,sizeof(struct ast_config_include));
1092  inc->include_location_file = ast_strdup(from_file);
1093  inc->include_location_lineno = from_lineno;
1094  if (!ast_strlen_zero(real_included_file_name))
1095  inc->included_file = ast_strdup(real_included_file_name);
1096  else
1097  inc->included_file = ast_strdup(included_file);
1098 
1099  inc->exec = is_exec;
1100  if (is_exec)
1101  inc->exec_file = ast_strdup(exec_file);
1102 
1103  /* attach this new struct to the conf struct */
1104  inc->next = conf->includes;
1105  conf->includes = inc;
1106 
1107  return inc;
1108 }
1109 
1110 void localized_ast_include_rename(struct ast_config *conf, const char *from_file, const char *to_file)
1111 {
1112  struct ast_config_include *incl;
1113  struct ast_category *cat;
1114  struct ast_variable *v;
1115 
1116  int from_len = strlen(from_file);
1117  int to_len = strlen(to_file);
1118 
1119  if (strcmp(from_file, to_file) == 0) /* no use wasting time if the name is the same */
1120  return;
1121 
1122  /* the manager code allows you to read in one config file, then
1123  write it back out under a different name. But, the new arrangement
1124  ties output lines to the file name. So, before you try to write
1125  the config file to disk, better riffle thru the data and make sure
1126  the file names are changed.
1127  */
1128  /* file names are on categories, includes (of course), and on variables. So,
1129  traverse all this and swap names */
1130 
1131  for (incl = conf->includes; incl; incl=incl->next) {
1132  if (strcmp(incl->include_location_file,from_file) == 0) {
1133  if (from_len >= to_len)
1134  strcpy(incl->include_location_file, to_file);
1135  else {
1136  free(incl->include_location_file);
1137  incl->include_location_file = strdup(to_file);
1138  }
1139  }
1140  }
1141  for (cat = conf->root; cat; cat = cat->next) {
1142  if (strcmp(cat->file,from_file) == 0) {
1143  if (from_len >= to_len)
1144  strcpy(cat->file, to_file);
1145  else {
1146  free(cat->file);
1147  cat->file = strdup(to_file);
1148  }
1149  }
1150  for (v = cat->root; v; v = v->next) {
1151  if (strcmp(v->file,from_file) == 0) {
1152  if (from_len >= to_len)
1153  strcpy(v->file, to_file);
1154  else {
1155  free(v->file);
1156  v->file = strdup(to_file);
1157  }
1158  }
1159  }
1160  }
1161 }
1162 
1163 static struct ast_config_include *ast_include_find(struct ast_config *conf, const char *included_file)
1164 {
1165  struct ast_config_include *x;
1166  for (x=conf->includes;x;x=x->next)
1167  {
1168  if (strcmp(x->included_file,included_file) == 0)
1169  return x;
1170  }
1171  return 0;
1172 }
1173 
1174 
1175 static void ast_variable_append(struct ast_category *category, struct ast_variable *variable);
1176 
1177 static void ast_variable_append(struct ast_category *category, struct ast_variable *variable)
1178 {
1179  if (!variable)
1180  return;
1181  if (category->last)
1182  category->last->next = variable;
1183  else
1184  category->root = variable;
1185  category->last = variable;
1186  while (category->last->next)
1187  category->last = category->last->next;
1188 }
1189 
1190 static struct ast_category *category_get(const struct ast_config *config, const char *category_name, int ignored);
1191 
1192 static struct ast_category *category_get(const struct ast_config *config, const char *category_name, int ignored)
1193 {
1194  struct ast_category *cat;
1195 
1196  /* try exact match first, then case-insensitive match */
1197  for (cat = config->root; cat; cat = cat->next) {
1198  if (cat->name == category_name && (ignored || !cat->ignored))
1199  return cat;
1200  }
1201 
1202  for (cat = config->root; cat; cat = cat->next) {
1203  if (!strcasecmp(cat->name, category_name) && (ignored || !cat->ignored))
1204  return cat;
1205  }
1206 
1207  return NULL;
1208 }
1209 
1210 static struct ast_category *ast_category_get(const struct ast_config *config, const char *category_name)
1211 {
1212  return category_get(config, category_name, 0);
1213 }
1214 
1215 static struct ast_variable *ast_variable_browse(const struct ast_config *config, const char *category)
1216 {
1217  struct ast_category *cat = NULL;
1218 
1219  if (category && config->last_browse && (config->last_browse->name == category))
1220  cat = config->last_browse;
1221  else
1222  cat = ast_category_get(config, category);
1223 
1224  return (cat) ? cat->root : NULL;
1225 }
1226 
1227 static const char *ast_variable_retrieve(const struct ast_config *config, const char *category, const char *variable)
1228 {
1229  struct ast_variable *v;
1230 
1231  if (category) {
1232  for (v = ast_variable_browse(config, category); v; v = v->next) {
1233  if (!strcasecmp(variable, v->name))
1234  return v->value;
1235  }
1236  } else {
1237  struct ast_category *cat;
1238 
1239  for (cat = config->root; cat; cat = cat->next)
1240  for (v = cat->root; v; v = v->next)
1241  if (!strcasecmp(variable, v->name))
1242  return v->value;
1243  }
1244 
1245  return NULL;
1246 }
1247 
1248 static struct ast_variable *variable_clone(const struct ast_variable *old)
1249 {
1250  struct ast_variable *new = ast_variable_new(old->name, old->value, old->file);
1251 
1252  if (new) {
1253  new->lineno = old->lineno;
1254  new->object = old->object;
1255  new->blanklines = old->blanklines;
1256  /* TODO: clone comments? */
1257  }
1258 
1259  return new;
1260 }
1261 
1262 static void ast_variables_destroy(struct ast_variable *v)
1263 {
1264  struct ast_variable *vn;
1265 
1266  while (v) {
1267  vn = v;
1268  v = v->next;
1269  free(vn);
1270  }
1271 }
1272 
1273 static void ast_includes_destroy(struct ast_config_include *incls)
1274 {
1275  struct ast_config_include *incl,*inclnext;
1276 
1277  for (incl=incls; incl; incl = inclnext) {
1278  inclnext = incl->next;
1279  if (incl->include_location_file)
1280  free(incl->include_location_file);
1281  if (incl->exec_file)
1282  free(incl->exec_file);
1283  if (incl->included_file)
1284  free(incl->included_file);
1285  free(incl);
1286  }
1287 }
1288 
1289 static void ast_config_destroy(struct ast_config *cfg)
1290 {
1291  struct ast_category *cat, *catn;
1292 
1293  if (!cfg)
1294  return;
1295 
1296  ast_includes_destroy(cfg->includes);
1297 
1298  cat = cfg->root;
1299  while (cat) {
1301  catn = cat;
1302  cat = cat->next;
1303  free(catn);
1304  }
1305  free(cfg);
1306 }
1307 
1309  /*! Allow \#exec in config files */
1311  /*! Do not fork() */
1313  /*! Keep quiet */
1315  /*! Console mode */
1317  /*! Run in realtime Linux priority */
1319  /*! Initialize keys for RSA authentication */
1321  /*! Remote console */
1323  /*! Execute an asterisk CLI command upon startup */
1324  AST_OPT_FLAG_EXEC = (1 << 7),
1325  /*! Don't use termcap colors */
1327  /*! Are we fully started yet? */
1329  /*! Trascode via signed linear */
1331  /*! Dump core on a seg fault */
1333  /*! Cache sound files */
1335  /*! Display timestamp in CLI verbose output */
1337  /*! Override config */
1339  /*! Reconnect */
1341  /*! Transmit Silence during Record() and DTMF Generation */
1343  /*! Suppress some warnings */
1345  /*! Always fork, even if verbose or debug settings are non-zero */
1347  /*! Disable log/verbose output to remote consoles */
1348  AST_OPT_FLAG_MUTE = (1 << 22),
1349  /*! There is a per-file debug setting */
1351  /*! Terminal colors should be adjusted for a light-colored background */
1353  /*! Force black background */
1355 };
1356 
1357 /* options.h declares ast_options extern; I need it static? */
1358 #define AST_CACHE_DIR_LEN 512
1359 #define AST_FILENAME_MAX 80
1360 
1361 /*! These are the options that set by default when Asterisk starts */
1362 #define AST_DEFAULT_OPTIONS AST_OPT_FLAG_TRANSCODE_VIA_SLIN
1363 
1364 struct ast_flags ast_options = { AST_DEFAULT_OPTIONS };
1365 
1366 #define ast_opt_exec_includes ast_test_flag(&ast_options, AST_OPT_FLAG_EXEC_INCLUDES)
1367 #define ast_opt_no_fork ast_test_flag(&ast_options, AST_OPT_FLAG_NO_FORK)
1368 #define ast_opt_quiet ast_test_flag(&ast_options, AST_OPT_FLAG_QUIET)
1369 #define ast_opt_console ast_test_flag(&ast_options, AST_OPT_FLAG_CONSOLE)
1370 #define ast_opt_high_priority ast_test_flag(&ast_options, AST_OPT_FLAG_HIGH_PRIORITY)
1371 #define ast_opt_init_keys ast_test_flag(&ast_options, AST_OPT_FLAG_INIT_KEYS)
1372 #define ast_opt_remote ast_test_flag(&ast_options, AST_OPT_FLAG_REMOTE)
1373 #define ast_opt_exec ast_test_flag(&ast_options, AST_OPT_FLAG_EXEC)
1374 #define ast_opt_no_color ast_test_flag(&ast_options, AST_OPT_FLAG_NO_COLOR)
1375 #define ast_fully_booted ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)
1376 #define ast_opt_transcode_via_slin ast_test_flag(&ast_options, AST_OPT_FLAG_TRANSCODE_VIA_SLIN)
1377 #define ast_opt_priority_jumping ast_test_flag(&ast_options, AST_OPT_FLAG_PRIORITY_JUMPING)
1378 #define ast_opt_dump_core ast_test_flag(&ast_options, AST_OPT_FLAG_DUMP_CORE)
1379 #define ast_opt_cache_record_files ast_test_flag(&ast_options, AST_OPT_FLAG_CACHE_RECORD_FILES)
1380 #define ast_opt_timestamp ast_test_flag(&ast_options, AST_OPT_FLAG_TIMESTAMP)
1381 #define ast_opt_override_config ast_test_flag(&ast_options, AST_OPT_FLAG_OVERRIDE_CONFIG)
1382 #define ast_opt_reconnect ast_test_flag(&ast_options, AST_OPT_FLAG_RECONNECT)
1383 #define ast_opt_transmit_silence ast_test_flag(&ast_options, AST_OPT_FLAG_TRANSMIT_SILENCE)
1384 #define ast_opt_dont_warn ast_test_flag(&ast_options, AST_OPT_FLAG_DONT_WARN)
1385 #define ast_opt_always_fork ast_test_flag(&ast_options, AST_OPT_FLAG_ALWAYS_FORK)
1386 #define ast_opt_mute ast_test_flag(&ast_options, AST_OPT_FLAG_MUTE)
1387 
1388 extern int option_verbose;
1389 extern int option_debug; /*!< Debugging */
1390 extern int ast_option_maxcalls; /*!< Maximum number of simultaneous channels */
1391 extern double ast_option_maxload;
1392 extern char ast_defaultlanguage[];
1393 
1394 extern pid_t ast_mainpid;
1395 
1396 extern char record_cache_dir[AST_CACHE_DIR_LEN];
1397 extern char debug_filename[AST_FILENAME_MAX];
1398 
1399 extern int ast_language_is_prefix;
1400 
1401 
1402 
1403 /* linkedlists.h */
1404 
1405 /*!
1406  \brief Write locks a list.
1407  \param head This is a pointer to the list head structure
1408 
1409  This macro attempts to place an exclusive write lock in the
1410  list head structure pointed to by head.
1411  Returns non-zero on success, 0 on failure
1412 */
1413 #define AST_RWLIST_WRLOCK(head) \
1414  ast_rwlock_wrlock(&(head)->lock)
1415 
1416 /*!
1417  \brief Read locks a list.
1418  \param head This is a pointer to the list head structure
1419 
1420  This macro attempts to place a read lock in the
1421  list head structure pointed to by head.
1422  Returns non-zero on success, 0 on failure
1423 */
1424 #define AST_RWLIST_RDLOCK(head) \
1425  ast_rwlock_rdlock(&(head)->lock)
1426 
1427 /*!
1428  \brief Attempts to unlock a read/write based list.
1429  \param head This is a pointer to the list head structure
1430 
1431  This macro attempts to remove a read or write lock from the
1432  list head structure pointed to by head. If the list
1433  was not locked by this thread, this macro has no effect.
1434 */
1435 #define AST_RWLIST_UNLOCK(head) \
1436  ast_rwlock_unlock(&(head)->lock)
1437 
1438 /*!
1439  \brief Defines a structure to be used to hold a list of specified type.
1440  \param name This will be the name of the defined structure.
1441  \param type This is the type of each list entry.
1442 
1443  This macro creates a structure definition that can be used
1444  to hold a list of the entries of type \a type. It does not actually
1445  declare (allocate) a structure; to do that, either follow this
1446  macro with the desired name of the instance you wish to declare,
1447  or use the specified \a name to declare instances elsewhere.
1448 
1449  Example usage:
1450  \code
1451  static AST_LIST_HEAD(entry_list, entry) entries;
1452  \endcode
1453 
1454  This would define \c struct \c entry_list, and declare an instance of it named
1455  \a entries, all intended to hold a list of type \c struct \c entry.
1456 */
1457 #define AST_LIST_HEAD(name, type) \
1458 struct name { \
1459  struct type *first; \
1460  struct type *last; \
1461  ast_mutex_t lock; \
1462 }
1463 
1464 /*!
1465  \brief Defines a structure to be used to hold a read/write list of specified type.
1466  \param name This will be the name of the defined structure.
1467  \param type This is the type of each list entry.
1468 
1469  This macro creates a structure definition that can be used
1470  to hold a list of the entries of type \a type. It does not actually
1471  declare (allocate) a structure; to do that, either follow this
1472  macro with the desired name of the instance you wish to declare,
1473  or use the specified \a name to declare instances elsewhere.
1474 
1475  Example usage:
1476  \code
1477  static AST_RWLIST_HEAD(entry_list, entry) entries;
1478  \endcode
1479 
1480  This would define \c struct \c entry_list, and declare an instance of it named
1481  \a entries, all intended to hold a list of type \c struct \c entry.
1482 */
1483 #define AST_RWLIST_HEAD(name, type) \
1484 struct name { \
1485  struct type *first; \
1486  struct type *last; \
1487  ast_rwlock_t lock; \
1488 }
1489 
1490 /*!
1491  \brief Defines a structure to be used to hold a list of specified type (with no lock).
1492  \param name This will be the name of the defined structure.
1493  \param type This is the type of each list entry.
1494 
1495  This macro creates a structure definition that can be used
1496  to hold a list of the entries of type \a type. It does not actually
1497  declare (allocate) a structure; to do that, either follow this
1498  macro with the desired name of the instance you wish to declare,
1499  or use the specified \a name to declare instances elsewhere.
1500 
1501  Example usage:
1502  \code
1503  static AST_LIST_HEAD_NOLOCK(entry_list, entry) entries;
1504  \endcode
1505 
1506  This would define \c struct \c entry_list, and declare an instance of it named
1507  \a entries, all intended to hold a list of type \c struct \c entry.
1508 */
1509 #define AST_LIST_HEAD_NOLOCK(name, type) \
1510 struct name { \
1511  struct type *first; \
1512  struct type *last; \
1513 }
1514 
1515 /*!
1516  \brief Defines initial values for a declaration of AST_LIST_HEAD
1517 */
1518 #define AST_LIST_HEAD_INIT_VALUE { \
1519  .first = NULL, \
1520  .last = NULL, \
1521  .lock = AST_MUTEX_INIT_VALUE, \
1522  }
1523 
1524 /*!
1525  \brief Defines initial values for a declaration of AST_RWLIST_HEAD
1526 */
1527 #define AST_RWLIST_HEAD_INIT_VALUE { \
1528  .first = NULL, \
1529  .last = NULL, \
1530  .lock = AST_RWLOCK_INIT_VALUE, \
1531  }
1532 
1533 /*!
1534  \brief Defines initial values for a declaration of AST_LIST_HEAD_NOLOCK
1535 */
1536 #define AST_LIST_HEAD_NOLOCK_INIT_VALUE { \
1537  .first = NULL, \
1538  .last = NULL, \
1539  }
1540 
1541 /*!
1542  \brief Defines a structure to be used to hold a list of specified type, statically initialized.
1543  \param name This will be the name of the defined structure.
1544  \param type This is the type of each list entry.
1545 
1546  This macro creates a structure definition that can be used
1547  to hold a list of the entries of type \a type, and allocates an instance
1548  of it, initialized to be empty.
1549 
1550  Example usage:
1551  \code
1552  static AST_LIST_HEAD_STATIC(entry_list, entry);
1553  \endcode
1554 
1555  This would define \c struct \c entry_list, intended to hold a list of
1556  type \c struct \c entry.
1557 */
1558 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
1559 #define AST_LIST_HEAD_STATIC(name, type) \
1560 struct name { \
1561  struct type *first; \
1562  struct type *last; \
1563  ast_mutex_t lock; \
1564 } name; \
1565 static void __attribute__((constructor)) init_##name(void) \
1566 { \
1567  AST_LIST_HEAD_INIT(&name); \
1568 } \
1569 static void __attribute__((destructor)) fini_##name(void) \
1570 { \
1571  AST_LIST_HEAD_DESTROY(&name); \
1572 } \
1573 struct __dummy_##name
1574 #else
1575 #define AST_LIST_HEAD_STATIC(name, type) \
1576 struct name { \
1577  struct type *first; \
1578  struct type *last; \
1579  ast_mutex_t lock; \
1580 } name = AST_LIST_HEAD_INIT_VALUE
1581 #endif
1582 
1583 /*!
1584  \brief Defines a structure to be used to hold a read/write list of specified type, statically initialized.
1585  \param name This will be the name of the defined structure.
1586  \param type This is the type of each list entry.
1587 
1588  This macro creates a structure definition that can be used
1589  to hold a list of the entries of type \a type, and allocates an instance
1590  of it, initialized to be empty.
1591 
1592  Example usage:
1593  \code
1594  static AST_RWLIST_HEAD_STATIC(entry_list, entry);
1595  \endcode
1596 
1597  This would define \c struct \c entry_list, intended to hold a list of
1598  type \c struct \c entry.
1599 */
1600 #ifndef AST_RWLOCK_INIT_VALUE
1601 #define AST_RWLIST_HEAD_STATIC(name, type) \
1602 struct name { \
1603  struct type *first; \
1604  struct type *last; \
1605  ast_rwlock_t lock; \
1606 } name; \
1607 static void __attribute__((constructor)) init_##name(void) \
1608 { \
1609  AST_RWLIST_HEAD_INIT(&name); \
1610 } \
1611 static void __attribute__((destructor)) fini_##name(void) \
1612 { \
1613  AST_RWLIST_HEAD_DESTROY(&name); \
1614 } \
1615 struct __dummy_##name
1616 #else
1617 #define AST_RWLIST_HEAD_STATIC(name, type) \
1618 struct name { \
1619  struct type *first; \
1620  struct type *last; \
1621  ast_rwlock_t lock; \
1622 } name = AST_RWLIST_HEAD_INIT_VALUE
1623 #endif
1624 
1625 /*!
1626  \brief Defines a structure to be used to hold a list of specified type, statically initialized.
1627 
1628  This is the same as AST_LIST_HEAD_STATIC, except without the lock included.
1629 */
1630 #define AST_LIST_HEAD_NOLOCK_STATIC(name, type) \
1631 struct name { \
1632  struct type *first; \
1633  struct type *last; \
1634 } name = AST_LIST_HEAD_NOLOCK_INIT_VALUE
1635 
1636 /*!
1637  \brief Initializes a list head structure with a specified first entry.
1638  \param head This is a pointer to the list head structure
1639  \param entry pointer to the list entry that will become the head of the list
1640 
1641  This macro initializes a list head structure by setting the head
1642  entry to the supplied value and recreating the embedded lock.
1643 */
1644 #define AST_LIST_HEAD_SET(head, entry) do { \
1645  (head)->first = (entry); \
1646  (head)->last = (entry); \
1647  ast_mutex_init(&(head)->lock); \
1648 } while (0)
1649 
1650 /*!
1651  \brief Initializes an rwlist head structure with a specified first entry.
1652  \param head This is a pointer to the list head structure
1653  \param entry pointer to the list entry that will become the head of the list
1654 
1655  This macro initializes a list head structure by setting the head
1656  entry to the supplied value and recreating the embedded lock.
1657 */
1658 #define AST_RWLIST_HEAD_SET(head, entry) do { \
1659  (head)->first = (entry); \
1660  (head)->last = (entry); \
1661  ast_rwlock_init(&(head)->lock); \
1662 } while (0)
1663 
1664 /*!
1665  \brief Initializes a list head structure with a specified first entry.
1666  \param head This is a pointer to the list head structure
1667  \param entry pointer to the list entry that will become the head of the list
1668 
1669  This macro initializes a list head structure by setting the head
1670  entry to the supplied value.
1671 */
1672 #define AST_LIST_HEAD_SET_NOLOCK(head, entry) do { \
1673  (head)->first = (entry); \
1674  (head)->last = (entry); \
1675 } while (0)
1676 
1677 /*!
1678  \brief Declare a forward link structure inside a list entry.
1679  \param type This is the type of each list entry.
1680 
1681  This macro declares a structure to be used to link list entries together.
1682  It must be used inside the definition of the structure named in
1683  \a type, as follows:
1684 
1685  \code
1686  struct list_entry {
1687  ...
1688  AST_LIST_ENTRY(list_entry) list;
1689  }
1690  \endcode
1691 
1692  The field name \a list here is arbitrary, and can be anything you wish.
1693 */
1694 #define AST_LIST_ENTRY(type) \
1695 struct { \
1696  struct type *next; \
1697 }
1698 
1699 #define AST_RWLIST_ENTRY AST_LIST_ENTRY
1700 
1701 /*!
1702  \brief Returns the first entry contained in a list.
1703  \param head This is a pointer to the list head structure
1704  */
1705 #define AST_LIST_FIRST(head) ((head)->first)
1706 
1707 #define AST_RWLIST_FIRST AST_LIST_FIRST
1708 
1709 /*!
1710  \brief Returns the last entry contained in a list.
1711  \param head This is a pointer to the list head structure
1712  */
1713 #define AST_LIST_LAST(head) ((head)->last)
1714 
1715 #define AST_RWLIST_LAST AST_LIST_LAST
1716 
1717 /*!
1718  \brief Returns the next entry in the list after the given entry.
1719  \param elm This is a pointer to the current entry.
1720  \param field This is the name of the field (declared using AST_LIST_ENTRY())
1721  used to link entries of this list together.
1722 */
1723 #define AST_LIST_NEXT(elm, field) ((elm)->field.next)
1724 
1725 #define AST_RWLIST_NEXT AST_LIST_NEXT
1726 
1727 /*!
1728  \brief Checks whether the specified list contains any entries.
1729  \param head This is a pointer to the list head structure
1730 
1731  Returns non-zero if the list has entries, zero if not.
1732  */
1733 #define AST_LIST_EMPTY(head) (AST_LIST_FIRST(head) == NULL)
1734 
1735 #define AST_RWLIST_EMPTY AST_LIST_EMPTY
1736 
1737 /*!
1738  \brief Loops over (traverses) the entries in a list.
1739  \param head This is a pointer to the list head structure
1740  \param var This is the name of the variable that will hold a pointer to the
1741  current list entry on each iteration. It must be declared before calling
1742  this macro.
1743  \param field This is the name of the field (declared using AST_LIST_ENTRY())
1744  used to link entries of this list together.
1745 
1746  This macro is use to loop over (traverse) the entries in a list. It uses a
1747  \a for loop, and supplies the enclosed code with a pointer to each list
1748  entry as it loops. It is typically used as follows:
1749  \code
1750  static AST_LIST_HEAD(entry_list, list_entry) entries;
1751  ...
1752  struct list_entry {
1753  ...
1754  AST_LIST_ENTRY(list_entry) list;
1755  }
1756  ...
1757  struct list_entry *current;
1758  ...
1759  AST_LIST_TRAVERSE(&entries, current, list) {
1760  (do something with current here)
1761  }
1762  \endcode
1763  \warning If you modify the forward-link pointer contained in the \a current entry while
1764  inside the loop, the behavior will be unpredictable. At a minimum, the following
1765  macros will modify the forward-link pointer, and should not be used inside
1766  AST_LIST_TRAVERSE() against the entry pointed to by the \a current pointer without
1767  careful consideration of their consequences:
1768  \li AST_LIST_NEXT() (when used as an lvalue)
1769  \li AST_LIST_INSERT_AFTER()
1770  \li AST_LIST_INSERT_HEAD()
1771  \li AST_LIST_INSERT_TAIL()
1772 */
1773 #define AST_LIST_TRAVERSE(head,var,field) \
1774  for((var) = (head)->first; (var); (var) = (var)->field.next)
1775 
1776 #define AST_RWLIST_TRAVERSE AST_LIST_TRAVERSE
1777 
1778 /*!
1779  \brief Loops safely over (traverses) the entries in a list.
1780  \param head This is a pointer to the list head structure
1781  \param var This is the name of the variable that will hold a pointer to the
1782  current list entry on each iteration. It must be declared before calling
1783  this macro.
1784  \param field This is the name of the field (declared using AST_LIST_ENTRY())
1785  used to link entries of this list together.
1786 
1787  This macro is used to safely loop over (traverse) the entries in a list. It
1788  uses a \a for loop, and supplies the enclosed code with a pointer to each list
1789  entry as it loops. It is typically used as follows:
1790 
1791  \code
1792  static AST_LIST_HEAD(entry_list, list_entry) entries;
1793  ...
1794  struct list_entry {
1795  ...
1796  AST_LIST_ENTRY(list_entry) list;
1797  }
1798  ...
1799  struct list_entry *current;
1800  ...
1801  AST_LIST_TRAVERSE_SAFE_BEGIN(&entries, current, list) {
1802  (do something with current here)
1803  }
1804  AST_LIST_TRAVERSE_SAFE_END;
1805  \endcode
1806 
1807  It differs from AST_LIST_TRAVERSE() in that the code inside the loop can modify
1808  (or even free, after calling AST_LIST_REMOVE_CURRENT()) the entry pointed to by
1809  the \a current pointer without affecting the loop traversal.
1810 */
1811 #define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field) { \
1812  typeof((head)->first) __list_next; \
1813  typeof((head)->first) __list_prev = NULL; \
1814  typeof((head)->first) __new_prev = NULL; \
1815  for ((var) = (head)->first, __new_prev = (var), \
1816  __list_next = (var) ? (var)->field.next : NULL; \
1817  (var); \
1818  __list_prev = __new_prev, (var) = __list_next, \
1819  __new_prev = (var), \
1820  __list_next = (var) ? (var)->field.next : NULL \
1821  )
1822 
1823 #define AST_RWLIST_TRAVERSE_SAFE_BEGIN AST_LIST_TRAVERSE_SAFE_BEGIN
1824 
1825 /*!
1826  \brief Removes the \a current entry from a list during a traversal.
1827  \param head This is a pointer to the list head structure
1828  \param field This is the name of the field (declared using AST_LIST_ENTRY())
1829  used to link entries of this list together.
1830 
1831  \note This macro can \b only be used inside an AST_LIST_TRAVERSE_SAFE_BEGIN()
1832  block; it is used to unlink the current entry from the list without affecting
1833  the list traversal (and without having to re-traverse the list to modify the
1834  previous entry, if any).
1835  */
1836 #define AST_LIST_REMOVE_CURRENT(head, field) \
1837  __new_prev->field.next = NULL; \
1838  __new_prev = __list_prev; \
1839  if (__list_prev) \
1840  __list_prev->field.next = __list_next; \
1841  else \
1842  (head)->first = __list_next; \
1843  if (!__list_next) \
1844  (head)->last = __list_prev;
1845 
1846 #define AST_RWLIST_REMOVE_CURRENT AST_LIST_REMOVE_CURRENT
1847 
1848 /*!
1849  \brief Inserts a list entry before the current entry during a traversal.
1850  \param head This is a pointer to the list head structure
1851  \param elm This is a pointer to the entry to be inserted.
1852  \param field This is the name of the field (declared using AST_LIST_ENTRY())
1853  used to link entries of this list together.
1854 
1855  \note This macro can \b only be used inside an AST_LIST_TRAVERSE_SAFE_BEGIN()
1856  block.
1857  */
1858 #define AST_LIST_INSERT_BEFORE_CURRENT(head, elm, field) do { \
1859  if (__list_prev) { \
1860  (elm)->field.next = __list_prev->field.next; \
1861  __list_prev->field.next = elm; \
1862  } else { \
1863  (elm)->field.next = (head)->first; \
1864  (head)->first = (elm); \
1865  } \
1866  __new_prev = (elm); \
1867 } while (0)
1868 
1869 #define AST_RWLIST_INSERT_BEFORE_CURRENT AST_LIST_INSERT_BEFORE_CURRENT
1870 
1871 /*!
1872  \brief Closes a safe loop traversal block.
1873  */
1874 #define AST_LIST_TRAVERSE_SAFE_END }
1875 
1876 #define AST_RWLIST_TRAVERSE_SAFE_END AST_LIST_TRAVERSE_SAFE_END
1877 
1878 /*!
1879  \brief Initializes a list head structure.
1880  \param head This is a pointer to the list head structure
1881 
1882  This macro initializes a list head structure by setting the head
1883  entry to \a NULL (empty list) and recreating the embedded lock.
1884 */
1885 #define AST_LIST_HEAD_INIT(head) { \
1886  (head)->first = NULL; \
1887  (head)->last = NULL; \
1888  ast_mutex_init(&(head)->lock); \
1889 }
1890 
1891 /*!
1892  \brief Initializes an rwlist head structure.
1893  \param head This is a pointer to the list head structure
1894 
1895  This macro initializes a list head structure by setting the head
1896  entry to \a NULL (empty list) and recreating the embedded lock.
1897 */
1898 #define AST_RWLIST_HEAD_INIT(head) { \
1899  (head)->first = NULL; \
1900  (head)->last = NULL; \
1901  ast_rwlock_init(&(head)->lock); \
1902 }
1903 
1904 /*!
1905  \brief Destroys an rwlist head structure.
1906  \param head This is a pointer to the list head structure
1907 
1908  This macro destroys a list head structure by setting the head
1909  entry to \a NULL (empty list) and destroying the embedded lock.
1910  It does not free the structure from memory.
1911 */
1912 #define AST_RWLIST_HEAD_DESTROY(head) { \
1913  (head)->first = NULL; \
1914  (head)->last = NULL; \
1915  ast_rwlock_destroy(&(head)->lock); \
1916 }
1917 
1918 /*!
1919  \brief Initializes a list head structure.
1920  \param head This is a pointer to the list head structure
1921 
1922  This macro initializes a list head structure by setting the head
1923  entry to \a NULL (empty list). There is no embedded lock handling
1924  with this macro.
1925 */
1926 #define AST_LIST_HEAD_INIT_NOLOCK(head) { \
1927  (head)->first = NULL; \
1928  (head)->last = NULL; \
1929 }
1930 
1931 /*!
1932  \brief Inserts a list entry after a given entry.
1933  \param head This is a pointer to the list head structure
1934  \param listelm This is a pointer to the entry after which the new entry should
1935  be inserted.
1936  \param elm This is a pointer to the entry to be inserted.
1937  \param field This is the name of the field (declared using AST_LIST_ENTRY())
1938  used to link entries of this list together.
1939  */
1940 #define AST_LIST_INSERT_AFTER(head, listelm, elm, field) do { \
1941  (elm)->field.next = (listelm)->field.next; \
1942  (listelm)->field.next = (elm); \
1943  if ((head)->last == (listelm)) \
1944  (head)->last = (elm); \
1945 } while (0)
1946 
1947 #define AST_RWLIST_INSERT_AFTER AST_LIST_INSERT_AFTER
1948 
1949 /*!
1950  \brief Inserts a list entry at the head of a list.
1951  \param head This is a pointer to the list head structure
1952  \param elm This is a pointer to the entry to be inserted.
1953  \param field This is the name of the field (declared using AST_LIST_ENTRY())
1954  used to link entries of this list together.
1955  */
1956 #define AST_LIST_INSERT_HEAD(head, elm, field) do { \
1957  (elm)->field.next = (head)->first; \
1958  (head)->first = (elm); \
1959  if (!(head)->last) \
1960  (head)->last = (elm); \
1961 } while (0)
1962 
1963 #define AST_RWLIST_INSERT_HEAD AST_LIST_INSERT_HEAD
1964 
1965 /*!
1966  \brief Appends a list entry to the tail of a list.
1967  \param head This is a pointer to the list head structure
1968  \param elm This is a pointer to the entry to be appended.
1969  \param field This is the name of the field (declared using AST_LIST_ENTRY())
1970  used to link entries of this list together.
1971 
1972  Note: The link field in the appended entry is \b not modified, so if it is
1973  actually the head of a list itself, the entire list will be appended
1974  temporarily (until the next AST_LIST_INSERT_TAIL is performed).
1975  */
1976 #define AST_LIST_INSERT_TAIL(head, elm, field) do { \
1977  if (!(head)->first) { \
1978  (head)->first = (elm); \
1979  (head)->last = (elm); \
1980  } else { \
1981  (head)->last->field.next = (elm); \
1982  (head)->last = (elm); \
1983  } \
1984 } while (0)
1985 
1986 #define AST_RWLIST_INSERT_TAIL AST_LIST_INSERT_TAIL
1987 
1988 /*!
1989  \brief Appends a whole list to the tail of a list.
1990  \param head This is a pointer to the list head structure
1991  \param list This is a pointer to the list to be appended.
1992  \param field This is the name of the field (declared using AST_LIST_ENTRY())
1993  used to link entries of this list together.
1994  */
1995 #define AST_LIST_APPEND_LIST(head, list, field) do { \
1996  if (!(head)->first) { \
1997  (head)->first = (list)->first; \
1998  (head)->last = (list)->last; \
1999  } else { \
2000  (head)->last->field.next = (list)->first; \
2001  (head)->last = (list)->last; \
2002  } \
2003 } while (0)
2004 
2005 #define AST_RWLIST_APPEND_LIST AST_LIST_APPEND_LIST
2006 
2007 /*!
2008  \brief Removes and returns the head entry from a list.
2009  \param head This is a pointer to the list head structure
2010  \param field This is the name of the field (declared using AST_LIST_ENTRY())
2011  used to link entries of this list together.
2012 
2013  Removes the head entry from the list, and returns a pointer to it.
2014  This macro is safe to call on an empty list.
2015  */
2016 #define AST_LIST_REMOVE_HEAD(head, field) ({ \
2017  typeof((head)->first) cur = (head)->first; \
2018  if (cur) { \
2019  (head)->first = cur->field.next; \
2020  cur->field.next = NULL; \
2021  if ((head)->last == cur) \
2022  (head)->last = NULL; \
2023  } \
2024  cur; \
2025  })
2026 
2027 #define AST_RWLIST_REMOVE_HEAD AST_LIST_REMOVE_HEAD
2028 
2029 /*!
2030  \brief Removes a specific entry from a list.
2031  \param head This is a pointer to the list head structure
2032  \param elm This is a pointer to the entry to be removed.
2033  \param field This is the name of the field (declared using AST_LIST_ENTRY())
2034  used to link entries of this list together.
2035  \warning The removed entry is \b not freed nor modified in any way.
2036  */
2037 #define AST_LIST_REMOVE(head, elm, field) do { \
2038  if ((head)->first == (elm)) { \
2039  (head)->first = (elm)->field.next; \
2040  if ((head)->last == (elm)) \
2041  (head)->last = NULL; \
2042  } else { \
2043  typeof(elm) curelm = (head)->first; \
2044  while (curelm && (curelm->field.next != (elm))) \
2045  curelm = curelm->field.next; \
2046  if (curelm) { \
2047  curelm->field.next = (elm)->field.next; \
2048  if ((head)->last == (elm)) \
2049  (head)->last = curelm; \
2050  } \
2051  } \
2052  (elm)->field.next = NULL; \
2053 } while (0)
2054 
2055 #define AST_RWLIST_REMOVE AST_LIST_REMOVE
2056 
2057 /* chanvars.h */
2058 
2059 struct ast_var_t {
2060  AST_LIST_ENTRY(ast_var_t) entries;
2061  char *value;
2062  char name[0];
2063 };
2064 
2066 
2067 AST_RWLOCK_DEFINE_STATIC(globalslock);
2068 static struct varshead globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
2069 
2070 
2071 /* IN CONFLICT: struct ast_var_t *ast_var_assign(const char *name, const char *value); */
2072 
2073 static struct ast_var_t *ast_var_assign(const char *name, const char *value);
2074 
2075 static void ast_var_delete(struct ast_var_t *var);
2076 
2077 /*from channel.h */
2078 #define AST_MAX_EXTENSION 80 /*!< Max length of an extension */
2079 
2080 
2081 /* from pbx.h */
2082 #define PRIORITY_HINT -1 /*!< Special Priority for a hint */
2083 
2085  AST_EXTENSION_REMOVED = -2, /*!< Extension removed */
2086  AST_EXTENSION_DEACTIVATED = -1, /*!< Extension hint removed */
2087  AST_EXTENSION_NOT_INUSE = 0, /*!< No device INUSE or BUSY */
2088  AST_EXTENSION_INUSE = 1 << 0, /*!< One or more devices INUSE */
2089  AST_EXTENSION_BUSY = 1 << 1, /*!< All devices BUSY */
2090  AST_EXTENSION_UNAVAILABLE = 1 << 2, /*!< All devices UNAVAILABLE/UNREGISTERED */
2091  AST_EXTENSION_RINGING = 1 << 3, /*!< All devices RINGING */
2092  AST_EXTENSION_ONHOLD = 1 << 4, /*!< All devices ONHOLD */
2093 };
2094 
2095 struct ast_custom_function {
2096  const char *name; /*!< Name */
2097  const char *synopsis; /*!< Short description for "show functions" */
2098  const char *desc; /*!< Help text that explains it all */
2099  const char *syntax; /*!< Syntax description */
2100  int (*read)(struct ast_channel *, const char *, char *, char *, size_t); /*!< Read function, if read is supported */
2101  int (*write)(struct ast_channel *, const char *, char *, const char *); /*!< Write function, if write is supported */
2102  AST_RWLIST_ENTRY(ast_custom_function) acflist;
2103 };
2104 
2105 typedef int (ast_switch_f)(struct ast_channel *chan, const char *context,
2106  const char *exten, int priority, const char *callerid, const char *data);
2107 
2108 struct ast_switch {
2109  AST_LIST_ENTRY(ast_switch) list;
2110  const char *name; /*!< Name of the switch */
2111  const char *description; /*!< Description of the switch */
2112 
2113  ast_switch_f *exists;
2114  ast_switch_f *canmatch;
2115  ast_switch_f *exec;
2116  ast_switch_f *matchmore;
2117 };
2118 
2119 
2120 static char *config_filename = "extensions.conf";
2121 static char *global_registrar = "conf2ael";
2122 static char userscontext[AST_MAX_EXTENSION] = "default";
2123 static int static_config = 0;
2124 static int write_protect_config = 1;
2125 static int autofallthrough_config = 0;
2126 static int clearglobalvars_config = 0;
2127 static void pbx_substitute_variables_helper(struct ast_channel *c,const char *cp1,char *cp2,int count);
2128 
2129 
2130 /* stolen from callerid.c */
2131 
2132 /*! \brief Clean up phone string
2133  * remove '(', ' ', ')', non-trailing '.', and '-' not in square brackets.
2134  * Basically, remove anything that could be invalid in a pattern.
2135  */
2136 static void ast_shrink_phone_number(char *n)
2137 {
2138  int x, y=0;
2139  int bracketed = 0;
2140 
2141  for (x=0; n[x]; x++) {
2142  switch(n[x]) {
2143  case '[':
2144  bracketed++;
2145  n[y++] = n[x];
2146  break;
2147  case ']':
2148  bracketed--;
2149  n[y++] = n[x];
2150  break;
2151  case '-':
2152  if (bracketed)
2153  n[y++] = n[x];
2154  break;
2155  case '.':
2156  if (!n[x+1])
2157  n[y++] = n[x];
2158  break;
2159  default:
2160  if (!strchr("()", n[x]))
2161  n[y++] = n[x];
2162  }
2163  }
2164  n[y] = '\0';
2165 }
2166 
2167 
2168 /* stolen from chanvars.c */
2169 
2170 static const char *ast_var_name(const struct ast_var_t *var)
2171 {
2172  const char *name;
2173 
2174  if (var == NULL || (name = var->name) == NULL)
2175  return NULL;
2176  /* Return the name without the initial underscores */
2177  if (name[0] == '_') {
2178  name++;
2179  if (name[0] == '_')
2180  name++;
2181  }
2182  return name;
2183 }
2184 
2185 /* experiment 1: see if it's easier just to use existing config code
2186  * to read in the extensions.conf file. In this scenario,
2187  I have to rip/copy code from other modules, because they
2188  are staticly declared as-is. A solution would be to move
2189  the ripped code to another location and make them available
2190  to other modules and standalones */
2191 
2192 /* Our own version of ast_log, since the expr parser uses it. -- stolen from utils/check_expr.c */
2193 
2194 static void ast_log(int level, const char *file, int line, const char *function, const char *fmt, ...)
2195 {
2196  va_list vars;
2197  va_start(vars,fmt);
2198 
2199  printf("LOG: lev:%d file:%s line:%d func: %s ",
2200  level, file, line, function);
2201  vprintf(fmt, vars);
2202  fflush(stdout);
2203  va_end(vars);
2204 }
2205 
2206 void __attribute__((format(printf, 1, 2))) ast_verbose(const char *fmt, ...)
2207 {
2208  va_list vars;
2209  va_start(vars,fmt);
2210 
2211  printf("VERBOSE: ");
2212  vprintf(fmt, vars);
2213  fflush(stdout);
2214  va_end(vars);
2215 }
2216 
2217 /* stolen from main/utils.c */
2218 static char *ast_process_quotes_and_slashes(char *start, char find, char replace_with)
2219 {
2220  char *dataPut = start;
2221  int inEscape = 0;
2222  int inQuotes = 0;
2223 
2224  for (; *start; start++) {
2225  if (inEscape) {
2226  *dataPut++ = *start; /* Always goes verbatim */
2227  inEscape = 0;
2228  } else {
2229  if (*start == '\\') {
2230  inEscape = 1; /* Do not copy \ into the data */
2231  } else if (*start == '\'') {
2232  inQuotes = 1 - inQuotes; /* Do not copy ' into the data */
2233  } else {
2234  /* Replace , with |, unless in quotes */
2235  *dataPut++ = inQuotes ? *start : ((*start == find) ? replace_with : *start);
2236  }
2237  }
2238  }
2239  if (start != dataPut)
2240  *dataPut = 0;
2241  return dataPut;
2242 }
2243 
2244 static int ast_true(const char *s)
2245 {
2246  if (ast_strlen_zero(s))
2247  return 0;
2248 
2249  /* Determine if this is a true value */
2250  if (!strcasecmp(s, "yes") ||
2251  !strcasecmp(s, "true") ||
2252  !strcasecmp(s, "y") ||
2253  !strcasecmp(s, "t") ||
2254  !strcasecmp(s, "1") ||
2255  !strcasecmp(s, "on"))
2256  return -1;
2257 
2258  return 0;
2259 }
2260 
2261 #define ONE_MILLION 1000000
2262 /*
2263  * put timeval in a valid range. usec is 0..999999
2264  * negative values are not allowed and truncated.
2265  */
2266 static struct timeval tvfix(struct timeval a)
2267 {
2268  if (a.tv_usec >= ONE_MILLION) {
2269  ast_log(LOG_WARNING, "warning too large timestamp %ld.%ld\n",
2270  (long)a.tv_sec, (long int) a.tv_usec);
2271  a.tv_sec += a.tv_usec / ONE_MILLION;
2272  a.tv_usec %= ONE_MILLION;
2273  } else if (a.tv_usec < 0) {
2274  ast_log(LOG_WARNING, "warning negative timestamp %ld.%ld\n",
2275  (long)a.tv_sec, (long int) a.tv_usec);
2276  a.tv_usec = 0;
2277  }
2278  return a;
2279 }
2280 
2281 struct timeval ast_tvadd(struct timeval a, struct timeval b);
2282 struct timeval ast_tvadd(struct timeval a, struct timeval b)
2283 {
2284  /* consistency checks to guarantee usec in 0..999999 */
2285  a = tvfix(a);
2286  b = tvfix(b);
2287  a.tv_sec += b.tv_sec;
2288  a.tv_usec += b.tv_usec;
2289  if (a.tv_usec >= ONE_MILLION) {
2290  a.tv_sec++;
2291  a.tv_usec -= ONE_MILLION;
2292  }
2293  return a;
2294 }
2295 
2296 struct timeval ast_tvsub(struct timeval a, struct timeval b);
2297 struct timeval ast_tvsub(struct timeval a, struct timeval b)
2298 {
2299  /* consistency checks to guarantee usec in 0..999999 */
2300  a = tvfix(a);
2301  b = tvfix(b);
2302  a.tv_sec -= b.tv_sec;
2303  a.tv_usec -= b.tv_usec;
2304  if (a.tv_usec < 0) {
2305  a.tv_sec-- ;
2306  a.tv_usec += ONE_MILLION;
2307  }
2308  return a;
2309 }
2310 #undef ONE_MILLION
2311 
2312 void ast_mark_lock_failed(void *lock_addr);
2313 void ast_mark_lock_failed(void *lock_addr)
2314 {
2315  /* Pretend to do something. */
2316 }
2317 
2318 /* stolen from pbx.c */
2319 #define VAR_BUF_SIZE 4096
2320 
2321 #define VAR_NORMAL 1
2322 #define VAR_SOFTTRAN 2
2323 #define VAR_HARDTRAN 3
2324 
2325 #define BACKGROUND_SKIP (1 << 0)
2326 #define BACKGROUND_NOANSWER (1 << 1)
2327 #define BACKGROUND_MATCHEXTEN (1 << 2)
2328 #define BACKGROUND_PLAYBACK (1 << 3)
2329 
2330 /*!
2331  \brief ast_exten: An extension
2332  The dialplan is saved as a linked list with each context
2333  having it's own linked list of extensions - one item per
2334  priority.
2335 */
2336 struct ast_exten {
2337  char *exten; /*!< Extension name */
2338  int matchcid; /*!< Match caller id ? */
2339  const char *cidmatch; /*!< Caller id to match for this extension */
2340  int priority; /*!< Priority */
2341  const char *label; /*!< Label */
2342  struct ast_context *parent; /*!< The context this extension belongs to */
2343  const char *app; /*!< Application to execute */
2344  struct ast_app *cached_app; /*!< Cached location of application */
2345  void *data; /*!< Data to use (arguments) */
2346  void (*datad)(void *); /*!< Data destructor */
2347  struct ast_exten *peer; /*!< Next higher priority with our extension */
2348  const char *registrar; /*!< Registrar */
2349  struct ast_exten *next; /*!< Extension with a greater ID */
2350  char stuff[0];
2351 };
2352 /* from pbx.h */
2353 typedef int (*ast_state_cb_type)(char *context, char* id, enum ast_extension_states state, void *data);
2354 struct ast_timing {
2355  int hastime; /*!< If time construct exists */
2356  unsigned int monthmask; /*!< Mask for month */
2357  unsigned int daymask; /*!< Mask for date */
2358  unsigned int dowmask; /*!< Mask for day of week (mon-sun) */
2359  unsigned int minmask[48]; /*!< Mask for minute */
2360  char *timezone; /*!< NULL, or zoneinfo style timezone */
2361 };
2362 /* end of pbx.h */
2363 /*! \brief ast_include: include= support in extensions.conf */
2364 struct ast_include {
2365  const char *name;
2366  const char *rname; /*!< Context to include */
2367  const char *registrar; /*!< Registrar */
2368  int hastime; /*!< If time construct exists */
2369  struct ast_timing timing; /*!< time construct */
2370  struct ast_include *next; /*!< Link them together */
2371  char stuff[0];
2372 };
2373 
2374 /*! \brief ast_sw: Switch statement in extensions.conf */
2375 struct ast_sw {
2376  char *name;
2377  const char *registrar; /*!< Registrar */
2378  char *data; /*!< Data load */
2379  int eval;
2380  AST_LIST_ENTRY(ast_sw) list;
2381  char *tmpdata;
2382  char stuff[0];
2383 };
2384 
2385 /*! \brief ast_ignorepat: Ignore patterns in dial plan */
2386 struct ast_ignorepat {
2387  const char *registrar;
2388  struct ast_ignorepat *next;
2389  char pattern[0];
2390 };
2391 
2392 /*! \brief ast_context: An extension context */
2393 struct ast_context {
2394  ast_rwlock_t lock; /*!< A lock to prevent multiple threads from clobbering the context */
2395  struct ast_exten *root; /*!< The root of the list of extensions */
2396  struct ast_context *next; /*!< Link them together */
2397  struct ast_include *includes; /*!< Include other contexts */
2398  struct ast_ignorepat *ignorepats; /*!< Patterns for which to continue playing dialtone */
2399  const char *registrar; /*!< Registrar */
2400  AST_LIST_HEAD_NOLOCK(, ast_sw) alts; /*!< Alternative switches */
2401  char name[0]; /*!< Name of the context */
2402 };
2403 
2404 
2405 /*! \brief ast_app: A registered application */
2406 struct ast_app {
2407  int (*execute)(struct ast_channel *chan, void *data);
2408  const char *synopsis; /*!< Synopsis text for 'show applications' */
2409  const char *description; /*!< Description (help text) for 'show application &lt;name&gt;' */
2410  AST_RWLIST_ENTRY(ast_app) list; /*!< Next app in list */
2411  void *module; /*!< Module this app belongs to */
2412  char name[0]; /*!< Name of the application */
2413 };
2414 
2415 
2416 /*! \brief ast_state_cb: An extension state notify register item */
2417 struct ast_state_cb {
2418  int id;
2419  void *data;
2420  ast_state_cb_type callback;
2421  struct ast_state_cb *next;
2422 };
2423 
2424 /*! \brief Structure for dial plan hints
2425 
2426  \note Hints are pointers from an extension in the dialplan to one or
2427  more devices (tech/name)
2428  - See \ref AstExtState
2429 */
2430 struct ast_hint {
2431  struct ast_exten *exten; /*!< Extension */
2432  int laststate; /*!< Last known state */
2433  struct ast_state_cb *callbacks; /*!< Callback list for this extension */
2434  AST_RWLIST_ENTRY(ast_hint) list;/*!< Pointer to next hint in list */
2435 };
2436 
2437 struct store_hint {
2438  char *context;
2439  char *exten;
2440  struct ast_state_cb *callbacks;
2441  int laststate;
2442  AST_LIST_ENTRY(store_hint) list;
2443  char data[1];
2444 };
2445 
2447 
2448 #define STATUS_NO_CONTEXT 1
2449 #define STATUS_NO_EXTENSION 2
2450 #define STATUS_NO_PRIORITY 3
2451 #define STATUS_NO_LABEL 4
2452 #define STATUS_SUCCESS 5
2453 
2454 static struct ast_var_t *ast_var_assign(const char *name, const char *value)
2455 {
2456  struct ast_var_t *var;
2457  int name_len = strlen(name) + 1;
2458  int value_len = strlen(value) + 1;
2459 
2460  if (!(var = ast_calloc(sizeof(*var) + name_len + value_len, sizeof(char)))) {
2461  return NULL;
2462  }
2463 
2464  ast_copy_string(var->name, name, name_len);
2465  var->value = var->name + name_len;
2466  ast_copy_string(var->value, value, value_len);
2467 
2468  return var;
2469 }
2470 
2471 static void ast_var_delete(struct ast_var_t *var)
2472 {
2473  free(var);
2474 }
2475 
2476 
2477 /* chopped this one off at the knees! */
2478 static int ast_func_write(struct ast_channel *chan, const char *function, const char *value)
2479 {
2480 
2481  /* ast_log(LOG_ERROR, "Function %s not registered\n", function); we are not interested in the details here */
2482 
2483  return -1;
2484 }
2485 
2486 static unsigned int ast_app_separate_args(char *buf, char delim, char **array, int arraylen)
2487 {
2488  int argc;
2489  char *scan;
2490  int paren = 0, quote = 0;
2491 
2492  if (!buf || !array || !arraylen)
2493  return 0;
2494 
2495  memset(array, 0, arraylen * sizeof(*array));
2496 
2497  scan = buf;
2498 
2499  for (argc = 0; *scan && (argc < arraylen - 1); argc++) {
2500  array[argc] = scan;
2501  for (; *scan; scan++) {
2502  if (*scan == '(')
2503  paren++;
2504  else if (*scan == ')') {
2505  if (paren)
2506  paren--;
2507  } else if (*scan == '"' && delim != '"') {
2508  quote = quote ? 0 : 1;
2509  /* Remove quote character from argument */
2510  memmove(scan, scan + 1, strlen(scan));
2511  scan--;
2512  } else if (*scan == '\\') {
2513  /* Literal character, don't parse */
2514  memmove(scan, scan + 1, strlen(scan));
2515  } else if ((*scan == delim) && !paren && !quote) {
2516  *scan++ = '\0';
2517  break;
2518  }
2519  }
2520  }
2521 
2522  if (*scan)
2523  array[argc++] = scan;
2524 
2525  return argc;
2526 }
2527 
2528 static void pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
2529 {
2530  struct ast_var_t *newvariable;
2531  struct varshead *headp;
2532  const char *nametail = name;
2533 
2534  /* XXX may need locking on the channel ? */
2535  if (name[strlen(name)-1] == ')') {
2536  char *function = ast_strdupa(name);
2537 
2538  ast_func_write(chan, function, value);
2539  return;
2540  }
2541 
2542  headp = &globals;
2543 
2544  /* For comparison purposes, we have to strip leading underscores */
2545  if (*nametail == '_') {
2546  nametail++;
2547  if (*nametail == '_')
2548  nametail++;
2549  }
2550 
2551  AST_LIST_TRAVERSE (headp, newvariable, entries) {
2552  if (strcasecmp(ast_var_name(newvariable), nametail) == 0) {
2553  /* there is already such a variable, delete it */
2554  AST_LIST_REMOVE(headp, newvariable, entries);
2555  ast_var_delete(newvariable);
2556  break;
2557  }
2558  }
2559 
2560  if (value && (newvariable = ast_var_assign(name, value))) {
2561  if ((option_verbose > 1) && (headp == &globals))
2562  ast_verbose(VERBOSE_PREFIX_2 "Setting global variable '%s' to '%s'\n", name, value);
2563  AST_LIST_INSERT_HEAD(headp, newvariable, entries);
2564  }
2565 
2566 }
2567 
2568 static int pbx_builtin_setvar(struct ast_channel *chan, const void *data)
2569 {
2570  char *name, *value, *mydata;
2571  int argc;
2572  char *argv[24]; /* this will only support a maximum of 24 variables being set in a single operation */
2573  int global = 0;
2574  int x;
2575 
2576  if (ast_strlen_zero(data)) {
2577  ast_log(LOG_WARNING, "Set requires at least one variable name/value pair.\n");
2578  return 0;
2579  }
2580 
2581  mydata = ast_strdupa(data);
2582  argc = ast_app_separate_args(mydata, '|', argv, sizeof(argv) / sizeof(argv[0]));
2583 
2584  /* check for a trailing flags argument */
2585  if ((argc > 1) && !strchr(argv[argc-1], '=')) {
2586  argc--;
2587  if (strchr(argv[argc], 'g'))
2588  global = 1;
2589  }
2590 
2591  for (x = 0; x < argc; x++) {
2592  name = argv[x];
2593  if ((value = strchr(name, '='))) {
2594  *value++ = '\0';
2595  pbx_builtin_setvar_helper((global) ? NULL : chan, name, value);
2596  } else
2597  ast_log(LOG_WARNING, "Ignoring entry '%s' with no = (and not last 'options' entry)\n", name);
2598  }
2599 
2600  return(0);
2601 }
2602 
2603 int localized_pbx_builtin_setvar(struct ast_channel *chan, const void *data);
2604 
2605 int localized_pbx_builtin_setvar(struct ast_channel *chan, const void *data)
2606 {
2607  return pbx_builtin_setvar(chan, data);
2608 }
2609 
2610 
2611 /*! \brief Helper for get_range.
2612  * return the index of the matching entry, starting from 1.
2613  * If names is not supplied, try numeric values.
2614  */
2615 static int lookup_name(const char *s, char *const names[], int max)
2616 {
2617  int i;
2618 
2619  if (names && *s > '9') {
2620  for (i = 0; names[i]; i++) {
2621  if (!strcasecmp(s, names[i])) {
2622  return i;
2623  }
2624  }
2625  }
2626 
2627  /* Allow months and weekdays to be specified as numbers, as well */
2628  if (sscanf(s, "%2d", &i) == 1 && i >= 1 && i <= max) {
2629  /* What the array offset would have been: "1" would be at offset 0 */
2630  return i - 1;
2631  }
2632  return -1; /* error return */
2633 }
2634 
2635 /*! \brief helper function to return a range up to max (7, 12, 31 respectively).
2636  * names, if supplied, is an array of names that should be mapped to numbers.
2637  */
2638 static unsigned get_range(char *src, int max, char *const names[], const char *msg)
2639 {
2640  int start, end; /* start and ending position */
2641  unsigned int mask = 0;
2642  char *part;
2643 
2644  /* Check for whole range */
2645  if (ast_strlen_zero(src) || !strcmp(src, "*")) {
2646  return (1 << max) - 1;
2647  }
2648 
2649  while ((part = strsep(&src, "&"))) {
2650  /* Get start and ending position */
2651  char *endpart = strchr(part, '-');
2652  if (endpart) {
2653  *endpart++ = '\0';
2654  }
2655  /* Find the start */
2656  if ((start = lookup_name(part, names, max)) < 0) {
2657  ast_log(LOG_WARNING, "Invalid %s '%s', skipping element\n", msg, part);
2658  continue;
2659  }
2660  if (endpart) { /* find end of range */
2661  if ((end = lookup_name(endpart, names, max)) < 0) {
2662  ast_log(LOG_WARNING, "Invalid end %s '%s', skipping element\n", msg, endpart);
2663  continue;
2664  }
2665  } else {
2666  end = start;
2667  }
2668  /* Fill the mask. Remember that ranges are cyclic */
2669  mask |= (1 << end); /* initialize with last element */
2670  while (start != end) {
2671  if (start >= max) {
2672  start = 0;
2673  }
2674  mask |= (1 << start);
2675  start++;
2676  }
2677  }
2678  return mask;
2679 }
2680 
2681 /*! \brief store a bitmask of valid times, one bit each 2 minute */
2682 static void get_timerange(struct ast_timing *i, char *times)
2683 {
2684  char *endpart, *part;
2685  int x;
2686  int st_h, st_m;
2687  int endh, endm;
2688  int minute_start, minute_end;
2689 
2690  /* start disabling all times, fill the fields with 0's, as they may contain garbage */
2691  memset(i->minmask, 0, sizeof(i->minmask));
2692 
2693  /* 1-minute per bit */
2694  /* Star is all times */
2695  if (ast_strlen_zero(times) || !strcmp(times, "*")) {
2696  /* 48, because each hour takes 2 integers; 30 bits each */
2697  for (x = 0; x < 48; x++) {
2698  i->minmask[x] = 0x3fffffff; /* 30 bits */
2699  }
2700  return;
2701  }
2702  /* Otherwise expect a range */
2703  while ((part = strsep(&times, "&"))) {
2704  if (!(endpart = strchr(part, '-'))) {
2705  if (sscanf(part, "%2d:%2d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) {
2706  ast_log(LOG_WARNING, "%s isn't a valid time.\n", part);
2707  continue;
2708  }
2709  i->minmask[st_h * 2 + (st_m >= 30 ? 1 : 0)] |= (1 << (st_m % 30));
2710  continue;
2711  }
2712  *endpart++ = '\0';
2713  /* why skip non digits? Mostly to skip spaces */
2714  while (*endpart && !isdigit(*endpart)) {
2715  endpart++;
2716  }
2717  if (!*endpart) {
2718  ast_log(LOG_WARNING, "Invalid time range starting with '%s-'.\n", part);
2719  continue;
2720  }
2721  if (sscanf(part, "%2d:%2d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) {
2722  ast_log(LOG_WARNING, "'%s' isn't a valid start time.\n", part);
2723  continue;
2724  }
2725  if (sscanf(endpart, "%2d:%2d", &endh, &endm) != 2 || endh < 0 || endh > 23 || endm < 0 || endm > 59) {
2726  ast_log(LOG_WARNING, "'%s' isn't a valid end time.\n", endpart);
2727  continue;
2728  }
2729  minute_start = st_h * 60 + st_m;
2730  minute_end = endh * 60 + endm;
2731  /* Go through the time and enable each appropriate bit */
2732  for (x = minute_start; x != minute_end; x = (x + 1) % (24 * 60)) {
2733  i->minmask[x / 30] |= (1 << (x % 30));
2734  }
2735  /* Do the last one */
2736  i->minmask[x / 30] |= (1 << (x % 30));
2737  }
2738  /* All done */
2739  return;
2740 }
2741 
2742 static void null_datad(void *foo)
2743 {
2744 }
2745 
2746 /*! \brief Find realtime engine for realtime family */
2747 static struct ast_config_engine *find_engine(const char *family, char *database, int dbsiz, char *table, int tabsiz)
2748 {
2749  struct ast_config_engine *eng, *ret = NULL;
2750  struct ast_config_map *map;
2751 
2752 
2753  for (map = config_maps; map; map = map->next) {
2754  if (!strcasecmp(family, map->name)) {
2755  if (database)
2756  ast_copy_string(database, map->database, dbsiz);
2757  if (table)
2758  ast_copy_string(table, map->table ? map->table : family, tabsiz);
2759  break;
2760  }
2761  }
2762 
2763  /* Check if the required driver (engine) exist */
2764  if (map) {
2765  for (eng = config_engine_list; !ret && eng; eng = eng->next) {
2766  if (!strcasecmp(eng->name, map->driver))
2767  ret = eng;
2768  }
2769  }
2770 
2771 
2772  /* if we found a mapping, but the engine is not available, then issue a warning */
2773  if (map && !ret)
2774  ast_log(LOG_WARNING, "Realtime mapping for '%s' found to engine '%s', but the engine is not available\n", map->name, map->driver);
2775 
2776  return ret;
2777 }
2778 
2779 struct ast_category *ast_config_get_current_category(const struct ast_config *cfg);
2780 
2782 {
2783  return cfg->current;
2784 }
2785 
2786 static struct ast_category *ast_category_new(const char *name, const char *in_file, int lineno);
2787 
2788 static struct ast_category *ast_category_new(const char *name, const char *in_file, int lineno)
2789 {
2790  struct ast_category *category;
2791 
2792  if ((category = ast_calloc(1, sizeof(*category))))
2793  ast_copy_string(category->name, name, sizeof(category->name));
2794  category->file = strdup(in_file);
2795  category->lineno = lineno; /* if you don't know the lineno, set it to 999999 or something real big */
2796  return category;
2797 }
2798 
2799 struct ast_category *localized_category_get(const struct ast_config *config, const char *category_name);
2800 
2801 struct ast_category *localized_category_get(const struct ast_config *config, const char *category_name)
2802 {
2803  return category_get(config, category_name, 0);
2804 }
2805 
2806 static void move_variables(struct ast_category *old, struct ast_category *new)
2807 {
2808  struct ast_variable *var = old->root;
2809  old->root = NULL;
2810 #if 1
2811  /* we can just move the entire list in a single op */
2812  ast_variable_append(new, var);
2813 #else
2814  while (var) {
2815  struct ast_variable *next = var->next;
2816  var->next = NULL;
2817  ast_variable_append(new, var);
2818  var = next;
2819  }
2820 #endif
2821 }
2822 
2823 static void inherit_category(struct ast_category *new, const struct ast_category *base)
2824 {
2825  struct ast_variable *var;
2826 
2827  for (var = base->root; var; var = var->next)
2828  ast_variable_append(new, variable_clone(var));
2829 }
2830 
2831 static void ast_category_append(struct ast_config *config, struct ast_category *category);
2832 
2833 static void ast_category_append(struct ast_config *config, struct ast_category *category)
2834 {
2835  if (config->last)
2836  config->last->next = category;
2837  else
2838  config->root = category;
2839  config->last = category;
2840  config->current = category;
2841 }
2842 
2843 static void ast_category_destroy(struct ast_category *cat);
2844 
2845 static void ast_category_destroy(struct ast_category *cat)
2846 {
2848  if (cat->file)
2849  free(cat->file);
2850 
2851  free(cat);
2852 }
2853 
2854 static struct ast_config_engine text_file_engine = {
2855  .name = "text",
2856  .load_func = config_text_file_load,
2857 };
2858 
2859 
2860 static struct ast_config *ast_config_internal_load(const char *filename, struct ast_config *cfg, int withcomments, const char *suggested_incl_file);
2861 
2862 static struct ast_config *ast_config_internal_load(const char *filename, struct ast_config *cfg, int withcomments, const char *suggested_incl_file)
2863 {
2864  char db[256] = "";
2865  char table[256] = "";
2866  struct ast_config_engine *loader = &text_file_engine;
2867  struct ast_config *result;
2868 
2869  if (cfg->include_level == cfg->max_include_level) {
2870  ast_log(LOG_WARNING, "Maximum Include level (%d) exceeded\n", cfg->max_include_level);
2871  return NULL;
2872  }
2873 
2874  cfg->include_level++;
2875  /* silence is golden!
2876  ast_log(LOG_WARNING, "internal loading file %s level=%d\n", filename, cfg->include_level);
2877  */
2878 
2879  if (strcmp(filename, extconfig_conf) && strcmp(filename, "asterisk.conf") && config_engine_list) {
2880  struct ast_config_engine *eng;
2881 
2882  eng = find_engine(filename, db, sizeof(db), table, sizeof(table));
2883 
2884 
2885  if (eng && eng->load_func) {
2886  loader = eng;
2887  } else {
2888  eng = find_engine("global", db, sizeof(db), table, sizeof(table));
2889  if (eng && eng->load_func)
2890  loader = eng;
2891  }
2892  }
2893 
2894  result = loader->load_func(db, table, filename, cfg, withcomments, suggested_incl_file);
2895  /* silence is golden
2896  ast_log(LOG_WARNING, "finished internal loading file %s level=%d\n", filename, cfg->include_level);
2897  */
2898 
2899  if (result)
2900  result->include_level--;
2901 
2902  return result;
2903 }
2904 
2905 
2906 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)
2907 {
2908  char *c;
2909  char *cur = buf;
2910  struct ast_variable *v;
2911  char exec_file[512];
2912  int object, do_exec, do_include;
2913 
2914  /* Actually parse the entry */
2915  if (cur[0] == '[') {
2916  struct ast_category *newcat = NULL;
2917  char *catname;
2918 
2919  /* A category header */
2920  c = strchr(cur, ']');
2921  if (!c) {
2922  ast_log(LOG_WARNING, "parse error: no closing ']', line %d of %s\n", lineno, configfile);
2923  return -1;
2924  }
2925  *c++ = '\0';
2926  cur++;
2927  if (*c++ != '(')
2928  c = NULL;
2929  catname = cur;
2930  if (!(*cat = newcat = ast_category_new(catname, ast_strlen_zero(suggested_include_file)?configfile:suggested_include_file, lineno))) {
2931  return -1;
2932  }
2933  (*cat)->lineno = lineno;
2934 
2935  /* add comments */
2936  if (withcomments && comment_buffer && comment_buffer[0] ) {
2937  newcat->precomments = ALLOC_COMMENT(comment_buffer);
2938  }
2939  if (withcomments && lline_buffer && lline_buffer[0] ) {
2940  newcat->sameline = ALLOC_COMMENT(lline_buffer);
2941  }
2942  if( withcomments )
2943  CB_RESET();
2944 
2945  /* If there are options or categories to inherit from, process them now */
2946  if (c) {
2947  if (!(cur = strchr(c, ')'))) {
2948  ast_log(LOG_WARNING, "parse error: no closing ')', line %d of %s\n", lineno, configfile);
2949  return -1;
2950  }
2951  *cur = '\0';
2952  while ((cur = strsep(&c, ","))) {
2953  if (!strcasecmp(cur, "!")) {
2954  (*cat)->ignored = 1;
2955  } else if (!strcasecmp(cur, "+")) {
2956  *cat = category_get(cfg, catname, 1);
2957  if (!*cat) {
2958  ast_config_destroy(cfg);
2959  if (newcat)
2960  ast_category_destroy(newcat);
2961  ast_log(LOG_WARNING, "Category addition requested, but category '%s' does not exist, line %d of %s\n", catname, lineno, configfile);
2962  return -1;
2963  }
2964  if (newcat) {
2965  move_variables(newcat, *cat);
2966  ast_category_destroy(newcat);
2967  newcat = NULL;
2968  }
2969  } else {
2970  struct ast_category *base;
2971 
2972  base = category_get(cfg, cur, 1);
2973  if (!base) {
2974  ast_log(LOG_WARNING, "Inheritance requested, but category '%s' does not exist, line %d of %s\n", cur, lineno, configfile);
2975  return -1;
2976  }
2977  inherit_category(*cat, base);
2978  }
2979  }
2980  }
2981  if (newcat)
2982  ast_category_append(cfg, *cat);
2983  } else if (cur[0] == '#') {
2984  /* A directive */
2985  cur++;
2986  c = cur;
2987  while(*c && (*c > 32)) c++;
2988  if (*c) {
2989  *c = '\0';
2990  /* Find real argument */
2991  c = ast_skip_blanks(c + 1);
2992  if (!*c)
2993  c = NULL;
2994  } else
2995  c = NULL;
2996  do_include = !strcasecmp(cur, "include");
2997  if(!do_include)
2998  do_exec = !strcasecmp(cur, "exec");
2999  else
3000  do_exec = 0;
3001  if (do_exec && !ast_opt_exec_includes) {
3002  ast_log(LOG_WARNING, "Cannot perform #exec unless execincludes option is enabled in asterisk.conf (options section)!\n");
3003  do_exec = 0;
3004  }
3005  if (do_include || do_exec) {
3006  if (c) {
3007  char *cur2;
3008  char real_inclusion_name[525];
3009 
3010  /* Strip off leading and trailing "'s and <>'s */
3011  while((*c == '<') || (*c == '>') || (*c == '\"')) c++;
3012  /* Get rid of leading mess */
3013  cur = c;
3014  cur2 = cur;
3015  while (!ast_strlen_zero(cur)) {
3016  c = cur + strlen(cur) - 1;
3017  if ((*c == '>') || (*c == '<') || (*c == '\"'))
3018  *c = '\0';
3019  else
3020  break;
3021  }
3022  /* #exec </path/to/executable>
3023  We create a tmp file, then we #include it, then we delete it. */
3024  if (do_exec) {
3025  char cmd[1024];
3026 
3027  snprintf(exec_file, sizeof(exec_file), "/var/tmp/exec.%d.%ld", (int)time(NULL), (long)pthread_self());
3028  if (snprintf(cmd, sizeof(cmd), "%s > %s 2>&1", cur, exec_file) >= sizeof(cmd)) {
3029  ast_log(LOG_ERROR, "Failed to construct command string to execute %s.\n", cur);
3030 
3031  return -1;
3032  }
3033  ast_safe_system(cmd);
3034  cur = exec_file;
3035  } else
3036  exec_file[0] = '\0';
3037  /* A #include */
3038  /* ast_log(LOG_WARNING, "Reading in included file %s withcomments=%d\n", cur, withcomments); */
3039 
3040  /* record this inclusion */
3041  ast_include_new(cfg, configfile, cur, do_exec, cur2, lineno, real_inclusion_name, sizeof(real_inclusion_name));
3042 
3043  do_include = ast_config_internal_load(cur, cfg, withcomments, real_inclusion_name) ? 1 : 0;
3044  if(!ast_strlen_zero(exec_file))
3045  unlink(exec_file);
3046  if(!do_include)
3047  return 0;
3048  /* ast_log(LOG_WARNING, "Done reading in included file %s withcomments=%d\n", cur, withcomments); */
3049 
3050  } else {
3051  ast_log(LOG_WARNING, "Directive '#%s' needs an argument (%s) at line %d of %s\n",
3052  do_exec ? "exec" : "include",
3053  do_exec ? "/path/to/executable" : "filename",
3054  lineno,
3055  configfile);
3056  }
3057  }
3058  else
3059  ast_log(LOG_WARNING, "Unknown directive '%s' at line %d of %s\n", cur, lineno, configfile);
3060  } else {
3061  /* Just a line (variable = value) */
3062  if (!*cat) {
3063  ast_log(LOG_WARNING,
3064  "parse error: No category context for line %d of %s\n", lineno, configfile);
3065  return -1;
3066  }
3067  c = strchr(cur, '=');
3068  if (c) {
3069  *c = 0;
3070  c++;
3071  /* Ignore > in => */
3072  if (*c== '>') {
3073  object = 1;
3074  c++;
3075  } else
3076  object = 0;
3077  if ((v = ast_variable_new(ast_strip(cur), ast_strip(c), configfile))) {
3078  v->lineno = lineno;
3079  v->object = object;
3080  /* Put and reset comments */
3081  v->blanklines = 0;
3082  ast_variable_append(*cat, v);
3083  /* add comments */
3084  if (withcomments && comment_buffer && comment_buffer[0] ) {
3085  v->precomments = ALLOC_COMMENT(comment_buffer);
3086  }
3087  if (withcomments && lline_buffer && lline_buffer[0] ) {
3088  v->sameline = ALLOC_COMMENT(lline_buffer);
3089  }
3090  if( withcomments )
3091  CB_RESET();
3092 
3093  } else {
3094  return -1;
3095  }
3096  } else {
3097  ast_log(LOG_WARNING, "EXTENSIONS.CONF: No '=' (equal sign) in line %d of %s\n", lineno, configfile);
3098  }
3099  }
3100  return 0;
3101 }
3102 
3103 static int use_local_dir = 1;
3104 
3105 void localized_use_local_dir(void);
3106 void localized_use_conf_dir(void);
3107 
3108 void localized_use_local_dir(void)
3109 {
3110  use_local_dir = 1;
3111 }
3112 
3113 void localized_use_conf_dir(void)
3114 {
3115  use_local_dir = 0;
3116 }
3117 
3118 
3119 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)
3120 {
3121  char fn[256];
3122  char buf[8192];
3123  char *new_buf, *comment_p, *process_buf;
3124  FILE *f;
3125  int lineno=0;
3126  int comment = 0, nest[MAX_NESTED_COMMENTS];
3127  struct ast_category *cat = NULL;
3128  int count = 0;
3129  struct stat statbuf;
3130 
3132 
3133  if (filename[0] == '/') {
3134  ast_copy_string(fn, filename, sizeof(fn));
3135  } else {
3136  if (use_local_dir)
3137  snprintf(fn, sizeof(fn), "./%s", filename);
3138  else
3139  snprintf(fn, sizeof(fn), "%s/%s", ast_config_AST_CONFIG_DIR, filename);
3140  }
3141 
3142  if (withcomments && cfg && cfg->include_level < 2 ) {
3143  CB_INIT();
3144  }
3145 
3146  do {
3147  if (stat(fn, &statbuf))
3148  continue;
3149 
3150  if (!S_ISREG(statbuf.st_mode)) {
3151  ast_log(LOG_WARNING, "'%s' is not a regular file, ignoring\n", fn);
3152  continue;
3153  }
3154  if (option_verbose > 1) {
3155  ast_verbose(VERBOSE_PREFIX_2 "Parsing '%s': ", fn);
3156  fflush(stdout);
3157  }
3158  if (!(f = fopen(fn, "r"))) {
3159  if (option_debug)
3160  ast_log(LOG_DEBUG, "No file to parse: %s\n", fn);
3161  if (option_verbose > 1)
3162  ast_verbose( "Not found (%s)\n", strerror(errno));
3163  continue;
3164  }
3165  count++;
3166  if (option_debug)
3167  ast_log(LOG_DEBUG, "Parsing %s\n", fn);
3168  if (option_verbose > 1)
3169  ast_verbose("Found\n");
3170  while(!feof(f)) {
3171  lineno++;
3172  if (fgets(buf, sizeof(buf), f)) {
3173  if ( withcomments ) {
3174  CB_ADD(lline_buffer); /* add the current lline buffer to the comment buffer */
3175  lline_buffer[0] = 0; /* erase the lline buffer */
3176  }
3177 
3178  new_buf = buf;
3179  if (comment)
3180  process_buf = NULL;
3181  else
3182  process_buf = buf;
3183 
3184  while ((comment_p = strchr(new_buf, COMMENT_META))) {
3185  if ((comment_p > new_buf) && (*(comment_p-1) == '\\')) {
3186  /* Yuck, gotta memmove */
3187  memmove(comment_p - 1, comment_p, strlen(comment_p) + 1);
3188  new_buf = comment_p;
3189  } else if(comment_p[1] == COMMENT_TAG && comment_p[2] == COMMENT_TAG && (comment_p[3] != '-')) {
3190  /* Meta-Comment start detected ";--" */
3191  if (comment < MAX_NESTED_COMMENTS) {
3192  *comment_p = '\0';
3193  new_buf = comment_p + 3;
3194  comment++;
3195  nest[comment-1] = lineno;
3196  } else {
3197  ast_log(LOG_ERROR, "Maximum nest limit of %d reached.\n", MAX_NESTED_COMMENTS);
3198  }
3199  } else if ((comment_p >= new_buf + 2) &&
3200  (*(comment_p - 1) == COMMENT_TAG) &&
3201  (*(comment_p - 2) == COMMENT_TAG)) {
3202  /* Meta-Comment end detected */
3203  comment--;
3204  new_buf = comment_p + 1;
3205  if (!comment) {
3206  /* Back to non-comment now */
3207  if (process_buf) {
3208  /* Actually have to move what's left over the top, then continue */
3209  char *oldptr;
3210  oldptr = process_buf + strlen(process_buf);
3211  if ( withcomments ) {
3212  CB_ADD(";");
3213  CB_ADD_LEN(oldptr+1,new_buf-oldptr-1);
3214  }
3215 
3216  memmove(oldptr, new_buf, strlen(new_buf) + 1);
3217  new_buf = oldptr;
3218  } else
3219  process_buf = new_buf;
3220  }
3221  } else {
3222  if (!comment) {
3223  /* If ; is found, and we are not nested in a comment,
3224  we immediately stop all comment processing */
3225  if ( withcomments ) {
3226  LLB_ADD(comment_p);
3227  }
3228  *comment_p = '\0';
3229  new_buf = comment_p;
3230  } else
3231  new_buf = comment_p + 1;
3232  }
3233  }
3234  if( withcomments && comment && !process_buf )
3235  {
3236  CB_ADD(buf); /* the whole line is a comment, store it */
3237  }
3238 
3239  if (process_buf) {
3240  char *stripped_process_buf = ast_strip(process_buf);
3241  if (!ast_strlen_zero(stripped_process_buf)) {
3242  if (process_text_line(cfg, &cat, stripped_process_buf, lineno, filename, withcomments, suggested_include_file)) {
3243  cfg = NULL;
3244  break;
3245  }
3246  }
3247  }
3248  }
3249  }
3250  fclose(f);
3251  } while(0);
3252  if (comment) {
3253  ast_log(LOG_WARNING,"Unterminated comment detected beginning on line %d\n", nest[comment]);
3254  }
3255  if (cfg && cfg->include_level == 1 && withcomments && comment_buffer) {
3256  if (comment_buffer) {
3257  free(comment_buffer);
3258  free(lline_buffer);
3259  comment_buffer=0;
3260  lline_buffer=0;
3261  comment_buffer_size=0;
3262  lline_buffer_size=0;
3263  }
3264  }
3265  if (count == 0)
3266  return NULL;
3267 
3268  return cfg;
3269 }
3270 
3271 
3272 static struct ast_config *ast_config_new(void) ;
3273 
3274 static struct ast_config *ast_config_new(void)
3275 {
3276  struct ast_config *config;
3277 
3278  if ((config = ast_calloc(1, sizeof(*config))))
3279  config->max_include_level = MAX_INCLUDE_LEVEL;
3280  return config;
3281 }
3282 
3283 struct ast_config *localized_config_load(const char *filename);
3284 
3285 struct ast_config *localized_config_load(const char *filename)
3286 {
3287  struct ast_config *cfg;
3288  struct ast_config *result;
3289 
3290  cfg = ast_config_new();
3291  if (!cfg)
3292  return NULL;
3293 
3294  result = ast_config_internal_load(filename, cfg, 0, "");
3295  if (!result)
3296  ast_config_destroy(cfg);
3297 
3298  return result;
3299 }
3300 
3301 struct ast_config *localized_config_load_with_comments(const char *filename);
3302 
3303 struct ast_config *localized_config_load_with_comments(const char *filename)
3304 {
3305  struct ast_config *cfg;
3306  struct ast_config *result;
3307 
3308  cfg = ast_config_new();
3309  if (!cfg)
3310  return NULL;
3311 
3312  result = ast_config_internal_load(filename, cfg, 1, "");
3313  if (!result)
3314  ast_config_destroy(cfg);
3315 
3316  return result;
3317 }
3318 
3319 static struct ast_category *next_available_category(struct ast_category *cat)
3320 {
3321  for (; cat && cat->ignored; cat = cat->next);
3322 
3323  return cat;
3324 }
3325 
3326 static char *ast_category_browse(struct ast_config *config, const char *prev)
3327 {
3328  struct ast_category *cat = NULL;
3329 
3330  if (prev && config->last_browse && (config->last_browse->name == prev))
3331  cat = config->last_browse->next;
3332  else if (!prev && config->root)
3333  cat = config->root;
3334  else if (prev) {
3335  for (cat = config->root; cat; cat = cat->next) {
3336  if (cat->name == prev) {
3337  cat = cat->next;
3338  break;
3339  }
3340  }
3341  if (!cat) {
3342  for (cat = config->root; cat; cat = cat->next) {
3343  if (!strcasecmp(cat->name, prev)) {
3344  cat = cat->next;
3345  break;
3346  }
3347  }
3348  }
3349  }
3350 
3351  if (cat)
3352  cat = next_available_category(cat);
3353 
3354  config->last_browse = cat;
3355  return (cat) ? cat->name : NULL;
3356 }
3357 
3358 
3359 
3360 void ast_config_set_current_category(struct ast_config *cfg, const struct ast_category *cat);
3361 
3362 void ast_config_set_current_category(struct ast_config *cfg, const struct ast_category *cat)
3363 {
3364  /* cast below is just to silence compiler warning about dropping "const" */
3365  cfg->current = (struct ast_category *) cat;
3366 }
3367 
3368 /* NOTE: categories and variables each have a file and lineno attribute. On a save operation, these are used to determine
3369  which file and line number to write out to. Thus, an entire hierarchy of config files (via #include statements) can be
3370  recreated. BUT, care must be taken to make sure that every cat and var has the proper file name stored, or you may
3371  be shocked and mystified as to why things are not showing up in the files!
3372 
3373  Also, All #include/#exec statements are recorded in the "includes" LL in the ast_config structure. The file name
3374  and line number are stored for each include, plus the name of the file included, so that these statements may be
3375  included in the output files on a file_save operation.
3376 
3377  The lineno's are really just for relative placement in the file. There is no attempt to make sure that blank lines
3378  are included to keep the lineno's the same between input and output. The lineno fields are used mainly to determine
3379  the position of the #include and #exec directives. So, blank lines tend to disappear from a read/rewrite operation,
3380  and a header gets added.
3381 
3382  vars and category heads are output in the order they are stored in the config file. So, if the software
3383  shuffles these at all, then the placement of #include directives might get a little mixed up, because the
3384  file/lineno data probably won't get changed.
3385 
3386 */
3387 
3388 static void gen_header(FILE *f1, const char *configfile, const char *fn, const char *generator)
3389 {
3390  char date[256]="";
3391  time_t t;
3392  time(&t);
3393  ast_copy_string(date, ctime(&t), sizeof(date));
3394 
3395  fprintf(f1, ";!\n");
3396  fprintf(f1, ";! Automatically generated configuration file\n");
3397  if (strcmp(configfile, fn))
3398  fprintf(f1, ";! Filename: %s (%s)\n", configfile, fn);
3399  else
3400  fprintf(f1, ";! Filename: %s\n", configfile);
3401  fprintf(f1, ";! Generator: %s\n", generator);
3402  fprintf(f1, ";! Creation Date: %s", date);
3403  fprintf(f1, ";!\n");
3404 }
3405 
3406 static void set_fn(char *fn, int fn_size, const char *file, const char *configfile)
3407 {
3408  if (!file || file[0] == 0) {
3409  if (configfile[0] == '/')
3410  ast_copy_string(fn, configfile, fn_size);
3411  else
3412  snprintf(fn, fn_size, "%s/%s", ast_config_AST_CONFIG_DIR, configfile);
3413  } else if (file[0] == '/')
3414  ast_copy_string(fn, file, fn_size);
3415  else
3416  snprintf(fn, fn_size, "%s/%s", ast_config_AST_CONFIG_DIR, file);
3417 }
3418 
3419 int localized_config_text_file_save(const char *configfile, const struct ast_config *cfg, const char *generator);
3420 
3421 int localized_config_text_file_save(const char *configfile, const struct ast_config *cfg, const char *generator)
3422 {
3423  FILE *f;
3424  char fn[256];
3425  struct ast_variable *var;
3426  struct ast_category *cat;
3427  struct ast_comment *cmt;
3428  struct ast_config_include *incl;
3429  int blanklines = 0;
3430 
3431  /* reset all the output flags, in case this isn't our first time saving this data */
3432 
3433  for (incl=cfg->includes; incl; incl = incl->next)
3434  incl->output = 0;
3435 
3436  /* go thru all the inclusions and make sure all the files involved (configfile plus all its inclusions)
3437  are all truncated to zero bytes and have that nice header*/
3438 
3439  for (incl=cfg->includes; incl; incl = incl->next)
3440  {
3441  if (!incl->exec) { /* leave the execs alone -- we'll write out the #exec directives, but won't zero out the include files or exec files*/
3442  FILE *f1;
3443 
3444  set_fn(fn, sizeof(fn), incl->included_file, configfile); /* normally, fn is just set to incl->included_file, prepended with config dir if relative */
3445  f1 = fopen(fn,"w");
3446  if (f1) {
3447  gen_header(f1, configfile, fn, generator);
3448  fclose(f1); /* this should zero out the file */
3449  } else {
3450  ast_verbose(VERBOSE_PREFIX_2 "Unable to write %s (%s)", fn, strerror(errno));
3451  }
3452  }
3453  }
3454 
3455  set_fn(fn, sizeof(fn), 0, configfile); /* just set fn to absolute ver of configfile */
3456 #ifdef __CYGWIN__
3457  if ((f = fopen(fn, "w+"))) {
3458 #else
3459  if ((f = fopen(fn, "w"))) {
3460 #endif
3461  if (option_verbose > 1)
3462  ast_verbose(VERBOSE_PREFIX_2 "Saving '%s': ", fn);
3463 
3464  gen_header(f, configfile, fn, generator);
3465  cat = cfg->root;
3466  fclose(f);
3467 
3468  /* from here out, we open each involved file and concat the stuff we need to add to the end and immediately close... */
3469  /* since each var, cat, and associated comments can come from any file, we have to be
3470  mobile, and open each file, print, and close it on an entry-by-entry basis */
3471 
3472  while(cat) {
3473  set_fn(fn, sizeof(fn), cat->file, configfile);
3474  f = fopen(fn, "a");
3475  if (!f)
3476  {
3477  ast_verbose(VERBOSE_PREFIX_2 "Unable to write %s (%s)", fn, strerror(errno));
3478  return -1;
3479  }
3480 
3481  /* dump any includes that happen before this category header */
3482  for (incl=cfg->includes; incl; incl = incl->next) {
3483  if (strcmp(incl->include_location_file, cat->file) == 0){
3484  if (cat->lineno > incl->include_location_lineno && !incl->output) {
3485  if (incl->exec)
3486  fprintf(f,"#exec \"%s\"\n", incl->exec_file);
3487  else
3488  fprintf(f,"#include \"%s\"\n", incl->included_file);
3489  incl->output = 1;
3490  }
3491  }
3492  }
3493 
3494  /* Dump section with any appropriate comment */
3495  for (cmt = cat->precomments; cmt; cmt=cmt->next) {
3496  if (cmt->cmt[0] != ';' || cmt->cmt[1] != '!')
3497  fprintf(f,"%s", cmt->cmt);
3498  }
3499  if (!cat->precomments)
3500  fprintf(f,"\n");
3501  fprintf(f, "[%s]", cat->name);
3502  for(cmt = cat->sameline; cmt; cmt=cmt->next) {
3503  fprintf(f,"%s", cmt->cmt);
3504  }
3505  if (!cat->sameline)
3506  fprintf(f,"\n");
3507  fclose(f);
3508 
3509  var = cat->root;
3510  while(var) {
3511  set_fn(fn, sizeof(fn), var->file, configfile);
3512  f = fopen(fn, "a");
3513  if (!f)
3514  {
3515  ast_verbose(VERBOSE_PREFIX_2 "Unable to write %s (%s)", fn, strerror(errno));
3516  return -1;
3517  }
3518 
3519  /* dump any includes that happen before this category header */
3520  for (incl=cfg->includes; incl; incl = incl->next) {
3521  if (strcmp(incl->include_location_file, var->file) == 0){
3522  if (var->lineno > incl->include_location_lineno && !incl->output) {
3523  if (incl->exec)
3524  fprintf(f,"#exec \"%s\"\n", incl->exec_file);
3525  else
3526  fprintf(f,"#include \"%s\"\n", incl->included_file);
3527  incl->output = 1;
3528  }
3529  }
3530  }
3531 
3532  for (cmt = var->precomments; cmt; cmt=cmt->next) {
3533  if (cmt->cmt[0] != ';' || cmt->cmt[1] != '!')
3534  fprintf(f,"%s", cmt->cmt);
3535  }
3536  if (var->sameline)
3537  fprintf(f, "%s %s %s %s", var->name, (var->object ? "=>" : "="), var->value, var->sameline->cmt);
3538  else
3539  fprintf(f, "%s %s %s\n", var->name, (var->object ? "=>" : "="), var->value);
3540  if (var->blanklines) {
3541  blanklines = var->blanklines;
3542  while (blanklines--)
3543  fprintf(f, "\n");
3544  }
3545 
3546  fclose(f);
3547 
3548 
3549  var = var->next;
3550  }
3551  cat = cat->next;
3552  }
3553  if ((option_verbose > 1) && !option_debug)
3554  ast_verbose("Saved\n");
3555  } else {
3556  if (option_debug)
3557  ast_log(LOG_DEBUG, "Unable to open for writing: %s\n", fn);
3558  if (option_verbose > 1)
3559  ast_verbose(VERBOSE_PREFIX_2 "Unable to write (%s)", strerror(errno));
3560  return -1;
3561  }
3562 
3563  /* Now, for files with trailing #include/#exec statements,
3564  we have to make sure every entry is output */
3565 
3566  for (incl=cfg->includes; incl; incl = incl->next) {
3567  if (!incl->output) {
3568  /* open the respective file */
3569  set_fn(fn, sizeof(fn), incl->include_location_file, configfile);
3570  f = fopen(fn, "a");
3571  if (!f)
3572  {
3573  ast_verbose(VERBOSE_PREFIX_2 "Unable to write %s (%s)", fn, strerror(errno));
3574  return -1;
3575  }
3576 
3577  /* output the respective include */
3578  if (incl->exec)
3579  fprintf(f,"#exec \"%s\"\n", incl->exec_file);
3580  else
3581  fprintf(f,"#include \"%s\"\n", incl->included_file);
3582  fclose(f);
3583  incl->output = 1;
3584  }
3585  }
3586 
3587  return 0;
3588 }
3589 
3590 /* ================ the Line ========================================
3591  above this line, you have what you need to load a config file,
3592  and below it, you have what you need to process the extensions.conf
3593  file into the context/exten/prio stuff. They are both in one file
3594  to make things simpler */
3595 
3596 static struct ast_context *local_contexts = NULL;
3597 static struct ast_context *contexts = NULL;
3598 struct ast_context;
3599 struct ast_app;
3600 #ifdef LOW_MEMORY
3601 #define EXT_DATA_SIZE 256
3602 #else
3603 #define EXT_DATA_SIZE 8192
3604 #endif
3605 
3606 #ifdef NOT_ANYMORE
3608 #endif
3609 
3610 #define SWITCH_DATA_LENGTH 256
3611 
3612 static const char *ast_get_extension_app(struct ast_exten *e)
3613 {
3614  return e ? e->app : NULL;
3615 }
3616 
3617 static const char *ast_get_extension_name(struct ast_exten *exten)
3618 {
3619  return exten ? exten->exten : NULL;
3620 }
3621 
3623 
3624 /*! \brief ast_change_hint: Change hint for an extension */
3625 static int ast_change_hint(struct ast_exten *oe, struct ast_exten *ne)
3626 {
3627  struct ast_hint *hint;
3628  int res = -1;
3629 
3630  AST_RWLIST_TRAVERSE(&hints, hint, list) {
3631  if (hint->exten == oe) {
3632  hint->exten = ne;
3633  res = 0;
3634  break;
3635  }
3636  }
3637 
3638  return res;
3639 }
3640 
3641 /*! \brief ast_add_hint: Add hint to hint list, check initial extension state */
3642 static int ast_add_hint(struct ast_exten *e)
3643 {
3644  struct ast_hint *hint;
3645 
3646  if (!e)
3647  return -1;
3648 
3649 
3650  /* Search if hint exists, do nothing */
3651  AST_RWLIST_TRAVERSE(&hints, hint, list) {
3652  if (hint->exten == e) {
3653  if (option_debug > 1)
3654  ast_log(LOG_DEBUG, "HINTS: Not re-adding existing hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e));
3655  return -1;
3656  }
3657  }
3658 
3659  if (option_debug > 1)
3660  ast_log(LOG_DEBUG, "HINTS: Adding hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e));
3661 
3662  if (!(hint = ast_calloc(1, sizeof(*hint)))) {
3663  return -1;
3664  }
3665  /* Initialize and insert new item at the top */
3666  hint->exten = e;
3667  AST_RWLIST_INSERT_HEAD(&hints, hint, list);
3668 
3669  return 0;
3670 }
3671 
3672 /*! \brief add the extension in the priority chain.
3673  * returns 0 on success, -1 on failure
3674  */
3675 static int add_pri(struct ast_context *con, struct ast_exten *tmp,
3676  struct ast_exten *el, struct ast_exten *e, int replace)
3677 {
3678  struct ast_exten *ep;
3679 
3680  for (ep = NULL; e ; ep = e, e = e->peer) {
3681  if (e->priority >= tmp->priority)
3682  break;
3683  }
3684  if (!e) { /* go at the end, and ep is surely set because the list is not empty */
3685  ep->peer = tmp;
3686  return 0; /* success */
3687  }
3688  if (e->priority == tmp->priority) {
3689  /* Can't have something exactly the same. Is this a
3690  replacement? If so, replace, otherwise, bonk. */
3691  if (!replace) {
3692  ast_log(LOG_WARNING, "Unable to register extension '%s', priority %d in '%s', already in use\n", tmp->exten, tmp->priority, con->name);
3693  tmp->datad(tmp->data);
3694  free(tmp);
3695  return -1;
3696  }
3697  /* we are replacing e, so copy the link fields and then update
3698  * whoever pointed to e to point to us
3699  */
3700  tmp->next = e->next; /* not meaningful if we are not first in the peer list */
3701  tmp->peer = e->peer; /* always meaningful */
3702  if (ep) /* We're in the peer list, just insert ourselves */
3703  ep->peer = tmp;
3704  else if (el) /* We're the first extension. Take over e's functions */
3705  el->next = tmp;
3706  else /* We're the very first extension. */
3707  con->root = tmp;
3708  if (tmp->priority == PRIORITY_HINT)
3709  ast_change_hint(e,tmp);
3710  /* Destroy the old one */
3711  e->datad(e->data);
3712  free(e);
3713  } else { /* Slip ourselves in just before e */
3714  tmp->peer = e;
3715  tmp->next = e->next; /* extension chain, or NULL if e is not the first extension */
3716  if (ep) /* Easy enough, we're just in the peer list */
3717  ep->peer = tmp;
3718  else { /* we are the first in some peer list, so link in the ext list */
3719  if (el)
3720  el->next = tmp; /* in the middle... */
3721  else
3722  con->root = tmp; /* ... or at the head */
3723  e->next = NULL; /* e is no more at the head, so e->next must be reset */
3724  }
3725  /* And immediately return success. */
3726  if (tmp->priority == PRIORITY_HINT)
3727  ast_add_hint(tmp);
3728  }
3729  return 0;
3730 }
3731 
3732 /*! \brief ast_remove_hint: Remove hint from extension */
3733 static int ast_remove_hint(struct ast_exten *e)
3734 {
3735  /* Cleanup the Notifys if hint is removed */
3736  struct ast_hint *hint;
3737  struct ast_state_cb *cblist, *cbprev;
3738  int res = -1;
3739 
3740  if (!e)
3741  return -1;
3742 
3743  AST_RWLIST_TRAVERSE_SAFE_BEGIN(&hints, hint, list) {
3744  if (hint->exten == e) {
3745  cbprev = NULL;
3746  cblist = hint->callbacks;
3747  while (cblist) {
3748  /* Notify with -1 and remove all callbacks */
3749  cbprev = cblist;
3750  cblist = cblist->next;
3751  free(cbprev);
3752  }
3753  hint->callbacks = NULL;
3754  AST_RWLIST_REMOVE_CURRENT(&hints, list);
3755  free(hint);
3756  res = 0;
3757  break;
3758  }
3759  }
3760  AST_RWLIST_TRAVERSE_SAFE_END
3761 
3762  return res;
3763 }
3764 
3765 static void destroy_exten(struct ast_exten *e)
3766 {
3767  if (e->priority == PRIORITY_HINT)
3768  ast_remove_hint(e);
3769 
3770  if (e->datad)
3771  e->datad(e->data);
3772  free(e);
3773 }
3774 
3775 char *days[] =
3776 {
3777  "sun",
3778  "mon",
3779  "tue",
3780  "wed",
3781  "thu",
3782  "fri",
3783  "sat",
3784  NULL,
3785 };
3786 
3787 char *months[] =
3788 {
3789  "jan",
3790  "feb",
3791  "mar",
3792  "apr",
3793  "may",
3794  "jun",
3795  "jul",
3796  "aug",
3797  "sep",
3798  "oct",
3799  "nov",
3800  "dec",
3801  NULL,
3802 };
3803 
3804 int ast_build_timing(struct ast_timing *i, const char *info_in);
3805 
3806 int ast_build_timing(struct ast_timing *i, const char *info_in)
3807 {
3808  char *info;
3809  int j, num_fields, last_sep = -1;
3810 
3811  i->timezone = NULL;
3812 
3813  /* Check for empty just in case */
3814  if (ast_strlen_zero(info_in)) {
3815  return 0;
3816  }
3817 
3818  /* make a copy just in case we were passed a static string */
3819  info = ast_strdupa(info_in);
3820 
3821  /* count the number of fields in the timespec */
3822  for (j = 0, num_fields = 1; info[j] != '\0'; j++) {
3823  if (info[j] == '|' || info[j] == ',') {
3824  last_sep = j;
3825  num_fields++;
3826  }
3827  }
3828 
3829  /* save the timezone, if it is specified */
3830  if (num_fields == 5) {
3831  i->timezone = ast_strdup(info + last_sep + 1);
3832  }
3833 
3834  /* Assume everything except time */
3835  i->monthmask = 0xfff; /* 12 bits */
3836  i->daymask = 0x7fffffffU; /* 31 bits */
3837  i->dowmask = 0x7f; /* 7 bits */
3838  /* on each call, use strsep() to move info to the next argument */
3839  get_timerange(i, strsep(&info, "|,"));
3840  if (info)
3841  i->dowmask = get_range(strsep(&info, "|,"), 7, days, "day of week");
3842  if (info)
3843  i->daymask = get_range(strsep(&info, "|,"), 31, NULL, "day");
3844  if (info)
3845  i->monthmask = get_range(strsep(&info, "|,"), 12, months, "month");
3846  return 1;
3847 }
3848 
3849 /*!
3850  * \brief helper functions to sort extensions and patterns in the desired way,
3851  * so that more specific patterns appear first.
3852  *
3853  * ext_cmp1 compares individual characters (or sets of), returning
3854  * an int where bits 0-7 are the ASCII code of the first char in the set,
3855  * while bit 8-15 are the cardinality of the set minus 1.
3856  * This way more specific patterns (smaller cardinality) appear first.
3857  * Wildcards have a special value, so that we can directly compare them to
3858  * sets by subtracting the two values. In particular:
3859  * 0x000xx one character, xx
3860  * 0x0yyxx yy character set starting with xx
3861  * 0x10000 '.' (one or more of anything)
3862  * 0x20000 '!' (zero or more of anything)
3863  * 0x30000 NUL (end of string)
3864  * 0x40000 error in set.
3865  * The pointer to the string is advanced according to needs.
3866  * NOTES:
3867  * 1. the empty set is equivalent to NUL.
3868  * 2. given that a full set has always 0 as the first element,
3869  * we could encode the special cases as 0xffXX where XX
3870  * is 1, 2, 3, 4 as used above.
3871  */
3872 static int ext_cmp1(const char **p)
3873 {
3874  uint32_t chars[8];
3875  int c, cmin = 0xff, count = 0;
3876  const char *end;
3877 
3878  /* load, sign extend and advance pointer until we find
3879  * a valid character.
3880  */
3881  while ( (c = *(*p)++) && (c == ' ' || c == '-') )
3882  ; /* ignore some characters */
3883 
3884  /* always return unless we have a set of chars */
3885  switch (c) {
3886  default: /* ordinary character */
3887  return 0x0000 | (c & 0xff);
3888 
3889  case 'N': /* 2..9 */
3890  return 0x0700 | '2' ;
3891 
3892  case 'X': /* 0..9 */
3893  return 0x0900 | '0';
3894 
3895  case 'Z': /* 1..9 */
3896  return 0x0800 | '1';
3897 
3898  case '.': /* wildcard */
3899  return 0x10000;
3900 
3901  case '!': /* earlymatch */
3902  return 0x20000; /* less specific than NULL */
3903 
3904  case '\0': /* empty string */
3905  *p = NULL;
3906  return 0x30000;
3907 
3908  case '[': /* pattern */
3909  break;
3910  }
3911  /* locate end of set */
3912  end = strchr(*p, ']');
3913 
3914  if (end == NULL) {
3915  ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n");
3916  return 0x40000; /* XXX make this entry go last... */
3917  }
3918 
3919  memset(chars, '\0', sizeof(chars)); /* clear all chars in the set */
3920  for (; *p < end ; (*p)++) {
3921  unsigned char c1, c2; /* first-last char in range */
3922  c1 = (unsigned char)((*p)[0]);
3923  if (*p + 2 < end && (*p)[1] == '-') { /* this is a range */
3924  c2 = (unsigned char)((*p)[2]);
3925  *p += 2; /* skip a total of 3 chars */
3926  } else /* individual character */
3927  c2 = c1;
3928  if (c1 < cmin)
3929  cmin = c1;
3930  for (; c1 <= c2; c1++) {
3931  uint32_t mask = 1 << (c1 % 32);
3932  if ( (chars[ c1 / 32 ] & mask) == 0)
3933  count += 0x100;
3934  chars[ c1 / 32 ] |= mask;
3935  }
3936  }
3937  (*p)++;
3938  return count == 0 ? 0x30000 : (count | cmin);
3939 }
3940 
3941 /*!
3942  * \brief the full routine to compare extensions in rules.
3943  */
3944 static int ext_cmp(const char *a, const char *b)
3945 {
3946  /* make sure non-patterns come first.
3947  * If a is not a pattern, it either comes first or
3948  * we use strcmp to compare the strings.
3949  */
3950  int ret = 0;
3951 
3952  if (a[0] != '_')
3953  return (b[0] == '_') ? -1 : strcmp(a, b);
3954 
3955  /* Now we know a is a pattern; if b is not, a comes first */
3956  if (b[0] != '_')
3957  return 1;
3958 #if 0 /* old mode for ext matching */
3959  return strcmp(a, b);
3960 #endif
3961  /* ok we need full pattern sorting routine */
3962  while (!ret && a && b)
3963  ret = ext_cmp1(&a) - ext_cmp1(&b);
3964  if (ret == 0)
3965  return 0;
3966  else
3967  return (ret > 0) ? 1 : -1;
3968 }
3969 
3970 /*! \brief copy a string skipping whitespace */
3971 static int ext_strncpy(char *dst, const char *src, int len)
3972 {
3973  int count=0;
3974 
3975  while (*src && (count < len - 1)) {
3976  switch(*src) {
3977  case ' ':
3978  /* otherwise exten => [a-b],1,... doesn't work */
3979  /* case '-': */
3980  /* Ignore */
3981  break;
3982  default:
3983  *dst = *src;
3984  dst++;
3985  }
3986  src++;
3987  count++;
3988  }
3989  *dst = '\0';
3990 
3991  return count;
3992 }
3993 
3994 /*
3995  * Wrapper around _extension_match_core() to do performance measurement
3996  * using the profiling code.
3997  */
3998 int ast_check_timing(const struct ast_timing *i);
3999 
4000 int ast_check_timing(const struct ast_timing *i)
4001 {
4002  /* sorry, but this feature will NOT be available
4003  in the standalone version */
4004  return 0;
4005 }
4006 
4007 #ifdef NOT_ANYMORE
4008 static struct ast_switch *pbx_findswitch(const char *sw)
4009 {
4010  struct ast_switch *asw;
4011 
4012  AST_RWLIST_TRAVERSE(&switches, asw, list) {
4013  if (!strcasecmp(asw->name, sw))
4014  break;
4015  }
4016 
4017  return asw;
4018 }
4019 #endif
4020 
4021 
4022 static struct ast_context *ast_walk_contexts(struct ast_context *con);
4023 
4024 static struct ast_context *ast_walk_contexts(struct ast_context *con)
4025 {
4026  return con ? con->next : contexts;
4027 }
4028 
4029 struct ast_context *localized_walk_contexts(struct ast_context *con);
4030 struct ast_context *localized_walk_contexts(struct ast_context *con)
4031 {
4032  return ast_walk_contexts(con);
4033 }
4034 
4035 
4036 
4037 static struct ast_exten *ast_walk_context_extensions(struct ast_context *con,
4038  struct ast_exten *exten);
4039 
4040 static struct ast_exten *ast_walk_context_extensions(struct ast_context *con,
4041  struct ast_exten *exten)
4042 {
4043  if (!exten)
4044  return con ? con->root : NULL;
4045  else
4046  return exten->next;
4047 }
4048 
4049 struct ast_exten *localized_walk_context_extensions(struct ast_context *con,
4050  struct ast_exten *exten);
4051 struct ast_exten *localized_walk_context_extensions(struct ast_context *con,
4052  struct ast_exten *exten)
4053 {
4054  return ast_walk_context_extensions(con,exten);
4055 }
4056 
4057 
4058 static struct ast_exten *ast_walk_extension_priorities(struct ast_exten *exten,
4059  struct ast_exten *priority);
4060 
4061 static struct ast_exten *ast_walk_extension_priorities(struct ast_exten *exten,
4062  struct ast_exten *priority)
4063 {
4064  return priority ? priority->peer : exten;
4065 }
4066 
4067 struct ast_exten *localized_walk_extension_priorities(struct ast_exten *exten,
4068  struct ast_exten *priority);
4069 struct ast_exten *localized_walk_extension_priorities(struct ast_exten *exten,
4070  struct ast_exten *priority)
4071 {
4072  return ast_walk_extension_priorities(exten, priority);
4073 }
4074 
4075 
4076 
4077 static struct ast_include *ast_walk_context_includes(struct ast_context *con,
4078  struct ast_include *inc);
4079 
4080 static struct ast_include *ast_walk_context_includes(struct ast_context *con,
4081  struct ast_include *inc)
4082 {
4083  if (!inc)
4084  return con ? con->includes : NULL;
4085  else
4086  return inc->next;
4087 }
4088 
4089 int ast_context_includes_count(struct ast_context *con);
4090 int ast_context_includes_count(struct ast_context *con)
4091 {
4092  int c = 0;
4093  struct ast_include *inc = NULL;
4094 
4095  while ((inc = ast_walk_context_includes(con, inc))) {
4096  c++;
4097  }
4098 
4099  return c;
4100 }
4101 
4102 struct ast_include *localized_walk_context_includes(struct ast_context *con,
4103  struct ast_include *inc);
4104 struct ast_include *localized_walk_context_includes(struct ast_context *con,
4105  struct ast_include *inc)
4106 {
4107  return ast_walk_context_includes(con, inc);
4108 }
4109 
4110 static struct ast_ignorepat *ast_walk_context_ignorepats(struct ast_context *con,
4111  struct ast_ignorepat *ip);
4112 
4113 static struct ast_ignorepat *ast_walk_context_ignorepats(struct ast_context *con,
4114  struct ast_ignorepat *ip)
4115 {
4116  if (!ip)
4117  return con ? con->ignorepats : NULL;
4118  else
4119  return ip->next;
4120 }
4121 
4122 int ast_context_ignorepats_count(struct ast_context *con);
4123 int ast_context_ignorepats_count(struct ast_context *con)
4124 {
4125  int c = 0;
4126  struct ast_ignorepat *ip = NULL;
4127 
4128  while ((ip = ast_walk_context_ignorepats(con, ip))) {
4129  c++;
4130  }
4131 
4132  return c;
4133 }
4134 
4135 
4136 static struct ast_sw *ast_walk_context_switches(struct ast_context *con,
4137  struct ast_sw *sw);
4138 
4139 static struct ast_sw *ast_walk_context_switches(struct ast_context *con,
4140  struct ast_sw *sw)
4141 {
4142  if (!sw)
4143  return con ? AST_LIST_FIRST(&con->alts) : NULL;
4144  else
4145  return AST_LIST_NEXT(sw, list);
4146 }
4147 
4148 struct ast_sw *localized_walk_context_switches(struct ast_context *con,
4149  struct ast_sw *sw);
4150 struct ast_sw *localized_walk_context_switches(struct ast_context *con,
4151  struct ast_sw *sw)
4152 {
4153  return ast_walk_context_switches(con, sw);
4154 }
4155 
4156 int ast_context_switches_count(struct ast_context *con);
4157 int ast_context_switches_count(struct ast_context *con)
4158 {
4159  int c = 0;
4160  struct ast_sw *sw = NULL;
4161 
4162  while ((sw = ast_walk_context_switches(con, sw))) {
4163  c++;
4164  }
4165 
4166  return c;
4167 }
4168 
4169 
4170 static struct ast_context *ast_context_find(const char *name);
4171 
4172 static struct ast_context *ast_context_find(const char *name)
4173 {
4174  struct ast_context *tmp = NULL;
4175  while ( (tmp = ast_walk_contexts(tmp)) ) {
4176  if (!name || !strcasecmp(name, tmp->name))
4177  break;
4178  }
4179  return tmp;
4180 }
4181 
4182 /*
4183  * Internal function for ast_extension_{match|close}
4184  * return 0 on no-match, 1 on match, 2 on early match.
4185  * mode is as follows:
4186  * E_MATCH success only on exact match
4187  * E_MATCHMORE success only on partial match (i.e. leftover digits in pattern)
4188  * E_CANMATCH either of the above.
4189  */
4190 
4191 static int _extension_match_core(const char *pattern, const char *data, enum ext_match_t mode)
4192 {
4193  mode &= E_MATCH_MASK; /* only consider the relevant bits */
4194 
4195  if ( (mode == E_MATCH) && (pattern[0] == '_') && (strcasecmp(pattern,data)==0) ) /* note: if this test is left out, then _x. will not match _x. !!! */
4196  return 1;
4197 
4198  if (pattern[0] != '_') { /* not a pattern, try exact or partial match */
4199  int ld = strlen(data), lp = strlen(pattern);
4200 
4201  if (lp < ld) /* pattern too short, cannot match */
4202  return 0;
4203  /* depending on the mode, accept full or partial match or both */
4204  if (mode == E_MATCH)
4205  return !strcmp(pattern, data); /* 1 on match, 0 on fail */
4206  if (ld == 0 || !strncasecmp(pattern, data, ld)) /* partial or full match */
4207  return (mode == E_MATCHMORE) ? lp > ld : 1; /* XXX should consider '!' and '/' ? */
4208  else
4209  return 0;
4210  }
4211  pattern++; /* skip leading _ */
4212  /*
4213  * XXX below we stop at '/' which is a separator for the CID info. However we should
4214  * not store '/' in the pattern at all. When we insure it, we can remove the checks.
4215  */
4216  while (*data && *pattern && *pattern != '/') {
4217  const char *end;
4218 
4219  if (*data == '-') { /* skip '-' in data (just a separator) */
4220  data++;
4221  continue;
4222  }
4223  switch (toupper(*pattern)) {
4224  case '[': /* a range */
4225  end = strchr(pattern+1, ']'); /* XXX should deal with escapes ? */
4226  if (end == NULL) {
4227  ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n");
4228  return 0; /* unconditional failure */
4229  }
4230  for (pattern++; pattern != end; pattern++) {
4231  if (pattern+2 < end && pattern[1] == '-') { /* this is a range */
4232  if (*data >= pattern[0] && *data <= pattern[2])
4233  break; /* match found */
4234  else {
4235  pattern += 2; /* skip a total of 3 chars */
4236  continue;
4237  }
4238  } else if (*data == pattern[0])
4239  break; /* match found */
4240  }
4241  if (pattern == end)
4242  return 0;
4243  pattern = end; /* skip and continue */
4244  break;
4245  case 'N':
4246  if (*data < '2' || *data > '9')
4247  return 0;
4248  break;
4249  case 'X':
4250  if (*data < '0' || *data > '9')
4251  return 0;
4252  break;
4253  case 'Z':
4254  if (*data < '1' || *data > '9')
4255  return 0;
4256  break;
4257  case '.': /* Must match, even with more digits */
4258  return 1;
4259  case '!': /* Early match */
4260  return 2;
4261  case ' ':
4262  case '-': /* Ignore these in patterns */
4263  data--; /* compensate the final data++ */
4264  break;
4265  default:
4266  if (*data != *pattern)
4267  return 0;
4268  }
4269  data++;
4270  pattern++;
4271  }
4272  if (*data) /* data longer than pattern, no match */
4273  return 0;
4274  /*
4275  * match so far, but ran off the end of the data.
4276  * Depending on what is next, determine match or not.
4277  */
4278  if (*pattern == '\0' || *pattern == '/') /* exact match */
4279  return (mode == E_MATCHMORE) ? 0 : 1; /* this is a failure for E_MATCHMORE */
4280  else if (*pattern == '!') /* early match */
4281  return 2;
4282  else /* partial match */
4283  return (mode == E_MATCH) ? 0 : 1; /* this is a failure for E_MATCH */
4284 }
4285 
4286 static int extension_match_core(const char *pattern, const char *data, enum ext_match_t mode)
4287 {
4288  int i;
4289  i = _extension_match_core(pattern, data, mode);
4290  return i;
4291 }
4292 
4293 static int ast_extension_match(const char *pattern, const char *data);
4294 
4295 static int ast_extension_match(const char *pattern, const char *data)
4296 {
4297  return extension_match_core(pattern, data, E_MATCH);
4298 }
4299 
4300 static int matchcid(const char *cidpattern, const char *callerid)
4301 {
4302  /* If the Caller*ID pattern is empty, then we're matching NO Caller*ID, so
4303  failing to get a number should count as a match, otherwise not */
4304 
4305  if (ast_strlen_zero(callerid))
4306  return ast_strlen_zero(cidpattern) ? 1 : 0;
4307 
4308  return ast_extension_match(cidpattern, callerid);
4309 }
4310 
4311 static inline int include_valid(struct ast_include *i)
4312 {
4313  if (!i->hastime)
4314  return 1;
4315 
4316  return ast_check_timing(&(i->timing));
4317 }
4318 
4319 
4320 
4321 static struct ast_exten *pbx_find_extension(struct ast_channel *chan,
4322  struct ast_context *bypass,
4323  struct pbx_find_info *q,
4324  const char *context,
4325  const char *exten,
4326  int priority,
4327  const char *label,
4328  const char *callerid,
4329  enum ext_match_t action);
4330 
4331 
4332 static struct ast_exten *pbx_find_extension(struct ast_channel *chan,
4333  struct ast_context *bypass,
4334  struct pbx_find_info *q,
4335  const char *context,
4336  const char *exten,
4337  int priority,
4338  const char *label,
4339  const char *callerid,
4340  enum ext_match_t action)
4341 {
4342  int x;
4343  struct ast_context *tmp;
4344  struct ast_exten *e, *eroot;
4345  struct ast_include *i;
4346 
4347  if (!context) {
4348  return NULL;
4349  }
4350 
4351  /* Initialize status if appropriate */
4352  if (q->stacklen == 0) {
4353  q->status = STATUS_NO_CONTEXT;
4354  q->swo = NULL;
4355  q->data = NULL;
4356  q->foundcontext = NULL;
4357  } else if (q->stacklen >= AST_PBX_MAX_STACK) {
4358  ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n");
4359  return NULL;
4360  }
4361  /* Check first to see if we've already been checked */
4362  for (x = 0; x < q->stacklen; x++) {
4363  if (!strcasecmp(q->incstack[x], context))
4364  return NULL;
4365  }
4366  if (bypass) /* bypass means we only look there */
4367  tmp = bypass;
4368  else { /* look in contexts */
4369  tmp = NULL;
4370  while ((tmp = ast_walk_contexts(tmp)) ) {
4371  if (!strcmp(tmp->name, context))
4372  break;
4373  }
4374  if (!tmp)
4375  return NULL;
4376  }
4377  if (q->status < STATUS_NO_EXTENSION)
4378  q->status = STATUS_NO_EXTENSION;
4379 
4380  /* scan the list trying to match extension and CID */
4381  eroot = NULL;
4382  while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) {
4383  int match = extension_match_core(eroot->exten, exten, action);
4384  /* 0 on fail, 1 on match, 2 on earlymatch */
4385 
4386  if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid)))
4387  continue; /* keep trying */
4388  if (match == 2 && action == E_MATCHMORE) {
4389  /* We match an extension ending in '!'.
4390  * The decision in this case is final and is NULL (no match).
4391  */
4392  return NULL;
4393  }
4394  /* found entry, now look for the right priority */
4395  if (q->status < STATUS_NO_PRIORITY)
4396  q->status = STATUS_NO_PRIORITY;
4397  e = NULL;
4398  while ( (e = ast_walk_extension_priorities(eroot, e)) ) {
4399  /* Match label or priority */
4400  if (action == E_FINDLABEL) {
4401  if (q->status < STATUS_NO_LABEL)
4402  q->status = STATUS_NO_LABEL;
4403  if (label && e->label && !strcmp(label, e->label))
4404  break; /* found it */
4405  } else if (e->priority == priority) {
4406  break; /* found it */
4407  } /* else keep searching */
4408  }
4409  if (e) { /* found a valid match */
4410  q->status = STATUS_SUCCESS;
4411  q->foundcontext = context;
4412  return e;
4413  }
4414  }
4415 #ifdef NOT_RIGHT_NOW
4416  /* Check alternative switches??? */
4417  AST_LIST_TRAVERSE(&tmp->alts, sw, list) {
4418  struct ast_switch *asw = pbx_findswitch(sw->name);
4419  ast_switch_f *aswf = NULL;
4420  char *datap;
4421 
4422  if (!asw) {
4423  ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name);
4424  continue;
4425  }
4426  /* No need to Substitute variables now; we shouldn't be here if there's any */
4427 
4428  /* equivalent of extension_match_core() at the switch level */
4429  if (action == E_CANMATCH)
4430  aswf = asw->canmatch;
4431  else if (action == E_MATCHMORE)
4432  aswf = asw->matchmore;
4433  else /* action == E_MATCH */
4434  aswf = asw->exists;
4435  datap = sw->eval ? sw->tmpdata : sw->data;
4436  res = !aswf ? 0 : aswf(chan, context, exten, priority, callerid, datap);
4437  if (res) { /* Got a match */
4438  q->swo = asw;
4439  q->data = datap;
4440  q->foundcontext = context;
4441  /* XXX keep status = STATUS_NO_CONTEXT ? */
4442  return NULL;
4443  }
4444  }
4445 #endif
4446  q->incstack[q->stacklen++] = tmp->name; /* Setup the stack */
4447  /* Now try any includes we have in this context */
4448  for (i = tmp->includes; i; i = i->next) {
4449  if (include_valid(i)) {
4450  if ((e = pbx_find_extension(NULL, bypass, q, i->rname, exten, priority, label, callerid, action)))
4451  return e;
4452  if (q->swo)
4453  return NULL;
4454  }
4455  }
4456  return NULL;
4457 }
4458 
4459 struct ast_exten *localized_find_extension(struct ast_context *bypass,
4460  struct pbx_find_info *q,
4461  const char *context,
4462  const char *exten,
4463  int priority,
4464  const char *label,
4465  const char *callerid,
4466  enum ext_match_t action);
4467 
4468 struct ast_exten *localized_find_extension(struct ast_context *bypass,
4469  struct pbx_find_info *q,
4470  const char *context,
4471  const char *exten,
4472  int priority,
4473  const char *label,
4474  const char *callerid,
4475  enum ext_match_t action)
4476 {
4477  return pbx_find_extension(NULL, bypass, q, context, exten, priority, label, callerid, action);
4478 }
4479 
4480 
4481 static struct ast_context *contexts;
4482 AST_RWLOCK_DEFINE_STATIC(conlock); /*!< Lock for the ast_context list */
4483 
4484 static const char *ast_get_context_name(struct ast_context *con);
4485 
4486 static const char *ast_get_context_name(struct ast_context *con)
4487 {
4488  return con ? con->name : NULL;
4489 }
4490 
4491 /*
4492  * errno values
4493  * ENOMEM - out of memory
4494  * EBUSY - can't lock
4495  * EEXIST - already included
4496  * EINVAL - there is no existence of context for inclusion
4497  */
4498 static int ast_context_add_include2(struct ast_context *con, const char *value,
4499  const char *registrar);
4500 
4501 static int ast_context_add_include2(struct ast_context *con, const char *value,
4502  const char *registrar)
4503 {
4504  struct ast_include *new_include;
4505  char *c;
4506  struct ast_include *i, *il = NULL; /* include, include_last */
4507  int length;
4508  char *p;
4509 
4510  length = sizeof(struct ast_include);
4511  length += 2 * (strlen(value) + 1);
4512 
4513  /* allocate new include structure ... */
4514  if (!(new_include = ast_calloc(1, length)))
4515  return -1;
4516  /* Fill in this structure. Use 'p' for assignments, as the fields
4517  * in the structure are 'const char *'
4518  */
4519  p = new_include->stuff;
4520  new_include->name = p;
4521  strcpy(p, value);
4522  p += strlen(value) + 1;
4523  new_include->rname = p;
4524  strcpy(p, value);
4525  /* Strip off timing info, and process if it is there */
4526  if ( (c = strchr(p, '|')) || (c = strchr(p, ',')) ) {
4527  *c++ = '\0';
4528  new_include->hastime = ast_build_timing(&(new_include->timing), c);
4529  }
4530  new_include->next = NULL;
4531  new_include->registrar = registrar;
4532 
4533 
4534  /* ... go to last include and check if context is already included too... */
4535  for (i = con->includes; i; i = i->next) {
4536  if (!strcasecmp(i->name, new_include->name)) {
4537  free(new_include);
4538  errno = EEXIST;
4539  return -1;
4540  }
4541  il = i;
4542  }
4543 
4544  /* ... include new context into context list, unlock, return */
4545  if (il)
4546  il->next = new_include;
4547  else
4548  con->includes = new_include;
4549  if (option_verbose > 2)
4550  ast_verbose(VERBOSE_PREFIX_3 "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con));
4551 
4552  return 0;
4553 }
4554 
4555 int localized_context_add_include2(struct ast_context *con, const char *value,
4556  const char *registrar);
4557 int localized_context_add_include2(struct ast_context *con, const char *value,
4558  const char *registrar)
4559 {
4560  return ast_context_add_include2(con, value, registrar);
4561 }
4562 
4563 
4564 
4565 static int ast_context_add_ignorepat2(struct ast_context *con, const char *value, const char *registrar);
4566 
4567 static int ast_context_add_ignorepat2(struct ast_context *con, const char *value, const char *registrar)
4568 {
4569  struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL;
4570  int length;
4571  length = sizeof(struct ast_ignorepat);
4572  length += strlen(value) + 1;
4573  if (!(ignorepat = ast_calloc(1, length)))
4574  return -1;
4575  /* The cast to char * is because we need to write the initial value.
4576  * The field is not supposed to be modified otherwise
4577  */
4578  strcpy((char *)ignorepat->pattern, value);
4579  ignorepat->next = NULL;
4580  ignorepat->registrar = registrar;
4581  for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) {
4582  ignorepatl = ignorepatc;
4583  if (!strcasecmp(ignorepatc->pattern, value)) {
4584  /* Already there */
4585  errno = EEXIST;
4586  return -1;
4587  }
4588  }
4589  if (ignorepatl)
4590  ignorepatl->next = ignorepat;
4591  else
4592  con->ignorepats = ignorepat;
4593  return 0;
4594 
4595 }
4596 
4597 int localized_context_add_ignorepat2(struct ast_context *con, const char *value, const char *registrar);
4598 
4599 int localized_context_add_ignorepat2(struct ast_context *con, const char *value, const char *registrar)
4600 {
4601  return ast_context_add_ignorepat2(con, value, registrar);
4602 }
4603 
4604 
4605 /*
4606  * Lock context list functions ...
4607  */
4608 
4609 static int ast_wrlock_contexts(void)
4610 {
4611  return ast_rwlock_wrlock(&conlock);
4612 }
4613 
4614 static int ast_unlock_contexts(void)
4615 {
4616  return ast_rwlock_unlock(&conlock);
4617 }
4618 
4619 static int ast_wrlock_context(struct ast_context *con)
4620 {
4621  return ast_rwlock_wrlock(&con->lock);
4622 }
4623 
4624 static int ast_unlock_context(struct ast_context *con)
4625 {
4626  return ast_rwlock_unlock(&con->lock);
4627 }
4628 
4629 /*
4630  * errno values
4631  * ENOMEM - out of memory
4632  * EBUSY - can't lock
4633  * EEXIST - already included
4634  * EINVAL - there is no existence of context for inclusion
4635  */
4636 static int ast_context_add_switch2(struct ast_context *con, const char *value,
4637  const char *data, int eval, const char *registrar);
4638 
4639 static int ast_context_add_switch2(struct ast_context *con, const char *value,
4640  const char *data, int eval, const char *registrar)
4641 {
4642  struct ast_sw *new_sw;
4643  struct ast_sw *i;
4644  int length;
4645  char *p;
4646 
4647  length = sizeof(struct ast_sw);
4648  length += strlen(value) + 1;
4649  if (data)
4650  length += strlen(data);
4651  length++;
4652  if (eval) {
4653  /* Create buffer for evaluation of variables */
4654  length += SWITCH_DATA_LENGTH;
4655  length++;
4656  }
4657 
4658  /* allocate new sw structure ... */
4659  if (!(new_sw = ast_calloc(1, length)))
4660  return -1;
4661  /* ... fill in this structure ... */
4662  p = new_sw->stuff;
4663  new_sw->name = p;
4664  strcpy(new_sw->name, value);
4665  p += strlen(value) + 1;
4666  new_sw->data = p;
4667  if (data) {
4668  strcpy(new_sw->data, data);
4669  p += strlen(data) + 1;
4670  } else {
4671  strcpy(new_sw->data, "");
4672  p++;
4673  }
4674  if (eval)
4675  new_sw->tmpdata = p;
4676  new_sw->eval = eval;
4677  new_sw->registrar = registrar;
4678 
4679  /* ... go to last sw and check if context is already swd too... */
4680  AST_LIST_TRAVERSE(&con->alts, i, list) {
4681  if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) {
4682  free(new_sw);
4683  errno = EEXIST;
4684  return -1;
4685  }
4686  }
4687 
4688  /* ... sw new context into context list, unlock, return */
4689  AST_LIST_INSERT_TAIL(&con->alts, new_sw, list);
4690 
4691  if (option_verbose > 2)
4692  ast_verbose(VERBOSE_PREFIX_3 "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con));
4693 
4694  return 0;
4695 }
4696 
4697 int localized_context_add_switch2(struct ast_context *con, const char *value,
4698  const char *data, int eval, const char *registrar);
4699 
4700 int localized_context_add_switch2(struct ast_context *con, const char *value,
4701  const char *data, int eval, const char *registrar)
4702 {
4703  return ast_context_add_switch2(con, value, data, eval, registrar);
4704 }
4705 
4706 static struct ast_context *__ast_context_create(struct ast_context **extcontexts, const char *name, const char *registrar, int existsokay)
4707 {
4708  struct ast_context *tmp, **loc_contexts;
4709  int length = sizeof(struct ast_context) + strlen(name) + 1;
4710 
4711  if (!extcontexts) {
4713  loc_contexts = &contexts;
4714  } else
4715  loc_contexts = extcontexts;
4716 
4717  for (tmp = *loc_contexts; tmp; tmp = tmp->next) {
4718  if (!strcasecmp(tmp->name, name)) {
4719  if (!existsokay) {
4720  ast_log(LOG_WARNING, "Tried to register context '%s', already in use\n", name);
4721  tmp = NULL;
4722  }
4723  if (!extcontexts)
4725  return tmp;
4726  }
4727  }
4728  if ((tmp = ast_calloc(1, length))) {
4729  ast_rwlock_init(&tmp->lock);
4730  strcpy(tmp->name, name);
4731  tmp->root = NULL;
4732  tmp->registrar = registrar;
4733  tmp->next = *loc_contexts;
4734  tmp->includes = NULL;
4735  tmp->ignorepats = NULL;
4736  *loc_contexts = tmp;
4737  if (option_debug)
4738  ast_log(LOG_DEBUG, "Registered context '%s'\n", tmp->name);
4739  if (option_verbose > 2)
4740  ast_verbose( VERBOSE_PREFIX_3 "Registered extension context '%s'\n", tmp->name);
4741  }
4742 
4743  if (!extcontexts)
4745  return tmp;
4746 }
4747 
4748 /*! \brief
4749  * Main interface to add extensions to the list for out context.
4750  *
4751  * We sort extensions in order of matching preference, so that we can
4752  * stop the search as soon as we find a suitable match.
4753  * This ordering also takes care of wildcards such as '.' (meaning
4754  * "one or more of any character") and '!' (which is 'earlymatch',
4755  * meaning "zero or more of any character" but also impacts the
4756  * return value from CANMATCH and EARLYMATCH.
4757  *
4758  * The extension match rules defined in the devmeeting 2006.05.05 are
4759  * quite simple: WE SELECT THE LONGEST MATCH.
4760  * In detail, "longest" means the number of matched characters in
4761  * the extension. In case of ties (e.g. _XXX and 333) in the length
4762  * of a pattern, we give priority to entries with the smallest cardinality
4763  * (e.g, [5-9] comes before [2-8] before the former has only 5 elements,
4764  * while the latter has 7, etc.
4765  * In case of same cardinality, the first element in the range counts.
4766  * If we still have a tie, any final '!' will make this as a possibly
4767  * less specific pattern.
4768  *
4769  * EBUSY - can't lock
4770  * EEXIST - extension with the same priority exist and no replace is set
4771  *
4772  */
4773 static int ast_add_extension2(struct ast_context *con,
4774  int replace, const char *extension, int priority, const char *label, const char *callerid,
4775  const char *application, void *data, void (*datad)(void *),
4776  const char *registrar)
4777 {
4778  /*
4779  * Sort extensions (or patterns) according to the rules indicated above.
4780  * These are implemented by the function ext_cmp()).
4781  * All priorities for the same ext/pattern/cid are kept in a list,
4782  * using the 'peer' field as a link field..
4783  */
4784  struct ast_exten *tmp, *e, *el = NULL;
4785  int res;
4786  int length;
4787  char *p;
4788 
4789  /* if we are adding a hint, and there are global variables, and the hint
4790  contains variable references, then expand them --- NOT In this situation!!!
4791  */
4792 
4793  length = sizeof(struct ast_exten);
4794  length += strlen(extension) + 1;
4795  length += strlen(application) + 1;
4796  if (label)
4797  length += strlen(label) + 1;
4798  if (callerid)
4799  length += strlen(callerid) + 1;
4800  else
4801  length ++; /* just the '\0' */
4802 
4803  /* Be optimistic: Build the extension structure first */
4804  if (datad == NULL)
4805  datad = null_datad;
4806  if (!(tmp = ast_calloc(1, length)))
4807  return -1;
4808 
4809  /* use p as dst in assignments, as the fields are const char * */
4810  p = tmp->stuff;
4811  if (label) {
4812  tmp->label = p;
4813  strcpy(p, label);
4814  p += strlen(label) + 1;
4815  }
4816  tmp->exten = p;
4817  p += ext_strncpy(p, extension, strlen(extension) + 1) + 1;
4818  tmp->priority = priority;
4819  tmp->cidmatch = p; /* but use p for assignments below */
4820  if (callerid) {
4821  p += ext_strncpy(p, callerid, strlen(callerid) + 1) + 1;
4822  tmp->matchcid = 1;
4823  } else {
4824  *p++ = '\0';
4825  tmp->matchcid = 0;
4826  }
4827  tmp->app = p;
4828  strcpy(p, application);
4829  tmp->parent = con;
4830  tmp->data = data;
4831  tmp->datad = datad;
4832  tmp->registrar = registrar;
4833 
4834  res = 0; /* some compilers will think it is uninitialized otherwise */
4835  for (e = con->root; e; el = e, e = e->next) { /* scan the extension list */
4836  res = ext_cmp(e->exten, extension);
4837  if (res == 0) { /* extension match, now look at cidmatch */
4838  if (!e->matchcid && !tmp->matchcid)
4839  res = 0;
4840  else if (tmp->matchcid && !e->matchcid)
4841  res = 1;
4842  else if (e->matchcid && !tmp->matchcid)
4843  res = -1;
4844  else
4845  res = strcasecmp(e->cidmatch, tmp->cidmatch);
4846  }
4847  if (res >= 0)
4848  break;
4849  }
4850  if (e && res == 0) { /* exact match, insert in the pri chain */
4851  res = add_pri(con, tmp, el, e, replace);
4852  if (res < 0) {
4853  errno = EEXIST; /* XXX do we care ? */
4854  return 0; /* XXX should we return -1 maybe ? */
4855  }
4856  } else {
4857  /*
4858  * not an exact match, this is the first entry with this pattern,
4859  * so insert in the main list right before 'e' (if any)
4860  */
4861  tmp->next = e;
4862  if (el)
4863  el->next = tmp;
4864  else
4865  con->root = tmp;
4866  if (tmp->priority == PRIORITY_HINT)
4867  ast_add_hint(tmp);
4868  }
4869  if (option_debug) {
4870  if (tmp->matchcid) {
4871  ast_log(LOG_DEBUG, "Added extension '%s' priority %d (CID match '%s') to %s\n",
4872  tmp->exten, tmp->priority, tmp->cidmatch, con->name);
4873  } else {
4874  ast_log(LOG_DEBUG, "Added extension '%s' priority %d to %s\n",
4875  tmp->exten, tmp->priority, con->name);
4876  }
4877  }
4878  if (option_verbose > 2) {
4879  if (tmp->matchcid) {
4880  ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d (CID match '%s')to %s\n",
4881  tmp->exten, tmp->priority, tmp->cidmatch, con->name);
4882  } else {
4883  ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d to %s\n",
4884  tmp->exten, tmp->priority, con->name);
4885  }
4886  }
4887  return 0;
4888 }
4889 
4890 int localized_add_extension2(struct ast_context *con,
4891  int replace, const char *extension, int priority, const char *label, const char *callerid,
4892  const char *application, void *data, void (*datad)(void *),
4893  const char *registrar);
4894 
4895 int localized_add_extension2(struct ast_context *con,
4896  int replace, const char *extension, int priority, const char *label, const char *callerid,
4897  const char *application, void *data, void (*datad)(void *),
4898  const char *registrar)
4899 {
4900  return ast_add_extension2(con, replace, extension, priority, label, callerid, application, data, datad, registrar);
4901 }
4902 
4903 
4904 
4905 /*! \brief The return value depends on the action:
4906  *
4907  * E_MATCH, E_CANMATCH, E_MATCHMORE require a real match,
4908  * and return 0 on failure, -1 on match;
4909  * E_FINDLABEL maps the label to a priority, and returns
4910  * the priority on success, ... XXX
4911  * E_SPAWN, spawn an application,
4912  * and return 0 on success, -1 on failure.
4913  */
4914 static int pbx_extension_helper(struct ast_channel *c, struct ast_context *con,
4915  const char *context, const char *exten, int priority,
4916  const char *label, const char *callerid, enum ext_match_t action)
4917 {
4918  struct ast_exten *e;
4919  int res;
4920  struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */
4921 
4922  int matching_action = (action == E_MATCH || action == E_CANMATCH || action == E_MATCHMORE);
4923 
4924  e = pbx_find_extension(NULL, con, &q, context, exten, priority, label, callerid, action);
4925  if (e) {
4926  if (matching_action) {
4927  return -1; /* success, we found it */
4928  } else if (action == E_FINDLABEL) { /* map the label to a priority */
4929  res = e->priority;
4930  return res; /* the priority we were looking for */
4931  } else { /* spawn */
4932 
4933  /* NOT!!!!! */
4934  return 0;
4935  }
4936  } else if (q.swo) { /* not found here, but in another switch */
4937  if (matching_action)
4938  return -1;
4939  else {
4940  if (!q.swo->exec) {
4941  ast_log(LOG_WARNING, "No execution engine for switch %s\n", q.swo->name);
4942  res = -1;
4943  }
4944  return q.swo->exec(c, q.foundcontext ? q.foundcontext : context, exten, priority, callerid, q.data);
4945  }
4946  } else { /* not found anywhere, see what happened */
4947  switch (q.status) {
4948  case STATUS_NO_CONTEXT:
4949  if (!matching_action)
4950  ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", context);
4951  break;
4952  case STATUS_NO_EXTENSION:
4953  if (!matching_action)
4954  ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, context);
4955  break;
4956  case STATUS_NO_PRIORITY:
4957  if (!matching_action)
4958  ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, context);
4959  break;
4960  case STATUS_NO_LABEL:
4961  if (context)
4962  ast_log(LOG_NOTICE, "No such label '%s' in extension '%s' in context '%s'\n", label, exten, context);
4963  break;
4964  default:
4965  if (option_debug)
4966  ast_log(LOG_DEBUG, "Shouldn't happen!\n");
4967  }
4968 
4969  return (matching_action) ? 0 : -1;
4970  }
4971 }
4972 
4973 static int ast_findlabel_extension2(struct ast_channel *c, struct ast_context *con, const char *exten, const char *label, const char *callerid);
4974 
4975 static int ast_findlabel_extension2(struct ast_channel *c, struct ast_context *con, const char *exten, const char *label, const char *callerid)
4976 {
4977  return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL);
4978 }
4979 
4980 static struct ast_context *ast_context_find_or_create(struct ast_context **extcontexts, void *tab, const char *name, const char *registrar)
4981 {
4982  return __ast_context_create(extcontexts, name, registrar, 1);
4983 }
4984 
4985 struct ast_context *localized_context_find_or_create(struct ast_context **extcontexts, void *tab, const char *name, const char *registrar);
4986 struct ast_context *localized_context_find_or_create(struct ast_context **extcontexts, void *tab, const char *name, const char *registrar)
4987 {
4988  return __ast_context_create(extcontexts, name, registrar, 1);
4989 }
4990 
4991 
4992 /* chopped this one off at the knees */
4993 static int ast_func_read(struct ast_channel *chan, const char *function, char *workspace, size_t len)
4994 {
4995  ast_log(LOG_ERROR, "Function %s not registered\n", function);
4996  return -1;
4997 }
4998 
4999 /*! \brief extract offset:length from variable name.
5000  * Returns 1 if there is a offset:length part, which is
5001  * trimmed off (values go into variables)
5002  */
5003 static int parse_variable_name(char *var, int *offset, int *length, int *isfunc)
5004 {
5005  int parens=0;
5006 
5007  *offset = 0;
5008  *length = INT_MAX;
5009  *isfunc = 0;
5010  for (; *var; var++) {
5011  if (*var == '(') {
5012  (*isfunc)++;
5013  parens++;
5014  } else if (*var == ')') {
5015  parens--;
5016  } else if (*var == ':' && parens == 0) {
5017  *var++ = '\0';
5018  sscanf(var, "%30d:%30d", offset, length);
5019  return 1; /* offset:length valid */
5020  }
5021  }
5022  return 0;
5023 }
5024 
5025 static const char *ast_var_value(const struct ast_var_t *var)
5026 {
5027  return (var ? var->value : NULL);
5028 }
5029 
5030 /*! \brief takes a substring. It is ok to call with value == workspace.
5031  *
5032  * offset < 0 means start from the end of the string and set the beginning
5033  * to be that many characters back.
5034  * length is the length of the substring. A value less than 0 means to leave
5035  * that many off the end.
5036  * Always return a copy in workspace.
5037  */
5038 static char *substring(const char *value, int offset, int length, char *workspace, size_t workspace_len)
5039 {
5040  char *ret = workspace;
5041  int lr; /* length of the input string after the copy */
5042 
5043  ast_copy_string(workspace, value, workspace_len); /* always make a copy */
5044 
5045  lr = strlen(ret); /* compute length after copy, so we never go out of the workspace */
5046 
5047  /* Quick check if no need to do anything */
5048  if (offset == 0 && length >= lr) /* take the whole string */
5049  return ret;
5050 
5051  if (offset < 0) { /* translate negative offset into positive ones */
5052  offset = lr + offset;
5053  if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */
5054  offset = 0;
5055  }
5056 
5057  /* too large offset result in empty string so we know what to return */
5058  if (offset >= lr)
5059  return ret + lr; /* the final '\0' */
5060 
5061  ret += offset; /* move to the start position */
5062  if (length >= 0 && length < lr - offset) /* truncate if necessary */
5063  ret[length] = '\0';
5064  else if (length < 0) {
5065  if (lr > offset - length) /* After we remove from the front and from the rear, is there anything left? */
5066  ret[lr + length - offset] = '\0';
5067  else
5068  ret[0] = '\0';
5069  }
5070 
5071  return ret;
5072 }
5073 
5074 /*! \brief Support for Asterisk built-in variables in the dialplan
5075 \note See also
5076  - \ref AstVar Channel variables
5077  - \ref AstCauses The HANGUPCAUSE variable
5078  */
5079 static void pbx_retrieve_variable(struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp)
5080 {
5081  const char not_found = '\0';
5082  char *tmpvar;
5083  const char *s; /* the result */
5084  int offset, length;
5085  int i, need_substring;
5086  struct varshead *places[2] = { headp, &globals }; /* list of places where we may look */
5087 
5088  /*
5089  * Make a copy of var because parse_variable_name() modifies the string.
5090  * Then if called directly, we might need to run substring() on the result;
5091  * remember this for later in 'need_substring', 'offset' and 'length'
5092  */
5093  tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */
5094  need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */);
5095 
5096  /*
5097  * Look first into predefined variables, then into variable lists.
5098  * Variable 's' points to the result, according to the following rules:
5099  * s == &not_found (set at the beginning) means that we did not find a
5100  * matching variable and need to look into more places.
5101  * If s != &not_found, s is a valid result string as follows:
5102  * s = NULL if the variable does not have a value;
5103  * you typically do this when looking for an unset predefined variable.
5104  * s = workspace if the result has been assembled there;
5105  * typically done when the result is built e.g. with an snprintf(),
5106  * so we don't need to do an additional copy.
5107  * s != workspace in case we have a string, that needs to be copied
5108  * (the ast_copy_string is done once for all at the end).
5109  * Typically done when the result is already available in some string.
5110  */
5111  s = &not_found; /* default value */
5112  if (s == &not_found) { /* look for more */
5113  if (!strcmp(var, "EPOCH")) {
5114  snprintf(workspace, workspacelen, "%u",(int)time(NULL));
5115  }
5116 
5117  s = workspace;
5118  }
5119  /* if not found, look into chanvars or global vars */
5120  for (i = 0; s == &not_found && i < (sizeof(places) / sizeof(places[0])); i++) {
5121  struct ast_var_t *variables;
5122  if (!places[i])
5123  continue;
5124  if (places[i] == &globals)
5125  ast_rwlock_rdlock(&globalslock);
5126  AST_LIST_TRAVERSE(places[i], variables, entries) {
5127  if (strcasecmp(ast_var_name(variables), var)==0) {
5128  s = ast_var_value(variables);
5129  break;
5130  }
5131  }
5132  if (places[i] == &globals)
5133  ast_rwlock_unlock(&globalslock);
5134  }
5135  if (s == &not_found || s == NULL)
5136  *ret = NULL;
5137  else {
5138  if (s != workspace)
5139  ast_copy_string(workspace, s, workspacelen);
5140  *ret = workspace;
5141  if (need_substring)
5142  *ret = substring(*ret, offset, length, workspace, workspacelen);
5143  }
5144 }
5145 
5146 static void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count)
5147 {
5148  /* Substitutes variables into cp2, based on string cp1, and assuming cp2 to be
5149  zero-filled */
5150  char *cp4;
5151  const char *tmp, *whereweare;
5152  int length, offset, offset2, isfunction;
5153  char *workspace = NULL;
5154  char *ltmp = NULL, *var = NULL;
5155  char *nextvar, *nextexp, *nextthing;
5156  char *vars, *vare;
5157  int pos, brackets, needsub, len;
5158 
5159  *cp2 = 0; /* just in case there's nothing to do */
5160  whereweare=tmp=cp1;
5161  while (!ast_strlen_zero(whereweare) && count) {
5162  /* Assume we're copying the whole remaining string */
5163  pos = strlen(whereweare);
5164  nextvar = NULL;
5165  nextexp = NULL;
5166  nextthing = strchr(whereweare, '$');
5167  if (nextthing) {
5168  switch (nextthing[1]) {
5169  case '{':
5170  nextvar = nextthing;
5171  pos = nextvar - whereweare;
5172  break;
5173  case '[':
5174  nextexp = nextthing;
5175  pos = nextexp - whereweare;
5176  break;
5177  }
5178  }
5179 
5180  if (pos) {
5181  /* Can't copy more than 'count' bytes */
5182  if (pos > count)
5183  pos = count;
5184 
5185  /* Copy that many bytes */
5186  memcpy(cp2, whereweare, pos);
5187 
5188  count -= pos;
5189  cp2 += pos;
5190  whereweare += pos;
5191  *cp2 = 0;
5192  }
5193 
5194  if (nextvar) {
5195  /* We have a variable. Find the start and end, and determine
5196  if we are going to have to recursively call ourselves on the
5197  contents */
5198  vars = vare = nextvar + 2;
5199  brackets = 1;
5200  needsub = 0;
5201 
5202  /* Find the end of it */
5203  while (brackets && *vare) {
5204  if ((vare[0] == '$') && (vare[1] == '{')) {
5205  needsub++;
5206  } else if (vare[0] == '{') {
5207  brackets++;
5208  } else if (vare[0] == '}') {
5209  brackets--;
5210  } else if ((vare[0] == '$') && (vare[1] == '['))
5211  needsub++;
5212  vare++;
5213  }
5214  if (brackets)
5215  ast_log(LOG_NOTICE, "Error in extension logic (missing '}' in '%s')\n", cp1);
5216  len = vare - vars - 1;
5217 
5218  /* Skip totally over variable string */
5219  whereweare += (len + 3);
5220 
5221  if (!var)
5222  var = alloca(VAR_BUF_SIZE);
5223 
5224  /* Store variable name (and truncate) */
5225  ast_copy_string(var, vars, len + 1);
5226 
5227  /* Substitute if necessary */
5228  if (needsub) {
5229  if (!ltmp)
5230  ltmp = alloca(VAR_BUF_SIZE);
5231 
5232  memset(ltmp, 0, VAR_BUF_SIZE);
5233  pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1);
5234  vars = ltmp;
5235  } else {
5236  vars = var;
5237  }
5238 
5239  if (!workspace)
5240  workspace = alloca(VAR_BUF_SIZE);
5241 
5242  workspace[0] = '\0';
5243 
5244  parse_variable_name(vars, &offset, &offset2, &isfunction);
5245  if (isfunction) {
5246  /* Evaluate function */
5247  cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
5248  if (option_debug)
5249  ast_log(LOG_DEBUG, "Function result is '%s'\n", cp4 ? cp4 : "(null)");
5250  } else {
5251  /* Retrieve variable value */
5252  pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp);
5253  }
5254  if (cp4) {
5255  cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE);
5256 
5257  length = strlen(cp4);
5258  if (length > count)
5259  length = count;
5260  memcpy(cp2, cp4, length);
5261  count -= length;
5262  cp2 += length;
5263  *cp2 = 0;
5264  }
5265  } else if (nextexp) {
5266  /* We have an expression. Find the start and end, and determine
5267  if we are going to have to recursively call ourselves on the
5268  contents */
5269  vars = vare = nextexp + 2;
5270  brackets = 1;
5271  needsub = 0;
5272 
5273  /* Find the end of it */
5274  while (brackets && *vare) {
5275  if ((vare[0] == '$') && (vare[1] == '[')) {
5276  needsub++;
5277  brackets++;
5278  vare++;
5279  } else if (vare[0] == '[') {
5280  brackets++;
5281  } else if (vare[0] == ']') {
5282  brackets--;
5283  } else if ((vare[0] == '$') && (vare[1] == '{')) {
5284  needsub++;
5285  vare++;
5286  }
5287  vare++;
5288  }
5289  if (brackets)
5290  ast_log(LOG_NOTICE, "Error in extension logic (missing ']')\n");
5291  len = vare - vars - 1;
5292 
5293  /* Skip totally over expression */
5294  whereweare += (len + 3);
5295 
5296  if (!var)
5297  var = alloca(VAR_BUF_SIZE);
5298 
5299  /* Store variable name (and truncate) */
5300  ast_copy_string(var, vars, len + 1);
5301 
5302  /* Substitute if necessary */
5303  if (needsub) {
5304  if (!ltmp)
5305  ltmp = alloca(VAR_BUF_SIZE);
5306 
5307  memset(ltmp, 0, VAR_BUF_SIZE);
5308  pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1);
5309  vars = ltmp;
5310  } else {
5311  vars = var;
5312  }
5313 
5314  length = ast_expr(vars, cp2, count, NULL);
5315 
5316  if (length) {
5317  if (option_debug)
5318  ast_log(LOG_DEBUG, "Expression result is '%s'\n", cp2);
5319  count -= length;
5320  cp2 += length;
5321  *cp2 = 0;
5322  }
5323  } else
5324  break;
5325  }
5326 }
5327 
5328 static void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count)
5329 {
5330  pbx_substitute_variables_helper_full(c, NULL, cp1, cp2, count);
5331 }
5332 
5333 
5334 static int pbx_load_config(const char *config_file);
5335 
5336 static int pbx_load_config(const char *config_file)
5337 {
5338  struct ast_config *cfg;
5339  char *end;
5340  char *label;
5341  char realvalue[256];
5342  int lastpri = -2;
5343  struct ast_context *con;
5344  struct ast_variable *v;
5345  const char *cxt;
5346  const char *aft;
5347 
5348  cfg = localized_config_load(config_file);
5349  if (!cfg)
5350  return 0;
5351 
5352  /* Use existing config to populate the PBX table */
5353  static_config = ast_true(ast_variable_retrieve(cfg, "general", "static"));
5354  write_protect_config = ast_true(ast_variable_retrieve(cfg, "general", "writeprotect"));
5355  if ((aft = ast_variable_retrieve(cfg, "general", "autofallthrough")))
5356  autofallthrough_config = ast_true(aft);
5357  clearglobalvars_config = ast_true(ast_variable_retrieve(cfg, "general", "clearglobalvars"));
5358 
5359  if ((cxt = ast_variable_retrieve(cfg, "general", "userscontext")))
5360  ast_copy_string(userscontext, cxt, sizeof(userscontext));
5361  else
5362  ast_copy_string(userscontext, "default", sizeof(userscontext));
5363 
5364  for (v = ast_variable_browse(cfg, "globals"); v; v = v->next) {
5365  memset(realvalue, 0, sizeof(realvalue));
5366  pbx_substitute_variables_helper(NULL, v->value, realvalue, sizeof(realvalue) - 1);
5367  pbx_builtin_setvar_helper(NULL, v->name, realvalue);
5368  }
5369  for (cxt = NULL; (cxt = ast_category_browse(cfg, cxt)); ) {
5370  /* All categories but "general" or "globals" are considered contexts */
5371  if (!strcasecmp(cxt, "general") || !strcasecmp(cxt, "globals"))
5372  continue;
5373  con=ast_context_find_or_create(&local_contexts,NULL,cxt, global_registrar);
5374  if (con == NULL)
5375  continue;
5376 
5377  for (v = ast_variable_browse(cfg, cxt); v; v = v->next) {
5378  if (!strcasecmp(v->name, "exten")) {
5379  char *tc = ast_strdup(v->value);
5380  if (tc) {
5381  int ipri = -2;
5382  char realext[256]="";
5383  char *plus, *firstp, *firstc;
5384  char *pri, *appl, *data, *cidmatch;
5385  char *stringp = tc;
5386  char *ext = strsep(&stringp, ",");
5387  if (!ext)
5388  ext="";
5389  pbx_substitute_variables_helper(NULL, ext, realext, sizeof(realext) - 1);
5390  cidmatch = strchr(realext, '/');
5391  if (cidmatch) {
5392  *cidmatch++ = '\0';
5393  ast_shrink_phone_number(cidmatch);
5394  }
5395  pri = strsep(&stringp, ",");
5396  if (!pri)
5397  pri="";
5398  label = strchr(pri, '(');
5399  if (label) {
5400  *label++ = '\0';
5401  end = strchr(label, ')');
5402  if (end)
5403  *end = '\0';
5404  else
5405  ast_log(LOG_WARNING, "Label missing trailing ')' at line %d\n", v->lineno);
5406  }
5407  plus = strchr(pri, '+');
5408  if (plus)
5409  *plus++ = '\0';
5410  if (!strcmp(pri,"hint"))
5411  ipri=PRIORITY_HINT;
5412  else if (!strcmp(pri, "next") || !strcmp(pri, "n")) {
5413  if (lastpri > -2)
5414  ipri = lastpri + 1;
5415  else
5416  ast_log(LOG_WARNING, "Can't use 'next' priority on the first entry!\n");
5417  } else if (!strcmp(pri, "same") || !strcmp(pri, "s")) {
5418  if (lastpri > -2)
5419  ipri = lastpri;
5420  else
5421  ast_log(LOG_WARNING, "Can't use 'same' priority on the first entry!\n");
5422  } else if (sscanf(pri, "%30d", &ipri) != 1 &&
5423  (ipri = ast_findlabel_extension2(NULL, con, realext, pri, cidmatch)) < 1) {
5424  ast_log(LOG_WARNING, "Invalid priority/label '%s' at line %d\n", pri, v->lineno);
5425  ipri = 0;
5426  }
5427  appl = S_OR(stringp, "");
5428  /* Find the first occurrence of either '(' or ',' */
5429  firstc = strchr(appl, ',');
5430  firstp = strchr(appl, '(');
5431  if (firstc && (!firstp || firstc < firstp)) {
5432  /* comma found, no parenthesis */
5433  /* or both found, but comma found first */
5434  appl = strsep(&stringp, ",");
5435  data = stringp;
5436  } else if (!firstc && !firstp) {
5437  /* Neither found */
5438  data = "";
5439  } else {
5440  /* Final remaining case is parenthesis found first */
5441  appl = strsep(&stringp, "(");
5442  data = stringp;
5443  end = strrchr(data, ')');
5444  if ((end = strrchr(data, ')'))) {
5445  *end = '\0';
5446  } else {
5447  ast_log(LOG_WARNING, "No closing parenthesis found? '%s(%s'\n", appl, data);
5448  }
5449  ast_process_quotes_and_slashes(data, ',', '|');
5450  }
5451 
5452  if (!data)
5453  data="";
5454  appl = ast_skip_blanks(appl);
5455  if (ipri) {
5456  if (plus)
5457  ipri += atoi(plus);
5458  lastpri = ipri;
5459  if (!ast_opt_dont_warn && !strcmp(realext, "_."))
5460  ast_log(LOG_WARNING, "The use of '_.' for an extension is strongly discouraged and can have unexpected behavior. Please use '_X.' instead at line %d\n", v->lineno);
5461  if (ast_add_extension2(con, 0, realext, ipri, label, cidmatch, appl, strdup(data), ast_free_ptr, global_registrar)) {
5462  ast_log(LOG_WARNING, "Unable to register extension at line %d\n", v->lineno);
5463  }
5464  }
5465  free(tc);
5466  }
5467  } else if (!strcasecmp(v->name, "include")) {
5468  memset(realvalue, 0, sizeof(realvalue));
5469  pbx_substitute_variables_helper(NULL, v->value, realvalue, sizeof(realvalue) - 1);
5470  if (ast_context_add_include2(con, realvalue, global_registrar))
5471  ast_log(LOG_WARNING, "Unable to include context '%s' in context '%s'\n", v->value, cxt);
5472  } else if (!strcasecmp(v->name, "ignorepat")) {
5473  memset(realvalue, 0, sizeof(realvalue));
5474  pbx_substitute_variables_helper(NULL, v->value, realvalue, sizeof(realvalue) - 1);
5475  if (ast_context_add_ignorepat2(con, realvalue, global_registrar))
5476  ast_log(LOG_WARNING, "Unable to include ignorepat '%s' in context '%s'\n", v->value, cxt);
5477  } else if (!strcasecmp(v->name, "switch") || !strcasecmp(v->name, "lswitch") || !strcasecmp(v->name, "eswitch")) {
5478  char *stringp= realvalue;
5479  char *appl, *data;
5480 
5481  memset(realvalue, 0, sizeof(realvalue));
5482  if (!strcasecmp(v->name, "switch"))
5483  pbx_substitute_variables_helper(NULL, v->value, realvalue, sizeof(realvalue) - 1);
5484  else
5485  ast_copy_string(realvalue, v->value, sizeof(realvalue));
5486  appl = strsep(&stringp, "/");
5487  data = strsep(&stringp, ""); /* XXX what for ? */
5488  if (!data)
5489  data = "";
5490  if (ast_context_add_switch2(con, appl, data, !strcasecmp(v->name, "eswitch"), global_registrar))
5491  ast_log(LOG_WARNING, "Unable to include switch '%s' in context '%s'\n", v->value, cxt);
5492  } else {
5493  ast_log(LOG_WARNING, "==!!== Unknown directive: %s at line %d -- IGNORING!!!\n", v->name, v->lineno);
5494  }
5495  }
5496  }
5497  ast_config_destroy(cfg);
5498  return 1;
5499 }
5500 
5501 static void __ast_context_destroy(struct ast_context *con, const char *registrar)
5502 {
5503  struct ast_context *tmp, *tmpl=NULL;
5504  struct ast_include *tmpi;
5505  struct ast_sw *sw;
5506  struct ast_exten *e, *el, *en;
5507  struct ast_ignorepat *ipi;
5508 
5509  for (tmp = contexts; tmp; ) {
5510  struct ast_context *next; /* next starting point */
5511  for (; tmp; tmpl = tmp, tmp = tmp->next) {
5512  if (option_debug)
5513  ast_log(LOG_DEBUG, "check ctx %s %s\n", tmp->name, tmp->registrar);
5514  if ( (!registrar || !strcasecmp(registrar, tmp->registrar)) &&
5515  (!con || !strcasecmp(tmp->name, con->name)) )
5516  break; /* found it */
5517  }
5518  if (!tmp) /* not found, we are done */
5519  break;
5520  ast_wrlock_context(tmp);
5521  if (option_debug)
5522  ast_log(LOG_DEBUG, "delete ctx %s %s\n", tmp->name, tmp->registrar);
5523  next = tmp->next;
5524  if (tmpl)
5525  tmpl->next = next;
5526  else
5527  contexts = next;
5528  /* Okay, now we're safe to let it go -- in a sense, we were
5529  ready to let it go as soon as we locked it. */
5530  ast_unlock_context(tmp);
5531  for (tmpi = tmp->includes; tmpi; ) { /* Free includes */
5532  struct ast_include *tmpil = tmpi;
5533  tmpi = tmpi->next;
5534  free(tmpil);
5535  }
5536  for (ipi = tmp->ignorepats; ipi; ) { /* Free ignorepats */
5537  struct ast_ignorepat *ipl = ipi;
5538  ipi = ipi->next;
5539  free(ipl);
5540  }
5541  while ((sw = AST_LIST_REMOVE_HEAD(&tmp->alts, list)))
5542  free(sw);
5543  for (e = tmp->root; e;) {
5544  for (en = e->peer; en;) {
5545  el = en;
5546  en = en->peer;
5547  destroy_exten(el);
5548  }
5549  el = e;
5550  e = e->next;
5551  destroy_exten(el);
5552  }
5553  ast_rwlock_destroy(&tmp->lock);
5554  free(tmp);
5555  /* if we have a specific match, we are done, otherwise continue */
5556  tmp = con ? NULL : next;
5557  }
5558 }
5559 
5560 void localized_context_destroy(struct ast_context *con, const char *registrar);
5561 
5562 void localized_context_destroy(struct ast_context *con, const char *registrar)
5563 {
5565  __ast_context_destroy(con,registrar);
5567 }
5568 
5569 
5570 static void ast_merge_contexts_and_delete(struct ast_context **extcontexts, const char *registrar)
5571 {
5572  struct ast_context *tmp, *lasttmp = NULL;
5573 
5574  /* it is very important that this function hold the hint list lock _and_ the conlock
5575  during its operation; not only do we need to ensure that the list of contexts
5576  and extensions does not change, but also that no hint callbacks (watchers) are
5577  added or removed during the merge/delete process
5578 
5579  in addition, the locks _must_ be taken in this order, because there are already
5580  other code paths that use this order
5581  */
5583 
5584  tmp = *extcontexts;
5585  if (registrar) {
5586  /* XXX remove previous contexts from same registrar */
5587  if (option_debug)
5588  ast_log(LOG_DEBUG, "must remove any reg %s\n", registrar);
5589  __ast_context_destroy(NULL,registrar);
5590  while (tmp) {
5591  lasttmp = tmp;
5592  tmp = tmp->next;
5593  }
5594  } else {
5595  /* XXX remove contexts with the same name */
5596  while (tmp) {
5597  ast_log(LOG_WARNING, "must remove %s reg %s\n", tmp->name, tmp->registrar);
5598  __ast_context_destroy(tmp,tmp->registrar);
5599  lasttmp = tmp;
5600  tmp = tmp->next;
5601  }
5602  }
5603  if (lasttmp) {
5604  lasttmp->next = contexts;
5605  contexts = *extcontexts;
5606  *extcontexts = NULL;
5607  } else
5608  ast_log(LOG_WARNING, "Requested contexts didn't get merged\n");
5609 
5611 
5612  return;
5613 }
5614 
5615 void localized_merge_contexts_and_delete(struct ast_context **extcontexts, void *tab, const char *registrar)
5616 {
5617  ast_merge_contexts_and_delete(extcontexts, registrar);
5618 }
5619 
5620 static int ast_context_verify_includes(struct ast_context *con)
5621 {
5622  struct ast_include *inc = NULL;
5623  int res = 0;
5624 
5625  while ( (inc = ast_walk_context_includes(con, inc)) )
5626  if (!ast_context_find(inc->rname)) {
5627  res = -1;
5628  if (strcasecmp(inc->rname,"parkedcalls")!=0)
5629  ast_log(LOG_WARNING, "Context '%s' tries to include the nonexistent context '%s'\n",
5630  ast_get_context_name(con), inc->rname);
5631  }
5632  return res;
5633 }
5634 
5635 int localized_context_verify_includes(struct ast_context *con);
5636 
5637 int localized_context_verify_includes(struct ast_context *con)
5638 {
5639  return ast_context_verify_includes(con);
5640 }
5641 
5642 int localized_pbx_load_module(void);
5643 
5644 int localized_pbx_load_module(void)
5645 {
5646  struct ast_context *con;
5647 
5648  if(!pbx_load_config(config_filename))
5649  return -1 /* AST_MODULE_LOAD_DECLINE*/;
5650 
5651  /* pbx_load_users(); */ /* does this affect the dialplan? */
5652 
5653  ast_merge_contexts_and_delete(&local_contexts, global_registrar);
5654 
5655  for (con = NULL; (con = ast_walk_contexts(con));)
5657 
5658  printf("=== Loading extensions.conf ===\n");
5659  con = 0;
5660  while ((con = ast_walk_contexts(con)) ) {
5661  printf("Context: %s\n", con->name);
5662  }
5663  printf("=========\n");
5664 
5665  return 0;
5666 }
5667 
5668 /* For platforms which don't have pthread_rwlock_timedrdlock() */
5669 struct timeval ast_tvnow(void);
5670 
5671 struct timeval ast_tvnow(void)
5672 {
5673  struct timeval t;
5674  gettimeofday(&t, NULL);
5675  return t;
5676 }
const char * label
Definition: pbx.c:244
const char * name
Definition: pbx.h:119
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
Definition: extconf.c:2282
ast_include: include= support in extensions.conf
Definition: pbx_include.c:37
struct ast_category * ast_category_new(const char *name, const char *in_file, int lineno)
Create a category.
Definition: extconf.c:2788
struct ast_variable * next
struct ast_category * next
Definition: main/config.c:246
int ast_unlock_context(struct ast_context *con)
Definition: pbx.c:8491
int ast_func_read(struct ast_channel *chan, const char *function, char *workspace, size_t len)
executes a read operation on a function
static void pbx_retrieve_variable(struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp)
Support for Asterisk built-in variables in the dialplan.
Definition: extconf.c:5079
Main Channel structure associated with a channel.
unsigned int daymask
Definition: pbx.h:174
const char * description
Definition: extconf.c:2409
ast_extension_states
Extension states.
Definition: pbx.h:61
Asterisk main include file. File version handling, generic pbx functions.
ast_exten: An extension The dialplan is saved as a linked list with each context having it's own link...
Definition: pbx.c:237
Structure to keep comments for rewriting configuration files.
Definition: main/config.c:84
#define ast_realloc(p, len)
A wrapper for realloc()
Definition: astmm.h:226
struct ast_include * next
Definition: extconf.c:2370
static SQLHSTMT execute(struct odbc_obj *obj, void *data, int silent)
Common execution function for SQL queries.
Definition: func_odbc.c:471
const char * synopsis
Definition: extconf.c:2097
void ast_unreplace_sigchld(void)
Restore the SIGCHLD handler.
Definition: extconf.c:815
char * file
The file name from whence this declaration was read.
Definition: main/config.c:233
static char * substring(const char *value, int offset, int length, char *workspace, size_t workspace_len)
takes a substring. It is ok to call with value == workspace.
Definition: extconf.c:5038
struct ast_include * includes
Definition: extconf.c:2397
char * ast_trim_blanks(char *str)
Trims trailing whitespace characters from a string.
Definition: extconf.c:1004
const char * desc
Definition: extconf.c:2098
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1262
struct ast_exten * root
Definition: pbx.c:289
static int lookup_name(const char *s, char *const names[], int max)
Helper for get_range. return the index of the matching entry, starting from 1. If names is not suppli...
Definition: extconf.c:2615
int ast_findlabel_extension2(struct ast_channel *c, struct ast_context *con, const char *exten, const char *label, const char *callerid)
Find the priority of an extension that has the specified label.
Definition: extconf.c:4975
int option_debug
Definition: options.c:69
char * include_location_file
file name in which the include occurs
Definition: main/config.c:266
Time-related functions and macros.
char context[AST_MAX_CONTEXT]
struct ast_config_include * includes
Definition: main/config.c:258
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: extconf.c:1773
int ast_build_timing(struct ast_timing *i, const char *info_in)
Construct a timing bitmap, for use in time-based conditionals.
Definition: extconf.c:3806
#define ast_rwlock_init(rwlock)
wrapper for rwlock with tracking enabled
Definition: lock.h:224
static int pbx_extension_helper(struct ast_channel *c, struct ast_context *con, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action)
The return value depends on the action:
Definition: extconf.c:4914
const char * database
Definition: main/config.c:207
struct ast_ignorepat * ignorepats
Definition: extconf.c:2398
ast_state_cb: An extension state notify register item
Definition: pbx.c:308
Generic (perhaps overly so) hashtable implementation Hash Table support in Asterisk.
char cmt[0]
Definition: main/config.c:87
Structure for variables, used for configurations and for channel variables.
pthread_t thread
Definition: app_sla.c:329
int ast_context_add_switch2(struct ast_context *con, const char *sw, const char *data, int eval, const char *registrar)
Adds a switch (first param is a ast_context)
Definition: ael_main.c:370
void ast_replace_sigchld(void)
Replace the SIGCHLD handler.
Definition: extconf.c:801
static int ast_remove_hint(struct ast_exten *e)
ast_remove_hint: Remove hint from extension
Definition: extconf.c:3733
static int comment_buffer_size
Definition: extconf.c:706
int option_verbose
Definition: options.c:67
Definition: astman.c:222
struct ast_category * prev
Definition: main/config.c:244
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: extconf.c:1976
static int ext_cmp1(const char **p)
helper functions to sort extensions and patterns in the desired way, so that more specific patterns a...
Definition: extconf.c:3872
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159
int ast_wrlock_contexts(void)
Write locks the context list.
Definition: pbx.c:8463
double ast_option_maxload
Definition: options.c:77
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
char * ast_process_quotes_and_slashes(char *start, char find, char replace_with)
Process a string to find and replace characters.
Definition: utils.c:2352
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
Definition: extconf.c:3326
const char * data
const char * table
Definition: main/config.c:209
static unsigned get_range(char *src, int max, char *const names[], const char *msg)
helper function to return a range up to max (7, 12, 31 respectively). names, if supplied, is an array of names that should be mapped to numbers.
Definition: extconf.c:2638
unsigned int minmask[48]
Definition: pbx.h:176
char * exec_file
if it's an exec, you'll have both the /var/tmp to read, and the original script
Definition: main/config.c:273
void ast_free_ptr(void *ptr)
free() wrapper
Definition: main/astmm.c:1739
struct ast_timing timing
Definition: pbx_include.c:46
static ast_rwlock_t conlock
Definition: extconf.c:4482
const char * registrar
Definition: pbx.c:253
static void ast_shrink_phone_number(char *n)
Clean up phone string remove '(', ' ', ')', non-trailing '.', and '-' not in square brackets...
Definition: extconf.c:2136
const char * synopsis
Definition: extconf.c:2408
int ast_option_maxcalls
Definition: options.c:79
Configuration engine structure, used to define realtime drivers.
const char * syntax
Definition: extconf.c:2099
struct ast_context * next
Definition: pbx.c:292
static int add_pri(struct ast_context *con, struct ast_exten *tmp, struct ast_exten *el, struct ast_exten *e, int replace)
add the extension in the priority chain. returns 0 on success, -1 on failure
Definition: extconf.c:3675
int ast_check_timing(const struct ast_timing *i)
Evaluate a pre-constructed bitmap as to whether the current time falls within the range specified...
Definition: extconf.c:4000
const char * name
Definition: pbx.h:162
unsigned int monthmask
Definition: pbx.h:173
All configuration options for http media cache.
struct ast_category * last
Definition: main/config.c:253
int matchcid
Definition: pbx.c:240
void ast_category_append(struct ast_config *config, struct ast_category *category)
Appends a category to a config.
Definition: extconf.c:2833
static char * lline_buffer
Definition: extconf.c:708
const char * registrar
Definition: pbx_sw.c:40
struct ast_exten * next
Definition: pbx.c:256
static const char config_file[]
void localized_merge_contexts_and_delete(struct ast_context **extcontexts, void *tab, const char *registrar)
Definition: extconf.c:5615
int priority
Definition: pbx.c:243
static int process_text_line(struct ast_config *cfg, struct ast_category **cat, char *buf, int lineno, const char *configfile, struct ast_flags flags, struct ast_str *comment_buffer, struct ast_str *lline_buffer, const char *suggested_include_file, struct ast_category **last_cat, struct ast_variable **last_var, const char *who_asked)
parse one line in the configuration.
Definition: main/config.c:1915
struct ast_category * ast_config_get_current_category(const struct ast_config *cfg)
Retrieve the current category name being built.
Definition: extconf.c:2781
struct ast_context * ast_context_find(const char *name)
Find a context.
Definition: extconf.c:4172
struct ast_exten * peer
Definition: pbx.c:250
ast_sw: Switch statement in extensions.conf
Definition: pbx_sw.c:37
ast_mutex_t lock
Asterisk file paths, configured in asterisk.conf.
void ast_config_set_current_category(struct ast_config *cfg, const struct ast_category *cat)
Set the category within the configuration as being current.
Definition: extconf.c:3362
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
Inlinable API function macro.
Data structure associated with a custom dialplan function.
Definition: pbx.h:118
Asterisk architecture endianess compatibility definitions.
const char * registrar
Definition: pbx.c:286
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: extconf.c:1956
struct ast_switch * pbx_findswitch(const char *sw)
Definition: pbx_switch.c:40
char * included_file
file name included
Definition: main/config.c:278
structure to hold extensions
#define AST_LIST_HEAD(name, type)
Defines a structure to be used to hold a list of specified type.
Definition: extconf.c:1457
static int ast_add_hint(struct ast_exten *e)
ast_add_hint: Add hint to hint list, check initial extension state
Definition: extconf.c:3642
static void _null_sig_handler(int sig)
NULL handler so we can collect the child exit status.
Definition: extconf.c:789
ast_acf_write_fn_t write
Definition: pbx.h:141
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:191
void(* datad)(void *)
Definition: pbx.c:249
struct ast_variable * root
Definition: main/config.c:240
char stuff[0]
Contents of file, name, and value in that order stuffed here.
int ast_language_is_prefix
The following variable controls the layout of localized sound files. If 0, use the historical layout ...
Definition: file.c:67
struct ast_config * ast_config_new(void)
Create a new base configuration structure.
Definition: extconf.c:3274
External configuration handlers (realtime and static configuration)
static char * comment_buffer
Definition: extconf.c:705
struct timeval ast_tvsub(struct timeval a, struct timeval b)
Returns the difference of two timevals a - b.
Definition: extconf.c:2297
struct ast_category * last_browse
Definition: main/config.c:255
static void get_timerange(struct ast_timing *i, char *times)
store a bitmask of valid times, one bit each 2 minute
Definition: extconf.c:2682
struct ast_exten * exten
Hint extension.
Definition: pbx.c:338
int( ast_switch_f)(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
All switch functions have the same interface, so define a type for them.
Definition: pbx.h:156
struct ast_ignorepats ignorepats
Definition: pbx.c:294
const char * name
Definition: main/config.c:203
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Definition: extconf.c:1023
char * exten
Definition: pbx.c:238
ast_rwlock_t lock
Definition: pbx.c:288
unsigned int dowmask
Definition: pbx.h:175
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
Definition: utils.c:2199
void ast_merge_contexts_and_delete(struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *registrar)
Merge the temporary contexts into a global contexts list and delete from the global list the ones tha...
Definition: pbx.c:6426
char * data
Definition: extconf.c:2378
ast_ignorepat: Ignore patterns in dial plan
Definition: pbx_ignorepat.c:37
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:8473
static unsigned int safe_system_level
Keep track of how many threads are currently trying to wait*() on a child process.
Definition: extconf.c:785
int ast_safe_system(const char *s)
Safely spawn an OS shell command while closing file descriptors.
Definition: extconf.c:829
Structure for dial plan hints.
Definition: pbx.c:331
#define AST_LIST_HEAD_NOLOCK(name, type)
Defines a structure to be used to hold a list of specified type (with no lock).
Definition: extconf.c:1509
static int parse_variable_name(char *var, int *offset, int *length, int *isfunc)
extract offset:length from variable name. Returns 1 if there is a offset:length part, which is trimmed off (values go into variables)
Definition: extconf.c:5003
char * ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
Definition: strings.h:161
int ast_context_add_include2(struct ast_context *con, const char *value, const char *registrar)
Add a context include.
Definition: ael_main.c:359
int ast_wrlock_context(struct ast_context *con)
Write locks a given context.
Definition: pbx.c:8481
General Definitions for Asterisk top level program Included by asterisk.h to handle platform-specific...
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
Definition: linkedlists.h:410
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
int ast_extension_match(const char *pattern, const char *extension)
Determine if a given extension matches a given pattern (in NXX format)
Definition: extconf.c:4295
#define AST_RWLIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a read/write list of specified type, statically initialized...
Definition: extconf.c:1617
Structures for AEL - the Asterisk extension language.
void ast_console_puts(const char *string)
write the string to the root console, and all attached network console clients
Definition: asterisk.c:1356
static int ast_change_hint(struct ast_exten *oe, struct ast_exten *ne)
ast_change_hint: Change hint for an extension
Definition: extconf.c:3625
int pbx_builtin_setvar(struct ast_channel *chan, const char *data)
Parse and set a single channel variable, where the name and value are separated with an '=' character...
static struct ast_config * config_text_file_load(const char *database, const char *table, const char *filename, struct ast_config *cfg, struct ast_flags flags, const char *suggested_include_file, const char *who_asked)
Definition: main/config.c:2212
#define AST_DEFAULT_OPTIONS
Definition: extconf.c:1362
Structure used to handle boolean flags.
Definition: utils.h:199
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
const char * cidmatch
Definition: pbx.c:241
struct ast_includes includes
Definition: pbx.c:293
static int ext_strncpy(char *dst, const char *src, int len)
copy a string skipping whitespace
Definition: extconf.c:3971
const char * name
Definition: pbx.c:285
static int ext_cmp(const char *a, const char *b)
the full routine to compare extensions in rules.
Definition: extconf.c:3944
const char * driver
Definition: main/config.c:205
#define AST_MAX_EXTENSION
Definition: extconf.c:2078
char * timezone
Definition: pbx.h:177
struct ast_variable * last
Definition: main/config.c:242
struct ast_context * localized_context_find_or_create(struct ast_context **extcontexts, void *tab, const char *name, const char *registrar)
Definition: extconf.c:4986
const char * rname
Definition: pbx_include.c:40
const char * app
Definition: pbx.c:246
Structure for rwlock and tracking information.
Definition: lock.h:157
struct ast_config_include * next
Definition: main/config.c:282
ast_acf_read_fn_t read
Definition: pbx.h:129
static struct ast_config_engine * find_engine(const char *family, char *database, int dbsiz, char *table, int tabsiz)
Find realtime engine for realtime family.
Definition: extconf.c:2747
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:80
ast_app: A registered application
Definition: pbx_app.c:45
ext_match_t
Definition: extconf.h:214
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Definition: extconf.c:1723
struct ast_context * parent
Definition: pbx.c:245
#define PRIORITY_HINT
Definition: extconf.c:2082
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: extconf.c:1705
int ast_context_verify_includes(struct ast_context *con)
Verifies includes in an ast_contect structure.
Definition: pbx.c:8732
void * data
Definition: pbx.c:248
struct ast_category * root
Definition: main/config.c:251
int(* ast_state_cb_type)(const char *context, const char *exten, struct ast_state_cb_info *info, void *data)
Typedef for devicestate and hint callbacks.
Definition: pbx.h:112
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return * the previous value of *p. This can be used to handle reference co...
Definition: extconf.c:593
struct ast_category * ast_category_get(const struct ast_config *config, const char *category_name, const char *filter)
Retrieve a category if it exists.
Definition: main/config.c:1111
struct ast_context * ast_context_find_or_create(struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *name, const char *registrar)
Register a new context or find an existing one.
Definition: pbx.c:6149
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
Definition: extconf.c:1289
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
Definition: extconf.c:1694
#define AST_LIST_REMOVE(head, elm, field)
Removes a specific entry from a list.
Definition: extconf.c:2037
struct ast_state_cb * callbacks
Definition: extconf.c:2433
struct ast_sws alts
Definition: pbx.c:295
void ast_log_backtrace(void)
Log a backtrace of the current thread's execution stack to the Asterisk log.
Definition: logger.c:2510
ast_option_flags
Definition: options.h:38
int ast_func_write(struct ast_channel *chan, const char *function, const char *value)
executes a write operation on a function
ast_context: An extension context
Definition: pbx.c:284
int ast_expr(char *expr, char *buf, int length, struct ast_channel *chan)
Evaluate the given expression.
struct ao2_container * callbacks
Definition: pbx.c:339
static int ast_add_extension2(struct ast_context *con, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar)
Main interface to add extensions to the list for out context.
Definition: extconf.c:4773
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: extconf.c:2016
const char * registrar
Definition: pbx_include.c:42
char exten[AST_MAX_EXTENSION]
Structure for mutex and tracking information.
Definition: lock.h:135
const char * data
Definition: pbx_sw.c:42
#define AST_LIST_HEAD_NOLOCK_INIT_VALUE
Defines initial values for a declaration of AST_LIST_HEAD_NOLOCK.
Definition: extconf.c:1536
int ast_atomic_dec_and_test(volatile int *p)
decrement *p by 1 and return true if the variable has reached 0. Useful e.g. to check if a refcount h...
Definition: extconf.c:634