📄 astconfig.c
字号:
/* * 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_4int 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 250static 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 10struct 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_4const char *ast_variable_retrieve(const struct ast_config *config, const char *category, const char *variable)#elsechar *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_4int 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;}#endifint 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 + -