cfg.c

来自「mms client」· C语言 代码 · 共 651 行 · 第 1/2 页

C
651
字号
/* * cfg.c - configuration file handling * * Lars Wirzenius */#include "gwlib/gwlib.h"/* for include dir */#include <sys/types.h>#include <sys/stat.h>#include <unistd.h>#include <dirent.h>struct CfgGroup {    Octstr *name;    Dict *vars;    Octstr *configfile;     long line; };static CfgGroup *create_group(void){    CfgGroup *grp;        grp = gw_malloc(sizeof(*grp));    grp->name = NULL;    grp->vars = dict_create(64, octstr_destroy_item);    grp->configfile = NULL;     grp->line = 0;     return grp;}static void destroy_group(void *arg){    CfgGroup *grp;        if (arg != NULL) {	grp = arg;	octstr_destroy(grp->name);	octstr_destroy(grp->configfile); 	dict_destroy(grp->vars);	gw_free(grp);    }}struct CfgLoc {     Octstr *filename;     long line_no;     Octstr *line; }; static CfgLoc *cfgloc_create(Octstr *filename) {     CfgLoc *cfgloc;          cfgloc = gw_malloc(sizeof(*cfgloc));     cfgloc->filename = octstr_duplicate(filename);     cfgloc->line_no = 0;     cfgloc->line = NULL;     return cfgloc; }   static void cfgloc_destroy(CfgLoc *cfgloc) {     if (cfgloc != NULL) { 	octstr_destroy(cfgloc->filename); 	octstr_destroy(cfgloc->line); 	gw_free(cfgloc);     } }  static void destroy_group_list(void *arg){    list_destroy(arg, destroy_group);}static void set_group_name(CfgGroup *grp, Octstr *name){    octstr_destroy(grp->name);    grp->name = octstr_duplicate(name);}struct Cfg {    Octstr *filename;    Dict *single_groups;    Dict *multi_groups;};static int is_allowed_in_group(Octstr *group, Octstr *variable){    Octstr *groupstr;        groupstr = octstr_imm("group");    #define OCTSTR(name) \    	if (octstr_compare(octstr_imm(#name), variable) == 0) \	    return 1;    #define SINGLE_GROUP(name, fields) \    	if (octstr_compare(octstr_imm(#name), group) == 0) { \	    if (octstr_compare(groupstr, variable) == 0) \		return 1; \	    fields \	    return 0; \	}    #define MULTI_GROUP(name, fields) \    	if (octstr_compare(octstr_imm(#name), group) == 0) { \	    if (octstr_compare(groupstr, variable) == 0) \		return 1; \	    fields \	    return 0; \	}    #include "cfg.def"    return 0;}static int is_single_group(Octstr *query){    #define OCTSTR(name)    #define SINGLE_GROUP(name, fields) \    	if (octstr_compare(octstr_imm(#name), query) == 0) \	    return 1;    #define MULTI_GROUP(name, fields) \    	if (octstr_compare(octstr_imm(#name), query) == 0) \	    return 0;    #include "cfg.def"    return 0;}static int add_group(Cfg *cfg, CfgGroup *grp){    Octstr *groupname;    Octstr *name;    List *names;    List *list;        groupname = cfg_get(grp, octstr_imm("group"));    if (groupname == NULL) {	error(0, "Group does not contain variable 'group'.");    	return -1;    }    set_group_name(grp, groupname);    names = dict_keys(grp->vars);    while ((name = list_extract_first(names)) != NULL) {	if (!is_allowed_in_group(groupname, name)) {	    error(0, "Group '%s' may not contain field '%s'.",		  octstr_get_cstr(groupname), octstr_get_cstr(name));	    octstr_destroy(name);	    octstr_destroy(groupname);	    list_destroy(names, octstr_destroy_item);	    return -1;	}	octstr_destroy(name);    }    list_destroy(names, NULL);    if (is_single_group(groupname))    	dict_put(cfg->single_groups, groupname, grp);    else {	list = dict_get(cfg->multi_groups, groupname);	if (list == NULL) {	    list = list_create();	    dict_put(cfg->multi_groups, groupname, list);	}    	list_append(list, grp);    }    octstr_destroy(groupname);    return 0;}Cfg *cfg_create(Octstr *filename){    Cfg *cfg;        cfg = gw_malloc(sizeof(*cfg));    cfg->filename = octstr_duplicate(filename);    cfg->single_groups = dict_create(64, destroy_group);    cfg->multi_groups = dict_create(64, destroy_group_list);    return cfg;}void cfg_destroy(Cfg *cfg){    if (cfg != NULL) {	octstr_destroy(cfg->filename);	dict_destroy(cfg->single_groups);	dict_destroy(cfg->multi_groups);	gw_free(cfg);    }}static void parse_value(Octstr *value){    Octstr *temp;    long len;    int c;        octstr_strip_blanks(value);    len = octstr_len(value);    if (octstr_get_char(value, 0) != '"' ||         octstr_get_char(value, len - 1) != '"')	return;    octstr_delete(value, len - 1, 1);    octstr_delete(value, 0, 1);    temp = octstr_duplicate(value);    octstr_truncate(value, 0);        while (octstr_len(temp) > 0) {	c = octstr_get_char(temp, 0);	octstr_delete(temp, 0, 1);	    	if (c != '\\' || octstr_len(temp) == 0)	    octstr_append_char(value, c);	else {	    c = octstr_get_char(temp, 0);	    octstr_delete(temp, 0, 1);	    switch (c) {    	    case '\\':    	    case '"':	    	octstr_append_char(value, c);	    	break;		    	    default:	    	octstr_append_char(value, '\\');	    	octstr_append_char(value, c);		break;	    }	}    }        octstr_destroy(temp);}static List *expand_file(Octstr *file, int forward) {    Octstr *os;    Octstr *line;    List *lines;     List *expand;     long lineno;     CfgLoc *loc;      os = octstr_read_file(octstr_get_cstr(file));     if (os == NULL)     	return NULL;      lines = octstr_split(os, octstr_imm("\n"));     lineno = 0;     expand = list_create();                   while ((line = list_extract_first(lines)) != NULL) {         ++lineno;         loc = cfgloc_create(file);         loc->line_no = lineno;         loc->line = line;         if (forward)             list_append(expand, loc);         else             list_insert(expand, 0, loc);     }         /*      * add newline at each end of included files to avoid      * concatenating different groups by mistake     */    if (lineno > 0) {        loc = cfgloc_create(file);         loc->line_no = lineno;        loc->line = octstr_create("\n");        if (forward)             list_append(expand, loc);         else             list_insert(expand, 0, loc);     }             list_destroy(lines, octstr_destroy_item);     octstr_destroy(os);      return expand; }   int cfg_read(Cfg *cfg) {     CfgLoc *loc;     CfgLoc *loc_inc;     List *lines;    List *expand;     List *stack;     Octstr *name;    Octstr *value;    Octstr *filename;     CfgGroup *grp;    long equals;    long lineno;    long error_lineno;        loc = loc_inc = NULL;    /*      * expand initial main config file and add it to the recursion      * stack to protect against cycling      */     if ((lines = expand_file(cfg->filename, 1)) == NULL) { 

⌨️ 快捷键说明

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