summaryrefslogtreecommitdiff
path: root/src/log
diff options
context:
space:
mode:
authorAndreas Baumann <abaumann@yahoo.com>2009-03-17 16:02:48 +0100
committerAndreas Baumann <abaumann@yahoo.com>2009-03-17 16:02:48 +0100
commit7c1d830045ea25ad3537e68b72900600d02fd135 (patch)
tree7287e020f05daa5c3fa6a5d6534f989a61a76793 /src/log
parentd2b1bd190c039c817ca6432a4b6a66c1e8db116f (diff)
downloadwolfbones-7c1d830045ea25ad3537e68b72900600d02fd135.tar.gz
wolfbones-7c1d830045ea25ad3537e68b72900600d02fd135.tar.bz2
moved the logger (log and messages) into it's own subdirectory (is a subsystem of wolf in the end)
Diffstat (limited to 'src/log')
-rw-r--r--src/log/log.c656
1 files changed, 656 insertions, 0 deletions
diff --git a/src/log/log.c b/src/log/log.c
new file mode 100644
index 0000000..0412e75
--- /dev/null
+++ b/src/log/log.c
@@ -0,0 +1,656 @@
+/*
+ Copyright (C) 2008 Andreas Baumann <abaumann@yahoo.com>
+
+ This program is free software: you can redistribute it 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.
+
+ This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "log/log.h"
+
+#include "log/messages.h" /* for i18n */
+
+#include "port/stdio.h" /* for vsnprintf, snprintf */
+#include "port/string.h" /* for strcmp, strerror_r, strlen */
+#include "port/time.h" /* for localtime_r, strftime, time
+ * time_t, struct tm */
+#include "port/unused.h" /* for WOLF_UNUSED */
+
+#include <stdarg.h> /* for variable arguments */
+#include <errno.h> /* for errno */
+#include <assert.h> /* for assertions */
+#include <stdlib.h> /* for abort */
+
+#if defined HAVE_SYSLOG_H
+#include <syslog.h> /* for syslog, closelog and levels */
+#endif /* defined HAVE_SYSLOG_H */
+
+#if defined HAVE_EVENTLOG
+#define WIND32_LEAN_AND_MEAN
+#include <windows.h>
+#endif /* defined HAVE_EVENTLOG */
+
+#if defined HAVE_SYSLOG_H
+const char *wolf_log_syslog_facility_to_str( wolf_log_syslog_facility_t facility ) {
+ switch( facility ) {
+ /* Linux, FreeBSD, OpenBSD, NetBSD */
+ case WOLF_LOG_KERN: return "KERN";
+ case WOLF_LOG_USER: return "USER";
+ case WOLF_LOG_MAIL: return "MAIL";
+ case WOLF_LOG_DAEMON: return "DAEMON";
+ case WOLF_LOG_AUTH: return "AUTH";
+ case WOLF_LOG_SYSLOG: return "SYSLOG";
+ case WOLF_LOG_LPR: return "LPR";
+ case WOLF_LOG_NEWS: return "NEWS";
+ case WOLF_LOG_UUCP: return "UUCP";
+ case WOLF_LOG_CRON: return "CRON";
+#if defined LOG_AUTHPRIV
+ /* Linux, FreeBSD, OpenBSD, NetBSD */
+ case WOLF_LOG_AUTHPRIV: return "AUTHPRIV";
+#else
+ case WOLF_LOG_AUTHPRIV: return "<unknown>";
+#endif
+#if defined LOG_FTP
+ /* Linux, FreeBSD, OpenBSD, NetBSD */
+ case WOLF_LOG_FTP: return "FTP";
+#else
+ case WOLF_LOG_FTP: return "<unknown>";
+#endif
+#if defined LOG_NTP
+ /* FreeBSD */
+ case WOLF_LOG_NTP: return "NTP";
+#else
+ case WOLF_LOG_NTP: return "<unknown>";
+#endif
+#if defined LOG_SECURITY
+ /* FreeBSD */
+ case WOLF_LOG_SECURITY: return "SECURITY";
+#else
+ case WOLF_LOG_SECURITY: return "<unknown>";
+#endif
+#if defined LOG_CONSOLE
+ /* FreeBSD */
+ case WOLF_LOG_CONSOLE: return "CONSOLE";
+#else
+ case WOLF_LOG_CONSOLE: return "<unknown>";
+#endif
+#if defined LOG_AUDIT
+ /* Solaris 10 */
+ case WOLF_LOG_AUDIT: return "AUDIT";
+#else
+ case WOLF_LOG_AUDIT: return "<unknown>";
+#endif
+ case WOLF_LOG_LOCAL0: return "LOCAL0";
+ case WOLF_LOG_LOCAL1: return "LOCAL1";
+ case WOLF_LOG_LOCAL2: return "LOCAL2";
+ case WOLF_LOG_LOCAL3: return "LOCAL3";
+ case WOLF_LOG_LOCAL4: return "LOCAL4";
+ case WOLF_LOG_LOCAL5: return "LOCAL5";
+ case WOLF_LOG_LOCAL6: return "LOCAL6";
+ case WOLF_LOG_LOCAL7: return "LOCAL7";
+ default: return "<unknown>";
+ }
+}
+#endif /* defined HAVE_SYSLOG_H */
+
+#if defined HAVE_SYSLOG_H
+wolf_log_syslog_facility_t wolf_log_str_to_syslog_facility( const char *facility ) {
+ if( strcmp( facility, "KERN" ) == 0 ) return WOLF_LOG_KERN;
+ if( strcmp( facility, "USER" ) == 0 ) return WOLF_LOG_USER;
+ if( strcmp( facility, "MAIL" ) == 0 ) return WOLF_LOG_MAIL;
+ if( strcmp( facility, "DAEMON" ) == 0 ) return WOLF_LOG_DAEMON;
+ if( strcmp( facility, "AUTH" ) == 0 ) return WOLF_LOG_AUTH;
+ if( strcmp( facility, "SYSLOG" ) == 0 ) return WOLF_LOG_SYSLOG;
+ if( strcmp( facility, "LPR" ) == 0 ) return WOLF_LOG_LPR;
+ if( strcmp( facility, "NEWS" ) == 0 ) return WOLF_LOG_NEWS;
+ if( strcmp( facility, "UUCP" ) == 0 ) return WOLF_LOG_UUCP;
+ if( strcmp( facility, "CRON" ) == 0 ) return WOLF_LOG_CRON;
+ if( strcmp( facility, "AUTHPRIV" ) == 0 ) return WOLF_LOG_AUTHPRIV;
+ if( strcmp( facility, "FTP" ) == 0 ) return WOLF_LOG_FTP;
+ if( strcmp( facility, "NTP" ) == 0 ) return WOLF_LOG_NTP;
+ if( strcmp( facility, "SECURITY" ) == 0 ) return WOLF_LOG_SECURITY;
+ if( strcmp( facility, "CONSOLE" ) == 0 ) return WOLF_LOG_CONSOLE;
+ if( strcmp( facility, "AUDIT" ) == 0 ) return WOLF_LOG_AUDIT;
+ if( strcmp( facility, "LOCAL0" ) == 0 ) return WOLF_LOG_LOCAL0;
+ if( strcmp( facility, "LOCAL1" ) == 0 ) return WOLF_LOG_LOCAL1;
+ if( strcmp( facility, "LOCAL2" ) == 0 ) return WOLF_LOG_LOCAL2;
+ if( strcmp( facility, "LOCAL3" ) == 0 ) return WOLF_LOG_LOCAL3;
+ if( strcmp( facility, "LOCAL4" ) == 0 ) return WOLF_LOG_LOCAL4;
+ if( strcmp( facility, "LOCAL5" ) == 0 ) return WOLF_LOG_LOCAL5;
+ if( strcmp( facility, "LOCAL6" ) == 0 ) return WOLF_LOG_LOCAL6;
+ if( strcmp( facility, "LOCAL7" ) == 0 ) return WOLF_LOG_LOCAL7;
+
+ /* this is a seasonable default if nothing else exists */
+ return WOLF_LOG_DAEMON;
+}
+#endif /* defined HAVE_SYSLOG_H */
+
+#if defined HAVE_SYSLOG_H
+bool wolf_log_platform_has_syslog_facility( wolf_log_syslog_facility_t facility ) {
+ switch( facility ) {
+ /* Linux, FreeBSD, OpenBSD, NetBSD */
+ case WOLF_LOG_KERN:
+ case WOLF_LOG_USER:
+ case WOLF_LOG_MAIL:
+ case WOLF_LOG_DAEMON:
+ case WOLF_LOG_AUTH:
+ case WOLF_LOG_SYSLOG:
+ case WOLF_LOG_LPR:
+ case WOLF_LOG_NEWS:
+ case WOLF_LOG_UUCP:
+ case WOLF_LOG_CRON:
+ case WOLF_LOG_LOCAL0:
+ case WOLF_LOG_LOCAL1:
+ case WOLF_LOG_LOCAL2:
+ case WOLF_LOG_LOCAL3:
+ case WOLF_LOG_LOCAL4:
+ case WOLF_LOG_LOCAL5:
+ case WOLF_LOG_LOCAL6:
+ case WOLF_LOG_LOCAL7:
+ return true;
+#if defined LOG_AUTHPRIV
+ /* Linux, FreeBSD, OpenBSD, NetBSD */
+ case WOLF_LOG_AUTHPRIV: return true;
+#else
+ case WOLF_LOG_AUTHPRIV: return false;
+#endif
+#if defined LOG_FTP
+ /* Linux, FreeBSD, OpenBSD, NetBSD */
+ case WOLF_LOG_FTP: return true;
+#else
+ case WOLF_LOG_FTP: return false;
+#endif
+#if defined LOG_NTP
+ /* FreeBSD */
+ case WOLF_LOG_NTP: return true;
+#else
+ case WOLF_LOG_NTP: return false;
+#endif
+#if defined LOG_SECURITY
+ /* FreeBSD */
+ case WOLF_LOG_SECURITY: return true;
+#else
+ case WOLF_LOG_SECURITY: return false;
+#endif
+#if defined LOG_CONSOLE
+ /* FreeBSD */
+ case WOLF_LOG_CONSOLE: return true;
+#else
+ case WOLF_LOG_CONSOLE: return false;
+#endif
+#if defined LOG_AUDIT
+ /* Solaris 10 */
+ case WOLF_LOG_AUDIT: return true;
+#else
+ case WOLF_LOG_AUDIT: return false;
+#endif
+ }
+
+ return false;
+}
+#endif /* defined HAVE_SYSLOG_H */
+
+wolf_log_level_t wolf_log_str_to_level( const char *level ) {
+ if( strcmp( level, "EMERG" ) == 0 ) return WOLF_LOG_EMERG;
+ if( strcmp( level, "ALERT" ) == 0 ) return WOLF_LOG_ALERT;
+ if( strcmp( level, "CRIT" ) == 0 ) return WOLF_LOG_CRIT;
+ if( strcmp( level, "ERR" ) == 0 ) return WOLF_LOG_ERR;
+ if( strcmp( level, "WARNING" ) == 0 ) return WOLF_LOG_WARNING;
+ if( strcmp( level, "NOTICE" ) == 0 ) return WOLF_LOG_NOTICE;
+ if( strcmp( level, "INFO" ) == 0 ) return WOLF_LOG_INFO;
+ if( strcmp( level, "DEBUG" ) == 0 ) return WOLF_LOG_DEBUG;
+ if( strcmp( level, "DEBUG1" ) == 0 ) return WOLF_LOG_DEBUG1;
+ if( strcmp( level, "DEBUG2" ) == 0 ) return WOLF_LOG_DEBUG2;
+ if( strcmp( level, "DEBUG3" ) == 0 ) return WOLF_LOG_DEBUG3;
+ if( strcmp( level, "DEBUG4" ) == 0 ) return WOLF_LOG_DEBUG4;
+ if( strcmp( level, "DEBUG5" ) == 0 ) return WOLF_LOG_DEBUG5;
+
+ return WOLF_LOG_EMERG;
+}
+
+#if defined HAVE_SYSLOG_H
+static int map_log_to_syslog_level( wolf_log_level_t level ) {
+ switch( level ) {
+ case WOLF_LOG_EMERG: return LOG_EMERG;
+ case WOLF_LOG_ALERT: return LOG_ALERT;
+ case WOLF_LOG_CRIT: return LOG_CRIT;
+ case WOLF_LOG_ERR: return LOG_ERR;
+ case WOLF_LOG_WARNING: return LOG_WARNING;
+ case WOLF_LOG_NOTICE: return LOG_NOTICE;
+ case WOLF_LOG_INFO: return LOG_INFO;
+ case WOLF_LOG_DEBUG:
+ case WOLF_LOG_DEBUG1:
+ case WOLF_LOG_DEBUG2:
+ case WOLF_LOG_DEBUG3:
+ case WOLF_LOG_DEBUG4:
+ case WOLF_LOG_DEBUG5: return LOG_DEBUG;
+ default: return LOG_EMERG;
+ }
+}
+#endif /* defined HAVE_SYSLOG_H */
+
+#if defined HAVE_EVENTLOG
+/* TODO: logging of audit success/fail and how to map this to the
+ * upper layer (so on Unix things can also go to LOG_SECURITY or
+ * LOG_AUDIT on special Unixes. But for this we have to read a
+ * log first!
+ */
+static WORD wolf_log_level_to_eventlog_type( wolf_log_level_t level ) {
+ switch( level ) {
+ case WOLF_LOG_EMERG:
+ case WOLF_LOG_ALERT:
+ case WOLF_LOG_CRIT:
+ case WOLF_LOG_ERR: return EVENTLOG_ERROR_TYPE;
+ case WOLF_LOG_WARNING: return EVENTLOG_WARNING_TYPE;
+ case WOLF_LOG_NOTICE:
+ case WOLF_LOG_INFO:
+ case WOLF_LOG_DEBUG:
+ case WOLF_LOG_DEBUG1:
+ case WOLF_LOG_DEBUG2:
+ case WOLF_LOG_DEBUG3:
+ case WOLF_LOG_DEBUG4:
+ case WOLF_LOG_DEBUG5: return EVENTLOG_INFORMATION_TYPE;
+ default: return EVENTLOG_ERROR_TYPE;
+ }
+}
+#endif /* defined HAVE_EVENTLOG */
+
+#if defined HAVE_SYSLOG_H
+static int map_log_facility_to_syslog_facility( int facility ) {
+ switch( facility ) {
+ case WOLF_LOG_KERN: return LOG_KERN;
+ case WOLF_LOG_USER: return LOG_USER;
+ case WOLF_LOG_MAIL: return LOG_MAIL;
+ case WOLF_LOG_DAEMON: return LOG_DAEMON;
+ case WOLF_LOG_AUTH: return LOG_AUTH;
+ case WOLF_LOG_SYSLOG: return LOG_SYSLOG;
+ case WOLF_LOG_LPR: return LOG_LPR;
+ case WOLF_LOG_NEWS: return LOG_NEWS;
+ case WOLF_LOG_UUCP: return LOG_UUCP;
+ case WOLF_LOG_CRON: return LOG_CRON;
+#if defined LOG_AUTHPRIV
+ case WOLF_LOG_AUTHPRIV: return LOG_AUTHPRIV;
+#else
+ case WOLF_LOG_AUTHPRIV: return LOG_DAEMON;
+#endif
+#if defined LOG_FTP
+ case WOLF_LOG_FTP: return LOG_FTP;
+#else
+ case WOLF_LOG_FTP: return LOG_DAEMON;
+#endif
+#if defined LOG_NTP
+ case WOLF_LOG_NTP: return LOG_NTP;
+#else
+ case WOLF_LOG_NTP: return LOG_DAEMON;
+#endif
+#if defined LOG_SECURITY
+ case WOLF_LOG_SECURITY: return LOG_SECURITY;
+#else
+ case WOLF_LOG_SECURITY: return LOG_DAEMON;
+#endif
+#if defined LOG_CONSOLE
+ case WOLF_LOG_CONSOLE: return LOG_CONSOLE;
+#else
+ case WOLF_LOG_CONSOLE: return LOG_DAEMON;
+#endif
+#if defined LOG_AUDIT
+ case WOLF_LOG_AUDIT: return LOG_AUDIT;
+#else
+ case WOLF_LOG_AUDIT: return LOG_DAEMON;
+#endif
+ case WOLF_LOG_LOCAL0: return LOG_LOCAL0;
+ case WOLF_LOG_LOCAL1: return LOG_LOCAL1;
+ case WOLF_LOG_LOCAL2: return LOG_LOCAL2;
+ case WOLF_LOG_LOCAL3: return LOG_LOCAL3;
+ case WOLF_LOG_LOCAL4: return LOG_LOCAL4;
+ case WOLF_LOG_LOCAL5: return LOG_LOCAL5;
+ case WOLF_LOG_LOCAL6: return LOG_LOCAL6;
+ case WOLF_LOG_LOCAL7: return LOG_LOCAL7;
+ default: return LOG_DAEMON;
+ }
+}
+#endif /* defined HAVE_SYSLOG_H */
+
+const char *wolf_log_level_to_str( wolf_log_level_t level ) {
+ switch( level ) {
+ case WOLF_LOG_EMERG: return "EMERG";
+ case WOLF_LOG_ALERT: return "ALERT";
+ case WOLF_LOG_CRIT: return "CRIT";
+ case WOLF_LOG_ERR: return "ERR";
+ case WOLF_LOG_WARNING: return "WARNING";
+ case WOLF_LOG_NOTICE: return "NOTICE";
+ case WOLF_LOG_INFO: return "INFO";
+ case WOLF_LOG_DEBUG: return "DEBUG";
+ case WOLF_LOG_DEBUG1: return "DEBUG1";
+ case WOLF_LOG_DEBUG2: return "DEBUG2";
+ case WOLF_LOG_DEBUG3: return "DEBUG3";
+ case WOLF_LOG_DEBUG4: return "DEBUG4";
+ case WOLF_LOG_DEBUG5: return "DEBUG5";
+ default: return "<unknown>";
+ }
+}
+
+static const char *log_logfile_filename;
+static FILE *log_file = NULL;
+static wolf_log_level_t log_logfile_level;
+static wolf_log_level_t log_stderr_level;
+#if defined HAVE_SYSLOG_H
+static const char *syslog_ident;
+static int syslog_facility;
+static int syslog_level;
+static int syslog_options;
+#endif /* defined HAVE_SYSLOG_H */
+#if defined HAVE_EVENTLOG
+static HANDLE event_source = 0;
+static int eventlog_level;
+static const char *eventlog_server;
+static const char *eventlog_log;
+static const char *eventlog_source;
+static PSID sid = NULL;
+#endif /* defined HAVE_EVENTLOG */
+
+void wolf_log_openlogtofile( const char *filename, wolf_log_level_t level ) {
+ log_logfile_filename = filename;
+ log_logfile_level = level;
+ wolf_log_reopenlogtofile( );
+}
+
+#if defined HAVE_SYSLOG_H
+static int map_log_options_to_syslog_options( int opts ) {
+ int syslog_opts = LOG_NDELAY;
+
+ if( ( opts & WOLF_LOG_SYSLOG_PID ) == WOLF_LOG_SYSLOG_PID ) {
+ syslog_opts |= LOG_PID;
+ }
+ if( ( opts & WOLF_LOG_SYSLOG_CONS ) == WOLF_LOG_SYSLOG_CONS ) {
+ syslog_opts |= LOG_CONS;
+ }
+
+ return syslog_opts;
+}
+#endif /* defined HAVE_SYSLOG_H */
+
+#if defined HAVE_SYSLOG_H
+void wolf_log_openlogtosyslog( const char *ident,
+ wolf_log_syslog_facility_t facility,
+ wolf_log_level_t level,
+ int options ) {
+ syslog_ident = ident;
+ syslog_facility = map_log_facility_to_syslog_facility( facility );
+ syslog_level = map_log_to_syslog_level( level );
+ syslog_options = map_log_options_to_syslog_options( options );
+
+ openlog( ident, LOG_CONS | LOG_NDELAY, facility );
+ setlogmask( LOG_UPTO( level ) );
+}
+#endif /* defined HAVE_SYSLOG_H */
+
+#if defined HAVE_EVENTLOG
+
+static void registry_set_expandable_string( HKEY h, TCHAR *name, TCHAR *value ) {
+ RegSetValueEx( h, name, 0, REG_EXPAND_SZ, (LPBYTE)value, strlen( value ) );
+}
+
+static void registry_set_word( HKEY h, TCHAR *name, DWORD value ) {
+ RegSetValueEx( h, name, 0, REG_DWORD, (LPBYTE)&value, sizeof( DWORD ) );
+}
+
+static void register_event_source( const char *log, const char *source ) {
+ char key[256];
+ HKEY h = 0;
+ DWORD disposition;
+
+ /* compose the registry key and simply overwrite the values there, we know */
+ snprintf( key, 256, "SYSTEM\\CurrentControlSet\\Services\\EventLog\\%s\\%s", log, source );
+ RegCreateKeyEx( HKEY_LOCAL_MACHINE, key, 0, NULL, REG_OPTION_NON_VOLATILE,
+ KEY_SET_VALUE, NULL, &h, &disposition );
+
+ /* make sure not to have hard-coded pathes here, otherwise remote
+ * event logging will not work! */
+ registry_set_expandable_string( h, "EventMessageFile", "%SystemRoot%\\System32\\wolfmsg.dll" );
+ registry_set_expandable_string( h, "CategoryMessageFile", "%SystemRoot%\\System32\\wolfmsg.dll" );
+ registry_set_word( h, "TypesSupported", (DWORD)7 );
+ registry_set_word( h, "CategoryCount", (DWORD)2 );
+ RegCloseKey( h );
+}
+
+static PSID get_current_sid( void ) {
+ HANDLE process = NULL;
+ HANDLE token = NULL;
+ DWORD token_user_size = 0;
+ PTOKEN_USER token_user;
+ PSID token_sid = NULL;
+ DWORD sid_size = 0;
+ PSID sid = NULL;
+
+ /* get the token for the current process */
+ process = GetCurrentProcess( );
+ if( process == NULL ) {
+ fprintf( stderr, "%s: Unable to get current process handle\n",
+ wolf_log_level_to_str( WOLF_LOG_ALERT ) );
+ abort( );
+ }
+ if( !OpenProcessToken( process, TOKEN_QUERY, &token ) ) {
+ fprintf( stderr, "%s: Unable to get process token of current process\n",
+ wolf_log_level_to_str( WOLF_LOG_ALERT ) );
+ abort( );
+ }
+
+ /* get the required size to store the user token and allocate memory for it */
+ (void)GetTokenInformation( token, TokenUser, NULL, 0, &token_user_size );
+ token_user = (PTOKEN_USER)malloc( token_user_size * sizeof( BYTE ) );
+ if( token_user == NULL ) {
+ fprintf( stderr, "%s: Unable to get memory to store user token\n",
+ wolf_log_level_to_str( WOLF_LOG_ALERT ) );
+ CloseHandle( token );
+ abort( );
+ }
+
+ /* get the user token */
+ if( !GetTokenInformation( token, TokenUser, (LPVOID)token_user, token_user_size, &token_user_size ) ) {
+ fprintf( stderr, "%s: Unable to get user token\n",
+ wolf_log_level_to_str( WOLF_LOG_ALERT ) );
+ free( token_user );
+ CloseHandle( token );
+ abort( );
+ }
+
+ /* finally we made our way to the SID. Make a local copy of it because it and return that one */
+ token_sid = (PSID)token_user->User.Sid;
+ sid_size = GetLengthSid( token_sid );
+ sid = (PSID)malloc( sid_size );
+ if( sid != NULL ) {
+ if( !CopySid( sid_size, sid, token_sid ) ) {
+ fprintf( stderr, "%s: Unable to make a copy of the current SID\n",
+ wolf_log_level_to_str( WOLF_LOG_ALERT ) );
+ free( sid );
+ free( token_user );
+ CloseHandle( token );
+ abort( );
+ }
+ }
+
+ /* process handle is a pseudo handle which doesn't need closing */
+ free( token_user );
+ CloseHandle( token );
+
+ return sid;
+}
+
+void wolf_log_openlogtoeventlog( const char *server,
+ const char *log,
+ const char *source,
+ wolf_log_level_t level ) {
+ eventlog_server = server;
+ eventlog_log = log;
+ eventlog_source = source;
+ eventlog_level = level;
+
+ /* fiddle in the registry and register the location of the
+ * message DLL, how many categories we define and what types
+ * of events we are supporting
+ */
+ register_event_source( log, source );
+
+ /* for logging the user of the process into the event log */
+ sid = get_current_sid( );
+
+ /* TODO: remote machine and event log source should be in the API,
+ * but we have Windows localized strings which are hard to unify
+ * with Unix. We also don't want to have a stupid string wrapper
+ * on top.. No clue for now
+ */
+ event_source = RegisterEventSource( server, source );
+ if( event_source == NULL ) {
+ /* TODO: add GetLastError here! */
+ fprintf( stderr, "%s: Unable to register event source\n",
+ wolf_log_level_to_str( WOLF_LOG_ALERT ) );
+ }
+}
+#endif /* defined HAVE_EVENTLOG */
+
+void wolf_log_openlogtostderr( wolf_log_level_t level ) {
+ log_stderr_level = level;
+}
+
+void wolf_log_closelogtofile( void ) {
+ if( log_file != NULL ) {
+ fclose( log_file );
+ log_file = NULL;
+ }
+}
+
+#if defined HAVE_SYSLOG_H
+void wolf_log_closelogtosyslog( void ) {
+ closelog( );
+}
+#endif /* defined HAVE_SYSLOG_H */
+
+#if defined HAVE_EVENTLOG
+void wolf_log_closelogtoeventlog( void ) {
+ if( sid != NULL ) {
+ free( sid );
+ sid = NULL;
+ }
+
+ if( !DeregisterEventSource( event_source ) ) {
+ /* TODO: add GetLastError here! */
+ fprintf( stderr, "%s: Unable to deregister event source handle\n",
+ wolf_log_level_to_str( WOLF_LOG_ALERT ) );
+ }
+}
+#endif /* defined HAVE_EVENTLOG */
+
+void wolf_log_closelogtostderr( void ) {
+ /* do nothing here */
+}
+
+void wolf_log_reopenlogtofile( void ) {
+ if( log_file != NULL ) {
+ fclose( log_file );
+ }
+ log_file = fopen( log_logfile_filename, "a" );
+ if( log_file == NULL ) {
+ char errmsg[255];
+ strerror_r( errno, errmsg, 255 );
+ fprintf( stderr, "%s: Unable to open logfile '%s': %s\n",
+ wolf_log_level_to_str( WOLF_LOG_ALERT ),
+ log_logfile_filename, errmsg );
+ }
+}
+
+#if defined HAVE_SYSLOG_H
+void wolf_log_reopenlogtosyslog( void ) {
+ openlog( syslog_ident, syslog_options, syslog_facility );
+ setlogmask( LOG_UPTO( syslog_level ) );
+}
+#endif /* defined HAVE_SYSLOG_H */
+
+#if defined HAVE_EVENTLOG
+void wolf_log_reopenlogtoeventlog( void ) {
+ /* TODO: close and open? */
+}
+#endif /* defined HAVE_EVENTLOG */
+
+void wolf_log( wolf_log_level_t level, int category_id, int message_id, const char *format, ... ) {
+ va_list ap;
+ char s[1024];
+ va_start( ap, format );
+ vsnprintf( s, 1024, format, ap );
+ va_end( ap );
+
+ WOLF_UNUSED( category_id );
+ WOLF_UNUSED( message_id );
+
+ if( level <= log_stderr_level )
+ fprintf( stderr, "%s: %s\n",wolf_log_level_to_str( level ), s );
+
+ if( level <= log_logfile_level && log_file != NULL ) {
+ time_t t;
+ struct tm local_time;
+ char date_str[100];
+
+ time( &t );
+ assert( t >= 0 ); /* actually the only error known is an illegal buffer */
+ if( localtime_r( &t, &local_time ) == NULL ) {
+ char errmsg[512];
+ strerror_r( errno, errmsg, 512 );
+ fprintf( stderr, "%s: localtime_r failed with errno %d (%s)!!\n",
+ wolf_log_level_to_str( WOLF_LOG_ALERT ), errno, errmsg );
+ abort( );
+ }
+
+ strftime( date_str, 100, "%b %d %H:%M:%S", &local_time );
+
+ fprintf( log_file, "%s %s %d-%d: %s\n",
+ date_str, wolf_log_level_to_str( level ), category_id, message_id, s );
+ fflush( log_file );
+ }
+
+#if defined HAVE_SYSLOG_H
+ syslog( map_log_to_syslog_level( level ), "%s", s );
+#endif /* defined HAVE_SYSLOG_H */
+
+#if defined HAVE_EVENTLOG
+ if( level <= eventlog_level && event_source != 0 ) {
+ /* for now we map the snprintf-like format directly
+ * to one message string for event ID 0 (actually as
+ * most others like the .NET guys are doing! This
+ * is a bit TODO!)
+ */
+ LPCTSTR msg_arr[2];
+
+ /* compose the message and the parameters */
+ msg_arr[0] = wolf_log_level_to_str( level );
+ msg_arr[1] = s;
+
+ /* TODO: event categories and type, message numbers,
+ * resources for message DLLs etc. etc. etc.
+ */
+ if( !ReportEvent(
+ event_source, /* event source handle */
+ wolf_log_level_to_eventlog_type( level ),
+ 0x0FFF0001L, /* event category */
+ 0xCFFF0101L, /* event identifier */
+ sid, /* the security identifier */
+ 2, /* at the moment only one string */
+ 0, /* no binary raw data */
+ msg_arr, /* the array of strings */
+ NULL /* no binary raw data */
+ ) ) {
+ /* TODO: add GetLastError here! */
+ fprintf( stderr, "%s: Unable to log to event log\n",
+ wolf_log_level_to_str( WOLF_LOG_ALERT ) );
+ }
+ }
+#endif /* defined HAVE_EVENTLOG */
+}