46 #define ASTMM_LIBC ASTMM_IGNORE
57 #include <sys/types.h>
59 #include <sys/resource.h>
65 #if !defined(SOLARIS) && !defined(__CYGWIN__)
72 #include <sys/param.h>
75 static void ast_log(
int level,
const char *
file,
int line,
const char *
function,
const char *fmt, ...) __attribute__((
format(printf, 5, 6)));
78 #define AST_API_MODULE 1
93 #define EVENTLOG "event_log"
94 #define QUEUELOG "queue_log"
96 #define DEBUG_M(a) { \
100 #define VERBOSE_PREFIX_1 " "
101 #define VERBOSE_PREFIX_2 " == "
102 #define VERBOSE_PREFIX_3 " -- "
103 #define VERBOSE_PREFIX_4 " > "
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)));
115 #define _A_ __FILE__, __LINE__, __PRETTY_FUNCTION__
120 #define __LOG_DEBUG 0
121 #define LOG_DEBUG __LOG_DEBUG, _A_
126 #define __LOG_EVENT 1
127 #define LOG_EVENT __LOG_EVENT, _A_
132 #define __LOG_NOTICE 2
133 #define LOG_NOTICE __LOG_NOTICE, _A_
138 #define __LOG_WARNING 3
139 #define LOG_WARNING __LOG_WARNING, _A_
144 #define __LOG_ERROR 4
145 #define LOG_ERROR __LOG_ERROR, _A_
150 #define __LOG_VERBOSE 5
151 #define LOG_VERBOSE __LOG_VERBOSE, _A_
157 #define LOG_DTMF __LOG_DTMF, _A_
160 #define _ASTERISK_LOCK_H
162 #ifndef HAVE_MTX_PROFILE
163 #define __MTX_PROF(a) return pthread_mutex_lock((a))
167 #define __MTX_PROF(a) do { \
170 ast_mark(mtx_prof, 1); \
171 i = pthread_mutex_trylock((a)); \
172 ast_mark(mtx_prof, 0); \
176 return pthread_mutex_lock((a)); \
180 #define AST_PTHREADT_NULL (pthread_t) -1
181 #define AST_PTHREADT_STOP (pthread_t) -2
183 #if defined(SOLARIS) || defined(BSD)
184 #define AST_MUTEX_INIT_W_CONSTRUCTORS
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
193 #define PTHREAD_MUTEX_INIT_VALUE PTHREAD_MUTEX_INITIALIZER
194 #define AST_MUTEX_KIND PTHREAD_MUTEX_RECURSIVE
199 #define log_mutex_error(canlog, ...) do { if (canlog) ast_log(LOG_ERROR, __VA_ARGS__); else fprintf(stderr, __VA_ARGS__); } while (0)
202 #define DO_THREAD_CRASH do { *((int *)(0)) = 1; } while(0)
204 #define DO_THREAD_CRASH do { } while (0)
207 #define AST_MUTEX_INIT_VALUE { PTHREAD_MUTEX_INIT_VALUE, { NULL }, { 0 }, 0, { NULL }, { 0 } }
209 #define AST_MAX_REENTRANCY 10
214 unsigned int track:1;
228 static void __attribute__((constructor)) init_empty_mutex(
void)
230 memset(&empty_mutex, 0,
sizeof(empty_mutex));
233 static inline int __ast_pthread_mutex_init_attr(
const char *filename,
int lineno,
const char *func,
235 pthread_mutexattr_t *attr)
237 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
238 int canlog = strcmp(filename,
"logger.c");
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);
252 t->file[0] = filename;
253 t->lineno[0] = lineno;
264 static pthread_mutexattr_t attr;
266 pthread_mutexattr_init(&attr);
269 return __ast_pthread_mutex_init_attr(filename, lineno, func, mutex_name, t, &attr);
271 #define ast_mutex_init(pmutex) __ast_pthread_mutex_init(__FILE__, __LINE__, __PRETTY_FUNCTION__, #pmutex, pmutex)
277 int canlog = strcmp(filename,
"logger.c");
279 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
281 log_mutex_error(canlog,
"%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
282 filename, lineno, func, mutex_name);
292 log_mutex_error(canlog,
"%s line %d (%s): Error: attempt to destroy invalid mutex '%s'.\n",
293 filename, lineno, func, mutex_name);
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);
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
310 t->file[0] = filename;
311 t->lineno[0] = lineno;
321 int canlog = strcmp(filename,
"logger.c");
323 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
325 log_mutex_error(canlog,
"%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
326 filename, lineno, func, mutex_name);
331 #ifdef DETECT_DEADLOCKS
333 time_t seconds = time(
NULL);
336 #ifdef HAVE_MTX_PROFILE
340 #ifdef HAVE_MTX_PROFILE
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);
354 }
while (res == EBUSY);
357 #ifdef HAVE_MTX_PROFILE
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();
374 log_mutex_error(canlog,
"%s line %d (%s): '%s' really deep reentrancy!\n",
375 filename, lineno, func, mutex_name);
378 log_mutex_error(canlog,
"%s line %d (%s): Error obtaining mutex: %s\n",
379 filename, lineno, func, strerror(
errno));
390 int canlog = strcmp(filename,
"logger.c");
392 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
394 log_mutex_error(canlog,
"%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
395 filename, lineno, func, mutex_name);
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();
408 log_mutex_error(canlog,
"%s line %d (%s): '%s' really deep reentrancy!\n",
409 filename, lineno, func, mutex_name);
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);
423 int canlog = strcmp(filename,
"logger.c");
425 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
427 log_mutex_error(canlog,
"%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
428 filename, lineno, func, mutex_name);
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);
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);
447 t->file[t->reentrancy] =
NULL;
448 t->lineno[t->reentrancy] = 0;
449 t->func[t->reentrancy] =
NULL;
450 t->thread[t->reentrancy] = 0;
454 log_mutex_error(canlog,
"%s line %d (%s): Error releasing mutex: %s\n",
455 filename, lineno, func, strerror(res));
467 #define AST_MUTEX_INIT_VALUE ((ast_mutex_t) PTHREAD_MUTEX_INIT_VALUE)
471 pthread_mutexattr_t attr;
473 pthread_mutexattr_init(&attr);
479 #define ast_pthread_mutex_init(pmutex,a) pthread_mutex_init(pmutex,a)
485 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
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) \
492 ast_mutex_init(&mutex); \
496 #define __AST_MUTEX_DEFINE(scope, mutex) \
497 scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE
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
504 #define AST_MUTEX_DEFINE_STATIC(mutex) __AST_MUTEX_DEFINE(static, mutex)
506 #define AST_MUTEX_INITIALIZER __use_AST_MUTEX_DEFINE_STATIC_rather_than_AST_MUTEX_INITIALIZER__
508 #define gethostbyname __gethostbyname__is__not__reentrant__use__ast_gethostbyname__instead__
511 #define pthread_create __use_ast_pthread_create_instead__
518 pthread_rwlockattr_t attr;
520 pthread_rwlockattr_init(&attr);
522 #ifdef HAVE_PTHREAD_RWLOCK_PREFER_WRITER_NP
523 pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NP);
526 return pthread_rwlock_init(prwlock, &attr);
531 return pthread_rwlock_destroy(prwlock);
536 return pthread_rwlock_unlock(prwlock);
541 return pthread_rwlock_rdlock(prwlock);
546 return pthread_rwlock_wrlock(prwlock);
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) \
556 ast_rwlock_init(&rwlock); \
558 static void __attribute__((destructor)) fini_##rwlock(void) \
560 ast_rwlock_destroy(&rwlock); \
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
568 #define AST_RWLOCK_DEFINE_STATIC(rwlock) __AST_RWLOCK_DEFINE(static, rwlock)
580 #if defined(HAVE_OSX_ATOMICS)
581 #include "libkern/OSAtomic.h"
589 #if defined(HAVE_GCC_ATOMICS)
592 return __sync_fetch_and_add(p, v);
594 #elif defined(HAVE_OSX_ATOMICS) && (
SIZEOF_INT == 4)
597 return OSAtomicAdd32(v, (
int32_t *) p);
599 #elif defined(HAVE_OSX_ATOMICS) && (
SIZEOF_INT == 8)
602 return OSAtomicAdd64(v, (int64_t *) p);
603 #elif defined (__i386__) || defined(__x86_64__)
607 " lock xaddl %0, %1 ; "
614 static int ast_atomic_fetchadd_int_slow(
volatile int *p,
int v)
623 return ast_atomic_fetchadd_int_slow(p, v);
633 return __sync_sub_and_fetch(p, 1) == 0;
635 #elif defined(HAVE_OSX_ATOMICS) && (
SIZEOF_INT == 4)
638 return OSAtomicAdd32( -1, (
int32_t *) p) == 0;
640 #elif defined(HAVE_OSX_ATOMICS) && (
SIZEOF_INT == 8)
643 return OSAtomicAdd64( -1, (int64_t *) p) == 0;
652 #ifdef DEBUG_CHANNEL_LOCKS
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)); \
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); \
689 (p)->flags |= (flag); \
691 (p)->flags &= ~(flag); \
696 #define MAX_NESTED_COMMENTS 128
697 #define COMMENT_START ";--"
698 #define COMMENT_END "--;"
699 #define COMMENT_META ';'
700 #define COMMENT_TAG '-'
740 int siz = strlen(
str);
767 int siz = strlen(
str);
796 .sa_flags = SA_RESTART,
832 #ifdef HAVE_WORKING_FORK
838 #if defined(HAVE_WORKING_FORK) || defined(HAVE_WORKING_VFORK)
841 #ifdef HAVE_WORKING_FORK
848 #ifdef HAVE_WORKING_FORK
850 for (x = STDERR_FILENO + 1; x < 4096; x++)
853 execl(
"/bin/sh",
"/bin/sh",
"-c", s, (
char *)
NULL);
855 }
else if (pid > 0) {
857 res = waitpid(pid, &
status, 0);
861 }
else if (
errno != EINTR)
880 strcpy(x->
cmt, buffer);
895 #define MAX_INCLUDE_LEVEL 10
936 typedef int realtime_update(
const char *database,
const char *
table,
const char *keyfield,
const char *entity, va_list ap);
954 return (!s || (*s ==
'\0'));
957 #define S_OR(a, b) (!ast_strlen_zero(a) ? (a) : (b))
962 while (*src && size) {
966 if (__builtin_expect(!size, 0))
992 work += strlen(work) - 1;
999 while ((work >=
str) && *work < 33)
1058 int name_len = strlen(
name) + 1;
1059 size_t value_len = strlen(
value) + 1;
1060 size_t filename_len = strlen(filename) + 1;
1062 if ((variable =
ast_calloc(1, name_len + value_len + filename_len +
sizeof(*variable)))) {
1064 variable->
value = variable->
stuff + name_len;
1065 variable->
file = variable->
value + value_len;
1087 ast_log(
LOG_WARNING,
"'%s', line %d: Same File included more than once! This data will be saved in %s if saved back to disk.\n", from_file, from_lineno, real_included_file_name);
1089 *real_included_file_name = 0;
1099 inc->
exec = is_exec;
1105 conf->includes = inc;
1116 int from_len = strlen(from_file);
1117 int to_len = strlen(to_file);
1119 if (strcmp(from_file, to_file) == 0)
1131 for (incl =
conf->includes; incl; incl=incl->
next) {
1133 if (from_len >= to_len)
1141 for (cat =
conf->root; cat; cat = cat->
next) {
1142 if (strcmp(cat->
file,from_file) == 0) {
1143 if (from_len >= to_len)
1144 strcpy(cat->
file, to_file);
1150 for (v = cat->
root; v; v = v->
next) {
1151 if (strcmp(v->
file,from_file) == 0) {
1152 if (from_len >= to_len)
1153 strcpy(v->
file, to_file);
1184 category->
root = variable;
1185 category->
last = variable;
1197 for (cat =
config->root; cat; cat = cat->
next) {
1202 for (cat =
config->root; cat; cat = cat->
next) {
1219 if (category &&
config->last_browse && (
config->last_browse->name == category))
1220 cat =
config->last_browse;
1233 if (!strcasecmp(variable, v->
name))
1239 for (cat =
config->root; cat; cat = cat->
next)
1240 for (v = cat->
root; v; v = v->
next)
1241 if (!strcasecmp(variable, v->
name))
1253 new->lineno = old->
lineno;
1254 new->object = old->
object;
1277 for (incl=incls; incl; incl = inclnext) {
1278 inclnext = incl->
next;
1358 #define AST_CACHE_DIR_LEN 512
1359 #define AST_FILENAME_MAX 80
1362 #define AST_DEFAULT_OPTIONS AST_OPT_FLAG_TRANSCODE_VIA_SLIN
1366 #define ast_opt_exec_includes ast_test_flag(&ast_options, AST_OPT_FLAG_EXEC_INCLUDES)
1367 #define ast_opt_no_fork ast_test_flag(&ast_options, AST_OPT_FLAG_NO_FORK)
1368 #define ast_opt_quiet ast_test_flag(&ast_options, AST_OPT_FLAG_QUIET)
1369 #define ast_opt_console ast_test_flag(&ast_options, AST_OPT_FLAG_CONSOLE)
1370 #define ast_opt_high_priority ast_test_flag(&ast_options, AST_OPT_FLAG_HIGH_PRIORITY)
1371 #define ast_opt_init_keys ast_test_flag(&ast_options, AST_OPT_FLAG_INIT_KEYS)
1372 #define ast_opt_remote ast_test_flag(&ast_options, AST_OPT_FLAG_REMOTE)
1373 #define ast_opt_exec ast_test_flag(&ast_options, AST_OPT_FLAG_EXEC)
1374 #define ast_opt_no_color ast_test_flag(&ast_options, AST_OPT_FLAG_NO_COLOR)
1375 #define ast_fully_booted ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)
1376 #define ast_opt_transcode_via_slin ast_test_flag(&ast_options, AST_OPT_FLAG_TRANSCODE_VIA_SLIN)
1377 #define ast_opt_priority_jumping ast_test_flag(&ast_options, AST_OPT_FLAG_PRIORITY_JUMPING)
1378 #define ast_opt_dump_core ast_test_flag(&ast_options, AST_OPT_FLAG_DUMP_CORE)
1379 #define ast_opt_cache_record_files ast_test_flag(&ast_options, AST_OPT_FLAG_CACHE_RECORD_FILES)
1380 #define ast_opt_timestamp ast_test_flag(&ast_options, AST_OPT_FLAG_TIMESTAMP)
1381 #define ast_opt_override_config ast_test_flag(&ast_options, AST_OPT_FLAG_OVERRIDE_CONFIG)
1382 #define ast_opt_reconnect ast_test_flag(&ast_options, AST_OPT_FLAG_RECONNECT)
1383 #define ast_opt_transmit_silence ast_test_flag(&ast_options, AST_OPT_FLAG_TRANSMIT_SILENCE)
1384 #define ast_opt_dont_warn ast_test_flag(&ast_options, AST_OPT_FLAG_DONT_WARN)
1385 #define ast_opt_always_fork ast_test_flag(&ast_options, AST_OPT_FLAG_ALWAYS_FORK)
1386 #define ast_opt_mute ast_test_flag(&ast_options, AST_OPT_FLAG_MUTE)
1413 #define AST_RWLIST_WRLOCK(head) \
1414 ast_rwlock_wrlock(&(head)->lock)
1424 #define AST_RWLIST_RDLOCK(head) \
1425 ast_rwlock_rdlock(&(head)->lock)
1435 #define AST_RWLIST_UNLOCK(head) \
1436 ast_rwlock_unlock(&(head)->lock)
1457 #define AST_LIST_HEAD(name, type) \
1459 struct type *first; \
1460 struct type *last; \
1483 #define AST_RWLIST_HEAD(name, type) \
1485 struct type *first; \
1486 struct type *last; \
1487 ast_rwlock_t lock; \
1509 #define AST_LIST_HEAD_NOLOCK(name, type) \
1511 struct type *first; \
1512 struct type *last; \
1518 #define AST_LIST_HEAD_INIT_VALUE { \
1521 .lock = AST_MUTEX_INIT_VALUE, \
1527 #define AST_RWLIST_HEAD_INIT_VALUE { \
1530 .lock = AST_RWLOCK_INIT_VALUE, \
1536 #define AST_LIST_HEAD_NOLOCK_INIT_VALUE { \
1558 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
1559 #define AST_LIST_HEAD_STATIC(name, type) \
1561 struct type *first; \
1562 struct type *last; \
1565 static void __attribute__((constructor)) init_##name(void) \
1567 AST_LIST_HEAD_INIT(&name); \
1569 static void __attribute__((destructor)) fini_##name(void) \
1571 AST_LIST_HEAD_DESTROY(&name); \
1573 struct __dummy_##name
1575 #define AST_LIST_HEAD_STATIC(name, type) \
1577 struct type *first; \
1578 struct type *last; \
1580 } name = AST_LIST_HEAD_INIT_VALUE
1600 #ifndef AST_RWLOCK_INIT_VALUE
1601 #define AST_RWLIST_HEAD_STATIC(name, type) \
1603 struct type *first; \
1604 struct type *last; \
1605 ast_rwlock_t lock; \
1607 static void __attribute__((constructor)) init_##name(void) \
1609 AST_RWLIST_HEAD_INIT(&name); \
1611 static void __attribute__((destructor)) fini_##name(void) \
1613 AST_RWLIST_HEAD_DESTROY(&name); \
1615 struct __dummy_##name
1617 #define AST_RWLIST_HEAD_STATIC(name, type) \
1619 struct type *first; \
1620 struct type *last; \
1621 ast_rwlock_t lock; \
1622 } name = AST_RWLIST_HEAD_INIT_VALUE
1630 #define AST_LIST_HEAD_NOLOCK_STATIC(name, type) \
1632 struct type *first; \
1633 struct type *last; \
1634 } name = AST_LIST_HEAD_NOLOCK_INIT_VALUE
1644 #define AST_LIST_HEAD_SET(head, entry) do { \
1645 (head)->first = (entry); \
1646 (head)->last = (entry); \
1647 ast_mutex_init(&(head)->lock); \
1658 #define AST_RWLIST_HEAD_SET(head, entry) do { \
1659 (head)->first = (entry); \
1660 (head)->last = (entry); \
1661 ast_rwlock_init(&(head)->lock); \
1672 #define AST_LIST_HEAD_SET_NOLOCK(head, entry) do { \
1673 (head)->first = (entry); \
1674 (head)->last = (entry); \
1694 #define AST_LIST_ENTRY(type) \
1696 struct type *next; \
1699 #define AST_RWLIST_ENTRY AST_LIST_ENTRY
1705 #define AST_LIST_FIRST(head) ((head)->first)
1707 #define AST_RWLIST_FIRST AST_LIST_FIRST
1713 #define AST_LIST_LAST(head) ((head)->last)
1715 #define AST_RWLIST_LAST AST_LIST_LAST
1723 #define AST_LIST_NEXT(elm, field) ((elm)->field.next)
1725 #define AST_RWLIST_NEXT AST_LIST_NEXT
1733 #define AST_LIST_EMPTY(head) (AST_LIST_FIRST(head) == NULL)
1735 #define AST_RWLIST_EMPTY AST_LIST_EMPTY
1773 #define AST_LIST_TRAVERSE(head,var,field) \
1774 for((var) = (head)->first; (var); (var) = (var)->field.next)
1776 #define AST_RWLIST_TRAVERSE AST_LIST_TRAVERSE
1811 #define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field) { \
1812 typeof((head)->first) __list_next; \
1813 typeof((head)->first) __list_prev = NULL; \
1814 typeof((head)->first) __new_prev = NULL; \
1815 for ((var) = (head)->first, __new_prev = (var), \
1816 __list_next = (var) ? (var)->field.next : NULL; \
1818 __list_prev = __new_prev, (var) = __list_next, \
1819 __new_prev = (var), \
1820 __list_next = (var) ? (var)->field.next : NULL \
1823 #define AST_RWLIST_TRAVERSE_SAFE_BEGIN AST_LIST_TRAVERSE_SAFE_BEGIN
1836 #define AST_LIST_REMOVE_CURRENT(head, field) \
1837 __new_prev->field.next = NULL; \
1838 __new_prev = __list_prev; \
1840 __list_prev->field.next = __list_next; \
1842 (head)->first = __list_next; \
1844 (head)->last = __list_prev;
1846 #define AST_RWLIST_REMOVE_CURRENT AST_LIST_REMOVE_CURRENT
1858 #define AST_LIST_INSERT_BEFORE_CURRENT(head, elm, field) do { \
1859 if (__list_prev) { \
1860 (elm)->field.next = __list_prev->field.next; \
1861 __list_prev->field.next = elm; \
1863 (elm)->field.next = (head)->first; \
1864 (head)->first = (elm); \
1866 __new_prev = (elm); \
1869 #define AST_RWLIST_INSERT_BEFORE_CURRENT AST_LIST_INSERT_BEFORE_CURRENT
1874 #define AST_LIST_TRAVERSE_SAFE_END }
1876 #define AST_RWLIST_TRAVERSE_SAFE_END AST_LIST_TRAVERSE_SAFE_END
1885 #define AST_LIST_HEAD_INIT(head) { \
1886 (head)->first = NULL; \
1887 (head)->last = NULL; \
1888 ast_mutex_init(&(head)->lock); \
1898 #define AST_RWLIST_HEAD_INIT(head) { \
1899 (head)->first = NULL; \
1900 (head)->last = NULL; \
1901 ast_rwlock_init(&(head)->lock); \
1912 #define AST_RWLIST_HEAD_DESTROY(head) { \
1913 (head)->first = NULL; \
1914 (head)->last = NULL; \
1915 ast_rwlock_destroy(&(head)->lock); \
1926 #define AST_LIST_HEAD_INIT_NOLOCK(head) { \
1927 (head)->first = NULL; \
1928 (head)->last = NULL; \
1940 #define AST_LIST_INSERT_AFTER(head, listelm, elm, field) do { \
1941 (elm)->field.next = (listelm)->field.next; \
1942 (listelm)->field.next = (elm); \
1943 if ((head)->last == (listelm)) \
1944 (head)->last = (elm); \
1947 #define AST_RWLIST_INSERT_AFTER AST_LIST_INSERT_AFTER
1956 #define AST_LIST_INSERT_HEAD(head, elm, field) do { \
1957 (elm)->field.next = (head)->first; \
1958 (head)->first = (elm); \
1959 if (!(head)->last) \
1960 (head)->last = (elm); \
1963 #define AST_RWLIST_INSERT_HEAD AST_LIST_INSERT_HEAD
1976 #define AST_LIST_INSERT_TAIL(head, elm, field) do { \
1977 if (!(head)->first) { \
1978 (head)->first = (elm); \
1979 (head)->last = (elm); \
1981 (head)->last->field.next = (elm); \
1982 (head)->last = (elm); \
1986 #define AST_RWLIST_INSERT_TAIL AST_LIST_INSERT_TAIL
1995 #define AST_LIST_APPEND_LIST(head, list, field) do { \
1996 if (!(head)->first) { \
1997 (head)->first = (list)->first; \
1998 (head)->last = (list)->last; \
2000 (head)->last->field.next = (list)->first; \
2001 (head)->last = (list)->last; \
2005 #define AST_RWLIST_APPEND_LIST AST_LIST_APPEND_LIST
2016 #define AST_LIST_REMOVE_HEAD(head, field) ({ \
2017 typeof((head)->first) cur = (head)->first; \
2019 (head)->first = cur->field.next; \
2020 cur->field.next = NULL; \
2021 if ((head)->last == cur) \
2022 (head)->last = NULL; \
2027 #define AST_RWLIST_REMOVE_HEAD AST_LIST_REMOVE_HEAD
2037 #define AST_LIST_REMOVE(head, elm, field) do { \
2038 if ((head)->first == (elm)) { \
2039 (head)->first = (elm)->field.next; \
2040 if ((head)->last == (elm)) \
2041 (head)->last = NULL; \
2043 typeof(elm) curelm = (head)->first; \
2044 while (curelm && (curelm->field.next != (elm))) \
2045 curelm = curelm->field.next; \
2047 curelm->field.next = (elm)->field.next; \
2048 if ((head)->last == (elm)) \
2049 (head)->last = curelm; \
2052 (elm)->field.next = NULL; \
2055 #define AST_RWLIST_REMOVE AST_LIST_REMOVE
2078 #define AST_MAX_EXTENSION 80
2082 #define PRIORITY_HINT -1
2141 for (x=0; n[x]; x++) {
2160 if (!strchr(
"()", n[x]))
2177 if (
name[0] ==
'_') {
2194 static void ast_log(
int level,
const char *
file,
int line,
const char *
function,
const char *fmt, ...)
2199 printf(
"LOG: lev:%d file:%s line:%d func: %s ",
2200 level,
file, line,
function);
2211 printf(
"VERBOSE: ");
2220 char *dataPut = start;
2224 for (; *start; start++) {
2226 *dataPut++ = *start;
2229 if (*start ==
'\\') {
2231 }
else if (*start ==
'\'') {
2232 inQuotes = 1 - inQuotes;
2235 *dataPut++ = inQuotes ? *start : ((*start == find) ? replace_with : *start);
2239 if (start != dataPut)
2250 if (!strcasecmp(s,
"yes") ||
2251 !strcasecmp(s,
"true") ||
2252 !strcasecmp(s,
"y") ||
2253 !strcasecmp(s,
"t") ||
2254 !strcasecmp(s,
"1") ||
2255 !strcasecmp(s,
"on"))
2261 #define ONE_MILLION 1000000
2266 static struct timeval
tvfix(struct timeval
a)
2270 (
long)
a.tv_sec, (
long int)
a.tv_usec);
2273 }
else if (
a.tv_usec < 0) {
2275 (
long)
a.tv_sec, (
long int)
a.tv_usec);
2281 struct timeval
ast_tvadd(struct timeval
a, struct timeval
b);
2282 struct timeval
ast_tvadd(struct timeval
a, struct timeval
b)
2287 a.tv_sec +=
b.tv_sec;
2288 a.tv_usec +=
b.tv_usec;
2296 struct timeval
ast_tvsub(struct timeval
a, struct timeval
b);
2297 struct timeval
ast_tvsub(struct timeval
a, struct timeval
b)
2302 a.tv_sec -=
b.tv_sec;
2303 a.tv_usec -=
b.tv_usec;
2304 if (
a.tv_usec < 0) {
2319 #define VAR_BUF_SIZE 4096
2321 #define VAR_NORMAL 1
2322 #define VAR_SOFTTRAN 2
2323 #define VAR_HARDTRAN 3
2325 #define BACKGROUND_SKIP (1 << 0)
2326 #define BACKGROUND_NOANSWER (1 << 1)
2327 #define BACKGROUND_MATCHEXTEN (1 << 2)
2328 #define BACKGROUND_PLAYBACK (1 << 3)
2346 void (*
datad)(
void *);
2449 #define STATUS_NO_CONTEXT 1
2450 #define STATUS_NO_EXTENSION 2
2451 #define STATUS_NO_PRIORITY 3
2452 #define STATUS_NO_LABEL 4
2453 #define STATUS_SUCCESS 5
2458 int name_len = strlen(
name) + 1;
2459 int value_len = strlen(
value) + 1;
2461 if (!(
var =
ast_calloc(
sizeof(*
var) + name_len + value_len,
sizeof(
char)))) {
2466 var->value =
var->name + name_len;
2500 for (argc = 0; *scan && (argc < arraylen - 1); argc++) {
2502 for (; *scan; scan++) {
2505 else if (*scan ==
')') {
2508 }
else if (*scan ==
'"' && delim !=
'"') {
2511 memmove(scan, scan + 1, strlen(scan));
2513 }
else if (*scan ==
'\\') {
2515 memmove(scan, scan + 1, strlen(scan));
2516 }
else if ((*scan == delim) && !
paren && !
quote) {
2524 array[argc++] = scan;
2533 const char *nametail =
name;
2546 if (*nametail ==
'_') {
2548 if (*nametail ==
'_')
2553 if (strcasecmp(
ast_var_name(newvariable), nametail) == 0) {
2586 if ((argc > 1) && !strchr(argv[argc-1],
'=')) {
2588 if (strchr(argv[argc],
'g'))
2592 for (x = 0; x < argc; x++) {
2620 if (names && *s >
'9') {
2621 for (i = 0; names[i]; i++) {
2622 if (!strcasecmp(s, names[i])) {
2629 if (sscanf(s,
"%2d", &i) == 1 && i >= 1 && i <=
max) {
2639 static unsigned get_range(
char *src,
int max,
char *
const names[],
const char *msg)
2642 unsigned int mask = 0;
2647 return (1 <<
max) - 1;
2650 while ((part =
strsep(&src,
"&"))) {
2652 char *endpart = strchr(part,
'-');
2671 while (start !=
end) {
2675 mask |= (1 << start);
2685 char *endpart, *part;
2689 int minute_start, minute_end;
2698 for (x = 0; x < 48; x++) {
2704 while ((part =
strsep(×,
"&"))) {
2705 if (!(endpart = strchr(part,
'-'))) {
2706 if (sscanf(part,
"%2d:%2d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) {
2710 i->
minmask[st_h * 2 + (st_m >= 30 ? 1 : 0)] |= (1 << (st_m % 30));
2715 while (*endpart && !isdigit(*endpart)) {
2722 if (sscanf(part,
"%2d:%2d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) {
2726 if (sscanf(endpart,
"%2d:%2d", &endh, &endm) != 2 || endh < 0 || endh > 23 || endm < 0 || endm > 59) {
2730 minute_start = st_h * 60 + st_m;
2731 minute_end = endh * 60 + endm;
2733 for (x = minute_start; x != minute_end; x = (x + 1) % (24 * 60)) {
2734 i->
minmask[x / 30] |= (1 << (x % 30));
2737 i->
minmask[x / 30] |= (1 << (x % 30));
2755 if (!strcasecmp(family, map->
name)) {
2767 if (!strcasecmp(eng->name, map->
driver))
2793 if ((category =
ast_calloc(1,
sizeof(*category))))
2837 config->last->next = category;
2841 config->current = category;
2866 char table[256] =
"";
2912 char exec_file[512];
2913 int object, do_exec, do_include;
2916 if (cur[0] ==
'[') {
2921 c = strchr(cur,
']');
2948 if (!(cur = strchr(
c,
')'))) {
2953 while ((cur =
strsep(&
c,
","))) {
2954 if (!strcasecmp(cur,
"!")) {
2955 (*cat)->ignored = 1;
2956 }
else if (!strcasecmp(cur,
"+")) {
2962 ast_log(
LOG_WARNING,
"Category addition requested, but category '%s' does not exist, line %d of %s\n", catname,
lineno, configfile);
2975 ast_log(
LOG_WARNING,
"Inheritance requested, but category '%s' does not exist, line %d of %s\n", cur,
lineno, configfile);
2984 }
else if (cur[0] ==
'#') {
2988 while(*
c && (*
c > 32))
c++;
2997 do_include = !strcasecmp(cur,
"include");
2999 do_exec = !strcasecmp(cur,
"exec");
3003 ast_log(
LOG_WARNING,
"Cannot perform #exec unless execincludes option is enabled in asterisk.conf (options section)!\n");
3006 if (do_include || do_exec) {
3009 char real_inclusion_name[525];
3012 while((*
c ==
'<') || (*
c ==
'>') || (*
c ==
'\"'))
c++;
3017 c = cur + strlen(cur) - 1;
3018 if ((*
c ==
'>') || (*
c ==
'<') || (*
c ==
'\"'))
3028 snprintf(exec_file,
sizeof(exec_file),
"/var/tmp/exec.%d.%ld", (
int)time(
NULL), (
long)pthread_self());
3029 if (snprintf(cmd,
sizeof(cmd),
"%s > %s 2>&1", cur, exec_file) >=
sizeof(cmd)) {
3030 ast_log(
LOG_ERROR,
"Failed to construct command string to execute %s.\n", cur);
3037 exec_file[0] =
'\0';
3042 ast_include_new(cfg, configfile, cur, do_exec, cur2,
lineno, real_inclusion_name,
sizeof(real_inclusion_name));
3053 do_exec ?
"exec" :
"include",
3054 do_exec ?
"/path/to/executable" :
"filename",
3065 "parse error: No category context for line %d of %s\n",
lineno, configfile);
3068 c = strchr(cur,
'=');
3124 char *new_buf, *comment_p, *process_buf;
3130 struct stat statbuf;
3134 if (filename[0] ==
'/') {
3138 snprintf(fn,
sizeof(fn),
"./%s", filename);
3148 if (stat(fn, &statbuf))
3151 if (!S_ISREG(statbuf.st_mode)) {
3159 if (!(f = fopen(fn,
"r"))) {
3173 if (fgets(
buf,
sizeof(
buf), f)) {
3174 if ( withcomments ) {
3186 if ((comment_p > new_buf) && (*(comment_p-1) ==
'\\')) {
3188 memmove(comment_p - 1, comment_p, strlen(comment_p) + 1);
3189 new_buf = comment_p;
3194 new_buf = comment_p + 3;
3200 }
else if ((comment_p >= new_buf + 2) &&
3205 new_buf = comment_p + 1;
3211 oldptr = process_buf + strlen(process_buf);
3212 if ( withcomments ) {
3217 memmove(oldptr, new_buf, strlen(new_buf) + 1);
3220 process_buf = new_buf;
3226 if ( withcomments ) {
3230 new_buf = comment_p;
3232 new_buf = comment_p + 1;
3235 if( withcomments &&
comment && !process_buf )
3241 char *stripped_process_buf =
ast_strip(process_buf);
3243 if (
process_text_line(cfg, &cat, stripped_process_buf, lineno, filename, withcomments, suggested_include_file)) {
3332 cat =
config->last_browse->next;
3336 for (cat =
config->root; cat; cat = cat->
next) {
3343 for (cat =
config->root; cat; cat = cat->
next) {
3344 if (!strcasecmp(cat->
name,
prev)) {
3355 config->last_browse = cat;
3389 static void gen_header(FILE *f1,
const char *configfile,
const char *fn,
const char *generator)
3396 fprintf(f1,
";!\n");
3397 fprintf(f1,
";! Automatically generated configuration file\n");
3398 if (strcmp(configfile, fn))
3399 fprintf(f1,
";! Filename: %s (%s)\n", configfile, fn);
3401 fprintf(f1,
";! Filename: %s\n", configfile);
3402 fprintf(f1,
";! Generator: %s\n", generator);
3403 fprintf(f1,
";! Creation Date: %s", date);
3404 fprintf(f1,
";!\n");
3407 static void set_fn(
char *fn,
int fn_size,
const char *
file,
const char *configfile)
3410 if (configfile[0] ==
'/')
3414 }
else if (
file[0] ==
'/')
3456 set_fn(fn,
sizeof(fn), 0, configfile);
3458 if ((f = fopen(fn,
"w+"))) {
3460 if ((f = fopen(fn,
"w"))) {
3474 set_fn(fn,
sizeof(fn), cat->
file, configfile);
3487 fprintf(f,
"#exec \"%s\"\n", incl->
exec_file);
3497 if (cmt->
cmt[0] !=
';' || cmt->
cmt[1] !=
'!')
3498 fprintf(f,
"%s", cmt->
cmt);
3502 fprintf(f,
"[%s]", cat->
name);
3504 fprintf(f,
"%s", cmt->
cmt);
3512 set_fn(fn,
sizeof(fn),
var->file, configfile);
3525 fprintf(f,
"#exec \"%s\"\n", incl->
exec_file);
3533 for (cmt =
var->precomments; cmt; cmt=cmt->
next) {
3534 if (cmt->
cmt[0] !=
';' || cmt->
cmt[1] !=
'!')
3535 fprintf(f,
"%s", cmt->
cmt);
3538 fprintf(f,
"%s %s %s %s",
var->name, (
var->object ?
"=>" :
"="),
var->value,
var->sameline->cmt);
3540 fprintf(f,
"%s %s %s\n",
var->name, (
var->object ?
"=>" :
"="),
var->value);
3541 if (
var->blanklines) {
3542 blanklines =
var->blanklines;
3543 while (blanklines--)
3580 fprintf(f,
"#exec \"%s\"\n", incl->
exec_file);
3602 #define EXT_DATA_SIZE 256
3604 #define EXT_DATA_SIZE 8192
3611 #define SWITCH_DATA_LENGTH 256
3632 if (hint->
exten == oe) {
3653 if (hint->
exten == e) {
3663 if (!(hint =
ast_calloc(1,
sizeof(*hint)))) {
3681 for (ep =
NULL; e ; ep = e, e = e->
peer) {
3693 ast_log(
LOG_WARNING,
"Unable to register extension '%s', priority %d in '%s', already in use\n",
tmp->exten,
tmp->priority, con->
name);
3745 if (hint->
exten == e) {
3751 cblist = cblist->
next;
3810 int j, num_fields, last_sep = -1;
3823 for (j = 0, num_fields = 1;
info[j] !=
'\0'; j++) {
3824 if (
info[j] ==
'|' ||
info[j] ==
',') {
3831 if (num_fields == 5) {
3876 int c, cmin = 0xff, count = 0;
3882 while ( (
c = *(*p)++) && (
c ==
' ' ||
c ==
'-') )
3888 return 0x0000 | (
c & 0xff);
3891 return 0x0700 |
'2' ;
3894 return 0x0900 |
'0';
3897 return 0x0800 |
'1';
3913 end = strchr(*p,
']');
3920 memset(chars,
'\0',
sizeof(chars));
3921 for (; *p <
end ; (*p)++) {
3922 unsigned char c1, c2;
3923 c1 = (
unsigned char)((*p)[0]);
3924 if (*p + 2 <
end && (*p)[1] ==
'-') {
3925 c2 = (
unsigned char)((*p)[2]);
3931 for (; c1 <= c2; c1++) {
3932 uint32_t mask = 1 << (c1 % 32);
3933 if ( (chars[ c1 / 32 ] & mask) == 0)
3935 chars[ c1 / 32 ] |= mask;
3939 return count == 0 ? 0x30000 : (count | cmin);
3954 return (
b[0] ==
'_') ? -1 : strcmp(
a,
b);
3960 return strcmp(
a,
b);
3963 while (!ret &&
a &&
b)
3968 return (ret > 0) ? 1 : -1;
3976 while (*src && (count <
len - 1)) {
4014 if (!strcasecmp(asw->
name, sw))
4196 if ( (mode ==
E_MATCH) && (pattern[0] ==
'_') && (strcasecmp(pattern,data)==0) )
4199 if (pattern[0] !=
'_') {
4200 int ld = strlen(data), lp = strlen(pattern);
4206 return !strcmp(pattern, data);
4207 if (ld == 0 || !strncasecmp(pattern, data, ld))
4217 while (*data && *pattern && *pattern !=
'/') {
4224 switch (toupper(*pattern)) {
4226 end = strchr(pattern+1,
']');
4231 for (pattern++; pattern !=
end; pattern++) {
4232 if (pattern+2 <
end && pattern[1] ==
'-') {
4233 if (*data >= pattern[0] && *data <= pattern[2])
4239 }
else if (*data == pattern[0])
4247 if (*data < '2' || *data >
'9')
4251 if (*data < '0' || *data >
'9')
4255 if (*data < '1' || *data >
'9')
4267 if (*data != *pattern)
4279 if (*pattern ==
'\0' || *pattern ==
'/')
4281 else if (*pattern ==
'!')
4284 return (mode ==
E_MATCH) ? 0 : 1;
4301 static int matchcid(
const char *cidpattern,
const char *callerid)
4329 const char *callerid,
4340 const char *callerid,
4363 for (x = 0; x < q->
stacklen; x++) {
4404 if (label && e->
label && !strcmp(label, e->
label))
4416 #ifdef NOT_RIGHT_NOW
4436 datap = sw->eval ? sw->tmpdata : sw->data;
4449 for (i =
tmp->includes; i; i = i->
next) {
4466 const char *callerid,
4475 const char *callerid,
4512 length += 2 * (strlen(
value) + 1);
4520 p = new_include->
stuff;
4521 new_include->
name = p;
4523 p += strlen(
value) + 1;
4524 new_include->
rname = p;
4527 if ( (
c = strchr(p,
'|')) || (
c = strchr(p,
',')) ) {
4537 if (!strcasecmp(i->
name, new_include->
name)) {
4547 il->
next = new_include;
4573 length += strlen(
value) + 1;
4582 for (ignorepatc = con->
ignorepats; ignorepatc; ignorepatc = ignorepatc->
next) {
4583 ignorepatl = ignorepatc;
4591 ignorepatl->
next = ignorepat;
4638 const char *data,
int eval,
const char *
registrar);
4641 const char *data,
int eval,
const char *
registrar)
4648 length =
sizeof(
struct ast_sw);
4649 length += strlen(
value) + 1;
4651 length += strlen(
data);
4666 p += strlen(
value) + 1;
4670 p += strlen(
data) + 1;
4672 strcpy(new_sw->
data,
"");
4682 if (!strcasecmp(i->
name, new_sw->
name) && !strcasecmp(i->
data, new_sw->
data)) {
4716 loc_contexts = extcontexts;
4719 if (!strcasecmp(
tmp->name,
name)) {
4735 tmp->next = *loc_contexts;
4738 *loc_contexts =
tmp;
4777 const char *application,
void *data,
void (*datad)(
void *),
4797 length += strlen(application) + 1;
4799 length += strlen(
label) + 1;
4801 length += strlen(callerid) + 1;
4816 p += strlen(
label) + 1;
4823 p +=
ext_strncpy(p, callerid, strlen(callerid) + 1) + 1;
4830 strcpy(p, application);
4837 for (e = con->
root; e;
el = e, e = e->
next) {
4852 if (e && res == 0) {
4872 if (
tmp->matchcid) {
4873 ast_log(
LOG_DEBUG,
"Added extension '%s' priority %d (CID match '%s') to %s\n",
4881 if (
tmp->matchcid) {
4894 const char *application,
void *
data,
void (*
datad)(
void *),
4899 const char *application,
void *
data,
void (*
datad)(
void *),
4928 if (matching_action) {
4939 if (matching_action)
4951 if (!matching_action)
4955 if (!matching_action)
4959 if (!matching_action)
4971 return (matching_action) ? 0 : -1;
5016 }
else if (*
var ==
')') {
5018 }
else if (*
var ==
':' && parens == 0) {
5020 sscanf(
var,
"%30d:%30d", offset, length);
5040 static char *
substring(
const char *
value,
int offset,
int length,
char *workspace,
size_t workspace_len)
5042 char *ret = workspace;
5050 if (offset == 0 && length >= lr)
5054 offset = lr + offset;
5064 if (length >= 0 && length < lr - offset)
5066 else if (length < 0) {
5067 if (lr > offset - length)
5068 ret[lr + length - offset] =
'\0';
5083 const char not_found =
'\0';
5087 int i, need_substring;
5114 if (s == ¬_found) {
5115 if (!strcmp(
var,
"EPOCH")) {
5116 snprintf(workspace, workspacelen,
"%u",(
int)time(
NULL));
5122 for (i = 0; s == ¬_found && i < (
sizeof(places) /
sizeof(places[0])); i++) {
5137 if (s == ¬_found || s ==