2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 2006, Digium, Inc.
6 * Steve Murphy <murf@digium.com>
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.
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.
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.
27 #include "asterisk/autoconfig.h"
36 #include <sys/types.h>
38 #include <sys/resource.h>
44 #if !defined(SOLARIS) && !defined(__CYGWIN__)
51 #include <sys/param.h>
52 #define ASINCLUDE_GLOB 1
53 #ifdef AST_INCLUDE_GLOB
54 #if defined(__Darwin__) || defined(__CYGWIN__)
55 #define GLOB_ABORTED GLOB_ABEND
60 static char ast_config_AST_CONFIG_DIR[PATH_MAX] = {"/etc/asterisk"};
61 #define AST_API_MODULE 1 /* gimme the inline defs! */
64 char x; /* basically empty! */
69 #include "asterisk/inline_api.h"
70 #include "asterisk/compat.h"
71 #include "asterisk/compiler.h"
72 #include "asterisk/endian.h"
73 #include "asterisk/ast_expr.h"
74 #include "asterisk/ael_structs.h"
75 #include "asterisk/pval.h"
78 #define EVENTLOG "event_log"
79 #define QUEUELOG "queue_log"
81 #define DEBUG_M(a) { \
85 #define VERBOSE_PREFIX_1 " "
86 #define VERBOSE_PREFIX_2 " == "
87 #define VERBOSE_PREFIX_3 " -- "
88 #define VERBOSE_PREFIX_4 " > "
90 /* IN CONFLICT: void ast_log(int level, const char *file, int line, const char *function, const char *fmt, ...)
91 __attribute__ ((format (printf, 5, 6))); */
93 static void ast_log(int level, const char *file, int line, const char *function, const char *fmt, ...) __attribute__ ((format (printf,5,6)));
96 void ast_backtrace(void);
98 void ast_queue_log(const char *queuename, const char *callid, const char *agent, const char *event, const char *fmt, ...)
99 __attribute__ ((format (printf, 5, 6)));
101 /* IN CONFLICT: void ast_verbose(const char *fmt, ...)
102 __attribute__ ((format (printf, 1, 2))); */
104 int ast_register_verbose(void (*verboser)(const char *string));
105 int ast_unregister_verbose(void (*verboser)(const char *string));
107 void ast_console_puts(const char *string);
109 void ast_console_puts_mutable(const char *string);
110 void ast_console_toggle_mute(int fd);
112 #define _A_ __FILE__, __LINE__, __PRETTY_FUNCTION__
117 #define __LOG_DEBUG 0
118 #define LOG_DEBUG __LOG_DEBUG, _A_
123 #define __LOG_EVENT 1
124 #define LOG_EVENT __LOG_EVENT, _A_
129 #define __LOG_NOTICE 2
130 #define LOG_NOTICE __LOG_NOTICE, _A_
135 #define __LOG_WARNING 3
136 #define LOG_WARNING __LOG_WARNING, _A_
141 #define __LOG_ERROR 4
142 #define LOG_ERROR __LOG_ERROR, _A_
147 #define __LOG_VERBOSE 5
148 #define LOG_VERBOSE __LOG_VERBOSE, _A_
154 #define LOG_DTMF __LOG_DTMF, _A_
158 static unsigned int __unsigned_int_flags_dummy;
160 struct ast_flags { /* stolen from utils.h */
163 #define ast_test_flag(p,flag) ({ \
164 typeof ((p)->flags) __p = (p)->flags; \
165 typeof (__unsigned_int_flags_dummy) __x = 0; \
166 (void) (&__p == &__x); \
167 ((p)->flags & (flag)); \
170 #define ast_set2_flag(p,value,flag) do { \
171 typeof ((p)->flags) __p = (p)->flags; \
172 typeof (__unsigned_int_flags_dummy) __x = 0; \
173 (void) (&__p == &__x); \
175 (p)->flags |= (flag); \
177 (p)->flags &= ~(flag); \
181 #ifdef __AST_DEBUG_MALLOC
182 static void ast_free(void *ptr) attribute_unused;
183 static void ast_free(void *ptr)
188 #define ast_free free
191 #ifndef __AST_DEBUG_MALLOC
193 #define MALLOC_FAILURE_MSG \
194 ast_log(LOG_ERROR, "Memory Allocation Failure in function %s at line %d of %s\n", func, lineno, file);
196 * \brief A wrapper for malloc()
198 * ast_malloc() is a wrapper for malloc() that will generate an Asterisk log
199 * message in the case that the allocation fails.
201 * The argument and return value are the same as malloc()
203 #define ast_malloc(len) \
204 _ast_malloc((len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
207 void * attribute_malloc _ast_malloc(size_t len, const char *file, int lineno, const char *func),
211 if (!(p = malloc(len)))
219 * \brief A wrapper for calloc()
221 * ast_calloc() is a wrapper for calloc() that will generate an Asterisk log
222 * message in the case that the allocation fails.
224 * The arguments and return value are the same as calloc()
226 #define ast_calloc(num, len) \
227 _ast_calloc((num), (len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
230 void * attribute_malloc _ast_calloc(size_t num, size_t len, const char *file, int lineno, const char *func),
234 if (!(p = calloc(num, len)))
242 * \brief A wrapper for calloc() for use in cache pools
244 * ast_calloc_cache() is a wrapper for calloc() that will generate an Asterisk log
245 * message in the case that the allocation fails. When memory debugging is in use,
246 * the memory allocated by this function will be marked as 'cache' so it can be
247 * distinguished from normal memory allocations.
249 * The arguments and return value are the same as calloc()
251 #define ast_calloc_cache(num, len) \
252 _ast_calloc((num), (len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
255 * \brief A wrapper for realloc()
257 * ast_realloc() is a wrapper for realloc() that will generate an Asterisk log
258 * message in the case that the allocation fails.
260 * The arguments and return value are the same as realloc()
262 #define ast_realloc(p, len) \
263 _ast_realloc((p), (len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
266 void * attribute_malloc _ast_realloc(void *p, size_t len, const char *file, int lineno, const char *func),
270 if (!(newp = realloc(p, len)))
278 * \brief A wrapper for strdup()
280 * ast_strdup() is a wrapper for strdup() that will generate an Asterisk log
281 * message in the case that the allocation fails.
283 * ast_strdup(), unlike strdup(), can safely accept a NULL argument. If a NULL
284 * argument is provided, ast_strdup will return NULL without generating any
285 * kind of error log message.
287 * The argument and return value are the same as strdup()
289 #define ast_strdup(str) \
290 _ast_strdup((str), __FILE__, __LINE__, __PRETTY_FUNCTION__)
293 char * attribute_malloc _ast_strdup(const char *str, const char *file, int lineno, const char *func),
298 if (!(newstr = strdup(str)))
307 * \brief A wrapper for strndup()
309 * ast_strndup() is a wrapper for strndup() that will generate an Asterisk log
310 * message in the case that the allocation fails.
312 * ast_strndup(), unlike strndup(), can safely accept a NULL argument for the
313 * string to duplicate. If a NULL argument is provided, ast_strdup will return
314 * NULL without generating any kind of error log message.
316 * The arguments and return value are the same as strndup()
318 #define ast_strndup(str, len) \
319 _ast_strndup((str), (len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
322 char * attribute_malloc _ast_strndup(const char *str, size_t len, const char *file, int lineno, const char *func),
327 if (!(newstr = strndup(str, len)))
336 * \brief A wrapper for asprintf()
338 * ast_asprintf() is a wrapper for asprintf() that will generate an Asterisk log
339 * message in the case that the allocation fails.
341 * The arguments and return value are the same as asprintf()
343 #define ast_asprintf(ret, fmt, ...) \
344 _ast_asprintf((ret), __FILE__, __LINE__, __PRETTY_FUNCTION__, fmt, __VA_ARGS__)
347 int _ast_asprintf(char **ret, const char *file, int lineno, const char *func, const char *fmt, ...),
353 if ((res = vasprintf(ret, fmt, ap)) == -1)
362 * \brief A wrapper for vasprintf()
364 * ast_vasprintf() is a wrapper for vasprintf() that will generate an Asterisk log
365 * message in the case that the allocation fails.
367 * The arguments and return value are the same as vasprintf()
369 #define ast_vasprintf(ret, fmt, ap) \
370 _ast_vasprintf((ret), __FILE__, __LINE__, __PRETTY_FUNCTION__, (fmt), (ap))
373 int _ast_vasprintf(char **ret, const char *file, int lineno, const char *func, const char *fmt, va_list ap),
377 if ((res = vasprintf(ret, fmt, ap)) == -1)
386 /* If astmm is in use, let it handle these. Otherwise, it will report that
387 all allocations are coming from this header file */
389 #define ast_malloc(a) malloc(a)
390 #define ast_calloc(a,b) calloc(a,b)
391 #define ast_realloc(a,b) realloc(a,b)
392 #define ast_strdup(a) strdup(a)
393 #define ast_strndup(a,b) strndup(a,b)
394 #define ast_asprintf(a,b,c) asprintf(a,b,c)
395 #define ast_vasprintf(a,b,c) vasprintf(a,b,c)
397 #endif /* AST_DEBUG_MALLOC */
399 #if !defined(ast_strdupa) && defined(__GNUC__)
401 \brief duplicate a string in memory from the stack
402 \param s The string to duplicate
404 This macro will duplicate the given string. It returns a pointer to the stack
405 allocatted memory for the new string.
407 #define ast_strdupa(s) \
410 const char *__old = (s); \
411 size_t __len = strlen(__old) + 1; \
412 char *__new = __builtin_alloca(__len); \
413 memcpy (__new, __old, __len); \
421 #define MAX_NESTED_COMMENTS 128
422 #define COMMENT_START ";--"
423 #define COMMENT_END "--;"
424 #define COMMENT_META ';'
425 #define COMMENT_TAG '-'
427 static char *extconfig_conf = "extconfig.conf";
429 /*! Growable string buffer */
430 static char *comment_buffer; /*!< this will be a comment collector.*/
431 static int comment_buffer_size; /*!< the amount of storage so far alloc'd for the comment_buffer */
433 static char *lline_buffer; /*!< A buffer for stuff behind the ; */
434 static int lline_buffer_size;
439 struct ast_comment *next;
443 static void CB_INIT(void)
445 if (!comment_buffer) {
446 comment_buffer = ast_malloc(CB_INCR);
449 comment_buffer[0] = 0;
450 comment_buffer_size = CB_INCR;
451 lline_buffer = ast_malloc(CB_INCR);
455 lline_buffer_size = CB_INCR;
457 comment_buffer[0] = 0;
462 static void CB_ADD(char *str)
464 int rem = comment_buffer_size - strlen(comment_buffer) - 1;
465 int siz = strlen(str);
467 comment_buffer = ast_realloc(comment_buffer, comment_buffer_size + CB_INCR + siz + 1);
470 comment_buffer_size += CB_INCR+siz+1;
472 strcat(comment_buffer,str);
475 static void CB_ADD_LEN(char *str, int len)
477 int cbl = strlen(comment_buffer) + 1;
478 int rem = comment_buffer_size - cbl;
480 comment_buffer = ast_realloc(comment_buffer, comment_buffer_size + CB_INCR + len + 1);
483 comment_buffer_size += CB_INCR+len+1;
485 strncat(comment_buffer,str,len);
486 comment_buffer[cbl+len-1] = 0;
489 static void LLB_ADD(char *str)
491 int rem = lline_buffer_size - strlen(lline_buffer) - 1;
492 int siz = strlen(str);
494 lline_buffer = ast_realloc(lline_buffer, lline_buffer_size + CB_INCR + siz + 1);
497 lline_buffer_size += CB_INCR + siz + 1;
499 strcat(lline_buffer,str);
502 static void CB_RESET(void )
504 comment_buffer[0] = 0;
508 /*! \brief Keep track of how many threads are currently trying to wait*() on
510 static unsigned int safe_system_level = 0;
511 static void *safe_system_prev_handler;
513 /*! \brief NULL handler so we can collect the child exit status */
514 static void null_sig_handler(int signal)
519 void ast_replace_sigchld(void);
521 void ast_replace_sigchld(void)
525 level = safe_system_level++;
527 /* only replace the handler if it has not already been done */
529 safe_system_prev_handler = signal(SIGCHLD, null_sig_handler);
533 void ast_unreplace_sigchld(void);
535 void ast_unreplace_sigchld(void)
539 level = --safe_system_level;
541 /* only restore the handler if we are the last one */
543 signal(SIGCHLD, safe_system_prev_handler);
547 int ast_safe_system(const char *s);
549 int ast_safe_system(const char *s)
552 #ifdef HAVE_WORKING_FORK
556 struct rusage rusage;
559 #if defined(HAVE_WORKING_FORK) || defined(HAVE_WORKING_VFORK)
560 ast_replace_sigchld();
562 #ifdef HAVE_WORKING_FORK
569 #ifdef HAVE_WORKING_FORK
570 /* Close file descriptors and launch system command */
571 for (x = STDERR_FILENO + 1; x < 4096; x++)
574 execl("/bin/sh", "/bin/sh", "-c", s, (char *) NULL);
576 } else if (pid > 0) {
578 res = wait4(pid, &status, 0, &rusage);
580 res = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
582 } else if (errno != EINTR)
586 ast_log(LOG_WARNING, "Fork failed: %s\n", strerror(errno));
590 ast_unreplace_sigchld();
598 static struct ast_comment *ALLOC_COMMENT(const char *buffer)
600 struct ast_comment *x = ast_calloc(1,sizeof(struct ast_comment)+strlen(buffer)+1);
601 strcpy(x->cmt, buffer);
605 static struct ast_config_map {
606 struct ast_config_map *next;
612 } *config_maps = NULL;
614 static struct ast_config_engine *config_engine_list;
616 #define MAX_INCLUDE_LEVEL 10
619 struct ast_category {
621 int ignored; /*!< do not let user of the config see this category */
623 struct ast_comment *precomments;
624 struct ast_comment *sameline;
625 struct ast_variable *root;
626 struct ast_variable *last;
627 struct ast_category *next;
631 struct ast_category *root;
632 struct ast_category *last;
633 struct ast_category *current;
634 struct ast_category *last_browse; /*!< used to cache the last category supplied via category_browse */
636 int max_include_level;
639 typedef struct ast_config *config_load_func(const char *database, const char *table, const char *configfile, struct ast_config *config, int withcomments);
640 typedef struct ast_variable *realtime_var_get(const char *database, const char *table, va_list ap);
641 typedef struct ast_config *realtime_multi_get(const char *database, const char *table, va_list ap);
642 typedef int realtime_update(const char *database, const char *table, const char *keyfield, const char *entity, va_list ap);
644 /*! \brief Configuration engine structure, used to define realtime drivers */
645 struct ast_config_engine {
647 config_load_func *load_func;
648 realtime_var_get *realtime_func;
649 realtime_multi_get *realtime_multi_func;
650 realtime_update *update_func;
651 struct ast_config_engine *next;
654 static struct ast_config_engine *config_engine_list;
658 struct ast_variable {
662 int object; /*!< 0 for variable, 1 for object */
663 int blanklines; /*!< Number of blanklines following entry */
664 struct ast_comment *precomments;
665 struct ast_comment *sameline;
666 struct ast_variable *next;
670 static const char *ast_variable_retrieve(const struct ast_config *config, const char *category, const char *variable);
671 static struct ast_config *config_text_file_load(const char *database, const char *table, const char *filename, struct ast_config *cfg, int withcomments);
673 struct ast_config *localized_config_load_with_comments(const char *filename);
674 static char *ast_category_browse(struct ast_config *config, const char *prev);
675 static struct ast_variable *ast_variable_browse(const struct ast_config *config, const char *category);
676 static void ast_variables_destroy(struct ast_variable *v);
677 static void ast_config_destroy(struct ast_config *cfg);
679 static struct ast_variable *ast_variable_new(const char *name, const char *value);
681 static struct ast_variable *ast_variable_new(const char *name, const char *value)
683 struct ast_variable *variable;
684 int name_len = strlen(name) + 1;
686 if ((variable = ast_calloc(1, name_len + strlen(value) + 1 + sizeof(*variable)))) {
687 variable->name = variable->stuff;
688 variable->value = variable->stuff + name_len;
689 strcpy(variable->name,name);
690 strcpy(variable->value,value);
696 static void ast_variable_append(struct ast_category *category, struct ast_variable *variable);
698 static void ast_variable_append(struct ast_category *category, struct ast_variable *variable)
703 category->last->next = variable;
705 category->root = variable;
706 category->last = variable;
707 while (category->last->next)
708 category->last = category->last->next;
711 static struct ast_category *category_get(const struct ast_config *config, const char *category_name, int ignored);
713 static struct ast_category *category_get(const struct ast_config *config, const char *category_name, int ignored)
715 struct ast_category *cat;
717 /* try exact match first, then case-insensitive match */
718 for (cat = config->root; cat; cat = cat->next) {
719 if (cat->name == category_name && (ignored || !cat->ignored))
723 for (cat = config->root; cat; cat = cat->next) {
724 if (!strcasecmp(cat->name, category_name) && (ignored || !cat->ignored))
731 static struct ast_category *ast_category_get(const struct ast_config *config, const char *category_name)
733 return category_get(config, category_name, 0);
736 static struct ast_variable *ast_variable_browse(const struct ast_config *config, const char *category)
738 struct ast_category *cat = NULL;
740 if (category && config->last_browse && (config->last_browse->name == category))
741 cat = config->last_browse;
743 cat = ast_category_get(config, category);
745 return (cat) ? cat->root : NULL;
748 static const char *ast_variable_retrieve(const struct ast_config *config, const char *category, const char *variable)
750 struct ast_variable *v;
753 for (v = ast_variable_browse(config, category); v; v = v->next) {
754 if (!strcasecmp(variable, v->name))
758 struct ast_category *cat;
760 for (cat = config->root; cat; cat = cat->next)
761 for (v = cat->root; v; v = v->next)
762 if (!strcasecmp(variable, v->name))
769 static struct ast_variable *variable_clone(const struct ast_variable *old)
771 struct ast_variable *new = ast_variable_new(old->name, old->value);
774 new->lineno = old->lineno;
775 new->object = old->object;
776 new->blanklines = old->blanklines;
777 /* TODO: clone comments? */
783 static void ast_variables_destroy(struct ast_variable *v)
785 struct ast_variable *vn;
794 static void ast_config_destroy(struct ast_config *cfg)
796 struct ast_category *cat, *catn;
803 ast_variables_destroy(cat->root);
812 /* options.h declars ast_options extern; I need it static? */
814 #define AST_CACHE_DIR_LEN 512
815 #define AST_FILENAME_MAX 80
817 /*! \ingroup main_options */
818 enum ast_option_flags {
819 /*! Allow \#exec in config files */
820 AST_OPT_FLAG_EXEC_INCLUDES = (1 << 0),
822 AST_OPT_FLAG_NO_FORK = (1 << 1),
824 AST_OPT_FLAG_QUIET = (1 << 2),
826 AST_OPT_FLAG_CONSOLE = (1 << 3),
827 /*! Run in realtime Linux priority */
828 AST_OPT_FLAG_HIGH_PRIORITY = (1 << 4),
829 /*! Initialize keys for RSA authentication */
830 AST_OPT_FLAG_INIT_KEYS = (1 << 5),
831 /*! Remote console */
832 AST_OPT_FLAG_REMOTE = (1 << 6),
833 /*! Execute an asterisk CLI command upon startup */
834 AST_OPT_FLAG_EXEC = (1 << 7),
835 /*! Don't use termcap colors */
836 AST_OPT_FLAG_NO_COLOR = (1 << 8),
837 /*! Are we fully started yet? */
838 AST_OPT_FLAG_FULLY_BOOTED = (1 << 9),
839 /*! Trascode via signed linear */
840 AST_OPT_FLAG_TRANSCODE_VIA_SLIN = (1 << 10),
841 /*! Enable priority jumping in applications */
842 AST_OPT_FLAG_PRIORITY_JUMPING = (1 << 11),
843 /*! Dump core on a seg fault */
844 AST_OPT_FLAG_DUMP_CORE = (1 << 12),
845 /*! Cache sound files */
846 AST_OPT_FLAG_CACHE_RECORD_FILES = (1 << 13),
847 /*! Display timestamp in CLI verbose output */
848 AST_OPT_FLAG_TIMESTAMP = (1 << 14),
849 /*! Override config */
850 AST_OPT_FLAG_OVERRIDE_CONFIG = (1 << 15),
852 AST_OPT_FLAG_RECONNECT = (1 << 16),
853 /*! Transmit Silence during Record() */
854 AST_OPT_FLAG_TRANSMIT_SILENCE = (1 << 17),
855 /*! Suppress some warnings */
856 AST_OPT_FLAG_DONT_WARN = (1 << 18),
857 /*! End CDRs before the 'h' extension */
858 AST_OPT_FLAG_END_CDR_BEFORE_H_EXTEN = (1 << 19),
859 /*! Use Zaptel Timing for generators if available */
860 AST_OPT_FLAG_INTERNAL_TIMING = (1 << 20),
861 /*! Always fork, even if verbose or debug settings are non-zero */
862 AST_OPT_FLAG_ALWAYS_FORK = (1 << 21),
863 /*! Disable log/verbose output to remote consoles */
864 AST_OPT_FLAG_MUTE = (1 << 22)
867 /*! These are the options that set by default when Asterisk starts */
868 #define AST_DEFAULT_OPTIONS AST_OPT_FLAG_TRANSCODE_VIA_SLIN
870 #define ast_opt_exec_includes ast_test_flag(&ast_options, AST_OPT_FLAG_EXEC_INCLUDES)
871 #define ast_opt_no_fork ast_test_flag(&ast_options, AST_OPT_FLAG_NO_FORK)
872 #define ast_opt_quiet ast_test_flag(&ast_options, AST_OPT_FLAG_QUIET)
873 #define ast_opt_console ast_test_flag(&ast_options, AST_OPT_FLAG_CONSOLE)
874 #define ast_opt_high_priority ast_test_flag(&ast_options, AST_OPT_FLAG_HIGH_PRIORITY)
875 #define ast_opt_init_keys ast_test_flag(&ast_options, AST_OPT_FLAG_INIT_KEYS)
876 #define ast_opt_remote ast_test_flag(&ast_options, AST_OPT_FLAG_REMOTE)
877 #define ast_opt_exec ast_test_flag(&ast_options, AST_OPT_FLAG_EXEC)
878 #define ast_opt_no_color ast_test_flag(&ast_options, AST_OPT_FLAG_NO_COLOR)
879 #define ast_fully_booted ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)
880 #define ast_opt_transcode_via_slin ast_test_flag(&ast_options, AST_OPT_FLAG_TRANSCODE_VIA_SLIN)
881 #define ast_opt_priority_jumping ast_test_flag(&ast_options, AST_OPT_FLAG_PRIORITY_JUMPING)
882 #define ast_opt_dump_core ast_test_flag(&ast_options, AST_OPT_FLAG_DUMP_CORE)
883 #define ast_opt_cache_record_files ast_test_flag(&ast_options, AST_OPT_FLAG_CACHE_RECORD_FILES)
884 #define ast_opt_timestamp ast_test_flag(&ast_options, AST_OPT_FLAG_TIMESTAMP)
885 #define ast_opt_override_config ast_test_flag(&ast_options, AST_OPT_FLAG_OVERRIDE_CONFIG)
886 #define ast_opt_reconnect ast_test_flag(&ast_options, AST_OPT_FLAG_RECONNECT)
887 #define ast_opt_transmit_silence ast_test_flag(&ast_options, AST_OPT_FLAG_TRANSMIT_SILENCE)
888 #define ast_opt_dont_warn ast_test_flag(&ast_options, AST_OPT_FLAG_DONT_WARN)
889 #define ast_opt_end_cdr_before_h_exten ast_test_flag(&ast_options, AST_OPT_FLAG_END_CDR_BEFORE_H_EXTEN)
890 #define ast_opt_internal_timing ast_test_flag(&ast_options, AST_OPT_FLAG_INTERNAL_TIMING)
891 #define ast_opt_always_fork ast_test_flag(&ast_options, AST_OPT_FLAG_ALWAYS_FORK)
892 #define ast_opt_mute ast_test_flag(&ast_options, AST_OPT_FLAG_MUTE)
894 /* IN CONFLICT: extern int option_verbose; */
895 /* IN CONFLICT: extern int option_debug; */ /*!< Debugging */
896 extern int option_maxcalls; /*!< Maximum number of simultaneous channels */
897 extern double option_maxload;
898 extern char defaultlanguage[];
900 extern time_t ast_startuptime;
901 extern time_t ast_lastreloadtime;
902 extern pid_t ast_mainpid;
904 extern char record_cache_dir[AST_CACHE_DIR_LEN];
905 extern char debug_filename[AST_FILENAME_MAX];
907 extern int ast_language_is_prefix;
913 #ifndef HAVE_MTX_PROFILE
914 #define __MTX_PROF(a) return pthread_mutex_lock((a))
916 #define __MTX_PROF(a) do { \
918 /* profile only non-blocking events */ \
919 ast_mark(mtx_prof, 1); \
920 i = pthread_mutex_trylock((a)); \
921 ast_mark(mtx_prof, 0); \
925 return pthread_mutex_lock((a)); \
927 #endif /* HAVE_MTX_PROFILE */
929 #define AST_PTHREADT_NULL (pthread_t) -1
930 #define AST_PTHREADT_STOP (pthread_t) -2
932 #if defined(SOLARIS) || defined(BSD)
933 #define AST_MUTEX_INIT_W_CONSTRUCTORS
934 #endif /* SOLARIS || BSD */
936 /* Asterisk REQUIRES recursive (not error checking) mutexes
937 and will not run without them. */
938 #if defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP)
939 #define PTHREAD_MUTEX_INIT_VALUE PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
940 #define AST_MUTEX_KIND PTHREAD_MUTEX_RECURSIVE_NP
942 #define PTHREAD_MUTEX_INIT_VALUE PTHREAD_MUTEX_INITIALIZER
943 #define AST_MUTEX_KIND PTHREAD_MUTEX_RECURSIVE
944 #endif /* PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP */
948 #define __ast_mutex_logger(...) do { if (canlog) ast_log(LOG_ERROR, __VA_ARGS__); else fprintf(stderr, __VA_ARGS__); } while (0)
951 #define DO_THREAD_CRASH do { *((int *)(0)) = 1; } while(0)
953 #define DO_THREAD_CRASH do { } while (0)
956 #define AST_MUTEX_INIT_VALUE { PTHREAD_MUTEX_INIT_VALUE, { NULL }, { 0 }, 0, { NULL }, { 0 } }
958 #define AST_MAX_REENTRANCY 10
960 struct ast_mutex_info {
961 pthread_mutex_t mutex;
962 const char *file[AST_MAX_REENTRANCY];
963 int lineno[AST_MAX_REENTRANCY];
965 const char *func[AST_MAX_REENTRANCY];
966 pthread_t thread[AST_MAX_REENTRANCY];
969 typedef struct ast_mutex_info ast_mutex_t;
971 typedef pthread_cond_t ast_cond_t;
973 static pthread_mutex_t empty_mutex;
975 static void __attribute__((constructor)) init_empty_mutex(void)
977 memset(&empty_mutex, 0, sizeof(empty_mutex));
980 static inline int __ast_pthread_mutex_init_attr(const char *filename, int lineno, const char *func,
981 const char *mutex_name, ast_mutex_t *t,
982 pthread_mutexattr_t *attr)
984 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
985 int canlog = strcmp(filename, "logger.c");
987 if ((t->mutex) != ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
988 if ((t->mutex) != (empty_mutex)) {
989 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is already initialized.\n",
990 filename, lineno, func, mutex_name);
991 __ast_mutex_logger("%s line %d (%s): Error: previously initialization of mutex '%s'.\n",
992 t->file[0], t->lineno[0], t->func[0], mutex_name);
999 t->file[0] = filename;
1000 t->lineno[0] = lineno;
1005 return pthread_mutex_init(&t->mutex, attr);
1008 static inline int __ast_pthread_mutex_init(const char *filename, int lineno, const char *func,
1009 const char *mutex_name, ast_mutex_t *t)
1011 static pthread_mutexattr_t attr;
1013 pthread_mutexattr_init(&attr);
1014 pthread_mutexattr_settype(&attr, AST_MUTEX_KIND);
1016 return __ast_pthread_mutex_init_attr(filename, lineno, func, mutex_name, t, &attr);
1018 #define ast_mutex_init(pmutex) __ast_pthread_mutex_init(__FILE__, __LINE__, __PRETTY_FUNCTION__, #pmutex, pmutex)
1020 static inline int __ast_pthread_mutex_destroy(const char *filename, int lineno, const char *func,
1021 const char *mutex_name, ast_mutex_t *t)
1024 int canlog = strcmp(filename, "logger.c");
1026 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
1027 if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
1028 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
1029 filename, lineno, func, mutex_name);
1033 res = pthread_mutex_trylock(&t->mutex);
1036 pthread_mutex_unlock(&t->mutex);
1039 __ast_mutex_logger("%s line %d (%s): Error: attempt to destroy invalid mutex '%s'.\n",
1040 filename, lineno, func, mutex_name);
1043 __ast_mutex_logger("%s line %d (%s): Error: attempt to destroy locked mutex '%s'.\n",
1044 filename, lineno, func, mutex_name);
1045 __ast_mutex_logger("%s line %d (%s): Error: '%s' was locked here.\n",
1046 t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
1050 if ((res = pthread_mutex_destroy(&t->mutex)))
1051 __ast_mutex_logger("%s line %d (%s): Error destroying mutex: %s\n",
1052 filename, lineno, func, strerror(res));
1053 #ifndef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
1055 t->mutex = PTHREAD_MUTEX_INIT_VALUE;
1057 t->file[0] = filename;
1058 t->lineno[0] = lineno;
1064 static inline int __ast_pthread_mutex_lock(const char *filename, int lineno, const char *func,
1065 const char* mutex_name, ast_mutex_t *t)
1068 int canlog = strcmp(filename, "logger.c");
1070 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
1071 if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
1072 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
1073 filename, lineno, func, mutex_name);
1076 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
1078 #ifdef DETECT_DEADLOCKS
1080 time_t seconds = time(NULL);
1083 #ifdef HAVE_MTX_PROFILE
1084 ast_mark(mtx_prof, 1);
1086 res = pthread_mutex_trylock(&t->mutex);
1087 #ifdef HAVE_MTX_PROFILE
1088 ast_mark(mtx_prof, 0);
1091 current = time(NULL);
1092 if ((current - seconds) && (!((current - seconds) % 5))) {
1093 __ast_mutex_logger("%s line %d (%s): Deadlock? waited %d sec for mutex '%s'?\n",
1094 filename, lineno, func, (int)(current - seconds), mutex_name);
1095 __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
1096 t->file[t->reentrancy-1], t->lineno[t->reentrancy-1],
1097 t->func[t->reentrancy-1], mutex_name);
1101 } while (res == EBUSY);
1104 #ifdef HAVE_MTX_PROFILE
1105 ast_mark(mtx_prof, 1);
1106 res = pthread_mutex_trylock(&t->mutex);
1107 ast_mark(mtx_prof, 0);
1110 res = pthread_mutex_lock(&t->mutex);
1111 #endif /* DETECT_DEADLOCKS */
1114 if (t->reentrancy < AST_MAX_REENTRANCY) {
1115 t->file[t->reentrancy] = filename;
1116 t->lineno[t->reentrancy] = lineno;
1117 t->func[t->reentrancy] = func;
1118 t->thread[t->reentrancy] = pthread_self();
1121 __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
1122 filename, lineno, func, mutex_name);
1125 __ast_mutex_logger("%s line %d (%s): Error obtaining mutex: %s\n",
1126 filename, lineno, func, strerror(errno));
1133 static inline int __ast_pthread_mutex_trylock(const char *filename, int lineno, const char *func,
1134 const char* mutex_name, ast_mutex_t *t)
1137 int canlog = strcmp(filename, "logger.c");
1139 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
1140 if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
1141 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
1142 filename, lineno, func, mutex_name);
1145 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
1147 if (!(res = pthread_mutex_trylock(&t->mutex))) {
1148 if (t->reentrancy < AST_MAX_REENTRANCY) {
1149 t->file[t->reentrancy] = filename;
1150 t->lineno[t->reentrancy] = lineno;
1151 t->func[t->reentrancy] = func;
1152 t->thread[t->reentrancy] = pthread_self();
1155 __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
1156 filename, lineno, func, mutex_name);
1159 __ast_mutex_logger("%s line %d (%s): Warning: '%s' was locked here.\n",
1160 t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
1166 static inline int __ast_pthread_mutex_unlock(const char *filename, int lineno, const char *func,
1167 const char *mutex_name, ast_mutex_t *t)
1170 int canlog = strcmp(filename, "logger.c");
1172 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
1173 if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
1174 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
1175 filename, lineno, func, mutex_name);
1179 if (t->reentrancy && (t->thread[t->reentrancy-1] != pthread_self())) {
1180 __ast_mutex_logger("%s line %d (%s): attempted unlock mutex '%s' without owning it!\n",
1181 filename, lineno, func, mutex_name);
1182 __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
1183 t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
1187 if (--t->reentrancy < 0) {
1188 __ast_mutex_logger("%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
1189 filename, lineno, func, mutex_name);
1193 if (t->reentrancy < AST_MAX_REENTRANCY) {
1194 t->file[t->reentrancy] = NULL;
1195 t->lineno[t->reentrancy] = 0;
1196 t->func[t->reentrancy] = NULL;
1197 t->thread[t->reentrancy] = 0;
1200 if ((res = pthread_mutex_unlock(&t->mutex))) {
1201 __ast_mutex_logger("%s line %d (%s): Error releasing mutex: %s\n",
1202 filename, lineno, func, strerror(res));
1209 static inline int __ast_cond_init(const char *filename, int lineno, const char *func,
1210 const char *cond_name, ast_cond_t *cond, pthread_condattr_t *cond_attr)
1212 return pthread_cond_init(cond, cond_attr);
1215 static inline int __ast_cond_signal(const char *filename, int lineno, const char *func,
1216 const char *cond_name, ast_cond_t *cond)
1218 return pthread_cond_signal(cond);
1221 static inline int __ast_cond_broadcast(const char *filename, int lineno, const char *func,
1222 const char *cond_name, ast_cond_t *cond)
1224 return pthread_cond_broadcast(cond);
1227 static inline int __ast_cond_destroy(const char *filename, int lineno, const char *func,
1228 const char *cond_name, ast_cond_t *cond)
1230 return pthread_cond_destroy(cond);
1233 static inline int __ast_cond_wait(const char *filename, int lineno, const char *func,
1234 const char *cond_name, const char *mutex_name,
1235 ast_cond_t *cond, ast_mutex_t *t)
1238 int canlog = strcmp(filename, "logger.c");
1240 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
1241 if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
1242 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
1243 filename, lineno, func, mutex_name);
1247 if (t->reentrancy && (t->thread[t->reentrancy-1] != pthread_self())) {
1248 __ast_mutex_logger("%s line %d (%s): attempted unlock mutex '%s' without owning it!\n",
1249 filename, lineno, func, mutex_name);
1250 __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
1251 t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
1255 if (--t->reentrancy < 0) {
1256 __ast_mutex_logger("%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
1257 filename, lineno, func, mutex_name);
1261 if (t->reentrancy < AST_MAX_REENTRANCY) {
1262 t->file[t->reentrancy] = NULL;
1263 t->lineno[t->reentrancy] = 0;
1264 t->func[t->reentrancy] = NULL;
1265 t->thread[t->reentrancy] = 0;
1268 if ((res = pthread_cond_wait(cond, &t->mutex))) {
1269 __ast_mutex_logger("%s line %d (%s): Error waiting on condition mutex '%s'\n",
1270 filename, lineno, func, strerror(res));
1273 if (t->reentrancy < AST_MAX_REENTRANCY) {
1274 t->file[t->reentrancy] = filename;
1275 t->lineno[t->reentrancy] = lineno;
1276 t->func[t->reentrancy] = func;
1277 t->thread[t->reentrancy] = pthread_self();
1280 __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
1281 filename, lineno, func, mutex_name);
1288 static inline int __ast_cond_timedwait(const char *filename, int lineno, const char *func,
1289 const char *cond_name, const char *mutex_name, ast_cond_t *cond,
1290 ast_mutex_t *t, const struct timespec *abstime)
1293 int canlog = strcmp(filename, "logger.c");
1295 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
1296 if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
1297 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
1298 filename, lineno, func, mutex_name);
1302 if (t->reentrancy && (t->thread[t->reentrancy-1] != pthread_self())) {
1303 __ast_mutex_logger("%s line %d (%s): attempted unlock mutex '%s' without owning it!\n",
1304 filename, lineno, func, mutex_name);
1305 __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
1306 t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
1310 if (--t->reentrancy < 0) {
1311 __ast_mutex_logger("%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
1312 filename, lineno, func, mutex_name);
1316 if (t->reentrancy < AST_MAX_REENTRANCY) {
1317 t->file[t->reentrancy] = NULL;
1318 t->lineno[t->reentrancy] = 0;
1319 t->func[t->reentrancy] = NULL;
1320 t->thread[t->reentrancy] = 0;
1323 if ((res = pthread_cond_timedwait(cond, &t->mutex, abstime)) && (res != ETIMEDOUT)) {
1324 __ast_mutex_logger("%s line %d (%s): Error waiting on condition mutex '%s'\n",
1325 filename, lineno, func, strerror(res));
1328 if (t->reentrancy < AST_MAX_REENTRANCY) {
1329 t->file[t->reentrancy] = filename;
1330 t->lineno[t->reentrancy] = lineno;
1331 t->func[t->reentrancy] = func;
1332 t->thread[t->reentrancy] = pthread_self();
1335 __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
1336 filename, lineno, func, mutex_name);
1343 #define ast_mutex_destroy(a) __ast_pthread_mutex_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
1344 #define ast_mutex_lock(a) __ast_pthread_mutex_lock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
1345 #define ast_mutex_unlock(a) __ast_pthread_mutex_unlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
1346 #define ast_mutex_trylock(a) __ast_pthread_mutex_trylock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
1347 #define ast_cond_init(cond, attr) __ast_cond_init(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond, attr)
1348 #define ast_cond_destroy(cond) __ast_cond_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond)
1349 #define ast_cond_signal(cond) __ast_cond_signal(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond)
1350 #define ast_cond_broadcast(cond) __ast_cond_broadcast(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond)
1351 #define ast_cond_wait(cond, mutex) __ast_cond_wait(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, #mutex, cond, mutex)
1352 #define ast_cond_timedwait(cond, mutex, time) __ast_cond_timedwait(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, #mutex, cond, mutex, time)
1354 #else /* !DEBUG_THREADS */
1357 typedef pthread_mutex_t ast_mutex_t;
1359 #define AST_MUTEX_INIT_VALUE ((ast_mutex_t) PTHREAD_MUTEX_INIT_VALUE)
1361 static inline int ast_mutex_init(ast_mutex_t *pmutex)
1363 pthread_mutexattr_t attr;
1365 pthread_mutexattr_init(&attr);
1366 pthread_mutexattr_settype(&attr, AST_MUTEX_KIND);
1368 return pthread_mutex_init(pmutex, &attr);
1371 #define ast_pthread_mutex_init(pmutex,a) pthread_mutex_init(pmutex,a)
1373 static inline int ast_mutex_unlock(ast_mutex_t *pmutex)
1375 return pthread_mutex_unlock(pmutex);
1378 static inline int ast_mutex_destroy(ast_mutex_t *pmutex)
1380 return pthread_mutex_destroy(pmutex);
1383 static inline int ast_mutex_lock(ast_mutex_t *pmutex)
1388 static inline int ast_mutex_trylock(ast_mutex_t *pmutex)
1390 return pthread_mutex_trylock(pmutex);
1393 typedef pthread_cond_t ast_cond_t;
1395 static inline int ast_cond_init(ast_cond_t *cond, pthread_condattr_t *cond_attr)
1397 return pthread_cond_init(cond, cond_attr);
1400 static inline int ast_cond_signal(ast_cond_t *cond)
1402 return pthread_cond_signal(cond);
1405 static inline int ast_cond_broadcast(ast_cond_t *cond)
1407 return pthread_cond_broadcast(cond);
1410 static inline int ast_cond_destroy(ast_cond_t *cond)
1412 return pthread_cond_destroy(cond);
1415 static inline int ast_cond_wait(ast_cond_t *cond, ast_mutex_t *t)
1417 return pthread_cond_wait(cond, t);
1420 static inline int ast_cond_timedwait(ast_cond_t *cond, ast_mutex_t *t, const struct timespec *abstime)
1422 return pthread_cond_timedwait(cond, t, abstime);
1425 #endif /* !DEBUG_THREADS */
1427 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
1428 /* If AST_MUTEX_INIT_W_CONSTRUCTORS is defined, use file scope
1429 constructors/destructors to create/destroy mutexes. */
1430 #define __AST_MUTEX_DEFINE(scope, mutex) \
1431 scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE; \
1432 static void __attribute__ ((constructor)) init_##mutex(void) \
1434 ast_mutex_init(&mutex); \
1436 static void __attribute__ ((destructor)) fini_##mutex(void) \
1438 ast_mutex_destroy(&mutex); \
1440 #else /* !AST_MUTEX_INIT_W_CONSTRUCTORS */
1441 /* By default, use static initialization of mutexes. */
1442 #define __AST_MUTEX_DEFINE(scope, mutex) \
1443 scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE
1444 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
1446 #define pthread_mutex_t use_ast_mutex_t_instead_of_pthread_mutex_t
1447 #define pthread_mutex_lock use_ast_mutex_lock_instead_of_pthread_mutex_lock
1448 #define pthread_mutex_unlock use_ast_mutex_unlock_instead_of_pthread_mutex_unlock
1449 #define pthread_mutex_trylock use_ast_mutex_trylock_instead_of_pthread_mutex_trylock
1450 #define pthread_mutex_init use_ast_mutex_init_instead_of_pthread_mutex_init
1451 #define pthread_mutex_destroy use_ast_mutex_destroy_instead_of_pthread_mutex_destroy
1452 #define pthread_cond_t use_ast_cond_t_instead_of_pthread_cond_t
1453 #define pthread_cond_init use_ast_cond_init_instead_of_pthread_cond_init
1454 #define pthread_cond_destroy use_ast_cond_destroy_instead_of_pthread_cond_destroy
1455 #define pthread_cond_signal use_ast_cond_signal_instead_of_pthread_cond_signal
1456 #define pthread_cond_broadcast use_ast_cond_broadcast_instead_of_pthread_cond_broadcast
1457 #define pthread_cond_wait use_ast_cond_wait_instead_of_pthread_cond_wait
1458 #define pthread_cond_timedwait use_ast_cond_timedwait_instead_of_pthread_cond_timedwait
1460 #define AST_MUTEX_DEFINE_STATIC(mutex) __AST_MUTEX_DEFINE(static, mutex)
1462 #define AST_MUTEX_INITIALIZER __use_AST_MUTEX_DEFINE_STATIC_rather_than_AST_MUTEX_INITIALIZER__
1464 #define gethostbyname __gethostbyname__is__not__reentrant__use__ast_gethostbyname__instead__
1467 #define pthread_create __use_ast_pthread_create_instead__
1470 typedef pthread_rwlock_t ast_rwlock_t;
1472 static inline int ast_rwlock_init(ast_rwlock_t *prwlock)
1474 pthread_rwlockattr_t attr;
1476 pthread_rwlockattr_init(&attr);
1478 #ifdef HAVE_PTHREAD_RWLOCK_PREFER_WRITER_NP
1479 pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NP);
1482 return pthread_rwlock_init(prwlock, &attr);
1485 static inline int ast_rwlock_destroy(ast_rwlock_t *prwlock)
1487 return pthread_rwlock_destroy(prwlock);
1490 static inline int ast_rwlock_unlock(ast_rwlock_t *prwlock)
1492 return pthread_rwlock_unlock(prwlock);
1495 static inline int ast_rwlock_rdlock(ast_rwlock_t *prwlock)
1497 return pthread_rwlock_rdlock(prwlock);
1500 static inline int ast_rwlock_tryrdlock(ast_rwlock_t *prwlock)
1502 return pthread_rwlock_tryrdlock(prwlock);
1505 static inline int ast_rwlock_wrlock(ast_rwlock_t *prwlock)
1507 return pthread_rwlock_wrlock(prwlock);
1510 static inline int ast_rwlock_trywrlock(ast_rwlock_t *prwlock)
1512 return pthread_rwlock_trywrlock(prwlock);
1515 /* Statically declared read/write locks */
1517 #ifndef HAVE_PTHREAD_RWLOCK_INITIALIZER
1518 #define __AST_RWLOCK_DEFINE(scope, rwlock) \
1519 scope ast_rwlock_t rwlock; \
1520 static void __attribute__ ((constructor)) init_##rwlock(void) \
1522 ast_rwlock_init(&rwlock); \
1524 static void __attribute__ ((destructor)) fini_##rwlock(void) \
1526 ast_rwlock_destroy(&rwlock); \
1529 #define AST_RWLOCK_INIT_VALUE PTHREAD_RWLOCK_INITIALIZER
1530 #define __AST_RWLOCK_DEFINE(scope, rwlock) \
1531 scope ast_rwlock_t rwlock = AST_RWLOCK_INIT_VALUE
1534 #define AST_RWLOCK_DEFINE_STATIC(rwlock) __AST_RWLOCK_DEFINE(static, rwlock)
1537 * Initial support for atomic instructions.
1538 * For platforms that have it, use the native cpu instruction to
1539 * implement them. For other platforms, resort to a 'slow' version
1540 * (defined in utils.c) that protects the atomic instruction with
1542 * The slow versions is always available, for testing purposes,
1543 * as ast_atomic_fetchadd_int_slow()
1546 int ast_atomic_fetchadd_int_slow(volatile int *p, int v);
1548 #if defined(HAVE_OSX_ATOMICS)
1549 #include "libkern/OSAtomic.h"
1552 /*! \brief Atomically add v to *p and return * the previous value of *p.
1553 * This can be used to handle reference counts, and the return value
1554 * can be used to generate unique identifiers.
1557 #if defined(HAVE_GCC_ATOMICS)
1558 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
1560 return __sync_fetch_and_add(p, v);
1562 #elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 4)
1563 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
1565 return OSAtomicAdd32(v, (int32_t *) p);
1567 #elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 8)
1568 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
1570 return OSAtomicAdd64(v, (int64_t *) p);
1571 #elif defined (__i386__)
1572 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
1575 " lock xaddl %0, %1 ; "
1576 : "+r" (v), /* 0 (result) */
1578 : "m" (*p)); /* 2 */
1581 #else /* low performance version in utils.c */
1582 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
1584 return ast_atomic_fetchadd_int_slow(p, v);
1588 /*! \brief decrement *p by 1 and return true if the variable has reached 0.
1589 * Useful e.g. to check if a refcount has reached 0.
1591 #if defined(HAVE_GCC_ATOMICS)
1592 AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
1594 return __sync_sub_and_fetch(p, 1) == 0;
1596 #elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 4)
1597 AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
1599 return OSAtomicAdd32( -1, (int32_t *) p) == 0;
1601 #elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 8)
1602 AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
1604 return OSAtomicAdd64( -1, (int64_t *) p) == 0;
1606 AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
1608 int a = ast_atomic_fetchadd_int(p, -1);
1609 return a == 1; /* true if the value is 0 now (so it was 1 previously) */
1613 #ifndef DEBUG_CHANNEL_LOCKS
1614 /*! \brief Lock a channel. If DEBUG_CHANNEL_LOCKS is defined
1615 in the Makefile, print relevant output for debugging */
1616 #define ast_channel_lock(x) ast_mutex_lock(&x->lock)
1617 /*! \brief Unlock a channel. If DEBUG_CHANNEL_LOCKS is defined
1618 in the Makefile, print relevant output for debugging */
1619 #define ast_channel_unlock(x) ast_mutex_unlock(&x->lock)
1620 /*! \brief Try locking a channel. If DEBUG_CHANNEL_LOCKS is defined
1621 in the Makefile, print relevant output for debugging */
1622 #define ast_channel_trylock(x) ast_mutex_trylock(&x->lock)
1627 /*! \brief Lock AST channel (and print debugging output)
1628 \note You need to enable DEBUG_CHANNEL_LOCKS for this function */
1629 int ast_channel_lock(struct ast_channel *chan);
1631 /*! \brief Unlock AST channel (and print debugging output)
1632 \note You need to enable DEBUG_CHANNEL_LOCKS for this function
1634 int ast_channel_unlock(struct ast_channel *chan);
1636 /*! \brief Lock AST channel (and print debugging output)
1637 \note You need to enable DEBUG_CHANNEL_LOCKS for this function */
1638 int ast_channel_trylock(struct ast_channel *chan);
1644 #define AST_LIST_LOCK(head) \
1645 ast_mutex_lock(&(head)->lock)
1648 \brief Write locks a list.
1649 \param head This is a pointer to the list head structure
1651 This macro attempts to place an exclusive write lock in the
1652 list head structure pointed to by head.
1653 Returns non-zero on success, 0 on failure
1655 #define AST_RWLIST_WRLOCK(head) \
1656 ast_rwlock_wrlock(&(head)->lock)
1659 \brief Read locks a list.
1660 \param head This is a pointer to the list head structure
1662 This macro attempts to place a read lock in the
1663 list head structure pointed to by head.
1664 Returns non-zero on success, 0 on failure
1666 #define AST_RWLIST_RDLOCK(head) \
1667 ast_rwlock_rdlock(&(head)->lock)
1670 \brief Locks a list, without blocking if the list is locked.
1671 \param head This is a pointer to the list head structure
1673 This macro attempts to place an exclusive lock in the
1674 list head structure pointed to by head.
1675 Returns non-zero on success, 0 on failure
1677 #define AST_LIST_TRYLOCK(head) \
1678 ast_mutex_trylock(&(head)->lock)
1681 \brief Write locks a list, without blocking if the list is locked.
1682 \param head This is a pointer to the list head structure
1684 This macro attempts to place an exclusive write lock in the
1685 list head structure pointed to by head.
1686 Returns non-zero on success, 0 on failure
1688 #define AST_RWLIST_TRYWRLOCK(head) \
1689 ast_rwlock_trywrlock(&(head)->lock)
1692 \brief Read locks a list, without blocking if the list is locked.
1693 \param head This is a pointer to the list head structure
1695 This macro attempts to place a read lock in the
1696 list head structure pointed to by head.
1697 Returns non-zero on success, 0 on failure
1699 #define AST_RWLIST_TRYRDLOCK(head) \
1700 ast_rwlock_tryrdlock(&(head)->lock)
1703 \brief Attempts to unlock a list.
1704 \param head This is a pointer to the list head structure
1706 This macro attempts to remove an exclusive lock from the
1707 list head structure pointed to by head. If the list
1708 was not locked by this thread, this macro has no effect.
1710 #define AST_LIST_UNLOCK(head) \
1711 ast_mutex_unlock(&(head)->lock)
1714 \brief Attempts to unlock a read/write based list.
1715 \param head This is a pointer to the list head structure
1717 This macro attempts to remove a read or write lock from the
1718 list head structure pointed to by head. If the list
1719 was not locked by this thread, this macro has no effect.
1721 #define AST_RWLIST_UNLOCK(head) \
1722 ast_rwlock_unlock(&(head)->lock)
1725 \brief Defines a structure to be used to hold a list of specified type.
1726 \param name This will be the name of the defined structure.
1727 \param type This is the type of each list entry.
1729 This macro creates a structure definition that can be used
1730 to hold a list of the entries of type \a type. It does not actually
1731 declare (allocate) a structure; to do that, either follow this
1732 macro with the desired name of the instance you wish to declare,
1733 or use the specified \a name to declare instances elsewhere.
1737 static AST_LIST_HEAD(entry_list, entry) entries;
1740 This would define \c struct \c entry_list, and declare an instance of it named
1741 \a entries, all intended to hold a list of type \c struct \c entry.
1743 #define AST_LIST_HEAD(name, type) \
1745 struct type *first; \
1746 struct type *last; \
1751 \brief Defines a structure to be used to hold a read/write list of specified type.
1752 \param name This will be the name of the defined structure.
1753 \param type This is the type of each list entry.
1755 This macro creates a structure definition that can be used
1756 to hold a list of the entries of type \a type. It does not actually
1757 declare (allocate) a structure; to do that, either follow this
1758 macro with the desired name of the instance you wish to declare,
1759 or use the specified \a name to declare instances elsewhere.
1763 static AST_RWLIST_HEAD(entry_list, entry) entries;
1766 This would define \c struct \c entry_list, and declare an instance of it named
1767 \a entries, all intended to hold a list of type \c struct \c entry.
1769 #define AST_RWLIST_HEAD(name, type) \
1771 struct type *first; \
1772 struct type *last; \
1773 ast_rwlock_t lock; \
1777 \brief Defines a structure to be used to hold a list of specified type (with no lock).
1778 \param name This will be the name of the defined structure.
1779 \param type This is the type of each list entry.
1781 This macro creates a structure definition that can be used
1782 to hold a list of the entries of type \a type. It does not actually
1783 declare (allocate) a structure; to do that, either follow this
1784 macro with the desired name of the instance you wish to declare,
1785 or use the specified \a name to declare instances elsewhere.
1789 static AST_LIST_HEAD_NOLOCK(entry_list, entry) entries;
1792 This would define \c struct \c entry_list, and declare an instance of it named
1793 \a entries, all intended to hold a list of type \c struct \c entry.
1795 #define AST_LIST_HEAD_NOLOCK(name, type) \
1797 struct type *first; \
1798 struct type *last; \
1802 \brief Defines initial values for a declaration of AST_LIST_HEAD
1804 #define AST_LIST_HEAD_INIT_VALUE { \
1807 .lock = AST_MUTEX_INIT_VALUE, \
1811 \brief Defines initial values for a declaration of AST_RWLIST_HEAD
1813 #define AST_RWLIST_HEAD_INIT_VALUE { \
1816 .lock = AST_RWLOCK_INIT_VALUE, \
1820 \brief Defines initial values for a declaration of AST_LIST_HEAD_NOLOCK
1822 #define AST_LIST_HEAD_NOLOCK_INIT_VALUE { \
1828 \brief Defines a structure to be used to hold a list of specified type, statically initialized.
1829 \param name This will be the name of the defined structure.
1830 \param type This is the type of each list entry.
1832 This macro creates a structure definition that can be used
1833 to hold a list of the entries of type \a type, and allocates an instance
1834 of it, initialized to be empty.
1838 static AST_LIST_HEAD_STATIC(entry_list, entry);
1841 This would define \c struct \c entry_list, intended to hold a list of
1842 type \c struct \c entry.
1844 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
1845 #define AST_LIST_HEAD_STATIC(name, type) \
1847 struct type *first; \
1848 struct type *last; \
1851 static void __attribute__ ((constructor)) init_##name(void) \
1853 AST_LIST_HEAD_INIT(&name); \
1855 static void __attribute__ ((destructor)) fini_##name(void) \
1857 AST_LIST_HEAD_DESTROY(&name); \
1859 struct __dummy_##name
1861 #define AST_LIST_HEAD_STATIC(name, type) \
1863 struct type *first; \
1864 struct type *last; \
1866 } name = AST_LIST_HEAD_INIT_VALUE
1870 \brief Defines a structure to be used to hold a read/write list of specified type, statically initialized.
1871 \param name This will be the name of the defined structure.
1872 \param type This is the type of each list entry.
1874 This macro creates a structure definition that can be used
1875 to hold a list of the entries of type \a type, and allocates an instance
1876 of it, initialized to be empty.
1880 static AST_RWLIST_HEAD_STATIC(entry_list, entry);
1883 This would define \c struct \c entry_list, intended to hold a list of
1884 type \c struct \c entry.
1886 #ifndef AST_RWLOCK_INIT_VALUE
1887 #define AST_RWLIST_HEAD_STATIC(name, type) \
1889 struct type *first; \
1890 struct type *last; \
1891 ast_rwlock_t lock; \
1893 static void __attribute__ ((constructor)) init_##name(void) \
1895 AST_RWLIST_HEAD_INIT(&name); \
1897 static void __attribute__ ((destructor)) fini_##name(void) \
1899 AST_RWLIST_HEAD_DESTROY(&name); \
1901 struct __dummy_##name
1903 #define AST_RWLIST_HEAD_STATIC(name, type) \
1905 struct type *first; \
1906 struct type *last; \
1907 ast_rwlock_t lock; \
1908 } name = AST_RWLIST_HEAD_INIT_VALUE
1912 \brief Defines a structure to be used to hold a list of specified type, statically initialized.
1914 This is the same as AST_LIST_HEAD_STATIC, except without the lock included.
1916 #define AST_LIST_HEAD_NOLOCK_STATIC(name, type) \
1918 struct type *first; \
1919 struct type *last; \
1920 } name = AST_LIST_HEAD_NOLOCK_INIT_VALUE
1923 \brief Initializes a list head structure with a specified first entry.
1924 \param head This is a pointer to the list head structure
1925 \param entry pointer to the list entry that will become the head of the list
1927 This macro initializes a list head structure by setting the head
1928 entry to the supplied value and recreating the embedded lock.
1930 #define AST_LIST_HEAD_SET(head, entry) do { \
1931 (head)->first = (entry); \
1932 (head)->last = (entry); \
1933 ast_mutex_init(&(head)->lock); \
1937 \brief Initializes an rwlist head structure with a specified first entry.
1938 \param head This is a pointer to the list head structure
1939 \param entry pointer to the list entry that will become the head of the list
1941 This macro initializes a list head structure by setting the head
1942 entry to the supplied value and recreating the embedded lock.
1944 #define AST_RWLIST_HEAD_SET(head, entry) do { \
1945 (head)->first = (entry); \
1946 (head)->last = (entry); \
1947 ast_rwlock_init(&(head)->lock); \
1951 \brief Initializes a list head structure with a specified first entry.
1952 \param head This is a pointer to the list head structure
1953 \param entry pointer to the list entry that will become the head of the list
1955 This macro initializes a list head structure by setting the head
1956 entry to the supplied value.
1958 #define AST_LIST_HEAD_SET_NOLOCK(head, entry) do { \
1959 (head)->first = (entry); \
1960 (head)->last = (entry); \
1964 \brief Declare a forward link structure inside a list entry.
1965 \param type This is the type of each list entry.
1967 This macro declares a structure to be used to link list entries together.
1968 It must be used inside the definition of the structure named in
1969 \a type, as follows:
1974 AST_LIST_ENTRY(list_entry) list;
1978 The field name \a list here is arbitrary, and can be anything you wish.
1980 #define AST_LIST_ENTRY(type) \
1982 struct type *next; \
1985 #define AST_RWLIST_ENTRY AST_LIST_ENTRY
1988 \brief Returns the first entry contained in a list.
1989 \param head This is a pointer to the list head structure
1991 #define AST_LIST_FIRST(head) ((head)->first)
1993 #define AST_RWLIST_FIRST AST_LIST_FIRST
1996 \brief Returns the last entry contained in a list.
1997 \param head This is a pointer to the list head structure
1999 #define AST_LIST_LAST(head) ((head)->last)
2001 #define AST_RWLIST_LAST AST_LIST_LAST
2004 \brief Returns the next entry in the list after the given entry.
2005 \param elm This is a pointer to the current entry.
2006 \param field This is the name of the field (declared using AST_LIST_ENTRY())
2007 used to link entries of this list together.
2009 #define AST_LIST_NEXT(elm, field) ((elm)->field.next)
2011 #define AST_RWLIST_NEXT AST_LIST_NEXT
2014 \brief Checks whether the specified list contains any entries.
2015 \param head This is a pointer to the list head structure
2017 Returns non-zero if the list has entries, zero if not.
2019 #define AST_LIST_EMPTY(head) (AST_LIST_FIRST(head) == NULL)
2021 #define AST_RWLIST_EMPTY AST_LIST_EMPTY
2024 \brief Loops over (traverses) the entries in a list.
2025 \param head This is a pointer to the list head structure
2026 \param var This is the name of the variable that will hold a pointer to the
2027 current list entry on each iteration. It must be declared before calling
2029 \param field This is the name of the field (declared using AST_LIST_ENTRY())
2030 used to link entries of this list together.
2032 This macro is use to loop over (traverse) the entries in a list. It uses a
2033 \a for loop, and supplies the enclosed code with a pointer to each list
2034 entry as it loops. It is typically used as follows:
2036 static AST_LIST_HEAD(entry_list, list_entry) entries;
2040 AST_LIST_ENTRY(list_entry) list;
2043 struct list_entry *current;
2045 AST_LIST_TRAVERSE(&entries, current, list) {
2046 (do something with current here)
2049 \warning If you modify the forward-link pointer contained in the \a current entry while
2050 inside the loop, the behavior will be unpredictable. At a minimum, the following
2051 macros will modify the forward-link pointer, and should not be used inside
2052 AST_LIST_TRAVERSE() against the entry pointed to by the \a current pointer without
2053 careful consideration of their consequences:
2054 \li AST_LIST_NEXT() (when used as an lvalue)
2055 \li AST_LIST_INSERT_AFTER()
2056 \li AST_LIST_INSERT_HEAD()
2057 \li AST_LIST_INSERT_TAIL()
2059 #define AST_LIST_TRAVERSE(head,var,field) \
2060 for((var) = (head)->first; (var); (var) = (var)->field.next)
2062 #define AST_RWLIST_TRAVERSE AST_LIST_TRAVERSE
2065 \brief Loops safely over (traverses) the entries in a list.
2066 \param head This is a pointer to the list head structure
2067 \param var This is the name of the variable that will hold a pointer to the
2068 current list entry on each iteration. It must be declared before calling
2070 \param field This is the name of the field (declared using AST_LIST_ENTRY())
2071 used to link entries of this list together.
2073 This macro is used to safely loop over (traverse) the entries in a list. It
2074 uses a \a for loop, and supplies the enclosed code with a pointer to each list
2075 entry as it loops. It is typically used as follows:
2078 static AST_LIST_HEAD(entry_list, list_entry) entries;
2082 AST_LIST_ENTRY(list_entry) list;
2085 struct list_entry *current;
2087 AST_LIST_TRAVERSE_SAFE_BEGIN(&entries, current, list) {
2088 (do something with current here)
2090 AST_LIST_TRAVERSE_SAFE_END;
2093 It differs from AST_LIST_TRAVERSE() in that the code inside the loop can modify
2094 (or even free, after calling AST_LIST_REMOVE_CURRENT()) the entry pointed to by
2095 the \a current pointer without affecting the loop traversal.
2097 #define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field) { \
2098 typeof((head)->first) __list_next; \
2099 typeof((head)->first) __list_prev = NULL; \
2100 typeof((head)->first) __new_prev = NULL; \
2101 for ((var) = (head)->first, __new_prev = (var), \
2102 __list_next = (var) ? (var)->field.next : NULL; \
2104 __list_prev = __new_prev, (var) = __list_next, \
2105 __new_prev = (var), \
2106 __list_next = (var) ? (var)->field.next : NULL \
2109 #define AST_RWLIST_TRAVERSE_SAFE_BEGIN AST_LIST_TRAVERSE_SAFE_BEGIN
2112 \brief Removes the \a current entry from a list during a traversal.
2113 \param head This is a pointer to the list head structure
2114 \param field This is the name of the field (declared using AST_LIST_ENTRY())
2115 used to link entries of this list together.
2117 \note This macro can \b only be used inside an AST_LIST_TRAVERSE_SAFE_BEGIN()
2118 block; it is used to unlink the current entry from the list without affecting
2119 the list traversal (and without having to re-traverse the list to modify the
2120 previous entry, if any).
2122 #define AST_LIST_REMOVE_CURRENT(head, field) \
2123 __new_prev->field.next = NULL; \
2124 __new_prev = __list_prev; \
2126 __list_prev->field.next = __list_next; \
2128 (head)->first = __list_next; \
2130 (head)->last = __list_prev;
2132 #define AST_RWLIST_REMOVE_CURRENT AST_LIST_REMOVE_CURRENT
2135 \brief Inserts a list entry before the current entry during a traversal.
2136 \param head This is a pointer to the list head structure
2137 \param elm This is a pointer to the entry to be inserted.
2138 \param field This is the name of the field (declared using AST_LIST_ENTRY())
2139 used to link entries of this list together.
2141 \note This macro can \b only be used inside an AST_LIST_TRAVERSE_SAFE_BEGIN()
2144 #define AST_LIST_INSERT_BEFORE_CURRENT(head, elm, field) do { \
2145 if (__list_prev) { \
2146 (elm)->field.next = __list_prev->field.next; \
2147 __list_prev->field.next = elm; \
2149 (elm)->field.next = (head)->first; \
2150 (head)->first = (elm); \
2152 __new_prev = (elm); \
2155 #define AST_RWLIST_INSERT_BEFORE_CURRENT AST_LIST_INSERT_BEFORE_CURRENT
2158 \brief Closes a safe loop traversal block.
2160 #define AST_LIST_TRAVERSE_SAFE_END }
2162 #define AST_RWLIST_TRAVERSE_SAFE_END AST_LIST_TRAVERSE_SAFE_END
2165 \brief Initializes a list head structure.
2166 \param head This is a pointer to the list head structure
2168 This macro initializes a list head structure by setting the head
2169 entry to \a NULL (empty list) and recreating the embedded lock.
2171 #define AST_LIST_HEAD_INIT(head) { \
2172 (head)->first = NULL; \
2173 (head)->last = NULL; \
2174 ast_mutex_init(&(head)->lock); \
2178 \brief Initializes an rwlist head structure.
2179 \param head This is a pointer to the list head structure
2181 This macro initializes a list head structure by setting the head
2182 entry to \a NULL (empty list) and recreating the embedded lock.
2184 #define AST_RWLIST_HEAD_INIT(head) { \
2185 (head)->first = NULL; \
2186 (head)->last = NULL; \
2187 ast_rwlock_init(&(head)->lock); \
2191 \brief Destroys a list head structure.
2192 \param head This is a pointer to the list head structure
2194 This macro destroys a list head structure by setting the head
2195 entry to \a NULL (empty list) and destroying the embedded lock.
2196 It does not free the structure from memory.
2198 #define AST_LIST_HEAD_DESTROY(head) { \
2199 (head)->first = NULL; \
2200 (head)->last = NULL; \
2201 ast_mutex_destroy(&(head)->lock); \
2205 \brief Destroys an rwlist head structure.
2206 \param head This is a pointer to the list head structure
2208 This macro destroys a list head structure by setting the head
2209 entry to \a NULL (empty list) and destroying the embedded lock.
2210 It does not free the structure from memory.
2212 #define AST_RWLIST_HEAD_DESTROY(head) { \
2213 (head)->first = NULL; \
2214 (head)->last = NULL; \
2215 ast_rwlock_destroy(&(head)->lock); \
2219 \brief Initializes a list head structure.
2220 \param head This is a pointer to the list head structure
2222 This macro initializes a list head structure by setting the head
2223 entry to \a NULL (empty list). There is no embedded lock handling
2226 #define AST_LIST_HEAD_INIT_NOLOCK(head) { \
2227 (head)->first = NULL; \
2228 (head)->last = NULL; \
2232 \brief Inserts a list entry after a given entry.
2233 \param head This is a pointer to the list head structure
2234 \param listelm This is a pointer to the entry after which the new entry should
2236 \param elm This is a pointer to the entry to be inserted.
2237 \param field This is the name of the field (declared using AST_LIST_ENTRY())
2238 used to link entries of this list together.
2240 #define AST_LIST_INSERT_AFTER(head, listelm, elm, field) do { \
2241 (elm)->field.next = (listelm)->field.next; \
2242 (listelm)->field.next = (elm); \
2243 if ((head)->last == (listelm)) \
2244 (head)->last = (elm); \
2247 #define AST_RWLIST_INSERT_AFTER AST_LIST_INSERT_AFTER
2250 \brief Inserts a list entry at the head of a list.
2251 \param head This is a pointer to the list head structure
2252 \param elm This is a pointer to the entry to be inserted.
2253 \param field This is the name of the field (declared using AST_LIST_ENTRY())
2254 used to link entries of this list together.
2256 #define AST_LIST_INSERT_HEAD(head, elm, field) do { \
2257 (elm)->field.next = (head)->first; \
2258 (head)->first = (elm); \
2259 if (!(head)->last) \
2260 (head)->last = (elm); \
2263 #define AST_RWLIST_INSERT_HEAD AST_LIST_INSERT_HEAD
2266 \brief Appends a list entry to the tail of a list.
2267 \param head This is a pointer to the list head structure
2268 \param elm This is a pointer to the entry to be appended.
2269 \param field This is the name of the field (declared using AST_LIST_ENTRY())
2270 used to link entries of this list together.
2272 Note: The link field in the appended entry is \b not modified, so if it is
2273 actually the head of a list itself, the entire list will be appended
2274 temporarily (until the next AST_LIST_INSERT_TAIL is performed).
2276 #define AST_LIST_INSERT_TAIL(head, elm, field) do { \
2277 if (!(head)->first) { \
2278 (head)->first = (elm); \
2279 (head)->last = (elm); \
2281 (head)->last->field.next = (elm); \
2282 (head)->last = (elm); \
2286 #define AST_RWLIST_INSERT_TAIL AST_LIST_INSERT_TAIL
2289 \brief Appends a whole list to the tail of a list.
2290 \param head This is a pointer to the list head structure
2291 \param list This is a pointer to the list to be appended.
2292 \param field This is the name of the field (declared using AST_LIST_ENTRY())
2293 used to link entries of this list together.
2295 #define AST_LIST_APPEND_LIST(head, list, field) do { \
2296 if (!(head)->first) { \
2297 (head)->first = (list)->first; \
2298 (head)->last = (list)->last; \
2300 (head)->last->field.next = (list)->first; \
2301 (head)->last = (list)->last; \
2305 #define AST_RWLIST_APPEND_LIST AST_LIST_APPEND_LIST
2308 \brief Removes and returns the head entry from a list.
2309 \param head This is a pointer to the list head structure
2310 \param field This is the name of the field (declared using AST_LIST_ENTRY())
2311 used to link entries of this list together.
2313 Removes the head entry from the list, and returns a pointer to it.
2314 This macro is safe to call on an empty list.
2316 #define AST_LIST_REMOVE_HEAD(head, field) ({ \
2317 typeof((head)->first) cur = (head)->first; \
2319 (head)->first = cur->field.next; \
2320 cur->field.next = NULL; \
2321 if ((head)->last == cur) \
2322 (head)->last = NULL; \
2327 #define AST_RWLIST_REMOVE_HEAD AST_LIST_REMOVE_HEAD
2330 \brief Removes a specific entry from a list.
2331 \param head This is a pointer to the list head structure
2332 \param elm This is a pointer to the entry to be removed.
2333 \param field This is the name of the field (declared using AST_LIST_ENTRY())
2334 used to link entries of this list together.
2335 \warning The removed entry is \b not freed nor modified in any way.
2337 #define AST_LIST_REMOVE(head, elm, field) do { \
2338 if ((head)->first == (elm)) { \
2339 (head)->first = (elm)->field.next; \
2340 if ((head)->last == (elm)) \
2341 (head)->last = NULL; \
2343 typeof(elm) curelm = (head)->first; \
2344 while (curelm && (curelm->field.next != (elm))) \
2345 curelm = curelm->field.next; \
2347 curelm->field.next = (elm)->field.next; \
2348 if ((head)->last == (elm)) \
2349 (head)->last = curelm; \
2352 (elm)->field.next = NULL; \
2355 #define AST_RWLIST_REMOVE AST_LIST_REMOVE
2360 AST_LIST_ENTRY(ast_var_t) entries;
2365 AST_LIST_HEAD_NOLOCK(varshead, ast_var_t);
2367 AST_RWLOCK_DEFINE_STATIC(globalslock);
2368 static struct varshead globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
2371 /* IN CONFLICT: struct ast_var_t *ast_var_assign(const char *name, const char *value); */
2373 static struct ast_var_t *ast_var_assign(const char *name, const char *value);
2375 static void ast_var_delete(struct ast_var_t *var);
2378 #define AST_MAX_EXTENSION 80 /*!< Max length of an extension */
2382 #define PRIORITY_HINT -1 /*!< Special Priority for a hint */
2384 enum ast_extension_states {
2385 AST_EXTENSION_REMOVED = -2, /*!< Extension removed */
2386 AST_EXTENSION_DEACTIVATED = -1, /*!< Extension hint removed */
2387 AST_EXTENSION_NOT_INUSE = 0, /*!< No device INUSE or BUSY */
2388 AST_EXTENSION_INUSE = 1 << 0, /*!< One or more devices INUSE */
2389 AST_EXTENSION_BUSY = 1 << 1, /*!< All devices BUSY */
2390 AST_EXTENSION_UNAVAILABLE = 1 << 2, /*!< All devices UNAVAILABLE/UNREGISTERED */
2391 AST_EXTENSION_RINGING = 1 << 3, /*!< All devices RINGING */
2392 AST_EXTENSION_ONHOLD = 1 << 4, /*!< All devices ONHOLD */
2395 struct ast_custom_function {
2396 const char *name; /*!< Name */
2397 const char *synopsis; /*!< Short description for "show functions" */
2398 const char *desc; /*!< Help text that explains it all */
2399 const char *syntax; /*!< Syntax description */
2400 int (*read)(struct ast_channel *, const char *, char *, char *, size_t); /*!< Read function, if read is supported */
2401 int (*write)(struct ast_channel *, const char *, char *, const char *); /*!< Write function, if write is supported */
2402 AST_RWLIST_ENTRY(ast_custom_function) acflist;
2405 typedef int (ast_switch_f)(struct ast_channel *chan, const char *context,
2406 const char *exten, int priority, const char *callerid, const char *data);
2409 AST_LIST_ENTRY(ast_switch) list;
2410 const char *name; /*!< Name of the switch */
2411 const char *description; /*!< Description of the switch */
2413 ast_switch_f *exists;
2414 ast_switch_f *canmatch;
2416 ast_switch_f *matchmore;
2420 static char *config = "extensions.conf";
2421 static char *registrar = "conf2ael";
2422 static char userscontext[AST_MAX_EXTENSION] = "default";
2423 static int static_config = 0;
2424 static int write_protect_config = 1;
2425 static int autofallthrough_config = 0;
2426 static int clearglobalvars_config = 0;
2427 /*! Go no deeper than this through includes (not counting loops) */
2428 #define AST_PBX_MAX_STACK 128
2429 static void pbx_substitute_variables_helper(struct ast_channel *c,const char *cp1,char *cp2,int count);
2432 /* taken from strings.h */
2434 static force_inline int ast_strlen_zero(const char *s)
2436 return (!s || (*s == '\0'));
2439 #define S_OR(a, b) (!ast_strlen_zero(a) ? (a) : (b))
2442 void ast_copy_string(char *dst, const char *src, size_t size),
2444 while (*src && size) {
2448 if (__builtin_expect(!size, 0))
2455 char *ast_skip_blanks(const char *str),
2457 while (*str && *str < 33)
2464 \brief Trims trailing whitespace characters from a string.
2465 \param ast_trim_blanks function being used
2466 \param str the input string
2467 \return a pointer to the modified string
2470 char *ast_trim_blanks(char *str),
2475 work += strlen(work) - 1;
2476 /* It's tempting to only want to erase after we exit this loop,
2477 but since ast_trim_blanks *could* receive a constant string
2478 (which we presumably wouldn't have to touch), we shouldn't
2479 actually set anything unless we must, and it's easier just
2480 to set each position to \0 than to keep track of a variable
2482 while ((work >= str) && *work < 33)
2490 \brief Strip leading/trailing whitespace from a string.
2491 \param s The string to be stripped (will be modified).
2492 \return The stripped string.
2494 This functions strips all leading and trailing whitespace
2495 characters from the input string, and returns a pointer to
2496 the resulting string. The string is modified in place.
2499 char *ast_strip(char *s),
2501 s = ast_skip_blanks(s);
2509 /* stolen from callerid.c */
2511 /*! \brief Clean up phone string
2512 * remove '(', ' ', ')', non-trailing '.', and '-' not in square brackets.
2513 * Basically, remove anything that could be invalid in a pattern.
2515 static void ast_shrink_phone_number(char *n)
2520 for (x=0; n[x]; x++) {
2539 if (!strchr("()", n[x]))
2547 /* stolen from chanvars.c */
2549 static const char *ast_var_name(const struct ast_var_t *var)
2553 if (var == NULL || (name = var->name) == NULL)
2555 /* Return the name without the initial underscores */
2556 if (name[0] == '_') {
2565 /* stolen from asterisk.c */
2567 static struct ast_flags ast_options = { AST_DEFAULT_OPTIONS };
2568 static int option_verbose = 0; /*!< Verbosity level */
2569 static int option_debug = 0; /*!< Debug level */
2572 /* experiment 1: see if it's easier just to use existing config code
2573 * to read in the extensions.conf file. In this scenario,
2574 I have to rip/copy code from other modules, because they
2575 are staticly declared as-is. A solution would be to move
2576 the ripped code to another location and make them available
2577 to other modules and standalones */
2579 /* Our own version of ast_log, since the expr parser uses it. -- stolen from utils/check_expr.c */
2581 static void ast_log(int level, const char *file, int line, const char *function, const char *fmt, ...)
2586 printf("LOG: lev:%d file:%s line:%d func: %s ",
2587 level, file, line, function);
2593 static void ast_verbose(const char *fmt, ...)
2598 printf("VERBOSE: ");
2604 /* stolen from main/utils.c */
2605 static char *ast_process_quotes_and_slashes(char *start, char find, char replace_with)
2607 char *dataPut = start;
2611 for (; *start; start++) {
2613 *dataPut++ = *start; /* Always goes verbatim */
2616 if (*start == '\\') {
2617 inEscape = 1; /* Do not copy \ into the data */
2618 } else if (*start == '\'') {
2619 inQuotes = 1 - inQuotes; /* Do not copy ' into the data */
2621 /* Replace , with |, unless in quotes */
2622 *dataPut++ = inQuotes ? *start : ((*start == find) ? replace_with : *start);
2626 if (start != dataPut)
2631 static int ast_true(const char *s)
2633 if (ast_strlen_zero(s))
2636 /* Determine if this is a true value */
2637 if (!strcasecmp(s, "yes") ||
2638 !strcasecmp(s, "true") ||
2639 !strcasecmp(s, "y") ||
2640 !strcasecmp(s, "t") ||
2641 !strcasecmp(s, "1") ||
2642 !strcasecmp(s, "on"))
2648 /* stolen from pbx.c */
2649 #define VAR_BUF_SIZE 4096
2651 #define VAR_NORMAL 1
2652 #define VAR_SOFTTRAN 2
2653 #define VAR_HARDTRAN 3
2655 #define BACKGROUND_SKIP (1 << 0)
2656 #define BACKGROUND_NOANSWER (1 << 1)
2657 #define BACKGROUND_MATCHEXTEN (1 << 2)
2658 #define BACKGROUND_PLAYBACK (1 << 3)
2661 \brief ast_exten: An extension
2662 The dialplan is saved as a linked list with each context
2663 having it's own linked list of extensions - one item per
2667 char *exten; /*!< Extension name */
2668 int matchcid; /*!< Match caller id ? */
2669 const char *cidmatch; /*!< Caller id to match for this extension */
2670 int priority; /*!< Priority */
2671 const char *label; /*!< Label */
2672 struct ast_context *parent; /*!< The context this extension belongs to */
2673 const char *app; /*!< Application to execute */
2674 struct ast_app *cached_app; /*!< Cached location of application */
2675 void *data; /*!< Data to use (arguments) */
2676 void (*datad)(void *); /*!< Data destructor */
2677 struct ast_exten *peer; /*!< Next higher priority with our extension */
2678 const char *registrar; /*!< Registrar */
2679 struct ast_exten *next; /*!< Extension with a greater ID */
2683 typedef int (*ast_state_cb_type)(char *context, char* id, enum ast_extension_states state, void *data);
2685 int hastime; /*!< If time construct exists */
2686 unsigned int monthmask; /*!< Mask for month */
2687 unsigned int daymask; /*!< Mask for date */
2688 unsigned int dowmask; /*!< Mask for day of week (mon-sun) */
2689 unsigned int minmask[24]; /*!< Mask for minute */
2692 /*! \brief ast_include: include= support in extensions.conf */
2693 struct ast_include {
2695 const char *rname; /*!< Context to include */
2696 const char *registrar; /*!< Registrar */
2697 int hastime; /*!< If time construct exists */
2698 struct ast_timing timing; /*!< time construct */
2699 struct ast_include *next; /*!< Link them together */
2703 /*! \brief ast_sw: Switch statement in extensions.conf */
2706 const char *registrar; /*!< Registrar */
2707 char *data; /*!< Data load */
2709 AST_LIST_ENTRY(ast_sw) list;
2714 /*! \brief ast_ignorepat: Ignore patterns in dial plan */
2715 struct ast_ignorepat {
2716 const char *registrar;
2717 struct ast_ignorepat *next;
2718 const char pattern[0];
2721 /*! \brief ast_context: An extension context */
2722 struct ast_context {
2723 ast_rwlock_t lock; /*!< A lock to prevent multiple threads from clobbering the context */
2724 struct ast_exten *root; /*!< The root of the list of extensions */
2725 struct ast_context *next; /*!< Link them together */
2726 struct ast_include *includes; /*!< Include other contexts */
2727 struct ast_ignorepat *ignorepats; /*!< Patterns for which to continue playing dialtone */
2728 const char *registrar; /*!< Registrar */
2729 AST_LIST_HEAD_NOLOCK(, ast_sw) alts; /*!< Alternative switches */
2730 ast_mutex_t macrolock; /*!< A lock to implement "exclusive" macros - held whilst a call is executing in the macro */
2731 char name[0]; /*!< Name of the context */
2735 /*! \brief ast_app: A registered application */
2737 int (*execute)(struct ast_channel *chan, void *data);
2738 const char *synopsis; /*!< Synopsis text for 'show applications' */
2739 const char *description; /*!< Description (help text) for 'show application <name>' */
2740 AST_RWLIST_ENTRY(ast_app) list; /*!< Next app in list */
2741 void *module; /*!< Module this app belongs to */
2742 char name[0]; /*!< Name of the application */
2746 /*! \brief ast_state_cb: An extension state notify register item */
2747 struct ast_state_cb {
2750 ast_state_cb_type callback;
2751 struct ast_state_cb *next;
2754 /*! \brief Structure for dial plan hints
2756 \note Hints are pointers from an extension in the dialplan to one or
2757 more devices (tech/name)
2758 - See \ref AstExtState
2761 struct ast_exten *exten; /*!< Extension */
2762 int laststate; /*!< Last known state */
2763 struct ast_state_cb *callbacks; /*!< Callback list for this extension */
2764 AST_RWLIST_ENTRY(ast_hint) list;/*!< Pointer to next hint in list */
2770 struct ast_state_cb *callbacks;
2772 AST_LIST_ENTRY(store_hint) list;
2776 AST_LIST_HEAD(store_hints, store_hint);
2778 static const struct cfextension_states {
2779 int extension_state;
2780 const char * const text;
2781 } extension_states[] = {
2782 { AST_EXTENSION_NOT_INUSE, "Idle" },
2783 { AST_EXTENSION_INUSE, "InUse" },
2784 { AST_EXTENSION_BUSY, "Busy" },
2785 { AST_EXTENSION_UNAVAILABLE, "Unavailable" },
2786 { AST_EXTENSION_RINGING, "Ringing" },
2787 { AST_EXTENSION_INUSE | AST_EXTENSION_RINGING, "InUse&Ringing" },
2788 { AST_EXTENSION_ONHOLD, "Hold" },
2789 { AST_EXTENSION_INUSE | AST_EXTENSION_ONHOLD, "InUse&Hold" }
2791 #define STATUS_NO_CONTEXT 1
2792 #define STATUS_NO_EXTENSION 2
2793 #define STATUS_NO_PRIORITY 3
2794 #define STATUS_NO_LABEL 4
2795 #define STATUS_SUCCESS 5
2798 #if defined ( __i386__) && (defined(__FreeBSD__) || defined(linux))
2799 #if defined(__FreeBSD__)
2800 #include <machine/cpufunc.h>
2801 #elif defined(linux)
2802 static __inline uint64_t
2807 __asm __volatile(".byte 0x0f, 0x31" : "=A" (rv));
2811 #else /* supply a dummy function on other platforms */
2812 static __inline uint64_t
2820 static struct ast_var_t *ast_var_assign(const char *name, const char *value)
2822 struct ast_var_t *var;
2823 int name_len = strlen(name) + 1;
2824 int value_len = strlen(value) + 1;
2826 if (!(var = ast_calloc(sizeof(*var) + name_len + value_len, sizeof(char)))) {
2830 ast_copy_string(var->name, name, name_len);
2831 var->value = var->name + name_len;
2832 ast_copy_string(var->value, value, value_len);
2837 static void ast_var_delete(struct ast_var_t *var)
2844 /* chopped this one off at the knees! */
2845 static int ast_func_write(struct ast_channel *chan, const char *function, const char *value)
2848 /* ast_log(LOG_ERROR, "Function %s not registered\n", function); we are not interested in the details here */
2853 static unsigned int ast_app_separate_args(char *buf, char delim, char **array, int arraylen)
2857 int paren = 0, quote = 0;
2859 if (!buf || !array || !arraylen)
2862 memset(array, 0, arraylen * sizeof(*array));
2866 for (argc = 0; *scan && (argc < arraylen - 1); argc++) {
2868 for (; *scan; scan++) {
2871 else if (*scan == ')') {
2874 } else if (*scan == '"' && delim != '"') {
2875 quote = quote ? 0 : 1;
2876 /* Remove quote character from argument */
2877 memmove(scan, scan + 1, strlen(scan));
2879 } else if (*scan == '\\') {
2880 /* Literal character, don't parse */
2881 memmove(scan, scan + 1, strlen(scan));
2882 } else if ((*scan == delim) && !paren && !quote) {
2890 array[argc++] = scan;
2895 static void pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
2897 struct ast_var_t *newvariable;
2898 struct varshead *headp;
2899 const char *nametail = name;
2901 /* XXX may need locking on the channel ? */
2902 if (name[strlen(name)-1] == ')') {
2903 char *function = ast_strdupa(name);
2905 ast_func_write(chan, function, value);
2911 /* For comparison purposes, we have to strip leading underscores */
2912 if (*nametail == '_') {
2914 if (*nametail == '_')
2918 AST_LIST_TRAVERSE (headp, newvariable, entries) {
2919 if (strcasecmp(ast_var_name(newvariable), nametail) == 0) {
2920 /* there is already such a variable, delete it */
2921 AST_LIST_REMOVE(headp, newvariable, entries);
2922 ast_var_delete(newvariable);
2928 if ((option_verbose > 1) && (headp == &globals))
2929 ast_verbose(VERBOSE_PREFIX_2 "Setting global variable '%s' to '%s'\n", name, value);
2930 newvariable = ast_var_assign(name, value);
2931 AST_LIST_INSERT_HEAD(headp, newvariable, entries);
2936 static int pbx_builtin_setvar(struct ast_channel *chan, void *data)
2938 char *name, *value, *mydata;
2940 char *argv[24]; /* this will only support a maximum of 24 variables being set in a single operation */
2944 if (ast_strlen_zero(data)) {
2945 ast_log(LOG_WARNING, "Set requires at least one variable name/value pair.\n");
2949 mydata = ast_strdupa(data);
2950 argc = ast_app_separate_args(mydata, '|', argv, sizeof(argv) / sizeof(argv[0]));
2952 /* check for a trailing flags argument */
2953 if ((argc > 1) && !strchr(argv[argc-1], '=')) {
2955 if (strchr(argv[argc], 'g'))
2959 for (x = 0; x < argc; x++) {
2961 if ((value = strchr(name, '='))) {
2963 pbx_builtin_setvar_helper((global) ? NULL : chan, name, value);
2965 ast_log(LOG_WARNING, "Ignoring entry '%s' with no = (and not last 'options' entry)\n", name);
2971 int localized_pbx_builtin_setvar(struct ast_channel *chan, void *data);
2973 int localized_pbx_builtin_setvar(struct ast_channel *chan, void *data)
2975 return pbx_builtin_setvar(chan, data);
2979 /*! \brief Helper for get_range.
2980 * return the index of the matching entry, starting from 1.
2981 * If names is not supplied, try numeric values.
2984 static int lookup_name(const char *s, char *const names[], int max)
2989 for (i = 0; names[i]; i++) {
2990 if (!strcasecmp(s, names[i]))
2993 } else if (sscanf(s, "%d", &i) == 1 && i >= 1 && i <= max) {
2996 return 0; /* error return */
2999 /*! \brief helper function to return a range up to max (7, 12, 31 respectively).
3000 * names, if supplied, is an array of names that should be mapped to numbers.
3002 static unsigned get_range(char *src, int max, char *const names[], const char *msg)
3004 int s, e; /* start and ending position */
3005 unsigned int mask = 0;
3007 /* Check for whole range */
3008 if (ast_strlen_zero(src) || !strcmp(src, "*")) {
3012 /* Get start and ending position */
3013 char *c = strchr(src, '-');
3016 /* Find the start */
3017 s = lookup_name(src, names, max);
3019 ast_log(LOG_WARNING, "Invalid %s '%s', assuming none\n", msg, src);
3023 if (c) { /* find end of range */
3024 e = lookup_name(c, names, max);
3026 ast_log(LOG_WARNING, "Invalid end %s '%s', assuming none\n", msg, c);
3033 /* Fill the mask. Remember that ranges are cyclic */
3034 mask = 1 << e; /* initialize with last element */
3047 /*! \brief store a bitmask of valid times, one bit each 2 minute */
3048 static void get_timerange(struct ast_timing *i, char *times)
3056 /* start disabling all times, fill the fields with 0's, as they may contain garbage */
3057 memset(i->minmask, 0, sizeof(i->minmask));
3059 /* 2-minutes per bit, since the mask has only 32 bits :( */
3060 /* Star is all times */
3061 if (ast_strlen_zero(times) || !strcmp(times, "*")) {
3062 for (x=0; x<24; x++)
3063 i->minmask[x] = 0x3fffffff; /* 30 bits */
3066 /* Otherwise expect a range */
3067 e = strchr(times, '-');
3069 ast_log(LOG_WARNING, "Time range is not valid. Assuming no restrictions based on time.\n");
3073 /* XXX why skip non digits ? */
3074 while (*e && !isdigit(*e))
3077 ast_log(LOG_WARNING, "Invalid time range. Assuming no restrictions based on time.\n");
3080 if (sscanf(times, "%d:%d", &s1, &s2) != 2) {
3081 ast_log(LOG_WARNING, "%s isn't a time. Assuming no restrictions based on time.\n", times);
3084 if (sscanf(e, "%d:%d", &e1, &e2) != 2) {
3085 ast_log(LOG_WARNING, "%s isn't a time. Assuming no restrictions based on time.\n", e);
3088 /* XXX this needs to be optimized */
3090 s1 = s1 * 30 + s2/2;
3091 if ((s1 < 0) || (s1 >= 24*30)) {
3092 ast_log(LOG_WARNING, "%s isn't a valid start time. Assuming no time.\n", times);
3095 e1 = e1 * 30 + e2/2;
3096 if ((e1 < 0) || (e1 >= 24*30)) {
3097 ast_log(LOG_WARNING, "%s isn't a valid end time. Assuming no time.\n", e);
3100 /* Go through the time and enable each appropriate bit */
3101 for (x=s1;x != e1;x = (x + 1) % (24 * 30)) {
3102 i->minmask[x/30] |= (1 << (x % 30));
3104 /* Do the last one */
3105 i->minmask[x/30] |= (1 << (x % 30));
3107 for (cth=0; cth<24; cth++) {
3108 /* Initialize masks to blank */
3109 i->minmask[cth] = 0;
3110 for (ctm=0; ctm<30; ctm++) {
3112 /* First hour with more than one hour */
3113 (((cth == s1) && (ctm >= s2)) &&
3116 || (((cth == s1) && (ctm >= s2)) &&
3117 ((cth == e1) && (ctm <= e2)))
3118 /* In between first and last hours (more than 2 hours) */
3121 /* Last hour with more than one hour */
3123 ((cth == e1) && (ctm <= e2)))
3125 i->minmask[cth] |= (1 << (ctm / 2));
3133 static void null_datad(void *foo)
3137 /*! \brief Find realtime engine for realtime family */
3138 static struct ast_config_engine *find_engine(const char *family, char *database, int dbsiz, char *table, int tabsiz)
3140 struct ast_config_engine *eng, *ret = NULL;
3141 struct ast_config_map *map;
3144 for (map = config_maps; map; map = map->next) {
3145 if (!strcasecmp(family, map->name)) {
3147 ast_copy_string(database, map->database, dbsiz);
3149 ast_copy_string(table, map->table ? map->table : family, tabsiz);
3154 /* Check if the required driver (engine) exist */
3156 for (eng = config_engine_list; !ret && eng; eng = eng->next) {
3157 if (!strcasecmp(eng->name, map->driver))
3163 /* if we found a mapping, but the engine is not available, then issue a warning */
3165 ast_log(LOG_WARNING, "Realtime mapping for '%s' found to engine '%s', but the engine is not available\n", map->name, map->driver);
3170 struct ast_category *ast_config_get_current_category(const struct ast_config *cfg);
3172 struct ast_category *ast_config_get_current_category(const struct ast_config *cfg)
3174 return cfg->current;
3177 static struct ast_category *ast_category_new(const char *name);
3179 static struct ast_category *ast_category_new(const char *name)
3181 struct ast_category *category;
3183 if ((category = ast_calloc(1, sizeof(*category))))
3184 ast_copy_string(category->name, name, sizeof(category->name));
3188 struct ast_category *localized_category_get(const struct ast_config *config, const char *category_name);
3190 struct ast_category *localized_category_get(const struct ast_config *config, const char *category_name)
3192 return category_get(config, category_name, 0);
3195 static void move_variables(struct ast_category *old, struct ast_category *new)
3197 struct ast_variable *var = old->root;
3200 /* we can just move the entire list in a single op */
3201 ast_variable_append(new, var);
3204 struct ast_variable *next = var->next;
3206 ast_variable_append(new, var);
3212 static void inherit_category(struct ast_category *new, const struct ast_category *base)
3214 struct ast_variable *var;
3216 for (var = base->root; var; var = var->next)
3217 ast_variable_append(new, variable_clone(var));
3220 static void ast_category_append(struct ast_config *config, struct ast_category *category);
3222 static void ast_category_append(struct ast_config *config, struct ast_category *category)
3225 config->last->next = category;
3227 config->root = category;
3228 config->last = category;
3229 config->current = category;
3232 static void ast_category_destroy(struct ast_category *cat);
3234 static void ast_category_destroy(struct ast_category *cat)
3236 ast_variables_destroy(cat->root);
3240 static struct ast_config_engine text_file_engine = {
3242 .load_func = config_text_file_load,
3246 static struct ast_config *ast_config_internal_load(const char *filename, struct ast_config *cfg, int withcomments);
3248 static struct ast_config *ast_config_internal_load(const char *filename, struct ast_config *cfg, int withcomments)
3252 struct ast_config_engine *loader = &text_file_engine;
3253 struct ast_config *result;
3255 if (cfg->include_level == cfg->max_include_level) {
3256 ast_log(LOG_WARNING, "Maximum Include level (%d) exceeded\n", cfg->max_include_level);
3260 cfg->include_level++;
3261 /* silence is golden!
3262 ast_log(LOG_WARNING, "internal loading file %s level=%d\n", filename, cfg->include_level);
3265 if (strcmp(filename, extconfig_conf) && strcmp(filename, "asterisk.conf") && config_engine_list) {
3266 struct ast_config_engine *eng;
3268 eng = find_engine(filename, db, sizeof(db), table, sizeof(table));
3271 if (eng && eng->load_func) {
3274 eng = find_engine("global", db, sizeof(db), table, sizeof(table));
3275 if (eng && eng->load_func)
3280 result = loader->load_func(db, table, filename, cfg, withcomments);
3281 /* silence is golden
3282 ast_log(LOG_WARNING, "finished internal loading file %s level=%d\n", filename, cfg->include_level);
3286 result->include_level--;
3292 static int process_text_line(struct ast_config *cfg, struct ast_category **cat, char *buf, int lineno, const char *configfile, int withcomments)
3296 struct ast_variable *v;
3297 char cmd[512], exec_file[512];
3298 int object, do_exec, do_include;
3300 /* Actually parse the entry */
3301 if (cur[0] == '[') {
3302 struct ast_category *newcat = NULL;
3305 /* A category header */
3306 c = strchr(cur, ']');
3308 ast_log(LOG_WARNING, "parse error: no closing ']', line %d of %s\n", lineno, configfile);
3316 if (!(*cat = newcat = ast_category_new(catname))) {
3320 if (withcomments && comment_buffer && comment_buffer[0] ) {
3321 newcat->precomments = ALLOC_COMMENT(comment_buffer);
3323 if (withcomments && lline_buffer && lline_buffer[0] ) {
3324 newcat->sameline = ALLOC_COMMENT(lline_buffer);
3329 /* If there are options or categories to inherit from, process them now */
3331 if (!(cur = strchr(c, ')'))) {
3332 ast_log(LOG_WARNING, "parse error: no closing ')', line %d of %s\n", lineno, configfile);
3336 while ((cur = strsep(&c, ","))) {
3337 if (!strcasecmp(cur, "!")) {
3338 (*cat)->ignored = 1;
3339 } else if (!strcasecmp(cur, "+")) {
3340 *cat = category_get(cfg, catname, 1);
3342 ast_config_destroy(cfg);
3344 ast_category_destroy(newcat);
3345 ast_log(LOG_WARNING, "Category addition requested, but category '%s' does not exist, line %d of %s\n", catname, lineno, configfile);
3349 move_variables(newcat, *cat);
3350 ast_category_destroy(newcat);
3354 struct ast_category *base;
3356 base = category_get(cfg, cur, 1);
3358 ast_log(LOG_WARNING, "Inheritance requested, but category '%s' does not exist, line %d of %s\n", cur, lineno, configfile);
3361 inherit_category(*cat, base);
3366 ast_category_append(cfg, *cat);
3367 } else if (cur[0] == '#') {
3371 while(*c && (*c > 32)) c++;
3374 /* Find real argument */
3375 c = ast_skip_blanks(c + 1);
3380 do_include = !strcasecmp(cur, "include");
3382 do_exec = !strcasecmp(cur, "exec");
3385 if (do_exec && !ast_opt_exec_includes) {
3386 ast_log(LOG_WARNING, "Cannot perform #exec unless execincludes option is enabled in asterisk.conf (options section)!\n");
3389 if (do_include || do_exec) {
3391 /* Strip off leading and trailing "'s and <>'s */
3392 while((*c == '<') || (*c == '>') || (*c == '\"')) c++;
3393 /* Get rid of leading mess */
3395 while (!ast_strlen_zero(cur)) {
3396 c = cur + strlen(cur) - 1;
3397 if ((*c == '>') || (*c == '<') || (*c == '\"'))
3402 /* #exec </path/to/executable>
3403 We create a tmp file, then we #include it, then we delete it. */
3405 snprintf(exec_file, sizeof(exec_file), "/var/tmp/exec.%d.%ld", (int)time(NULL), (long)pthread_self());
3406 snprintf(cmd, sizeof(cmd), "%s > %s 2>&1", cur, exec_file);
3407 ast_safe_system(cmd);
3410 exec_file[0] = '\0';
3412 /* ast_log(LOG_WARNING, "Reading in included file %s withcomments=%d\n", cur, withcomments); */
3414 do_include = ast_config_internal_load(cur, cfg, withcomments) ? 1 : 0;
3415 if(!ast_strlen_zero(exec_file))
3419 /* ast_log(LOG_WARNING, "Done reading in included file %s withcomments=%d\n", cur, withcomments); */
3422 ast_log(LOG_WARNING, "Directive '#%s' needs an argument (%s) at line %d of %s\n",
3423 do_exec ? "exec" : "include",
3424 do_exec ? "/path/to/executable" : "filename",
3430 ast_log(LOG_WARNING, "Unknown directive '%s' at line %d of %s\n", cur, lineno, configfile);
3432 /* Just a line (variable = value) */
3434 ast_log(LOG_WARNING,
3435 "parse error: No category context for line %d of %s\n", lineno, configfile);
3438 c = strchr(cur, '=');
3442 /* Ignore > in => */
3448 if ((v = ast_variable_new(ast_strip(cur), ast_strip(c)))) {
3451 /* Put and reset comments */
3453 ast_variable_append(*cat, v);
3455 if (withcomments && comment_buffer && comment_buffer[0] ) {
3456 v->precomments = ALLOC_COMMENT(comment_buffer);
3458 if (withcomments && lline_buffer && lline_buffer[0] ) {
3459 v->sameline = ALLOC_COMMENT(lline_buffer);
3468 ast_log(LOG_WARNING, "EXTENSIONS.CONF: No '=' (equal sign) in line %d of %s\n", lineno, configfile);
3474 static int use_local_dir = 1;
3476 void localized_use_local_dir(void);
3477 void localized_use_conf_dir(void);
3479 void localized_use_local_dir(void)
3484 void localized_use_conf_dir(void)
3490 static struct ast_config *config_text_file_load(const char *database, const char *table, const char *filename, struct ast_config *cfg, int withcomments)
3494 char *new_buf, *comment_p, *process_buf;
3497 int comment = 0, nest[MAX_NESTED_COMMENTS];
3498 struct ast_category *cat = NULL;
3500 struct stat statbuf;
3502 cat = ast_config_get_current_category(cfg);
3504 if (filename[0] == '/') {
3505 ast_copy_string(fn, filename, sizeof(fn));
3508 snprintf(fn, sizeof(fn), "./%s", filename);
3510 snprintf(fn, sizeof(fn), "%s/%s", (char *)ast_config_AST_CONFIG_DIR, filename);
3513 if (withcomments && cfg && cfg->include_level < 2 ) {
3517 #ifdef AST_INCLUDE_GLOB
3522 globbuf.gl_offs = 0; /* initialize it to silence gcc */
3524 glob_ret = glob(fn, GLOB_NOCHECK, NULL, &globbuf);
3526 glob_ret = glob(fn, GLOB_NOMAGIC|GLOB_BRACE, NULL, &globbuf);
3528 if (glob_ret == GLOB_NOSPACE)
3529 ast_log(LOG_WARNING,
3530 "Glob Expansion of pattern '%s' failed: Not enough memory\n", fn);
3531 else if (glob_ret == GLOB_ABORTED)
3532 ast_log(LOG_WARNING,
3533 "Glob Expansion of pattern '%s' failed: Read error\n", fn);
3535 /* loop over expanded files */
3537 for (i=0; i<globbuf.gl_pathc; i++) {
3538 ast_copy_string(fn, globbuf.gl_pathv[i], sizeof(fn));
3541 if (stat(fn, &statbuf))
3544 if (!S_ISREG(statbuf.st_mode)) {
3545 ast_log(LOG_WARNING, "'%s' is not a regular file, ignoring\n", fn);
3548 if (option_verbose > 1) {
3549 ast_verbose(VERBOSE_PREFIX_2 "Parsing '%s': ", fn);
3552 if (!(f = fopen(fn, "r"))) {
3554 ast_log(LOG_DEBUG, "No file to parse: %s\n", fn);
3555 if (option_verbose > 1)
3556 ast_verbose( "Not found (%s)\n", strerror(errno));
3561 ast_log(LOG_DEBUG, "Parsing %s\n", fn);
3562 if (option_verbose > 1)
3563 ast_verbose("Found\n");
3566 if (fgets(buf, sizeof(buf), f)) {
3567 if ( withcomments ) {
3568 CB_ADD(lline_buffer); /* add the current lline buffer to the comment buffer */
3569 lline_buffer[0] = 0; /* erase the lline buffer */
3578 while ((comment_p = strchr(new_buf, COMMENT_META))) {
3579 if ((comment_p > new_buf) && (*(comment_p-1) == '\\')) {
3580 /* Yuck, gotta memmove */
3581 memmove(comment_p - 1, comment_p, strlen(comment_p) + 1);
3582 new_buf = comment_p;
3583 } else if(comment_p[1] == COMMENT_TAG && comment_p[2] == COMMENT_TAG && (comment_p[3] != '-')) {
3584 /* Meta-Comment start detected ";--" */
3585 if (comment < MAX_NESTED_COMMENTS) {
3587 new_buf = comment_p + 3;
3589 nest[comment-1] = lineno;
3591 ast_log(LOG_ERROR, "Maximum nest limit of %d reached.\n", MAX_NESTED_COMMENTS);
3593 } else if ((comment_p >= new_buf + 2) &&
3594 (*(comment_p - 1) == COMMENT_TAG) &&
3595 (*(comment_p - 2) == COMMENT_TAG)) {
3596 /* Meta-Comment end detected */
3598 new_buf = comment_p + 1;
3600 /* Back to non-comment now */
3602 /* Actually have to move what's left over the top, then continue */
3604 oldptr = process_buf + strlen(process_buf);
3605 if ( withcomments ) {
3607 CB_ADD_LEN(oldptr+1,new_buf-oldptr-1);
3610 memmove(oldptr, new_buf, strlen(new_buf) + 1);
3613 process_buf = new_buf;
3617 /* If ; is found, and we are not nested in a comment,
3618 we immediately stop all comment processing */
3619 if ( withcomments ) {
3623 new_buf = comment_p;
3625 new_buf = comment_p + 1;
3628 if( withcomments && comment && !process_buf )
3630 CB_ADD(buf); /* the whole line is a comment, store it */
3634 char *buf = ast_strip(process_buf);
3635 if (!ast_strlen_zero(buf)) {
3636 if (process_text_line(cfg, &cat, buf, lineno, filename, withcomments)) {
3647 ast_log(LOG_WARNING,"Unterminated comment detected beginning on line %d\n", nest[comment]);
3649 #ifdef AST_INCLUDE_GLOB
3657 if (cfg && cfg->include_level == 1 && withcomments && comment_buffer) {
3658 if (comment_buffer) {
3659 free(comment_buffer);
3663 comment_buffer_size=0;
3664 lline_buffer_size=0;
3674 static struct ast_config *ast_config_new(void) ;
3676 static struct ast_config *ast_config_new(void)
3678 struct ast_config *config;
3680 if ((config = ast_calloc(1, sizeof(*config))))
3681 config->max_include_level = MAX_INCLUDE_LEVEL;
3685 struct ast_config *localized_config_load(const char *filename);
3687 struct ast_config *localized_config_load(const char *filename)
3689 struct ast_config *cfg;
3690 struct ast_config *result;
3692 cfg = ast_config_new();
3696 result = ast_config_internal_load(filename, cfg, 0);
3698 ast_config_destroy(cfg);
3703 struct ast_config *localized_config_load_with_comments(const char *filename);
3705 struct ast_config *localized_config_load_with_comments(const char *filename)
3707 struct ast_config *cfg;
3708 struct ast_config *result;
3710 cfg = ast_config_new();
3714 result = ast_config_internal_load(filename, cfg, 1);
3716 ast_config_destroy(cfg);
3721 static struct ast_category *next_available_category(struct ast_category *cat)