/****************************************************************************** * * * Function: parse_cfg_file * * * * Purpose: parse configuration file * * * * Parameters: cfg_file - full name of config file * * cfg - pointer to configuration parameter structure * * * * Return value: SUCCEED - parsed successfully * * FAIL - error processing config file * * * * Author: Alexei Vladishev, Eugene Grigorjev * * * * Comments: * * * ******************************************************************************/ static int __parse_cfg_file(const char *cfg_file, struct cfg_line *cfg, int level, int optional) { #define ZBX_MAX_INCLUDE_LEVEL 10 #define ZBX_CFG_LTRIM_CHARS "\t " #define ZBX_CFG_RTRIM_CHARS ZBX_CFG_LTRIM_CHARS "\r\n" FILE *file; int i, lineno, result = SUCCEED; char line[MAX_STRING_LEN], *parameter, *value; zbx_uint64_t var; assert(cfg); if (++level > ZBX_MAX_INCLUDE_LEVEL) { zbx_error("Recursion detected! Skipped processing of '%s'.", cfg_file); return FAIL; } if (NULL != cfg_file) { if (NULL == (file = fopen(cfg_file, "r"))) goto cannot_open; for (lineno = 1; NULL != fgets(line, sizeof(line), file); lineno++) { zbx_ltrim(line, ZBX_CFG_LTRIM_CHARS); if ('#' == *line) continue; if (strlen(line) < 3) continue; parameter = line; value = strstr(line, "="); if (NULL == value) { zbx_error("error in line [%d] \"%s\"", lineno, line); result = FAIL; break; } *value++ = '\0'; zbx_rtrim(parameter, ZBX_CFG_RTRIM_CHARS); zbx_ltrim(value, ZBX_CFG_LTRIM_CHARS); zbx_rtrim(value, ZBX_CFG_RTRIM_CHARS); zabbix_log(LOG_LEVEL_DEBUG, "cfg: para: [%s] val [%s]", parameter, value); if (0 == strcmp(parameter, "Include")) { if (FAIL == (result = parse_cfg_object(value, cfg, level))) break; } for (i = 0; '\0' != value[i]; i++) { if ('\n' == value[i]) { value[i] = '\0'; break; } } for (i = 0; NULL != cfg[i].parameter; i++) { if (0 != strcmp(cfg[i].parameter, parameter)) continue; zabbix_log(LOG_LEVEL_DEBUG, "accepted configuration parameter: '%s' = '%s'",parameter, value); if (NULL != cfg[i].function) { if (SUCCEED != cfg[i].function(value)) goto incorrect_config; } else if (TYPE_INT == cfg[i].type) { if (FAIL == str2uint64(value, &var)) goto incorrect_config; if ((cfg[i].min && var < cfg[i].min) || (cfg[i].max && var > cfg[i].max)) goto incorrect_config; *((int *)cfg[i].variable) = var; } else if (TYPE_STRING == cfg[i].type) { *((char **)cfg[i].variable) = strdup(value); } else assert(0); } } fclose(file); } if (1 != level) /* skip mandatory parameters check for included files */ return result; for (i = 0; NULL != cfg[i].parameter; i++) /* check for mandatory parameters */ { if (PARM_MAND != cfg[i].mandatory) continue; if (TYPE_INT == cfg[i].type) { if (0 == *((int *)cfg[i].variable)) goto missing_mandatory; } else if (TYPE_STRING == cfg[i].type) { if (NULL == (*(char **)cfg[i].variable)) goto missing_mandatory; } else assert(0); } return result; cannot_open: if (optional) return result; zbx_error("cannot open config file [%s] [%s]", cfg_file, strerror(errno)); exit(1); missing_mandatory: zbx_error("missing mandatory parameter [%s]", cfg[i].parameter); exit(1); incorrect_config: zbx_error("wrong value for [%s] in line %d", cfg[i].parameter, lineno); exit(1); }
/****************************************************************************** * * * Function: parse_cfg_file * * * * Purpose: parse configuration file * * * * Parameters: cfg_file - full name of config file * * cfg - pointer to configuration parameter structure * * level - a level of included file * * optional - do not treat missing configuration file as error * * strict - treat unknown parameters as error * * * * Return value: SUCCEED - parsed successfully * * FAIL - error processing config file * * * * Author: Alexei Vladishev, Eugene Grigorjev * * * * Comments: * * * ******************************************************************************/ static int __parse_cfg_file(const char *cfg_file, struct cfg_line *cfg, int level, int optional, int strict) { #define ZBX_MAX_INCLUDE_LEVEL 10 #define ZBX_CFG_LTRIM_CHARS "\t " #define ZBX_CFG_RTRIM_CHARS ZBX_CFG_LTRIM_CHARS "\r\n" FILE *file; int i, lineno, result = SUCCEED, param_valid; char line[MAX_STRING_LEN], *parameter, *value; zbx_uint64_t var; assert(cfg); if (++level > ZBX_MAX_INCLUDE_LEVEL) { zbx_error("Recursion detected! Skipped processing of '%s'.", cfg_file); return FAIL; } if (NULL != cfg_file) { if (NULL == (file = fopen(cfg_file, "r"))) goto cannot_open; for (lineno = 1; NULL != fgets(line, sizeof(line), file); lineno++) { zbx_ltrim(line, ZBX_CFG_LTRIM_CHARS); zbx_rtrim(line, ZBX_CFG_RTRIM_CHARS); if ('#' == *line || '\0' == *line) continue; parameter = line; if (NULL == (value = strchr(line, '='))) goto garbage; *value++ = '\0'; zbx_rtrim(parameter, ZBX_CFG_RTRIM_CHARS); zbx_ltrim(value, ZBX_CFG_LTRIM_CHARS); zabbix_log(LOG_LEVEL_DEBUG, "cfg: para: [%s] val [%s]", parameter, value); if (0 == strcmp(parameter, "Include")) { if (FAIL == (result = parse_cfg_object(value, cfg, level, strict))) break; continue; } for (i = 0; '\0' != value[i]; i++) { if ('\n' == value[i]) { value[i] = '\0'; break; } } param_valid = 0; for (i = 0; NULL != cfg[i].parameter; i++) { if (0 != strcmp(cfg[i].parameter, parameter)) continue; param_valid = 1; zabbix_log(LOG_LEVEL_DEBUG, "accepted configuration parameter: '%s' = '%s'",parameter, value); if (TYPE_INT == cfg[i].type) { if (FAIL == str2uint64(value, &var)) goto incorrect_config; if ((cfg[i].min && var < cfg[i].min) || (cfg[i].max && var > cfg[i].max)) goto incorrect_config; *((int *)cfg[i].variable) = (int)var; } else if (TYPE_STRING == cfg[i].type) { /* free previous value memory */ char *p = *((char **)cfg[i].variable); if (NULL != p) zbx_free(p); *((char **)cfg[i].variable) = strdup(value); } else if (TYPE_MULTISTRING == cfg[i].type) { zbx_strarr_add(cfg[i].variable, value); } else assert(0); } if (0 == param_valid && ZBX_CFG_STRICT == strict) goto unknown_parameter; } fclose(file); } if (1 != level) /* skip mandatory parameters check for included files */ return result; for (i = 0; NULL != cfg[i].parameter; i++) /* check for mandatory parameters */ { if (PARM_MAND != cfg[i].mandatory) continue; if (TYPE_INT == cfg[i].type) { if (0 == *((int *)cfg[i].variable)) goto missing_mandatory; } else if (TYPE_STRING == cfg[i].type) { if (NULL == (*(char **)cfg[i].variable)) goto missing_mandatory; } else assert(0); } return result; cannot_open: if (optional) return result; zbx_error("cannot open config file [%s]: %s", cfg_file, zbx_strerror(errno)); exit(1); missing_mandatory: zbx_error("missing mandatory parameter [%s] in config file [%s]", cfg[i].parameter, cfg_file); exit(1); incorrect_config: fclose(file); zbx_error("wrong value of [%s] in config file [%s], line %d", cfg[i].parameter, cfg_file, lineno); exit(1); unknown_parameter: fclose(file); zbx_error("unknown parameter [%s] in config file [%s], line %d", parameter, cfg_file, lineno); exit(1); garbage: fclose(file); zbx_error("invalid entry [%s] (not following \"parameter=value\" notation) in config file [%s], line %d", line, cfg_file, lineno); exit(1); }
int parse_cfg_file(const char *cfg_file,struct cfg_line *cfg) { FILE *file; #define ZBX_MAX_INCLUDE_LEVEL 10 #define ZBX_CFG_LTRIM_CHARS "\t " #define ZBX_CFG_RTRIM_CHARS ZBX_CFG_LTRIM_CHARS "\r\n\0" register int i, lineno; char line[MAX_STRING_LEN], *parameter, *value; int var; int result = SUCCEED; assert(cfg); // printf("%d %s\n", level, cfg_file); if(++level > ZBX_MAX_INCLUDE_LEVEL) { /* Ignore include files of depth 10 */ return result; } if(cfg_file) { if( NULL == (file = fopen(cfg_file,"r")) ) { goto lbl_cannot_open; } else { for(lineno = 1; fgets(line,MAX_STRING_LEN,file) != NULL; lineno++) { zbx_ltrim(line, ZBX_CFG_LTRIM_CHARS); if(line[0]=='#') continue; if(strlen(line) < 3) continue; parameter = line; value = strstr(line,"="); if(NULL == value) { zbx_error("Error in line [%d] \"%s\"", lineno, line); result = FAIL; break; } *value = '\0'; value++; zbx_rtrim(parameter, ZBX_CFG_RTRIM_CHARS); zbx_ltrim(value, ZBX_CFG_LTRIM_CHARS); zbx_rtrim(value, ZBX_CFG_RTRIM_CHARS); zabbix_log(LOG_LEVEL_DEBUG, "cfg: para: [%s] val [%s]", parameter, value); if(strcmp(parameter, "Include") == 0) { parse_cfg_object(value, cfg); } for(i = 0; value[i] != '\0'; i++) { if(value[i] == '\n') { value[i] = '\0'; break; } } for(i = 0; cfg[i].parameter != 0; i++) { if(strcmp(cfg[i].parameter, parameter)) continue; zabbix_log(LOG_LEVEL_DEBUG, "Accepted configuration parameter: '%s' = '%s'",parameter, value); if(cfg[i].function != 0) { if(cfg[i].function(value) != SUCCEED) goto lbl_incorrect_config; } else if(TYPE_INT == cfg[i].type) { var = atoi(value); if ( (cfg[i].min && var < cfg[i].min) || (cfg[i].max && var > cfg[i].max) ) goto lbl_incorrect_config; *((int*)cfg[i].variable) = var; } else { *((char **)cfg[i].variable) = strdup(value); } } } fclose(file); } } level--; /* Check for mandatory parameters */ if (level == 0) { // printf("here: %s\n", cfg_file); for(i = 0; cfg[i].parameter != 0; i++) { if(PARM_MAND != cfg[i].mandatory) continue; if(TYPE_INT == cfg[i].type) { if(*((int*)cfg[i].variable) == 0) goto lbl_missing_mandatory; } else if(TYPE_STRING == cfg[i].type) { if((*(char **)cfg[i].variable) == NULL) goto lbl_missing_mandatory; } } } return SUCCEED; lbl_cannot_open: zbx_error("Cannot open config file [%s] [%s].",cfg_file,strerror(errno)); exit(1); lbl_missing_mandatory: zbx_error("Missing mandatory parameter [%s].", cfg[i].parameter); exit(1); lbl_incorrect_config: zbx_error("Wrong value of [%s] in line %d.", cfg[i].parameter, lineno); exit(1); }