⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 astconfig.c

📁 asterisk1.4.6版本下 7#信令驱动 源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 * Asterisk -- An open source telephony toolkit.
 *
 * Copyright (C) 1999 - 2005, Digium, Inc.
 *
 * 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
 * See doc/realtime.txt and doc/extconfig.txt
 */

#include <asterisk.h>

ASTERISK_FILE_VERSION(__FILE__, "$Revision: 69470 $")

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <sys/stat.h>
#define AST_INCLUDE_GLOB 1
#ifdef AST_INCLUDE_GLOB
#if defined(__Darwin__) || defined(__CYGWIN__)
#define GLOB_ABORTED GLOB_ABEND
#endif
# include <glob.h>
#endif

#include "asterisk/config.h"
#include "asterisk/cli.h"
#include "asterisk/lock.h"
#include "asterisk/options.h"
#include "asterisk/logger.h"
#include "asterisk/utils.h"
#include "asterisk/channel.h"
#include "asterisk/app.h"

#include "astversion.h"

#define MAX_NESTED_COMMENTS 128
#define COMMENT_START ";--"
#define COMMENT_END "--;"
#define COMMENT_META ';'
#define COMMENT_TAG '-'

static char *extconfig_conf = "extconfig.conf";

#ifndef USE_ASTERISK_1_4
int ast_opt_exec_includes = 0;
#undef ast_malloc
#undef ast_realloc
#undef ast_calloc
#define ast_malloc malloc
#define ast_realloc realloc
#define ast_calloc calloc
#endif

/*! \brief Structure to keep comments for rewriting configuration files */
struct ast_comment {
	struct ast_comment *next;
	char cmt[0];
};

#define CB_INCR 250

static void CB_INIT(char **comment_buffer, int *comment_buffer_size, char **lline_buffer, int *lline_buffer_size)
{
	if (!(*comment_buffer)) {
		*comment_buffer = ast_malloc(CB_INCR);
		if (!(*comment_buffer))
			return;
		(*comment_buffer)[0] = 0;
		*comment_buffer_size = CB_INCR;
		*lline_buffer = ast_malloc(CB_INCR);
		if (!(*lline_buffer))
			return;
		(*lline_buffer)[0] = 0;
		*lline_buffer_size = CB_INCR;
	} else {
		(*comment_buffer)[0] = 0;
		(*lline_buffer)[0] = 0;
	}
}

static void  CB_ADD(char **comment_buffer, int *comment_buffer_size, char *str)
{
	int rem = *comment_buffer_size - strlen(*comment_buffer) - 1;
	int siz = strlen(str);
	if (rem < siz+1) {
		*comment_buffer = ast_realloc(*comment_buffer, *comment_buffer_size + CB_INCR + siz + 1);
		if (!(*comment_buffer))
			return;
		*comment_buffer_size += CB_INCR+siz+1;
	}
	strcat(*comment_buffer,str);
}

static void  CB_ADD_LEN(char **comment_buffer, int *comment_buffer_size, char *str, int len)
{
	int cbl = strlen(*comment_buffer) + 1;
	int rem = *comment_buffer_size - cbl;
	if (rem < len+1) {
		*comment_buffer = ast_realloc(*comment_buffer, *comment_buffer_size + CB_INCR + len + 1);
		if (!(*comment_buffer))
			return;
		*comment_buffer_size += CB_INCR+len+1;
	}
	strncat(*comment_buffer,str,len);
	(*comment_buffer)[cbl+len-1] = 0;
}

static void  LLB_ADD(char **lline_buffer, int *lline_buffer_size, char *str)
{
	int rem = *lline_buffer_size - strlen(*lline_buffer) - 1;
	int siz = strlen(str);
	if (rem < siz+1) {
		*lline_buffer = ast_realloc(*lline_buffer, *lline_buffer_size + CB_INCR + siz + 1);
		if (!(*lline_buffer)) 
			return;
		*lline_buffer_size += CB_INCR + siz + 1;
	}
	strcat(*lline_buffer,str);
}

