Newer
Older
* Asterisk -- An open source telephony toolkit.
* Copyright (C) 1999 - 2010, Digium, Inc.
Mark Spencer
committed
* Mark Spencer <markster@digium.com>
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*! \file
*
* \brief Configuration File Parser
*
* \author Mark Spencer <markster@digium.com>
*
* Includes the Asterisk Realtime API - ARA
/*** MODULEINFO
<support_level>core</support_level>
***/
Kevin P. Fleming
committed
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/paths.h" /* use ast_config_AST_CONFIG_DIR */
#include "asterisk/network.h" /* we do some sockaddr manipulation here */
#include <string.h>
#include <libgen.h>
Kevin P. Fleming
committed
#include <sys/stat.h>
#include <math.h> /* HUGE_VAL */
#include <regex.h>
Kevin P. Fleming
committed
#include "asterisk/config.h"
#include "asterisk/cli.h"
#include "asterisk/lock.h"
#include "asterisk/utils.h"
#include "asterisk/channel.h"
#include "asterisk/app.h"
Steve Murphy
committed
#include "asterisk/astobj2.h"
#include "asterisk/strings.h" /* for the ast_str_*() API */
#define MAX_NESTED_COMMENTS 128
#define COMMENT_START ";--"
#define COMMENT_END "--;"
#define COMMENT_META ';'
#define COMMENT_TAG '-'
/*!
* Define the minimum filename space to reserve for each
* ast_variable in case the filename is renamed later by
* ast_include_rename().
*/
#define MIN_VARIABLE_FNAME_SPACE 40
static char *extconfig_conf = "extconfig.conf";
static struct ao2_container *cfg_hooks;
static void config_hook_exec(const char *filename, const char *module, const struct ast_config *cfg);
Matthew Jordan
committed
static inline struct ast_variable *variable_list_switch(struct ast_variable *l1, struct ast_variable *l2);
static int does_category_match(struct ast_category *cat, const char *category_name,
const char *match, char sep);
/*! \brief Structure to keep comments for rewriting configuration files */
struct ast_comment {
struct ast_comment *next;
/*! Comment body allocated after struct. */
/*! \brief Hold the mtime for config files, so if we don't need to reread our config, don't. */
struct cache_file_include {
AST_LIST_ENTRY(cache_file_include) list;
Richard Mudgett
committed
/*! Filename or wildcard pattern as specified by the including file. */
char include[0];
};
struct cache_file_mtime {
AST_LIST_ENTRY(cache_file_mtime) list;
AST_LIST_HEAD_NOLOCK(includes, cache_file_include) includes;
unsigned int has_exec:1;
Richard Mudgett
committed
/*! stat() file size */
unsigned long stat_size;
/*! stat() file modtime nanoseconds */
unsigned long stat_mtime_nsec;
/*! stat() file modtime seconds since epoc */
time_t stat_mtime;
/*! String stuffed in filename[] after the filename string. */
const char *who_asked;
/*! Filename and who_asked stuffed after it. */
char filename[0];
};
/*! Cached file mtime list. */
static AST_LIST_HEAD_STATIC(cfmtime_head, cache_file_mtime);
static int init_appendbuf(void *data)
{
struct ast_str **str = data;
*str = ast_str_create(16);
return *str ? 0 : -1;
}
AST_THREADSTORAGE_CUSTOM(appendbuf, init_appendbuf, ast_free_ptr);
/* comment buffers are better implemented using the ast_str_*() API */
#define CB_SIZE 250 /* initial size of comment buffers */
static void CB_ADD(struct ast_str **cb, const char *str)
ast_str_append(cb, 0, "%s", str);
static void CB_ADD_LEN(struct ast_str **cb, const char *str, int len)
char *s = ast_alloca(len + 1);
memcpy(s, str, len);
s[len] = '\0';
ast_str_append(cb, 0, "%s", s);
static void CB_RESET(struct ast_str *cb, struct ast_str *llb)
{
if (cb) {
ast_str_reset(cb);
}
if (llb) {
ast_str_reset(llb);
}
static struct ast_comment *ALLOC_COMMENT(struct ast_str *buffer)
struct ast_comment *x = NULL;
if (!buffer || !ast_str_strlen(buffer)) {
return NULL;
}
if ((x = ast_calloc(1, sizeof(*x) + ast_str_strlen(buffer) + 1))) {
strcpy(x->cmt, ast_str_buffer(buffer)); /* SAFE */
}
Steve Murphy
committed
/* I need to keep track of each config file, and all its inclusions,
so that we can track blank lines in each */
Steve Murphy
committed
char *fname;
int lineno;
};
static int hash_string(const void *obj, const int flags)
{
char *str = ((struct inclfile *) obj)->fname;
Steve Murphy
committed
int total;
for (total = 0; *str; str++) {
Steve Murphy
committed
unsigned int tmp = total;
total <<= 1; /* multiply by 2 */
total += tmp; /* multiply by 3 */
total <<= 2; /* multiply by 12 */
total += tmp; /* multiply by 13 */
total += ((unsigned int) (*str));
Steve Murphy
committed
}
if (total < 0) {
Steve Murphy
committed
total = -total;
}
Steve Murphy
committed
return total;
}
static int hashtab_compare_strings(void *a, void *b, int flags)
Steve Murphy
committed
{
const struct inclfile *ae = a, *be = b;
return !strcmp(ae->fname, be->fname) ? CMP_MATCH | CMP_STOP : 0;
Steve Murphy
committed
}
static struct ast_config_map {
struct ast_config_map *next;
/*! Stored in stuff[] at struct end. */
Loading
Loading full blame...