/* * rc.c * * Copyright 2001-2003, Meiosys (www.meiosys.com). All rights reserved. * * See the COPYING file for the terms of usage and distribution. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "log4c/rc.h" #include "log4c/category.h" #include "log4c/appender.h" #include "log4c/layout.h" #include "log4c/appender_type_rollingfile.h" #include "log4c/rollingpolicy.h" #include "log4c/rollingpolicy_type_sizewin.h" #include "sd/error.h" #include "sd/domnode.h" #include "sd/malloc.h" #include "sd/sd_xplatform.h" #include "sd/factory.h" #include #include static const TCHAR version[] = _T("1.2.1"); static log4c_rc_t __log4c_rc = { { 0, 0, 0, 0 } }; log4c_rc_t* const log4c_rc = &__log4c_rc; /******************************************************************************/ static long parse_byte_size (const TCHAR *astring) { /* Parse size in bytes depending on the suffix. Valid suffixes are KB, MB and GB */ size_t sz = _tcslen (astring); long res = _tcstol(astring, (TCHAR **) NULL, 10); if (res <= 0) return 0; if (astring[ sz - 1 ] == _T('B')) { switch (astring[ sz - 2 ]) { case _T('K'): res *= 1024; break; case _T('M'): res *= 1024 * 1024; break; case _T('G'): res *= 1024 * 1024 * 1024; break; default: sd_debug(_T("Wrong suffix parsing size in bytes for string %s, ignoring suffix"), astring); } } sd_debug(_T("Parsed size parameter %s to value %ld"),astring, res); return (res); } /******************************************************************************/ static int config_load(log4c_rc_t* this, sd_domnode_t* anode) { sd_list_iter_t* i = NULL; for (i = sd_list_begin(anode->children); i != sd_list_end(anode->children); i = sd_list_iter_next(i)) { sd_domnode_t* node = i->data; if (!_tcscmp(node->name, _T("nocleanup"))) { this->config.nocleanup = _ttoi(node->value); if (this->config.nocleanup) sd_debug(_T("deactivating log4c cleanup")); } if (!_tcscmp(node->name, _T("bufsize"))) { this->config.bufsize = parse_byte_size(node->value); if (this->config.bufsize) sd_debug(_T("using fixed buffer size of %d bytes"), this->config.bufsize); else sd_debug(_T("using dynamic allocated buffer")); } if (!_tcscmp(node->name, _T("debug"))) { sd_domnode_t* level = sd_domnode_attrs_get(node, _T("level")); if (level) { this->config.debug = _ttoi(level->value); sd_debug(_T("activating log4c debugging. level = %d"), this->config.debug); } } if (!_tcscmp(node->name, _T("reread"))) { this->config.reread = _ttoi(node->value); sd_debug(_T("log4crc reread is %d"),this->config.reread); if (0 == this->config.reread) sd_debug(_T("deactivating log4crc reread")); } } return 0; } /******************************************************************************/ static int category_load(log4c_rc_t* this, sd_domnode_t* anode) { sd_domnode_t* name = sd_domnode_attrs_get(anode, _T("name")); sd_domnode_t* priority = sd_domnode_attrs_get(anode, _T("priority")); sd_domnode_t* additivity = sd_domnode_attrs_get(anode, _T("additivity")); sd_domnode_t* appender = sd_domnode_attrs_get(anode, _T("appender")); log4c_category_t* cat = NULL; if (!name) { sd_error(_T("attribute \"name\" is missing")); return -1; } cat = log4c_category_get(name->value); if (priority) log4c_category_set_priority( cat, log4c_priority_to_int(priority->value)); if (additivity) { if (!strcasecmp(additivity->value, _T("false"), _tcslen(_T("false")))) { log4c_category_set_additivity(cat, 0); } else if (!strcasecmp(additivity->value, _T("true"), _tcslen(_T("true")))) { log4c_category_set_additivity(cat, 1); } else { sd_error(_T("additivity value is invalid : %s"), additivity->value); } } if (appender) log4c_category_set_appender( cat, log4c_appender_get(appender->value)); return 0; } /******************************************************************************/ static int appender_load(log4c_rc_t* this, sd_domnode_t* anode) { sd_domnode_t* name = sd_domnode_attrs_get(anode, _T("name")); sd_domnode_t* type = sd_domnode_attrs_get(anode, _T("type")); sd_domnode_t* layout = sd_domnode_attrs_get(anode, _T("layout")); log4c_appender_t* app = NULL; if (!name) { sd_error(_T("attribute \"name\" is missing")); return -1; } sd_debug(_T("appender_load[name='%s'"), (name->value ? name->value : _T("(not set)"))); app = log4c_appender_get(name->value); if (type){ sd_debug(_T("appender type is '%s'"), (type->value ? type->value: _T("(not set)"))); log4c_appender_set_type(app, log4c_appender_type_get(type->value)); #ifdef WITH_ROLLINGFILE if ( !strcasecmp(type->value, _T("rollingfile"), _tcsclen(_T("rollingfile")))) { rollingfile_udata_t *rfup = NULL; log4c_rollingpolicy_t *rollingpolicyp = NULL; sd_domnode_t* logdir = sd_domnode_attrs_get(anode, _T("logdir")); sd_domnode_t* logprefix = sd_domnode_attrs_get(anode, _T("prefix")); sd_domnode_t* rollingpolicy_name = sd_domnode_attrs_get(anode, _T("rollingpolicy")); sd_debug(_T("logdir='%s', prefix='%s', rollingpolicy='%s'"), (logdir && logdir->value ? name->value : _T("(not set)")), (logprefix && logprefix->value ? logprefix->value : _T("(not set)")), (rollingpolicy_name && rollingpolicy_name->value ? rollingpolicy_name->value : _T("(not set)"))); rfup = rollingfile_make_udata(); rollingfile_udata_set_logdir(rfup, (TCHAR *)logdir->value); rollingfile_udata_set_files_prefix(rfup, (TCHAR *)logprefix->value); if (rollingpolicy_name){ /* recover a rollingpolicy instance with this name */ rollingpolicyp = log4c_rollingpolicy_get(rollingpolicy_name->value); /* connect that policy to this rollingfile appender conf */ rollingfile_udata_set_policy(rfup, rollingpolicyp); log4c_appender_set_udata(app, rfup); /* allow the policy to initialize itself */ log4c_rollingpolicy_init(rollingpolicyp, rfup); } else { /* no rollingpolicy specified, default to default sizewin */ sd_debug(_T("no rollingpolicy name specified--will default")); } } #endif } if (layout) log4c_appender_set_layout(app, log4c_layout_get(layout->value)); sd_debug(_T("]")); return 0; } /******************************************************************************/ static int layout_load(log4c_rc_t* this, sd_domnode_t* anode) { sd_domnode_t* name = sd_domnode_attrs_get(anode, _T("name")); sd_domnode_t* type = sd_domnode_attrs_get(anode, _T("type")); log4c_layout_t* layout = NULL; if (!name) { sd_error(_T("attribute \"name\" is missing")); return -1; } layout = log4c_layout_get(name->value); if (type) log4c_layout_set_type(layout, log4c_layout_type_get(type->value)); return 0; } #ifdef WITH_ROLLINGFILE /******************************************************************************/ static int rollingpolicy_load(log4c_rc_t* this, sd_domnode_t* anode) { sd_domnode_t* name = sd_domnode_attrs_get(anode, _T("name")); sd_domnode_t* type = sd_domnode_attrs_get(anode, _T("type")); log4c_rollingpolicy_t* rpolicyp = NULL; long a_maxsize; sd_debug(_T("rollingpolicy_load[")); if (!name) { sd_error(_T("attribute \"name\" is missing")); return -1; } rpolicyp = log4c_rollingpolicy_get(name->value); if (type){ log4c_rollingpolicy_set_type(rpolicyp, log4c_rollingpolicy_type_get(type->value)); if (!strcasecmp(type->value, _T("sizewin"), _tcsclen(_T("sizewin")))){ sd_domnode_t* maxsize = sd_domnode_attrs_get(anode, _T("maxsize")); sd_domnode_t* maxnum = sd_domnode_attrs_get(anode, _T("maxnum")); rollingpolicy_sizewin_udata_t *sizewin_udatap = NULL; sd_debug(_T("type='sizewin', maxsize='%s', maxnum='%s', rpolicyname='%s'"), (maxsize && maxsize->value ? maxsize->value : _T("(not set)")), (maxnum && maxnum->value ? maxnum->value : _T("(not set)")), (name && name->value ? name->value : _T("(not set)"))); /* * Get a new sizewin policy type and configure it. * Then attach it to the policy object. * Check to see if this policy already has a sw udata object. If so, leave as is except update the params */ if ( !(sizewin_udatap = log4c_rollingpolicy_get_udata(rpolicyp))){ sd_debug(_T("creating new sizewin udata for this policy")); sizewin_udatap = sizewin_make_udata(); log4c_rollingpolicy_set_udata(rpolicyp,sizewin_udatap); a_maxsize = parse_byte_size(maxsize->value); if (a_maxsize) sizewin_udata_set_file_maxsize(sizewin_udatap, a_maxsize); else{ sd_debug(_T("When parsing %s a size of 0 was returned. Default size %d will be used"), maxsize->value, ROLLINGPOLICY_SIZE_DEFAULT_MAX_FILE_SIZE); sizewin_udata_set_file_maxsize(sizewin_udatap, ROLLINGPOLICY_SIZE_DEFAULT_MAX_FILE_SIZE); } sizewin_udata_set_max_num_files(sizewin_udatap, _ttoi(maxnum->value)); }else{ sd_debug(_T("policy already has a sizewin udata--just updating params")); sizewin_udata_set_file_maxsize(sizewin_udatap, parse_byte_size(maxsize->value)); sizewin_udata_set_max_num_files(sizewin_udatap, _ttoi(maxnum->value)); /* allow the policy to initialize itself */ log4c_rollingpolicy_init(rpolicyp, log4c_rollingpolicy_get_rfudata(rpolicyp)); } } } sd_debug(_T("]")); return 0; } #endif /******************************************************************************/ extern int log4c_rc_load(log4c_rc_t* this, const TCHAR* a_filename) { sd_list_iter_t* i = NULL; sd_domnode_t* node = NULL; sd_domnode_t* root_node = NULL; sd_debug(_T("parsing file '%s'\n"), a_filename); if (!this) return -1; root_node = sd_domnode_new(NULL, NULL); if (sd_domnode_load(root_node, a_filename) == -1) { sd_domnode_delete(root_node); return -1; } /* Check configuration file root node */ if (_tcscmp(root_node->name, _T("log4c"))) { sd_error(_T("invalid root name %s"), root_node->name); sd_domnode_delete(root_node); return -1; } /* Check configuration file revision */ if ( (node = sd_domnode_attrs_get(root_node, _T("version"))) != NULL) if (_tcscmp(version, node->value)) { sd_error(_T("version mismatch: %s != %s"), version, node->value); sd_domnode_delete(root_node); return -1; } /* backward compatibility. */ if ( (node = sd_domnode_attrs_get(root_node, _T("cleanup"))) != NULL) { sd_debug(_T("attribute \"cleanup\" is deprecated")); this->config.nocleanup = !_ttoi(node->value); } /* load configuration elements */ for (i = sd_list_begin(root_node->children); i != sd_list_end(root_node->children); i = sd_list_iter_next(i)) { sd_domnode_t* node = i->data; if (!_tcscmp(node->name, _T("category"))) category_load(this, node); if (!_tcscmp(node->name, _T("appender"))) appender_load(this, node); #ifdef WITH_ROLLINGFILE if (!_tcscmp(node->name, _T("rollingpolicy")))rollingpolicy_load(this, node); #endif if (!_tcscmp(node->name, _T("layout"))) layout_load(this, node); if (!_tcscmp(node->name, _T("config"))) config_load(this, node); } sd_domnode_delete(root_node); return 0; } /******************************************************************************/ extern int log4c_load(const TCHAR* a_filename) { return log4c_rc_load(&__log4c_rc, a_filename); }