BuildSystem: Remove unused variables.
[asterisk/asterisk.git] / main / utils.c
index ba1a07c..85228c1 100644 (file)
@@ -29,8 +29,6 @@
 
 #include "asterisk.h"
 
-ASTERISK_REGISTER_FILE()
-
 #include <ctype.h>
 #include <fcntl.h>
 #include <sys/stat.h>
@@ -61,9 +59,6 @@ ASTERISK_REGISTER_FILE()
 #include "asterisk/time.h"
 
 #define AST_API_MODULE         /* ensure that inlinable API functions will be built in this module if required */
-#include "asterisk/stringfields.h"
-
-#define AST_API_MODULE         /* ensure that inlinable API functions will be built in this module if required */
 #include "asterisk/utils.h"
 
 #define AST_API_MODULE
@@ -72,6 +67,9 @@ ASTERISK_REGISTER_FILE()
 #define AST_API_MODULE
 #include "asterisk/config.h"
 
+#define AST_API_MODULE
+#include "asterisk/alertpipe.h"
+
 static char base64[64];
 static char b2a[256];
 
@@ -617,10 +615,9 @@ static int dev_urandom_fd = -1;
 #undef pthread_create /* For ast_pthread_create function only */
 #endif /* !__linux__ */
 
-#if !defined(LOW_MEMORY)
-
 #ifdef DEBUG_THREADS
 
+#if !defined(LOW_MEMORY)
 /*! \brief A reasonable maximum number of locks a thread would be holding ... */
 #define AST_MAX_LOCKS 64
 
@@ -723,14 +720,12 @@ static void lock_info_destroy(void *data)
  * \brief The thread storage key for per-thread lock info
  */
 AST_THREADSTORAGE_CUSTOM(thread_lock_info, NULL, lock_info_destroy);
-#ifdef HAVE_BKTR
+#endif /* ! LOW_MEMORY */
+
 void ast_store_lock_info(enum ast_lock_type type, const char *filename,
        int line_num, const char *func, const char *lock_name, void *lock_addr, struct ast_bt *bt)
-#else
-void ast_store_lock_info(enum ast_lock_type type, const char *filename,
-       int line_num, const char *func, const char *lock_name, void *lock_addr)
-#endif
 {
+#if !defined(LOW_MEMORY)
        struct thr_lock_info *lock_info;
        int i;
 
@@ -781,10 +776,12 @@ void ast_store_lock_info(enum ast_lock_type type, const char *filename,
        lock_info->num_locks++;
 
        pthread_mutex_unlock(&lock_info->lock);
+#endif /* ! LOW_MEMORY */
 }
 
 void ast_mark_lock_acquired(void *lock_addr)
 {
+#if !defined(LOW_MEMORY)
        struct thr_lock_info *lock_info;
 
        if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info))))
@@ -795,10 +792,12 @@ void ast_mark_lock_acquired(void *lock_addr)
                lock_info->locks[lock_info->num_locks - 1].pending = 0;
        }
        pthread_mutex_unlock(&lock_info->lock);
+#endif /* ! LOW_MEMORY */
 }
 
 void ast_mark_lock_failed(void *lock_addr)
 {
+#if !defined(LOW_MEMORY)
        struct thr_lock_info *lock_info;
 
        if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info))))
@@ -810,10 +809,12 @@ void ast_mark_lock_failed(void *lock_addr)
                lock_info->locks[lock_info->num_locks - 1].times_locked--;
        }
        pthread_mutex_unlock(&lock_info->lock);
+#endif /* ! LOW_MEMORY */
 }
 
 int ast_find_lock_info(void *lock_addr, char *filename, size_t filename_size, int *lineno, char *func, size_t func_size, char *mutex_name, size_t mutex_name_size)
 {
+#if !defined(LOW_MEMORY)
        struct thr_lock_info *lock_info;
        int i = 0;
 
@@ -841,10 +842,14 @@ int ast_find_lock_info(void *lock_addr, char *filename, size_t filename_size, in
        pthread_mutex_unlock(&lock_info->lock);
 
        return 0;
+#else /* if defined(LOW_MEMORY) */
+       return -1;
+#endif
 }
 
 void ast_suspend_lock_info(void *lock_addr)
 {
+#if !defined(LOW_MEMORY)
        struct thr_lock_info *lock_info;
        int i = 0;
 
@@ -868,10 +873,12 @@ void ast_suspend_lock_info(void *lock_addr)
        lock_info->locks[i].suspended = 1;
 
        pthread_mutex_unlock(&lock_info->lock);
+#endif /* ! LOW_MEMORY */
 }
 
 void ast_restore_lock_info(void *lock_addr)
 {
+#if !defined(LOW_MEMORY)
        struct thr_lock_info *lock_info;
        int i = 0;
 
@@ -894,15 +901,13 @@ void ast_restore_lock_info(void *lock_addr)
        lock_info->locks[i].suspended = 0;
 
        pthread_mutex_unlock(&lock_info->lock);
+#endif /* ! LOW_MEMORY */
 }
 
 
-#ifdef HAVE_BKTR
 void ast_remove_lock_info(void *lock_addr, struct ast_bt *bt)
-#else
-void ast_remove_lock_info(void *lock_addr)
-#endif
 {
+#if !defined(LOW_MEMORY)
        struct thr_lock_info *lock_info;
        int i = 0;
 
@@ -940,8 +945,10 @@ void ast_remove_lock_info(void *lock_addr)
        lock_info->num_locks--;
 
        pthread_mutex_unlock(&lock_info->lock);
+#endif /* ! LOW_MEMORY */
 }
 
+#if !defined(LOW_MEMORY)
 static const char *locktype2str(enum ast_lock_type type)
 {
        switch (type) {
@@ -1020,7 +1027,7 @@ static void append_lock_information(struct ast_str **str, struct thr_lock_info *
        }
        ast_reentrancy_unlock(lt);
 }
-
+#endif /* ! LOW_MEMORY */
 
 /*! This function can help you find highly temporal locks; locks that happen for a
     short time, but at unexpected times, usually at times that create a deadlock,
@@ -1043,6 +1050,7 @@ static void append_lock_information(struct ast_str **str, struct thr_lock_info *
 */
 void ast_log_show_lock(void *this_lock_addr)
 {
+#if !defined(LOW_MEMORY)
        struct thr_lock_info *lock_info;
        struct ast_str *str;
 
@@ -1069,11 +1077,13 @@ void ast_log_show_lock(void *this_lock_addr)
        }
        pthread_mutex_unlock(&lock_infos_lock.mutex);
        ast_free(str);
+#endif /* ! LOW_MEMORY */
 }
 
 
 struct ast_str *ast_dump_locks(void)
 {
+#if !defined(LOW_MEMORY)
        struct thr_lock_info *lock_info;
        struct ast_str *str;
 
@@ -1140,8 +1150,12 @@ struct ast_str *ast_dump_locks(void)
                       "\n");
 
        return str;
+#else /* if defined(LOW_MEMORY) */
+       return NULL;
+#endif
 }
 
