diff options
author | Andreas Baumann <abaumann@yahoo.com> | 2012-09-10 10:33:38 +0200 |
---|---|---|
committer | Andreas Baumann <abaumann@yahoo.com> | 2012-09-10 10:33:38 +0200 |
commit | a3cc8b970a24e1970275f0e8032bf6b221d3e235 (patch) | |
tree | 8f69aa22ef6abf18457db3d923fbb1feaf2c5a48 /src/liblogger | |
parent | dcc75cfbc4e5069038f0ec9929d1000f1630e382 (diff) | |
download | crawler-a3cc8b970a24e1970275f0e8032bf6b221d3e235.tar.gz crawler-a3cc8b970a24e1970275f0e8032bf6b221d3e235.tar.bz2 |
libutil move and liblogger rename on Windows
Diffstat (limited to 'src/liblogger')
-rwxr-xr-x | src/liblogger/ConsoleLogSink.cpp | 17 | ||||
-rw-r--r-- | src/liblogger/FileLogSink.cpp | 85 | ||||
-rwxr-xr-x | src/liblogger/GNUmakefile | 43 | ||||
-rwxr-xr-x | src/liblogger/Logger.cpp | 183 | ||||
-rwxr-xr-x | src/liblogger/Makefile.W32 | 60 | ||||
-rwxr-xr-x | src/liblogger/SyslogLogSink.cpp | 91 | ||||
-rwxr-xr-x | src/liblogger/WinDbgLogSink.cpp | 22 | ||||
-rw-r--r-- | src/liblogger/win32/syslog_win32.c | 261 | ||||
-rw-r--r-- | src/liblogger/win32/syslog_win32.h | 171 |
9 files changed, 933 insertions, 0 deletions
diff --git a/src/liblogger/ConsoleLogSink.cpp b/src/liblogger/ConsoleLogSink.cpp new file mode 100755 index 0000000..84a1ebd --- /dev/null +++ b/src/liblogger/ConsoleLogSink.cpp @@ -0,0 +1,17 @@ +#include "ConsoleLogSink.hpp" + +#include <iostream> + +using namespace std; + +void ConsoleLogSink::log( const LogLevel level, const string &msg ) +{ + if( level > reportingLevel( ) ) return; + + cerr << Logger::toString( level ) + << ": " + << msg + << endl; + + cerr.flush( ); +} diff --git a/src/liblogger/FileLogSink.cpp b/src/liblogger/FileLogSink.cpp new file mode 100644 index 0000000..d812dbe --- /dev/null +++ b/src/liblogger/FileLogSink.cpp @@ -0,0 +1,85 @@ +#include "FileLogSink.hpp" + +#include <iostream> +#include <cstring> + +#ifndef _WIN32 +#include <sys/time.h> +#else +#define WIN32_MEAN_AND_LEAN +#include <windows.h> +#endif + +using namespace std; + +#ifndef _WIN32 + +static string timestamp( ) +{ + time_t t; + time( &t ); + + struct tm r; + memset( &r, 0, sizeof( r ) ); + localtime_r( &t, &r ); + + char buf[30]; + strftime( buf, sizeof( buf ), "%F - %X", &r ); + + struct timeval tv; + gettimeofday( &tv, 0 ); + char result[100]; + snprintf( result, sizeof( result ), "%s.%03ld", buf, (long)tv.tv_usec / 1000 ); + + return result; +} + +#else + +static string timestamp( ) +{ + enum { LEN = 255 }; + char buf[LEN]; + + if( GetTimeFormat( LOCALE_USER_DEFAULT, 0, 0, "HH':'mm':'ss", buf, LEN ) == 0 ) { + return "<timestamp error>"; + } + + static DWORD first = GetTickCount( ); + + char result[LEN] = { 0 }; + _snprintf( result, LEN, "%s.%03ld", buf, (long)( GetTickCount( ) - first ) % 1000 ); + + return result; +} + +#endif + +FileLogSink::FileLogSink( const LogLevel level, const string &filename ) + : LogSink( level ), m_filename( filename ) +{ + m_file.exceptions( m_file.badbit | m_file.failbit ); + + try { + m_file.open( m_filename.c_str( ), std::ios::app ); + } catch( exception &e ) { + LOG( logCRITICAL ) << e.what( ); + } +} + +FileLogSink::~FileLogSink( ) +{ + m_file.close( ); +} + +void FileLogSink::log( const LogLevel level, const string &msg ) +{ + if( level > reportingLevel( ) ) return; + + m_file << timestamp( ) + << " " + << Logger::toString( level ) + << ": " + << msg + << endl; +} diff --git a/src/liblogger/GNUmakefile b/src/liblogger/GNUmakefile new file mode 100755 index 0000000..7993f7d --- /dev/null +++ b/src/liblogger/GNUmakefile @@ -0,0 +1,43 @@ +TOPDIR = ../.. + +SUBDIRS = + +-include $(TOPDIR)/makefiles/gmake/platform.mk + +INCLUDE_CPPFLAGS = \ + +INCLUDE_LDFLAGS = \ + +INCLUDE_DIRS = \ + -I. \ + -I$(TOPDIR)/include/logger \ + -I$(TOPDIR)/include/util + +INCLUDE_LIBS = \ + +STATIC_LIB = liblogger.a + +DYNAMIC_LIB = liblogger.so +DYNAMIC_LIB_MAJOR = 0 +DYNAMIC_LIB_MINOR = 0 +DYNAMIC_LIB_PATCH = 0 + +CPP_OBJS = \ + Logger.o \ + ConsoleLogSink.o \ + FileLogSink.o \ + SyslogLogSink.o + +-include $(TOPDIR)/makefiles/gmake/sub.mk + +local_all: + +local_clean: + +local_distclean: + +local_install: + +local_uninstall: + +local_test: diff --git a/src/liblogger/Logger.cpp b/src/liblogger/Logger.cpp new file mode 100755 index 0000000..c4d44d8 --- /dev/null +++ b/src/liblogger/Logger.cpp @@ -0,0 +1,183 @@ +#include "Logger.hpp" +#include "LogSink.hpp" +#include "ConsoleLogSink.hpp" +#include "FileLogSink.hpp" +#include "SyslogLogSink.hpp" +#ifdef _WIN32 +#include "WinDbgLogSink.hpp" +#endif + +#include <algorithm> +#include <list> + +using namespace std; + +LogStream::LogStream( Logger &logger, const LogLevel level ) + : m_logger( logger ), m_level( level ) +{ +} + +LogStream::~LogStream( ) +{ + m_logger.log( m_level, str( ) ); +} + +ostream &LogStream::get( ) +{ + // transform the ostringstream to ostream, so the operator + // << functions work a little bit more as expected (e.g. + // for strings/char *) + return static_cast<ostream &>( *this ); +} + +class LoggerImpl +{ + public: + void addSink( LogSink *sink ); + void removeSink( LogSink *sink ); + void log( const LogLevel level, const std::string &msg ); + + static std::string toString( const LogLevel level ); + static LogLevel fromString( const std::string &s ); + + void openConsoleLog( const LogLevel level ); + void openFileLog( const LogLevel level, const std::string &filename ); + void openSyslog( const LogLevel level, const string &ident, const string &facility ); + void openWinDbgLog( const LogLevel level ); + + public: + LoggerImpl( ); + ~LoggerImpl( ); + + private: + typedef std::list< LogSink * > SinkList; + SinkList m_sinks; +}; + +LoggerImpl::LoggerImpl( ) +{ +} + +LoggerImpl::~LoggerImpl( ) +{ + SinkList::const_iterator it, end = m_sinks.end( ); + + for( it = m_sinks.begin( ); it != end; it++ ) { + delete (*it); + } +} + +void LoggerImpl::addSink( LogSink *sink ) +{ + m_sinks.push_back( sink ); +} +void LoggerImpl::removeSink( LogSink *sink ) +{ + SinkList::iterator it = find( m_sinks.begin( ), m_sinks.end( ), sink ); + if( it != m_sinks.end( ) ) { + m_sinks.erase( it ); + } +} + +void LoggerImpl::log( const LogLevel level, const string &msg ) +{ + SinkList::const_iterator it, end = m_sinks.end( ); + + for( it = m_sinks.begin( ); it != end; it++ ) { + (*it)->log( level, msg ); + } +} + +void LoggerImpl::openConsoleLog( const LogLevel level ) +{ + addSink( new ConsoleLogSink( level ) ); +} + +void LoggerImpl::openFileLog( const LogLevel level, const string &filename ) +{ + addSink( new FileLogSink( level, filename ) ); +} + +void LoggerImpl::openSyslog( const LogLevel level, const string &ident, const string &facility ) +{ + addSink( new SyslogLogSink( level, ident, facility ) ); +} + +void LoggerImpl::openWinDbgLog( const LogLevel level ) +{ +#ifdef _WIN32 + addSink( new WinDbgLogSink( level ) ); +#else + (void)level; + LOG( logWARNING ) << "WinDbg logger is only available on Windows"; +#endif +} + +string Logger::toString( const LogLevel level ) +{ + static const char* const buf[] = { "NONE", "FATAL", "CRITICAL", "ERROR", "WARNING", "NOTICE", "INFO", "DEBUG", "DEBUG1", "DEBUG2", "DEBUG3", "DEBUG4" }; + return buf[level]; +} + +LogLevel Logger::fromString( const string& level ) +{ + if( level == "DEBUG4" ) return logDEBUG4; + if( level == "DEBUG3" ) return logDEBUG3; + if( level == "DEBUG2" ) return logDEBUG2; + if( level == "DEBUG1") return logDEBUG1; + if( level == "DEBUG") return logDEBUG; + if( level == "INFO") return logINFO; + if( level == "NOTICE" ) return logNOTICE; + if( level == "WARNING" ) return logWARNING; + if( level == "ERROR" ) return logERROR; + if( level == "CRITICAL" ) return logCRITICAL; + if( level == "FATAL" ) return logFATAL; + if( level == "NONE" ) return logNONE; + + LOG( logWARNING ) << "Unknown log level '" << level << "'. Using INFO level as default."; + return logINFO; +} + +Logger::Logger( ) +{ + m_impl.reset( new LoggerImpl( ) ); +} + +Logger::~Logger( ) +{ +} + +void Logger::addSink( LogSink *sink ) +{ + m_impl->addSink( sink ); +} + +void Logger::removeSink( LogSink *sink ) +{ + m_impl->removeSink( sink ); +} + +void Logger::log( const LogLevel level, const string &msg ) +{ + m_impl->log( level, msg ); +} + +void Logger::openConsoleLog( const LogLevel level ) +{ + m_impl->openConsoleLog( level ); +} + +void Logger::openFileLog( const LogLevel level, const std::string &filename ) +{ + m_impl->openFileLog( level, filename ); +} + +void Logger::openSyslog( const LogLevel level, const string &ident, const string &facility ) +{ + m_impl->openSyslog( level, ident, facility ); +} + +void Logger::openWinDbgLog( const LogLevel level ) +{ + m_impl->openWinDbgLog( level ); +} diff --git a/src/liblogger/Makefile.W32 b/src/liblogger/Makefile.W32 new file mode 100755 index 0000000..10c99f6 --- /dev/null +++ b/src/liblogger/Makefile.W32 @@ -0,0 +1,60 @@ +TOPDIR = ..\.. + +SUBDIRS = + +!INCLUDE $(TOPDIR)\makefiles\nmake\platform.mk + +INCLUDE_CXXFLAGS = \ + /D_WIN32_WINNT=0x504 \ + /DBUILDING_LOGGER /DBUILDING_UTIL + +INCLUDE_DIRS = \ + /I. \ + /I$(TOPDIR)\include\logger \ + /I$(TOPDIR)\include\util + +INCLUDE_LDFLAGS = \ + +INCLUDE_LIBS = \ + $(TOPDIR)\src\libutil\util.lib \ + Ws2_32.lib + +CPP_OBJS = \ + win32\syslog_win32.obj \ + Logger.obj \ + ConsoleLogSink.obj \ + FileLogSink.obj \ + SyslogLogSink.obj \ + WinDbgLogSink.obj + +DYNAMIC_CPP_OBJS = \ + win32\syslog_win32.dllobj \ + Logger.dllobj \ + ConsoleLogSink.dllobj \ + FileLogSink.dllobj \ + SyslogLogSink.dllobj \ + WinDbgLogSink.dllobj + +DYNAMIC_LIB = \ + logger.dll + +STATIC_LIB = \ + loggerstatic.lib + +!INCLUDE $(TOPDIR)\makefiles\nmake\sub.mk + +$(DYNAMIC_LIB): $(DYNAMIC_CPP_OBJS) + $(LINK) /nologo /dll /out:$@ $(LDFLAGS) $(LIBS) $? + +$(STATIC_LIB): $(CPP_OBJS) + $(LINK) /nologo /dll /out:$@ $(STATIC_LDFLAGS) $(LIBS) $? + +local_all: $(DYNAMIC_LIB) $(STATIC_LIB) + +local_clean: + @-erase $(DYNAMIC_LIB) $(STATIC_LIB) 2>NUL + @-erase win32\*.obj 2>NUL + +local_distclean: + +local_test: diff --git a/src/liblogger/SyslogLogSink.cpp b/src/liblogger/SyslogLogSink.cpp new file mode 100755 index 0000000..c2716a9 --- /dev/null +++ b/src/liblogger/SyslogLogSink.cpp @@ -0,0 +1,91 @@ +#include "SyslogLogSink.hpp" + +#ifndef _WIN32 +#include <syslog.h> +#else +#include "win32/syslog_win32.h" +#endif + +using namespace std; + +SyslogLogSink::SyslogLogSink( const LogLevel level, const string &ident, const string &facility ) + : LogSink( level ), m_ident( ident ), m_facility( facility ) +{ + openlog( m_ident.c_str( ), LOG_PID, facilityFromString( m_facility ) ); +} + +SyslogLogSink::~SyslogLogSink( ) +{ + closelog( ); +} + +void SyslogLogSink::log( const LogLevel level, const string &msg ) +{ + if( level > reportingLevel( ) ) return; + + syslog( levelToSyslogLevel( level ), "%s", msg.c_str( ) ); +} + +int SyslogLogSink::levelToSyslogLevel( const LogLevel level ) +{ + switch( level ) { + case logFATAL: return LOG_ALERT; + case logCRITICAL: return LOG_CRIT; + case logERROR: return LOG_ERR; + case logWARNING: return LOG_WARNING; + case logNOTICE: return LOG_NOTICE; + case logINFO: return LOG_INFO; + case logDEBUG: + case logDEBUG1: + case logDEBUG2: + case logDEBUG3: + case logDEBUG4: return LOG_DEBUG; + + case logNONE: + default: + LOG( logWARNING ) << "Unknown log level '" << level << "'. Using LOG)ERR level as syslog log level."; + return LOG_ERR; + } +} + +int SyslogLogSink::facilityFromString( const std::string &facility ) +{ + if( facility == "kern" ) return LOG_KERN; + else if( facility == "user" ) return LOG_USER; + else if( facility == "mail" ) return LOG_MAIL; + else if( facility == "daemon" ) return LOG_DAEMON; + else if( facility == "auth" ) return LOG_AUTH; + else if( facility == "syslog" ) return LOG_SYSLOG; + else if( facility == "lpr" ) return LOG_LPR; + else if( facility == "news" ) return LOG_NEWS; + else if( facility == "uucp" ) return LOG_UUCP; + else if( facility == "cron" ) return LOG_CRON; +#ifdef LOG_AUTHPRIV + else if( facility == "authpriv" ) return LOG_AUTHPRIV; +#endif +#ifdef LOG_FTP + else if( facility == "ftp" ) return LOG_FTP; +#endif +#ifdef LOG_NTP + else if( facility == "ntp" ) return LOG_NTP; +#endif +#ifdef LOG_SECURITY + else if( facility == "security" ) return LOG_SECURITY; +#endif +#ifdef LOG_CONSOLE + else if( facility == "console" ) return LOG_CONSOLE; +#endif +#ifdef LOG_AUDIT + else if( facility == "audit" ) return LOG_AUDIT; +#endif + else if( facility == "local0" ) return LOG_LOCAL0; + else if( facility == "local1" ) return LOG_LOCAL1; + else if( facility == "local2" ) return LOG_LOCAL2; + else if( facility == "local3" ) return LOG_LOCAL3; + else if( facility == "local4" ) return LOG_LOCAL4; + else if( facility == "local5" ) return LOG_LOCAL5; + else if( facility == "local6" ) return LOG_LOCAL6; + else if( facility == "local7" ) return LOG_LOCAL7; + else return LOG_USER; +} + diff --git a/src/liblogger/WinDbgLogSink.cpp b/src/liblogger/WinDbgLogSink.cpp new file mode 100755 index 0000000..f5a830c --- /dev/null +++ b/src/liblogger/WinDbgLogSink.cpp @@ -0,0 +1,22 @@ +#include "WinDbgLogSink.hpp" + +#include <sstream> + +#define WIN32_MEAN_AND_LEAN +#include <windows.h> + +using namespace std; + +void WinDbgLogSink::log( const LogLevel level, const string &msg ) +{ + if( level > reportingLevel( ) ) return; + + ostringstream ss; + + ss << Logger::toString( level ) + << ": " + << msg + << "\r\n"; + + OutputDebugString( ss.str( ).c_str( ) ); +} diff --git a/src/liblogger/win32/syslog_win32.c b/src/liblogger/win32/syslog_win32.c new file mode 100644 index 0000000..e94bb9e --- /dev/null +++ b/src/liblogger/win32/syslog_win32.c @@ -0,0 +1,261 @@ +/************************************************************************ + + Copyright (C) 2011, 2012 Project Wolframe. + All rights reserved. + + This file is part of Project Wolframe. + + Commercial Usage + Licensees holding valid Project Wolframe Commercial licenses may + use this file in accordance with the Project Wolframe + Commercial License Agreement provided with the Software or, + alternatively, in accordance with the terms contained + in a written agreement between the licensee and Project Wolframe. + + GNU General Public License Usage + Alternatively, you can redistribute this file and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Wolframe 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Wolframe. If not, see <http://www.gnu.org/licenses/>. + + If you have questions regarding the use of this file, please contact + Project Wolframe. + +************************************************************************/ + +/* + * syslog-client.c - syslog client implementation for windows + * + * Created by Alexander Yaworsky + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAIMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + */ + +/** + * \file syslog_win32.c + * \brief implementation of a syslog client on Windows + * + * It is roughly based on the one of http://syslog-win32.sourceforge.net, + * changed in the way it's configured (we can't have a /etc/syslog.conf + * on Windows, host and port must be injectable through a function from + * the Wolframe configuration), in the way the messages are composed using + * newer string functions, using WSock2 funtions like getaddrinfo and + * some small other things like added documentation. +*/ + +/* TODOS: + * - reset logmask in openlog? + * - handle more options + */ + +#include "syslog_win32.h" + +#include <Winsock2.h> +#include <ws2tcpip.h> +#include <string.h> +#include <stdio.h> + +static BOOL initialized = FALSE; +static BOOL wsa_initialized = FALSE; + +static int log_mask = 0xFF; +static const char *syslog_ident = NULL; +static int syslog_facility = 0; +static char str_pid[40]; +static char local_hostname[MAX_COMPUTERNAME_LENGTH+4]; + +static char syslog_hostname[256] = "localhost"; +static char syslog_service[256] = "514"; + +/* UDP socket and data to use for sending messages */ +static SOCKADDR_STORAGE sa_logger; +static SOCKET sock = INVALID_SOCKET; +#define SYSLOG_DGRAM_SIZE 1024 +static char datagram[SYSLOG_DGRAM_SIZE]; +static int datagram_size = SYSLOG_DGRAM_SIZE; + +void openlog( const char* ident, int option, int facility ) +{ + BOOL failed = TRUE; + WSADATA wsd; + struct addrinfo hints; + struct addrinfo *result = NULL; + SOCKADDR_IN sa_local; + int size; + DWORD n; + + /* allow idempotent calls, first options are taken, use closelog + * before openlog if you want to reconfigure the syslog interface + */ + if( initialized ) return; + + /* Initialize Windows Socket DLL */ + if( WSAStartup( MAKEWORD( 2, 2 ), &wsd ) != 0 ) goto DONE; + wsa_initialized = TRUE; + + /* tell getaddrinfo what we want */ + memset( &hints, 0, sizeof( struct addrinfo ) ); + hints.ai_flags = 0; + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_DGRAM; + hints.ai_protocol = IPPROTO_UDP; + + /* resolve the domain name into a list of addresses */ + if( getaddrinfo( syslog_hostname, syslog_service, &hints, &result ) != 0 ) goto DONE; + + /* Compose the socket address and port of the logging destination */ + memset( &sa_logger, 0, sizeof( SOCKADDR_IN ) ); + memcpy( &sa_logger, result->ai_addr, result->ai_addrlen ); + + /* Create a UDP socket */ + sock = socket( result->ai_family, result->ai_socktype, result->ai_protocol ); + if( sock == INVALID_SOCKET ) goto DONE; + + /* from RFC 3164: The client should connect from a constant port, if possible + * also port 514. + * + * But if we are on the same machine with loopback the port is taken? + * Should we try 514 and if it is taken take a fixed different one? + */ + + /* bind to the socket */ + memset( &sa_local, 0, sizeof( SOCKADDR_IN ) ); + sa_local.sin_family = AF_INET; + if( bind( sock, (SOCKADDR *)&sa_local, sizeof( SOCKADDR_IN ) ) != 0 ) goto DONE; + + /* determine the maximal size of a datagram packet we can send */ + size = sizeof( datagram_size ); + if( getsockopt( sock, SOL_SOCKET, SO_MAX_MSG_SIZE, (char *)&datagram_size, &size ) != 0 ) goto DONE; + if( datagram_size > sizeof( datagram ) ) datagram_size = sizeof( datagram ); + + /* set global facility and ident */ + syslog_facility = facility ? facility : LOG_USER; + syslog_ident = ident; + + /* by RFC 3164 we should put here the name of the local machine */ + n = sizeof( local_hostname ); + if( !GetComputerName( local_hostname, &n ) ) goto DONE; + + /* interpret options, currently we use only LOG_PID */ + if( option & LOG_PID ) + _snprintf_s( str_pid, sizeof( str_pid ), _TRUNCATE, "[%lu]", GetCurrentProcessId( ) ); + else + str_pid[0] = '\0'; + + /* install C cleanup function */ + if( atexit( closelog ) ) goto DONE; + + /* if we get here, everything's peachy */ + failed = FALSE; + +DONE: + if( failed ) { + if( sock != INVALID_SOCKET ) { + closesocket( sock ); + sock = INVALID_SOCKET; + } + if( wsa_initialized ) { + wsa_initialized = FALSE; + WSACleanup( ); + } + } + + initialized = !failed; +} + +extern int setlogmask( int mask ) +{ + /* set log mask, return old one */ + int old_mask = log_mask; + + if( mask ) log_mask = mask; + + return old_mask; +} + +void syslog( int pri, char* fmt, ... ) +{ + va_list ap; + va_start( ap, fmt ); + vsyslog( pri, fmt, ap ); + va_end( ap ); +} + +void vsyslog( int pri, char* fmt, va_list ap ) +{ + /* from RFC 3164: Mmm is the English language abbreviation for the month of the + * year with the first character in uppercase and the other two + * characters in lowercase. The following are the only acceptable + * values: + * + * Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec + */ + static char *month[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; + + int len; + SYSTEMTIME t; + + /* do not log if we are not inside the logging mask */ + if( !( LOG_MASK( LOG_PRI( pri ) ) & log_mask ) ) return; + + /* open default logger, will return immediatelly if already + * registered before */ + openlog( NULL, 0, pri & LOG_FACMASK ); + + /* do not log if not initialized after opening a default log */ + if( !initialized ) return; + + if( !( pri & LOG_FACMASK ) ) pri |= syslog_facility; + + /* from RFC 3164: .. hh:mm:ss is the local time. .. */ + GetLocalTime( &t ); + + /* the PRI and the HEADER with TIMESTAMP and HOSTNAME as + * well as the TAG field of the MSG part + */ + len = _snprintf_s( datagram, datagram_size, _TRUNCATE, "<%d>%s %2d %02d:%02d:%02d %s %s%s: ", + pri, month[t.wMonth-1], t.wDay, t.wHour, t.wMinute, t.wSecond, + local_hostname, syslog_ident ? syslog_ident : "", str_pid ); + + /* append now the formatted user message */ + (void)_vsnprintf_s( datagram + len, datagram_size - len, _TRUNCATE, fmt, ap ); + + /* send as datagram, we are not really interested in errors here */ + (void)sendto( sock, datagram, strlen( datagram ), 0, (SOCKADDR *)&sa_logger, sizeof( SOCKADDR_IN ) ); +} + +void closelog( ) +{ + if( !initialized ) return; + + if( sock != INVALID_SOCKET ) (void)closesocket( sock ); + if( wsa_initialized ) WSACleanup( ); + + sock = INVALID_SOCKET; + wsa_initialized = FALSE; + initialized = FALSE; +} + +void set_syslogd_destination( const char *hostname, const char *service ) +{ + strncpy_s( syslog_hostname, 255, hostname, _TRUNCATE ); + strncpy_s( syslog_service, 255, service, _TRUNCATE ); +} diff --git a/src/liblogger/win32/syslog_win32.h b/src/liblogger/win32/syslog_win32.h new file mode 100644 index 0000000..94157a1 --- /dev/null +++ b/src/liblogger/win32/syslog_win32.h @@ -0,0 +1,171 @@ +/************************************************************************ + + Copyright (C) 2011, 2012 Project Wolframe. + All rights reserved. + + This file is part of Project Wolframe. + + Commercial Usage + Licensees holding valid Project Wolframe Commercial licenses may + use this file in accordance with the Project Wolframe + Commercial License Agreement provided with the Software or, + alternatively, in accordance with the terms contained + in a written agreement between the licensee and Project Wolframe. + + GNU General Public License Usage + Alternatively, you can redistribute this file and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Wolframe 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Wolframe. If not, see <http://www.gnu.org/licenses/>. + + If you have questions regarding the use of this file, please contact + Project Wolframe. + +************************************************************************/ + +/* + * Copyright (c) 1982, 1986, 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)syslog.h 8.1 (Berkeley) 6/2/93 + */ + +/// +/// \file syslog_win32.h +/// \brief syslog header file on Windows +/// + +#ifndef _SYSLOG_WIN32_HPP_INCLUDED +#define _SYSLOG_WIN32_HPP_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdarg.h> + +/* + * priorities/facilities are encoded into a single 32-bit quantity, where the + * bottom 3 bits are the priority (0-7) and the top 28 bits are the facility + * (0-big number). Both the priorities and the facilities map roughly + * one-to-one to strings in the syslogd(8) source code. This mapping is + * included in this file. + * + * priorities (these are ordered) + */ +#define LOG_EMERG 0 /* system is unusable */ +#define LOG_ALERT 1 /* action must be taken immediately */ +#define LOG_CRIT 2 /* critical conditions */ +#define LOG_ERR 3 /* error conditions */ +#define LOG_WARNING 4 /* warning conditions */ +#define LOG_NOTICE 5 /* normal but significant condition */ +#define LOG_INFO 6 /* informational */ +#define LOG_DEBUG 7 /* debug-level messages */ + +#define LOG_PRIMASK 0x07 /* mask to extract priority part (internal) */ + /* extract priority */ +#define LOG_PRI(p) ((p) & LOG_PRIMASK) +#define LOG_MAKEPRI(fac, pri) (((fac) << 3) | (pri)) + +/* facility codes */ +#define LOG_KERN (0<<3) /* kernel messages */ +#define LOG_USER (1<<3) /* random user-level messages */ +#define LOG_MAIL (2<<3) /* mail system */ +#define LOG_DAEMON (3<<3) /* system daemons */ +#define LOG_AUTH (4<<3) /* security/authorization messages */ +#define LOG_SYSLOG (5<<3) /* messages generated internally by syslogd */ +#define LOG_LPR (6<<3) /* line printer subsystem */ +#define LOG_NEWS (7<<3) /* network news subsystem */ +#define LOG_UUCP (8<<3) /* UUCP subsystem */ +#define LOG_CRON (9<<3) /* clock daemon */ +#define LOG_AUTHPRIV (10<<3) /* security/authorization messages (private) */ +#define LOG_FTP (11<<3) /* ftp daemon */ + + /* other codes through 15 reserved for system use */ +#define LOG_LOCAL0 (16<<3) /* reserved for local use */ +#define LOG_LOCAL1 (17<<3) /* reserved for local use */ +#define LOG_LOCAL2 (18<<3) /* reserved for local use */ +#define LOG_LOCAL3 (19<<3) /* reserved for local use */ +#define LOG_LOCAL4 (20<<3) /* reserved for local use */ +#define LOG_LOCAL5 (21<<3) /* reserved for local use */ +#define LOG_LOCAL6 (22<<3) /* reserved for local use */ +#define LOG_LOCAL7 (23<<3) /* reserved for local use */ + +#define LOG_NFACILITIES 24 /* current number of facilities */ +#define LOG_FACMASK 0x03f8 /* mask to extract facility part */ + /* facility of pri */ +#define LOG_FAC(p) (((p) & LOG_FACMASK) >> 3) + +/* + * arguments to setlogmask. + */ +#define LOG_MASK(pri) (1 << (pri)) /* mask for one priority */ +#define LOG_UPTO(pri) ((1 << ((pri)+1)) - 1) /* all priorities through pri */ + +/* + * Option flags for openlog. + */ +#define LOG_PID 0x01 /* log the pid with each message */ + +/* Close descriptor used to write to system logger. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern void closelog (void); + +/* Open connection to system logger. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern void openlog (const char *__ident, int __option, int __facility); + +/* Set the log mask level. */ +extern int setlogmask( int __mask ); + +/* Generate a log message using FMT string and option arguments. */ +extern void syslog (int __pri, char *__fmt, ...); + +/* Generate a log message using FMT and using arguments pointed to by AP. */ +void vsyslog( int __pri, char* __fmt, va_list __ap ); + +/* Wolframe specific function, set the hostname and port for logging through + * the configuration programatically */ +extern void set_syslogd_destination( const char *__hostname, const char *__service ); + +#ifdef __cplusplus +} +#endif + +#endif // _SYSLOG_WIN32_HPP_INCLUDED |