static void CB_RESET(char **comment_buffer, char **lline_buffer)  
{ 
	(*comment_buffer)[0] = 0; 
	(*lline_buffer)[0] = 0;
}


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;
}


static struct ast_config_map {
	struct ast_config_map *next;
	char *name;
	char *driver;
	char *database;
	char *table;
	char stuff[0];
} *config_maps = NULL;

AST_MUTEX_DEFINE_STATIC(config_lock);
static struct ast_config_engine *config_engine_list;

#define MAX_INCLUDE_LEVEL 10

struct ast_category {
	char name[80];
	int ignored;			/*!< do not let user of the config see this category */
	int include_level;	
	struct ast_comment *precomments;
	struct ast_comment *sameline;
	struct ast_variable *root;
	struct ast_variable *last;
	struct ast_category *next;
};

struct ast_config {
	struct ast_category *root;
	struct ast_category *last;
	struct ast_category *current;
	struct ast_category *last_browse;		/*!< used to cache the last category supplied via category_browse */
	int include_level;
	int max_include_level;
};

struct ast_variable *ast_variable_new(const char *name, const char *value) 
{
	struct ast_variable *variable;
	int name_len = strlen(name) + 1;	

	if ((variable = ast_calloc(1, name_len + strlen(value) + 1 + sizeof(*variable)))) {
		variable->name = variable->stuff;
		variable->value = variable->stuff + name_len;		
		strcpy(variable->name,name);
		strcpy(variable->value,value);
	}

	return variable;
}

void ast_variable_append(struct ast_category *category, struct ast_variable *variable)
{
	if (!variable)
		return;
	if (category->last)
		category->last->next = variable;
	else
		category->root = variable;
	category->last = variable;
	while (category->last->next)
		category->last = category->last->next;
}

void ast_variables_destroy(struct ast_variable *v)
{
	struct ast_variable *vn;

	while(v) {
		vn = v;
		v = v->next;
		free(vn);
	}
}

struct ast_variable *ast_variable_browse(const struct ast_config *config, const char *category)
{
	struct ast_category *cat = NULL;

	if (category && config->last_browse && (config->last_browse->name == category))
		cat = config->last_browse;
	else
		cat = ast_category_get(config, category);

	return (cat) ? cat->root : NULL;
}

const char *ast_config_option(struct ast_config *cfg, const char *cat, const char *var)
{
	const char *tmp;
	tmp = ast_variable_retrieve(cfg, cat, var);
	if (!tmp)
		tmp = ast_variable_retrieve(cfg, "general", var);
	return tmp;
}


#ifdef USE_ASTERISK_1_4
const char *ast_variable_retrieve(const struct ast_config *config, const char *category, const char *variable)
#else
char *ast_variable_retrieve(const struct ast_config *config, const char *category, const char *variable)
#endif
{
	struct ast_variable *v;

	if (category) {
		for (v = ast_variable_browse(config, category); v; v = v->next) {
			if (!strcasecmp(variable, v->name))
				return v->value;
		}
	} else {
		struct ast_category *cat;

		for (cat = config->root; cat; cat = cat->next)
			for (v = cat->root; v; v = v->next)
				if (!strcasecmp(variable, v->name))
					return v->value;
	}

	return NULL;
}

static struct ast_variable *variable_clone(const struct ast_variable *old)
{
	struct ast_variable *new = ast_variable_new(old->name, old->value);

	if (new) {
		new->lineno = old->lineno;
		new->object = old->object;
		new->blanklines = old->blanklines;
		/* TODO: clone comments? */
	}

	return new;
}
 
static void move_variables(struct ast_category *old, struct ast_category *new)
{
	struct ast_variable *var = old->root;
	old->root = NULL;
#if 1
	/* we can just move the entire list in a single op */
	ast_variable_append(new, var);
#else
	while (var) {
		struct ast_variable *next = var->next;
		var->next = NULL;
		ast_variable_append(new, var);
		var = next;
	}
#endif
}

struct ast_category *ast_category_new(const char *name) 
{
	struct ast_category *category;

