123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556 |
- /*
- * This file is part of the zlog Library.
- *
- * Copyright (C) 2011 by Hardy Simpson <HardySimpson1984@gmail.com>
- *
- * Licensed under the LGPL v2.1, see the file COPYING in base directory.
- */
- #include "fmacros.h"
- #include <ctype.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <errno.h>
- #include <string.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <unistd.h>
- #include <time.h>
- #include "conf.h"
- #include "rule.h"
- #include "format.h"
- #include "level_list.h"
- #include "rotater.h"
- #include "zc_defs.h"
- /*******************************************************************************/
- #define ZLOG_CONF_DEFAULT_FORMAT "default = \"%D %V [%p:%F:%L] %m%n\""
- #define ZLOG_CONF_DEFAULT_RULE "*.* >stdout"
- #define ZLOG_CONF_DEFAULT_BUF_SIZE_MIN 1024
- #define ZLOG_CONF_DEFAULT_BUF_SIZE_MAX (2 * 1024 * 1024)
- #define ZLOG_CONF_DEFAULT_FILE_PERMS 0600
- #define ZLOG_CONF_DEFAULT_RELOAD_CONF_PERIOD 0
- #define ZLOG_CONF_DEFAULT_FSYNC_PERIOD 0
- #define ZLOG_CONF_BACKUP_ROTATE_LOCK_FILE "/tmp/zlog.lock"
- /*******************************************************************************/
- void zlog_conf_profile(zlog_conf_t * a_conf, int flag)
- {
- int i;
- zlog_rule_t *a_rule;
- zlog_format_t *a_format;
- zc_assert(a_conf,);
- zc_profile(flag, "-conf[%p]-", a_conf);
- zc_profile(flag, "--global--");
- zc_profile(flag, "---file[%s],mtime[%s]---", a_conf->file, a_conf->mtime);
- zc_profile(flag, "---in-memory conf[%s]---", a_conf->cfg_ptr);
- zc_profile(flag, "---strict init[%d]---", a_conf->strict_init);
- zc_profile(flag, "---buffer min[%ld]---", a_conf->buf_size_min);
- zc_profile(flag, "---buffer max[%ld]---", a_conf->buf_size_max);
- if (a_conf->default_format) {
- zc_profile(flag, "---default_format---");
- zlog_format_profile(a_conf->default_format, flag);
- }
- zc_profile(flag, "---file perms[0%o]---", a_conf->file_perms);
- zc_profile(flag, "---reload conf period[%ld]---", a_conf->reload_conf_period);
- zc_profile(flag, "---fsync period[%ld]---", a_conf->fsync_period);
- zc_profile(flag, "---rotate lock file[%s]---", a_conf->rotate_lock_file);
- if (a_conf->rotater) zlog_rotater_profile(a_conf->rotater, flag);
- if (a_conf->levels) zlog_level_list_profile(a_conf->levels, flag);
- if (a_conf->formats) {
- zc_profile(flag, "--format list[%p]--", a_conf->formats);
- zc_arraylist_foreach(a_conf->formats, i, a_format) {
- zlog_format_profile(a_format, flag);
- }
- }
- if (a_conf->rules) {
- zc_profile(flag, "--rule_list[%p]--", a_conf->rules);
- zc_arraylist_foreach(a_conf->rules, i, a_rule) {
- zlog_rule_profile(a_rule, flag);
- }
- }
- return;
- }
- /*******************************************************************************/
- void zlog_conf_del(zlog_conf_t * a_conf)
- {
- zc_assert(a_conf,);
- if (a_conf->rotater) zlog_rotater_del(a_conf->rotater);
- if (a_conf->levels) zlog_level_list_del(a_conf->levels);
- if (a_conf->default_format) zlog_format_del(a_conf->default_format);
- if (a_conf->formats) zc_arraylist_del(a_conf->formats);
- if (a_conf->rules) zc_arraylist_del(a_conf->rules);
- free(a_conf);
- zc_debug("zlog_conf_del[%p]");
- return;
- }
- static int zlog_conf_build_without_file(zlog_conf_t * a_conf);
- static int zlog_conf_build_with_file(zlog_conf_t * a_conf);
- static int zlog_conf_build_with_in_memory(zlog_conf_t * a_conf);
- enum{
- NO_CFG,
- FILE_CFG,
- IN_MEMORY_CFG
- };
- zlog_conf_t *zlog_conf_new(const char *config)
- {
- int nwrite = 0;
- int cfg_source = 0;
- zlog_conf_t *a_conf = NULL;
- a_conf = calloc(1, sizeof(zlog_conf_t));
- if (!a_conf) {
- zc_error("calloc fail, errno[%d]", errno);
- return NULL;
- }
- // Find content of pointer. If it starts with '[' then content are configurations.
- if (config && config[0] != '\0' && config[0] != '[') {
- nwrite = snprintf(a_conf->file, sizeof(a_conf->file), "%s", config);
- cfg_source = FILE_CFG;
- } else if (getenv("ZLOG_CONF_PATH") != NULL) {
- nwrite = snprintf(a_conf->file, sizeof(a_conf->file), "%s", getenv("ZLOG_CONF_PATH"));
- cfg_source = FILE_CFG;
- } else if (config[0]=='[') {
- memset(a_conf->file, 0x00, sizeof(a_conf->file));
- nwrite = snprintf(a_conf->cfg_ptr, sizeof(a_conf->cfg_ptr), "%s", config);
- cfg_source = IN_MEMORY_CFG;
- if (nwrite < 0 || nwrite >= sizeof(a_conf->file)) {
- zc_error("not enough space for configurations, nwrite=[%d], errno[%d]", nwrite, errno);
- goto err;
- }
- } else {
- memset(a_conf->file, 0x00, sizeof(a_conf->file));
- cfg_source = NO_CFG;
- }
- if (nwrite < 0 || nwrite >= sizeof(a_conf->file) && cfg_source == FILE_CFG) {
- zc_error("not enough space for path name, nwrite=[%d], errno[%d]", nwrite, errno);
- goto err;
- }
- /* set default configuration start */
- a_conf->strict_init = 1;
- a_conf->buf_size_min = ZLOG_CONF_DEFAULT_BUF_SIZE_MIN;
- a_conf->buf_size_max = ZLOG_CONF_DEFAULT_BUF_SIZE_MAX;
- if (cfg_source == FILE_CFG) {
- /* configure file as default lock file */
- strcpy(a_conf->rotate_lock_file, a_conf->file);
- } else {
- strcpy(a_conf->rotate_lock_file, ZLOG_CONF_BACKUP_ROTATE_LOCK_FILE);
- }
- strcpy(a_conf->default_format_line, ZLOG_CONF_DEFAULT_FORMAT);
- a_conf->file_perms = ZLOG_CONF_DEFAULT_FILE_PERMS;
- a_conf->reload_conf_period = ZLOG_CONF_DEFAULT_RELOAD_CONF_PERIOD;
- a_conf->fsync_period = ZLOG_CONF_DEFAULT_FSYNC_PERIOD;
- /* set default configuration end */
- a_conf->levels = zlog_level_list_new();
- if (!a_conf->levels) {
- zc_error("zlog_level_list_new fail");
- goto err;
- }
- a_conf->formats = zc_arraylist_new((zc_arraylist_del_fn) zlog_format_del);
- if (!a_conf->formats) {
- zc_error("zc_arraylist_new fail");
- goto err;
- }
- a_conf->rules = zc_arraylist_new((zc_arraylist_del_fn) zlog_rule_del);
- if (!a_conf->rules) {
- zc_error("init rule_list fail");
- goto err;
- }
- if (cfg_source == FILE_CFG) {
- if (zlog_conf_build_with_file(a_conf)) {
- zc_error("zlog_conf_build_with_file fail");
- goto err;
- }
- } else if (cfg_source == IN_MEMORY_CFG) {
- if(zlog_conf_build_with_in_memory(a_conf)){
- zc_error("zlog_conf_build_with_in_memory fail");
- goto err;
- }
- } else {
- if (zlog_conf_build_without_file(a_conf)) {
- zc_error("zlog_conf_build_without_file fail");
- goto err;
- }
- }
- zlog_conf_profile(a_conf, ZC_DEBUG);
- return a_conf;
- err:
- zlog_conf_del(a_conf);
- return NULL;
- }
- /*******************************************************************************/
- static int zlog_conf_build_without_file(zlog_conf_t * a_conf)
- {
- zlog_rule_t *default_rule;
- a_conf->default_format = zlog_format_new(a_conf->default_format_line, &(a_conf->time_cache_count));
- if (!a_conf->default_format) {
- zc_error("zlog_format_new fail");
- return -1;
- }
- a_conf->rotater = zlog_rotater_new(a_conf->rotate_lock_file);
- if (!a_conf->rotater) {
- zc_error("zlog_rotater_new fail");
- return -1;
- }
- default_rule = zlog_rule_new(
- ZLOG_CONF_DEFAULT_RULE,
- a_conf->levels,
- a_conf->default_format,
- a_conf->formats,
- a_conf->file_perms,
- a_conf->fsync_period,
- &(a_conf->time_cache_count));
- if (!default_rule) {
- zc_error("zlog_rule_new fail");
- return -1;
- }
- /* add default rule */
- if (zc_arraylist_add(a_conf->rules, default_rule)) {
- zlog_rule_del(default_rule);
- zc_error("zc_arraylist_add fail");
- return -1;
- }
- return 0;
- }
- /*******************************************************************************/
- static int zlog_conf_parse_line(zlog_conf_t * a_conf, char *line, int *section);
- static int zlog_conf_build_with_file(zlog_conf_t * a_conf)
- {
- int rc = 0;
- struct zlog_stat a_stat;
- struct tm local_time;
- FILE *fp = NULL;
- char line[MAXLEN_CFG_LINE + 1];
- size_t line_len;
- char *pline = NULL;
- char *p = NULL;
- int line_no = 0;
- int i = 0;
- int in_quotation = 0;
- int section = 0;
- /* [global:1] [levels:2] [formats:3] [rules:4] */
- if (lstat(a_conf->file, &a_stat)) {
- zc_error("lstat conf file[%s] fail, errno[%d]", a_conf->file,
- errno);
- return -1;
- }
- localtime_r(&(a_stat.st_mtime), &local_time);
- strftime(a_conf->mtime, sizeof(a_conf->mtime), "%F %T", &local_time);
- if ((fp = fopen(a_conf->file, "r")) == NULL) {
- zc_error("open configure file[%s] fail", a_conf->file);
- return -1;
- }
- /* Now process the file.
- */
- pline = line;
- memset(&line, 0x00, sizeof(line));
- while (fgets((char *)pline, sizeof(line) - (pline - line), fp) != NULL) {
- ++line_no;
- line_len = strlen(pline);
- if (0 == line_len) {
- continue;
- }
- if (pline[line_len - 1] == '\n') {
- pline[line_len - 1] = '\0';
- }
- /* check for end-of-section, comments, strip off trailing
- * spaces and newline character.
- */
- p = pline;
- while (*p && isspace((int)*p))
- ++p;
- if (*p == '\0' || *p == '#')
- continue;
- for (i = 0; p[i] != '\0'; ++i) {
- pline[i] = p[i];
- }
- pline[i] = '\0';
- for (p = pline + strlen(pline) - 1; isspace((int)*p); --p)
- /*EMPTY*/;
- if (*p == '\\') {
- if ((p - line) > MAXLEN_CFG_LINE - 30) {
- /* Oops the buffer is full - what now? */
- pline = line;
- } else {
- for (p--; isspace((int)*p); --p)
- /*EMPTY*/;
- p++;
- *p = 0;
- pline = p;
- continue;
- }
- } else
- pline = line;
- *++p = '\0';
- /* clean the tail comments start from # and not in quotation */
- in_quotation = 0;
- for (p = line; *p != '\0'; p++) {
- if (*p == '"') {
- in_quotation ^= 1;
- continue;
- }
- if (*p == '#' && !in_quotation) {
- *p = '\0';
- break;
- }
- }
- /* we now have the complete line,
- * and are positioned at the first non-whitespace
- * character. So let's process it
- */
- rc = zlog_conf_parse_line(a_conf, line, §ion);
- if (rc < 0) {
- zc_error("parse configure file[%s]line_no[%ld] fail", a_conf->file, line_no);
- zc_error("line[%s]", line);
- goto exit;
- } else if (rc > 0) {
- zc_warn("parse configure file[%s]line_no[%ld] fail", a_conf->file, line_no);
- zc_warn("line[%s]", line);
- zc_warn("as strict init is set to false, ignore and go on");
- rc = 0;
- continue;
- }
- }
- exit:
- fclose(fp);
- return rc;
- }
- /**********************************************************************/
- static int zlog_conf_build_with_in_memory(zlog_conf_t * a_conf)
- {
- int rc = 0;
- char line[MAXLEN_CFG_LINE + 1];
- char *pline = NULL;
- int section = 0;
- pline = line;
- memset(&line, 0x00, sizeof(line));
- pline = strtok((char *)a_conf->cfg_ptr, "\n");
- while (pline != NULL) {
- rc = zlog_conf_parse_line(a_conf, pline, §ion);
- if (rc < 0) {
- zc_error("parse in-memory configurations[%s] line [%s] fail", a_conf->cfg_ptr, pline);
- break;
- } else if (rc > 0) {
- zc_error("parse in-memory configurations[%s] line [%s] fail", a_conf->cfg_ptr, pline);
- zc_warn("as strict init is set to false, ignore and go on");
- rc = 0;
- continue;
- }
- pline = strtok(NULL, "\n");
- }
- return rc;
- }
- /* section [global:1] [levels:2] [formats:3] [rules:4] */
- static int zlog_conf_parse_line(zlog_conf_t * a_conf, char *line, int *section)
- {
- int nscan;
- int nread;
- char name[MAXLEN_CFG_LINE + 1];
- char word_1[MAXLEN_CFG_LINE + 1];
- char word_2[MAXLEN_CFG_LINE + 1];
- char word_3[MAXLEN_CFG_LINE + 1];
- char value[MAXLEN_CFG_LINE + 1];
- zlog_format_t *a_format = NULL;
- zlog_rule_t *a_rule = NULL;
- if (strlen(line) > MAXLEN_CFG_LINE) {
- zc_error ("line_len[%ld] > MAXLEN_CFG_LINE[%ld], may cause overflow",
- strlen(line), MAXLEN_CFG_LINE);
- return -1;
- }
- /* get and set outer section flag, so it is a closure? haha */
- if (line[0] == '[') {
- int last_section = *section;
- nscan = sscanf(line, "[ %[^] \t]", name);
- if (STRCMP(name, ==, "global")) {
- *section = 1;
- } else if (STRCMP(name, ==, "levels")) {
- *section = 2;
- } else if (STRCMP(name, ==, "formats")) {
- *section = 3;
- } else if (STRCMP(name, ==, "rules")) {
- *section = 4;
- } else {
- zc_error("wrong section name[%s]", name);
- return -1;
- }
- /* check the sequence of section, must increase */
- if (last_section >= *section) {
- zc_error("wrong sequence of section, must follow global->levels->formats->rules");
- return -1;
- }
- if (*section == 4) {
- if (a_conf->reload_conf_period != 0
- && a_conf->fsync_period >= a_conf->reload_conf_period) {
- /* as all rule will be rebuilt when conf is reload,
- * so fsync_period > reload_conf_period will never
- * cause rule to fsync it's file.
- * fsync_period will be meaningless and down speed,
- * so make it zero.
- */
- zc_warn("fsync_period[%ld] >= reload_conf_period[%ld],"
- "set fsync_period to zero");
- a_conf->fsync_period = 0;
- }
- /* now build rotater and default_format
- * from the unchanging global setting,
- * for zlog_rule_new() */
- a_conf->rotater = zlog_rotater_new(a_conf->rotate_lock_file);
- if (!a_conf->rotater) {
- zc_error("zlog_rotater_new fail");
- return -1;
- }
- a_conf->default_format = zlog_format_new(a_conf->default_format_line,
- &(a_conf->time_cache_count));
- if (!a_conf->default_format) {
- zc_error("zlog_format_new fail");
- return -1;
- }
- }
- return 0;
- }
- /* process detail */
- switch (*section) {
- case 1:
- memset(name, 0x00, sizeof(name));
- memset(value, 0x00, sizeof(value));
- nscan = sscanf(line, " %[^=]= %s ", name, value);
- if (nscan != 2) {
- zc_error("sscanf [%s] fail, name or value is null", line);
- return -1;
- }
- memset(word_1, 0x00, sizeof(word_1));
- memset(word_2, 0x00, sizeof(word_2));
- memset(word_3, 0x00, sizeof(word_3));
- nread = 0;
- nscan = sscanf(name, "%s%n%s%s", word_1, &nread, word_2, word_3);
- if (STRCMP(word_1, ==, "strict") && STRCMP(word_2, ==, "init")) {
- /* if environment variable ZLOG_STRICT_INIT is set
- * then always make it strict
- */
- if (STRICMP(value, ==, "false") && !getenv("ZLOG_STRICT_INIT")) {
- a_conf->strict_init = 0;
- } else {
- a_conf->strict_init = 1;
- }
- } else if (STRCMP(word_1, ==, "buffer") && STRCMP(word_2, ==, "min")) {
- a_conf->buf_size_min = zc_parse_byte_size(value);
- } else if (STRCMP(word_1, ==, "buffer") && STRCMP(word_2, ==, "max")) {
- a_conf->buf_size_max = zc_parse_byte_size(value);
- } else if (STRCMP(word_1, ==, "file") && STRCMP(word_2, ==, "perms")) {
- sscanf(value, "%o", &(a_conf->file_perms));
- } else if (STRCMP(word_1, ==, "rotate") &&
- STRCMP(word_2, ==, "lock") && STRCMP(word_3, ==, "file")) {
- /* may overwrite the inner default value, or last value */
- if (STRCMP(value, ==, "self")) {
- strcpy(a_conf->rotate_lock_file, a_conf->file);
- } else {
- strcpy(a_conf->rotate_lock_file, value);
- }
- } else if (STRCMP(word_1, ==, "default") && STRCMP(word_2, ==, "format")) {
- /* so the input now is [format = "xxyy"], fit format's style */
- strcpy(a_conf->default_format_line, line + nread);
- } else if (STRCMP(word_1, ==, "reload") &&
- STRCMP(word_2, ==, "conf") && STRCMP(word_3, ==, "period")) {
- a_conf->reload_conf_period = zc_parse_byte_size(value);
- } else if (STRCMP(word_1, ==, "fsync") && STRCMP(word_2, ==, "period")) {
- a_conf->fsync_period = zc_parse_byte_size(value);
- } else {
- zc_error("name[%s] is not any one of global options", name);
- if (a_conf->strict_init) return -1;
- }
- break;
- case 2:
- if (zlog_level_list_set(a_conf->levels, line)) {
- zc_error("zlog_level_list_set fail");
- if (a_conf->strict_init) return -1;
- }
- break;
- case 3:
- a_format = zlog_format_new(line, &(a_conf->time_cache_count));
- if (!a_format) {
- zc_error("zlog_format_new fail [%s]", line);
- if (a_conf->strict_init) return -1;
- else break;
- }
- if (zc_arraylist_add(a_conf->formats, a_format)) {
- zlog_format_del(a_format);
- zc_error("zc_arraylist_add fail");
- return -1;
- }
- break;
- case 4:
- a_rule = zlog_rule_new(line,
- a_conf->levels,
- a_conf->default_format,
- a_conf->formats,
- a_conf->file_perms,
- a_conf->fsync_period,
- &(a_conf->time_cache_count));
- if (!a_rule) {
- zc_error("zlog_rule_new fail [%s]", line);
- if (a_conf->strict_init) return -1;
- else break;
- }
- if (zc_arraylist_add(a_conf->rules, a_rule)) {
- zlog_rule_del(a_rule);
- zc_error("zc_arraylist_add fail");
- return -1;
- }
- break;
- default:
- zc_error("not in any section");
- return -1;
- }
- return 0;
- }
- /*******************************************************************************/
|