/** * @file mce-log.c * Logging functions for Mode Control Entity * <p> * Copyright © 2006-2007, 2010 Nokia Corporation and/or its subsidiary(-ies). * <p> * @author David Weinehall <david.weinehall@nokia.com> * * mce is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * mce is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with mce. If not, see <http://www.gnu.org/licenses/>. */ #include <glib.h> #include <glib/gprintf.h> #ifdef OSSOLOG_COMPILE #include <stdio.h> /* fprintf() */ #include <stdarg.h> /* va_start(), va_end(), vfprintf() */ #include <string.h> /* strdup() */ #include <syslog.h> /* openlog(), closelog(), vsyslog() */ #include "mce-log.h" static unsigned int logverbosity = LL_WARN; /**< Log verbosity */ static int logtype = MCE_LOG_STDERR; /**< Output for log messages */ static char *logname = NULL; /** Make sure loglevel is in the supported range * * @param loglevel level to check * * @return log level clipped to LL_CRIT ... LL_DEBUG range */ static loglevel_t mce_log_level_normalize(loglevel_t loglevel) { if( loglevel < LL_CRIT ) { loglevel = LL_CRIT; } else if( loglevel > LL_DEBUG ) { loglevel = LL_DEBUG; } return loglevel; } /** Get level indication tag to include in stderr logging * * @param loglevel level for the message * * @return level indication string */ static const char *mce_log_level_tag(loglevel_t loglevel) { const char *res = "?"; switch( loglevel ) { case LL_CRIT: res = "C"; break; case LL_ERR: res = "E"; break; case LL_WARN: res = "W"; break; case LL_NOTICE: res = "N"; break; case LL_INFO: res = "I"; break; case LL_DEBUG: res = "D"; break; default: break; } return res; } /** * Log debug message with optional filename and function name attached * * @param loglevel The level of severity for this message * @param fmt The format string for this message * @param ... Input to the format string */ void mce_log_file(loglevel_t loglevel, const char *const file, const char *const function, const char *const fmt, ...) { va_list args; loglevel = mce_log_level_normalize(loglevel); if (logverbosity >= loglevel) { gchar *msg = 0; va_start(args, fmt); g_vasprintf(&msg, fmt, args); va_end(args); if( file && function ) { gchar *tmp = g_strconcat(file, ": ", function, "(): ", msg, NULL); g_free(msg), msg = tmp; } if (logtype == MCE_LOG_STDERR) { fprintf(stderr, "%s: %s: %s\n", logname, mce_log_level_tag(loglevel), msg); } else { /* loglevels are subset of syslog priorities, so * we can use loglevel as is for syslog priority */ syslog(loglevel, "%s", msg); } g_free(msg); } } /** * Set log verbosity * messages with loglevel higher than or equal to verbosity will be logged * * @param verbosity minimum level for log level */ void mce_log_set_verbosity(const int verbosity) { logverbosity = verbosity; } /** * Open log * * @param name identifier to use for log messages * @param facility the log facility; normally LOG_USER or LOG_DAEMON * @param type log type to use; MCE_LOG_STDERR or MCE_LOG_SYSLOG */ void mce_log_open(const char *const name, const int facility, const int type) { logtype = type; if (logtype == MCE_LOG_SYSLOG) openlog(name, LOG_PID | LOG_NDELAY, facility); else logname = g_strdup(name); } /** * Close log */ void mce_log_close(void) { g_free(logname), logname = 0; if (logtype == MCE_LOG_SYSLOG) closelog(); } /** * Log level testing predicate * * For testing whether given level of logging is allowed * before spending cpu time for gathering parameters etc * * @param loglevel level of logging we might do * * @return 1 if logging at givel level is enabled, 0 if not */ int mce_log_p(const loglevel_t loglevel) { return logverbosity >= loglevel; } #endif /* OSSOLOG_COMPILE */