	if ((category = ast_calloc(1, sizeof(*category))))
		ast_copy_string(category->name, name, sizeof(category->name));
	return category;
}

static struct ast_category *category_get(const struct ast_config *config, const char *category_name, int ignored)
{
	struct ast_category *cat;

	/* try exact match first, then case-insensitive match */
	for (cat = config->root; cat; cat = cat->next) {
		if (cat->name == category_name && (ignored || !cat->ignored))
			return cat;
	}

	for (cat = config->root; cat; cat = cat->next) {
		if (!strcasecmp(cat->name, category_name) && (ignored || !cat->ignored))
			return cat;
	}

	return NULL;
}

struct ast_category *ast_category_get(const struct ast_config *config, const char *category_name)
{
	return category_get(config, category_name, 0);
}

int ast_category_exist(const struct ast_config *config, const char *category_name)
{
	return !!ast_category_get(config, category_name);
}

void ast_category_append(struct ast_config *config, struct ast_category *category)
{
	if (config->last)
		config->last->next = category;
	else
		config->root = category;
	category->include_level = config->include_level;
	config->last = category;
	config->current = category;
}

void ast_category_destroy(struct ast_category *cat)
{
	ast_variables_destroy(cat->root);
	free(cat);
}

static struct ast_category *next_available_category(struct ast_category *cat)
{
	for (; cat && cat->ignored; cat = cat->next);

	return cat;
}

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))
		cat = config->last_browse->next;
	else if (!prev && config->root)
		cat = config->root;
	else if (prev) {
		for (cat = config->root; cat; cat = cat->next) {
			if (cat->name == prev) {
				cat = cat->next;
				break;
			}
		}
		if (!cat) {
			for (cat = config->root; cat; cat = cat->next) {
				if (!strcasecmp(cat->name, prev)) {
					cat = cat->next;
					break;
				}
			}
		}
	}
	
	if (cat)
		cat = next_available_category(cat);

	config->last_browse = cat;
	return (cat) ? cat->name : NULL;
}

struct ast_variable *ast_category_detach_variables(struct ast_category *cat)
{
	struct ast_variable *v;

	v = cat->root;
	cat->root = NULL;
	cat->last = NULL;

	return v;
}

void ast_category_rename(struct ast_category *cat, const char *name)
{
	ast_copy_string(cat->name, name, sizeof(cat->name));
}

static void inherit_category(struct ast_category *new, const struct ast_category *base)
{
	struct ast_variable *var;

	for (var = base->root; var; var = var->next)
		ast_variable_append(new, variable_clone(var));
}

struct ast_config *ast_config_new(void) 
{
	struct ast_config *config;

	if ((config = ast_calloc(1, sizeof(*config))))
		config->max_include_level = MAX_INCLUDE_LEVEL;
	return config;
}

#ifdef USE_ASTERISK_1_4
int ast_variable_delete(struct ast_category *category, char *variable, char *match)
{
	struct ast_variable *cur, *prev=NULL, *curn;
	int res = -1;
	cur = category->root;
	while (cur) {
		if (cur->name == variable) {
			if (prev) {
				prev->next = cur->next;
				if (cur == category->last)
					category->last = prev;
			} else {
				category->root = cur->next;
				if (cur == category->last)
					category->last = NULL;
			}
			cur->next = NULL;
			ast_variables_destroy(cur);
			return 0;
		}
		prev = cur;
		cur = cur->next;
	}

	prev = NULL;
	cur = category->root;
	while (cur) {
		curn = cur->next;
		if (!strcasecmp(cur->name, variable) && (ast_strlen_zero(match) || !strcasecmp(cur->value, match))) {
			if (prev) {
				prev->next = cur->next;
				if (cur == category->last)
					category->last = prev;
			} else {
				category->root = cur->next;
				if (cur == category->last)
					category->last = NULL;
			}
			cur->next = NULL;
			ast_variables_destroy(cur);
			res = 0;
		} else
			prev = cur;

		cur = curn;
	}
	return res;
}
#endif

int ast_variable_update(struct ast_category *category, const char *variable, 
	const char *value, const char *match, unsigned int object)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -