Merge "res_pjsip_mwi.c: Fix null pointer crash"
[asterisk/asterisk.git] / utils / extconf.c
index 53347b4..1be739c 100644 (file)
@@ -1,4 +1,4 @@
-/*  
+/*
  * Asterisk -- An open source telephony toolkit.
  *
  * Copyright (C) 2006, Digium, Inc.
@@ -18,7 +18,7 @@
 
 
 /*!
- * \file extconf
+ * \file
  * A condensation of the pbx_config stuff, to read into exensions.conf, and provide an interface to the data there,
  * for operations outside of asterisk. A huge, awful hack.
  *
@@ -43,7 +43,7 @@
        <support_level>extended</support_level>
  ***/
 
-#define WRAP_LIBC_MALLOC
+#define ASTMM_LIBC ASTMM_REDIRECT
 #include "asterisk.h"
 
 #undef DEBUG_THREADS
@@ -86,7 +86,7 @@ void ast_verbose(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
 #endif
 
 #define AST_API_MODULE  1 /* gimme the inline defs! */
-struct ast_channel 
+struct ast_channel
 {
        char x; /* basically empty! */
 };
@@ -120,9 +120,6 @@ void ast_queue_log(const char *queuename, const char *callid, const char *agent,
 /* IN CONFLICT: void ast_verbose(const char *fmt, ...)
    __attribute__((format(printf, 1, 2))); */
 
-int ast_register_verbose(void (*verboser)(const char *string));
-int ast_unregister_verbose(void (*verboser)(const char *string));
-
 void ast_console_puts(const char *string);
 
 #define _A_ __FILE__, __LINE__, __PRETTY_FUNCTION__
@@ -245,7 +242,7 @@ static void __attribute__((constructor)) init_empty_mutex(void)
 
 static inline int __ast_pthread_mutex_init_attr(const char *filename, int lineno, const char *func,
                                                const char *mutex_name, ast_mutex_t *t,
-                                               pthread_mutexattr_t *attr) 
+                                               pthread_mutexattr_t *attr)
 {
 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
        int canlog = strcmp(filename, "logger.c");
@@ -464,7 +461,7 @@ static inline int __ast_pthread_mutex_unlock(const char *filename, int lineno, c
        }
 
        if ((res = pthread_mutex_unlock(&t->mutex))) {
-               __ast_mutex_logger("%s line %d (%s): Error releasing mutex: %s\n", 
+               __ast_mutex_logger("%s line %d (%s): Error releasing mutex: %s\n",
                                   filename, lineno, func, strerror(res));
                DO_THREAD_CRASH;
        }
@@ -505,7 +502,7 @@ static void  __attribute__((constructor)) init_##mutex(void) \
        ast_mutex_init(&mutex); \
 }
 #else /* !AST_MUTEX_INIT_W_CONSTRUCTORS */
-/* By default, use static initialization of mutexes. */ 
+/* By default, use static initialization of mutexes. */
 #define __AST_MUTEX_DEFINE(scope, mutex) \
        scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE
 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
@@ -618,7 +615,7 @@ AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
 {
        __asm __volatile (
        "       lock   xaddl   %0, %1 ;        "
-       : "+r" (v),                     /* 0 (result) */   
+       : "+r" (v),                     /* 0 (result) */
          "=m" (*p)                     /* 1 */
        : "m" (*p));                    /* 2 */
        return (v);
@@ -687,41 +684,6 @@ int ast_channel_trylock(struct ast_channel *chan);
 #define ast_free free
 #define ast_free_ptr free
 
-#define MALLOC_FAILURE_MSG \
-       ast_log(LOG_ERROR, "Memory Allocation Failure in function %s at line %d of %s\n", func, lineno, file);
-
-/*!
- * \brief A wrapper for malloc()
- *
- * ast_malloc() is a wrapper for malloc() that will generate an Asterisk log
- * message in the case that the allocation fails.
- *
- * The argument and return value are the same as malloc()
- */
-#define ast_malloc(len) \
-       _ast_malloc((len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
-
-#define ast_calloc(num, len) \
-       _ast_calloc((num), (len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
-
-#define ast_calloc_cache(num, len) \
-       _ast_calloc((num), (len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
-
-#define ast_realloc(p, len) \
-       _ast_realloc((p), (len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
-
-#define ast_strdup(str) \
-       _ast_strdup((str), __FILE__, __LINE__, __PRETTY_FUNCTION__)
-
-#define ast_strndup(str, len) \
-       _ast_strndup((str), (len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
-
-#define ast_asprintf(ret, fmt, ...) \
-       _ast_asprintf((ret), __FILE__, __LINE__, __PRETTY_FUNCTION__, fmt, __VA_ARGS__)
-
-#define ast_vasprintf(ret, fmt, ap) \
-       _ast_vasprintf((ret), __FILE__, __LINE__, __PRETTY_FUNCTION__, (fmt), (ap))
-
 struct ast_flags {  /* stolen from utils.h */
        unsigned int flags;
 };
@@ -746,6 +708,7 @@ struct ast_flags {  /* stolen from utils.h */
 
 #define MALLOC_FAILURE_MSG \
        ast_log(LOG_ERROR, "Memory Allocation Failure in function %s at line %d of %s\n", func, lineno, file);
+
 /*!
  * \brief A wrapper for malloc()
  *
@@ -755,10 +718,10 @@ struct ast_flags {  /* stolen from utils.h */
  * The argument and return value are the same as malloc()
  */
 #define ast_malloc(len) \
-       _ast_malloc((len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
+       __ast_malloc((len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
 
 AST_INLINE_API(
-void * attribute_malloc _ast_malloc(size_t len, const char *file, int lineno, const char *func),
+void * attribute_malloc __ast_malloc(size_t len, const char *file, int lineno, const char *func),
 {
        void *p;
 
@@ -778,10 +741,10 @@ void * attribute_malloc _ast_malloc(size_t len, const char *file, int lineno, co
  * The arguments and return value are the same as calloc()
  */
 #define ast_calloc(num, len) \
-       _ast_calloc((num), (len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
+       __ast_calloc((num), (len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
 
 AST_INLINE_API(
-void * attribute_malloc _ast_calloc(size_t num, size_t len, const char *file, int lineno, const char *func),
+void * attribute_malloc __ast_calloc(size_t num, size_t len, const char *file, int lineno, const char *func),
 {
        void *p;
 
@@ -803,7 +766,7 @@ void * attribute_malloc _ast_calloc(size_t num, size_t len, const char *file, in
  * The arguments and return value are the same as calloc()
  */
 #define ast_calloc_cache(num, len) \
-       _ast_calloc((num), (len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
+       __ast_calloc((num), (len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
 
 /*!
  * \brief A wrapper for realloc()
@@ -814,10 +777,10 @@ void * attribute_malloc _ast_calloc(size_t num, size_t len, const char *file, in
  * The arguments and return value are the same as realloc()
  */
 #define ast_realloc(p, len) \
-       _ast_realloc((p), (len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
+       __ast_realloc((p), (len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
 
 AST_INLINE_API(
-void * attribute_malloc _ast_realloc(void *p, size_t len, const char *file, int lineno, const char *func),
+void * attribute_malloc __ast_realloc(void *p, size_t len, const char *file, int lineno, const char *func),
 {
        void *newp;
 
@@ -841,10 +804,10 @@ void * attribute_malloc _ast_realloc(void *p, size_t len, const char *file, int
  * The argument and return value are the same as strdup()
  */
 #define ast_strdup(str) \
-       _ast_strdup((str), __FILE__, __LINE__, __PRETTY_FUNCTION__)
+       __ast_strdup((str), __FILE__, __LINE__, __PRETTY_FUNCTION__)
 
 AST_INLINE_API(
-char * attribute_malloc _ast_strdup(const char *str, const char *file, int lineno, const char *func),
+char * attribute_malloc __ast_strdup(const char *str, const char *file, int lineno, const char *func),
 {
        char *newstr = NULL;
 
@@ -864,16 +827,16 @@ char * attribute_malloc _ast_strdup(const char *str, const char *file, int linen
  * message in the case that the allocation fails.
  *
  * ast_strndup(), unlike strndup(), can safely accept a NULL argument for the
- * string to duplicate. If a NULL argument is provided, ast_strdup will return  
+ * string to duplicate. If a NULL argument is provided, ast_strdup will return
  * NULL without generating any kind of error log message.
  *
  * The arguments and return value are the same as strndup()
  */
 #define ast_strndup(str, len) \
-       _ast_strndup((str), (len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
+       __ast_strndup((str), (len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
 
 AST_INLINE_API(
-char * attribute_malloc _ast_strndup(const char *str, size_t len, const char *file, int lineno, const char *func),
+char * attribute_malloc __ast_strndup(const char *str, size_t len, const char *file, int lineno, const char *func),
 {
        char *newstr = NULL;
 
@@ -895,11 +858,11 @@ char * attribute_malloc _ast_strndup(const char *str, size_t len, const char *fi
  * The arguments and return value are the same as asprintf()
  */
 #define ast_asprintf(ret, fmt, ...) \
-       _ast_asprintf((ret), __FILE__, __LINE__, __PRETTY_FUNCTION__, fmt, __VA_ARGS__)
+       __ast_asprintf(__FILE__, __LINE__, __PRETTY_FUNCTION__, (ret), (fmt), __VA_ARGS__)
 
 AST_INLINE_API(
 __attribute__((format(printf, 5, 6)))
-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;
@@ -922,11 +885,11 @@ int _ast_asprintf(char **ret, const char *file, int lineno, const char *func, co
  * The arguments and return value are the same as vasprintf()
  */
 #define ast_vasprintf(ret, fmt, ap) \
-       _ast_vasprintf((ret), __FILE__, __LINE__, __PRETTY_FUNCTION__, (fmt), (ap))
+       __ast_vasprintf((ret), (fmt), (ap), __FILE__, __LINE__, __PRETTY_FUNCTION__)
 
 AST_INLINE_API(
-__attribute__((format(printf, 5, 0)))
-int _ast_vasprintf(char **ret, const char *file, int lineno, const char *func, const char *fmt, va_list ap),
+__attribute__((format(printf, 2, 0)))
+int __ast_vasprintf(char **ret, const char *fmt, va_list ap, const char *file, int lineno, const char *func),
 {
        int res;
 
@@ -1033,19 +996,19 @@ static void  LLB_ADD(char *str)
        int siz = strlen(str);
        if (rem < siz+1) {
                lline_buffer = ast_realloc(lline_buffer, lline_buffer_size + CB_INCR + siz + 1);
-               if (!lline_buffer) 
+               if (!lline_buffer)
                        return;
                lline_buffer_size += CB_INCR + siz + 1;
        }
        strcat(lline_buffer,str);
 }
 
-static void CB_RESET(void )  
-{ 
-       comment_buffer[0] = 0; 
+static void CB_RESET(void )
+{
+       comment_buffer[0] = 0;
        lline_buffer[0] = 0;
 }
-               
+
 /*! \brief Keep track of how many threads are currently trying to wait*() on
  *  a child process */
 static unsigned int safe_system_level = 0;
@@ -1108,7 +1071,7 @@ int ast_safe_system(const char *s)
        pid = fork();
 #else
        pid = vfork();
-#endif 
+#endif
 
        if (pid == 0) {
 #ifdef HAVE_WORKING_FORK
@@ -1124,7 +1087,7 @@ int ast_safe_system(const char *s)
                        if (res > -1) {
                                res = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
                                break;
-                       } else if (errno != EINTR) 
+                       } else if (errno != EINTR)
                                break;
                }
        } else {
@@ -1141,7 +1104,7 @@ int ast_safe_system(const char *s)
 }
 
 static struct ast_comment *ALLOC_COMMENT(const char *buffer)
-{ 
+{
        struct ast_comment *x = ast_calloc(1,sizeof(struct ast_comment)+strlen(buffer)+1);
        strcpy(x->cmt, buffer);
        return x;
@@ -1164,7 +1127,7 @@ static struct ast_config_engine *config_engine_list;
 struct ast_category {
        char name[80];
        int ignored;                    /*!< do not let user of the config see this category */
-       int include_level;      
+       int include_level;
     char *file;                /*!< the file name from whence this declaration was read */
     int lineno;
        struct ast_comment *precomments;
@@ -1257,7 +1220,7 @@ char *ast_trim_blanks(char *str),
 
        if (work) {
                work += strlen(work) - 1;
-               /* It's tempting to only want to erase after we exit this loop, 
+               /* It's tempting to only want to erase after we exit this loop,
                   but since ast_trim_blanks *could* receive a constant string
                   (which we presumably wouldn't have to touch), we shouldn't
                   actually set anything unless we must, and it's easier just
@@ -1286,7 +1249,7 @@ char *ast_strip(char *s),
        if (s)
                ast_trim_blanks(s);
        return s;
-} 
+}
 )
 
 
@@ -1319,15 +1282,15 @@ void localized_ast_include_rename(struct ast_config *conf, const char *from_file
 
 static struct ast_variable *ast_variable_new(const char *name, const char *value, const char *filename);
 
-static struct ast_variable *ast_variable_new(const char *name, const char *value, const char *filename) 
+static struct ast_variable *ast_variable_new(const char *name, const char *value, const char *filename)
 {
        struct ast_variable *variable;
-       int name_len = strlen(name) + 1;        
+       int name_len = strlen(name) + 1;
 
        if ((variable = ast_calloc(1, name_len + strlen(value) + 1 + strlen(filename) + 1 + sizeof(*variable)))) {
                variable->name = variable->stuff;
-               variable->value = variable->stuff + name_len;           
-               variable->file = variable->value + strlen(value) + 1;           
+               variable->value = variable->stuff + name_len;
+               variable->file = variable->value + strlen(value) + 1;
                strcpy(variable->name,name);
                strcpy(variable->value,value);
                strcpy(variable->file,filename);
@@ -1339,11 +1302,11 @@ static struct ast_variable *ast_variable_new(const char *name, const char *value
 static struct ast_config_include *ast_include_new(struct ast_config *conf, const char *from_file, const char *included_file, int is_exec, const char *exec_file, int from_lineno, char *real_included_file_name, int real_included_file_name_size)
 {
        /* a file should be included ONCE. Otherwise, if one of the instances is changed,
-       then all be changed. -- how do we know to include it? -- Handling modified 
+       then all be changed. -- how do we know to include it? -- Handling modified
        instances is possible, I'd have
        to create a new master for each instance. */
        struct ast_config_include *inc;
-    
+
        inc = ast_include_find(conf, included_file);
        if (inc)
        {
@@ -1352,7 +1315,7 @@ static struct ast_config_include *ast_include_new(struct ast_config *conf, const
                ast_log(LOG_WARNING,"'%s', line %d:  Same File included more than once! This data will be saved in %s if saved back to disk.\n", from_file, from_lineno, real_included_file_name);
        } else
                *real_included_file_name = 0;
-       
+
        inc = ast_calloc(1,sizeof(struct ast_config_include));
        inc->include_location_file = ast_strdup(from_file);
        inc->include_location_lineno = from_lineno;
@@ -1360,15 +1323,15 @@ static struct ast_config_include *ast_include_new(struct ast_config *conf, const
                inc->included_file = ast_strdup(real_included_file_name);
        else
                inc->included_file = ast_strdup(included_file);
-       
+
        inc->exec = is_exec;
        if (is_exec)
                inc->exec_file = ast_strdup(exec_file);
-       
+
        /* attach this new struct to the conf struct */
        inc->next = conf->includes;
        conf->includes = inc;
-    
+
        return inc;
 }
 
@@ -1377,13 +1340,13 @@ void localized_ast_include_rename(struct ast_config *conf, const char *from_file
        struct ast_config_include *incl;
        struct ast_category *cat;
        struct ast_variable *v;
-    
+
        int from_len = strlen(from_file);
        int to_len = strlen(to_file);
-    
+
        if (strcmp(from_file, to_file) == 0) /* no use wasting time if the name is the same */
                return;
-       
+
        /* the manager code allows you to read in one config file, then
        write it back out under a different name. But, the new arrangement
           ties output lines to the file name. So, before you try to write
@@ -1392,7 +1355,7 @@ void localized_ast_include_rename(struct ast_config *conf, const char *from_file
        */
        /* file names are on categories, includes (of course), and on variables. So,
           traverse all this and swap names */
-       
+
        for (incl = conf->includes; incl; incl=incl->next) {
                if (strcmp(incl->include_location_file,from_file) == 0) {
                        if (from_len >= to_len)
@@ -1523,7 +1486,7 @@ static struct ast_variable *variable_clone(const struct ast_variable *old)
 
        return new;
 }
+
 static void ast_variables_destroy(struct ast_variable *v)
 {
        struct ast_variable *vn;
@@ -1538,7 +1501,7 @@ static void ast_variables_destroy(struct ast_variable *v)
 static void ast_includes_destroy(struct ast_config_include *incls)
 {
        struct ast_config_include *incl,*inclnext;
-    
+
        for (incl=incls; incl; incl = inclnext) {
                inclnext = incl->next;
                if (incl->include_location_file)
@@ -1559,7 +1522,7 @@ static void ast_config_destroy(struct ast_config *cfg)
                return;
 
        ast_includes_destroy(cfg->includes);
-       
+
        cat = cfg->root;
        while (cat) {
                ast_variables_destroy(cat->root);
@@ -1695,7 +1658,7 @@ extern int ast_language_is_prefix;
 */
 #define AST_RWLIST_RDLOCK(head)                                         \
         ast_rwlock_rdlock(&(head)->lock)
-       
+
 /*!
   \brief Attempts to unlock a read/write based list.
   \param head This is a pointer to the list head structure
@@ -1969,7 +1932,7 @@ struct {                                                          \
 }
 
 #define AST_RWLIST_ENTRY AST_LIST_ENTRY
+
 /*!
   \brief Returns the first entry contained in a list.
   \param head This is a pointer to the list head structure
@@ -2381,7 +2344,7 @@ struct ast_switch {
        AST_LIST_ENTRY(ast_switch) list;
        const char *name;                       /*!< Name of the switch */
        const char *description;                /*!< Description of the switch */
-       
+
        ast_switch_f *exists;
        ast_switch_f *canmatch;
        ast_switch_f *exec;
@@ -2455,7 +2418,7 @@ static const char *ast_var_name(const struct ast_var_t *var)
 }
 
 /* experiment 1: see if it's easier just to use existing config code
- *               to read in the extensions.conf file. In this scenario, 
+ *               to read in the extensions.conf file. In this scenario,
                  I have to rip/copy code from other modules, because they
                  are staticly declared as-is. A solution would be to move
                  the ripped code to another location and make them available
@@ -2467,7 +2430,7 @@ static void ast_log(int level, const char *file, int line, const char *function,
 {
        va_list vars;
        va_start(vars,fmt);
-       
+
        printf("LOG: lev:%d file:%s  line:%d func: %s  ",
                   level, file, line, function);
        vprintf(fmt, vars);
@@ -2479,7 +2442,7 @@ void __attribute__((format(printf, 1, 2))) ast_verbose(const char *fmt, ...)
 {
        va_list vars;
        va_start(vars,fmt);
-       
+
        printf("VERBOSE: ");
        vprintf(fmt, vars);
        fflush(stdout);
@@ -2697,7 +2660,7 @@ struct ast_state_cb {
 /*! \brief Structure for dial plan hints
 
   \note Hints are pointers from an extension in the dialplan to one or
-  more devices (tech/name) 
+  more devices (tech/name)
        - See \ref AstExtState
 */
 struct ast_hint {
@@ -2725,7 +2688,7 @@ AST_LIST_HEAD(store_hints, store_hint);
 #define STATUS_SUCCESS         5
 
 static struct ast_var_t *ast_var_assign(const char *name, const char *value)
-{      
+{
        struct ast_var_t *var;
        int name_len = strlen(name) + 1;
        int value_len = strlen(value) + 1;
@@ -2737,10 +2700,10 @@ static struct ast_var_t *ast_var_assign(const char *name, const char *value)
        ast_copy_string(var->name, name, name_len);
        var->value = var->name + name_len;
        ast_copy_string(var->value, value, value_len);
-       
+
        return var;
-}      
-       
+}
+
 static void ast_var_delete(struct ast_var_t *var)
 {
        free(var);
@@ -3017,7 +2980,7 @@ static void null_datad(void *foo)
 }
 
 /*! \brief Find realtime engine for realtime family */
-static struct ast_config_engine *find_engine(const char *family, char *database, int dbsiz, char *table, int tabsiz) 
+static struct ast_config_engine *find_engine(const char *family, char *database, int dbsiz, char *table, int tabsiz)
 {
        struct ast_config_engine *eng, *ret = NULL;
        struct ast_config_map *map;
@@ -3040,12 +3003,12 @@ static struct ast_config_engine *find_engine(const char *family, char *database,
                                ret = eng;
                }
        }
-       
-       
+
+
        /* if we found a mapping, but the engine is not available, then issue a warning */
        if (map && !ret)
                ast_log(LOG_WARNING, "Realtime mapping for '%s' found to engine '%s', but the engine is not available\n", map->name, map->driver);
-       
+
        return ret;
 }
 
@@ -3120,7 +3083,7 @@ static void ast_category_destroy(struct ast_category *cat)
        ast_variables_destroy(cat->root);
        if (cat->file)
                free(cat->file);
-       
+
        free(cat);
 }
 
@@ -3137,7 +3100,7 @@ static struct ast_config *ast_config_internal_load(const char *filename, struct
        char db[256];
        char table[256];
        struct ast_config_engine *loader = &text_file_engine;
-       struct ast_config *result; 
+       struct ast_config *result;
 
        if (cfg->include_level == cfg->max_include_level) {
                ast_log(LOG_WARNING, "Maximum Include level (%d) exceeded\n", cfg->max_include_level);
@@ -3165,7 +3128,7 @@ static struct ast_config *ast_config_internal_load(const char *filename, struct
        }
 
        result = loader->load_func(db, table, filename, cfg, withcomments, suggested_incl_file);
-       /* silence is golden 
+       /* silence is golden
           ast_log(LOG_WARNING, "finished internal loading file %s level=%d\n", filename, cfg->include_level);
        */
 
@@ -3204,7 +3167,7 @@ static int process_text_line(struct ast_config *cfg, struct ast_category **cat,
                        return -1;
                }
                (*cat)->lineno = lineno;
-        
+
                /* add comments */
                if (withcomments && comment_buffer && comment_buffer[0] ) {
                        newcat->precomments = ALLOC_COMMENT(comment_buffer);
@@ -3214,7 +3177,7 @@ static int process_text_line(struct ast_config *cfg, struct ast_category **cat,
                }
                if( withcomments )
                        CB_RESET();
-               
+
                /* If there are options or categories to inherit from, process them now */
                if (c) {
                        if (!(cur = strchr(c, ')'))) {
@@ -3241,7 +3204,7 @@ static int process_text_line(struct ast_config *cfg, struct ast_category **cat,
                                        }
                                } else {
                                        struct ast_category *base;
-                               
+
                                        base = category_get(cfg, cur, 1);
                                        if (!base) {
                                                ast_log(LOG_WARNING, "Inheritance requested, but category '%s' does not exist, line %d of %s\n", cur, lineno, configfile);
@@ -3264,7 +3227,7 @@ static int process_text_line(struct ast_config *cfg, struct ast_category **cat,
                        c = ast_skip_blanks(c + 1);
                        if (!*c)
                                c = NULL;
-               } else 
+               } else
                        c = NULL;
                do_include = !strcasecmp(cur, "include");
                if(!do_include)
@@ -3279,7 +3242,7 @@ static int process_text_line(struct ast_config *cfg, struct ast_category **cat,
                        if (c) {
                                char *cur2;
                                char real_inclusion_name[256];
-                
+
                                /* Strip off leading and trailing "'s and <>'s */
                                while((*c == '<') || (*c == '>') || (*c == '\"')) c++;
                                /* Get rid of leading mess */
@@ -3294,7 +3257,7 @@ static int process_text_line(struct ast_config *cfg, struct ast_category **cat,
                                }
                                /* #exec </path/to/executable>
                                   We create a tmp file, then we #include it, then we delete it. */
-                               if (do_exec) { 
+                               if (do_exec) {
                                        snprintf(exec_file, sizeof(exec_file), "/var/tmp/exec.%d.%ld", (int)time(NULL), (long)pthread_self());
                                        snprintf(cmd, sizeof(cmd), "%s > %s 2>&1", cur, exec_file);
                                        ast_safe_system(cmd);
@@ -3303,26 +3266,26 @@ static int process_text_line(struct ast_config *cfg, struct ast_category **cat,
                                        exec_file[0] = '\0';
                                /* A #include */
                                /* ast_log(LOG_WARNING, "Reading in included file %s withcomments=%d\n", cur, withcomments); */
-                               
+
                                /* record this inclusion */
                                ast_include_new(cfg, configfile, cur, do_exec, cur2, lineno, real_inclusion_name, sizeof(real_inclusion_name));
-                               
+
                                do_include = ast_config_internal_load(cur, cfg, withcomments, real_inclusion_name) ? 1 : 0;
                                if(!ast_strlen_zero(exec_file))
                                        unlink(exec_file);
                                if(!do_include)
                                        return 0;
                                /* ast_log(LOG_WARNING, "Done reading in included file %s withcomments=%d\n", cur, withcomments); */
-                               
+
                        } else {
-                               ast_log(LOG_WARNING, "Directive '#%s' needs an argument (%s) at line %d of %s\n", 
+                               ast_log(LOG_WARNING, "Directive '#%s' needs an argument (%s) at line %d of %s\n",
                                                do_exec ? "exec" : "include",
                                                do_exec ? "/path/to/executable" : "filename",
                                                lineno,
                                                configfile);
                        }
                }
-               else 
+               else
                        ast_log(LOG_WARNING, "Unknown directive '%s' at line %d of %s\n", cur, lineno, configfile);
        } else {
                /* Just a line (variable = value) */
@@ -3356,7 +3319,7 @@ static int process_text_line(struct ast_config *cfg, struct ast_category **cat,
                                }
                                if( withcomments )
                                        CB_RESET();
-                               
+
                        } else {
                                return -1;
                        }
@@ -3394,7 +3357,7 @@ static struct ast_config *config_text_file_load(const char *database, const char
        struct ast_category *cat = NULL;
        int count = 0;
        struct stat statbuf;
-       
+
        cat = ast_config_get_current_category(cfg);
 
        if (filename[0] == '/') {
@@ -3409,7 +3372,7 @@ static struct ast_config *config_text_file_load(const char *database, const char
        if (withcomments && cfg && cfg->include_level < 2 ) {
                CB_INIT();
        }
-       
+
 #ifdef AST_INCLUDE_GLOB
        {
                int glob_ret;
@@ -3460,17 +3423,17 @@ static struct ast_config *config_text_file_load(const char *database, const char
                while(!feof(f)) {
                        lineno++;
                        if (fgets(buf, sizeof(buf), f)) {
-                               if ( withcomments ) {    
+                               if ( withcomments ) {
                                        CB_ADD(lline_buffer);       /* add the current lline buffer to the comment buffer */
                                        lline_buffer[0] = 0;        /* erase the lline buffer */
                                }
-                               
+
                                new_buf = buf;
-                               if (comment) 
+                               if (comment)
                                        process_buf = NULL;
                                else
                                        process_buf = buf;
-                               
+
                                while ((comment_p = strchr(new_buf, COMMENT_META))) {
                                        if ((comment_p > new_buf) && (*(comment_p-1) == '\\')) {
                                                /* Yuck, gotta memmove */
@@ -3502,7 +3465,7 @@ static struct ast_config *config_text_file_load(const char *database, const char
                                                                        CB_ADD(";");
                                                                        CB_ADD_LEN(oldptr+1,new_buf-oldptr-1);
                                                                }
-                                                               
+
                                                                memmove(oldptr, new_buf, strlen(new_buf) + 1);
                                                                new_buf = oldptr;
                                                        } else
@@ -3510,12 +3473,12 @@ static struct ast_config *config_text_file_load(const char *database, const char
                                                }
                                        } else {
                                                if (!comment) {
-                                                       /* If ; is found, and we are not nested in a comment, 
+                                                       /* If ; is found, and we are not nested in a comment,
                                                           we immediately stop all comment processing */
                                                        if ( withcomments ) {
                                                                LLB_ADD(comment_p);
                                                        }
-                                                       *comment_p = '\0'; 
+                                                       *comment_p = '\0';
                                                        new_buf = comment_p;
                                                } else
                                                        new_buf = comment_p + 1;
@@ -3525,7 +3488,7 @@ static struct ast_config *config_text_file_load(const char *database, const char
                                {
                                        CB_ADD(buf);  /* the whole line is a comment, store it */
                                }
-                               
+
                                if (process_buf) {
                                        char *stripped_process_buf = ast_strip(process_buf);
                                        if (!ast_strlen_zero(stripped_process_buf)) {
@@ -3537,7 +3500,7 @@ static struct ast_config *config_text_file_load(const char *database, const char
                                }
                        }
                }
-               fclose(f);              
+               fclose(f);
        } while(0);
        if (comment) {
                ast_log(LOG_WARNING,"Unterminated comment detected beginning on line %d\n", nest[comment]);
@@ -3551,12 +3514,12 @@ static struct ast_config *config_text_file_load(const char *database, const char
                }
 #endif
        if (cfg && cfg->include_level == 1 && withcomments && comment_buffer) {
-               if (comment_buffer) { 
+               if (comment_buffer) {
                        free(comment_buffer);
                        free(lline_buffer);
-                       comment_buffer=0; 
-                       lline_buffer=0; 
-                       comment_buffer_size=0; 
+                       comment_buffer=0;
+                       lline_buffer=0;
+                       comment_buffer_size=0;
                        lline_buffer_size=0;
                }
        }
@@ -3569,7 +3532,7 @@ static struct ast_config *config_text_file_load(const char *database, const char
 
 static struct ast_config *ast_config_new(void) ;
 
-static struct ast_config *ast_config_new(void) 
+static struct ast_config *ast_config_new(void)
 {
        struct ast_config *config;
 
@@ -3622,7 +3585,7 @@ static struct ast_category *next_available_category(struct ast_category *cat)
 }
 
 static char *ast_category_browse(struct ast_config *config, const char *prev)
-{      
+{
        struct ast_category *cat = NULL;
 
        if (prev && config->last_browse && (config->last_browse->name == prev))
@@ -3645,7 +3608,7 @@ static char *ast_category_browse(struct ast_config *config, const char *prev)
                        }
                }
        }
-       
+
        if (cat)
                cat = next_available_category(cat);
 
@@ -3666,21 +3629,21 @@ void ast_config_set_current_category(struct ast_config *cfg, const struct ast_ca
 /* NOTE: categories and variables each have a file and lineno attribute. On a save operation, these are used to determine
    which file and line number to write out to. Thus, an entire hierarchy of config files (via #include statements) can be
    recreated. BUT, care must be taken to make sure that every cat and var has the proper file name stored, or you may
-   be shocked and mystified as to why things are not showing up in the files! 
-   
+   be shocked and mystified as to why things are not showing up in the files!
+
    Also, All #include/#exec statements are recorded in the "includes" LL in the ast_config structure. The file name
    and line number are stored for each include, plus the name of the file included, so that these statements may be
-   included in the output files on a file_save operation. 
-   
+   included in the output files on a file_save operation.
+
    The lineno's are really just for relative placement in the file. There is no attempt to make sure that blank lines
    are included to keep the lineno's the same between input and output. The lineno fields are used mainly to determine
    the position of the #include and #exec directives. So, blank lines tend to disappear from a read/rewrite operation,
    and a header gets added.
-   
+
    vars and category heads are output in the order they are stored in the config file. So, if the software
    shuffles these at all, then the placement of #include directives might get a little mixed up, because the
    file/lineno data probably won't get changed.
-   
+
 */
 
 static void gen_header(FILE *f1, const char *configfile, const char *fn, const char *generator)
@@ -3689,7 +3652,7 @@ static void gen_header(FILE *f1, const char *configfile, const char *fn, const c
        time_t t;
        time(&t);
        ast_copy_string(date, ctime(&t), sizeof(date));
-       
+
        fprintf(f1, ";!\n");
        fprintf(f1, ";! Automatically generated configuration file\n");
        if (strcmp(configfile, fn))
@@ -3708,7 +3671,7 @@ static void set_fn(char *fn, int fn_size, const char *file, const char *configfi
                        ast_copy_string(fn, configfile, fn_size);
                else
                        snprintf(fn, fn_size, "%s/%s", ast_config_AST_CONFIG_DIR, configfile);
-       } else if (file[0] == '/') 
+       } else if (file[0] == '/')
                ast_copy_string(fn, file, fn_size);
        else
                snprintf(fn, fn_size, "%s/%s", ast_config_AST_CONFIG_DIR, file);
@@ -3725,20 +3688,20 @@ int localized_config_text_file_save(const char *configfile, const struct ast_con
        struct ast_comment *cmt;
        struct ast_config_include *incl;
        int blanklines = 0;
-       
+
        /* reset all the output flags, in case this isn't our first time saving this data */
-       
+
        for (incl=cfg->includes; incl; incl = incl->next)
                incl->output = 0;
-       
+
        /* go thru all the inclusions and make sure all the files involved (configfile plus all its inclusions)
           are all truncated to zero bytes and have that nice header*/
-       
+
        for (incl=cfg->includes; incl; incl = incl->next)
        {
                if (!incl->exec) { /* leave the execs alone -- we'll write out the #exec directives, but won't zero out the include files or exec files*/
                        FILE *f1;
-                       
+
                        set_fn(fn, sizeof(fn), incl->included_file, configfile); /* normally, fn is just set to incl->included_file, prepended with config dir if relative */
                        f1 = fopen(fn,"w");
                        if (f1) {
@@ -3749,24 +3712,24 @@ int localized_config_text_file_save(const char *configfile, const struct ast_con
                        }
                }
        }
-       
+
        set_fn(fn, sizeof(fn), 0, configfile); /* just set fn to absolute ver of configfile */
-#ifdef __CYGWIN__      
+#ifdef __CYGWIN__
        if ((f = fopen(fn, "w+"))) {
 #else
        if ((f = fopen(fn, "w"))) {
-#endif     
+#endif
                if (option_verbose > 1)
                        ast_verbose(VERBOSE_PREFIX_2 "Saving '%s': ", fn);
 
                gen_header(f, configfile, fn, generator);
                cat = cfg->root;
                fclose(f);
-        
+
                /* from here out, we open each involved file and concat the stuff we need to add to the end and immediately close... */
-               /* since each var, cat, and associated comments can come from any file, we have to be 
+               /* since each var, cat, and associated comments can come from any file, we have to be
                   mobile, and open each file, print, and close it on an entry-by-entry basis */
-               
+
                while(cat) {
                        set_fn(fn, sizeof(fn), cat->file, configfile);
                        f = fopen(fn, "a");
@@ -3775,7 +3738,7 @@ int localized_config_text_file_save(const char *configfile, const struct ast_con
                                ast_verbose(VERBOSE_PREFIX_2 "Unable to write %s (%s)", fn, strerror(errno));
                                return -1;
                        }
-                       
+
                        /* dump any includes that happen before this category header */
                        for (incl=cfg->includes; incl; incl = incl->next) {
                                if (strcmp(incl->include_location_file, cat->file) == 0){
@@ -3788,7 +3751,7 @@ int localized_config_text_file_save(const char *configfile, const struct ast_con
                                        }
                                }
                        }
-            
+
                        /* Dump section with any appropriate comment */
                        for (cmt = cat->precomments; cmt; cmt=cmt->next) {
                                if (cmt->cmt[0] != ';' || cmt->cmt[1] != '!')
@@ -3803,7 +3766,7 @@ int localized_config_text_file_save(const char *configfile, const struct ast_con
                        if (!cat->sameline)
                                fprintf(f,"\n");
                        fclose(f);
-            
+
                        var = cat->root;
                        while(var) {
                                set_fn(fn, sizeof(fn), var->file, configfile);
@@ -3813,7 +3776,7 @@ int localized_config_text_file_save(const char *configfile, const struct ast_con
                                        ast_verbose(VERBOSE_PREFIX_2 "Unable to write %s (%s)", fn, strerror(errno));
                                        return -1;
                                }
-                
+
                                /* dump any includes that happen before this category header */
                                for (incl=cfg->includes; incl; incl = incl->next) {
                                        if (strcmp(incl->include_location_file, var->file) == 0){
@@ -3826,24 +3789,24 @@ int localized_config_text_file_save(const char *configfile, const struct ast_con
                                                }
                                        }
                                }
-                
+
                                for (cmt = var->precomments; cmt; cmt=cmt->next) {
                                        if (cmt->cmt[0] != ';' || cmt->cmt[1] != '!')
                                                fprintf(f,"%s", cmt->cmt);
                                }
-                               if (var->sameline) 
+                               if (var->sameline)
                                        fprintf(f, "%s %s %s  %s", var->name, (var->object ? "=>" : "="), var->value, var->sameline->cmt);
-                               else    
+                               else
                                        fprintf(f, "%s %s %s\n", var->name, (var->object ? "=>" : "="), var->value);
                                if (var->blanklines) {
                                        blanklines = var->blanklines;
                                        while (blanklines--)
                                                fprintf(f, "\n");
                                }
-                               
+
                                fclose(f);
-                
-                               
+
+
                                var = var->next;
                        }
                        cat = cat->next;
@@ -3860,7 +3823,7 @@ int localized_config_text_file_save(const char *configfile, const struct ast_con
 
        /* Now, for files with trailing #include/#exec statements,
           we have to make sure every entry is output */
-       
+
        for (incl=cfg->includes; incl; incl = incl->next) {
                if (!incl->output) {
                        /* open the respective file */
@@ -3871,7 +3834,7 @@ int localized_config_text_file_save(const char *configfile, const struct ast_con
                                ast_verbose(VERBOSE_PREFIX_2 "Unable to write %s (%s)", fn, strerror(errno));
                                return -1;
                        }
-            
+
                        /* output the respective include */
                        if (incl->exec)
                                fprintf(f,"#exec \"%s\"\n", incl->exec_file);
@@ -3881,7 +3844,7 @@ int localized_config_text_file_save(const char *configfile, const struct ast_con
                        incl->output = 1;
                }
        }
-       
+
        return 0;
 }
 
@@ -4207,7 +4170,7 @@ static int ext_cmp1(const char **p)
                break;
        }
        /* locate end of set */
-       end = strchr(*p, ']');  
+       end = strchr(*p, ']');
 
        if (end == NULL) {
                ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n");
@@ -4384,6 +4347,19 @@ static struct ast_include *ast_walk_context_includes(struct ast_context *con,
                return inc->next;
 }
 
+int ast_context_includes_count(struct ast_context *con);
+int ast_context_includes_count(struct ast_context *con)
+{
+       int c = 0;
+       struct ast_include *inc = NULL;
+
+       while ((inc = ast_walk_context_includes(con, inc))) {
+               c++;
+       }
+
+       return c;
+}
+
 struct ast_include *localized_walk_context_includes(struct ast_context *con,
                                                                                                        struct ast_include *inc);
 struct ast_include *localized_walk_context_includes(struct ast_context *con,
@@ -4392,6 +4368,31 @@ struct ast_include *localized_walk_context_includes(struct ast_context *con,
        return ast_walk_context_includes(con, inc);
 }
 
+static struct ast_ignorepat *ast_walk_context_ignorepats(struct ast_context *con,
+       struct ast_ignorepat *ip);
+
+static struct ast_ignorepat *ast_walk_context_ignorepats(struct ast_context *con,
+       struct ast_ignorepat *ip)
+{
+       if (!ip)
+               return con ? con->ignorepats : NULL;
+       else
+               return ip->next;
+}
+
+int ast_context_ignorepats_count(struct ast_context *con);
+int ast_context_ignorepats_count(struct ast_context *con)
+{
+       int c = 0;
+       struct ast_ignorepat *ip = NULL;
+
+       while ((ip = ast_walk_context_ignorepats(con, ip))) {
+               c++;
+       }
+
+       return c;
+}
+
 
 static struct ast_sw *ast_walk_context_switches(struct ast_context *con,
                                                                                                         struct ast_sw *sw);
@@ -4413,6 +4414,19 @@ struct ast_sw *localized_walk_context_switches(struct ast_context *con,
        return ast_walk_context_switches(con, sw);
 }
 
+int ast_context_switches_count(struct ast_context *con);
+int ast_context_switches_count(struct ast_context *con)
+{
+       int c = 0;
+       struct ast_sw *sw = NULL;
+
+       while ((sw = ast_walk_context_switches(con, sw))) {
+               c++;
+       }
+
+       return c;
+}
+
 
 static struct ast_context *ast_context_find(const char *name);
 
@@ -4566,24 +4580,24 @@ static inline int include_valid(struct ast_include *i)
 
 
 static struct ast_exten *pbx_find_extension(struct ast_channel *chan,
-                                                                                       struct ast_context *bypass, 
+                                                                                       struct ast_context *bypass,
                                                                                        struct pbx_find_info *q,
-                                                                                       const char *context, 
-                                                                                       const char *exten, 
+                                                                                       const char *context,
+                                                                                       const char *exten,
                                                                                        int priority,
-                                                                                       const char *label, 
-                                                                                       const char *callerid, 
+                                                                                       const char *label,
+                                                                                       const char *callerid,
                                                                                        enum ext_match_t action);
 
 
 static struct ast_exten *pbx_find_extension(struct ast_channel *chan,
-                                                                                       struct ast_context *bypass, 
+                                                                                       struct ast_context *bypass,
                                                                                        struct pbx_find_info *q,
-                                                                                       const char *context, 
-                                                                                       const char *exten, 
+                                                                                       const char *context,
+                                                                                       const char *exten,
                                                                                        int priority,
-                                                                                       const char *label, 
-                                                                                       const char *callerid, 
+                                                                                       const char *label,
+                                                                                       const char *callerid,
                                                                                        enum ext_match_t action)
 {
        int x;
@@ -4591,6 +4605,10 @@ static struct ast_exten *pbx_find_extension(struct ast_channel *chan,
        struct ast_exten *e, *eroot;
        struct ast_include *i;
 
+       if (!context) {
+               return NULL;
+       }
+
        /* Initialize status if appropriate */
        if (q->stacklen == 0) {
                q->status = STATUS_NO_CONTEXT;
@@ -4667,7 +4685,7 @@ static struct ast_exten *pbx_find_extension(struct ast_channel *chan,
                        continue;
                }
                /* No need to Substitute variables now; we shouldn't be here if there's any  */
-               
+
                /* equivalent of extension_match_core() at the switch level */
                if (action == E_CANMATCH)
                        aswf = asw->canmatch;
@@ -4701,20 +4719,20 @@ static struct ast_exten *pbx_find_extension(struct ast_channel *chan,
 
 struct ast_exten *localized_find_extension(struct ast_context *bypass,
                                                                                  struct pbx_find_info *q,
-                                                                                 const char *context, 
-                                                                                 const char *exten, 
+                                                                                 const char *context,
+                                                                                 const char *exten,
                                                                                  int priority,
-                                                                                 const char *label, 
-                                                                                 const char *callerid, 
+                                                                                 const char *label,
+                                                                                 const char *callerid,
                                                                                  enum ext_match_t action);
 
 struct ast_exten *localized_find_extension(struct ast_context *bypass,
                                                                                  struct pbx_find_info *q,
-                                                                                 const char *context, 
-                                                                                 const char *exten, 
+                                                                                 const char *context,
+                                                                                 const char *exten,
                                                                                  int priority,
-                                                                                 const char *label, 
-                                                                                 const char *callerid, 
+                                                                                 const char *label,
+                                                                                 const char *callerid,
                                                                                   enum ext_match_t action)
 {
        return pbx_find_extension(NULL, bypass, q, context, exten, priority, label, callerid, action);
@@ -5328,7 +5346,7 @@ static void pbx_retrieve_variable(struct ast_channel *c, const char *var, char *
        int offset, length;
        int i, need_substring;
        struct varshead *places[2] = { headp, &globals };       /* list of places where we may look */
-       
+
        /*
         * Make a copy of var because parse_variable_name() modifies the string.
         * Then if called directly, we might need to run substring() on the result;
@@ -5336,7 +5354,7 @@ static void pbx_retrieve_variable(struct ast_channel *c, const char *var, char *
         */
        tmpvar = ast_strdupa(var);      /* parse_variable_name modifies the string */
        need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */);
-       
+
        /*
         * Look first into predefined variables, then into variable lists.
         * Variable 's' points to the result, according to the following rules:
@@ -5357,7 +5375,7 @@ static void pbx_retrieve_variable(struct ast_channel *c, const char *var, char *
                if (!strcmp(var, "EPOCH")) {
                        snprintf(workspace, workspacelen, "%u",(int)time(NULL));
                }
-               
+
                s = workspace;
        }
        /* if not found, look into chanvars or global vars */
@@ -5600,11 +5618,11 @@ static int pbx_load_config(const char *config_file)
                autofallthrough_config = ast_true(aft);
        clearglobalvars_config = ast_true(ast_variable_retrieve(cfg, "general", "clearglobalvars"));
 
-       if ((cxt = ast_variable_retrieve(cfg, "general", "userscontext"))) 
+       if ((cxt = ast_variable_retrieve(cfg, "general", "userscontext")))
                ast_copy_string(userscontext, cxt, sizeof(userscontext));
        else
                ast_copy_string(userscontext, "default", sizeof(userscontext));
-                                                                   
+
        for (v = ast_variable_browse(cfg, "globals"); v; v = v->next) {
                memset(realvalue, 0, sizeof(realvalue));
                pbx_substitute_variables_helper(NULL, v->value, realvalue, sizeof(realvalue) - 1);
@@ -5905,7 +5923,7 @@ int localized_pbx_load_module(void)
                printf("Context: %s\n", con->name);
        }
        printf("=========\n");
-       
+
        return 0;
 }
 
@@ -5918,4 +5936,3 @@ struct timeval ast_tvnow(void)
        gettimeofday(&t, NULL);
        return t;
 }
-