Asterisk - The Open Source Telephony Project  GIT-master-1f78ee9
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 exensions.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 {
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:
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
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 
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 
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 
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 
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 
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 
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 ast_trim_blanks function being used
984  \param str the input string
985  \return a pointer to the modified string
986  */
988 char *ast_trim_blanks(char *str),
989 {
990  char *work = str;
991 
992  if (work) {
993  work += strlen(work) - 1;
994  /* It's tempting to only want to erase after we exit this loop,
995  but since ast_trim_blanks *could* receive a constant string
996  (which we presumably wouldn't have to touch), we shouldn't
997  actually set anything unless we must, and it's easier just
998  to set each position to \0 than to keep track of a variable
999  for it */
1000  while ((work >= str) && *work < 33)
1001  *(work--) = '\0';
1002  }
1003  return str;
1004 }
1006 
1007 /*!
1008  \brief Strip leading/trailing whitespace from a string.
1009  \param s The string to be stripped (will be modified).
1010  \return The stripped string.
1011 
1012  This functions strips all leading and trailing whitespace
1013  characters from the input string, and returns a pointer to
1014  the resulting string. The string is modified in place.
1015 */
1017 char *ast_strip(char *s),
1018 {
1019  s = ast_skip_blanks(s);
1020  if (s)
1021  ast_trim_blanks(s);
1022  return s;
1023 }
1025 
1026 
1027 /* from config.h */
1028 
1029 struct ast_variable {
1030  char *name;
1031  char *value;
1032  char *file;
1033  int lineno;
1034  int object; /*!< 0 for variable, 1 for object */
1035  int blanklines; /*!< Number of blanklines following entry */
1036  struct ast_comment *precomments;
1037  struct ast_comment *sameline;
1038  struct ast_variable *next;
1039  char stuff[0];
1040 };
1041 
1042 static const char *ast_variable_retrieve(const struct ast_config *config, const char *category, const char *variable);
1043 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);
1044 
1045 struct ast_config *localized_config_load_with_comments(const char *filename);
1046 static char *ast_category_browse(struct ast_config *config, const char *prev);
1047 static struct ast_variable *ast_variable_browse(const struct ast_config *config, const char *category);
1048 static void ast_variables_destroy(struct ast_variable *v);
1049 static void ast_config_destroy(struct ast_config *cfg);
1050 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);
1051 static struct ast_config_include *ast_include_find(struct ast_config *conf, const char *included_file);
1052 void localized_ast_include_rename(struct ast_config *conf, const char *from_file, const char *to_file);
1053 
1054 static struct ast_variable *ast_variable_new(const char *name, const char *value, const char *filename);
1055 
1056 static struct ast_variable *ast_variable_new(const char *name, const char *value, const char *filename)
1057 {
1058  struct ast_variable *variable;
1059  int name_len = strlen(name) + 1;
1060  size_t value_len = strlen(value) + 1;
1061  size_t filename_len = strlen(filename) + 1;
1062 
1063  if ((variable = ast_calloc(1, name_len + value_len + filename_len + sizeof(*variable)))) {
1064  variable->name = variable->stuff;
1065  variable->value = variable->stuff + name_len;
1066  variable->file = variable->value + value_len;
1067  strcpy(variable->name,name);
1068  ast_copy_string(variable->value, value, value_len);
1069  ast_copy_string(variable->file, filename, filename_len);
1070  }
1071 
1072  return variable;
1073 }
1074 
1075 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)
1076 {
1077  /* a file should be included ONCE. Otherwise, if one of the instances is changed,
1078  then all be changed. -- how do we know to include it? -- Handling modified
1079  instances is possible, I'd have
1080  to create a new master for each instance. */
1081  struct ast_config_include *inc;
1082 
1083  inc = ast_include_find(conf, included_file);
1084  if (inc)
1085  {
1086  inc->inclusion_count++;
1087  snprintf(real_included_file_name, real_included_file_name_size, "%s~~%d", included_file, inc->inclusion_count);
1088  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);
1089  } else
1090  *real_included_file_name = 0;
1091 
1092  inc = ast_calloc(1,sizeof(struct ast_config_include));
1093  inc->include_location_file = ast_strdup(from_file);
1094  inc->include_location_lineno = from_lineno;
1095  if (!ast_strlen_zero(real_included_file_name))
1096  inc->included_file = ast_strdup(real_included_file_name);
1097  else
1098  inc->included_file = ast_strdup(included_file);
1099 
1100  inc->exec = is_exec;
1101  if (is_exec)
1102  inc->exec_file = ast_strdup(exec_file);
1103 
1104  /* attach this new struct to the conf struct */
1105  inc->next = conf->includes;
1106  conf->includes = inc;
1107 
1108  return inc;
1109 }
1110 
1111 void localized_ast_include_rename(struct ast_config *conf, const char *from_file, const char *to_file)
1112 {
1113  struct ast_config_include *incl;
1114  struct ast_category *cat;
1115  struct ast_variable *v;
1116 
1117  int from_len = strlen(from_file);
1118  int to_len = strlen(to_file);
1119 
1120  if (strcmp(from_file, to_file) == 0) /* no use wasting time if the name is the same */
1121  return;
1122 
1123  /* the manager code allows you to read in one config file, then
1124  write it back out under a different name. But, the new arrangement
1125  ties output lines to the file name. So, before you try to write
1126  the config file to disk, better riffle thru the data and make sure
1127  the file names are changed.
1128  */
1129  /* file names are on categories, includes (of course), and on variables. So,
1130  traverse all this and swap names */
1131 
1132  for (incl = conf->includes; incl; incl=incl->next) {
1133  if (strcmp(incl->include_location_file,from_file) == 0) {
1134  if (from_len >= to_len)
1135  strcpy(incl->include_location_file, to_file);
1136  else {
1137  free(incl->include_location_file);
1138  incl->include_location_file = strdup(to_file);
1139  }
1140  }
1141  }
1142  for (cat = conf->root; cat; cat = cat->next) {
1143  if (strcmp(cat->file,from_file) == 0) {
1144  if (from_len >= to_len)
1145  strcpy(cat->file, to_file);
1146  else {
1147  free(cat->file);
1148  cat->file = strdup(to_file);
1149  }
1150  }
1151  for (v = cat->root; v; v = v->next) {
1152  if (strcmp(v->file,from_file) == 0) {
1153  if (from_len >= to_len)
1154  strcpy(v->file, to_file);
1155  else {
1156  free(v->file);
1157  v->file = strdup(to_file);
1158  }
1159  }
1160  }
1161  }
1162 }
1163 
1165 {
1166  struct ast_config_include *x;
1167  for (x=conf->includes;x;x=x->next)
1168  {
1169  if (strcmp(x->included_file,included_file) == 0)
1170  return x;
1171  }
1172  return 0;
1173 }
1174 
1175 
1176 static void ast_variable_append(struct ast_category *category, struct ast_variable *variable);
1177 
1178 static void ast_variable_append(struct ast_category *category, struct ast_variable *variable)
1179 {
1180  if (!variable)
1181  return;
1182  if (category->last)
1183  category->last->next = variable;
1184  else
1185  category->root = variable;
1186  category->last = variable;
1187  while (category->last->next)
1188  category->last = category->last->next;
1189 }
1190 
1191 static struct ast_category *category_get(const struct ast_config *config, const char *category_name, int ignored);
1192 
1193 static struct ast_category *category_get(const struct ast_config *config, const char *category_name, int ignored)
1194 {
1195  struct ast_category *cat;
1196 
1197  /* try exact match first, then case-insensitive match */
1198  for (cat = config->root; cat; cat = cat->next) {
1199  if (cat->name == category_name && (ignored || !cat->ignored))
1200  return cat;
1201  }
1202 
1203  for (cat = config->root; cat; cat = cat->next) {
1204  if (!strcasecmp(cat->name, category_name) && (ignored || !cat->ignored))
1205  return cat;
1206  }
1207 
1208  return NULL;
1209 }
1210 
1211 static struct ast_category *ast_category_get(const struct ast_config *config, const char *category_name)
1212 {
1213  return category_get(config, category_name, 0);
1214 }
1215 
1216 static struct ast_variable *ast_variable_browse(const struct ast_config *config, const char *category)
1217 {
1218  struct ast_category *cat = NULL;
1219 
1220  if (category && config->last_browse && (config->last_browse->name == category))
1221  cat = config->last_browse;
1222  else
1223  cat = ast_category_get(config, category);
1224 
1225  return (cat) ? cat->root : NULL;
1226 }
1227 
1228 static const char *ast_variable_retrieve(const struct ast_config *config, const char *category, const char *variable)
1229 {
1230  struct ast_variable *v;
1231 
1232  if (category) {
1233  for (v = ast_variable_browse(config, category); v; v = v->next) {
1234  if (!strcasecmp(variable, v->name))
1235  return v->value;
1236  }
1237  } else {
1238  struct ast_category *cat;
1239 
1240  for (cat = config->root; cat; cat = cat->next)
1241  for (v = cat->root; v; v = v->next)
1242  if (!strcasecmp(variable, v->name))
1243  return v->value;
1244  }
1245 
1246  return NULL;
1247 }
1248 
1249 static struct ast_variable *variable_clone(const struct ast_variable *old)
1250 {
1251  struct ast_variable *new = ast_variable_new(old->name, old->value, old->file);
1252 
1253  if (new) {
1254  new->lineno = old->lineno;
1255  new->object = old->object;
1256  new->blanklines = old->blanklines;
1257  /* TODO: clone comments? */
1258  }
1259 
1260  return new;
1261 }
1262 
1263 static void ast_variables_destroy(struct ast_variable *v)
1264 {
1265  struct ast_variable *vn;
1266 
1267  while (v) {
1268  vn = v;
1269  v = v->next;
1270  free(vn);
1271  }
1272 }
1273 
1274 static void ast_includes_destroy(struct ast_config_include *incls)
1275 {
1276  struct ast_config_include *incl,*inclnext;
1277 
1278  for (incl=incls; incl; incl = inclnext) {
1279  inclnext = incl->next;
1280  if (incl->include_location_file)
1281  free(incl->include_location_file);
1282  if (incl->exec_file)
1283  free(incl->exec_file);
1284  if (incl->included_file)
1285  free(incl->included_file);
1286  free(incl);
1287  }
1288 }
1289 
1290 static void ast_config_destroy(struct ast_config *cfg)
1291 {
1292  struct ast_category *cat, *catn;
1293 
1294  if (!cfg)
1295  return;
1296 
1298 
1299  cat = cfg->root;
1300  while (cat) {
1302  catn = cat;
1303  cat = cat->next;
1304  free(catn);
1305  }
1306  free(cfg);
1307 }
1308 
1310  /*! Allow \#exec in config files */
1312  /*! Do not fork() */
1314  /*! Keep quiet */
1316  /*! Console mode */
1318  /*! Run in realtime Linux priority */
1320  /*! Initialize keys for RSA authentication */
1322  /*! Remote console */
1324  /*! Execute an asterisk CLI command upon startup */
1325  AST_OPT_FLAG_EXEC = (1 << 7),
1326  /*! Don't use termcap colors */
1328  /*! Are we fully started yet? */
1330  /*! Trascode via signed linear */
1332  /*! Dump core on a seg fault */
1334  /*! Cache sound files */
1336  /*! Display timestamp in CLI verbose output */
1338  /*! Override config */
1340  /*! Reconnect */
1342  /*! Transmit Silence during Record() and DTMF Generation */
1344  /*! Suppress some warnings */
1346  /*! Always fork, even if verbose or debug settings are non-zero */
1348  /*! Disable log/verbose output to remote consoles */
1349  AST_OPT_FLAG_MUTE = (1 << 22),
1350  /*! There is a per-file debug setting */
1352  /*! Terminal colors should be adjusted for a light-colored background */
1354  /*! Force black background */
1356 };
1357 
1358 /* options.h declares ast_options extern; I need it static? */
1359 #define AST_CACHE_DIR_LEN 512
1360 #define AST_FILENAME_MAX 80
1361 
1362 /*! These are the options that set by default when Asterisk starts */
1363 #define AST_DEFAULT_OPTIONS AST_OPT_FLAG_TRANSCODE_VIA_SLIN
1364 
1366 
1367 #define ast_opt_exec_includes ast_test_flag(&ast_options, AST_OPT_FLAG_EXEC_INCLUDES)
1368 #define ast_opt_no_fork ast_test_flag(&ast_options, AST_OPT_FLAG_NO_FORK)
1369 #define ast_opt_quiet ast_test_flag(&ast_options, AST_OPT_FLAG_QUIET)
1370 #define ast_opt_console ast_test_flag(&ast_options, AST_OPT_FLAG_CONSOLE)
1371 #define ast_opt_high_priority ast_test_flag(&ast_options, AST_OPT_FLAG_HIGH_PRIORITY)
1372 #define ast_opt_init_keys ast_test_flag(&ast_options, AST_OPT_FLAG_INIT_KEYS)
1373 #define ast_opt_remote ast_test_flag(&ast_options, AST_OPT_FLAG_REMOTE)
1374 #define ast_opt_exec ast_test_flag(&ast_options, AST_OPT_FLAG_EXEC)
1375 #define ast_opt_no_color ast_test_flag(&ast_options, AST_OPT_FLAG_NO_COLOR)
1376 #define ast_fully_booted ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)
1377 #define ast_opt_transcode_via_slin ast_test_flag(&ast_options, AST_OPT_FLAG_TRANSCODE_VIA_SLIN)
1378 #define ast_opt_priority_jumping ast_test_flag(&ast_options, AST_OPT_FLAG_PRIORITY_JUMPING)
1379 #define ast_opt_dump_core ast_test_flag(&ast_options, AST_OPT_FLAG_DUMP_CORE)
1380 #define ast_opt_cache_record_files ast_test_flag(&ast_options, AST_OPT_FLAG_CACHE_RECORD_FILES)
1381 #define ast_opt_timestamp ast_test_flag(&ast_options, AST_OPT_FLAG_TIMESTAMP)
1382 #define ast_opt_override_config ast_test_flag(&ast_options, AST_OPT_FLAG_OVERRIDE_CONFIG)
1383 #define ast_opt_reconnect ast_test_flag(&ast_options, AST_OPT_FLAG_RECONNECT)
1384 #define ast_opt_transmit_silence ast_test_flag(&ast_options, AST_OPT_FLAG_TRANSMIT_SILENCE)
1385 #define ast_opt_dont_warn ast_test_flag(&ast_options, AST_OPT_FLAG_DONT_WARN)
1386 #define ast_opt_always_fork ast_test_flag(&ast_options, AST_OPT_FLAG_ALWAYS_FORK)
1387 #define ast_opt_mute ast_test_flag(&ast_options, AST_OPT_FLAG_MUTE)
1388 
1389 extern int option_verbose;
1390 extern int option_debug; /*!< Debugging */
1391 extern int ast_option_maxcalls; /*!< Maximum number of simultaneous channels */
1392 extern double ast_option_maxload;
1393 extern char ast_defaultlanguage[];
1394 
1395 extern pid_t ast_mainpid;
1396 
1397 extern char record_cache_dir[AST_CACHE_DIR_LEN];
1398 extern char debug_filename[AST_FILENAME_MAX];
1399 
1400 extern int ast_language_is_prefix;
1401 
1402 
1403 
1404 /* linkedlists.h */
1405 
1406 /*!
1407  \brief Write locks a list.
1408  \param head This is a pointer to the list head structure
1409 
1410  This macro attempts to place an exclusive write lock in the
1411  list head structure pointed to by head.
1412  Returns non-zero on success, 0 on failure
1413 */
1414 #define AST_RWLIST_WRLOCK(head) \
1415  ast_rwlock_wrlock(&(head)->lock)
1416 
1417 /*!
1418  \brief Read locks a list.
1419  \param head This is a pointer to the list head structure
1420 
1421  This macro attempts to place a read lock in the
1422  list head structure pointed to by head.
1423  Returns non-zero on success, 0 on failure
1424 */
1425 #define AST_RWLIST_RDLOCK(head) \
1426  ast_rwlock_rdlock(&(head)->lock)
1427 
1428 /*!
1429  \brief Attempts to unlock a read/write based list.
1430  \param head This is a pointer to the list head structure
1431 
1432  This macro attempts to remove a read or write lock from the
1433  list head structure pointed to by head. If the list
1434  was not locked by this thread, this macro has no effect.
1435 */
1436 #define AST_RWLIST_UNLOCK(head) \
1437  ast_rwlock_unlock(&(head)->lock)
1438 
1439 /*!
1440  \brief Defines a structure to be used to hold a list of specified type.
1441  \param name This will be the name of the defined structure.
1442  \param type This is the type of each list entry.
1443 
1444  This macro creates a structure definition that can be used
1445  to hold a list of the entries of type \a type. It does not actually
1446  declare (allocate) a structure; to do that, either follow this
1447  macro with the desired name of the instance you wish to declare,
1448  or use the specified \a name to declare instances elsewhere.
1449 
1450  Example usage:
1451  \code
1452  static AST_LIST_HEAD(entry_list, entry) entries;
1453  \endcode
1454 
1455  This would define \c struct \c entry_list, and declare an instance of it named
1456  \a entries, all intended to hold a list of type \c struct \c entry.
1457 */
1458 #define AST_LIST_HEAD(name, type) \
1459 struct name { \
1460  struct type *first; \
1461  struct type *last; \
1462  ast_mutex_t lock; \
1463 }
1464 
1465 /*!
1466  \brief Defines a structure to be used to hold a read/write list of specified type.
1467  \param name This will be the name of the defined structure.
1468  \param type This is the type of each list entry.
1469 
1470  This macro creates a structure definition that can be used
1471  to hold a list of the entries of type \a type. It does not actually
1472  declare (allocate) a structure; to do that, either follow this
1473  macro with the desired name of the instance you wish to declare,
1474  or use the specified \a name to declare instances elsewhere.
1475 
1476  Example usage:
1477  \code
1478  static AST_RWLIST_HEAD(entry_list, entry) entries;
1479  \endcode
1480 
1481  This would define \c struct \c entry_list, and declare an instance of it named
1482  \a entries, all intended to hold a list of type \c struct \c entry.
1483 */
1484 #define AST_RWLIST_HEAD(name, type) \
1485 struct name { \
1486  struct type *first; \
1487  struct type *last; \
1488  ast_rwlock_t lock; \
1489 }
1490 
1491 /*!
1492  \brief Defines a structure to be used to hold a list of specified type (with no lock).
1493  \param name This will be the name of the defined structure.
1494  \param type This is the type of each list entry.
1495 
1496  This macro creates a structure definition that can be used
1497  to hold a list of the entries of type \a type. It does not actually
1498  declare (allocate) a structure; to do that, either follow this
1499  macro with the desired name of the instance you wish to declare,
1500  or use the specified \a name to declare instances elsewhere.
1501 
1502  Example usage:
1503  \code
1504  static AST_LIST_HEAD_NOLOCK(entry_list, entry) entries;
1505  \endcode
1506 
1507  This would define \c struct \c entry_list, and declare an instance of it named
1508  \a entries, all intended to hold a list of type \c struct \c entry.
1509 */
1510 #define AST_LIST_HEAD_NOLOCK(name, type) \
1511 struct name { \
1512  struct type *first; \
1513  struct type *last; \
1514 }
1515 
1516 /*!
1517  \brief Defines initial values for a declaration of AST_LIST_HEAD
1518 */
1519 #define AST_LIST_HEAD_INIT_VALUE { \
1520  .first = NULL, \
1521  .last = NULL, \
1522  .lock = AST_MUTEX_INIT_VALUE, \
1523  }
1524 
1525 /*!
1526  \brief Defines initial values for a declaration of AST_RWLIST_HEAD
1527 */
1528 #define AST_RWLIST_HEAD_INIT_VALUE { \
1529  .first = NULL, \
1530  .last = NULL, \
1531  .lock = AST_RWLOCK_INIT_VALUE, \
1532  }
1533 
1534 /*!
1535  \brief Defines initial values for a declaration of AST_LIST_HEAD_NOLOCK
1536 */
1537 #define AST_LIST_HEAD_NOLOCK_INIT_VALUE { \
1538  .first = NULL, \
1539  .last = NULL, \
1540  }
1541 
1542 /*!
1543  \brief Defines a structure to be used to hold a list of specified type, statically initialized.
1544  \param name This will be the name of the defined structure.
1545  \param type This is the type of each list entry.
1546 
1547  This macro creates a structure definition that can be used
1548  to hold a list of the entries of type \a type, and allocates an instance
1549  of it, initialized to be empty.
1550 
1551  Example usage:
1552  \code
1553  static AST_LIST_HEAD_STATIC(entry_list, entry);
1554  \endcode
1555 
1556  This would define \c struct \c entry_list, intended to hold a list of
1557  type \c struct \c entry.
1558 */
1559 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
1560 #define AST_LIST_HEAD_STATIC(name, type) \
1561 struct name { \
1562  struct type *first; \
1563  struct type *last; \
1564  ast_mutex_t lock; \
1565 } name; \
1566 static void __attribute__((constructor)) init_##name(void) \
1567 { \
1568  AST_LIST_HEAD_INIT(&name); \
1569 } \
1570 static void __attribute__((destructor)) fini_##name(void) \
1571 { \
1572  AST_LIST_HEAD_DESTROY(&name); \
1573 } \
1574 struct __dummy_##name
1575 #else
1576 #define AST_LIST_HEAD_STATIC(name, type) \
1577 struct name { \
1578  struct type *first; \
1579  struct type *last; \
1580  ast_mutex_t lock; \
1581 } name = AST_LIST_HEAD_INIT_VALUE
1582 #endif
1583 
1584 /*!
1585  \brief Defines a structure to be used to hold a read/write list of specified type, statically initialized.
1586  \param name This will be the name of the defined structure.
1587  \param type This is the type of each list entry.
1588 
1589  This macro creates a structure definition that can be used
1590  to hold a list of the entries of type \a type, and allocates an instance
1591  of it, initialized to be empty.
1592 
1593  Example usage:
1594  \code
1595  static AST_RWLIST_HEAD_STATIC(entry_list, entry);
1596  \endcode
1597 
1598  This would define \c struct \c entry_list, intended to hold a list of
1599  type \c struct \c entry.
1600 */
1601 #ifndef AST_RWLOCK_INIT_VALUE
1602 #define AST_RWLIST_HEAD_STATIC(name, type) \
1603 struct name { \
1604  struct type *first; \
1605  struct type *last; \
1606  ast_rwlock_t lock; \
1607 } name; \
1608 static void __attribute__((constructor)) init_##name(void) \
1609 { \
1610  AST_RWLIST_HEAD_INIT(&name); \
1611 } \
1612 static void __attribute__((destructor)) fini_##name(void) \
1613 { \
1614  AST_RWLIST_HEAD_DESTROY(&name); \
1615 } \
1616 struct __dummy_##name
1617 #else
1618 #define AST_RWLIST_HEAD_STATIC(name, type) \
1619 struct name { \
1620  struct type *first; \
1621  struct type *last; \
1622  ast_rwlock_t lock; \
1623 } name = AST_RWLIST_HEAD_INIT_VALUE
1624 #endif
1625 
1626 /*!
1627  \brief Defines a structure to be used to hold a list of specified type, statically initialized.
1628 
1629  This is the same as AST_LIST_HEAD_STATIC, except without the lock included.
1630 */
1631 #define AST_LIST_HEAD_NOLOCK_STATIC(name, type) \
1632 struct name { \
1633  struct type *first; \
1634  struct type *last; \
1635 } name = AST_LIST_HEAD_NOLOCK_INIT_VALUE
1636 
1637 /*!
1638  \brief Initializes a list head structure with a specified first entry.
1639  \param head This is a pointer to the list head structure
1640  \param entry pointer to the list entry that will become the head of the list
1641 
1642  This macro initializes a list head structure by setting the head
1643  entry to the supplied value and recreating the embedded lock.
1644 */
1645 #define AST_LIST_HEAD_SET(head, entry) do { \
1646  (head)->first = (entry); \
1647  (head)->last = (entry); \
1648  ast_mutex_init(&(head)->lock); \
1649 } while (0)
1650 
1651 /*!
1652  \brief Initializes an rwlist head structure with a specified first entry.
1653  \param head This is a pointer to the list head structure
1654  \param entry pointer to the list entry that will become the head of the list
1655 
1656  This macro initializes a list head structure by setting the head
1657  entry to the supplied value and recreating the embedded lock.
1658 */
1659 #define AST_RWLIST_HEAD_SET(head, entry) do { \
1660  (head)->first = (entry); \
1661  (head)->last = (entry); \
1662  ast_rwlock_init(&(head)->lock); \
1663 } while (0)
1664 
1665 /*!
1666  \brief Initializes a list head structure with a specified first entry.
1667  \param head This is a pointer to the list head structure
1668  \param entry pointer to the list entry that will become the head of the list
1669 
1670  This macro initializes a list head structure by setting the head
1671  entry to the supplied value.
1672 */
1673 #define AST_LIST_HEAD_SET_NOLOCK(head, entry) do { \
1674  (head)->first = (entry); \
1675  (head)->last = (entry); \
1676 } while (0)
1677 
1678 /*!
1679  \brief Declare a forward link structure inside a list entry.
1680  \param type This is the type of each list entry.
1681 
1682  This macro declares a structure to be used to link list entries together.
1683  It must be used inside the definition of the structure named in
1684  \a type, as follows:
1685 
1686  \code
1687  struct list_entry {
1688  ...
1689  AST_LIST_ENTRY(list_entry) list;
1690  }
1691  \endcode
1692 
1693  The field name \a list here is arbitrary, and can be anything you wish.
1694 */
1695 #define AST_LIST_ENTRY(type) \
1696 struct { \
1697  struct type *next; \
1698 }
1699 
1700 #define AST_RWLIST_ENTRY AST_LIST_ENTRY
1701 
1702 /*!
1703  \brief Returns the first entry contained in a list.
1704  \param head This is a pointer to the list head structure
1705  */
1706 #define AST_LIST_FIRST(head) ((head)->first)
1707 
1708 #define AST_RWLIST_FIRST AST_LIST_FIRST
1709 
1710 /*!
1711  \brief Returns the last entry contained in a list.
1712  \param head This is a pointer to the list head structure
1713  */
1714 #define AST_LIST_LAST(head) ((head)->last)
1715 
1716 #define AST_RWLIST_LAST AST_LIST_LAST
1717 
1718 /*!
1719  \brief Returns the next entry in the list after the given entry.
1720  \param elm This is a pointer to the current entry.
1721  \param field This is the name of the field (declared using AST_LIST_ENTRY())
1722  used to link entries of this list together.
1723 */
1724 #define AST_LIST_NEXT(elm, field) ((elm)->field.next)
1725 
1726 #define AST_RWLIST_NEXT AST_LIST_NEXT
1727 
1728 /*!
1729  \brief Checks whether the specified list contains any entries.
1730  \param head This is a pointer to the list head structure
1731 
1732  Returns non-zero if the list has entries, zero if not.
1733  */
1734 #define AST_LIST_EMPTY(head) (AST_LIST_FIRST(head) == NULL)
1735 
1736 #define AST_RWLIST_EMPTY AST_LIST_EMPTY
1737 
1738 /*!
1739  \brief Loops over (traverses) the entries in a list.
1740  \param head This is a pointer to the list head structure
1741  \param var This is the name of the variable that will hold a pointer to the
1742  current list entry on each iteration. It must be declared before calling
1743  this macro.
1744  \param field This is the name of the field (declared using AST_LIST_ENTRY())
1745  used to link entries of this list together.
1746 
1747  This macro is use to loop over (traverse) the entries in a list. It uses a
1748  \a for loop, and supplies the enclosed code with a pointer to each list
1749  entry as it loops. It is typically used as follows:
1750  \code
1751  static AST_LIST_HEAD(entry_list, list_entry) entries;
1752  ...
1753  struct list_entry {
1754  ...
1755  AST_LIST_ENTRY(list_entry) list;
1756  }
1757  ...
1758  struct list_entry *current;
1759  ...
1760  AST_LIST_TRAVERSE(&entries, current, list) {
1761  (do something with current here)
1762  }
1763  \endcode
1764  \warning If you modify the forward-link pointer contained in the \a current entry while
1765  inside the loop, the behavior will be unpredictable. At a minimum, the following
1766  macros will modify the forward-link pointer, and should not be used inside
1767  AST_LIST_TRAVERSE() against the entry pointed to by the \a current pointer without
1768  careful consideration of their consequences:
1769  \li AST_LIST_NEXT() (when used as an lvalue)
1770  \li AST_LIST_INSERT_AFTER()
1771  \li AST_LIST_INSERT_HEAD()
1772  \li AST_LIST_INSERT_TAIL()
1773 */
1774 #define AST_LIST_TRAVERSE(head,var,field) \
1775  for((var) = (head)->first; (var); (var) = (var)->field.next)
1776 
1777 #define AST_RWLIST_TRAVERSE AST_LIST_TRAVERSE
1778 
1779 /*!
1780  \brief Loops safely over (traverses) the entries in a list.
1781  \param head This is a pointer to the list head structure
1782  \param var This is the name of the variable that will hold a pointer to the
1783  current list entry on each iteration. It must be declared before calling
1784  this macro.
1785  \param field This is the name of the field (declared using AST_LIST_ENTRY())
1786  used to link entries of this list together.
1787 
1788  This macro is used to safely loop over (traverse) the entries in a list. It
1789  uses a \a for loop, and supplies the enclosed code with a pointer to each list
1790  entry as it loops. It is typically used as follows:
1791 
1792  \code
1793  static AST_LIST_HEAD(entry_list, list_entry) entries;
1794  ...
1795  struct list_entry {
1796  ...
1797  AST_LIST_ENTRY(list_entry) list;
1798  }
1799  ...
1800  struct list_entry *current;
1801  ...
1802  AST_LIST_TRAVERSE_SAFE_BEGIN(&entries, current, list) {
1803  (do something with current here)
1804  }
1805  AST_LIST_TRAVERSE_SAFE_END;
1806  \endcode
1807 
1808  It differs from AST_LIST_TRAVERSE() in that the code inside the loop can modify
1809  (or even free, after calling AST_LIST_REMOVE_CURRENT()) the entry pointed to by
1810  the \a current pointer without affecting the loop traversal.
1811 */
1812 #define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field) { \
1813  typeof((head)->first) __list_next; \
1814  typeof((head)->first) __list_prev = NULL; \
1815  typeof((head)->first) __new_prev = NULL; \
1816  for ((var) = (head)->first, __new_prev = (var), \
1817  __list_next = (var) ? (var)->field.next : NULL; \
1818  (var); \
1819  __list_prev = __new_prev, (var) = __list_next, \
1820  __new_prev = (var), \
1821  __list_next = (var) ? (var)->field.next : NULL \
1822  )
1823 
1824 #define AST_RWLIST_TRAVERSE_SAFE_BEGIN AST_LIST_TRAVERSE_SAFE_BEGIN
1825 
1826 /*!
1827  \brief Removes the \a current entry from a list during a traversal.
1828  \param head This is a pointer to the list head structure
1829  \param field This is the name of the field (declared using AST_LIST_ENTRY())
1830  used to link entries of this list together.
1831 
1832  \note This macro can \b only be used inside an AST_LIST_TRAVERSE_SAFE_BEGIN()
1833  block; it is used to unlink the current entry from the list without affecting
1834  the list traversal (and without having to re-traverse the list to modify the
1835  previous entry, if any).
1836  */
1837 #define AST_LIST_REMOVE_CURRENT(head, field) \
1838  __new_prev->field.next = NULL; \
1839  __new_prev = __list_prev; \
1840  if (__list_prev) \
1841  __list_prev->field.next = __list_next; \
1842  else \
1843  (head)->first = __list_next; \
1844  if (!__list_next) \
1845  (head)->last = __list_prev;
1846 
1847 #define AST_RWLIST_REMOVE_CURRENT AST_LIST_REMOVE_CURRENT
1848 
1849 /*!
1850  \brief Inserts a list entry before the current entry during a traversal.
1851  \param head This is a pointer to the list head structure
1852  \param elm This is a pointer to the entry to be inserted.
1853  \param field This is the name of the field (declared using AST_LIST_ENTRY())
1854  used to link entries of this list together.
1855 
1856  \note This macro can \b only be used inside an AST_LIST_TRAVERSE_SAFE_BEGIN()
1857  block.
1858  */
1859 #define AST_LIST_INSERT_BEFORE_CURRENT(head, elm, field) do { \
1860  if (__list_prev) { \
1861  (elm)->field.next = __list_prev->field.next; \
1862  __list_prev->field.next = elm; \
1863  } else { \
1864  (elm)->field.next = (head)->first; \
1865  (head)->first = (elm); \
1866  } \
1867  __new_prev = (elm); \
1868 } while (0)
1869 
1870 #define AST_RWLIST_INSERT_BEFORE_CURRENT AST_LIST_INSERT_BEFORE_CURRENT
1871 
1872 /*!
1873  \brief Closes a safe loop traversal block.
1874  */
1875 #define AST_LIST_TRAVERSE_SAFE_END }
1876 
1877 #define AST_RWLIST_TRAVERSE_SAFE_END AST_LIST_TRAVERSE_SAFE_END
1878 
1879 /*!
1880  \brief Initializes a list head structure.
1881  \param head This is a pointer to the list head structure
1882 
1883  This macro initializes a list head structure by setting the head
1884  entry to \a NULL (empty list) and recreating the embedded lock.
1885 */
1886 #define AST_LIST_HEAD_INIT(head) { \
1887  (head)->first = NULL; \
1888  (head)->last = NULL; \
1889  ast_mutex_init(&(head)->lock); \
1890 }
1891 
1892 /*!
1893  \brief Initializes an rwlist head structure.
1894  \param head This is a pointer to the list head structure
1895 
1896  This macro initializes a list head structure by setting the head
1897  entry to \a NULL (empty list) and recreating the embedded lock.
1898 */
1899 #define AST_RWLIST_HEAD_INIT(head) { \
1900  (head)->first = NULL; \
1901  (head)->last = NULL; \
1902  ast_rwlock_init(&(head)->lock); \
1903 }
1904 
1905 /*!
1906  \brief Destroys an rwlist head structure.
1907  \param head This is a pointer to the list head structure
1908 
1909  This macro destroys a list head structure by setting the head
1910  entry to \a NULL (empty list) and destroying the embedded lock.
1911  It does not free the structure from memory.
1912 */
1913 #define AST_RWLIST_HEAD_DESTROY(head) { \
1914  (head)->first = NULL; \
1915  (head)->last = NULL; \
1916  ast_rwlock_destroy(&(head)->lock); \
1917 }
1918 
1919 /*!
1920  \brief Initializes a list head structure.
1921  \param head This is a pointer to the list head structure
1922 
1923  This macro initializes a list head structure by setting the head
1924  entry to \a NULL (empty list). There is no embedded lock handling
1925  with this macro.
1926 */
1927 #define AST_LIST_HEAD_INIT_NOLOCK(head) { \
1928  (head)->first = NULL; \
1929  (head)->last = NULL; \
1930 }
1931 
1932 /*!
1933  \brief Inserts a list entry after a given entry.
1934  \param head This is a pointer to the list head structure
1935  \param listelm This is a pointer to the entry after which the new entry should
1936  be inserted.
1937  \param elm This is a pointer to the entry to be inserted.
1938  \param field This is the name of the field (declared using AST_LIST_ENTRY())
1939  used to link entries of this list together.
1940  */
1941 #define AST_LIST_INSERT_AFTER(head, listelm, elm, field) do { \
1942  (elm)->field.next = (listelm)->field.next; \
1943  (listelm)->field.next = (elm); \
1944  if ((head)->last == (listelm)) \
1945  (head)->last = (elm); \
1946 } while (0)
1947 
1948 #define AST_RWLIST_INSERT_AFTER AST_LIST_INSERT_AFTER
1949 
1950 /*!
1951  \brief Inserts a list entry at the head of a list.
1952  \param head This is a pointer to the list head structure
1953  \param elm This is a pointer to the entry to be inserted.
1954  \param field This is the name of the field (declared using AST_LIST_ENTRY())
1955  used to link entries of this list together.
1956  */
1957 #define AST_LIST_INSERT_HEAD(head, elm, field) do { \
1958  (elm)->field.next = (head)->first; \
1959  (head)->first = (elm); \
1960  if (!(head)->last) \
1961  (head)->last = (elm); \
1962 } while (0)
1963 
1964 #define AST_RWLIST_INSERT_HEAD AST_LIST_INSERT_HEAD
1965 
1966 /*!
1967  \brief Appends a list entry to the tail of a list.
1968  \param head This is a pointer to the list head structure
1969  \param elm This is a pointer to the entry to be appended.
1970  \param field This is the name of the field (declared using AST_LIST_ENTRY())
1971  used to link entries of this list together.
1972 
1973  Note: The link field in the appended entry is \b not modified, so if it is
1974  actually the head of a list itself, the entire list will be appended
1975  temporarily (until the next AST_LIST_INSERT_TAIL is performed).
1976  */
1977 #define AST_LIST_INSERT_TAIL(head, elm, field) do { \
1978  if (!(head)->first) { \
1979  (head)->first = (elm); \
1980  (head)->last = (elm); \
1981  } else { \
1982  (head)->last->field.next = (elm); \
1983  (head)->last = (elm); \
1984  } \
1985 } while (0)
1986 
1987 #define AST_RWLIST_INSERT_TAIL AST_LIST_INSERT_TAIL
1988 
1989 /*!
1990  \brief Appends a whole list to the tail of a list.
1991  \param head This is a pointer to the list head structure
1992  \param list This is a pointer to the list to be appended.
1993  \param field This is the name of the field (declared using AST_LIST_ENTRY())
1994  used to link entries of this list together.
1995  */
1996 #define AST_LIST_APPEND_LIST(head, list, field) do { \
1997  if (!(head)->first) { \
1998  (head)->first = (list)->first; \
1999  (head)->last = (list)->last; \
2000  } else { \
2001  (head)->last->field.next = (list)->first; \
2002  (head)->last = (list)->last; \
2003  } \
2004 } while (0)
2005 
2006 #define AST_RWLIST_APPEND_LIST AST_LIST_APPEND_LIST
2007 
2008 /*!
2009  \brief Removes and returns the head entry from a list.
2010  \param head This is a pointer to the list head structure
2011  \param field This is the name of the field (declared using AST_LIST_ENTRY())
2012  used to link entries of this list together.
2013 
2014  Removes the head entry from the list, and returns a pointer to it.
2015  This macro is safe to call on an empty list.
2016  */
2017 #define AST_LIST_REMOVE_HEAD(head, field) ({ \
2018  typeof((head)->first) cur = (head)->first; \
2019  if (cur) { \
2020  (head)->first = cur->field.next; \
2021  cur->field.next = NULL; \
2022  if ((head)->last == cur) \
2023  (head)->last = NULL; \
2024  } \
2025  cur; \
2026  })
2027 
2028 #define AST_RWLIST_REMOVE_HEAD AST_LIST_REMOVE_HEAD
2029 
2030 /*!
2031  \brief Removes a specific entry from a list.
2032  \param head This is a pointer to the list head structure
2033  \param elm This is a pointer to the entry to be removed.
2034  \param field This is the name of the field (declared using AST_LIST_ENTRY())
2035  used to link entries of this list together.
2036  \warning The removed entry is \b not freed nor modified in any way.
2037  */
2038 #define AST_LIST_REMOVE(head, elm, field) do { \
2039  if ((head)->first == (elm)) { \
2040  (head)->first = (elm)->field.next; \
2041  if ((head)->last == (elm)) \
2042  (head)->last = NULL; \
2043  } else { \
2044  typeof(elm) curelm = (head)->first; \
2045  while (curelm && (curelm->field.next != (elm))) \
2046  curelm = curelm->field.next; \
2047  if (curelm) { \
2048  curelm->field.next = (elm)->field.next; \
2049  if ((head)->last == (elm)) \
2050  (head)->last = curelm; \
2051  } \
2052  } \
2053  (elm)->field.next = NULL; \
2054 } while (0)
2055 
2056 #define AST_RWLIST_REMOVE AST_LIST_REMOVE
2057 
2058 /* chanvars.h */
2059 
2060 struct ast_var_t {
2061  AST_LIST_ENTRY(ast_var_t) entries;
2062  char *value;
2063  char name[0];
2064 };
2065 
2067 
2070 
2071 
2072 /* IN CONFLICT: struct ast_var_t *ast_var_assign(const char *name, const char *value); */
2073 
2074 static struct ast_var_t *ast_var_assign(const char *name, const char *value);
2075 
2076 static void ast_var_delete(struct ast_var_t *var);
2077 
2078 /*from channel.h */
2079 #define AST_MAX_EXTENSION 80 /*!< Max length of an extension */
2080 
2081 
2082 /* from pbx.h */
2083 #define PRIORITY_HINT -1 /*!< Special Priority for a hint */
2084 
2086  AST_EXTENSION_REMOVED = -2, /*!< Extension removed */
2087  AST_EXTENSION_DEACTIVATED = -1, /*!< Extension hint removed */
2088  AST_EXTENSION_NOT_INUSE = 0, /*!< No device INUSE or BUSY */
2089  AST_EXTENSION_INUSE = 1 << 0, /*!< One or more devices INUSE */
2090  AST_EXTENSION_BUSY = 1 << 1, /*!< All devices BUSY */
2091  AST_EXTENSION_UNAVAILABLE = 1 << 2, /*!< All devices UNAVAILABLE/UNREGISTERED */
2092  AST_EXTENSION_RINGING = 1 << 3, /*!< All devices RINGING */
2093  AST_EXTENSION_ONHOLD = 1 << 4, /*!< All devices ONHOLD */
2094 };
2095 
2096 struct ast_custom_function {
2097  const char *name; /*!< Name */
2098  const char *synopsis; /*!< Short description for "show functions" */
2099  const char *desc; /*!< Help text that explains it all */
2100  const char *syntax; /*!< Syntax description */
2101  int (*read)(struct ast_channel *, const char *, char *, char *, size_t); /*!< Read function, if read is supported */
2102  int (*write)(struct ast_channel *, const char *, char *, const char *); /*!< Write function, if write is supported */
2104 };
2105 
2106 typedef int (ast_switch_f)(struct ast_channel *chan, const char *context,
2107  const char *exten, int priority, const char *callerid, const char *data);
2108 
2109 struct ast_switch {
2110  AST_LIST_ENTRY(ast_switch) list;
2111  const char *name; /*!< Name of the switch */
2112  const char *description; /*!< Description of the switch */
2113 
2116  ast_switch_f *exec;
2118 };
2119 
2120 
2121 static char *config_filename = "extensions.conf";
2122 static char *global_registrar = "conf2ael";
2123 static char userscontext[AST_MAX_EXTENSION] = "default";
2124 static int static_config = 0;
2125 static int write_protect_config = 1;
2126 static int autofallthrough_config = 0;
2127 static int clearglobalvars_config = 0;
2128 static void pbx_substitute_variables_helper(struct ast_channel *c,const char *cp1,char *cp2,int count);
2129 
2130 
2131 /* stolen from callerid.c */
2132 
2133 /*! \brief Clean up phone string
2134  * remove '(', ' ', ')', non-trailing '.', and '-' not in square brackets.
2135  * Basically, remove anything that could be invalid in a pattern.
2136  */
2137 static void ast_shrink_phone_number(char *n)
2138 {
2139  int x, y=0;
2140  int bracketed = 0;
2141 
2142  for (x=0; n[x]; x++) {
2143  switch(n[x]) {
2144  case '[':
2145  bracketed++;
2146  n[y++] = n[x];
2147  break;
2148  case ']':
2149  bracketed--;
2150  n[y++] = n[x];
2151  break;
2152  case '-':
2153  if (bracketed)
2154  n[y++] = n[x];
2155  break;
2156  case '.':
2157  if (!n[x+1])
2158  n[y++] = n[x];
2159  break;
2160  default:
2161  if (!strchr("()", n[x]))
2162  n[y++] = n[x];
2163  }
2164  }
2165  n[y] = '\0';
2166 }
2167 
2168 
2169 /* stolen from chanvars.c */
2170 
2171 static const char *ast_var_name(const struct ast_var_t *var)
2172 {
2173  const char *name;
2174 
2175  if (var == NULL || (name = var->name) == NULL)
2176  return NULL;
2177  /* Return the name without the initial underscores */
2178  if (name[0] == '_') {
2179  name++;
2180  if (name[0] == '_')
2181  name++;
2182  }
2183  return name;
2184 }
2185 
2186 /* experiment 1: see if it's easier just to use existing config code
2187  * to read in the extensions.conf file. In this scenario,
2188  I have to rip/copy code from other modules, because they
2189  are staticly declared as-is. A solution would be to move
2190  the ripped code to another location and make them available
2191  to other modules and standalones */
2192 
2193 /* Our own version of ast_log, since the expr parser uses it. -- stolen from utils/check_expr.c */
2194 
2195 static void ast_log(int level, const char *file, int line, const char *function, const char *fmt, ...)
2196 {
2197  va_list vars;
2198  va_start(vars,fmt);
2199 
2200  printf("LOG: lev:%d file:%s line:%d func: %s ",
2201  level, file, line, function);
2202  vprintf(fmt, vars);
2203  fflush(stdout);
2204  va_end(vars);
2205 }
2206 
2207 void __attribute__((format(printf, 1, 2))) ast_verbose(const char *fmt, ...)
2208 {
2209  va_list vars;
2210  va_start(vars,fmt);
2211 
2212  printf("VERBOSE: ");
2213  vprintf(fmt, vars);
2214  fflush(stdout);
2215  va_end(vars);
2216 }
2217 
2218 /* stolen from main/utils.c */
2219 static char *ast_process_quotes_and_slashes(char *start, char find, char replace_with)
2220 {
2221  char *dataPut = start;
2222  int inEscape = 0;
2223  int inQuotes = 0;
2224 
2225  for (; *start; start++) {
2226  if (inEscape) {
2227  *dataPut++ = *start; /* Always goes verbatim */
2228  inEscape = 0;
2229  } else {
2230  if (*start == '\\') {
2231  inEscape = 1; /* Do not copy \ into the data */
2232  } else if (*start == '\'') {
2233  inQuotes = 1 - inQuotes; /* Do not copy ' into the data */
2234  } else {
2235  /* Replace , with |, unless in quotes */
2236  *dataPut++ = inQuotes ? *start : ((*start == find) ? replace_with : *start);
2237  }
2238  }
2239  }
2240  if (start != dataPut)
2241  *dataPut = 0;
2242  return dataPut;
2243 }
2244 
2245 static int ast_true(const char *s)
2246 {
2247  if (ast_strlen_zero(s))
2248  return 0;
2249 
2250  /* Determine if this is a true value */
2251  if (!strcasecmp(s, "yes") ||
2252  !strcasecmp(s, "true") ||
2253  !strcasecmp(s, "y") ||
2254  !strcasecmp(s, "t") ||
2255  !strcasecmp(s, "1") ||
2256  !strcasecmp(s, "on"))
2257  return -1;
2258 
2259  return 0;
2260 }
2261 
2262 #define ONE_MILLION 1000000
2263 /*
2264  * put timeval in a valid range. usec is 0..999999
2265  * negative values are not allowed and truncated.
2266  */
2267 static struct timeval tvfix(struct timeval a)
2268 {
2269  if (a.tv_usec >= ONE_MILLION) {
2270  ast_log(LOG_WARNING, "warning too large timestamp %ld.%ld\n",
2271  (long)a.tv_sec, (long int) a.tv_usec);
2272  a.tv_sec += a.tv_usec / ONE_MILLION;
2273  a.tv_usec %= ONE_MILLION;
2274  } else if (a.tv_usec < 0) {
2275  ast_log(LOG_WARNING, "warning negative timestamp %ld.%ld\n",
2276  (long)a.tv_sec, (long int) a.tv_usec);
2277  a.tv_usec = 0;
2278  }
2279  return a;
2280 }
2281 
2282 struct timeval ast_tvadd(struct timeval a, struct timeval b);
2283 struct timeval ast_tvadd(struct timeval a, struct timeval b)
2284 {
2285  /* consistency checks to guarantee usec in 0..999999 */
2286  a = tvfix(a);
2287  b = tvfix(b);
2288  a.tv_sec += b.tv_sec;
2289  a.tv_usec += b.tv_usec;
2290  if (a.tv_usec >= ONE_MILLION) {
2291  a.tv_sec++;
2292  a.tv_usec -= ONE_MILLION;
2293  }
2294  return a;
2295 }
2296 
2297 struct timeval ast_tvsub(struct timeval a, struct timeval b);
2298 struct timeval ast_tvsub(struct timeval a, struct timeval b)
2299 {
2300  /* consistency checks to guarantee usec in 0..999999 */
2301  a = tvfix(a);
2302  b = tvfix(b);
2303  a.tv_sec -= b.tv_sec;
2304  a.tv_usec -= b.tv_usec;
2305  if (a.tv_usec < 0) {
2306  a.tv_sec-- ;
2307  a.tv_usec += ONE_MILLION;
2308  }
2309  return a;
2310 }
2311 #undef ONE_MILLION
2312 
2313 void ast_mark_lock_failed(void *lock_addr);
2314 void ast_mark_lock_failed(void *lock_addr)
2315 {
2316  /* Pretend to do something. */
2317 }
2318 
2319 /* stolen from pbx.c */
2320 #define VAR_BUF_SIZE 4096
2321 
2322 #define VAR_NORMAL 1
2323 #define VAR_SOFTTRAN 2
2324 #define VAR_HARDTRAN 3
2325 
2326 #define BACKGROUND_SKIP (1 << 0)
2327 #define BACKGROUND_NOANSWER (1 << 1)
2328 #define BACKGROUND_MATCHEXTEN (1 << 2)
2329 #define BACKGROUND_PLAYBACK (1 << 3)
2330 
2331 /*!
2332  \brief ast_exten: An extension
2333  The dialplan is saved as a linked list with each context
2334  having it's own linked list of extensions - one item per
2335  priority.
2336 */
2337 struct ast_exten {
2338  char *exten; /*!< Extension name */
2339  int matchcid; /*!< Match caller id ? */
2340  const char *cidmatch; /*!< Caller id to match for this extension */
2341  int priority; /*!< Priority */
2342  const char *label; /*!< Label */
2343  struct ast_context *parent; /*!< The context this extension belongs to */
2344  const char *app; /*!< Application to execute */
2345  struct ast_app *cached_app; /*!< Cached location of application */
2346  void *data; /*!< Data to use (arguments) */
2347  void (*datad)(void *); /*!< Data destructor */
2348  struct ast_exten *peer; /*!< Next higher priority with our extension */
2349  const char *registrar; /*!< Registrar */
2350  struct ast_exten *next; /*!< Extension with a greater ID */
2351  char stuff[0];
2352 };
2353 /* from pbx.h */
2354 typedef int (*ast_state_cb_type)(char *context, char* id, enum ast_extension_states state, void *data);
2355 struct ast_timing {
2356  int hastime; /*!< If time construct exists */
2357  unsigned int monthmask; /*!< Mask for month */
2358  unsigned int daymask; /*!< Mask for date */
2359  unsigned int dowmask; /*!< Mask for day of week (mon-sun) */
2360  unsigned int minmask[48]; /*!< Mask for minute */
2361  char *timezone; /*!< NULL, or zoneinfo style timezone */
2362 };
2363 /* end of pbx.h */
2364 /*! \brief ast_include: include= support in extensions.conf */
2365 struct ast_include {
2366  const char *name;
2367  const char *rname; /*!< Context to include */
2368  const char *registrar; /*!< Registrar */
2369  int hastime; /*!< If time construct exists */
2370  struct ast_timing timing; /*!< time construct */
2371  struct ast_include *next; /*!< Link them together */
2372  char stuff[0];
2373 };
2374 
2375 /*! \brief ast_sw: Switch statement in extensions.conf */
2376 struct ast_sw {
2377  char *name;
2378  const char *registrar; /*!< Registrar */
2379  char *data; /*!< Data load */
2380  int eval;
2381  AST_LIST_ENTRY(ast_sw) list;
2382  char *tmpdata;
2383  char stuff[0];
2384 };
2385 
2386 /*! \brief ast_ignorepat: Ignore patterns in dial plan */
2387 struct ast_ignorepat {
2388  const char *registrar;
2389  struct ast_ignorepat *next;
2390  char pattern[0];
2391 };
2392 
2393 /*! \brief ast_context: An extension context */
2394 struct ast_context {
2395  ast_rwlock_t lock; /*!< A lock to prevent multiple threads from clobbering the context */
2396  struct ast_exten *root; /*!< The root of the list of extensions */
2397  struct ast_context *next; /*!< Link them together */
2398  struct ast_include *includes; /*!< Include other contexts */
2399  struct ast_ignorepat *ignorepats; /*!< Patterns for which to continue playing dialtone */
2400  const char *registrar; /*!< Registrar */
2401  AST_LIST_HEAD_NOLOCK(, ast_sw) alts; /*!< Alternative switches */
2402  ast_mutex_t macrolock; /*!< A lock to implement "exclusive" macros - held whilst a call is executing in the macro */
2403  char name[0]; /*!< Name of the context */
2404 };
2405 
2406 
2407 /*! \brief ast_app: A registered application */
2408 struct ast_app {
2409  int (*execute)(struct ast_channel *chan, void *data);
2410  const char *synopsis; /*!< Synopsis text for 'show applications' */
2411  const char *description; /*!< Description (help text) for 'show application &lt;name&gt;' */
2412  AST_RWLIST_ENTRY(ast_app) list; /*!< Next app in list */
2413  void *module; /*!< Module this app belongs to */
2414  char name[0]; /*!< Name of the application */
2415 };
2416 
2417 
2418 /*! \brief ast_state_cb: An extension state notify register item */
2419 struct ast_state_cb {
2420  int id;
2421  void *data;
2422  ast_state_cb_type callback;
2423  struct ast_state_cb *next;
2424 };
2425 
2426 /*! \brief Structure for dial plan hints
2427 
2428  \note Hints are pointers from an extension in the dialplan to one or
2429  more devices (tech/name)
2430  - See \ref AstExtState
2431 */
2432 struct ast_hint {
2433  struct ast_exten *exten; /*!< Extension */
2434  int laststate; /*!< Last known state */
2435  struct ast_state_cb *callbacks; /*!< Callback list for this extension */
2436  AST_RWLIST_ENTRY(ast_hint) list;/*!< Pointer to next hint in list */
2437 };
2438 
2439 struct store_hint {
2440  char *context;
2441  char *exten;
2442  struct ast_state_cb *callbacks;
2443  int laststate;
2444  AST_LIST_ENTRY(store_hint) list;
2445  char data[1];
2446 };
2447 
2449 
2450 #define STATUS_NO_CONTEXT 1
2451 #define STATUS_NO_EXTENSION 2
2452 #define STATUS_NO_PRIORITY 3
2453 #define STATUS_NO_LABEL 4
2454 #define STATUS_SUCCESS 5
2455 
2456 static struct ast_var_t *ast_var_assign(const char *name, const char *value)
2457 {
2458  struct ast_var_t *var;
2459  int name_len = strlen(name) + 1;
2460  int value_len = strlen(value) + 1;
2461 
2462  if (!(var = ast_calloc(sizeof(*var) + name_len + value_len, sizeof(char)))) {
2463  return NULL;
2464  }
2465 
2466  ast_copy_string(var->name, name, name_len);
2467  var->value = var->name + name_len;
2468  ast_copy_string(var->value, value, value_len);
2469 
2470  return var;
2471 }
2472 
2473 static void ast_var_delete(struct ast_var_t *var)
2474 {
2475  free(var);
2476 }
2477 
2478 
2479 /* chopped this one off at the knees! */
2480 static int ast_func_write(struct ast_channel *chan, const char *function, const char *value)
2481 {
2482 
2483  /* ast_log(LOG_ERROR, "Function %s not registered\n", function); we are not interested in the details here */
2484 
2485  return -1;
2486 }
2487 
2488 static unsigned int ast_app_separate_args(char *buf, char delim, char **array, int arraylen)
2489 {
2490  int argc;
2491  char *scan;
2492  int paren = 0, quote = 0;
2493 
2494  if (!buf || !array || !arraylen)
2495  return 0;
2496 
2497  memset(array, 0, arraylen * sizeof(*array));
2498 
2499  scan = buf;
2500 
2501  for (argc = 0; *scan && (argc < arraylen - 1); argc++) {
2502  array[argc] = scan;
2503  for (; *scan; scan++) {
2504  if (*scan == '(')
2505  paren++;
2506  else if (*scan == ')') {
2507  if (paren)
2508  paren--;
2509  } else if (*scan == '"' && delim != '"') {
2510  quote = quote ? 0 : 1;
2511  /* Remove quote character from argument */
2512  memmove(scan, scan + 1, strlen(scan));
2513  scan--;
2514  } else if (*scan == '\\') {
2515  /* Literal character, don't parse */
2516  memmove(scan, scan + 1, strlen(scan));
2517  } else if ((*scan == delim) && !paren && !quote) {
2518  *scan++ = '\0';
2519  break;
2520  }
2521  }
2522  }
2523 
2524  if (*scan)
2525  array[argc++] = scan;
2526 
2527  return argc;
2528 }
2529 
2530 static void pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
2531 {
2532  struct ast_var_t *newvariable;
2533  struct varshead *headp;
2534  const char *nametail = name;
2535 
2536  /* XXX may need locking on the channel ? */
2537  if (name[strlen(name)-1] == ')') {
2538  char *function = ast_strdupa(name);
2539 
2540  ast_func_write(chan, function, value);
2541  return;
2542  }
2543 
2544  headp = &globals;
2545 
2546  /* For comparison purposes, we have to strip leading underscores */
2547  if (*nametail == '_') {
2548  nametail++;
2549  if (*nametail == '_')
2550  nametail++;
2551  }
2552 
2553  AST_LIST_TRAVERSE (headp, newvariable, entries) {
2554  if (strcasecmp(ast_var_name(newvariable), nametail) == 0) {
2555  /* there is already such a variable, delete it */
2556  AST_LIST_REMOVE(headp, newvariable, entries);
2557  ast_var_delete(newvariable);
2558  break;
2559  }
2560  }
2561 
2562  if (value && (newvariable = ast_var_assign(name, value))) {
2563  if ((option_verbose > 1) && (headp == &globals))
2564  ast_verbose(VERBOSE_PREFIX_2 "Setting global variable '%s' to '%s'\n", name, value);
2565  AST_LIST_INSERT_HEAD(headp, newvariable, entries);
2566  }
2567 
2568 }
2569 
2570 static int pbx_builtin_setvar(struct ast_channel *chan, const void *data)
2571 {
2572  char *name, *value, *mydata;
2573  int argc;
2574  char *argv[24]; /* this will only support a maximum of 24 variables being set in a single operation */
2575  int global = 0;
2576  int x;
2577 
2578  if (ast_strlen_zero(data)) {
2579  ast_log(LOG_WARNING, "Set requires at least one variable name/value pair.\n");
2580  return 0;
2581  }
2582 
2583  mydata = ast_strdupa(data);
2584  argc = ast_app_separate_args(mydata, '|', argv, sizeof(argv) / sizeof(argv[0]));
2585 
2586  /* check for a trailing flags argument */
2587  if ((argc > 1) && !strchr(argv[argc-1], '=')) {
2588  argc--;
2589  if (strchr(argv[argc], 'g'))
2590  global = 1;
2591  }
2592 
2593  for (x = 0; x < argc; x++) {
2594  name = argv[x];
2595  if ((value = strchr(name, '='))) {
2596  *value++ = '\0';
2597  pbx_builtin_setvar_helper((global) ? NULL : chan, name, value);
2598  } else
2599  ast_log(LOG_WARNING, "Ignoring entry '%s' with no = (and not last 'options' entry)\n", name);
2600  }
2601 
2602  return(0);
2603 }
2604 
2605 int localized_pbx_builtin_setvar(struct ast_channel *chan, const void *data);
2606 
2607 int localized_pbx_builtin_setvar(struct ast_channel *chan, const void *data)
2608 {
2609  return pbx_builtin_setvar(chan, data);
2610 }
2611 
2612 
2613 /*! \brief Helper for get_range.
2614  * return the index of the matching entry, starting from 1.
2615  * If names is not supplied, try numeric values.
2616  */
2617 static int lookup_name(const char *s, char *const names[], int max)
2618 {
2619  int i;
2620 
2621  if (names && *s > '9') {
2622  for (i = 0; names[i]; i++) {
2623  if (!strcasecmp(s, names[i])) {
2624  return i;
2625  }
2626  }
2627  }
2628 
2629  /* Allow months and weekdays to be specified as numbers, as well */
2630  if (sscanf(s, "%2d", &i) == 1 && i >= 1 && i <= max) {
2631  /* What the array offset would have been: "1" would be at offset 0 */
2632  return i - 1;
2633  }
2634  return -1; /* error return */
2635 }
2636 
2637 /*! \brief helper function to return a range up to max (7, 12, 31 respectively).
2638  * names, if supplied, is an array of names that should be mapped to numbers.
2639  */
2640 static unsigned get_range(char *src, int max, char *const names[], const char *msg)
2641 {
2642  int start, end; /* start and ending position */
2643  unsigned int mask = 0;
2644  char *part;
2645 
2646  /* Check for whole range */
2647  if (ast_strlen_zero(src) || !strcmp(src, "*")) {
2648  return (1 << max) - 1;
2649  }
2650 
2651  while ((part = strsep(&src, "&"))) {
2652  /* Get start and ending position */
2653  char *endpart = strchr(part, '-');
2654  if (endpart) {
2655  *endpart++ = '\0';
2656  }
2657  /* Find the start */
2658  if ((start = lookup_name(part, names, max)) < 0) {
2659  ast_log(LOG_WARNING, "Invalid %s '%s', skipping element\n", msg, part);
2660  continue;
2661  }
2662  if (endpart) { /* find end of range */
2663  if ((end = lookup_name(endpart, names, max)) < 0) {
2664  ast_log(LOG_WARNING, "Invalid end %s '%s', skipping element\n", msg, endpart);
2665  continue;
2666  }
2667  } else {
2668  end = start;
2669  }
2670  /* Fill the mask. Remember that ranges are cyclic */
2671  mask |= (1 << end); /* initialize with last element */
2672  while (start != end) {
2673  if (start >= max) {
2674  start = 0;
2675  }
2676  mask |= (1 << start);
2677  start++;
2678  }
2679  }
2680  return mask;
2681 }
2682 
2683 /*! \brief store a bitmask of valid times, one bit each 2 minute */
2684 static void get_timerange(struct ast_timing *i, char *times)
2685 {
2686  char *endpart, *part;
2687  int x;
2688  int st_h, st_m;
2689  int endh, endm;
2690  int minute_start, minute_end;
2691 
2692  /* start disabling all times, fill the fields with 0's, as they may contain garbage */
2693  memset(i->minmask, 0, sizeof(i->minmask));
2694 
2695  /* 1-minute per bit */
2696  /* Star is all times */
2697  if (ast_strlen_zero(times) || !strcmp(times, "*")) {
2698  /* 48, because each hour takes 2 integers; 30 bits each */
2699  for (x = 0; x < 48; x++) {
2700  i->minmask[x] = 0x3fffffff; /* 30 bits */
2701  }
2702  return;
2703  }
2704  /* Otherwise expect a range */
2705  while ((part = strsep(&times, "&"))) {
2706  if (!(endpart = strchr(part, '-'))) {
2707  if (sscanf(part, "%2d:%2d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) {
2708  ast_log(LOG_WARNING, "%s isn't a valid time.\n", part);
2709  continue;
2710  }
2711  i->minmask[st_h * 2 + (st_m >= 30 ? 1 : 0)] |= (1 << (st_m % 30));
2712  continue;
2713  }
2714  *endpart++ = '\0';
2715  /* why skip non digits? Mostly to skip spaces */
2716  while (*endpart && !isdigit(*endpart)) {
2717  endpart++;
2718  }
2719  if (!*endpart) {
2720  ast_log(LOG_WARNING, "Invalid time range starting with '%s-'.\n", part);
2721  continue;
2722  }
2723  if (sscanf(part, "%2d:%2d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) {
2724  ast_log(LOG_WARNING, "'%s' isn't a valid start time.\n", part);
2725  continue;
2726  }
2727  if (sscanf(endpart, "%2d:%2d", &endh, &endm) != 2 || endh < 0 || endh > 23 || endm < 0 || endm > 59) {
2728  ast_log(LOG_WARNING, "'%s' isn't a valid end time.\n", endpart);
2729  continue;
2730  }
2731  minute_start = st_h * 60 + st_m;
2732  minute_end = endh * 60 + endm;
2733  /* Go through the time and enable each appropriate bit */
2734  for (x = minute_start; x != minute_end; x = (x + 1) % (24 * 60)) {
2735  i->minmask[x / 30] |= (1 << (x % 30));
2736  }
2737  /* Do the last one */
2738  i->minmask[x / 30] |= (1 << (x % 30));
2739  }
2740  /* All done */
2741  return;
2742 }
2743 
2744 static void null_datad(void *foo)
2745 {
2746 }
2747 
2748 /*! \brief Find realtime engine for realtime family */
2749 static struct ast_config_engine *find_engine(const char *family, char *database, int dbsiz, char *table, int tabsiz)
2750 {
2751  struct ast_config_engine *eng, *ret = NULL;
2752  struct ast_config_map *map;
2753 
2754 
2755  for (map = config_maps; map; map = map->next) {
2756  if (!strcasecmp(family, map->name)) {
2757  if (database)
2758  ast_copy_string(database, map->database, dbsiz);
2759  if (table)
2760  ast_copy_string(table, map->table ? map->table : family, tabsiz);
2761  break;
2762  }
2763  }
2764 
2765  /* Check if the required driver (engine) exist */
2766  if (map) {
2767  for (eng = config_engine_list; !ret && eng; eng = eng->next) {
2768  if (!strcasecmp(eng->name, map->driver))
2769  ret = eng;
2770  }
2771  }
2772 
2773 
2774  /* if we found a mapping, but the engine is not available, then issue a warning */
2775  if (map && !ret)
2776  ast_log(LOG_WARNING, "Realtime mapping for '%s' found to engine '%s', but the engine is not available\n", map->name, map->driver);
2777 
2778  return ret;
2779 }
2780 
2781 struct ast_category *ast_config_get_current_category(const struct ast_config *cfg);
2782 
2784 {
2785  return cfg->current;
2786 }
2787 
2788 static struct ast_category *ast_category_new(const char *name, const char *in_file, int lineno);
2789 
2790 static struct ast_category *ast_category_new(const char *name, const char *in_file, int lineno)
2791 {
2792  struct ast_category *category;
2793 
2794  if ((category = ast_calloc(1, sizeof(*category))))
2795  ast_copy_string(category->name, name, sizeof(category->name));
2796  category->file = strdup(in_file);
2797  category->lineno = lineno; /* if you don't know the lineno, set it to 999999 or something real big */
2798  return category;
2799 }
2800 
2801 struct ast_category *localized_category_get(const struct ast_config *config, const char *category_name);
2802 
2803 struct ast_category *localized_category_get(const struct ast_config *config, const char *category_name)
2804 {
2805  return category_get(config, category_name, 0);
2806 }
2807 
2808 static void move_variables(struct ast_category *old, struct ast_category *new)
2809 {
2810  struct ast_variable *var = old->root;
2811  old->root = NULL;
2812 #if 1
2813  /* we can just move the entire list in a single op */
2814  ast_variable_append(new, var);
2815 #else
2816  while (var) {
2817  struct ast_variable *next = var->next;
2818  var->next = NULL;
2819  ast_variable_append(new, var);
2820  var = next;
2821  }
2822 #endif
2823 }
2824 
2825 static void inherit_category(struct ast_category *new, const struct ast_category *base)
2826 {
2827  struct ast_variable *var;
2828 
2829  for (var = base->root; var; var = var->next)
2831 }
2832 
2833 static void ast_category_append(struct ast_config *config, struct ast_category *category);
2834 
2835 static void ast_category_append(struct ast_config *config, struct ast_category *category)
2836 {
2837  if (config->last)
2838  config->last->next = category;
2839  else
2840  config->root = category;
2841  config->last = category;
2842  config->current = category;
2843 }
2844 
2845 static void ast_category_destroy(struct ast_category *cat);
2846 
2847 static void ast_category_destroy(struct ast_category *cat)
2848 {
2850  if (cat->file)
2851  free(cat->file);
2852 
2853  free(cat);
2854 }
2855 
2857  .name = "text",
2858  .load_func = config_text_file_load,
2859 };
2860 
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 static struct ast_config *ast_config_internal_load(const char *filename, struct ast_config *cfg, int withcomments, const char *suggested_incl_file)
2865 {
2866  char db[256];
2867  char table[256];
2868  struct ast_config_engine *loader = &text_file_engine;
2869  struct ast_config *result;
2870 
2871  if (cfg->include_level == cfg->max_include_level) {
2872  ast_log(LOG_WARNING, "Maximum Include level (%d) exceeded\n", cfg->max_include_level);
2873  return NULL;
2874  }
2875 
2876  cfg->include_level++;
2877  /* silence is golden!
2878  ast_log(LOG_WARNING, "internal loading file %s level=%d\n", filename, cfg->include_level);
2879  */
2880 
2881  if (strcmp(filename, extconfig_conf) && strcmp(filename, "asterisk.conf") && config_engine_list) {
2882  struct ast_config_engine *eng;
2883 
2884  eng = find_engine(filename, db, sizeof(db), table, sizeof(table));
2885 
2886 
2887  if (eng && eng->load_func) {
2888  loader = eng;
2889  } else {
2890  eng = find_engine("global", db, sizeof(db), table, sizeof(table));
2891  if (eng && eng->load_func)
2892  loader = eng;
2893  }
2894  }
2895 
2896  result = loader->load_func(db, table, filename, cfg, withcomments, suggested_incl_file);
2897  /* silence is golden
2898  ast_log(LOG_WARNING, "finished internal loading file %s level=%d\n", filename, cfg->include_level);
2899  */
2900 
2901  if (result)
2902  result->include_level--;
2903 
2904  return result;
2905 }
2906 
2907 
2908 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)
2909 {
2910  char *c;
2911  char *cur = buf;
2912  struct ast_variable *v;
2913  char exec_file[512];
2914  int object, do_exec, do_include;
2915 
2916  /* Actually parse the entry */
2917  if (cur[0] == '[') {
2918  struct ast_category *newcat = NULL;
2919  char *catname;
2920 
2921  /* A category header */
2922  c = strchr(cur, ']');
2923  if (!c) {
2924  ast_log(LOG_WARNING, "parse error: no closing ']', line %d of %s\n", lineno, configfile);
2925  return -1;
2926  }
2927  *c++ = '\0';
2928  cur++;
2929  if (*c++ != '(')
2930  c = NULL;
2931  catname = cur;
2932  if (!(*cat = newcat = ast_category_new(catname, ast_strlen_zero(suggested_include_file)?configfile:suggested_include_file, lineno))) {
2933  return -1;
2934  }
2935  (*cat)->lineno = lineno;
2936 
2937  /* add comments */
2938  if (withcomments && comment_buffer && comment_buffer[0] ) {
2939  newcat->precomments = ALLOC_COMMENT(comment_buffer);
2940  }
2941  if (withcomments && lline_buffer && lline_buffer[0] ) {
2942  newcat->sameline = ALLOC_COMMENT(lline_buffer);
2943  }
2944  if( withcomments )
2945  CB_RESET();
2946 
2947  /* If there are options or categories to inherit from, process them now */
2948  if (c) {
2949  if (!(cur = strchr(c, ')'))) {
2950  ast_log(LOG_WARNING, "parse error: no closing ')', line %d of %s\n", lineno, configfile);
2951  return -1;
2952  }
2953  *cur = '\0';
2954  while ((cur = strsep(&c, ","))) {
2955  if (!strcasecmp(cur, "!")) {
2956  (*cat)->ignored = 1;
2957  } else if (!strcasecmp(cur, "+")) {
2958  *cat = category_get(cfg, catname, 1);
2959  if (!*cat) {
2960  ast_config_destroy(cfg);
2961  if (newcat)
2962  ast_category_destroy(newcat);
2963  ast_log(LOG_WARNING, "Category addition requested, but category '%s' does not exist, line %d of %s\n", catname, lineno, configfile);
2964  return -1;
2965  }
2966  if (newcat) {
2967  move_variables(newcat, *cat);
2968  ast_category_destroy(newcat);
2969  newcat = NULL;
2970  }
2971  } else {
2972  struct ast_category *base;
2973 
2974  base = category_get(cfg, cur, 1);
2975  if (!base) {
2976  ast_log(LOG_WARNING, "Inheritance requested, but category '%s' does not exist, line %d of %s\n", cur, lineno, configfile);
2977  return -1;
2978  }
2979  inherit_category(*cat, base);
2980  }
2981  }
2982  }
2983  if (newcat)
2984  ast_category_append(cfg, *cat);
2985  } else if (cur[0] == '#') {
2986  /* A directive */
2987  cur++;
2988  c = cur;
2989  while(*c && (*c > 32)) c++;
2990  if (*c) {
2991  *c = '\0';
2992  /* Find real argument */
2993  c = ast_skip_blanks(c + 1);
2994  if (!*c)
2995  c = NULL;
2996  } else
2997  c = NULL;
2998  do_include = !strcasecmp(cur, "include");
2999  if(!do_include)
3000  do_exec = !strcasecmp(cur, "exec");
3001  else
3002  do_exec = 0;
3003  if (do_exec && !ast_opt_exec_includes) {
3004  ast_log(LOG_WARNING, "Cannot perform #exec unless execincludes option is enabled in asterisk.conf (options section)!\n");
3005  do_exec = 0;
3006  }
3007  if (do_include || do_exec) {
3008  if (c) {
3009  char *cur2;
3010  char real_inclusion_name[525];
3011 
3012  /* Strip off leading and trailing "'s and <>'s */
3013  while((*c == '<') || (*c == '>') || (*c == '\"')) c++;
3014  /* Get rid of leading mess */
3015  cur = c;
3016  cur2 = cur;
3017  while (!ast_strlen_zero(cur)) {
3018  c = cur + strlen(cur) - 1;
3019  if ((*c == '>') || (*c == '<') || (*c == '\"'))
3020  *c = '\0';
3021  else
3022  break;
3023  }
3024  /* #exec </path/to/executable>
3025  We create a tmp file, then we #include it, then we delete it. */
3026  if (do_exec) {
3027  char cmd[1024];
3028 
3029  snprintf(exec_file, sizeof(exec_file), "/var/tmp/exec.%d.%ld", (int)time(NULL), (long)pthread_self());
3030  if (snprintf(cmd, sizeof(cmd), "%s > %s 2>&1", cur, exec_file) >= sizeof(cmd)) {
3031  ast_log(LOG_ERROR, "Failed to construct command string to execute %s.\n", cur);
3032 
3033  return -1;
3034  }
3035  ast_safe_system(cmd);
3036  cur = exec_file;
3037  } else
3038  exec_file[0] = '\0';
3039  /* A #include */
3040  /* ast_log(LOG_WARNING, "Reading in included file %s withcomments=%d\n", cur, withcomments); */
3041 
3042  /* record this inclusion */
3043  ast_include_new(cfg, configfile, cur, do_exec, cur2, lineno, real_inclusion_name, sizeof(real_inclusion_name));
3044 
3045  do_include = ast_config_internal_load(cur, cfg, withcomments, real_inclusion_name) ? 1 : 0;
3046  if(!ast_strlen_zero(exec_file))
3047  unlink(exec_file);
3048  if(!do_include)
3049  return 0;
3050  /* ast_log(LOG_WARNING, "Done reading in included file %s withcomments=%d\n", cur, withcomments); */
3051 
3052  } else {
3053  ast_log(LOG_WARNING, "Directive '#%s' needs an argument (%s) at line %d of %s\n",
3054  do_exec ? "exec" : "include",
3055  do_exec ? "/path/to/executable" : "filename",
3056  lineno,
3057  configfile);
3058  }
3059  }
3060  else
3061  ast_log(LOG_WARNING, "Unknown directive '%s' at line %d of %s\n", cur, lineno, configfile);
3062  } else {
3063  /* Just a line (variable = value) */
3064  if (!*cat) {
3066  "parse error: No category context for line %d of %s\n", lineno, configfile);
3067  return -1;
3068  }
3069  c = strchr(cur, '=');
3070  if (c) {
3071  *c = 0;
3072  c++;
3073  /* Ignore > in => */
3074  if (*c== '>') {
3075  object = 1;
3076  c++;
3077  } else
3078  object = 0;
3079  if ((v = ast_variable_new(ast_strip(cur), ast_strip(c), configfile))) {
3080  v->lineno = lineno;
3081  v->object = object;
3082  /* Put and reset comments */
3083  v->blanklines = 0;
3084  ast_variable_append(*cat, v);
3085  /* add comments */
3086  if (withcomments && comment_buffer && comment_buffer[0] ) {
3087  v->precomments = ALLOC_COMMENT(comment_buffer);
3088  }
3089  if (withcomments && lline_buffer && lline_buffer[0] ) {
3090  v->sameline = ALLOC_COMMENT(lline_buffer);
3091  }
3092  if( withcomments )
3093  CB_RESET();
3094 
3095  } else {
3096  return -1;
3097  }
3098  } else {
3099  ast_log(LOG_WARNING, "EXTENSIONS.CONF: No '=' (equal sign) in line %d of %s\n", lineno, configfile);
3100  }
3101  }
3102  return 0;
3103 }
3104 
3105 static int use_local_dir = 1;
3106 
3107 void localized_use_local_dir(void);
3108 void localized_use_conf_dir(void);
3109 
3111 {
3112  use_local_dir = 1;
3113 }
3114 
3116 {
3117  use_local_dir = 0;
3118 }
3119 
3120 
3121 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)
3122 {
3123  char fn[256];
3124  char buf[8192];
3125  char *new_buf, *comment_p, *process_buf;
3126  FILE *f;
3127  int lineno=0;
3128  int comment = 0, nest[MAX_NESTED_COMMENTS];
3129  struct ast_category *cat = NULL;
3130  int count = 0;
3131  struct stat statbuf;
3132 
3134 
3135  if (filename[0] == '/') {
3136  ast_copy_string(fn, filename, sizeof(fn));
3137  } else {
3138  if (use_local_dir)
3139  snprintf(fn, sizeof(fn), "./%s", filename);
3140  else
3141  snprintf(fn, sizeof(fn), "%s/%s", ast_config_AST_CONFIG_DIR, filename);
3142  }
3143 
3144  if (withcomments && cfg && cfg->include_level < 2 ) {
3145  CB_INIT();
3146  }
3147 
3148  do {
3149  if (stat(fn, &statbuf))
3150  continue;
3151 
3152  if (!S_ISREG(statbuf.st_mode)) {
3153  ast_log(LOG_WARNING, "'%s' is not a regular file, ignoring\n", fn);
3154  continue;
3155  }
3156  if (option_verbose > 1) {
3157  ast_verbose(VERBOSE_PREFIX_2 "Parsing '%s': ", fn);
3158  fflush(stdout);
3159  }
3160  if (!(f = fopen(fn, "r"))) {
3161  if (option_debug)
3162  ast_log(LOG_DEBUG, "No file to parse: %s\n", fn);
3163  if (option_verbose > 1)
3164  ast_verbose( "Not found (%s)\n", strerror(errno));
3165  continue;
3166  }
3167  count++;
3168  if (option_debug)
3169  ast_log(LOG_DEBUG, "Parsing %s\n", fn);
3170  if (option_verbose > 1)
3171  ast_verbose("Found\n");
3172  while(!feof(f)) {
3173  lineno++;
3174  if (fgets(buf, sizeof(buf), f)) {
3175  if ( withcomments ) {
3176  CB_ADD(lline_buffer); /* add the current lline buffer to the comment buffer */
3177  lline_buffer[0] = 0; /* erase the lline buffer */
3178  }
3179 
3180  new_buf = buf;
3181  if (comment)
3182  process_buf = NULL;
3183  else
3184  process_buf = buf;
3185 
3186  while ((comment_p = strchr(new_buf, COMMENT_META))) {
3187  if ((comment_p > new_buf) && (*(comment_p-1) == '\\')) {
3188  /* Yuck, gotta memmove */
3189  memmove(comment_p - 1, comment_p, strlen(comment_p) + 1);
3190  new_buf = comment_p;
3191  } else if(comment_p[1] == COMMENT_TAG && comment_p[2] == COMMENT_TAG && (comment_p[3] != '-')) {
3192  /* Meta-Comment start detected ";--" */
3193  if (comment < MAX_NESTED_COMMENTS) {
3194  *comment_p = '\0';
3195  new_buf = comment_p + 3;
3196  comment++;
3197  nest[comment-1] = lineno;
3198  } else {
3199  ast_log(LOG_ERROR, "Maximum nest limit of %d reached.\n", MAX_NESTED_COMMENTS);
3200  }
3201  } else if ((comment_p >= new_buf + 2) &&
3202  (*(comment_p - 1) == COMMENT_TAG) &&
3203  (*(comment_p - 2) == COMMENT_TAG)) {
3204  /* Meta-Comment end detected */
3205  comment--;
3206  new_buf = comment_p + 1;
3207  if (!comment) {
3208  /* Back to non-comment now */
3209  if (process_buf) {
3210  /* Actually have to move what's left over the top, then continue */
3211  char *oldptr;
3212  oldptr = process_buf + strlen(process_buf);
3213  if ( withcomments ) {
3214  CB_ADD(";");
3215  CB_ADD_LEN(oldptr+1,new_buf-oldptr-1);
3216  }
3217 
3218  memmove(oldptr, new_buf, strlen(new_buf) + 1);
3219  new_buf = oldptr;
3220  } else
3221  process_buf = new_buf;
3222  }
3223  } else {
3224  if (!comment) {
3225  /* If ; is found, and we are not nested in a comment,
3226  we immediately stop all comment processing */
3227  if ( withcomments ) {
3228  LLB_ADD(comment_p);
3229  }
3230  *comment_p = '\0';
3231  new_buf = comment_p;
3232  } else
3233  new_buf = comment_p + 1;
3234  }
3235  }
3236  if( withcomments && comment && !process_buf )
3237  {
3238  CB_ADD(buf); /* the whole line is a comment, store it */
3239  }
3240 
3241  if (process_buf) {
3242  char *stripped_process_buf = ast_strip(process_buf);
3243  if (!ast_strlen_zero(stripped_process_buf)) {
3244  if (process_text_line(cfg, &cat, stripped_process_buf, lineno, filename, withcomments, suggested_include_file)) {
3245  cfg = NULL;
3246  break;
3247  }
3248  }
3249  }
3250  }
3251  }
3252  fclose(f);
3253  } while(0);
3254  if (comment) {
3255  ast_log(LOG_WARNING,"Unterminated comment detected beginning on line %d\n", nest[comment]);
3256  }
3257  if (cfg && cfg->include_level == 1 && withcomments && comment_buffer) {
3258  if (comment_buffer) {
3259  free(comment_buffer);
3260  free(lline_buffer);
3261  comment_buffer=0;
3262  lline_buffer=0;
3263  comment_buffer_size=0;
3264  lline_buffer_size=0;
3265  }
3266  }
3267  if (count == 0)
3268  return NULL;
3269 
3270  return cfg;
3271 }
3272 
3273 
3274 static struct ast_config *ast_config_new(void) ;
3275 
3276 static struct ast_config *ast_config_new(void)
3277 {
3278  struct ast_config *config;
3279 
3280  if ((config = ast_calloc(1, sizeof(*config))))
3282  return config;
3283 }
3284 
3285 struct ast_config *localized_config_load(const char *filename);
3286 
3287 struct ast_config *localized_config_load(const char *filename)
3288 {
3289  struct ast_config *cfg;
3290  struct ast_config *result;
3291 
3292  cfg = ast_config_new();
3293  if (!cfg)
3294  return NULL;
3295 
3296  result = ast_config_internal_load(filename, cfg, 0, "");
3297  if (!result)
3298  ast_config_destroy(cfg);
3299 
3300  return result;
3301 }
3302 
3303 struct ast_config *localized_config_load_with_comments(const char *filename);
3304 
3306 {
3307  struct ast_config *cfg;
3308  struct ast_config *result;
3309 
3310  cfg = ast_config_new();
3311  if (!cfg)
3312  return NULL;
3313 
3314  result = ast_config_internal_load(filename, cfg, 1, "");
3315  if (!result)
3316  ast_config_destroy(cfg);
3317 
3318  return result;
3319 }
3320 
3322 {
3323  for (; cat && cat->ignored; cat = cat->next);
3324 
3325  return cat;
3326 }
3327 
3328 static char *ast_category_browse(struct ast_config *config, const char *prev)
3329 {
3330  struct ast_category *cat = NULL;
3331 
3332  if (prev && config->last_browse && (config->last_browse->name == prev))
3333  cat = config->last_browse->next;
3334  else if (!prev && config->root)
3335  cat = config->root;
3336  else if (prev) {
3337  for (cat = config->root; cat; cat = cat->next) {
3338  if (cat->name == prev) {
3339  cat = cat->next;
3340  break;
3341  }
3342  }
3343  if (!cat) {
3344  for (cat = config->root; cat; cat = cat->next) {
3345  if (!strcasecmp(cat->name, prev)) {
3346  cat = cat->next;
3347  break;
3348  }
3349  }
3350  }
3351  }
3352 
3353  if (cat)
3354  cat = next_available_category(cat);
3355 
3356  config->last_browse = cat;
3357  return (cat) ? cat->name : NULL;
3358 }
3359 
3360 
3361 
3362 void ast_config_set_current_category(struct ast_config *cfg, const struct ast_category *cat);
3363 
3364 void ast_config_set_current_category(struct ast_config *cfg, const struct ast_category *cat)
3365 {
3366  /* cast below is just to silence compiler warning about dropping "const" */
3367  cfg->current = (struct ast_category *) cat;
3368 }
3369 
3370 /* NOTE: categories and variables each have a file and lineno attribute. On a save operation, these are used to determine
3371  which file and line number to write out to. Thus, an entire hierarchy of config files (via #include statements) can be
3372  recreated. BUT, care must be taken to make sure that every cat and var has the proper file name stored, or you may
3373  be shocked and mystified as to why things are not showing up in the files!
3374 
3375  Also, All #include/#exec statements are recorded in the "includes" LL in the ast_config structure. The file name
3376  and line number are stored for each include, plus the name of the file included, so that these statements may be
3377  included in the output files on a file_save operation.
3378 
3379  The lineno's are really just for relative placement in the file. There is no attempt to make sure that blank lines
3380  are included to keep the lineno's the same between input and output. The lineno fields are used mainly to determine
3381  the position of the #include and #exec directives. So, blank lines tend to disappear from a read/rewrite operation,
3382  and a header gets added.
3383 
3384  vars and category heads are output in the order they are stored in the config file. So, if the software
3385  shuffles these at all, then the placement of #include directives might get a little mixed up, because the
3386  file/lineno data probably won't get changed.
3387 
3388 */
3389 
3390 static void gen_header(FILE *f1, const char *configfile, const char *fn, const char *generator)
3391 {
3392  char date[256]="";
3393  time_t t;
3394  time(&t);
3395  ast_copy_string(date, ctime(&t), sizeof(date));
3396 
3397  fprintf(f1, ";!\n");
3398  fprintf(f1, ";! Automatically generated configuration file\n");
3399  if (strcmp(configfile, fn))
3400  fprintf(f1, ";! Filename: %s (%s)\n", configfile, fn);
3401  else
3402  fprintf(f1, ";! Filename: %s\n", configfile);
3403  fprintf(f1, ";! Generator: %s\n", generator);
3404  fprintf(f1, ";! Creation Date: %s", date);
3405  fprintf(f1, ";!\n");
3406 }
3407 
3408 static void set_fn(char *fn, int fn_size, const char *file, const char *configfile)
3409 {
3410  if (!file || file[0] == 0) {
3411  if (configfile[0] == '/')
3412  ast_copy_string(fn, configfile, fn_size);
3413  else
3414  snprintf(fn, fn_size, "%s/%s", ast_config_AST_CONFIG_DIR, configfile);
3415  } else if (file[0] == '/')
3416  ast_copy_string(fn, file, fn_size);
3417  else
3418  snprintf(fn, fn_size, "%s/%s", ast_config_AST_CONFIG_DIR, file);
3419 }
3420 
3421 int localized_config_text_file_save(const char *configfile, const struct ast_config *cfg, const char *generator);
3422 
3423 int localized_config_text_file_save(const char *configfile, const struct ast_config *cfg, const char *generator)
3424 {
3425  FILE *f;
3426  char fn[256];
3427  struct ast_variable *var;
3428  struct ast_category *cat;
3429  struct ast_comment *cmt;
3430  struct ast_config_include *incl;
3431  int blanklines = 0;
3432 
3433  /* reset all the output flags, in case this isn't our first time saving this data */
3434 
3435  for (incl=cfg->includes; incl; incl = incl->next)
3436  incl->output = 0;
3437 
3438  /* go thru all the inclusions and make sure all the files involved (configfile plus all its inclusions)
3439  are all truncated to zero bytes and have that nice header*/
3440 
3441  for (incl=cfg->includes; incl; incl = incl->next)
3442  {
3443  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*/
3444  FILE *f1;
3445 
3446  set_fn(fn, sizeof(fn), incl->included_file, configfile); /* normally, fn is just set to incl->included_file, prepended with config dir if relative */
3447  f1 = fopen(fn,"w");
3448  if (f1) {
3449  gen_header(f1, configfile, fn, generator);
3450  fclose(f1); /* this should zero out the file */
3451  } else {
3452  ast_verbose(VERBOSE_PREFIX_2 "Unable to write %s (%s)", fn, strerror(errno));
3453  }
3454  }
3455  }
3456 
3457  set_fn(fn, sizeof(fn), 0, configfile); /* just set fn to absolute ver of configfile */
3458 #ifdef __CYGWIN__
3459  if ((f = fopen(fn, "w+"))) {
3460 #else
3461  if ((f = fopen(fn, "w"))) {
3462 #endif
3463  if (option_verbose > 1)
3464  ast_verbose(VERBOSE_PREFIX_2 "Saving '%s': ", fn);
3465 
3466  gen_header(f, configfile, fn, generator);
3467  cat = cfg->root;
3468  fclose(f);
3469 
3470  /* from here out, we open each involved file and concat the stuff we need to add to the end and immediately close... */
3471  /* since each var, cat, and associated comments can come from any file, we have to be
3472  mobile, and open each file, print, and close it on an entry-by-entry basis */
3473 
3474  while(cat) {
3475  set_fn(fn, sizeof(fn), cat->file, configfile);
3476  f = fopen(fn, "a");
3477  if (!f)
3478  {
3479  ast_verbose(VERBOSE_PREFIX_2 "Unable to write %s (%s)", fn, strerror(errno));
3480  return -1;
3481  }
3482 
3483  /* dump any includes that happen before this category header */
3484  for (incl=cfg->includes; incl; incl = incl->next) {
3485  if (strcmp(incl->include_location_file, cat->file) == 0){
3486  if (cat->lineno > incl->include_location_lineno && !incl->output) {
3487  if (incl->exec)
3488  fprintf(f,"#exec \"%s\"\n", incl->exec_file);
3489  else
3490  fprintf(f,"#include \"%s\"\n", incl->included_file);
3491  incl->output = 1;
3492  }
3493  }
3494  }
3495 
3496  /* Dump section with any appropriate comment */
3497  for (cmt = cat->precomments; cmt; cmt=cmt->next) {
3498  if (cmt->cmt[0] != ';' || cmt->cmt[1] != '!')
3499  fprintf(f,"%s", cmt->cmt);
3500  }
3501  if (!cat->precomments)
3502  fprintf(f,"\n");
3503  fprintf(f, "[%s]", cat->name);
3504  for(cmt = cat->sameline; cmt; cmt=cmt->next) {
3505  fprintf(f,"%s", cmt->cmt);
3506  }
3507  if (!cat->sameline)
3508  fprintf(f,"\n");
3509  fclose(f);
3510 
3511  var = cat->root;
3512  while(var) {
3513  set_fn(fn, sizeof(fn), var->file, configfile);
3514  f = fopen(fn, "a");
3515  if (!f)
3516  {
3517  ast_verbose(VERBOSE_PREFIX_2 "Unable to write %s (%s)", fn, strerror(errno));
3518  return -1;
3519  }
3520 
3521  /* dump any includes that happen before this category header */
3522  for (incl=cfg->includes; incl; incl = incl->next) {
3523  if (strcmp(incl->include_location_file, var->file) == 0){
3524  if (var->lineno > incl->include_location_lineno && !incl->output) {
3525  if (incl->exec)
3526  fprintf(f,"#exec \"%s\"\n", incl->exec_file);
3527  else
3528  fprintf(f,"#include \"%s\"\n", incl->included_file);
3529  incl->output = 1;
3530  }
3531  }
3532  }
3533 
3534  for (cmt = var->precomments; cmt; cmt=cmt->next) {
3535  if (cmt->cmt[0] != ';' || cmt->cmt[1] != '!')
3536  fprintf(f,"%s", cmt->cmt);
3537  }
3538  if (var->sameline)
3539  fprintf(f, "%s %s %s %s", var->name, (var->object ? "=>" : "="), var->value, var->sameline->cmt);
3540  else
3541  fprintf(f, "%s %s %s\n", var->name, (var->object ? "=>" : "="), var->value);
3542  if (var->blanklines) {
3543  blanklines = var->blanklines;
3544  while (blanklines--)
3545  fprintf(f, "\n");
3546  }
3547 
3548  fclose(f);
3549 
3550 
3551  var = var->next;
3552  }
3553  cat = cat->next;
3554  }
3555  if ((option_verbose > 1) && !option_debug)
3556  ast_verbose("Saved\n");
3557  } else {
3558  if (option_debug)
3559  ast_log(LOG_DEBUG, "Unable to open for writing: %s\n", fn);
3560  if (option_verbose > 1)
3561  ast_verbose(VERBOSE_PREFIX_2 "Unable to write (%s)", strerror(errno));
3562  return -1;
3563  }
3564 
3565  /* Now, for files with trailing #include/#exec statements,
3566  we have to make sure every entry is output */
3567 
3568  for (incl=cfg->includes; incl; incl = incl->next) {
3569  if (!incl->output) {
3570  /* open the respective file */
3571  set_fn(fn, sizeof(fn), incl->include_location_file, configfile);
3572  f = fopen(fn, "a");
3573  if (!f)
3574  {
3575  ast_verbose(VERBOSE_PREFIX_2 "Unable to write %s (%s)", fn, strerror(errno));
3576  return -1;
3577  }
3578 
3579  /* output the respective include */
3580  if (incl->exec)
3581  fprintf(f,"#exec \"%s\"\n", incl->exec_file);
3582  else
3583  fprintf(f,"#include \"%s\"\n", incl->included_file);
3584  fclose(f);
3585  incl->output = 1;
3586  }
3587  }
3588 
3589  return 0;
3590 }
3591 
3592 /* ================ the Line ========================================
3593  above this line, you have what you need to load a config file,
3594  and below it, you have what you need to process the extensions.conf
3595  file into the context/exten/prio stuff. They are both in one file
3596  to make things simpler */
3597 
3599 static struct ast_context *contexts = NULL;
3600 struct ast_context;
3601 struct ast_app;
3602 #ifdef LOW_MEMORY
3603 #define EXT_DATA_SIZE 256
3604 #else
3605 #define EXT_DATA_SIZE 8192
3606 #endif
3607 
3608 #ifdef NOT_ANYMORE
3610 #endif
3611 
3612 #define SWITCH_DATA_LENGTH 256
3613 
3614 static const char *ast_get_extension_app(struct ast_exten *e)
3615 {
3616  return e ? e->app : NULL;
3617 }
3618 
3619 static const char *ast_get_extension_name(struct ast_exten *exten)
3620 {
3621  return exten ? exten->exten : NULL;
3622 }
3623 
3625 
3626 /*! \brief ast_change_hint: Change hint for an extension */
3627 static int ast_change_hint(struct ast_exten *oe, struct ast_exten *ne)
3628 {
3629  struct ast_hint *hint;
3630  int res = -1;
3631 
3632  AST_RWLIST_TRAVERSE(&hints, hint, list) {
3633  if (hint->exten == oe) {
3634  hint->exten = ne;
3635  res = 0;
3636  break;
3637  }
3638  }
3639 
3640  return res;
3641 }
3642 
3643 /*! \brief ast_add_hint: Add hint to hint list, check initial extension state */
3644 static int ast_add_hint(struct ast_exten *e)
3645 {
3646  struct ast_hint *hint;
3647 
3648  if (!e)
3649  return -1;
3650 
3651 
3652  /* Search if hint exists, do nothing */
3653  AST_RWLIST_TRAVERSE(&hints, hint, list) {
3654  if (hint->exten == e) {
3655  if (option_debug > 1)
3656  ast_log(LOG_DEBUG, "HINTS: Not re-adding existing hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e));
3657  return -1;
3658  }
3659  }
3660 
3661  if (option_debug > 1)
3662  ast_log(LOG_DEBUG, "HINTS: Adding hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e));
3663 
3664  if (!(hint = ast_calloc(1, sizeof(*hint)))) {
3665  return -1;
3666  }
3667  /* Initialize and insert new item at the top */
3668  hint->exten = e;
3669  AST_RWLIST_INSERT_HEAD(&hints, hint, list);
3670 
3671  return 0;
3672 }
3673 
3674 /*! \brief add the extension in the priority chain.
3675  * returns 0 on success, -1 on failure
3676  */
3677 static int add_pri(struct ast_context *con, struct ast_exten *tmp,
3678  struct ast_exten *el, struct ast_exten *e, int replace)
3679 {
3680  struct ast_exten *ep;
3681 
3682  for (ep = NULL; e ; ep = e, e = e->peer) {
3683  if (e->priority >= tmp->priority)
3684  break;
3685  }
3686  if (!e) { /* go at the end, and ep is surely set because the list is not empty */
3687  ep->peer = tmp;
3688  return 0; /* success */
3689  }
3690  if (e->priority == tmp->priority) {
3691  /* Can't have something exactly the same. Is this a
3692  replacement? If so, replace, otherwise, bonk. */
3693  if (!replace) {
3694  ast_log(LOG_WARNING, "Unable to register extension '%s', priority %d in '%s', already in use\n", tmp->exten, tmp->priority, con->name);
3695  tmp->datad(tmp->data);
3696  free(tmp);
3697  return -1;
3698  }
3699  /* we are replacing e, so copy the link fields and then update
3700  * whoever pointed to e to point to us
3701  */
3702  tmp->next = e->next; /* not meaningful if we are not first in the peer list */
3703  tmp->peer = e->peer; /* always meaningful */
3704  if (ep) /* We're in the peer list, just insert ourselves */
3705  ep->peer = tmp;
3706  else if (el) /* We're the first extension. Take over e's functions */
3707  el->next = tmp;
3708  else /* We're the very first extension. */
3709  con->root = tmp;
3710  if (tmp->priority == PRIORITY_HINT)
3711  ast_change_hint(e,tmp);
3712  /* Destroy the old one */
3713  e->datad(e->data);
3714  free(e);
3715  } else { /* Slip ourselves in just before e */
3716  tmp->peer = e;
3717  tmp->next = e->next; /* extension chain, or NULL if e is not the first extension */
3718  if (ep) /* Easy enough, we're just in the peer list */
3719  ep->peer = tmp;
3720  else { /* we are the first in some peer list, so link in the ext list */
3721  if (el)
3722  el->next = tmp; /* in the middle... */
3723  else
3724  con->root = tmp; /* ... or at the head */
3725  e->next = NULL; /* e is no more at the head, so e->next must be reset */
3726  }
3727  /* And immediately return success. */
3728  if (tmp->priority == PRIORITY_HINT)
3729  ast_add_hint(tmp);
3730  }
3731  return 0;
3732 }
3733 
3734 /*! \brief ast_remove_hint: Remove hint from extension */
3735 static int ast_remove_hint(struct ast_exten *e)
3736 {
3737  /* Cleanup the Notifys if hint is removed */
3738  struct ast_hint *hint;
3739  struct ast_state_cb *cblist, *cbprev;
3740  int res = -1;
3741 
3742  if (!e)
3743  return -1;
3744 
3745  AST_RWLIST_TRAVERSE_SAFE_BEGIN(&hints, hint, list) {
3746  if (hint->exten == e) {
3747  cbprev = NULL;
3748  cblist = hint->callbacks;
3749  while (cblist) {
3750  /* Notify with -1 and remove all callbacks */
3751  cbprev = cblist;
3752  cblist = cblist->next;
3753  free(cbprev);
3754  }
3755  hint->callbacks = NULL;
3757  free(hint);
3758  res = 0;
3759  break;
3760  }
3761  }
3763 
3764  return res;
3765 }
3766 
3767 static void destroy_exten(struct ast_exten *e)
3768 {
3769  if (e->priority == PRIORITY_HINT)
3770  ast_remove_hint(e);
3771 
3772  if (e->datad)
3773  e->datad(e->data);
3774  free(e);
3775 }
3776 
3777 char *days[] =
3778 {
3779  "sun",
3780  "mon",
3781  "tue",
3782  "wed",
3783  "thu",
3784  "fri",
3785  "sat",
3786  NULL,
3787 };
3788 
3789 char *months[] =
3790 {
3791  "jan",
3792  "feb",
3793  "mar",
3794  "apr",
3795  "may",
3796  "jun",
3797  "jul",
3798  "aug",
3799  "sep",
3800  "oct",
3801  "nov",
3802  "dec",
3803  NULL,
3804 };
3805 
3806 int ast_build_timing(struct ast_timing *i, const char *info_in);
3807 
3808 int ast_build_timing(struct ast_timing *i, const char *info_in)
3809 {
3810  char *info;
3811  int j, num_fields, last_sep = -1;
3812 
3813  i->timezone = NULL;
3814 
3815  /* Check for empty just in case */
3816  if (ast_strlen_zero(info_in)) {
3817  return 0;
3818  }
3819 
3820  /* make a copy just in case we were passed a static string */
3821  info = ast_strdupa(info_in);
3822 
3823  /* count the number of fields in the timespec */
3824  for (j = 0, num_fields = 1; info[j] != '\0'; j++) {
3825  if (info[j] == ',') {
3826  last_sep = j;
3827  num_fields++;
3828  }
3829  }
3830 
3831  /* save the timezone, if it is specified */
3832  if (num_fields == 5) {
3833  i->timezone = ast_strdup(info + last_sep + 1);
3834  }
3835 
3836  /* Assume everything except time */
3837  i->monthmask = 0xfff; /* 12 bits */
3838  i->daymask = 0x7fffffffU; /* 31 bits */
3839  i->dowmask = 0x7f; /* 7 bits */
3840  /* on each call, use strsep() to move info to the next argument */
3841  get_timerange(i, strsep(&info, "|,"));
3842  if (info)
3843  i->dowmask = get_range(strsep(&info, "|,"), 7, days, "day of week");
3844  if (info)
3845  i->daymask = get_range(strsep(&info, "|,"), 31, NULL, "day");
3846  if (info)
3847  i->monthmask = get_range(strsep(&info, "|,"), 12, months, "month");
3848  return 1;
3849 }
3850 
3851 /*!
3852  * \brief helper functions to sort extensions and patterns in the desired way,
3853  * so that more specific patterns appear first.
3854  *
3855  * ext_cmp1 compares individual characters (or sets of), returning
3856  * an int where bits 0-7 are the ASCII code of the first char in the set,
3857  * while bit 8-15 are the cardinality of the set minus 1.
3858  * This way more specific patterns (smaller cardinality) appear first.
3859  * Wildcards have a special value, so that we can directly compare them to
3860  * sets by subtracting the two values. In particular:
3861  * 0x000xx one character, xx
3862  * 0x0yyxx yy character set starting with xx
3863  * 0x10000 '.' (one or more of anything)
3864  * 0x20000 '!' (zero or more of anything)
3865  * 0x30000 NUL (end of string)
3866  * 0x40000 error in set.
3867  * The pointer to the string is advanced according to needs.
3868  * NOTES:
3869  * 1. the empty set is equivalent to NUL.
3870  * 2. given that a full set has always 0 as the first element,
3871  * we could encode the special cases as 0xffXX where XX
3872  * is 1, 2, 3, 4 as used above.
3873  */
3874 static int ext_cmp1(const char **p)
3875 {
3876  uint32_t chars[8];
3877  int c, cmin = 0xff, count = 0;
3878  const char *end;
3879 
3880  /* load, sign extend and advance pointer until we find
3881  * a valid character.
3882  */
3883  while ( (c = *(*p)++) && (c == ' ' || c == '-') )
3884  ; /* ignore some characters */
3885 
3886  /* always return unless we have a set of chars */
3887  switch (c) {
3888  default: /* ordinary character */
3889  return 0x0000 | (c & 0xff);
3890 
3891  case 'N': /* 2..9 */
3892  return 0x0700 | '2' ;
3893 
3894  case 'X': /* 0..9 */
3895  return 0x0900 | '0';
3896 
3897  case 'Z': /* 1..9 */
3898  return 0x0800 | '1';
3899 
3900  case '.': /* wildcard */
3901  return 0x10000;
3902 
3903  case '!': /* earlymatch */
3904  return 0x20000; /* less specific than NULL */
3905 
3906  case '\0': /* empty string */
3907  *p = NULL;
3908  return 0x30000;
3909 
3910  case '[': /* pattern */
3911  break;
3912  }
3913  /* locate end of set */
3914  end = strchr(*p, ']');
3915 
3916  if (end == NULL) {
3917  ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n");
3918  return 0x40000; /* XXX make this entry go last... */
3919  }
3920 
3921  memset(chars, '\0', sizeof(chars)); /* clear all chars in the set */
3922  for (; *p < end ; (*p)++) {
3923  unsigned char c1, c2; /* first-last char in range */
3924  c1 = (unsigned char)((*p)[0]);
3925  if (*p + 2 < end && (*p)[1] == '-') { /* this is a range */
3926  c2 = (unsigned char)((*p)[2]);
3927  *p += 2; /* skip a total of 3 chars */
3928  } else /* individual character */
3929  c2 = c1;
3930  if (c1 < cmin)
3931  cmin = c1;
3932  for (; c1 <= c2; c1++) {
3933  uint32_t mask = 1 << (c1 % 32);
3934  if ( (chars[ c1 / 32 ] & mask) == 0)
3935  count += 0x100;
3936  chars[ c1 / 32 ] |= mask;
3937  }
3938  }
3939  (*p)++;
3940  return count == 0 ? 0x30000 : (count | cmin);
3941 }
3942 
3943 /*!
3944  * \brief the full routine to compare extensions in rules.
3945  */
3946 static int ext_cmp(const char *a, const char *b)
3947 {
3948  /* make sure non-patterns come first.
3949  * If a is not a pattern, it either comes first or
3950  * we use strcmp to compare the strings.
3951  */
3952  int ret = 0;
3953 
3954  if (a[0] != '_')
3955  return (b[0] == '_') ? -1 : strcmp(a, b);
3956 
3957  /* Now we know a is a pattern; if b is not, a comes first */
3958  if (b[0] != '_')
3959  return 1;
3960 #if 0 /* old mode for ext matching */
3961  return strcmp(a, b);
3962 #endif
3963  /* ok we need full pattern sorting routine */
3964  while (!ret && a && b)
3965  ret = ext_cmp1(&a) - ext_cmp1(&b);
3966  if (ret == 0)
3967  return 0;
3968  else
3969  return (ret > 0) ? 1 : -1;
3970 }
3971 
3972 /*! \brief copy a string skipping whitespace */
3973 static int ext_strncpy(char *dst, const char *src, int len)
3974 {
3975  int count=0;
3976 
3977  while (*src && (count < len - 1)) {
3978  switch(*src) {
3979  case ' ':
3980  /* otherwise exten => [a-b],1,... doesn't work */
3981  /* case '-': */
3982  /* Ignore */
3983  break;
3984  default:
3985  *dst = *src;
3986  dst++;
3987  }
3988  src++;
3989  count++;
3990  }
3991  *dst = '\0';
3992 
3993  return count;
3994 }
3995 
3996 /*
3997  * Wrapper around _extension_match_core() to do performance measurement
3998  * using the profiling code.
3999  */
4000 int ast_check_timing(const struct ast_timing *i);
4001 
4002 int ast_check_timing(const struct ast_timing *i)
4003 {
4004  /* sorry, but this feature will NOT be available
4005  in the standalone version */
4006  return 0;
4007 }
4008 
4009 #ifdef NOT_ANYMORE
4010 static struct ast_switch *pbx_findswitch(const char *sw)
4011 {
4012  struct ast_switch *asw;
4013 
4015  if (!strcasecmp(asw->name, sw))
4016  break;
4017  }
4018 
4019  return asw;
4020 }
4021 #endif
4022 
4023 
4024 static struct ast_context *ast_walk_contexts(struct ast_context *con);
4025 
4026 static struct ast_context *ast_walk_contexts(struct ast_context *con)
4027 {
4028  return con ? con->next : contexts;
4029 }
4030 
4031 struct ast_context *localized_walk_contexts(struct ast_context *con);
4033 {
4034  return ast_walk_contexts(con);
4035 }
4036 
4037 
4038 
4039 static struct ast_exten *ast_walk_context_extensions(struct ast_context *con,
4040  struct ast_exten *exten);
4041 
4043  struct ast_exten *exten)
4044 {
4045  if (!exten)
4046  return con ? con->root : NULL;
4047  else
4048  return exten->next;
4049 }
4050 
4052  struct ast_exten *exten);
4054  struct ast_exten *exten)
4055 {
4056  return ast_walk_context_extensions(con,exten);
4057 }
4058 
4059 
4060 static struct ast_exten *ast_walk_extension_priorities(struct ast_exten *exten,
4061  struct ast_exten *priority);
4062 
4064  struct ast_exten *priority)
4065 {
4066  return priority ? priority->peer : exten;
4067 }
4068 
4070  struct ast_exten *priority);
4072  struct ast_exten *priority)
4073 {
4074  return ast_walk_extension_priorities(exten, priority);
4075 }
4076 
4077 
4078 
4079 static struct ast_include *ast_walk_context_includes(struct ast_context *con,
4080  struct ast_include *inc);
4081 
4083  struct ast_include *inc)
4084 {
4085  if (!inc)
4086  return con ? con->includes : NULL;
4087  else
4088  return inc->next;
4089 }
4090 
4091 int ast_context_includes_count(struct ast_context *con);
4093 {
4094  int c = 0;
4095  struct ast_include *inc = NULL;
4096 
4097  while ((inc = ast_walk_context_includes(con, inc))) {
4098  c++;
4099  }
4100 
4101  return c;
4102 }
4103 
4105  struct ast_include *inc);
4107  struct ast_include *inc)
4108 {
4109  return ast_walk_context_includes(con, inc);
4110 }
4111 
4112 static struct ast_ignorepat *ast_walk_context_ignorepats(struct ast_context *con,
4113  struct ast_ignorepat *ip);
4114 
4116  struct ast_ignorepat *ip)
4117 {
4118  if (!ip)
4119  return con ? con->ignorepats : NULL;
4120  else
4121  return ip->next;
4122 }
4123 
4124 int ast_context_ignorepats_count(struct ast_context *con);
4126 {
4127  int c = 0;
4128  struct ast_ignorepat *ip = NULL;
4129 
4130  while ((ip = ast_walk_context_ignorepats(con, ip))) {
4131  c++;
4132  }
4133 
4134  return c;
4135 }
4136 
4137 
4138 static struct ast_sw *ast_walk_context_switches(struct ast_context *con,
4139  struct ast_sw *sw);
4140 
4141 static struct ast_sw *ast_walk_context_switches(struct ast_context *con,
4142  struct ast_sw *sw)
4143 {
4144  if (!sw)
4145  return con ? AST_LIST_FIRST(&con->alts) : NULL;
4146  else
4147  return AST_LIST_NEXT(sw, list);
4148 }
4149 
4151  struct ast_sw *sw);
4153  struct ast_sw *sw)
4154 {
4155  return ast_walk_context_switches(con, sw);
4156 }
4157 
4158 int ast_context_switches_count(struct ast_context *con);
4160 {
4161  int c = 0;
4162  struct ast_sw *sw = NULL;
4163 
4164  while ((sw = ast_walk_context_switches(con, sw))) {
4165  c++;
4166  }
4167 
4168  return c;
4169 }
4170 
4171 
4172 static struct ast_context *ast_context_find(const char *name);
4173 
4174 static struct ast_context *ast_context_find(const char *name)
4175 {
4176  struct ast_context *tmp = NULL;
4177  while ( (tmp = ast_walk_contexts(tmp)) ) {
4178  if (!name || !strcasecmp(name, tmp->name))
4179  break;
4180  }
4181  return tmp;
4182 }
4183 
4184 /*
4185  * Internal function for ast_extension_{match|close}
4186  * return 0 on no-match, 1 on match, 2 on early match.
4187  * mode is as follows:
4188  * E_MATCH success only on exact match
4189  * E_MATCHMORE success only on partial match (i.e. leftover digits in pattern)
4190  * E_CANMATCH either of the above.
4191  */
4192 
4193 static int _extension_match_core(const char *pattern, const char *data, enum ext_match_t mode)
4194 {
4195  mode &= E_MATCH_MASK; /* only consider the relevant bits */
4196 
4197  if ( (mode == E_MATCH) && (pattern[0] == '_') && (strcasecmp(pattern,data)==0) ) /* note: if this test is left out, then _x. will not match _x. !!! */
4198  return 1;
4199 
4200  if (pattern[0] != '_') { /* not a pattern, try exact or partial match */
4201  int ld = strlen(data), lp = strlen(pattern);
4202 
4203  if (lp < ld) /* pattern too short, cannot match */
4204  return 0;
4205  /* depending on the mode, accept full or partial match or both */
4206  if (mode == E_MATCH)
4207  return !strcmp(pattern, data); /* 1 on match, 0 on fail */
4208  if (ld == 0 || !strncasecmp(pattern, data, ld)) /* partial or full match */
4209  return (mode == E_MATCHMORE) ? lp > ld : 1; /* XXX should consider '!' and '/' ? */
4210  else
4211  return 0;
4212  }
4213  pattern++; /* skip leading _ */
4214  /*
4215  * XXX below we stop at '/' which is a separator for the CID info. However we should
4216  * not store '/' in the pattern at all. When we insure it, we can remove the checks.
4217  */
4218  while (*data && *pattern && *pattern != '/') {
4219  const char *end;
4220 
4221  if (*data == '-') { /* skip '-' in data (just a separator) */
4222  data++;
4223  continue;
4224  }
4225  switch (toupper(*pattern)) {
4226  case '[': /* a range */
4227  end = strchr(pattern+1, ']'); /* XXX should deal with escapes ? */
4228  if (end == NULL) {
4229  ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n");
4230  return 0; /* unconditional failure */
4231  }
4232  for (pattern++; pattern != end; pattern++) {
4233  if (pattern+2 < end && pattern[1] == '-') { /* this is a range */
4234  if (*data >= pattern[0] && *data <= pattern[2])
4235  break; /* match found */
4236  else {
4237  pattern += 2; /* skip a total of 3 chars */
4238  continue;
4239  }
4240  } else if (*data == pattern[0])
4241  break; /* match found */
4242  }
4243  if (pattern == end)
4244  return 0;
4245  pattern = end; /* skip and continue */
4246  break;
4247  case 'N':
4248  if (*data < '2' || *data > '9')
4249  return 0;
4250  break;
4251  case 'X':
4252  if (*data < '0' || *data > '9')
4253  return 0;
4254  break;
4255  case 'Z':
4256  if (*data < '1' || *data > '9')
4257  return 0;
4258  break;
4259  case '.': /* Must match, even with more digits */
4260  return 1;
4261  case '!': /* Early match */
4262  return 2;
4263  case ' ':
4264  case '-': /* Ignore these in patterns */
4265  data--; /* compensate the final data++ */
4266  break;
4267  default:
4268  if (*data != *pattern)
4269  return 0;
4270  }
4271  data++;
4272  pattern++;
4273  }
4274  if (*data) /* data longer than pattern, no match */
4275  return 0;
4276  /*
4277  * match so far, but ran off the end of the data.
4278  * Depending on what is next, determine match or not.
4279  */
4280  if (*pattern == '\0' || *pattern == '/') /* exact match */
4281  return (mode == E_MATCHMORE) ? 0 : 1; /* this is a failure for E_MATCHMORE */
4282  else if (*pattern == '!') /* early match */
4283  return 2;
4284  else /* partial match */
4285  return (mode == E_MATCH) ? 0 : 1; /* this is a failure for E_MATCH */
4286 }
4287 
4288 static int extension_match_core(const char *pattern, const char *data, enum ext_match_t mode)
4289 {
4290  int i;
4291  i = _extension_match_core(pattern, data, mode);
4292  return i;
4293 }
4294 
4295 static int ast_extension_match(const char *pattern, const char *data);
4296 
4297 static int ast_extension_match(const char *pattern, const char *data)
4298 {
4299  return extension_match_core(pattern, data, E_MATCH);
4300 }
4301 
4302 static int matchcid(const char *cidpattern, const char *callerid)
4303 {
4304  /* If the Caller*ID pattern is empty, then we're matching NO Caller*ID, so
4305  failing to get a number should count as a match, otherwise not */
4306 
4307  if (ast_strlen_zero(callerid))
4308  return ast_strlen_zero(cidpattern) ? 1 : 0;
4309 
4310  return ast_extension_match(cidpattern, callerid);
4311 }
4312 
4313 static inline int include_valid(struct ast_include *i)
4314 {
4315  if (!i->hastime)
4316  return 1;
4317 
4318  return ast_check_timing(&(i->timing));
4319 }
4320 
4321 
4322 
4323 static struct ast_exten *pbx_find_extension(struct ast_channel *chan,
4324  struct ast_context *bypass,
4325  struct pbx_find_info *q,
4326  const char *context,
4327  const char *exten,
4328  int priority,
4329  const char *label,
4330  const char *callerid,
4331  enum ext_match_t action);
4332 
4333 
4334 static struct ast_exten *pbx_find_extension(struct ast_channel *chan,
4335  struct ast_context *bypass,
4336  struct pbx_find_info *q,
4337  const char *context,
4338  const char *exten,
4339  int priority,
4340  const char *label,
4341  const char *callerid,
4342  enum ext_match_t action)
4343 {
4344  int x;
4345  struct ast_context *tmp;
4346  struct ast_exten *e, *eroot;
4347  struct ast_include *i;
4348 
4349  if (!context) {
4350  return NULL;
4351  }
4352 
4353  /* Initialize status if appropriate */
4354  if (q->stacklen == 0) {
4356  q->swo = NULL;
4357  q->data = NULL;
4358  q->foundcontext = NULL;
4359  } else if (q->stacklen >= AST_PBX_MAX_STACK) {
4360  ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n");
4361  return NULL;
4362  }
4363  /* Check first to see if we've already been checked */
4364  for (x = 0; x < q->stacklen; x++) {
4365  if (!strcasecmp(q->incstack[x], context))
4366  return NULL;
4367  }
4368  if (bypass) /* bypass means we only look there */
4369  tmp = bypass;
4370  else { /* look in contexts */
4371  tmp = NULL;
4372  while ((tmp = ast_walk_contexts(tmp)) ) {
4373  if (!strcmp(tmp->name, context))
4374  break;
4375  }
4376  if (!tmp)
4377  return NULL;
4378  }
4379  if (q->status < STATUS_NO_EXTENSION)
4381 
4382  /* scan the list trying to match extension and CID */
4383  eroot = NULL;
4384  while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) {
4385  int match = extension_match_core(eroot->exten, exten, action);
4386  /* 0 on fail, 1 on match, 2 on earlymatch */
4387 
4388  if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid)))
4389  continue; /* keep trying */
4390  if (match == 2 && action == E_MATCHMORE) {
4391  /* We match an extension ending in '!'.
4392  * The decision in this case is final and is NULL (no match).
4393  */
4394  return NULL;
4395  }
4396  /* found entry, now look for the right priority */
4397  if (q->status < STATUS_NO_PRIORITY)
4399  e = NULL;
4400  while ( (e = ast_walk_extension_priorities(eroot, e)) ) {
4401  /* Match label or priority */
4402  if (action == E_FINDLABEL) {
4403  if (q->status < STATUS_NO_LABEL)
4404  q->status = STATUS_NO_LABEL;
4405  if (label && e->label && !strcmp(label, e->label))
4406  break; /* found it */
4407  } else if (e->priority == priority) {
4408  break; /* found it */
4409  } /* else keep searching */
4410  }
4411  if (e) { /* found a valid match */
4412  q->status = STATUS_SUCCESS;
4413  q->foundcontext = context;
4414  return e;
4415  }
4416  }
4417 #ifdef NOT_RIGHT_NOW
4418  /* Check alternative switches??? */
4419  AST_LIST_TRAVERSE(&tmp->alts, sw, list) {
4420  struct ast_switch *asw = pbx_findswitch(sw->name);
4421  ast_switch_f *aswf = NULL;
4422  char *datap;
4423 
4424  if (!asw) {
4425  ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name);
4426  continue;
4427  }
4428  /* No need to Substitute variables now; we shouldn't be here if there's any */
4429 
4430  /* equivalent of extension_match_core() at the switch level */
4431  if (action == E_CANMATCH)
4432  aswf = asw->canmatch;
4433  else if (action == E_MATCHMORE)
4434  aswf = asw->matchmore;
4435  else /* action == E_MATCH */
4436  aswf = asw->exists;
4437  datap = sw->eval ? sw->tmpdata : sw->data;
4438  res = !aswf ? 0 : aswf(chan, context, exten, priority, callerid, datap);
4439  if (res) { /* Got a match */
4440  q->swo = asw;
4441  q->data = datap;
4442  q->foundcontext = context;
4443  /* XXX keep status = STATUS_NO_CONTEXT ? */
4444  return NULL;
4445  }
4446  }
4447 #endif
4448  q->incstack[q->stacklen++] = tmp->name; /* Setup the stack */
4449  /* Now try any includes we have in this context */
4450  for (i = tmp->includes; i; i = i->next) {
4451  if (include_valid(i)) {
4452  if ((e = pbx_find_extension(NULL, bypass, q, i->rname, exten, priority, label, callerid, action)))
4453  return e;
4454  if (q->swo)
4455  return NULL;
4456  }
4457  }
4458  return NULL;
4459 }
4460 
4461 struct ast_exten *localized_find_extension(struct ast_context *bypass,
4462  struct pbx_find_info *q,
4463  const char *context,
4464  const char *exten,
4465  int priority,
4466  const char *label,
4467  const char *callerid,
4468  enum ext_match_t action);
4469 
4471  struct pbx_find_info *q,
4472  const char *context,
4473  const char *exten,
4474  int priority,
4475  const char *label,
4476  const char *callerid,
4477  enum ext_match_t action)
4478 {
4479  return pbx_find_extension(NULL, bypass, q, context, exten, priority, label, callerid, action);
4480 }
4481 
4482 
4483 static struct ast_context *contexts;
4484 AST_RWLOCK_DEFINE_STATIC(conlock); /*!< Lock for the ast_context list */
4485 
4486 static const char *ast_get_context_name(struct ast_context *con);
4487 
4488 static const char *ast_get_context_name(struct ast_context *con)
4489 {
4490  return con ? con->name : NULL;
4491 }
4492 
4493 /*
4494  * errno values
4495  * ENOMEM - out of memory
4496  * EBUSY - can't lock
4497  * EEXIST - already included
4498  * EINVAL - there is no existence of context for inclusion
4499  */
4500 static int ast_context_add_include2(struct ast_context *con, const char *value,
4501  const char *registrar);
4502 
4503 static int ast_context_add_include2(struct ast_context *con, const char *value,
4504  const char *registrar)
4505 {
4506  struct ast_include *new_include;
4507  char *c;
4508  struct ast_include *i, *il = NULL; /* include, include_last */
4509  int length;
4510  char *p;
4511 
4512  length = sizeof(struct ast_include);
4513  length += 2 * (strlen(value) + 1);
4514 
4515  /* allocate new include structure ... */
4516  if (!(new_include = ast_calloc(1, length)))
4517  return -1;
4518  /* Fill in this structure. Use 'p' for assignments, as the fields
4519  * in the structure are 'const char *'
4520  */
4521  p = new_include->stuff;
4522  new_include->name = p;
4523  strcpy(p, value);
4524  p += strlen(value) + 1;
4525  new_include->rname = p;
4526  strcpy(p, value);
4527  /* Strip off timing info, and process if it is there */
4528  if ( (c = strchr(p, '|')) ) {
4529  *c++ = '\0';
4530  new_include->hastime = ast_build_timing(&(new_include->timing), c);
4531  }
4532  new_include->next = NULL;
4533  new_include->registrar = registrar;
4534 
4535 
4536  /* ... go to last include and check if context is already included too... */
4537  for (i = con->includes; i; i = i->next) {
4538  if (!strcasecmp(i->name, new_include->name)) {
4539  free(new_include);
4540  errno = EEXIST;
4541  return -1;
4542  }
4543  il = i;
4544  }
4545 
4546  /* ... include new context into context list, unlock, return */
4547  if (il)
4548  il->next = new_include;
4549  else
4550  con->includes = new_include;
4551  if (option_verbose > 2)
4552  ast_verbose(VERBOSE_PREFIX_3 "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con));
4553 
4554  return 0;
4555 }
4556 
4557 int localized_context_add_include2(struct ast_context *con, const char *value,
4558  const char *registrar);
4559 int localized_context_add_include2(struct ast_context *con, const char *value,
4560  const char *registrar)
4561 {
4562  return ast_context_add_include2(con, value, registrar);
4563 }
4564 
4565 
4566 
4567 static int ast_context_add_ignorepat2(struct ast_context *con, const char *value, const char *registrar);
4568 
4569 static int ast_context_add_ignorepat2(struct ast_context *con, const char *value, const char *registrar)
4570 {
4571  struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL;
4572  int length;
4573  length = sizeof(struct ast_ignorepat);
4574  length += strlen(value) + 1;
4575  if (!(ignorepat = ast_calloc(1, length)))
4576  return -1;
4577  /* The cast to char * is because we need to write the initial value.
4578  * The field is not supposed to be modified otherwise
4579  */
4580  strcpy((char *)ignorepat->pattern, value);
4581  ignorepat->next = NULL;
4582  ignorepat->registrar = registrar;
4583  for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) {
4584  ignorepatl = ignorepatc;
4585  if (!strcasecmp(ignorepatc->pattern, value)) {
4586  /* Already there */
4587  errno = EEXIST;
4588  return -1;
4589  }
4590  }
4591  if (ignorepatl)
4592  ignorepatl->next = ignorepat;
4593  else
4594  con->ignorepats = ignorepat;
4595  return 0;
4596 
4597 }
4598 
4599 int localized_context_add_ignorepat2(struct ast_context *con, const char *value, const char *registrar);
4600 
4601 int localized_context_add_ignorepat2(struct ast_context *con, const char *value, const char *registrar)
4602 {
4603  return ast_context_add_ignorepat2(con, value, registrar);
4604 }
4605 
4606 
4607 /*
4608  * Lock context list functions ...
4609  */
4610 
4611 static int ast_wrlock_contexts(void)
4612 {
4613  return ast_rwlock_wrlock(&conlock);
4614 }
4615 
4616 static int ast_unlock_contexts(void)
4617 {
4618  return ast_rwlock_unlock(&conlock);
4619 }
4620 
4621 static int ast_wrlock_context(struct ast_context *con)
4622 {
4623  return ast_rwlock_wrlock(&con->lock);
4624 }
4625 
4626 static int ast_unlock_context(struct ast_context *con)
4627 {
4628  return ast_rwlock_unlock(&con->lock);
4629 }
4630 
4631 /*
4632  * errno values
4633  * ENOMEM - out of memory
4634  * EBUSY - can't lock
4635  * EEXIST - already included
4636  * EINVAL - there is no existence of context for inclusion
4637  */
4638 static int ast_context_add_switch2(struct ast_context *con, const char *value,
4639  const char *data, int eval, const char *registrar);
4640 
4641 static int ast_context_add_switch2(struct ast_context *con, const char *value,
4642  const char *data, int eval, const char *registrar)
4643 {
4644  struct ast_sw *new_sw;
4645  struct ast_sw *i;
4646  int length;
4647  char *p;
4648 
4649  length = sizeof(struct ast_sw);
4650  length += strlen(value) + 1;
4651  if (data)
4652  length += strlen(data);
4653  length++;
4654  if (eval) {
4655  /* Create buffer for evaluation of variables */
4656  length += SWITCH_DATA_LENGTH;
4657  length++;
4658  }
4659 
4660  /* allocate new sw structure ... */
4661  if (!(new_sw = ast_calloc(1, length)))
4662  return -1;
4663  /* ... fill in this structure ... */
4664  p = new_sw->stuff;
4665  new_sw->name = p;
4666  strcpy(new_sw->name, value);
4667  p += strlen(value) + 1;
4668  new_sw->data = p;
4669  if (data) {
4670  strcpy(new_sw->data, data);
4671  p += strlen(data) + 1;
4672  } else {
4673  strcpy(new_sw->data, "");
4674  p++;
4675  }
4676  if (eval)
4677  new_sw->tmpdata = p;
4678  new_sw->eval = eval;
4679  new_sw->registrar = registrar;
4680 
4681  /* ... go to last sw and check if context is already swd too... */
4682  AST_LIST_TRAVERSE(&con->alts, i, list) {
4683  if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) {
4684  free(new_sw);
4685  errno = EEXIST;
4686  return -1;
4687  }
4688  }
4689 
4690  /* ... sw new context into context list, unlock, return */
4691  AST_LIST_INSERT_TAIL(&con->alts, new_sw, list);
4692 
4693  if (option_verbose > 2)
4694  ast_verbose(VERBOSE_PREFIX_3 "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con));
4695 
4696  return 0;
4697 }
4698 
4699 int localized_context_add_switch2(struct ast_context *con, const char *value,
4700  const char *data, int eval, const char *registrar);
4701 
4702 int localized_context_add_switch2(struct ast_context *con, const char *value,
4703  const char *data, int eval, const char *registrar)
4704 {
4705  return ast_context_add_switch2(con, value, data, eval, registrar);
4706 }
4707 
4708 static struct ast_context *__ast_context_create(struct ast_context **extcontexts, const char *name, const char *registrar, int existsokay)
4709 {
4710  struct ast_context *tmp, **loc_contexts;
4711  int length = sizeof(struct ast_context) + strlen(name) + 1;
4712 
4713  if (!extcontexts) {
4715  loc_contexts = &contexts;
4716  } else
4717  loc_contexts = extcontexts;
4718 
4719  for (tmp = *loc_contexts; tmp; tmp = tmp->next) {
4720  if (!strcasecmp(tmp->name, name)) {
4721  if (!existsokay) {
4722  ast_log(LOG_WARNING, "Tried to register context '%s', already in use\n", name);
4723  tmp = NULL;
4724  }
4725  if (!extcontexts)
4727  return tmp;
4728  }
4729  }
4730  if ((tmp = ast_calloc(1, length))) {
4731  ast_rwlock_init(&tmp->lock);
4732  ast_mutex_init(&tmp->macrolock);
4733  strcpy(tmp->name, name);
4734  tmp->root = NULL;
4735  tmp->registrar = registrar;
4736  tmp->next = *loc_contexts;
4737  tmp->includes = NULL;
4738  tmp->ignorepats = NULL;
4739  *loc_contexts = tmp;
4740  if (option_debug)
4741  ast_log(LOG_DEBUG, "Registered context '%s'\n", tmp->name);
4742  if (option_verbose > 2)
4743  ast_verbose( VERBOSE_PREFIX_3 "Registered extension context '%s'\n", tmp->name);
4744  }
4745 
4746  if (!extcontexts)
4748  return tmp;
4749 }
4750 
4751 /*! \brief
4752  * Main interface to add extensions to the list for out context.
4753  *
4754  * We sort extensions in order of matching preference, so that we can
4755  * stop the search as soon as we find a suitable match.
4756  * This ordering also takes care of wildcards such as '.' (meaning
4757  * "one or more of any character") and '!' (which is 'earlymatch',
4758  * meaning "zero or more of any character" but also impacts the
4759  * return value from CANMATCH and EARLYMATCH.
4760  *
4761  * The extension match rules defined in the devmeeting 2006.05.05 are
4762  * quite simple: WE SELECT THE LONGEST MATCH.
4763  * In detail, "longest" means the number of matched characters in
4764  * the extension. In case of ties (e.g. _XXX and 333) in the length
4765  * of a pattern, we give priority to entries with the smallest cardinality
4766  * (e.g, [5-9] comes before [2-8] before the former has only 5 elements,
4767  * while the latter has 7, etc.
4768  * In case of same cardinality, the first element in the range counts.
4769  * If we still have a tie, any final '!' will make this as a possibly
4770  * less specific pattern.
4771  *
4772  * EBUSY - can't lock
4773  * EEXIST - extension with the same priority exist and no replace is set
4774  *
4775  */
4776 static int ast_add_extension2(struct ast_context *con,
4777  int replace, const char *extension, int priority, const char *label, const char *callerid,
4778  const char *application, void *data, void (*datad)(void *),
4779  const char *registrar)
4780 {
4781  /*
4782  * Sort extensions (or patterns) according to the rules indicated above.
4783  * These are implemented by the function ext_cmp()).
4784  * All priorities for the same ext/pattern/cid are kept in a list,
4785  * using the 'peer' field as a link field..
4786  */
4787  struct ast_exten *tmp, *e, *el = NULL;
4788  int res;
4789  int length;
4790  char *p;
4791 
4792  /* if we are adding a hint, and there are global variables, and the hint
4793  contains variable references, then expand them --- NOT In this situation!!!
4794  */
4795 
4796  length = sizeof(struct ast_exten);
4797  length += strlen(extension) + 1;
4798  length += strlen(application) + 1;
4799  if (label)
4800  length += strlen(label) + 1;
4801  if (callerid)
4802  length += strlen(callerid) + 1;
4803  else
4804  length ++; /* just the '\0' */
4805 
4806  /* Be optimistic: Build the extension structure first */
4807  if (datad == NULL)
4808  datad = null_datad;
4809  if (!(tmp = ast_calloc(1, length)))
4810  return -1;
4811 
4812  /* use p as dst in assignments, as the fields are const char * */
4813  p = tmp->stuff;
4814  if (label) {
4815  tmp->label = p;
4816  strcpy(p, label);
4817  p += strlen(label) + 1;
4818  }
4819  tmp->exten = p;
4820  p += ext_strncpy(p, extension, strlen(extension) + 1) + 1;
4821  tmp->priority = priority;
4822  tmp->cidmatch = p; /* but use p for assignments below */
4823  if (callerid) {
4824  p += ext_strncpy(p, callerid, strlen(callerid) + 1) + 1;
4825  tmp->matchcid = 1;
4826  } else {
4827  *p++ = '\0';
4828  tmp->matchcid = 0;
4829  }
4830  tmp->app = p;
4831  strcpy(p, application);
4832  tmp->parent = con;
4833  tmp->data = data;
4834  tmp->datad = datad;
4835  tmp->registrar = registrar;
4836 
4837  res = 0; /* some compilers will think it is uninitialized otherwise */
4838  for (e = con->root; e; el = e, e = e->next) { /* scan the extension list */
4839  res = ext_cmp(e->exten, extension);
4840  if (res == 0) { /* extension match, now look at cidmatch */
4841  if (!e->matchcid && !tmp->matchcid)
4842  res = 0;
4843  else if (tmp->matchcid && !e->matchcid)
4844  res = 1;
4845  else if (e->matchcid && !tmp->matchcid)
4846  res = -1;
4847  else
4848  res = strcasecmp(e->cidmatch, tmp->cidmatch);
4849  }
4850  if (res >= 0)
4851  break;
4852  }
4853  if (e && res == 0) { /* exact match, insert in the pri chain */
4854  res = add_pri(con, tmp, el, e, replace);
4855  if (res < 0) {
4856  errno = EEXIST; /* XXX do we care ? */
4857  return 0; /* XXX should we return -1 maybe ? */
4858  }
4859  } else {
4860  /*
4861  * not an exact match, this is the first entry with this pattern,
4862  * so insert in the main list right before 'e' (if any)
4863  */
4864  tmp->next = e;
4865  if (el)
4866  el->next = tmp;
4867  else
4868  con->root = tmp;
4869  if (tmp->priority == PRIORITY_HINT)
4870  ast_add_hint(tmp);
4871  }
4872  if (option_debug) {
4873  if (tmp->matchcid) {
4874  ast_log(LOG_DEBUG, "Added extension '%s' priority %d (CID match '%s') to %s\n",
4875  tmp->exten, tmp->priority, tmp->cidmatch, con->name);
4876  } else {
4877  ast_log(LOG_DEBUG, "Added extension '%s' priority %d to %s\n",
4878  tmp->exten, tmp->priority, con->name);
4879  }
4880  }
4881  if (option_verbose > 2) {
4882  if (tmp->matchcid) {
4883  ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d (CID match '%s')to %s\n",
4884  tmp->exten, tmp->priority, tmp->cidmatch, con->name);
4885  } else {
4886  ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d to %s\n",
4887  tmp->exten, tmp->priority, con->name);
4888  }
4889  }
4890  return 0;
4891 }
4892 
4893 int localized_add_extension2(struct ast_context *con,
4894  int replace, const char *extension, int priority, const char *label, const char *callerid,
4895  const char *application, void *data, void (*datad)(void *),
4896  const char *registrar);
4897 
4899  int replace, const char *extension, int priority, const char *label, const char *callerid,
4900  const char *application, void *data, void (*datad)(void *),
4901  const char *registrar)
4902 {
4903  return ast_add_extension2(con, replace, extension, priority, label, callerid, application, data, datad, registrar);
4904 }
4905 
4906 
4907 
4908 /*! \brief The return value depends on the action:
4909  *
4910  * E_MATCH, E_CANMATCH, E_MATCHMORE require a real match,
4911  * and return 0 on failure, -1 on match;
4912  * E_FINDLABEL maps the label to a priority, and returns
4913  * the priority on success, ... XXX
4914  * E_SPAWN, spawn an application,
4915  * and return 0 on success, -1 on failure.
4916  */
4917 static int pbx_extension_helper(struct ast_channel *c, struct ast_context *con,
4918  const char *context, const char *exten, int priority,
4919  const char *label, const char *callerid, enum ext_match_t action)
4920 {
4921  struct ast_exten *e;
4922  int res;
4923  struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */
4924 
4925  int matching_action = (action == E_MATCH || action == E_CANMATCH || action == E_MATCHMORE);
4926 
4927  e = pbx_find_extension(NULL, con, &q, context, exten, priority, label, callerid, action);
4928  if (e) {
4929  if (matching_action) {
4930  return -1; /* success, we found it */
4931  } else if (action == E_FINDLABEL) { /* map the label to a priority */
4932  res = e->priority;
4933  return res; /* the priority we were looking for */
4934  } else { /* spawn */
4935 
4936  /* NOT!!!!! */
4937  return 0;
4938  }
4939  } else if (q.swo) { /* not found here, but in another switch */
4940  if (matching_action)
4941  return -1;
4942  else {
4943  if (!q.swo->exec) {
4944  ast_log(LOG_WARNING, "No execution engine for switch %s\n", q.swo->name);
4945  res = -1;
4946  }
4947  return q.swo->exec(c, q.foundcontext ? q.foundcontext : context, exten, priority, callerid, q.data);
4948  }
4949  } else { /* not found anywhere, see what happened */
4950  switch (q.status) {
4951  case STATUS_NO_CONTEXT:
4952  if (!matching_action)
4953  ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", context);
4954  break;
4955  case STATUS_NO_EXTENSION:
4956  if (!matching_action)
4957  ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, context);
4958  break;
4959  case STATUS_NO_PRIORITY:
4960  if (!matching_action)
4961  ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, context);
4962  break;
4963  case STATUS_NO_LABEL:
4964  if (context)
4965  ast_log(LOG_NOTICE, "No such label '%s' in extension '%s' in context '%s'\n", label, exten, context);
4966  break;
4967  default:
4968  if (option_debug)
4969  ast_log(LOG_DEBUG, "Shouldn't happen!\n");
4970  }
4971 
4972  return (matching_action) ? 0 : -1;
4973  }
4974 }
4975 
4976 static int ast_findlabel_extension2(struct ast_channel *c, struct ast_context *con, const char *exten, const char *label, const char *callerid);
4977 
4978 static int ast_findlabel_extension2(struct ast_channel *c, struct ast_context *con, const char *exten, const char *label, const char *callerid)
4979 {
4980  return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL);
4981 }
4982 
4983 static struct ast_context *ast_context_find_or_create(struct ast_context **extcontexts, void *tab, const char *name, const char *registrar)
4984 {
4985  return __ast_context_create(extcontexts, name, registrar, 1);
4986 }
4987 
4988 struct ast_context *localized_context_find_or_create(struct ast_context **extcontexts, void *tab, const char *name, const char *registrar);
4989 struct ast_context *localized_context_find_or_create(struct ast_context **extcontexts, void *tab, const char *name, const char *registrar)
4990 {
4991  return __ast_context_create(extcontexts, name, registrar, 1);
4992 }
4993 
4994 
4995 /* chopped this one off at the knees */
4996 static int ast_func_read(struct ast_channel *chan, const char *function, char *workspace, size_t len)
4997 {
4998  ast_log(LOG_ERROR, "Function %s not registered\n", function);
4999  return -1;
5000 }
5001 
5002 /*! \brief extract offset:length from variable name.
5003  * Returns 1 if there is a offset:length part, which is
5004  * trimmed off (values go into variables)
5005  */
5006 static int parse_variable_name(char *var, int *offset, int *length, int *isfunc)
5007 {
5008  int parens=0;
5009 
5010  *offset = 0;
5011  *length = INT_MAX;
5012  *isfunc = 0;
5013  for (; *var; var++) {
5014  if (*var == '(') {
5015  (*isfunc)++;
5016  parens++;
5017  } else if (*var == ')') {
5018  parens--;
5019  } else if (*var == ':' && parens == 0) {
5020  *var++ = '\0';
5021  sscanf(var, "%30d:%30d", offset, length);
5022  return 1; /* offset:length valid */
5023  }
5024  }
5025  return 0;
5026 }
5027 
5028 static const char *ast_var_value(const struct ast_var_t *var)
5029 {
5030  return (var ? var->value : NULL);
5031 }
5032 
5033 /*! \brief takes a substring. It is ok to call with value == workspace.
5034  *
5035  * offset < 0 means start from the end of the string and set the beginning
5036  * to be that many characters back.
5037  * length is the length of the substring. A value less than 0 means to leave
5038  * that many off the end.
5039  * Always return a copy in workspace.
5040  */
5041 static char *substring(const char *value, int offset, int length, char *workspace, size_t workspace_len)
5042 {
5043  char *ret = workspace;
5044  int lr; /* length of the input string after the copy */
5045 
5046  ast_copy_string(workspace, value, workspace_len); /* always make a copy */
5047 
5048  lr = strlen(ret); /* compute length after copy, so we never go out of the workspace */
5049 
5050  /* Quick check if no need to do anything */
5051  if (offset == 0 && length >= lr) /* take the whole string */
5052  return ret;
5053 
5054  if (offset < 0) { /* translate negative offset into positive ones */
5055  offset = lr + offset;
5056  if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */
5057  offset = 0;
5058  }
5059 
5060  /* too large offset result in empty string so we know what to return */
5061  if (offset >= lr)
5062  return ret + lr; /* the final '\0' */
5063 
5064  ret += offset; /* move to the start position */
5065  if (length >= 0 && length < lr - offset) /* truncate if necessary */
5066  ret[length] = '\0';
5067  else if (length < 0) {
5068  if (lr > offset - length) /* After we remove from the front and from the rear, is there anything left? */
5069  ret[lr + length - offset] = '\0';
5070  else
5071  ret[0] = '\0';
5072  }
5073 
5074  return ret;
5075 }
5076 
5077 /*! \brief Support for Asterisk built-in variables in the dialplan
5078 \note See also
5079  - \ref AstVar Channel variables
5080  - \ref AstCauses The HANGUPCAUSE variable
5081  */
5082 static void pbx_retrieve_variable(struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp)
5083 {
5084  const char not_found = '\0';
5085  char *tmpvar;
5086  const char *s; /* the result */
5087  int offset, length;
5088  int i, need_substring;
5089  struct varshead *places[2] = { headp, &globals }; /* list of places where we may look */
5090 
5091  /*
5092  * Make a copy of var because parse_variable_name() modifies the string.
5093  * Then if called directly, we might need to run substring() on the result;
5094  * remember this for later in 'need_substring', 'offset' and 'length'
5095  */
5096  tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */
5097  need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */);
5098 
5099  /*
5100  * Look first into predefined variables, then into variable lists.
5101  * Variable 's' points to the result, according to the following rules:
5102  * s == &not_found (set at the beginning) means that we did not find a
5103  * matching variable and need to look into more places.
5104  * If s != &not_found, s is a valid result string as follows:
5105  * s = NULL if the variable does not have a value;
5106  * you typically do this when looking for an unset predefined variable.
5107  * s = workspace if the result has been assembled there;
5108  * typically done when the result is built e.g. with an snprintf(),
5109  * so we don't need to do an additional copy.
5110  * s != workspace in case we have a string, that needs to be copied
5111  * (the ast_copy_string is done once for all at the end).
5112  * Typically done when the result is already available in some string.
5113  */
5114  s = &not_found; /* default value */
5115  if (s == &not_found) { /* look for more */
5116  if (!strcmp(var, "EPOCH")) {
5117  snprintf(workspace, workspacelen, "%u",(int)time(NULL));
5118  }
5119 
5120  s = workspace;
5121  }
5122  /* if not found, look into chanvars or global vars */
5123  for (i = 0; s == &not_found && i < (sizeof(places) / sizeof(places[0])); i++) {
5124  struct ast_var_t *variables;
5125  if (!places[i])
5126  continue;
5127  if (places[i] == &globals)
5129  AST_LIST_TRAVERSE(places[i], variables, entries) {
5130  if (strcasecmp(ast_var_name(variables), var)==0) {
5131  s = ast_var_value(variables);
5132  break;
5133  }
5134  }
5135  if (places[i] == &globals)
5137  }
5138  if (s == &not_found || s == NULL)
5139  *ret = NULL;
5140  else {
5141  if (s != workspace)
5142  ast_copy_string(workspace, s, workspacelen);
5143  *ret = workspace;
5144  if (need_substring)
5145  *ret = substring(*ret, offset, length, workspace, workspacelen);
5146  }
5147 }
5148 
5149 static void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count)
5150 {
5151  /* Substitutes variables into cp2, based on string cp1, and assuming cp2 to be
5152  zero-filled */
5153  char *cp4;
5154  const char *tmp, *whereweare;
5155  int length, offset, offset2, isfunction;
5156  char *workspace = NULL;
5157  char *ltmp = NULL, *var = NULL;
5158  char *nextvar, *nextexp, *nextthing;
5159  char *vars, *vare;
5160  int pos, brackets, needsub, len;
5161 
5162  *cp2 = 0; /* just in case there's nothing to do */
5163  whereweare=tmp=cp1;
5164  while (!ast_strlen_zero(whereweare) && count) {
5165  /* Assume we're copying the whole remaining string */
5166  pos = strlen(whereweare);
5167  nextvar = NULL;
5168  nextexp = NULL;
5169  nextthing = strchr(whereweare, '$');
5170  if (nextthing) {
5171  switch (nextthing[1]) {
5172  case '{':
5173  nextvar = nextthing;
5174  pos = nextvar - whereweare;
5175  break;
5176  case '[':
5177  nextexp = nextthing;
5178  pos = nextexp - whereweare;
5179  break;
5180  }
5181  }
5182 
5183  if (pos) {
5184  /* Can't copy more than 'count' bytes */
5185  if (pos > count)
5186  pos = count;
5187 
5188  /* Copy that many bytes */
5189  memcpy(cp2, whereweare, pos);
5190 
5191  count -= pos;
5192  cp2 += pos;
5193  whereweare += pos;
5194  *cp2 = 0;
5195  }
5196 
5197  if (nextvar) {
5198  /* We have a variable. Find the start and end, and determine
5199  if we are going to have to recursively call ourselves on the
5200  contents */
5201  vars = vare = nextvar + 2;
5202  brackets = 1;
5203  needsub = 0;
5204 
5205  /* Find the end of it */
5206  while (brackets && *vare) {
5207  if ((vare[0] == '$') && (vare[1] == '{')) {
5208  needsub++;
5209  } else if (vare[0] == '{') {
5210  brackets++;
5211  } else if (vare[0] == '}') {
5212  brackets--;
5213  } else if ((vare[0] == '$') && (vare[1] == '['))
5214  needsub++;
5215  vare++;
5216  }
5217  if (brackets)
5218  ast_log(LOG_NOTICE, "Error in extension logic (missing '}' in '%s')\n", cp1);
5219  len = vare - vars - 1;
5220 
5221  /* Skip totally over variable string */
5222  whereweare += (len + 3);
5223 
5224  if (!var)
5225  var = alloca(VAR_BUF_SIZE);
5226 
5227  /* Store variable name (and truncate) */
5228  ast_copy_string(var, vars, len + 1);
5229 
5230  /* Substitute if necessary */
5231  if (needsub) {
5232  if (!ltmp)
5233  ltmp = alloca(VAR_BUF_SIZE);
5234 
5235  memset(ltmp, 0, VAR_BUF_SIZE);
5236  pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1);
5237  vars = ltmp;
5238  } else {
5239  vars = var;
5240  }
5241 
5242  if (!workspace)
5243  workspace = alloca(VAR_BUF_SIZE);
5244 
5245  workspace[0] = '\0';
5246 
5247  parse_variable_name(vars, &offset, &offset2, &isfunction);
5248  if (isfunction) {
5249  /* Evaluate function */
5250  cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
5251  if (option_debug)
5252  ast_log(LOG_DEBUG, "Function result is '%s'\n", cp4 ? cp4 : "(null)");
5253  } else {
5254  /* Retrieve variable value */
5255  pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp);
5256  }
5257  if (cp4) {
5258  cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE);
5259 
5260  length = strlen(cp4);
5261  if (length > count)
5262  length = count;
5263  memcpy(cp2, cp4, length);
5264  count -= length;
5265  cp2 += length;
5266  *cp2 = 0;
5267  }
5268  } else if (nextexp) {
5269  /* We have an expression. Find the start and end, and determine
5270  if we are going to have to recursively call ourselves on the
5271  contents */
5272  vars = vare = nextexp + 2;
5273  brackets = 1;
5274  needsub = 0;
5275 
5276  /* Find the end of it */
5277  while (brackets && *vare) {
5278  if ((vare[0] == '$') && (vare[1] == '[')) {
5279  needsub++;
5280  brackets++;
5281  vare++;
5282  } else if (vare[0] == '[') {
5283  brackets++;
5284  } else if (vare[0] == ']') {
5285  brackets--;
5286  } else if ((vare[0] == '$') && (vare[1] == '{')) {
5287  needsub++;
5288  vare++;
5289  }
5290  vare++;
5291  }
5292  if (brackets)
5293  ast_log(LOG_NOTICE, "Error in extension logic (missing ']')\n");
5294  len = vare - vars - 1;
5295 
5296  /* Skip totally over expression */
5297  whereweare += (len + 3);
5298 
5299  if (!var)
5300  var = alloca(VAR_BUF_SIZE);
5301 
5302  /* Store variable name (and truncate) */
5303  ast_copy_string(var, vars, len + 1);
5304 
5305  /* Substitute if necessary */
5306  if (needsub) {
5307  if (!ltmp)
5308  ltmp = alloca(VAR_BUF_SIZE);
5309 
5310  memset(ltmp, 0, VAR_BUF_SIZE);
5311  pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1);
5312  vars = ltmp;
5313  } else {
5314  vars = var;
5315  }
5316 
5317  length = ast_expr(vars, cp2, count, NULL);
5318 
5319  if (length) {
5320  if (option_debug)
5321  ast_log(LOG_DEBUG, "Expression result is '%s'\n", cp2);
5322  count -= length;
5323  cp2 += length;
5324  *cp2 = 0;
5325  }
5326  } else
5327  break;
5328  }
5329 }
5330 
5331 static void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count)
5332 {
5333  pbx_substitute_variables_helper_full(c, NULL, cp1, cp2, count);
5334 }
5335 
5336 
5337 static int pbx_load_config(const char *config_file);
5338 
5339 static int pbx_load_config(const char *config_file)
5340 {
5341  struct ast_config *cfg;
5342  char *end;
5343  char *label;
5344  char realvalue[256];
5345  int lastpri = -2;
5346  struct ast_context *con;
5347  struct ast_variable *v;
5348  const char *cxt;
5349  const char *aft;
5350 
5351  cfg = localized_config_load(config_file);
5352  if (!cfg)
5353  return 0;
5354 
5355  /* Use existing config to populate the PBX table */
5356  static_config = ast_true(ast_variable_retrieve(cfg, "general", "static"));
5357  write_protect_config = ast_true(ast_variable_retrieve(cfg, "general", "writeprotect"));
5358  if ((aft = ast_variable_retrieve(cfg, "general", "autofallthrough")))
5359  autofallthrough_config = ast_true(aft);
5360  clearglobalvars_config = ast_true(ast_variable_retrieve(cfg, "general", "clearglobalvars"));
5361 
5362  if ((cxt = ast_variable_retrieve(cfg, "general", "userscontext")))
5363  ast_copy_string(userscontext, cxt, sizeof(userscontext));
5364  else
5365  ast_copy_string(userscontext, "default", sizeof(userscontext));
5366 
5367  for (v = ast_variable_browse(cfg, "globals"); v; v = v->next) {
5368  memset(realvalue, 0, sizeof(realvalue));
5369  pbx_substitute_variables_helper(NULL, v->value, realvalue, sizeof(realvalue) - 1);
5370  pbx_builtin_setvar_helper(NULL, v->name, realvalue);
5371  }
5372  for (cxt = NULL; (cxt = ast_category_browse(cfg, cxt)); ) {
5373  /* All categories but "general" or "globals" are considered contexts */
5374  if (!strcasecmp(cxt, "general") || !strcasecmp(cxt, "globals"))
5375  continue;
5376  con=ast_context_find_or_create(&local_contexts,NULL,cxt, global_registrar);
5377  if (con == NULL)
5378  continue;
5379 
5380  for (v = ast_variable_browse(cfg, cxt); v; v = v->next) {
5381  if (!strcasecmp(v->name, "exten")) {
5382  char *tc = ast_strdup(v->value);
5383  if (tc) {
5384  int ipri = -2;
5385  char realext[256]="";
5386  char *plus, *firstp, *firstc;
5387  char *pri, *appl, *data, *cidmatch;
5388  char *stringp = tc;
5389  char *ext = strsep(&stringp, ",");
5390  if (!ext)
5391  ext="";
5392  pbx_substitute_variables_helper(NULL, ext, realext, sizeof(realext) - 1);
5393  cidmatch = strchr(realext, '/');
5394  if (cidmatch) {
5395  *cidmatch++ = '\0';
5396  ast_shrink_phone_number(cidmatch);
5397  }
5398  pri = strsep(&stringp, ",");
5399  if (!pri)
5400  pri="";
5401  label = strchr(pri, '(');
5402  if (label) {
5403  *label++ = '\0';
5404  end = strchr(label, ')');
5405  if (end)
5406  *end = '\0';
5407  else
5408  ast_log(LOG_WARNING, "Label missing trailing ')' at line %d\n", v->lineno);
5409  }
5410  plus = strchr(pri, '+');
5411  if (plus)
5412  *plus++ = '\0';
5413  if (!strcmp(pri,"hint"))
5414  ipri=PRIORITY_HINT;
5415  else if (!strcmp(pri, "next") || !strcmp(pri, "n")) {
5416  if (lastpri > -2)
5417  ipri = lastpri + 1;
5418  else
5419  ast_log(LOG_WARNING, "Can't use 'next' priority on the first entry!\n");
5420  } else if (!strcmp(pri, "same") || !strcmp(pri, "s")) {
5421  if (lastpri > -2)
5422  ipri = lastpri;
5423  else
5424  ast_log(LOG_WARNING, "Can't use 'same' priority on the first entry!\n");
5425  } else if (sscanf(pri, "%30d", &ipri) != 1 &&
5426  (ipri = ast_findlabel_extension2(NULL, con, realext, pri, cidmatch)) < 1) {
5427  ast_log(LOG_WARNING, "Invalid priority/label '%s' at line %d\n", pri, v->lineno);
5428  ipri = 0;
5429  }
5430  appl = S_OR(stringp, "");
5431  /* Find the first occurrence of either '(' or ',' */
5432  firstc = strchr(appl, ',');
5433  firstp = strchr(appl, '(');
5434  if (firstc && (!firstp || firstc < firstp)) {
5435  /* comma found, no parenthesis */
5436  /* or both found, but comma found first */
5437  appl = strsep(&stringp, ",");
5438  data = stringp;
5439  } else if (!firstc && !firstp) {
5440  /* Neither found */
5441  data = "";
5442  } else {
5443  /* Final remaining case is parenthesis found first */
5444  appl = strsep(&stringp, "(");
5445  data = stringp;
5446  end = strrchr(data, ')');
5447  if ((end = strrchr(data, ')'))) {
5448  *end = '\0';
5449  } else {
5450  ast_log(LOG_WARNING, "No closing parenthesis found? '%s(%s'\n", appl, data);
5451  }
5452  ast_process_quotes_and_slashes(data, ',', '|');
5453  }
5454 
5455  if (!data)
5456  data="";
5457  appl = ast_skip_blanks(appl);
5458  if (ipri) {
5459  if (plus)
5460  ipri += atoi(plus);
5461  lastpri = ipri;
5462  if (!ast_opt_dont_warn && !strcmp(realext, "_."))
5463  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);
5464  if (ast_add_extension2(con, 0, realext, ipri, label, cidmatch, appl, strdup(data), ast_free_ptr, global_registrar)) {
5465  ast_log(LOG_WARNING, "Unable to register extension at line %d\n", v->lineno);
5466  }
5467  }
5468  free(tc);
5469  }
5470  } else if (!strcasecmp(v->name, "include")) {
5471  memset(realvalue, 0, sizeof(realvalue));
5472  pbx_substitute_variables_helper(NULL, v->value, realvalue, sizeof(realvalue) - 1);
5473  if (ast_context_add_include2(con, realvalue, global_registrar))
5474  ast_log(LOG_WARNING, "Unable to include context '%s' in context '%s'\n", v->value, cxt);
5475  } else if (!strcasecmp(v->name, "ignorepat")) {
5476  memset(realvalue, 0, sizeof(realvalue));
5477  pbx_substitute_variables_helper(NULL, v->value, realvalue, sizeof(realvalue) - 1);
5478  if (ast_context_add_ignorepat2(con, realvalue, global_registrar))
5479  ast_log(LOG_WARNING, "Unable to include ignorepat '%s' in context '%s'\n", v->value, cxt);
5480  } else if (!strcasecmp(v->name, "switch") || !strcasecmp(v->name, "lswitch") || !strcasecmp(v->name, "eswitch")) {
5481  char *stringp= realvalue;
5482  char *appl, *data;
5483 
5484  memset(realvalue, 0, sizeof(realvalue));
5485  if (!strcasecmp(v->name, "switch"))
5486  pbx_substitute_variables_helper(NULL, v->value, realvalue, sizeof(realvalue) - 1);
5487  else
5488  ast_copy_string(realvalue, v->value, sizeof(realvalue));
5489  appl = strsep(&stringp, "/");
5490  data = strsep(&stringp, ""); /* XXX what for ? */
5491  if (!data)
5492  data = "";
5493  if (ast_context_add_switch2(con, appl, data, !strcasecmp(v->name, "eswitch"), global_registrar))
5494  ast_log(LOG_WARNING, "Unable to include switch '%s' in context '%s'\n", v->value, cxt);
5495  } else {
5496  ast_log(LOG_WARNING, "==!!== Unknown directive: %s at line %d -- IGNORING!!!\n", v->name, v->lineno);
5497  }
5498  }
5499  }
5500  ast_config_destroy(cfg);
5501  return 1;
5502 }
5503 
5504 static void __ast_context_destroy(struct ast_context *con, const char *registrar)
5505 {
5506  struct ast_context *tmp, *tmpl=NULL;
5507  struct ast_include *tmpi;
5508  struct ast_sw *sw;
5509  struct ast_exten *e, *el, *en;
5510  struct ast_ignorepat *ipi;
5511 
5512  for (tmp = contexts; tmp; ) {
5513  struct ast_context *next; /* next starting point */
5514  for (; tmp; tmpl = tmp, tmp = tmp->next) {
5515  if (option_debug)
5516  ast_log(LOG_DEBUG, "check ctx %s %s\n", tmp->name, tmp->registrar);
5517  if ( (!registrar || !strcasecmp(registrar, tmp->registrar)) &&
5518  (!con || !strcasecmp(tmp->name, con->name)) )
5519  break; /* found it */
5520  }
5521  if (!tmp) /* no