+#if !defined(LOW_MEMORY)
 static char *handle_show_locks(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
        struct ast_str *str;
@@ -1153,6 +1167,7 @@ static char *handle_show_locks(struct ast_cli_entry *e, int cmd, struct ast_cli_
                        "Usage: core show locks\n"
                        "       This command is for lock debugging.  It prints out which locks\n"
                        "are owned by each active thread.\n";
+               ast_cli_allow_at_shutdown(e);
                return NULL;
 
        case CLI_GENERATE:
@@ -1174,9 +1189,10 @@ static char *handle_show_locks(struct ast_cli_entry *e, int cmd, struct ast_cli_
 static struct ast_cli_entry utils_cli[] = {
        AST_CLI_DEFINE(handle_show_locks, "Show which locks are held by which thread"),
 };
-
+#endif /* ! LOW_MEMORY */
 #endif /* DEBUG_THREADS */
 
+#if !defined(LOW_MEMORY)
 /*
  * support for 'show threads'. The start routine is wrapped by
  * dummy_start(), so that ast_register_thread() and
@@ -1208,7 +1224,7 @@ static void *dummy_start(void *data)
 
        lock_info->thread_id = pthread_self();
        lock_info->lwp = ast_get_tid();
-       lock_info->thread_name = strdup(a.name);
+       lock_info->thread_name = ast_strdup(a.name);
 
        pthread_mutexattr_init(&mutex_attr);
        pthread_mutexattr_settype(&mutex_attr, AST_MUTEX_KIND);
@@ -1238,6 +1254,15 @@ static void *dummy_start(void *data)
 
 #endif /* !LOW_MEMORY */
 
+int ast_background_stacksize(void)
+{
+#if !defined(LOW_MEMORY)
+       return AST_STACKSIZE;
+#else
+       return AST_STACKSIZE_LOW;
+#endif
+}
+
 int ast_pthread_create_stack(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *),
                             void *data, size_t stacksize, const char *file, const char *caller,
                             int line, const char *start_fn)
@@ -1399,7 +1424,13 @@ int ast_carefulwrite(int fd, char *s, int len, int timeoutms)
 
                if (res < 0 && errno != EAGAIN && errno != EINTR) {
                        /* fatal error from write() */
-                       ast_log(LOG_ERROR, "write() returned error: %s\n", strerror(errno));
+                       if (errno == EPIPE) {
+#ifndef STANDALONE
+                               ast_debug(1, "write() failed due to reading end being closed: %s\n", strerror(errno));
+#endif
+                       } else {
+                               ast_log(LOG_ERROR, "write() returned error: %s\n", strerror(errno));
+                       }
                        return -1;
                }
 
@@ -1425,68 +1456,6 @@ int ast_carefulwrite(int fd, char *s, int len, int timeoutms)
        return res;
 }
 
-int ast_careful_fwrite(FILE *f, int fd, const char *src, size_t len, int timeoutms)
-{
-       struct timeval start = ast_tvnow();
-       int n = 0;
-       int elapsed = 0;
-
-       while (len) {
-               if (wait_for_output(fd, timeoutms - elapsed)) {
-                       /* poll returned a fatal error, so bail out immediately. */
-                       return -1;
-               }
-
-               /* Clear any errors from a previous write */
-               clearerr(f);
-
-               n = fwrite(src, 1, len, f);
-
-               if (ferror(f) && errno != EINTR && errno != EAGAIN) {
-                       /* fatal error from fwrite() */
-                       if (!feof(f)) {
-                               /* Don't spam the logs if it was just that the connection is closed. */
-                               ast_log(LOG_ERROR, "fwrite() returned error: %s\n", strerror(errno));
-                       }
-                       n = -1;
-                       break;
-               }
-
-               /* Update for data already written to the socket */
-               len -= n;
-               src += n;
-
-               elapsed = ast_tvdiff_ms(ast_tvnow(), start);
-               if (elapsed >= timeoutms) {
-                       /* We've taken too long to write
-                        * This is only an error condition if we haven't finished writing. */
-                       n = len ? -1 : 0;
-                       break;
-               }
-       }
-
-       errno = 0;
-       while (fflush(f)) {
-               if (errno == EAGAIN || errno == EINTR) {
-                       /* fflush() does not appear to reset errno if it flushes
-                        * and reaches EOF at the same time. It returns EOF with
-                        * the last seen value of errno, causing a possible loop.
-                        * Also usleep() to reduce CPU eating if it does loop */
-                       errno = 0;
-                       usleep(1);
-                       continue;
-               }
-               if (errno && !feof(f)) {
-                       /* Don't spam the logs if it was just that the connection is closed. */
-                       ast_log(LOG_ERROR, "fflush() returned error: %s\n", strerror(errno));
-               }
-               n = -1;
-               break;
-       }
-
-       return n < 0 ? -1 : 0;
-}
-
 char *ast_strip_quoted(char *s, const char *beg_quotes, const char *end_quotes)
 {
        char *e;
@@ -1512,7 +1481,7 @@ char *ast_strsep(char **iss, const char sep, uint32_t flags)
        int found = 0;
        char stack[8];
 
-       if (iss == NULL || *iss == '\0') {
+       if (ast_strlen_zero(st)) {
                return NULL;
        }
 
@@ -2016,374 +1985,6 @@ char *ast_to_camel_case_delim(const char *s, const char *delim)
        return res;
 }
 
-/*
- * stringfields support routines.
- */
-
-/* this is a little complex... string fields are stored with their
-   allocated size in the bytes preceding the string; even the
-   constant 'empty' string has to be this way, so the code that
-   checks to see if there is enough room for a new string doesn't
-   have to have any special case checks
-*/
-
-static const struct {
-       ast_string_field_allocation allocation;
-       char string[1];
-} __ast_string_field_empty_buffer;
-
-ast_string_field __ast_string_field_empty = __ast_string_field_empty_buffer.string;
-
-#define ALLOCATOR_OVERHEAD 48
-
-static size_t optimal_alloc_size(size_t size)
-{
-       unsigned int count;
-
-       size += ALLOCATOR_OVERHEAD;
-
-       for (count = 1; size; size >>= 1, count++);
-
-       return (1 << count) - ALLOCATOR_OVERHEAD;
-}
-
-/*! \brief add a new block to the pool.
- * We can only allocate from the topmost pool, so the
- * fields in *mgr reflect the size of that only.
- */
-static int add_string_pool(struct ast_string_field_mgr *mgr, struct ast_string_field_pool **pool_head,
-                          size_t size, const char *file, int lineno, const char *func)
-{
-       struct ast_string_field_pool *pool;
-       size_t alloc_size = optimal_alloc_size(sizeof(*pool) + size);
-
-#if defined(__AST_DEBUG_MALLOC)
-       if (!(pool = __ast_calloc(1, alloc_size, file, lineno, func))) {
-               return -1;
-       }
-#else
-       if (!(pool = ast_calloc(1, alloc_size))) {
-               return -1;
-       }
-#endif
-
-       pool->prev = *pool_head;
-       pool->size = alloc_size - sizeof(*pool);
-       *pool_head = pool;
-       mgr->last_alloc = NULL;
-
-       return 0;
-}
-
-/*
- * This is an internal API, code should not use it directly.
- * It initializes all fields as empty, then uses 'size' for 3 functions:
- * size > 0 means initialize the pool list with a pool of given size.
- *     This must be called right after allocating the object.
- * size = 0 means release all pools except the most recent one.
- *      If the first pool was allocated via embedding in another
- *      object, that pool will be preserved instead.
- *     This is useful to e.g. reset an object to the initial value.
- * size < 0 means release all pools.
- *     This must be done before destroying the object.
- */
-int __ast_string_field_init(struct ast_string_field_mgr *mgr, struct ast_string_field_pool **pool_head,
-                           int needed, const char *file, int lineno, const char *func)
-{
-       const char **p = (const char **) pool_head + 1;
-       struct ast_string_field_pool *cur = NULL;
-       struct ast_string_field_pool *preserve = NULL;
-
-       /* clear fields - this is always necessary */
-       while ((struct ast_string_field_mgr *) p != mgr) {
-               *p++ = __ast_string_field_empty;
-       }
-
-       mgr->last_alloc = NULL;
-#if defined(__AST_DEBUG_MALLOC)
-       mgr->owner_file = file;
-       mgr->owner_func = func;
-       mgr->owner_line = lineno;
-#endif
-       if (needed > 0) {               /* allocate the initial pool */
-               *pool_head = NULL;
-               mgr->embedded_pool = NULL;
-               return add_string_pool(mgr, pool_head, needed, file, lineno, func);
-       }
-
-       /* if there is an embedded pool, we can't actually release *all*
-        * pools, we must keep the embedded one. if the caller is about
-        * to free the structure that contains the stringfield manager
-        * and embedded pool anyway, it will be freed as part of that
-        * operation.
-        */
-       if ((needed < 0) && mgr->embedded_pool) {
-               needed = 0;
-       }
-
-       if (needed < 0) {               /* reset all pools */
-               cur = *pool_head;
-       } else if (mgr->embedded_pool) { /* preserve the embedded pool */
-               preserve = mgr->embedded_pool;
-               cur = *pool_head;
-       } else {                        /* preserve the last pool */
-               if (*pool_head == NULL) {
-                       ast_log(LOG_WARNING, "trying to reset empty pool\n");
-                       return -1;
-               }
-               preserve = *pool_head;
-               cur = preserve->prev;
-       }
-
-       if (preserve) {
-               preserve->prev = NULL;
-               preserve->used = preserve->active = 0;
-       }
-
-       while (cur) {
-               struct ast_string_field_pool *prev = cur->prev;
-
-               if (cur != preserve) {
-                       ast_free(cur);
-               }
-               cur = prev;
-       }
-
-       *pool_head = preserve;
-
-       return 0;
-}
-
-ast_string_field __ast_string_field_alloc_space(struct ast_string_field_mgr *mgr,
-                                               struct ast_string_field_pool **pool_head, size_t needed)
-{
-       char *result = NULL;
-       size_t space = (*pool_head)->size - (*pool_head)->used;
-       size_t to_alloc;
-
-       /* Make room for ast_string_field_allocation and make it a multiple of that. */
-       to_alloc = ast_make_room_for(needed, ast_string_field_allocation);
-       ast_assert(to_alloc % ast_alignof(ast_string_field_allocation) == 0);
-
-       if (__builtin_expect(to_alloc > space, 0)) {
-               size_t new_size = (*pool_head)->size;
-
-               while (new_size < to_alloc) {
-                       new_size *= 2;
-               }
-
-#if defined(__AST_DEBUG_MALLOC)
-               if (add_string_pool(mgr, pool_head, new_size, mgr->owner_file, mgr->owner_line, mgr->owner_func))
-                       return NULL;
-#else
-               if (add_string_pool(mgr, pool_head, new_size, __FILE__, __LINE__, __FUNCTION__))
-                       return NULL;
-#endif
-       }
-
-       /* pool->base is always aligned (gcc aligned attribute). We ensure that
-        * to_alloc is also a multiple of ast_alignof(ast_string_field_allocation)
-        * causing result to always be aligned as well; which in turn fixes that
-        * AST_STRING_FIELD_ALLOCATION(result) is aligned. */
-       result = (*pool_head)->base + (*pool_head)->used;
-       (*pool_head)->used += to_alloc;
-       (*pool_head)->active += needed;
-       result += ast_alignof(ast_string_field_allocation);
-       AST_STRING_FIELD_ALLOCATION(result) = needed;
-       mgr->last_alloc = result;
-
-       return result;
-}
-
-int __ast_string_field_ptr_grow(struct ast_string_field_mgr *mgr,
-                               struct ast_string_field_pool **pool_head, size_t needed,
-                               const ast_string_field *ptr)
-{
-       ssize_t grow = needed - AST_STRING_FIELD_ALLOCATION(*ptr);
-       size_t space = (*pool_head)->size - (*pool_head)->used;
-
-       if (*ptr != mgr->last_alloc) {
-               return 1;
-       }
-
-       if (space < grow) {
-               return 1;
-       }
-
-       (*pool_head)->used += grow;
-       (*pool_head)->active += grow;
-       AST_STRING_FIELD_ALLOCATION(*ptr) += grow;
-
-       return 0;
-}
-
-void __ast_string_field_release_active(struct ast_string_field_pool *pool_head,
-                                      const ast_string_field ptr)
-{
-       struct ast_string_field_pool *pool, *prev;
-
-       if (ptr == __ast_string_field_empty) {
-               return;
-       }
-
-       for (pool = pool_head, prev = NULL; pool; prev = pool, pool = pool->prev) {
-               if ((ptr >= pool->base) && (ptr <= (pool->base + pool->size))) {
-                       pool->active -= AST_STRING_FIELD_ALLOCATION(ptr);
-                       if (pool->active == 0) {
-                               if (prev) {
-                                       prev->prev = pool->prev;
-                                       ast_free(pool);
-                               } else {
-                                       pool->used = 0;
-                               }
-                       }
-                       break;
-               }
-       }
-}
-
-void __ast_string_field_ptr_build_va(struct ast_string_field_mgr *mgr,
-                                    struct ast_string_field_pool **pool_head,
-                                    ast_string_field *ptr, const char *format, va_list ap)
-{
-       size_t needed;
-       size_t available;
-       size_t space = (*pool_head)->size - (*pool_head)->used;
-       int res;
-       ssize_t grow;
-       char *target;
-       va_list ap2;
-
-       /* if the field already has space allocated, try to reuse it;
-          otherwise, try to use the empty space at the end of the current
-          pool
-       */
-       if (*ptr != __ast_string_field_empty) {
-               target = (char *) *ptr;
-               available = AST_STRING_FIELD_ALLOCATION(*ptr);
-               if (*ptr == mgr->last_alloc) {
-                       available += space;
-               }
-       } else {
-               /* pool->used is always a multiple of ast_alignof(ast_string_field_allocation)
-                * so we don't need to re-align anything here.
-                */
-               target = (*pool_head)->base + (*pool_head)->used + ast_alignof(ast_string_field_allocation);
-               if (space > ast_alignof(ast_string_field_allocation)) {
-                       available = space - ast_alignof(ast_string_field_allocation);
-               } else {
-                       available = 0;
-               }
-       }
-
-       va_copy(ap2, ap);
-       res = vsnprintf(target, available, format, ap2);
-       va_end(ap2);
-
-       if (res < 0) {
-               /* Are we out of memory? */
-               return;
-       }
-       if (res == 0) {
-               __ast_string_field_release_active(*pool_head, *ptr);
-               *ptr = __ast_string_field_empty;
-               return;
-       }
-       needed = (size_t)res + 1; /* NUL byte */
-
-       if (needed > available) {
-               /* the allocation could not be satisfied using the field's current allocation
-                  (if it has one), or the space available in the pool (if it does not). allocate
-                  space for it, adding a new string pool if necessary.
-               */
-               if (!(target = (char *) __ast_string_field_alloc_space(mgr, pool_head, needed))) {
-                       return;
-               }
-               vsprintf(target, format, ap);
-               va_end(ap); /* XXX va_end without va_start? */
-               __ast_string_field_release_active(*pool_head, *ptr);
-               *ptr = target;
-       } else if (*ptr != target) {
-               /* the allocation was satisfied using available space in the pool, but not
-                  using the space already allocated to the field
-               */
-               __ast_string_field_release_active(*pool_head, *ptr);
-               mgr->last_alloc = *ptr = target;
-               ast_assert(needed < (ast_string_field_allocation)-1);
-               AST_STRING_FIELD_ALLOCATION(target) = (ast_string_field_allocation)needed;
-               (*pool_head)->used += ast_make_room_for(needed, ast_string_field_allocation);
-               (*pool_head)->active += needed;
-       } else if ((grow = (needed - AST_STRING_FIELD_ALLOCATION(*ptr))) > 0) {
-               /* the allocation was satisfied by using available space in the pool *and*
-                  the field was the last allocated field from the pool, so it grew
-               */
-               AST_STRING_FIELD_ALLOCATION(*ptr) += grow;
-               (*pool_head)->used += ast_align_for(grow, ast_string_field_allocation);
-               (*pool_head)->active += grow;
-       }
-}
-
-void __ast_string_field_ptr_build(struct ast_string_field_mgr *mgr,
-                                 struct ast_string_field_pool **pool_head,
-                                 ast_string_field *ptr, const char *format, ...)
-{
-       va_list ap;
-
-       va_start(ap, format);
-       __ast_string_field_ptr_build_va(mgr, pool_head, ptr, format, ap);
-       va_end(ap);
-}
-
-void *__ast_calloc_with_stringfields(unsigned int num_structs, size_t struct_size, size_t field_mgr_offset,
-                                    size_t field_mgr_pool_offset, size_t pool_size, const char *file,
-                                    int lineno, const char *func)
-{
-       struct ast_string_field_mgr *mgr;
-       struct ast_string_field_pool *pool;
-       struct ast_string_field_pool **pool_head;
-       size_t pool_size_needed = sizeof(*pool) + pool_size;
-       size_t size_to_alloc = optimal_alloc_size(struct_size + pool_size_needed);
-       void *allocation;
-       unsigned int x;
-
-#if defined(__AST_DEBUG_MALLOC)
-       if (!(allocation = __ast_calloc(num_structs, size_to_alloc, file, lineno, func))) {
-               return NULL;
-       }
-#else
-       if (!(allocation = ast_calloc(num_structs, size_to_alloc))) {
-               return NULL;
-       }
-#endif
-
-       for (x = 0; x < num_structs; x++) {
-               void *base = allocation + (size_to_alloc * x);
-               const char **p;
-
-               mgr = base + field_mgr_offset;
-               pool_head = base + field_mgr_pool_offset;
-               pool = base + struct_size;
-
-               p = (const char **) pool_head + 1;
-               while ((struct ast_string_field_mgr *) p != mgr) {
-                       *p++ = __ast_string_field_empty;
-               }
-
-               mgr->embedded_pool = pool;
-               *pool_head = pool;
-               pool->size = size_to_alloc - struct_size - sizeof(*pool);
-#if defined(__AST_DEBUG_MALLOC)
-               mgr->owner_file = file;
-               mgr->owner_func = func;
-               mgr->owner_line = lineno;
-#endif
-       }
-
-       return allocation;
-}
-
-/* end of stringfields support */
-
 AST_MUTEX_DEFINE_STATIC(fetchadd_m); /* used for all fetc&add ops */
 
 int ast_atomic_fetchadd_int_slow(volatile int *p, int v)
@@ -2733,13 +2334,19 @@ int ast_parse_digest(const char *digest, struct ast_http_digest *d, int request,
 }
 
 #ifndef __AST_DEBUG_MALLOC
-int _ast_asprintf(char **ret, const char *file, int lineno, const char *func, const char *fmt, ...)
+int __ast_asprintf(const char *file, int lineno, const char *func, char **ret, const char *fmt, ...)
 {
        int res;
        va_list ap;
 
        va_start(ap, fmt);
-       if ((res = vasprintf(ret, fmt, ap)) == -1) {
+       res = vasprintf(ret, fmt, ap);
+       if (res < 0) {
+               /*
+                * *ret is undefined so set to NULL to ensure it is
+                * initialized to something useful.
+                */
+               *ret = NULL;
                MALLOC_FAILURE_MSG;
        }
        va_end(ap);
@@ -2784,7 +2391,19 @@ char *ast_utils_which(const char *binary, char *fullpath, size_t fullpath_size)
        return NULL;
 }
 
-void ast_do_crash(void)
+int ast_check_ipv6(void)
+{
+       int udp6_socket = socket(AF_INET6, SOCK_DGRAM, 0);
+
+       if (udp6_socket < 0) {
+               return 0;
+       }
+
+       close(udp6_socket);
+       return 1;
+}
+
+void DO_CRASH_NORETURN ast_do_crash(void)
 {
 #if defined(DO_CRASH)
        abort();
@@ -2796,17 +2415,16 @@ void ast_do_crash(void)
 #endif /* defined(DO_CRASH) */
 }
 
-#if defined(AST_DEVMODE)
-void __ast_assert_failed(int condition, const char *condition_str, const char *file, int line, const char *function)
+void DO_CRASH_NORETURN __ast_assert_failed(int condition, const char *condition_str, const char *file, int line, const char *function)
 {
        /*
         * Attempt to put it into the logger, but hope that at least
         * someone saw the message on stderr ...
         */
-       ast_log(__LOG_ERROR, file, line, function, "FRACK!, Failed assertion %s (%d)\n",
-               condition_str, condition);
        fprintf(stderr, "FRACK!, Failed assertion %s (%d) at line %d in %s of %s\n",
                condition_str, condition, line, function, file);
+       ast_log(__LOG_ERROR, file, line, function, "FRACK!, Failed assertion %s (%d)\n",
+               condition_str, condition);
 
        /* Generate a backtrace for the assert */
        ast_log_backtrace();
@@ -2819,7 +2437,6 @@ void __ast_assert_failed(int condition, const char *condition_str, const char *f
        usleep(1);
        ast_do_crash();
 }
-#endif /* defined(AST_DEVMODE) */
 
 char *ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
 {
@@ -2839,72 +2456,226 @@ char *ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
        return os;
 }
 
+#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__Darwin__)
+#include <ifaddrs.h>
+#include <net/if_dl.h>
+
 void ast_set_default_eid(struct ast_eid *eid)
 {
-#if defined(SIOCGIFHWADDR) && defined(HAVE_STRUCT_IFREQ_IFR_IFRU_IFRU_HWADDR)
-       int s, x = 0;
+       struct ifaddrs *ifap, *ifaphead;
+       int rtnerr;
+       const struct sockaddr_dl *sdl;
+       int alen;
+       caddr_t ap;
        char eid_str[20];
-       struct ifreq ifr;
-       static const unsigned int MAXIF = 10;
+       unsigned char empty_mac[6] = {0, 0, 0, 0, 0, 0};
+       unsigned char full_mac[6]  = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
 
-       s = socket(AF_INET, SOCK_STREAM, 0);
-       if (s < 0) {
+       rtnerr = getifaddrs(&ifaphead);
+       if (rtnerr) {
+               ast_log(LOG_WARNING, "No ethernet interface found for seeding global EID. "
+                       "You will have to set it manually.\n");
                return;
        }
-       for (x = 0; x < MAXIF; x++) {
-               static const char *prefixes[] = { "eth", "em" };
-               unsigned int i;
 
-               for (i = 0; i < ARRAY_LEN(prefixes); i++) {
-                       memset(&ifr, 0, sizeof(ifr));
-                       snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s%d", prefixes[i], x);
-                       if (!ioctl(s, SIOCGIFHWADDR, &ifr)) {
-                               break;
-                       }
+       if (!ifaphead) {
+               ast_log(LOG_WARNING, "No ethernet interface found for seeding global EID. "
+                       "You will have to set it manually.\n");
+               return;
+       }
+
+       for (ifap = ifaphead; ifap; ifap = ifap->ifa_next) {
+               if (ifap->ifa_addr->sa_family != AF_LINK) {
+                       continue;
                }
 
-               if (i == ARRAY_LEN(prefixes)) {
-                       /* Try pciX#[1..N] */
-                       for (i = 0; i < MAXIF; i++) {
-                               memset(&ifr, 0, sizeof(ifr));
-                               snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "pci%d#%u", x, i);
-                               if (!ioctl(s, SIOCGIFHWADDR, &ifr)) {
-                                       break;
-                               }
-                       }
-                       if (i == MAXIF) {
-                               continue;
-                       }
+               sdl = (const struct sockaddr_dl *) ifap->ifa_addr;
+               ap = ((caddr_t) ((sdl)->sdl_data + (sdl)->sdl_nlen));
+               alen = sdl->sdl_alen;
+               if (alen != 6 || !(memcmp(ap, &empty_mac, 6) && memcmp(ap, &full_mac, 6))) {
+                       continue;
                }
 
-               memcpy(eid, ((unsigned char *)&ifr.ifr_hwaddr) + 2, sizeof(*eid));
-               ast_debug(1, "Seeding global EID '%s' from '%s' using 'siocgifhwaddr'\n", ast_eid_to_str(eid_str, sizeof(eid_str), eid), ifr.ifr_name);
+               memcpy(eid, ap, sizeof(*eid));
+               ast_debug(1, "Seeding global EID '%s'\n",
+                               ast_eid_to_str(eid_str, sizeof(eid_str), eid));
+               freeifaddrs(ifaphead);
+               return;
+       }
+
+       ast_log(LOG_WARNING, "No ethernet interface found for seeding global EID. "
+               "You will have to set it manually.\n");
+       freeifaddrs(ifaphead);
+
+       return;
+}
+
+#elif defined(SOLARIS)
+#include <sys/sockio.h>
+#include <net/if_arp.h>
+
+void ast_set_default_eid(struct ast_eid *eid)
+{
+       int s;
+       int x;
+       int res = 0;
+       struct lifreq *ifr = NULL;
+       struct lifnum ifn;
+       struct lifconf ifc;
+       struct arpreq ar;
+       struct sockaddr_in *sa, *sa2;
+       char *buf = NULL;
+       char eid_str[20];
+       int bufsz;
+       unsigned char empty_mac[6] = {0, 0, 0, 0, 0, 0};
+       unsigned char full_mac[6]  = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
+
+       s = socket(AF_INET, SOCK_STREAM, 0);
+       if (s <= 0) {
+               ast_log(LOG_WARNING, "Unable to open a socket for seeding global EID. "
+                       " You will have to set it manually.\n");
+               return;
+       }
+
+       /* Get a count of interfaces on the machine */
+       ifn.lifn_family = AF_UNSPEC;
+       ifn.lifn_flags = 0;
+       ifn.lifn_count = 0;
+       if (ioctl(s, SIOCGLIFNUM, &ifn) < 0) {
+               ast_log(LOG_WARNING, "No ethernet interface found for seeding global EID. "
+                       " You will have to set it manually.\n");
                close(s);
                return;
        }
+
+       bufsz = ifn.lifn_count * sizeof(struct lifreq);
+       if (!(buf = ast_malloc(bufsz))) {
+               ast_log(LOG_WARNING, "Unable to allocate memory for seeding global EID. "
+                       "You will have to set it manually.\n");
+               close(s);
+               return;
+       }
+       memset(buf, 0, bufsz);
+
+       /* Get a list of interfaces on the machine */
+       ifc.lifc_len = bufsz;
+       ifc.lifc_buf = buf;
+       ifc.lifc_family = AF_UNSPEC;
+       ifc.lifc_flags = 0;
+       if (ioctl(s, SIOCGLIFCONF, &ifc) < 0) {
+               ast_log(LOG_WARNING, "No ethernet interface found for seeding global EID. "
+                       "You will have to set it manually.\n");
+               ast_free(buf);
+               close(s);
+               return;
+       }
+
+       for (ifr = (struct lifreq *)buf, x = 0; x < ifn.lifn_count; ifr++, x++) {
+               unsigned char *p;
+
+               sa = (struct sockaddr_in *)&(ifr->lifr_addr);
+               sa2 = (struct sockaddr_in *)&(ar.arp_pa);
+               *sa2 = *sa;
+
+               if(ioctl(s, SIOCGARP, &ar) >= 0) {
+                       p = (unsigned char *)&(ar.arp_ha.sa_data);
+                       if (!(memcmp(p, &empty_mac, 6) && memcmp(p, &full_mac, 6))) {
+                               continue;
+                       }
+
+                       memcpy(eid, p, sizeof(*eid));
+                       ast_debug(1, "Seeding global EID '%s'\n",
+                               ast_eid_to_str(eid_str, sizeof(eid_str), eid));
+                       ast_free(buf);
+                       close(s);
+                       return;
+               }
+       }
+
+       ast_log(LOG_WARNING, "No ethernet interface found for seeding global EID. "
+               "You will have to set it manually.\n");
+       ast_free(buf);
        close(s);
+
+       return;
+}
+
 #else
-#if defined(ifa_broadaddr) && !defined(SOLARIS)
+void ast_set_default_eid(struct ast_eid *eid)
+{
+       int s;
+       int i;
+       struct ifreq *ifr;
+       struct ifreq *ifrp;
+       struct ifconf ifc;
+       char *buf = NULL;
        char eid_str[20];
-       struct ifaddrs *ifap;
-
-       if (getifaddrs(&ifap) == 0) {
-               struct ifaddrs *p;
-               for (p = ifap; p; p = p->ifa_next) {
-                       if ((p->ifa_addr->sa_family == AF_LINK) && !(p->ifa_flags & IFF_LOOPBACK) && (p->ifa_flags & IFF_RUNNING)) {
-                               struct sockaddr_dl* sdp = (struct sockaddr_dl*) p->ifa_addr;
-                               memcpy(&(eid->eid), sdp->sdl_data + sdp->sdl_nlen, 6);
-                               ast_debug(1, "Seeding global EID '%s' from '%s' using 'getifaddrs'\n", ast_eid_to_str(eid_str, sizeof(eid_str), eid), p->ifa_name);
-                               freeifaddrs(ifap);
-                               return;
+       int bufsz, num_interfaces;
+       unsigned char empty_mac[6] = {0, 0, 0, 0, 0, 0};
+       unsigned char full_mac[6]  = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
+
+       s = socket(AF_INET, SOCK_STREAM, 0);
+       if (s < 0) {
+               ast_log(LOG_WARNING, "Unable to open socket for seeding global EID. "
+                       "You will have to set it manually.\n");
+               return;
+       }
+
+       ifc.ifc_len = 0;
+       ifc.ifc_buf = NULL;
+       if (ioctl(s, SIOCGIFCONF, &ifc) || ifc.ifc_len <= 0) {
+               ast_log(LOG_WARNING, "No ethernet interface found for seeding global EID. "
+                       "You will have to set it manually.\n");
+               close(s);
+               return;
+       }
+       bufsz = ifc.ifc_len;
+
+       if (!(buf = ast_malloc(bufsz))) {
+               ast_log(LOG_WARNING, "Unable to allocate memory for seeding global EID. "
+                       "You will have to set it manually.\n");
+               close(s);
+               return;
+       }
+
+       ifc.ifc_buf = buf;
+       if (ioctl(s, SIOCGIFCONF, &ifc) < 0) {
+               ast_log(LOG_WARNING, "Unable to retrieve ethernet interfaces for seeding global EID. "
+                       "You will have to set it manually.\n");
+               ast_free(buf);
+               close(s);
+               return;
+       }
+
+       ifrp = ifc.ifc_req;
+       num_interfaces = ifc.ifc_len / sizeof(*ifr);
+
+       for (i = 0; i < num_interfaces; i++) {
+               ifr = &ifrp[i];
+               if (!ioctl(s, SIOCGIFHWADDR, ifr)) {
+                       unsigned char *hwaddr = (unsigned char *) ifr->ifr_hwaddr.sa_data;
+
+                       if (!(memcmp(hwaddr, &empty_mac, 6) && memcmp(hwaddr, &full_mac, 6))) {
+                               continue;
                        }
+
+                       memcpy(eid, hwaddr, sizeof(*eid));
+                       ast_debug(1, "Seeding global EID '%s' from '%s' using 'siocgifhwaddr'\n",
+                               ast_eid_to_str(eid_str, sizeof(eid_str), eid), ifr->ifr_name);
+                       ast_free(buf);
+                       close(s);
+                       return;
                }
-               freeifaddrs(ifap);
        }
-#endif
-#endif
-       ast_debug(1, "No ethernet interface found for seeding global EID. You will have to set it manually.\n");
+
+       ast_log(LOG_WARNING, "No ethernet interface found for seeding global EID. "
+               "You will have to set it manually.\n");
+       ast_free(buf);
+       close(s);
+
+       return;
 }
+#endif /* LINUX */
 
 int ast_str_to_eid(struct ast_eid *eid, const char *s)
 {
@@ -2927,3 +2698,88 @@ int ast_eid_cmp(const struct ast_eid *eid1, const struct ast_eid *eid2)
 {
        return memcmp(eid1, eid2, sizeof(*eid1));
 }
+
+int ast_eid_is_empty(const struct ast_eid *eid)
+{
+       struct ast_eid empty_eid;
+
+       memset(&empty_eid, 0, sizeof(empty_eid));
+       return memcmp(eid, &empty_eid, sizeof(empty_eid)) ? 0 : 1;
+}
+
+int ast_file_is_readable(const char *filename)
+{
+#if defined(HAVE_EACCESS) || defined(HAVE_EUIDACCESS)
+#if defined(HAVE_EUIDACCESS) && !defined(HAVE_EACCESS)
+#define eaccess euidaccess
+#endif
+       return eaccess(filename, R_OK) == 0;
+#else
+       int fd = open(filename, O_RDONLY |  O_NONBLOCK);
+       if (fd < 0) {
+               return 0;
+       }
+       close(fd);
+       return 1;
+#endif
+}
+
+int ast_compare_versions(const char *version1, const char *version2)
+{
+       unsigned int major[2] = { 0 };
+       unsigned int minor[2] = { 0 };
+       unsigned int patch[2] = { 0 };
+       unsigned int extra[2] = { 0 };
+       int res;
+
+       sscanf(version1, "%u.%u.%u.%u", &major[0], &minor[0], &patch[0], &extra[0]);
+       sscanf(version2, "%u.%u.%u.%u", &major[1], &minor[1], &patch[1], &extra[1]);
+
+       res = major[0] - major[1];
+       if (res) {
+               return res;
+       }
+       res = minor[0] - minor[1];
+       if (res) {
+               return res;
+       }
+       res = patch[0] - patch[1];
+       if (res) {
+               return res;
+       }
+       return extra[0] - extra[1];
+}
+
+int __ast_fd_set_flags(int fd, int flags, enum ast_fd_flag_operation op,
+       const char *file, int lineno, const char *function)
+{
+       int f;
+
+       f = fcntl(fd, F_GETFL);
+       if (f == -1) {
+               ast_log(__LOG_ERROR, file, lineno, function,
+                       "Failed to get fcntl() flags for file descriptor: %s\n", strerror(errno));
+               return -1;
+       }
+
+       switch (op) {
+       case AST_FD_FLAG_SET:
+               f |= flags;
+               break;
+       case AST_FD_FLAG_CLEAR:
+               f &= ~flags;
+               break;
+       default:
+               ast_assert(0);
+               break;
+       }
+
+       f = fcntl(fd, F_SETFL, f);
+       if (f == -1) {
+               ast_log(__LOG_ERROR, file, lineno, function,
+                       "Failed to set fcntl() flags for file descriptor: %s\n", strerror(errno));
+               return -1;
+       }
+
+       return 0;
+}